r3181 - in tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9: . 2.6.9-3 2.6.9-3/debian 2.6.9-3/debian/patches 2.6.9-3/debian/patches/series

Simon Horman horms at costa.debian.org
Fri Oct 19 10:56:27 UTC 2007


Author: horms
Date: 2005-05-19 09:05:54 +0000 (Thu, 19 May 2005)
New Revision: 3181

Added:
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/README.Debian
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/apply
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/changelog
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/compat
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/control
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/copyright
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/make-substvars
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/SG_IO-safe-commands-1.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aic79xx-nohw.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alpha-writeq-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alsa-module-load-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aout-loader-fixes.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix-2.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/dm_io-ENOMEM-goof.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/doc-post_halloween.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-blacklist-toshiba.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-ricoh.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-input-psaux-hacks.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-8139too-locking.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-tg3-readd.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-pci-quirks-via8233a.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi-generic_proc_info.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi_changer.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-8250-ioremap-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-sn_console-up-buildfix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-1.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-2.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-video-fm2fb-build-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes-the-return.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-asfs.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-ext3-directio-leak-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-tmpfs-free_inode-leak.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp-1-to-2.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-hp-sba_iommu-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-mem-max_addr-cmdline-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-sn-move-irq-noop.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64_cyclone_nosmp.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ipsec-missing_wakeup.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/marvell-pegasos.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-shmem-nomount-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-vmscan.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide-pnp.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-vesafb.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-xfrm_tunnel-export-symbol.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/parport_pc-via8231.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-g4-l2-flush-errata.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-pegasos.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ppc64-iSeries-build-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/remove-references-to-removed-drivers.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/s390-sacf-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/scsi-blacklist.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-1
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-2
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-3
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overflow-fixes.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overrun.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-cg14-init.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-sunzilog-timeout.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc32-initrd-memcpy.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-hme-lockup.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-sunsab-break-fix.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tg3-update.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tty-locking-fixes9.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/vlan-update-1.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/x86-i486_emu.dpatch
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/prune-non-free
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/rules
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/unpatch
Removed:
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/1/
   tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/3/
Log:
Make tagging of kernel-image-2.6.9-i386-2.6.9 consistent

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/README.Debian
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/README.Debian	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/README.Debian	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,78 @@
+kernel-source for DEBIAN
+------------------------
+
+Patches
+-------
+Debian applies various changes to the kernel source.  These are split up
+into small patches addressing individual problems.  Each of the patch files
+contains a description and mentions the author.  The patches can be found
+at http://svn.debian.org/viewcvs/kernel/tags/kernel/source/${version}.
+
+Rebuilding Adaptec AIC7xxx/79xx firmware
+----------------------------------------
+You can rebuild the firmware for the Adaptec AIC7xxx/79xx SCSI Adapters. To
+do so you need to set AIC7XXX_BUILD_FIRMWARE/AIC79XX_BUILD_FIRMWARE config
+options.  Note that this requires to have the development packages for
+berkelydb (libdb4.2-dev) installed.
+
+PS/2 Mice
+---------
+If your PS/2 mouse does not work, make sure that the modules psmouse and
+mousedev are loaded.
+
+AMD 768 erratum 10
+------------------
+If you have a motherboard with the AMD 768 chipset, and you are experiencing
+IDE errors or lock ups, then you should either connect a PS/2 mouse to the
+system or disable APIC.  Refer to the following link for details:
+
+http://lists.insecure.org/lists/linux-kernel/2002/Sep/5966.html
+
+mem= on 2.4.19 and later
+------------------------
+mem=xxxM can no longer be used to enlarge the RAM that the kernel uses.
+You must specify the exact memory map.  For example, Compaq Proliant users
+can specify mem=48M at 16M if they have 64M of memory.
+
+80386 compatibility
+-------------------
+DRM modules will not work on true 80386 processors.  These drivers all assume
+that cmpxchg is available.
+
+IDE bswap option
+----------------
+The bswap option is obsolete and may disappear in future.  For the moment
+it does work provided that you disable dma with the nodma option.
+
+Additional Drivers
+------------------
+* SCSI Media Changer
+  http://bytesex.org/patches/
+* Amiga Smart Filesystem driver
+  http://march.home.staszic.waw.pl/asfs/
+
+Non-free bits removed
+---------------------
+* Keyspan firmware, driver disabled
+  . drivers/usb/serial/ksyspan_{mpr,usa*}_fw.h
+* Emagic EMI 2|6 usb audio interface firmware loader
+  . drivers/usb/misc/emi62_fw_*.h
+
+Firmware removed
+----------------
+* SMC Token Ring firmware, driver disabled:
+  . drivers/net/tokenring/smctr_firmware.h
+* ACENIC firwmare, driver disabled:
+  . drivers/net/acenic_firmware.h
+* DGRS firmware, driver disabled:
+  . drivers/net/dgrs_firmware.c
+* DAB firmware, driver disabled:
+  . drivers/usb/media/dabfirmware.h
+* QLA2XXX firmware, driver disabled:
+  . drivers/scsi/qla2xxx/*_fw.c
+* TIGON3 firmware:
+  . drivers/net/tg3.c
+* Unused firmware:
+  . sound/oss/724hwmcode.h
+  . sound/oss/Hwmcode.h
+

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/apply
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/apply	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/apply	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,203 @@
+#!/bin/sh 
+# $Id: apply,v 1.4 2003/06/30 12:49:09 herbert Exp $
+
+set -e
+
+length=50
+
+die() {
+	echo "E: $@" >&2
+	exit 1
+}
+
+warn() {
+	echo "W: $@" >&2
+}
+
+uncompress_patch() {
+	patch=$1
+	case "$patch" in
+		*.bz2) bzcat $patch ;;
+		*.gz) zcat $patch ;;
+		*) cat $patch ;;
+	esac
+}
+
+find_patch() {
+	patch=$1
+
+	if [ -f "$patch" ]; then
+		echo "$patch"
+	elif [ -f "$patch.bz2" ]; then
+		echo "$patch.bz2"
+	elif [ -f "$patch.gz" ]; then
+		echo "$patch.gz"
+	else
+		die "$patch is in the series, but doesn't exist!"
+	fi
+}
+		
+apply_patch() {
+	patch=$(find_patch $home/$1)
+	base=$1
+	if uncompress_patch "$patch" | patch -p1 -f -s -t --no-backup-if-mismatch; then
+		printf "%-${length}s\tOK (+)\n" "$base"
+	else
+		printf "%-${length}s\tFAIL (+)\n" "$base"
+		exit 1
+	fi
+}
+
+deapply_patch() {
+	patch=$(find_patch $home/$1)
+	base=$1
+	if uncompress_patch "$patch" | patch -p1 -f -s -t -R --no-backup-if-mismatch; then
+		printf "%-${length}s\tOK (-)\n" "$base"
+	else
+		printf "%-${length}s\tFAIL (-)\n" "$base"
+		exit 1
+	fi
+}
+
+unpatch_series() {
+	series=$1
+	[ -f "$series" ] || die "I wasn't passed a series!"
+
+	tac $series | while read action patch; do
+		case "$action" in
+			+) deapply_patch $patch ;;
+			-) apply_patch $patch ;;
+			X)
+				bakfile="$(dirname $patch)/.$(basename $patch).bak"
+				if [ -f "$bakfile" ]; then
+					mv -f "$bakfile" "$patch"
+					printf "%-${length}s\tRESTORED (X)\n" "$patch"
+				else
+					printf "%-${length}s\tNO BACKUP (X)\n" "$patch"
+				fi
+			;;
+		esac
+	done 
+	echo "--> $(basename $series) fully unapplied."
+}
+
+patch_series() {
+	series=$1
+	[ -f "$series" ] || die "I wasn't passed a series!"
+
+	while read action patch; do
+		case "$action" in
+			+) apply_patch $patch ;;
+			-) deapply_patch $patch ;;
+			X)
+				bakfile="$(dirname $patch)/.$(basename $patch).bak"
+				if [ -f "$patch" ]; then
+					mv -f "$patch" "$bakfile"
+					printf "%-${length}s\tREMOVED (X)\n" "$patch"
+				else
+					printf "%-${length}s\tNO FILE (X)\n" "$patch"
+				fi
+			;;
+		esac
+	done < $series
+	echo "--> $(basename $series) fully applied."
+}
+
+if ! [ -d Documentation ] || ! [ -d kernel ]; then
+	die 'Not in kernel top level directory.  Exiting'
+	exit 1
+fi
+
+# for THIS particular version of the source package
+version=${override_version:- at version@}
+upstream=${version%-*}
+revision=${version#*-}
+
+home=${home:-/usr/src/kernel-patches/all/$upstream/debian}
+
+if [ -f version.Debian ]; then
+	current=$(cat version.Debian)
+	current_rev=${current#*-}
+	current_up=${current%-*}
+
+	if [ "$current" = "$upstream" ]; then
+		current_rev=0
+	fi
+else
+	warn "No version.Debian file, assuming pristine Linux $upstream"
+	current=$upstream
+	current_rev=0
+fi
+
+target=${1:-$version}
+
+target_rev=${target#*-}
+target_up=${target%-*}
+
+# Sanity checks
+if [ "$target_up" != "$upstream" ]; then
+	die "Upstream $target_up doesn't match $upstream!"
+# We don't have that version out yet!
+elif [ ! -n "$target_rev" ] || ( [ "$target_rev" != "$target" ] && [ $target_rev -gt $revision ] ); then
+	year=$(($(date +%Y) + 1))
+	die "Can't patch to nonexistent revision $target_rev (wait until $year)"
+fi
+
+# At this point, we must handle three cases.
+# 1. $target_rev is greater than $current_rev. We must patch forward for this.
+# 2. $target_rev is less than $current_rev. We must reverse the list of series,
+#    reverse each used series (tac) and unapply applied patches and vice versa.
+# 3. $target_rev is undefined, and $target is $upstream.
+
+# Revert to upstream.
+if [ "$target_rev" = "$target" ]; then
+	# already reverted
+	if [ "$current" = "$target" ]; then 
+		echo "Nothing to do, exiting."
+		exit 0
+	fi
+
+	for sver in $(ls -d $home/series/* | sort -r); do
+		base=$(basename "$sver")
+		srev=${base#*-}
+		if [ -n "$srev" ]; then
+			if [ $srev -le $current_rev ]; then
+				unpatch_series $sver
+			fi
+		else
+			die "Series doesn't have a revision!"
+		fi
+	done
+elif [ "$current_rev" = "$upstream" ] || [ $target_rev -gt $current_rev ]; then
+	for sver in $home/series/*; do
+		base=$(basename "$sver")
+		srev=${base#*-}
+		if [ -n "$srev" ]; then
+			if [ $srev -gt $current_rev ] && [ $srev -le $target_rev ]; then
+				patch_series $sver
+			fi
+		else
+			die "Series doesn't have a revision!"
+		fi
+	done
+elif [ $target_rev -eq $current_rev ]; then
+	echo "Nothing to do, exiting."
+	exit 0
+elif [ $target_rev -lt $current_rev ]; then
+	for sver in $(ls -d $home/series/* | sort -r); do
+		base=$(basename "$sver")
+		srev=${base#*-}
+		if [ -n "$srev" ]; then
+			# -gt because you don't want to unapply the target series
+			if [ $srev -le $current_rev ] && [ $srev -gt $target_rev ]; then
+				unpatch_series $sver
+			fi
+		else
+			die "Series doesn't have a revision!"
+		fi
+	done
+fi
+
+echo $target > version.Debian
+
+# vim:noet:ai:ts=4

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/changelog
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/changelog	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/changelog	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,2040 @@
+kernel-source-2.6.9 (2.6.9-3) unstable; urgency=low
+
+  * Include dm_io-ENOMEM-goof patch that was included in final 2.6.8-8
+    (Andres Salomon).
+
+  * [SECURITY] Further binfmt_elf fixes, and binfmt_aout fixes as well
+    (Andres Salomon).
+
+  * [SECURITY] s390: sacf local root exploit (CAN-2004-0887) (Andres Salomon).
+
+  * [SECURITY] Further smbfs overflow fixes, stolen from -ac tree
+    (Andres Salomon).
+
+  * Add missing check for tty == NULL in uart_tasklet_action to fix an init
+    oops on serial console. (Joshua Kwan)
+
+  * Adding drivers-serial-8250-ioremap-fix.dpatch: a patch from Alex
+    Williamson that prevents setserial from crashing the kernel. See:
+    http://marc.theaimsgroup.com/?l=linux-kernel&m=109913237604338&w=2
+    (Dann Frazier)
+ 
+  * PCI IDE legacy mode fix for ata_piix
+    (Possible fix for: #279902, #273171) (Simon Horman)
+
+  * VLAN updates (Potential fix for: Bug#280743) (Simon Horman)
+
+  * Remove bogus DMA blacklist for RICOH CD-R/RW MP7083A (Maximilian Attems)
+  
+  * tmpfs inode accounting leak fix (Maximilian Attems)
+
+  * sparc fixes from ML (Joshua Kwan):
+    - sparc32: fix memcpy() bug that caused ramdisk failure (Jurij Smakov)
+    - sparc64: don't let breaks get eaten by sunsab (Jurij Smakov)
+
+ -- Andres Salomon <dilinger at voxel.net>  Thu, 25 Nov 2004 01:55:04 -0500
+
+kernel-source-2.6.9 (2.6.9-2) unstable; urgency=low
+
+  * [SECURITY] Fix problems in binfmt_elf loader; see
+    http://isec.pl/vulnerabilities/isec-0017-binfmt_elf.txt for more
+    details (Andres Salomon).
+
+  * Correctly detect VIA 8233A sound card (Simon Horman)
+
+  * VIA8231 support for parallel port driver (Simon Horman)
+
+  * Changed recomends libqt3-dev to libqt3-mt-dev as the former is debricated.
+    (closes: #279605) (Simon Horman)
+
+  * Allow READ_BUFFER_CAPACITY scsi ioctl. (Simon Horman)
+
+  * [ia64] fix a bug that causes HP systems to run out of DMA mapping resources
+    under heavy load (dann frazier)
+
+  * Include a UP build fix for the sn_console driver (dann frazier)
+
+  * Fix writeq/readq compile on alpha (Norbert Tretkowski).
+
+  * pages_scanned fix to stop kswapd going into loops (Simon Horman).
+
+  * Fixes to cope with hadrware with broken GetMaxLUN responses (Simon Horman).
+    (closes: Bug#279889)
+
+  * [ia64] Fix UP build by making sn_move_irq() a no-op when CONFIG_SMP=n
+    (dann frazier)
+
+  * Don't allow tmpfs to be mounted if the driver is not present
+    (closes: #275874) (Simon Horman)
+
+  * [sparc] Patches fixing sunzilog and cg14 (also applied to 2.6.8.)
+    (Joshua Kwan)
+
+ -- Andres Salomon <dilinger at voxel.net>  Mon, 15 Nov 2004 03:01:01 -0500
+
+kernel-source-2.6.9 (2.6.9-1) unstable; urgency=low
+
+  * New upstream release.
+
+  * Update prune-non-free (Andres Salomon).
+
+  * Delete the following unused patches (Andres Salomon):
+    . acpi-early.dpatch
+    . aic7xxx-pcitable.dpatch
+    . bio_uncopy_user-memleak.dpatch
+    . changelog.dpatch
+    . drivers-scsi-sym53c8xx_revert.dpatch
+    . modular-xfrm_tunnel.dpatch
+    . SG_IO-cap.dpatch
+    . SG_IO-safe-commands.dpatch
+
+  * Delete the following merged/backported patches (Andres Salomon):
+    . acpi-osname.dpatch
+    . acpi-speedstep-fix.dpatch
+    . alpha-epoch-comment.dpatch
+    . bio_uncopy_user-memleak-2.dpatch
+    . capi-freeing-fix.dpatch
+    . cciss-update.dpatch
+    . copy_to_high_bio_irq-leak-fix.dpatch
+    . fix-url-bsd-acct.dpatch
+    . drivers-ftape.dpatch
+    . drivers-input-hiddev-HIDIOCGUCODE.dpatch (note: Herbert's cleanups
+      dropped)
+    . drivers-macintosh-adb-trackpad.dpatch
+    . drivers-net-3c59x-build-fix.dpatch
+    . drivers-net-arcnet-crash.dpatch
+    . drivers-net-wireless-airo-build-smp.dpatch
+    . drivers-scsi-sym_2-dv-hang.dpatch
+    . drivers-usb-storage-transport_dimage_getmaxlun.dpatch
+    . ext3-direct-io-assert-fix.dpatch
+    . fix-sn_console-for-config_smp.dpatch
+    . forcedeth-update.dpatch
+    . hfs-loop-fix.dpatch
+    . i915-agp.dpatch
+    . ia64-mem-boot-param-fix.dpatch
+    . ia64-sparse-access_ok.dpatch
+    . ia64-sparse-copy_to_user.dpatch
+    . include-missing-includes.dpatch
+    . intel-cache-descriptors.dpatch
+    . jfs-memory-leak.dpatch
+    . marvell-mm.dpatch
+    . microcode-devfs-name.dpatch
+    . minix-block-accounting-fix.dpatch
+    . net-sched-fix.dpatch
+    . netstat-fix-output.dpatch
+    . nfs-fix.dpatch
+    . nfsd-subtreecheck-nostale.dpatch
+    . openpromfs-loop.dpatch
+    . pmac-no-of-stdout.dpatch
+    . powerpc-cmdline.dpatch
+    . powerpc-g4-errata.dpatch
+    . ppc-boot-isa.dpatch
+    . ptmx-fix.dpatch
+    . reiserfs-write-signed-fix.dpatch
+    . reiserfs-xattr-dont-dirty-mark.dpatch
+    . reiserfs-xattr.dpatch
+    . scsi-shutdown-fix.dpatch
+    . SG_IO-safe-commands-2.dpatch
+    . shm-segment-count-fix.dpatch
+    . sis900-add-phy.dpatch
+    . sparc32-export-more-ksyms.dpatch
+    . sparc64-sunsab-fix.dpatch
+    . sparc64-syslog-register.dpatch
+    . sparc64-update.dpatch
+    . tty-locking-fixes.dpatch
+    . xfs-ioctl32.dpatch
+
+  * Update the following patches (Andres Salomon)
+    . ia64-generic-no-smp.dpatch (partially merged)
+    . modular-ide.dpatch (triflex dropped /proc/ide/triflex)
+    . modular-vesafb.dpatch
+    . powerpc-ibm-240-e30.dpatch (partially merged)
+    . tg3-update.dpatch (no need to update tg3.h, it's not deleted)
+
+  * Drop the following patches (Andres Salomon, Christoph Hellwig):
+    . extraversion.dpatch (kernel now supports localversion; use that
+      instead)
+    . tcp_default_win_scale.dpatch (win_scale now auto-generated based
+      on optimum max win scale.  hopefully it works!)
+    . drivers-net-typhoon-build-fix.dpatch (fixes ETHTOOL stuff that's
+      only in BK?)
+    . alpha-termbits.dpatch (not needed anymore)
+    . pcxx-is-broken.dpatch (not needed anymore)
+    . powerpc-ibm-240-e30.dpatch (replaced by generie prep rtas support)
+
+  * Add build fixes for iSeries ppc64, typhoon, framemaster 2.
+    (Maximilian Attems)
+
+  * Add ext3 directio block leak fix. (Maximilian Attems)
+
+ -- Andres Salomon <dilinger at voxel.net>  Thu, 28 Oct 2004 01:11:01 -0400
+
+kernel-source-2.6.8 (2.6.8-8) unstable; urgency=medium
+
+  * Add workaround for broken Happy Meal ethernet controllers.
+    (closes: #275485) (Joshua Kwan)
+
+  * Fix goof in dm-io.c that led to uncaught errors on ENOMEM (Joshua Kwan)
+    using Nigel Cunningham's patch on LKML.
+
+  * Include a couple fixes for the mem= & max_addr= boot params on ia64.
+    (dann frazier)
+
+  * Resolved grammatical error in README.Debian
+    (closes: Bug#276359) (Simon Horman)
+
+  * Security: fix race conditions in linux terminal subsystem (CAN-2004-0814)
+    (dann frazier)
+
+  * Fix a couple ia64 argument order problems discovered by David Mosberger's
+    sparse runs (dann frazier)
+
+  * Ext3 direct io assert fix, update stale journal (Andres Salomon).
+
+  * Revert aic7xxx-pcitable patch (closes: #275302) (Andres Salomon).
+
+  * Another reiserfs xattr fix; this one keeps inodes from being marked
+    dirty if it hasn't been hashed (Andres Salomon).
+
+  * Reiserfs's write() return values should be signed, not unsigned
+    (Andres Salomon).
+
+  * Added work-around to allow usb storage device to access
+    a Konica-Minolta DiMAGE A2 camera. (closes: Bug#276134) (Simon Horman)
+
+  * Fix memory leak in packet scheduler.
+    (closes: Bug#276476) (closes: Bug#275059) (Simon Horman)
+
+  * Fix slab corruption on packet scheduler. (Simon Horman)
+
+  * NFS localhost mount netfilter fix (closes: #254645) (Andres Salomon).
+
+  * Correctly detect VIA 8233A sound card (closes: #254645) (Simon Horman)
+
+  * Update aic7xxx/aic79xx to current mainline versions (Christoph Hellwig).
+
+  * Drop aic79xx-nohw; superceded by aic7xxx-update (Andres Salomon).
+
+  * Fix smbfs overrun/leak (Andres Salomon).
+
+  * VIA8231 support for parallel port driver (closes: #279174) (Simon Horman)
+
+  * [ACPI] reserve EBDA for Dell BIOS that neglects to.
+    (Possible fix for: Bug#277298) (Simon Horman)
+
+  * Changed recomends libqt3-dev to libqt3-mt-dev as the former is debricated.
+    (closes: #279605) (Simon Horman)
+
+  * Via Velocity Driver update from 2.6.9
+    (closes: Bug#278508) (Simon Horman)
+
+  * Allow more SCSI ioctls.
+    (Possible fix for: Bug#277083) (Simon Horman)
+
+  * [ia64] fix a bug that causes HP systems to run out of DMA mapping resources
+    under heavy load (dann frazier)
+
+  * Backport of vmscan fixes from upstream. (Simon Horman)
+
+  * Fixes to cope with hardware with broken GetMaxLUN responses (Simon Horman).
+    (Possible fix for: Bug#279889)
+
+ -- Andres Salomon <dilinger at voxel.net>  Tue, 09 Nov 2004 01:28:16 -0500
+
+kernel-source-2.6.8 (2.6.8-7) unstable; urgency=medium
+
+  * Fix VGA console on PReP systems (closes: #271852) (Jens Schmalzing).
+
+  * Really enable i915 agpgart support (Christoph Hellwig).
+
+  * Fix yet another bio leak (Christoph Hellwig).
+
+  * Switch /proc/sys/net/ipv4/tcp_default_win_scale default back to 0, there's
+    just too many broken system out there in the wild. (closes: #267342)
+    (Christoph Hellwig).
+
+  * Fix ata_piix controller numbering in combined mode (closes: #270194)
+    (Christoph Hellwig).
+
+  * Update tg3 driver (Christoph Hellwig).
+  
+  * Update forcedeth driver to fix autoneg on 100Mbit cards (Christoph Hellwig).
+
+  * Fix ALSA module locking issue (closes: #259056) (Andres Salomon).
+
+  * Build-fix for 3c59x without pci (closes: #267240) (Maximilian Attems).
+
+  * Fix crash in ArcNet PCMCIA card (Maximilian Attems).
+
+  * Build-fix for airo on smp (Maximilian Attems).
+
+  * ACK old nmu (closes: #181350, #126482, #153451, #206984)
+
+  * Back out acpi-early caused problems on laptops, where APIC should not 
+    be enabled. (closes: #272177, #273474, #274011) (Maximilian Attems)
+
+ -- Andres Salomon <dilinger at voxel.net>  Sun, 03 Oct 2004 03:21:14 -0400
+
+kernel-source-2.6.8 (2.6.8-6) unstable; urgency=medium
+
+  * reiserfs xattr/acl fix if root fs (Max Attems).
+
+  * fix /proc/net/netstat output for `netstat -s` (Max Attems).
+
+  * Add missing intel CPU descriptors (Max Attems).
+
+  * Revert changelog.dpatch that was silently added (Christoph Hellwig).
+
+  * JFS: fix memory leak (Max Attems).
+
+  * Add sis900 phy (Max Attems).
+
+  * Fix bad URL in BSD acct help entry (closes: #268871) (Max Attems).
+
+  * Mark CONFIG_DIGI broken (closes: #258676) (Christoph Hellwig).
+
+  * Fix devfs name for microcode driver (closes: #221813) (Christoph Hellwig).
+
+  * Fix loop on hfs/hfsplus (closes: #261195) (Christoph Hellwig).
+
+  * Fix default kernel boot args on openfirmware powerpc (Sven Luther).
+
+  * Add CAPI skb freeing fix (closes: #269134) (Christoph Hellwig).
+
+  * Update debian/apply from 2.4 to allow us to base prune-non-free on
+    file removals in the patch series. (Closes: #267655)
+
+  * Make sure SCSI disk caches are flushed on shutdown (Christoph Hellwig).
+
+  * Handle loaded but no hardware present properly in aic79xx (closes: 270102)
+    (Christoph Hellwig).
+
+  * Export proper PCI ID table to hotplug in aic7xxx/aic79xx
+    (Christoph Hellwig).
+
+  * Add a patch by davem which suppresses a loop when reading from openpromfs.
+    (Joshua Kwan)
+  
+  * Set all files in the patch dir non-executable.
+
+ -- Joshua Kwan <joshk at triplehelix.org>  Mon,  6 Sep 2004 21:28:18 -0700
+
+kernel-source-2.6.8 (2.6.8-5) unstable; urgency=high
+
+  * Patches by the infintely wise and awesome David S. Miller:
+    - sparc64-sunsab-fix.dpatch: Fix the infamous serial output
+      bug causing every other character in kernel messages to be omitted.
+    - sparc64-syslog-register.dpatch: Fix a critical typo that
+      caused the 32-bit syslog wrapper to halt the entire system.
+    (Joshua Kwan).
+
+  * sparc32: Export enough ksyms for our modules to work  (Joshua Kwan).
+
+  * Drop patch modular-xfrm4_tunnel, which caused far more trouble than it
+    was worth. (Joshua Kwan).
+
+  * Switch to the 2.4.x patch-series system. Drop build-dependency on dpatch
+    (Joshua Kwan).
+
+  * Add myself to Uploaders (Joshua Kwan).
+
+  * Build kernel-tree package before kernel-doc, because it takes a _long_
+    time (Joshua Kwan).
+
+ -- Joshua Kwan <joshk at triplehelix.org>  Fri, 27 Aug 2004 16:36:39 -0700
+
+kernel-source-2.6.8 (2.6.8-4) unstable; urgency=high
+
+  * Added patch by Alex Clausen to stop spurious mouse button events
+    on older ADB using pmac notebooks (Sven Luther).
+
+  * Added two SCSI commands, namely VERIFY_16 and GPCMD_SEND_CUE_SHEET,
+    that were mentioned in the list from 2.6.9-rc1 but missing from the
+    corresponding header files (closes: #268128) (Jens Schmalzing).
+
+  * Added g4-errata followup patch that clears the BTIC bit, instead of
+    just not setting it (Sven Luther).
+
+  * Add some Sparc64 backports to make Josh happy (Christoph Hellwig).
+
+ -- Jens Schmalzing <jensen at debian.org>  Thu, 26 Aug 2004 14:30:01 +0200
+
+kernel-source-2.6.8 (2.6.8-3) unstable; urgency=high
+
+  * Suggest libqt3-dev for xconfig (closes: #261784) (Andres Salomon).
+
+  * Update documentation (Christoph Hellwig).
+
+  * Add bio_uncopy_user leak fix from Kurt Garloff (closes: #256871)
+    (Christoph Hellwig).
+
+  * Update scsi blacklist for USB multi card readers (Christoph Hellwig).
+
+  * Claim we're Windows (TM) to ACPI to work around broken BIOSes
+    (Christoph Hellwig).
+
+  * Fix early boot crash on some oldworld Power Macs. (closes: #266731)
+    (Christoph Hellwig).
+
+  * Add qdisc crash fix (closes: #266892) (Christoph Hellwig).
+
+  * Replace the drivers-scsi-sym53c8xx_revert workaround with
+    drivers-scsi-sym_2-dv-hang, which is a proper fix for the hang
+    (dann frazier).
+
+  * Enter ACPI mode earlier (closes: #258061) (Christoph Hellwig).
+
+  * Add a comment about the Adaptec firmware rebuild situation to
+    README.Debian (closes: #256757) (Christoph Hellwig).
+
+  * Update bio_uncopy_user-memleak to really fix the problem
+    (closes: #267464, #267338) (Christoph Hellwig).
+
+  * Update list of safe SCSI commands for SG_IO to match 2.6.9-rc1
+    (Christoph Hellwig).
+
+  * Update CCISS driver (Christoph Hellwig).
+
+  * Add minix block accounting fix (Christoph Hellwig).
+
+  * Fix nfsd to not errornously return ESTALE on failed permission check
+    (closes: #255931) (Christoph Hellwig).
+
+  * Fix SHM segment count limit off by one (Christoph Hellwig).
+
+  * Modularize xfrm_tunnel (Christoph Hellwig).
+
+  * Add small ACPI fix that makes speedstep work on some Centrino Laptops
+    (closes: #257763) (Christoph Hellwig).
+
+ -- Sven Luther <luther at debian.org>  Wed, 25 Aug 2004 17:40:07 +0200
+
+kernel-source-2.6.8 (2.6.8-2) unstable; urgency=high
+
+  * Add updated fix for generic UP kernel builds on IA64 (dann frazier).
+
+  * Added g4 l2 flush and MSR patch from Jacob Pan (Sven Luther).
+ 
+  * Added marvell gigabit ethernet driver errata patch from Nicolas Det
+    (Sven Luther).
+
+  * Added UP build fixes for sn_console & cyclone on ia64 (dann frazier).
+
+ -- Sven Luther <luther at debian.org>  Tue, 17 Aug 2004 15:34:59 +0200
+
+kernel-source-2.6.8 (2.6.8-1) unstable; urgency=high
+
+  * New upstream release.
+  
+  * Nuke tg3.c properly in prune-non-free; rely on patch to supply driver
+    (Andres Salomon).
+
+  * The following patches have been merged upstream (Andres Salomon):
+    . acpi-typo
+    . chown-gid-check
+    . chown-procfs
+    . dont-dereference-netdev.name-before-register_netdev
+      (partially applied; this is a broken patch)
+    . drivers-atkbd-quiten
+    . drivers-dpt_i2o-fixup
+    . drivers-isdn-io_funcs-fixup
+    . drivers-net-irda-dma_api
+    . drivers-net-via_rhine-avoid_bitfield
+    . drivers-sb-pnp_unregister
+    . drivers-scsi-advansys-dma_api
+    . drivers-scsi-sd-NO_SENSE
+    . drivers-usb-net-pegasus-startstop_queue
+    . envp
+    . fs-isofs-acorn
+    . fs-isofs-dont-check-period
+    . fs-jfs-compile
+    . include-linux-mca.h-fixups
+    . netfilter-signedcharbug
+    . netlink-macro-fixups
+    . powerpc-g4-errata
+    . xfs-update
+
+  * The following patches have been modified (Andres Salomon):
+    . drivers-input-hiddev-HIDIOCGUCODE
+      (sparse fixes; s/(void *) arg/user_arg/g)
+    . remove-references-to-removed-drivers
+      (upstream now considers SMCTR a broken and legacy driver)
+    . drivers-net-tg3-readd
+      (forward port firmware changes to new tg3; from version 3.3
+      of driver to version 3.8)
+
+  * Stop the kernel distclean from nuking the debian directory by
+    having the clean rule check for debian/official (Andres Salomon).
+
+  * Fix typo in alpha-termbits patch naming (Christoph Hellwig).
+
+  * Drop two unneeded patches (Christoph Hellwig):
+    . fs-cramfs-constify
+    . include-thread_info-ifdefs
+
+  * Remove -2 postfixes from patches, this is a new upstream release
+    (Christoph Hellwig).
+
+  * Add NFS OOPS fix (Christoph Hellwig).
+
+  * Add SG_IO WRITE_BUFFER capability check (Christoph Hellwig).
+
+  * Fix IA64 generic kernel compile on UP (Christoph Hellwig).
+
+  * Add pty leak fix from Al Viro (Christoph Hellwig).
+
+  * Add patch from Gustavo Barbier to support IBM RS/6000 7043-240 and -E30
+    (Christoph Hellwig).
+
+  * Add 32bit ioctl translation support to XFS (closes: Bug#257265)
+    (Christoph Hellwig).
+
+  * Revert sym53c8xx driver (dann frazier).
+
+ -- Andres Salomon <dilinger at voxel.net>  Sat, 14 Aug 2004 02:40:50 -0400
+
+kernel-source-2.6.7 (2.6.7-4) unstable; urgency=high
+
+  * Migrated pegasos patch from the powerpc package, as it will be accepted
+    upstream (Sven Luther).
+
+  * Added a errata fix for some recent G4 processors (Sven Luther).
+
+  * Fixed the Powerpc/Pegasos marvell discovery II builtin gigabit ethernet
+    driver to use the MAC address set by the firmware, instead of reading the
+    value from the prom in a way specific to the mips board (Sven Luther).
+
+ -- Jens Schmalzing <jensen at debian.org>  Thu,  5 Aug 2004 18:32:00 +0200
+
+kernel-source-2.6.7 (2.6.7-3) unstable; urgency=low
+
+  * Upgraded the fs-asfs patch to 1.0beta7 (Jens Schmalzing).
+
+  * Updated README.NMU to explain the new build process based on split
+    patches and dpatch (Jens Schmalzing).
+
+  * Added chown security fixes (closes: Bug#257504) (Christoph Hellwig).
+
+  * Dropped modular-swsusp, doesn't work and unmaintained (Christoph Hellwig).
+
+  * Added 3ware SATA-RAID driver, backported from mainline (Christoph Hellwig).
+
+  * Update XFS to most current upstream BK version (Christoph Hellwig).
+
+  * Added Marvell Ethernet driver (closes: Bug#256064) (Christoph Hellwig).
+
+  * Added a backport of the netfilter signed char fix (Christoph Hellwig).
+
+ -- Sven Luther <luther at debian.org>  Wed,  7 Jul 2004 18:12:20 +0200
+
+kernel-source-2.6.7 (2.6.7-2) unstable; urgency=low
+
+  * Removed another tainted driver (closes: Bug#242895), and amended
+    remove-references-to-removed-drivers.dpatch accordingly.  Actually,
+    this was done in the previous revision, but we forgot the changelog
+    entry (Christoph Hellwig, Jens Schmalzing).
+
+  * Renamed debian/revision back to version.Debian.  Having it outside the
+    debian/ directory is mandatory for kernel-tree to work (Jens Schmalzing).
+
+  * Added the drivers-net-tg3 patch.  It only adds firmware loading
+    support, contrary to the drivers-net-tg3-readd patch which re-adds the
+    whole driver.  As a consequence, the Debian patch also applies to the
+    vanilla kernel again.  Note that this patch is only kept here for
+    reference for the time being and will not be activated until the next
+    upstream release (Jens Schmalzing).
+
+  * Added the fs-asfs patch by Marek Szyprowski, containing support for
+    the Amiga Smart Filesystem.  Actually, the patch was already part of
+    the kernel-patch-powerpc package and has been moved over from there
+    (Jens Schmalzing).
+
+ -- Jens Schmalzing <jensen at debian.org>  Thu, 24 Jun 2004 09:56:13 +0200
+
+kernel-source-2.6.7 (2.6.7-1) unstable; urgency=low
+
+  * New upstream release.
+
+  * Added split patches in dpatch format (Christoph Hellwig and Sven Luther).
+
+  * Lots of patches merged upstream:
+    . acpi-link
+    . console-refcounting
+    . doc-sound
+    . drivers-hotplug-acpi-unregister
+    . drivers-i810-update
+    . drivers-ide-CONFIG_IDE_STROKE-at-runtime (slight changes, allows drops
+      the config option completely)
+    . drivers-mca_53c9x-needs_mca_legacy
+    . drivers-mtd-sharp-missing-includes
+    . drivers-mtd-uclinux-rootfs
+    . drivers-neomagic-ids
+    . drivers-neomagic-oss-ids
+    . drivers-paride-epat (with minor updates)
+    . drivers-pnp-needs-x86
+    . drivers-scsi-aic7xxx-fixes (slightly different)
+    . drivers-usb-storage-new-sony-device
+    . drivers-video-tgafb-needs-selection.h
+    . drivers-watchdog-missing-includes
+    . fs-isofs-remove-unused
+    . include-linux-mca.h-fixups (only partially)
+    . makefile-wc-fixup
+    . sparc64-NR_CPUS
+    . x86-dma-mapping.h-fixups
+
+  * Dropped some patches (Christoph Hellwig):
+    . alpha_cia_window - incorrect (closes: #253787)
+    . doc-initrd_devfs - incorrect, devfs names for initrd are okay
+    . drivers-mwave_paper_over_sysfs_crap - buggy driver model integration
+      removed completely upstream
+    . drivers-net-ns83820-needs-FW_LOADER - incorrect, ns83820 doesn't
+      load firmware at all
+    . drivers-scsi-3w-xxxx-no_unregister - incorrect
+    . export-proc_get_inode - the symbol is internal for a reason.  buggy
+      drivers using it removed in 2.6.7
+    . fs-msdos-dontbug - rejected upstream
+    . fs-umsdosfs-crapola - umdos is disconnected from the build in 2.6
+    . ppc-higher-binutils-requirement - upstream disagrees, Debian uses
+      dpkg build depencies anyway
+    . 00_doc-README.Debian - now handled differently by the packaging
+  
+  * Renamed version.Debian to debian/revision, in order to have all Debian
+    specific bits in the debian directory (Jens Schmalzing).
+
+  * Added the prune target to debian/rules.  It unpacks the vanilla
+    kernel, removes the tainted bits, and creates a free .orig.tar.gz
+    (Jens Schmalzing).
+
+  * Added the monolith target to debian/rules.  It saves a copy of the
+    original kernel tree, then for each revision applies the split patches
+    via dpatch and creates a monolithic patch (Jens Schmalzing).
+
+  * Add fs-jfs-compile to fix JFS compilation (Christoph Hellwig).
+
+  * Package the upstream changelog file, taken from ChangeLog-<release>,
+    into kernel-tree.  The rationale of this being that we should
+    distribute the upstream changelog in the usual location, but it is
+    enough to do this once (Jens Schmalzing).
+
+ -- Jens Schmalzing <jensen at debian.org>  Mon, 21 Jun 2004 12:55:48 +0200
+
+kernel-source-2.6.6 (2.6.6-2) unstable; urgency=low
+
+  * Fix i386 FPU bug.
+  * Transfer control of package to debian kernel team.
+
+ -- William Lee Irwin III <wli at debian.org>  Tue, 15 Jun 2004 11:06:35 -0700
+
+kernel-source-2.6.6 (2.6.6-1) unstable; urgency=low
+
+  * New upstream release (closes: #243084, #244728, #245959, #247486).
+  * Deleted unused exit prototype in drivers/scsi/aic7xxx/aic7xxx_osm.c.
+  * Unregister properly if no devices are found in
+    drivers/scsi/aic7xxx/aic79xx_osm.c (closes: #246277, #247298).
+  * Fixed GUCODE type check in drivers/usb/input/hiddev.c (Sergey Vlasov).
+  * Added basic highmem support in drivers/scsi/advansys.c (closes: #245238).
+  * Changed all occurrences herbert at debian.org:
+    . arch/i386/power/swsusp_syms.c
+    . arch/x86_64/kernel/swsusp_syms.c
+    . kernel/power/swsusp-core.c
+    . kernel/power/swsusp.h
+  * Reverted broken "VIA KT400-8235" change in arch/i386/kernel/dmi_scan.c.
+  * Fixed IRQ assignment in drivers/acpi/pci_link.c (Len Brown).
+  * Fixed resume device check (Sau Dan Lee):
+    . kernel/power/swsusp-core.c
+    . kernel/power/swsusp.c
+    . kernel/power/swsusp.h
+  * Restored driver without firmware:
+    . drivers/net/Kconfig
+    . drivers/net/Makefile
+    . drivers/net/tg3.c
+  * Added firmware loading support (Nathaneal Nerode):
+    . drivers/net/Kconfig
+    . drivers/net/tg3.c
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 11 May 2004 19:42:16 +1000
+
+kernel-source-2.6.5 (2.6.5-4) unstable; urgency=high
+
+  * Unregister PCI driver in drivers/pci/hotplug/acpiphp_glue.c.
+  * Fixed print_pirt NULL deref in drivers/pci/hotplug/shpchprm_acpi.c
+    (closes: #246149).
+  * Reverted radeon/r128 firmware changes (closes: #246587, #246594, #246627):
+    . drivers/char/drm/Kconfig
+    . drivers/char/drm/Makefile
+    . drivers/char/drm/r128_cce.c
+    . drivers/char/drm/r128_drv.h
+    . drivers/char/drm/r128_firmware_loader.c
+    . drivers/char/drm/radeon_cp.c
+    . drivers/char/drm/radeon_drv.h
+    . drivers/char/drm/radeon_firmware_loader.c
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 30 Apr 2004 09:05:39 +1000
+
+kernel-source-2.6.5 (2.6.5-3) unstable; urgency=medium
+
+  * Added firmware loading support (Nathaneal Nerode):
+    . drivers/char/drm/Kconfig
+    . drivers/char/drm/Makefile
+    . drivers/char/drm/r128_cce.c
+    . drivers/char/drm/r128_drv.h
+    . drivers/char/drm/r128_firmware_loader.c
+    . drivers/char/drm/radeon_cp.c
+    . drivers/char/drm/radeon_drv.h
+    . drivers/char/drm/radeon_firmware_loader.c
+  * Removed non-free firmware:
+    . R128 firmware: drivers/char/drm/r128_cce.c
+    . Radeon firmware: drivers/char/drm/radeon_cp.c
+  * Read .extraversion if it exists in Makefile.
+  * Added support for removal in drivers/ide/ide-generic.c.
+  * Set GPL license in arch/i386/kernel/cpu/mcheck/non-fatal.c.
+  * Copy pages in reverse (closes: #234976):
+    . arch/i386/power/pmdisk.S
+    . arch/i386/power/swsusp.S
+  * Lowered maximum NR_CPUS to 32 in arch/sparc64/Kconfig (closes: #245971).
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 27 Apr 2004 20:31:41 +1000
+
+kernel-source-2.6.5 (2.6.5-2) unstable; urgency=low
+
+  * Reverted pid == 1 change in kernel/fork.c.
+  * Allow PCI IDE drivers to be unloaded if probing fails in
+    drivers/ide/pci/atiixp.c.
+  * Fixed single word src misalign > dest misalign case in
+    arch/alpha/lib/stxncpy.S (glibc).
+  * Removed obsolete gcc workaround in sound/core/oss/Makefile.
+  * Fixed boundary checks for GUSAGE/SUSAGE in drivers/usb/input/hiddev.c.
+  * Fake inquiry for Sony Clie PEG-TJ25 in drivers/usb/storage/unusual_devs.h
+    (closes: #243650).
+  * Strip quotes from parameters in kernel/params.c (bk, closes: #243588).
+  * Added device release function in drivers/char/mwave/mwavedd.c
+    (closes: #244207).
+  * Set __exit tags on module_exit in drivers/ide/pci/*.
+  * Partially modularised software suspend:
+    . arch/i386/power/Makefile
+    . arch/i386/power/swsusp_syms.c
+    . arch/x86_64/kernel/Makefile
+    . arch/x86_64/kernel/swsusp_syms.c
+    . drivers/acpi/sleep/proc.c
+    . fs/buffer.c
+    . include/linux/suspend.h
+    . kernel/sys.c
+    . kernel/power/Kconfig
+    . kernel/power/Makefile
+    . kernel/power/console.c
+    . kernel/power/process.c
+    . kernel/power/swsusp-core.c
+    . kernel/power/swsusp.c
+    . kernel/power/swsusp.h
+    . mm/vmscan.c
+  * Fixed illegal __exit reference:
+    . drivers/scsi/aic7xxx/aic7xxx_osm.c
+    . drivers/scsi/aic7xxx/aic7xxx_osm.h
+  * Fixed local root exploit in fs/isofs/rock.c (Ernie Petrides).
+  * Clear b_data in journal_get_descriptor_buffer in fs/jbd/journal.c
+    (Ted Ts'o).
+  * Added module option parsing in drivers/video/vesafb.c (closes: #244031).
+  * Fixed vesafb_exit leaks in drivers/video/vesafb.c.
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 23 Apr 2004 21:50:18 +1000
+
+kernel-source-2.6.5 (2.6.5-1) unstable; urgency=low
+
+  * New upstream release (closes: #235419, #238569).
+  * Applied SCSI Media Changer patch (closes: #238476).
+  * Fixed strcmp in sysfs store (closes: #234446):
+    . kernel/power/main.c
+    . kernel/power/disk.c
+  * Do not unshare files for pid == 1 in kernel/fork.c (closes: #239029).
+  * Removed ide-detect in favour of ide-generic:
+    . drivers/ide/Makefile
+    . drivers/ide/ide-default.c
+    . drivers/ide/ide-generic.c
+    . drivers/ide/ide-io.c
+    . drivers/ide/ide-probe.c
+    . drivers/ide/ide-probe-mini.c
+  * Check __HAVE_THREAD_FUNCTIONS in include/linux/thread_info.h (m68k).
+  * Unregister properly if no devices are found (closes: #237477):
+    . drivers/scsi/aic7xxx/aic7770_osm.c
+    . drivers/scsi/aic7xxx/aic7xxx_osm.c
+    . drivers/scsi/aic7xxx/aic7xxx_osm.h
+  * Fixed X86_PM_TIMER description in drivers/acpi/Kconfig (Jochen Voss,
+    closes: #241941).
+  * Removed non-free firmware and disabled their drivers (see #239952):
+    . QLA2XXX: drivers/scsi/qla2xxx/*_fw.c
+    . TIGON3: drivers/net/tg3.c
+    . Unused: sound/oss/724hwmcode.h
+    . Unused: sound/oss/Hwmcode.h
+  * Lowered priority of "too many keys" message in
+    drivers/input/keyboard/atkbd.c (closes: #239036).
+  * Made %docs depend on scripts_basic instead of scripts in Makefile.
+  * Fixed syntax error in Documentation/DocBook/parportbook.tmpl.
+  * Include linux/init.h for __init in sound/pcmcia/pdaudiocf/pdaudiocf.c
+  * Fixed bashism in Makefile.
+
+ -- Herbert Xu <herbert at debian.org>  Tue,  6 Apr 2004 20:42:02 +1000
+
+kernel-source-2.6.4 (2.6.4-1) unstable; urgency=low
+
+  * New upstream release (closes: #234631, #234754, #236570).
+  * Added vmlinux.syms:
+    . scripts/Makefile.modpost
+    . scripts/modpost.c
+  * Allow X86_MCE_NONFATAL to be a module:
+    . arch/i386/Kconfig
+    . arch/i386/kernel/cpu/mcheck/mce.c (Andrew Morton)
+  * Black listed "TOSHIBA CD-ROM XM-1702BC" in drivers/ide/ide-dma.c.
+  * Black listed "VIA KT400-8235" for broken_pirq in
+    arch/i386/kernel/dmi_scan.c (closes: #235188).
+  * Handle NO_SENSE in sd_rw_intr in drivers/scsi/sd.c (Alan Stern,
+    closes: #232494).
+  * Reverted tasklet change in drivers/usb/host/uhci-hcd.*.
+  * Fixed ThinkPad lock up problem in drivers/usb/host/uhci-hcd.c (Alan Stern).
+  * Put __modpost under MODVERDIR in scripts/Makefile.modpost.
+  * Provide *-2.6 instead of *-2.4 (closes: #236779).
+  * Fixed IDE CD capacity detection in drivers/ide/ide-cd.c (Jens Axboe,
+    closes: #216581).
+  * Removed dev->name lookups before register_netdev (closes: #234817):
+    . drivers/net/3c501.c
+    . drivers/net/3c503.c
+    . drivers/net/8390.c
+    . drivers/net/8390.h
+    . drivers/net/ac3200.c
+    . drivers/net/apne.c
+    . drivers/net/e2100.c
+    . drivers/net/es3210.c
+    . drivers/net/hp-plus.c
+    . drivers/net/hp.c
+    . drivers/net/hydra.c
+    . drivers/net/lne390.c
+    . drivers/net/mac8390.c
+    . drivers/net/ne.c
+    . drivers/net/ne2.c
+    . drivers/net/ne2k-pci.c
+    . drivers/net/ne2k_cbus.c
+    . drivers/net/ne3210.c
+    . drivers/net/oaknet.c
+    . drivers/net/smc-mca.c
+    . drivers/net/smc-ultra.c
+    . drivers/net/smc-ultra32.c
+    . drivers/net/stnic.c
+    . drivers/net/wd.c
+    . drivers/net/zorro8390.c
+  * Set MODVERDIR based on SUBDIRS in Makefile (Andreas Gruenbacher,
+    closes: #236626).
+  * Remove reference to drivers/parport/init.c in
+    Documentation/DocBook/parportbook.tmp.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 13 Mar 2004 14:13:45 +1100
+
+kernel-source-2.6.3 (2.6.3-2) unstable; urgency=low
+
+  * Rebuilt to fix tarball in kernel-source package.
+  * Really added the Post-Halloween document.
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 23 Feb 2004 08:01:24 +1100
+
+kernel-source-2.6.3 (2.6.3-1) unstable; urgency=low
+
+  * New upstream release.
+  * Replaced irq_resource usage:
+    . drivers/isdn/hardware/avm/b1isa.c
+    . drivers/isdn/hardware/avm/t1isa.c
+    . drivers/isdn/hisax/hisax_fcclassic.c
+  * Added Post-Halloween document.
+  * Allow PCI IDE drivers to be unloaded if probing fails (closes: #202828):
+    . drivers/ide/arm/*.c
+    . drivers/ide/pci/*.c
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 20 Feb 2004 20:48:48 +1100
+
+kernel-source-2.6.2 (2.6.2-2) unstable; urgency=high
+
+  * Added build-dependency on gs (closes: #232631).
+  * Restored generic SCSI proc_info function in drivers/scsi/scsi_proc.c
+    (closes: #232533).
+  * Fixed early chip programming in tg3_setup_copper_phy() in drivers/net/tg3.c
+    (David Miller).
+  * Fixed dev timer SMP deadlock in drivers/scsi/aic7xxx/aic7xxx_osm.c
+    (Andrew Morton).
+  * Check return value of do_munmap in do_mremap in mm/mremap.c (2.6.3).
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 18 Feb 2004 21:29:09 +1100
+
+kernel-source-2.6.2 (2.6.2-1) unstable; urgency=low
+
+  * New upstream release (closes: #227071, #229745, #227240, #231466).
+  * Made PDC202XX_{BURST,FORCE} available even if it is a module in
+    drivers/ide/Kconfig.
+  * Fixed dead lock in drain_dac in sound/oss/i810_audio.c.
+  * Added drivers/ide/ide-probe-mini.c (2.4, closes: #224082, #227317, #228906,
+    #230195, #230755).
+  * Updated kernel-source description from kernel-package (closes: #226816).
+  * Added upstream changelog (closes: #230183).
+  * Added build-dependency on docbook-utils and transfig.
+  * Put kernel_thread_helper in right segment in arch/i386/kernel/process.c
+    (bk).
+
+ -- Herbert Xu <herbert at debian.org>  Sat,  7 Feb 2004 10:36:58 +1100
+
+kernel-source-2.6.0 (2.6.0-2) unstable; urgency=low
+
+  * Don't allow mremap of zero-sized areas in mm/mremap.c (2.6.1,
+    closes: #226542).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 11 Jan 2004 16:34:27 +1100
+
+kernel-source-2.6.0 (2.6.0-1) unstable; urgency=low
+
+  * New upstream release.
+  * Documented psmouse/mousedev in README.Debian (closes: #223596).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 21 Dec 2003 16:16:02 +1100
+
+kernel-source-2.6.0-test11 (2.6.0-test11-1) unstable; urgency=low
+
+  * New upstream release (closes: #212831, #215530, #217908, #218749, #218768,
+    #219239, #219944, #220432).
+  * Reverted set_blocksize change in fs/block_dev.c (closes: #214131).
+  * Removed libqt-dev suggestion in kernel-source.
+  * Added Freecom FX-5/FX-50 in drivers/usb/storage/unusual_devs.h
+    (Luke Kenneth Casson Leighton, closes: #218781).
+  * Unregister driver if probing fails in sound/oss/sb_card.c
+    (closes: #218845).
+  * Work around gcc bug in sound/core/oss/Makefile (closes: #203195).
+  * Use page cache for cramfs_read in fs/cramfs/inode.c (Al Viro).
+  * Fixed DMA overruns/bugs in sound/oss/i810_audio.c.
+  * Include asm/io.h and asm/scatterlist.h in include/asm-i386/dma-mapping.h.
+  * Removed uses of isa_vir_to_bus (closes: #218878):
+    . drivers/net/irda/ali-ircc.c
+    . drivers/net/irda/nsc-ircc.c
+    . drivers/net/irda/smsc-ircc2.c
+    . drivers/net/irda/via-ircc.c
+    . drivers/net/irda/via-ircc.h
+    . drivers/net/irda/w83977af_ir.c
+    . include/net/irda/ali-ircc.h
+    . include/net/irda/irda_device.h
+    . include/net/irda/nsc-ircc.h
+    . include/net/irda/w83977af_ir.h
+    . net/irda/irda_device.c
+  * Fixed Tekram DC390 driver (Guennadi Liakhovetski, closes: #221865):
+    . drivers/scsi/Kconfig
+    . drivers/scsi/dc390.h
+    . drivers/scsi/scsiiom.c
+    . drivers/scsi/tmscsim.c
+    . drivers/scsi/tmscsim.h
+  * Flush bundles when devices go down:
+    . include/net/xfrm.h
+    . net/xfrm/xfrm_policy.c
+    . net/xfrm/xfrm_state.c
+  * Fixed inclusion loop with include/net/sctp/sm.h:
+    . include/net/sctp/sctp.h
+    . net/sctp/associola.c
+    . net/sctp/outqueue.c
+    . net/sctp/socket.c
+    . net/sctp/transport.c
+  * Fixed connect/disconnect race in drivers/usb/core/hub.c (2.4,
+    closes: #218670).
+  * Initialise state for /proc/net/tcp in net/ipv4/tcp_ipv4.c (bk).
+  * Cleaned up debian/rules a little.
+  * Schedule tasklets for async removal in drivers/usb/host/uhci-hcd.*.
+
+ -- Herbert Xu <herbert at debian.org>  Mon,  8 Dec 2003 20:23:22 +1100
+
+kernel-source-2.6.0-test9 (2.6.0-test9-1) unstable; urgency=low
+
+  * New upstream release (closes: #216972).
+  * Applied x86/64bit fix in drivers/char/ftape/lowlevel/ftape-calibr.c (2.4).
+  * Include linux/fs.h for struct file:
+    . drivers/char/watchdog/scx200_wdt.c
+    . drivers/char/watchdog/wdt_pci.c
+    . drivers/char/watchdog/i810-tco.c
+    . drivers/char/watchdog/alim7101_wdt.c
+    . drivers/char/watchdog/alim1535_wdt.c
+    . drivers/char/watchdog/sc1200wdt.c
+    . drivers/char/watchdog/amd7xx_tco.c
+    . drivers/char/applicom.c
+  * Include linux/init.h for __init:
+    . drivers/char/moxa.c
+    . drivers/char/mxser.c
+    . drivers/mtd/chips/jedec_probe.c
+    . drivers/mtd/chips/sharp.c
+    . drivers/net/sb1000.c
+    . drivers/net/wan/sealevel.c
+    . drivers/net/wan/cosa.c
+  * Removed unnecessary asm/setup.h in drivers/mtd/cmdlinepart.c.
+  * Support architectures without asm/mca.h:
+    . include/linux/mca.h
+    . include/linux/mca-legacy.h
+  * Made PNPBIOS X86 only in drivers/pnp/Kconfig.
+  * Added CIBAUD/CMSPAR in include/asm-alpha/termbits.h.
+  * Include linux/selection.h for color_table in drivers/video/tgafb.c.
+  * Added optimise by size option:
+    . Makefile
+    . init/Kconfig
+  * Fixed reference count bug in net/xfrm/xfrm_policy.c.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 26 Oct 2003 16:16:43 +1100
+
+kernel-source-2.6.0-test7 (2.6.0-test7-1) unstable; urgency=low
+
+  * Fixed NLMSG_OK and RTA_OK:
+    . include/linux/netlink.h
+    . include/linux/rtnetlink.h
+  * Reverted process group accessor change (bk):
+    . arch/ia64/kernel/unaligned.c
+    . arch/sparc64/solaris/misc.c
+    . drivers/char/n_tty.c
+    . drivers/char/rocket.c
+    . drivers/char/tty_io.c
+    . drivers/char/vt.c
+    . drivers/char/vt_ioctl.c
+    . drivers/net/slip.c
+    . fs/binfmt_elf.c
+    . fs/compat_ioctl.c
+    . fs/dquot.c
+    . fs/exec.c
+    . fs/open.c
+    . fs/proc/array.c
+    . include/linux/sched.h
+    . kernel/acct.c
+    . kernel/exit.c
+    . kernel/fork.c
+    . kernel/pid.c
+    . kernel/signal.c
+    . kernel/sys.c
+    . net/ipv4/netfilter/ipt_owner.c
+    . net/ipv6/netfilter/ip6t_owner.c
+  * Export blk_queue_activity_fn for ide-probe in drivers/block/ll_rw_blk.c.
+    This change did not make it into the package (closes: #215223).
+  * Include mca-legacy.h for MCA_NOTFOUND in drivers/isdn/eicon/eicon_mod.c.
+  * Use gcc-2.95 compatible variadic macro in
+    drivers/media/video/saa7134/saa7134-core.c.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 12 Oct 2003 09:51:18 +1000
+
+kernel-source-2.6.0-test6 (2.6.0-test6-2) unstable; urgency=low
+
+  * Export blk_queue_activity_fn for ide-probe in drivers/block/ll_rw_blk.c.
+
+ -- Herbert Xu <herbert at debian.org>  Sat,  4 Oct 2003 13:45:40 +1000
+
+kernel-source-2.6.0-test6 (2.6.0-test6-1) unstable; urgency=low
+
+  * New upstream release (closes: #209307).
+  * Use mac_len for move ll headers:
+    . include/linux/skbuff.h
+    . net/core/dev.c
+    . net/ipv4/xfrm4_input.c
+    . net/ipv6/xfrm6_input.c
+  * Removed ACENIC/DGRS/DABUSB in arch/*/defconfig (closes: #211852).
+  * Fixed double request_region:
+    . drivers/net/arcnet/com20020.c
+    . drivers/net/arcnet/com20020-isa.c
+    . drivers/net/arcnet/com20020-pci.c
+  * Forbid unspecified tunnel mode SAs in net/xfrm/xfrm_policy.c.
+  * Removed duplicate policy checks for ipip tunnels:
+    . net/ipv4/ipip.c
+    . net/ipv4/xfrm4_tunnel.c
+  * Restored err_tty_modem label in drivers/isdn/i4l/isdn_common.c.
+  * Added probe declaration in drivers/net/wireless/arlan-main.c.
+  * Include linux/termios.h for TCGETS in fs/intermezzo/dir.c
+    (Kalle Olavi Niemitalo, closes: #208966).
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  3 Oct 2003 19:38:37 +1000
+
+kernel-source-2.6.0-test4 (2.6.0-test4-3) unstable; urgency=low
+
+  * Fixed fatal bug in xfrm ll header patch:
+    . net/ipv4/xfrm4_input.c
+    . net/ipv6/xfrm6_input.c
+
+ -- Herbert Xu <herbert at debian.org>  Thu,  4 Sep 2003 20:51:57 +1000
+
+kernel-source-2.6.0-test4 (2.6.0-test4-2) unstable; urgency=low
+
+  * Added MODULE_LICENSE to net/xfrm/xfrm_user.c.
+  * Export idedefault_driver in drivers/ide/ide-default.c.
+
+ -- Herbert Xu <herbert at debian.org>  Mon,  1 Sep 2003 21:16:07 +1000
+
+kernel-source-2.6.0-test4 (2.6.0-test4-1) unstable; urgency=low
+
+  * New upstream release (closes: #206656).
+  * Fixed ll header of tunnel packets:
+    . include/linux/skbuff.h
+    . net/ipv4/xfrm4_input.c
+    . net/ipv6/xfrm6_input.c
+  * Fixed gcc 3 declaration in drivers/net/sis190.c.
+  * Fixed synchronize_irq() call in drivers/net/sis190.c.
+  * Fixed freenet_devtypo in drivers/net/wan/cosa.c.
+  * Fixed device name setting in drivers/net/3c509.c.
+  * Removed release timer in sound/pcmcia/vx/vx_entry.c.
+  * Always define cmpxchg in include/asm-i386/system.h (closes: #206956).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 31 Aug 2003 13:41:55 +1000
+
+kernel-source-2.6.0-test2 (2.6.0-test2-1) unstable; urgency=low
+
+  * Cope with exit status 2 from md5sum in drivers/isdn/hisax/cert.c.
+  * Fixed binutils test in scripts/ver_linux.
+  * Wrapped long line in kernel-source description.
+  * Marked IDE PCI proc entries as __devinitdata (closes: #202412):
+    . drivers/ide/pci/*.h
+  * Fixed binutils version recommendation in arch/ppc/Makefile.
+  * Added per-SA ECN flag:
+    . include/linux/pfkeyv2.h
+    . include/linux/xfrm.h
+    . include/net/inet_ecn.h
+    . include/net/xfrm.h
+    . net/ipv4/ah4.c
+    . net/ipv4/esp4.c
+    . net/ipv4/ipcomp.c
+    . net/ipv4/xfrm4_input.c
+    . net/ipv6/ah6.c
+    . net/ipv6/esp6.c
+    . net/ipv6/ipcomp.c
+    . net/ipv6/xfrm6_input.c
+    . net/key/af_key.c
+    . net/xfrm/xfrm_user.c
+  * Fixed secpath xfrm state leak:
+    . include/net/xfrm.h
+    . net/ipv4/xfrm4_input.c
+    . net/ipv4/xfrm4_policy.c
+    . net/ipv6/xfrm6_input.c
+    . net/ipv6/xfrm6_policy.c
+    . net/netsyms.c
+    . net/xfrm/xfrm_input.c
+    . net/xfrm/xfrm_policy.c
+  * Fixed owner setting in drivers/net/arcnet/com20020-isa.c.
+  * Fixed module refcounting in drivers/net/pcmcia/com20020_cs.c.
+  * Fixed hdlc proto type:
+    . drivers/net/wan/dscc4.c
+    . drivers/net/wan/pc300_drv.c
+  * Use gcc-2.95 compatible variadic macro in drivers/net/wireless/wl3501_cs.c.
+  * Applied 486 emulation patch (Willy Tarreau):
+    . arch/i386/Kconfig
+    . arch/i386/kernel/Makefile
+    . arch/i386/kernel/emu.c
+    . arch/i386/kernel/entry.S
+
+ -- Herbert Xu <herbert at debian.org>  Thu, 31 Jul 2003 20:01:30 +1000
+
+kernel-source-2.6.0-test1 (2.6.0-test1-1) unstable; urgency=low
+
+  * New upstream release (closes: #194242, #199893).
+  * Fixed size of default_port in drivers/net/via-rhine.c.
+  * Added general notes from 2.4 README.Debian file.
+  * Removed cmd640 from drivers/ide/pci/Makefile (closes: #195286).
+  * Made MCA_53C9X depend on MCA_LEGACY in drivers/scsi/Kconfig.
+  * Setup two 1G mappings if cia_rev == 1 in arch/alpha/kernel/core_cia.c.
+  * Added inclusion of linux/stddef.h due to NULL in linux/timer.h.
+  * Fixed multiline string literals in drivers/net/wan/sdla_chdlc.c.
+  * Suggest libqt-dev in kernel-source package (closes: #196296).
+  * Fixed IDE PCI proc entries for modules in drivers/ide/ide-proc.c.
+  * Fixed assembly specification in drivers/net/wan/sbni.c.
+  * Enable hw_resend_irq if io_apic is on (ac):
+    . include/asm-i386/hw_irq.h
+    . arch/i386/kernel/io_apic.c
+  * Include linux/skbuff.h for skb_put in include/linux/netlink.h.
+  * Include linux/spinlock.h for rwlock_t in include/net/ip6_fib.h.
+  * Include linux/ipv6.h for inet6_sk in include/net/ip6_route.h.
+  * Include net/sock.h for struct sock in include/net/ip6_route.h.
+  * Include linux/netdevice.h for MAX_ADDR_LEN in include/net/neighbour.h.
+  * Added forward declaration for struct neighbour in include/net/neighbour.h.
+  * Include linux/types.h for __u32 in include/linux/watchdog.h.
+  * Added forward declaration for struct net_device in include/linux/skbuff.h.
+  * Wake up km_waitq after policy changes in net/xfrm/xfrm_policy.c.
+  * Restored mdio_sem that replaced rtnl_lock in drivers/net/8139too.c.
+  * Include linux/root_dev.h for ROOT_DEV in drivers/mtd/maps/uclinux.c.
+  * Removed bogus devfs references in Documentation/initrd.txt (Nikolaus Rath).
+  * Kill temp addresses and regen timer on shutdown in net/ipv6/addrconf.c.
+  * Fixed optional choice setting in scripts/kconfig/confdata.c.
+  * Made CONFIG_IDEDISK_STROKE a runtime option (Joerg Platte):
+    . include/linux/ide.h
+    . drivers/ide/ide.c
+    . drivers/ide/ide-disk.c
+  * Export blk_rq_prep_restart for ide-disk in drivers/block/ll_rw_blk.c.
+  * Fixed IDE modularisation:
+    . drivers/ide/Kconfig
+    . drivers/ide/Makefile
+    . drivers/ide/ide.c
+    . drivers/ide/ide-io.c
+    . drivers/ide/ide-pnp.c
+    . drivers/ide/ide-probe.c
+    . drivers/ide/pci/*
+    . drivers/ide/setup-pci.c
+    . include/linux/ide.h
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 15 Jul 2003 21:36:05 +1000
+
+kernel-source-2.5.69 (2.5.69-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Wed,  7 May 2003 20:54:36 +1000
+
+kernel-source-2.4.20 (2.4.20-6) unstable; urgency=low
+
+  * Documented mem= change in README.Debian.
+  * Fixed printk warnings in init/do_mounts.c.
+  * Fixed printk warnings in fs/fat/file.c (closes: #178355).
+  * Commented out non-TeX heading in Documentation/smp.tex (Daniel van Eeden,
+    closes: #174554).
+  * Fixed dupliate detection problem in drivers/net/tokenring/ibmtr.c
+    (closes: #178874).
+  * Close old_fd and root_fd in init/do_mounts.c (Brian May, closes: #180934).
+  * Ignore errors from tw_setfeature in drivers/scsi/3w-xxxx.c
+    (closes: #181581).
+  * Changed all occurances of infobox+sleep to msgbox in scripts/Menuconfig
+    (closes: #181640).
+  * Use rq->special instead of rq->buffer in drivers/scsi/ide-scsi.c
+    (closes: #180125).
+  * Fixed precedence bug in drivers/sound/trident.c (John Levon).
+  * Documented AMD 768 erratum (closes: #177139).
+  * Fixed initialisation error handling in drivers/block/cciss.c.
+  * Fixed initialisation error handling in drivers/block/cpqarray.c.
+  * Fixed ptrace security hole (closes: #185375).
+  * Work around broken Toshiba keyboards (2.4.21pre, closes: #121335).
+  * Fixed sock address length check (2.4.21pre, closes: #171983).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 22 Mar 2003 10:05:53 +1100
+
+kernel-source-2.4.20 (2.4.20-5) unstable; urgency=high
+
+  * Fixed ethernet packet padding information leak (2.4ac, see #176178):
+    . via-rhine
+  * Added sk_padto function (closes: #176487).
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 13 Jan 2003 19:17:48 +1100
+
+kernel-source-2.4.20 (2.4.20-4) unstable; urgency=high
+
+  * Added missing printk newlines in net/sched/sch_htb.c
+    (Alexandra N. Kossovsky, closes: #174152).
+  * Removed bogus VIA KT266 IO-APIC check.  It is a useful warning.
+  * Removed bogus ip_conntrack_{ftp,irc} check.
+  * Fixed a typo in Documentation/sound/Introduction (Daniel van Eeden,
+    closes: #174944).
+  * Reverted CONFIG_VIDEO_VESA change (closes: #175614).
+  * Fixed ethernet packet padding information leak (2.4ac, see #176178):
+    . 3c501
+    . 3c505
+    . 3c507
+    . 3c523
+    . 3c527
+    . 7990
+    . 8139too
+    . 82596
+    . 8390
+    . a2065
+    . am79c961a
+    . ariadne
+    . at1700
+    . atarilance
+    . atp
+    . bagetlance
+    . de600
+    . de620
+    . declance
+    . depca
+    . eepro
+    . eexpress
+    . epic100
+    . eth16i
+    . fmv18x
+    . hp100
+    . lance
+    . lasi_82596
+    . lp486e
+    . ni5010
+    . ni52
+    . ni65
+    . axnet_cs
+    . fmvj18x_cs
+    . ray_cs
+    . xirc2ps_cs
+    . xircom_tulip_cb
+    . seeq8005
+    . sgiseeq
+    . sk_g16
+    . smc9194
+    . sun3_82586
+    . sun3lance
+    . wavelan
+    . yellowfin
+    . znet
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 11 Jan 2003 17:31:43 +1100
+
+kernel-source-2.4.20 (2.4.20-3) unstable; urgency=low
+
+  * Fixed ext3 remount deadlock added in 2.4.20-2 (Andrew Morton).
+  * Fixed ext3 use-after-free bug (Andrew Morton).
+  * Fixed i845G AGP Gart initialisation (Michael Milligan, closes: #172724).
+  * Updated i810_audio driver (2.4.21pre1, closes: #172194).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 21 Dec 2002 13:49:15 +1100
+
+kernel-source-2.4.20 (2.4.20-2) unstable; urgency=low
+
+  * Include acpidrv.o in the kernel (Mario Holbe, closes: #168439).
+  * Removed CONFIG_INET_ECN_DISABLED option.
+  * Removed CONFIG_INET_ECN check in net/ipv4/tcp_diag.c.
+  * Fixed stxncpy on alpha (2.4.21pre).
+  * Fixed ext3 data=journal umount problem (2.4.21pre1, closes: #171632).
+  * Added dependency on MTD_CONCAT for sc520cdp (closes: #173045).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 15 Dec 2002 14:53:05 +1100
+
+kernel-source-2.4.20 (2.4.20-1) unstable; urgency=low
+
+  * New upstream release (closes: #164065, #164204, #165478, #166312, #168141,
+    #168190, #170962).
+  * Disable CONFIG_VIDEO_VESA unless VESA FB support is turned on.
+  * Mention Debian changes in kernel-source package description.
+  * Fixed a bug where ACPI is always compiled as a module (closes: #168439).
+  * CONFIG_VIDEO_SELECT is always on again.
+  * Modularised VESA FB.
+  * Added coreutils as an alternative to fileutils (closes: #170459).
+  * Replaced BUG() with printk() in fs/fat/file.c (closes: #168886).
+  * Fixed circular dependency in include/linux/netfilter_ipv4/ip_conntrack.h.
+  * Do not get seqno if we will not use it in fs/isofs/inode.c.
+  * Fixed HID name fix so that produce id is actually read.
+  * Added missing semicolons in drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
+    (Michael Osamu Shiobara, closes: #165375).
+  * Made CONFIG_PARIDE_EPATC8 into a runtime option.
+  * Fixed double PCI unregistration in drivers/char/joystick/pcigame.c.
+  * Include linux/init.h in drivers/char/amd76x_pm.c.
+  * Include linux/init.h in drivers/scsi/cpqfcTSinit.c.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 30 Nov 2002 16:39:30 +1100
+
+kernel-source-2.4.19 (2.4.19-5) unstable; urgency=high
+
+  * Fixed i386 lcall DoS (Petr Vandrovec).
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 18 Nov 2002 21:22:02 +1100
+
+kernel-source-2.4.19 (2.4.19-4) unstable; urgency=low
+
+  * Added missing headers in drivers/isdn/hisax/avma1_cs.c.
+  * Added missing headers in drivers/net/wan/comx-hw-munich.c.
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 16 Oct 2002 22:42:01 +1000
+
+kernel-source-2.4.19 (2.4.19-3) unstable; urgency=low
+
+  * Fixed more ACPI module building problems.
+  * Fixed initialisation oops in drivers/scsi/aic7xxx/aic7770.c
+    (closes: #162347).
+  * Made CONFIG_VIDEO_SELECT conditional in drivers/video.
+
+ -- Herbert Xu <herbert at debian.org>  Sun,  6 Oct 2002 16:33:04 +1000
+
+kernel-source-2.4.19 (2.4.19-2) unstable; urgency=low
+
+  * Inlucde pagemap.h for unlock_page in drivers/char/drm/i810_dma.c
+    (closes: #144971).
+  * Set ?time to zero in fs/cramfs/inode.c.
+  * Allow ACPI to be compiled as a module.
+  * Fixed umsdos_solve_hlink oops in fs/umsdos/dir.c (closes: #159772).
+  * Honour ide?=dma in drivers/ide/via82cxxx.c (Arne Nordmark,
+    closes: #157925).
+  * Restored priority of invalidate messages in fs/buffer.c.  The submitter of
+    #131419 did a badblocks -f.
+  * Wait before flushing in drivers/char/drm/mga_dma.c (ac, closes: #161100).
+  * Applied SCSI Media Changer patch (closes: #144850).
+  * Applied Big Physical Area Reservation patch (closes: #144849).
+  * Removed period check for executables in fs/isofs/inode.c (closes: #162190).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 28 Sep 2002 16:53:27 +1000
+
+kernel-source-2.4.19 (2.4.19-1) unstable; urgency=low
+
+  * New upstream release (closes: #139617, #146349).
+  * ip_nat_{ftp,irc} cannot be m if ip_conntrack_{ftp,irc} is y, respectively
+    (closes: #142532).
+  * Removed volume checks in fs/isofs/inode.c (closes: #138384).
+  * Removed gsem from drivers/usb/pegasus.c.
+  * Always call complete after unlinking an urb in drivers/usb/usb-ohci.c.
+  * Set hardsect size to 512 in drivers/scsi/sr.c (closes: #154510).
+  * Removed non-free firmware and disabled their drivers (closes: #150052):
+   . SMC Token Ring
+   . ACENIC
+   . DGRS
+   . DABUSB
+  * Lowed invalidate messages to priority DEBUG in fs/buffer.c
+    (closes: #131349).
+
+ -- Herbert Xu <herbert at debian.org>  Wed,  7 Aug 2002 21:12:03 +1000
+
+kernel-source-2.4.18 (2.4.18-5) unstable; urgency=low
+
+  * Corrected AdvWriteDWordLramNoSwap in drivers/scsi/advansys.c
+    (Jerome L. Quinn, closes: #128080).
+  * Added check for VIA KT266 IO-APIC, version == 2 (closes: #136163).
+  * Updated pegasus driver (2.4.19pre6).
+  * Added ATARAID device names to main.c (Eduard Bloch, closes: #139604).
+  * Updated uhci driver (Johannes Erdfelt, closes: #135785).
+  * Translate slashes in broken Acorn ISO9660 file systems (Darren Salt,
+    closes: #141660).
+  * Added newline to printk in drivers/sound/i810_audio.c
+    (handler-case at gmx.net, closes: #142214).
+  * Updated parport driver (2.4.19pre6).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 13 Apr 2002 22:07:22 +1000
+
+kernel-source-2.4.18 (2.4.18-4) unstable; urgency=high
+
+  * Fixed remaining double free in
+     drivers/net/zlib.c
+     fs/jffs2/zlib.c
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 20 Mar 2002 20:02:18 +1100
+
+kernel-source-2.4.18 (2.4.18-3) unstable; urgency=high
+
+  * Fixed double free in
+     drivers/net/zlib.c
+     fs/jffs2/zlib.c
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 13 Mar 2002 20:24:09 +1100
+
+kernel-source-2.4.18 (2.4.18-2) unstable; urgency=low
+
+  * Removed -g from driviers/atm/Makefile.
+  * Added missing personality patch to fs/binfmt_elf.c.
+  * Export est_cycle_freq (needed for removing CONFIG_FT_ALPHA_CLOCK).
+  * Extern inline -> static inline in
+     drivers/char/specialx.c
+     drivers/net/hamradio/soundmodem
+  * Added asm/io.h for in*/out* to
+     drivers/isdn/hisax/hisax_fcpcipnp.c
+     drivers/net/wan/farsync.c
+
+ -- Herbert Xu <herbert at debian.org>  Wed,  6 Mar 2002 19:53:30 +1100
+
+kernel-source-2.4.18 (2.4.18-1) unstable; urgency=low
+
+  * New upstream release (closes: #126391, #135156).
+  * Reverted tulip BMCR_FULLDPLX patch.
+  * Moved mkcramfs to the cramfs source package.
+  * CONFIG_SERIAL_ACPI now depends on CONFIG_SERIAL == y (closes: #132038).
+  * Fixed negative inodes in /proc/net (Arnaud Giersch, closes: #134704).
+  * pcnet32_purge_tx_ring may be called from IRQ context (Darren Salt,
+    closes: #134930).
+  * Check old_bbpnt in drivers/scsi/sr.c (2.5).
+  * Removed CONFIG_FT_ALPHA_CLOCK.
+  * Fixed the use of return values from mem*_io in drivers/isdn/sc.
+  * Added missing headers in drivers/pcmcia/i82092.c.
+  * Fixed compile error in drivers/scsi/dpt_i2o.c on alpha.
+
+ -- Herbert Xu <herbert at debian.org>  Thu, 28 Feb 2002 19:40:29 +1100
+
+kernel-source-2.4.17 (2.4.17-1) unstable; urgency=low
+
+  * New upstream release (closes: #122168, #123471).
+  * Only set startup to 0 for 21143 (rev 65) in tulip.
+  * Don't clear BMCR_FULLDPLX bit in tulip_find_mii as it breaks some cards
+    (closes: #100624).
+  * Fixed atyfb compilation problem (Tobias Ringstrom).
+  * Removed obsolete vfat patch.
+  * Fixed double cache allocation in mount_devfs_fs.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 22 Dec 2001 13:41:46 +1100
+
+kernel-source-2.4.16 (2.4.16-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 28 Nov 2001 07:30:44 +1100
+
+kernel-source-2.4.15 (2.4.15-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 24 Nov 2001 13:34:51 +1100
+
+kernel-source-2.4.14 (2.4.14-1) unstable; urgency=low
+
+  * New upstream release (closes: #117368, #118111).
+  * Made mkcramfs more verbose about write errors.
+  * Fixed compilation problem in loopback driver.
+  * Fixed compilation problem in ps2esdi.c.
+  * Fixed compilation problem in i2c-core.c.
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  9 Nov 2001 20:15:49 +1100
+
+kernel-source-2.4.13 (2.4.13-1) unstable; urgency=low
+
+  * New upstream release.
+  * Updated kernel-source suggests (closes: #115716).
+  * Added support for nm256xl+ (Mattia Monga, closes: #116378).
+  * Fixed comment about epochs in arch/alpha/kernel/time.c.
+  * Fixed symlink size bug on tmpfs.
+  * Fixed handling of HIDs with product strings bug no manufacturer.
+  * Work around tmpfs symlink size bug in mkcramfs.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 27 Oct 2001 17:39:07 +1000
+
+kernel-source-2.4.12 (2.4.12-1) unstable; urgency=low
+
+  * New upstream release.
+  * Fixed typo in debian/rules (closes: #114065).
+  * Fixed ECN compilation problem (closes: #114192).
+  * Fixed typo in Documentation/sound/OPL3-SA
+    (Marius Gedminas, closes: #114760).
+  * Fixed typo in drivers/parport/ieee1284_ops.c (Tim Waugh).
+  * Don't kill page cache entries in set_blocksize.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 13 Oct 2001 11:41:03 +1000
+
+kernel-source-2.4.10 (2.4.10-1) unstable; urgency=low
+
+  * New upstream release.
+  * Added support for EPAT C7/C8 chips.
+  * Fixed dead lock on shutdown in 8139too (closes: #107779).
+  * Removed const from drivers/net/irda/smc-ircc.c
+    (Keith Owens, closes: #110193).
+  * Allow ECN to be compiled in but disabled.
+  * Removed non-free Keyspan firmware.  We're no longer pristine.
+  * Fixed list_del bug in usb-uhci (ac patches).
+  * Fixed apm argument processing (ac patches).
+  * Added ioctl defines for cpq (ac patches).
+  * Included linux/init.h in drivers/net/aironet4500_card.c.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 29 Sep 2001 16:05:20 +1000
+
+kernel-source-2.4.9 (2.4.9-1) unstable; urgency=low
+
+  * New upstream release (closes: #63393).
+  * Fixed highmem CramFS bug (closes: #108893).
+  * Added missing include in fs/ntfs/unistr.c.
+  * Reverted startup==1 patch from drivers/net/tulip/21142.c.
+  * Fixed obsolete use of min: drivers/net/rrunner.c.
+  * Exported snprintf/vsnprintf (ac patches).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 18 Aug 2001 21:23:07 +1000
+
+kernel-source-2.4.8 (2.4.8-1) unstable; urgency=low
+
+  * New upstream release.
+  * Menuconfig now exits with 1 if screen is too small (closes: #106510).
+  * Applied NFS client seekdir patch (closes: #63063, #107045).
+  * Build-depend on kernel-package >= 7.48 (closes: #107545).
+  * Applied emu10k fixes (ac patches).
+  * Fixed ldm macros (ac patches).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 12 Aug 2001 09:04:44 +1000
+
+kernel-source-2.4.7 (2.4.7-1) unstable; urgency=low
+
+  * New upstream release (closes: #97516, #104141, #104267).
+  * Applied ReiserFS umount patch (closes: #100740).
+  * Applied DAC960 completion patch (Jens Axboe).
+  * Restricted CONFIG_FB_PVR2 to SH (ac patches).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 22 Jul 2001 11:52:29 +1000
+
+kernel-source-2.4.6 (2.4.6-1) unstable; urgency=low
+
+  * New upstream release (closes: #102864).
+  * Fixed pegasus_set_multicast lockup.
+  * Reverted sysinfo patch.
+
+ -- Herbert Xu <herbert at debian.org>  Thu,  5 Jul 2001 19:24:12 +1000
+
+kernel-source-2.4.5 (2.4.5-1) unstable; urgency=low
+
+  * New upstream release (closes: #78761, #96443).
+  * Fixed set_blocksize() on RAMDISKs.
+  * Removed flavour patch from Makefile as it is now obsolete.
+  * Fixed typo in drivers/usb/ov511.c (ac patches).
+  * Fixed race in fs/super.c (Alexander Viro).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 27 May 2001 10:25:42 +1000
+
+kernel-source-2.4.4 (2.4.4-2) unstable; urgency=low
+
+  * Hacked ide_xlate_1024 to work when IDE is modularised (closes: #94853).
+  * Fixed typo in pci2220i.c (ac patches).
+  * Treat files that begin with FD_FILL_BYTE correctly in vfat
+    (closes: #75413).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 13 May 2001 09:33:09 +1000
+
+kernel-source-2.4.4 (2.4.4-1) unstable; urgency=low
+
+  * New upstream release.
+  * Fixed a typo in Documentation/sound/OPL3-SA (Carlos Valdivia Yague,
+    closes: #95255).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 29 Apr 2001 10:32:51 +1000
+
+kernel-source-2.4.3 (2.4.3-4) unstable; urgency=low
+
+  * ip_conntrack_ftp fix (netfilter, closes: #94216).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 22 Apr 2001 11:15:02 +1000
+
+kernel-source-2.4.3 (2.4.3-3) unstable; urgency=low
+
+  * Added missing SIEMENS PCI ID (ac patches).
+  * Exported proc_get_inode (ac patches).
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 16 Apr 2001 08:42:17 +1000
+
+kernel-source-2.4.3 (2.4.3-2) unstable; urgency=low
+
+  * Correct devfs path name in scsi-generic.txt (closes: #93405).
+  * Fixed negative padding in struct sysinfo.
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 13 Apr 2001 19:42:42 +1000
+
+kernel-source-2.4.3 (2.4.3-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Sun,  8 Apr 2001 16:50:40 +1000
+
+kernel-source-2.4.2 (2.4.2-3) unstable; urgency=low
+
+  * Added build-time dependency on libz-dev (closes: #89722).
+  * Compilation fixes in 6pack.c and genhd.h (closes: #90646).
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 23 Mar 2001 20:30:03 +1100
+
+kernel-source-2.4.2 (2.4.2-2) unstable; urgency=low
+
+  * Added initrd support for cramfs.
+  * Fixed bug that prevented initrd from being freed (ac patches).
+  * Fixed a typo in Documentation/sound/VIBRA16 (Carlos Valdivia,
+    closes: #88018).
+  * Removed misleading securetty note in devfs README files (closes: #89148).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 11 Mar 2001 08:56:27 +1100
+
+kernel-source-2.4.2 (2.4.2-1) unstable; urgency=low
+
+  * New upstream release.
+  * Created mkcramfs package.
+  * Accomodate option change in binutils (closes: #87009).
+  * Applied loopback patch by Jens Axobe.
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 23 Feb 2001 20:19:31 +1100
+
+kernel-source-2.4.1 (2.4.1-3) unstable; urgency=low
+
+  * Applied tmpfs patch by Christoph Rohland.
+  * Fixed incorrect conditional check in struct sysinfo (closes: #85603).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 11 Feb 2001 21:08:05 +1100
+
+kernel-source-2.4.1 (2.4.1-2) unstable; urgency=low
+
+  * Fixed the struct sysinfo warning properly (closes: #84234).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 10 Feb 2001 23:10:44 +1100
+
+kernel-source-2.4.1 (2.4.1-1) unstable; urgency=low
+
+  * New upstream release.
+  * Added support for flavours to Makefile.
+  * Only include asm/bitops.h if __KERNEL__ is defined in linux/fs.h
+    (closes: #84238).
+  * Added padding to struct sysinfo so that it's identical to 2.2 (#84234).
+  * Fixed typos in asm/socket.h (closes: #39168).
+  * Updated IrDA URL in asm/termios.h (closes: #42222).
+
+ -- Herbert Xu <herbert at debian.org>  Sun,  4 Feb 2001 10:11:47 +1100
+
+kernel-source-2.4.0 (2.4.0-1) unstable; urgency=low
+
+  * New upstream release (closes: #71874, #79490).
+  * Added missing build-time dependencies (closes: #81728).
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 16 Jan 2001 11:14:16 +1100
+
+kernel-source-2.4.0-test11 (2.4.0-test11-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Sat,  9 Dec 2000 11:34:37 +1100
+
+kernel-source-2.4.0-test5 (2.4.0-test5-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 29 Jul 2000 17:55:37 +1000
+
+kernel-source-2.4.0-test4 (2.4.0-test4-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 19 Jul 2000 18:37:17 +1000
+
+kernel-source-2.4.0-test3 (2.4.0-test3-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 12 Jul 2000 09:49:57 +1000
+
+kernel-source-2.4.0-test2 (2.4.0-test2-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 10 Jul 2000 19:24:59 +1000
+
+kernel-source-2.2.17 (2.2.17pre6-1) frozen unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 24 Jun 2000 21:53:40 +1000
+
+kernel-source-2.2.16 (2.2.16-1) frozen unstable; urgency=high
+
+  * New upstream release (closes: #65745).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 18 Jun 2000 12:42:37 +1000
+
+kernel-source-2.2.15 (1:2.2.15-3) frozen unstable; urgency=low
+
+  * Bring capabilities closer to POSIX spec (Andrew Morgan)
+    | Note. This subtly changes cap_bset behaviour.
+
+ -- Herbert Xu <herbert at debian.org>  Thu,  1 Jun 2000 09:32:11 +1000
+
+kernel-source-2.2.15 (1:2.2.15-2) frozen unstable; urgency=low
+
+  * AIC7XXX 5.1.29 (closes: #63946).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 13 May 2000 09:29:50 +1000
+
+kernel-source-2.2.15 (1:2.2.15-1) frozen unstable; urgency=low
+
+  * New upstream release (closes: #63675).
+  * Built with kernel-package 7.04.potato.1 (closes: #63290).
+
+ -- Herbert Xu <herbert at debian.org>  Tue,  9 May 2000 12:54:09 +1000
+
+kernel-source-2.2.15pre19 (2.2.15pre19-2) frozen unstable; urgency=low
+
+  * New upstream release (pre20).
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 25 Apr 2000 15:31:03 +1000
+
+kernel-source-2.2.15pre19 (2.2.15pre19-1) frozen unstable; urgency=low
+
+  * New upstream release (closes: #55383).
+  * Applied patch from Chris Evans.
+  * Applied patch from David Miller.
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 21 Apr 2000 12:15:30 +1000
+
+kernel-source-2.2.14 (2.2.14-5) frozen unstable; urgency=low
+
+  * Delete my copy of the control file before calling make-kpkg
+    (closes: #62269).
+
+ -- Herbert Xu <herbert at debian.org>  Thu, 13 Apr 2000 08:33:18 +1000
+
+kernel-source-2.2.14 (2.2.14-4) frozen unstable; urgency=medium
+
+  * Applied patch from Alexey Kuznetsov that fixes the AF_UNIX socket crash
+    (closes: #61335).
+  * Rebuilt with new kernel-package (closes: #61261).
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 31 Mar 2000 14:12:43 +1000
+
+kernel-source-2.2.14 (2.2.14-3) frozen unstable; urgency=low
+
+  * Rebuilt with new kernel-package (closes: #60001).
+  * Included a patch from Eric Delaunay <delaunay at lix.polytechnique.fr> that
+    fixes a couple of argument parsing bugs in main.c (closes: #58566).
+
+ -- Herbert Xu <herbert at debian.org>  Thu, 23 Mar 2000 19:05:11 +1100
+
+kernel-source-2.2.14 (2.2.14-2) unstable; urgency=low
+
+  * Fixed incorrect assembly code for i386.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 16 Jan 2000 12:36:59 +1100
+
+kernel-source-2.2.14 (2.2.14-1) unstable; urgency=low
+
+  * New upstream release.
+  * Fixed a typo in aha152x.c (closes: #12636).
+
+ -- Herbert Xu <herbert at debian.org>  Thu, 13 Jan 2000 12:09:06 +1100
+
+kernel-source-2.2.13 (2.2.13-2) unstable; urgency=low
+
+  * Updated version number in README.Debian (closes: #49033).
+  * Removed kernel-image as it will be generated by the kernel-image source
+    package.
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 19 Nov 1999 19:41:45 +1100
+
+kernel-source-2.2.13 (2.2.13-1) unstable; urgency=low
+
+  * New upstream release.
+  * Enabled ServeRAID (closes: #47653).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 24 Oct 1999 14:22:49 +1000
+
+kernel-source-2.2.12 (2.2.12-4) unstable; urgency=low
+
+  * Fixed a typo in tgafb.c.
+  * Added CONFIG_APM_DISABLE_BY_DEFAULT.
+  * Call make-kpkg to clean up (closes: #45603).
+
+ -- Herbert Xu <herbert at debian.org>  Thu, 14 Oct 1999 09:06:57 +1000
+
+kernel-source-2.2.12 (2.2.12-3) unstable; urgency=low
+
+  * Compiled with stacks aligned on dwords.
+  * Enabled serial consoles (closes: #46152).
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 28 Sep 1999 17:39:34 +1000
+
+kernel-source-2.2.12 (2.2.12-2) unstable; urgency=low
+
+  * Rewrote the kmod patch to only bail out when the other side is our parent.
+  * Use the VFS patch rather than the autofs patch.
+  * Enabled Joliet extensions (fixes #42006).
+  * Enabled APM (fixes #42258).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 11 Sep 1999 23:51:00 +1000
+
+kernel-source-2.2.12 (2.2.12-1) unstable; urgency=low
+
+  * New upstream release (fixes #43865).
+  * Fixed an nlink update problem in nfs.
+  * New rules file from Hartmut Koptein.
+  * Fixed an overflow bug in the stallion driver.
+  * Fixed an autofs deadlock.
+  * Don't load a module that we're already trying to load (Chris Butler) (fixes
+    #39910).
+
+ -- Herbert Xu <herbert at debian.org>  Wed,  1 Sep 1999 09:12:15 +1000
+
+kernel-source-2.2.10 (2.2.10-1) unstable; urgency=low
+
+  * New upsream release.
+  * Moved default.config to new kernel-patch for i386.
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 15 Jun 1999 21:59:48 +1000
+
+kernel-source-2.2.9 (2.2.9-2) unstable; urgency=high
+
+  * Fixed a network DoS attack.
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  4 Jun 1999 21:06:28 +1000
+
+kernel-source-2.2.9 (2.2.9-1) unstable; urgency=low
+
+  * New upstream relesae.
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 18 May 1999 10:20:08 +1000
+
+kernel-source-2.2.7 (2.2.7-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  7 May 1999 22:19:56 +1000
+
+kernel-source-2.2.5 (1:2.2.5-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 16 Apr 1999 13:56:45 +1000
+
+kernel-source-2.0.36 (2.0.36-3) frozen unstable; urgency=low
+
+  * Upgraded AIC7XXX to 5.1.11 which should make some owners of Adaptec cards
+    able to install Debian.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 21 Feb 1999 14:56:42 +1100
+
+kernel-source-2.0.36 (2.0.36-2) frozen unstable; urgency=low
+
+  * Applied ISDN patch from Paul Slootman that enables idle timeouts in the
+    manual dialmode and allows callback syncPPP connections to be made
+    (fixes #31516).
+  * Enlarged kernel message buffer so that all messages are caught by klogd.
+  * Included module for TLAN based network cards (fixes #31623).
+  * Include EtherExpressPro and FMV0181/182/183/184 as modules.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 16 Jan 1999 16:39:01 +1100
+
+kernel-source-2.0.36 (2.0.36-1) unstable; urgency=low
+
+  * New upstream release.
+  * Enabled ETH16I.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 28 Nov 1998 17:40:21 +1100
+
+kernel-source-2.0.35 (2.0.35-3) frozen; urgency=low
+
+  * Upgraded to aic7xxx 5.1.4 (fixes #29480, #27859, #28946).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 22 Nov 1998 15:41:44 +1100
+
+kernel-source-2.0.35 (2.0.35-2) unstable; urgency=low
+
+  * Upgraded to aic7xxx 5.1.0.
+  * Removed spurious definition in 3c523.c (fixes #25370).
+  * Built with kernel-package 5.11 (fixes #25623).
+  * Enabled autofs (fixes #22338, #27860).
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 24 Oct 1998 17:32:06 +1000
+
+kernel-source-2.0.35 (2.0.35-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 19 Jul 1998 08:59:44 +1000
+
+kernel-source-2.0.34 (2.0.34-4) frozen unstable; urgency=high
+
+  * Updated to aic7xxx 5.0.19 (fixes #24252).
+
+ -- Herbert Xu <herbert at debian.org>  Wed,  8 Jul 1998 20:06:08 +1000
+
+kernel-source-2.0.34 (2.0.34-3) frozen unstable; urgency=high
+
+  * Reversed euid test in fs/fcntl.c.
+
+ -- Herbert Xu <herbert at debian.org>  Tue, 30 Jun 1998 16:27:49 +1000
+
+kernel-source-2.0.34 (2.0.34-2) frozen unstable; urgency=low
+
+  * Upload to hamm as well.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 21 Jun 1998 16:48:13 +1000
+
+kernel-source-2.0.34 (2.0.34-1) unstable; urgency=low
+
+  * New upstream release (fixes #17651, #18788, #21231, #22330).
+
+ -- Herbert Xu <herbert at debian.org>  Sun,  7 Jun 1998 12:29:27 +1000
+
+kernel-source-2.0.33 (2.0.33-9) frozen unstable; urgency=low
+
+  * Disabled certain MCA NIC drivers (fixes #22254).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 10 May 1998 15:59:32 +1000
+
+kernel-source-2.0.33 (2.0.33-8) frozen unstable; urgency=low
+
+  * Disabled experimental drivers.
+  * Reapplied joliet patch (fixes #19160, #21537).
+  * Built with kernel-package 4.07 (fixes #21229).
+  * Replaced NO_PCI with !CONFIG_PCI in 3c59x.c (fixes #21916).
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  1 May 1998 18:29:03 +1000
+
+kernel-source-2.0.33 (2.0.33-7) frozen unstable; urgency=high
+
+  * Applied IP fragmentation patch from Alan Cox.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 18 Apr 1998 12:57:56 +1000
+
+kernel-source-2.0.33 (2.0.33-6) frozen unstable; urgency=low
+
+  * Disabled scc since we don't support ax25 by default (fixes #20307).
+
+ -- Herbert Xu <herbert at debian.org>  Wed,  1 Apr 1998 19:21:05 +1000
+
+kernel-source-2.0.33 (2.0.33-5) unstable; urgency=low
+
+  * Turned rst cookies off.
+
+ -- Herbert Xu <herbert at debian.org>  Wed, 18 Mar 1998 20:41:27 +1100
+
+kernel-source-2.0.33 (2.0.33-4) unstable; urgency=low
+
+  * Applied patch from Paul Slootman (fixes #18787).
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  6 Mar 1998 11:30:44 +1100
+
+kernel-source-2.0.33 (2.0.33-3) stable unstable; urgency=low
+
+  * Built with new kernel-package (3.61).
+  * Added support for fat32 (fixes #14042).
+
+ -- Herbert Xu <herbert at debian.org>  Fri, 20 Feb 1998 16:33:40 +1100
+
+kernel-source-2.0.33 (2.0.33-2) stable unstable; urgency=low
+
+  * built with new kernel-package (3.57)
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 16 Feb 1998 08:59:11 +1100
+
+kernel-source-2.0.33 (2.0.33-1) stable unstable; urgency=high
+
+  * New upstream release (fixes #15736).
+
+ -- Herbert Xu <herbert at debian.org>  Sat,  7 Feb 1998 15:06:57 +1100
+
+kernel-source-2.0.32 (2.0.32-3) stable unstable; urgency=low
+
+  * Built with new kernel-package (3.49).
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 15 Dec 1997 12:22:45 +1100
+
+kernel-source-2.0.32 (2.0.32-2) stable unstable; urgency=low
+
+  * Removed teles driver which was accidentally left in.
+  * Applied patch from Andreas Jaeger.
+  * Built with new kernel-package (3.48) for use by libc6.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 14 Dec 1997 09:29:26 +1100
+
+kernel-source-2.0.32 (2.0.32-1) unstable; urgency=low
+
+  * New upstream release.
+  * Pristine source.
+  * Bugs fixed (#6132, #6133, #8647, #11823, #13705).
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 23 Nov 1997 18:34:38 +1100
+
+kernel-source-2.0.29 (1:2.0.29-10) unstable; urgency=low
+
+  * NCR53C8XX driver updates.
+  * Installed 3c59x 0.46C (#10902).
+  * Modified scc.c to compile with libc6 (#14367).
+
+ -- Herbert Xu <herbert at debian.org>  Mon, 17 Nov 1997 20:46:57 +1100
+
+kernel-source-2.0.29 (1:2.0.29-9) unstable; urgency=low
+
+  * Slight mod to pci.c to ignore bridges that the kernel can't handle (#11865).
+  * Removed sound module support.
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  3 Oct 1997 11:17:02 +1000
+
+kernel-source-2.0.29 (1:2.0.29-8) unstable; urgency=low
+
+  * Used epoch numbers to deal with old kernel-source releases.
+  * Enabled support for NCPFS.
+  * Added sound support.
+  * Enabled IP firewalls, forwarding, and aliasing.
+  * Applied ne2000 patch from Paul Gortmaker.
+
+ -- Herbert Xu <herbert at debian.org>  Fri,  4 Jul 1997 22:01:16 +1000
+
+kernel-source-2.0.29 (2.0.29-7) frozen unstable; urgency=high
+
+  * Applied security patch from Alan Cox.
+  * Applied patch from Andreas Jellinghaus.
+
+ -- Herbert Xu <herbert at debian.org>  Sat, 31 May 1997 11:59:56 +1000
+
+kernel-source-2.0.29 (2.0.29-6) frozen unstable; urgency=medium
+
+  * Merged Debian changes from 2.0.30.
+
+ -- Herbert Xu <herbert at debian.org>  Sun, 25 May 1997 22:26:30 +1000
+

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/compat
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/compat	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/compat	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1 @@
+4

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/control
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/control	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/control	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,76 @@
+Source: kernel-source-2.6.9
+Section: devel
+Priority: optional
+Maintainer: Debian kernel team <debian-kernel at lists.debian.org>
+Uploaders: William Lee Irwin III <wli at debian.org>, Jens Schmalzing <jensen at debian.org>, Sven Luther <luther at debian.org>, Andres Salomon <dilinger at voxel.net>, Joshua Kwan <joshk at triplehelix.org>, Simon Horman <horms at debian.org>
+Standards-Version: 3.6.1
+Build-Depends-Indep: bzip2, debhelper (>= 4), docbook-utils, gs, kernel-package (>= 7.48), transfig
+
+Package: kernel-source-2.6.9
+Architecture: all
+Section: devel
+Priority: optional
+Provides: kernel-source, kernel-source-2.6
+Depends: binutils, bzip2, coreutils | fileutils (>= 4.0)
+Recommends: libc6-dev | libc-dev, gcc, make
+Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-mt-dev
+Description: Linux kernel source for version 2.6.9 with Debian patches
+ This package provides the source code for the Linux kernel version 2.6.9.
+ .
+ You may configure the kernel to your setup by typing "make config"
+ and following instructions, but you could get ncursesX.X-dev and try
+ "make menuconfig" for a jazzier, and easier to use interface. There 
+ are options to use QT or GNOME based configuration interfaces, but they
+ need additional packages to be installed. Also, please read the detailed 
+ documentation in the file
+ /usr/share/doc/kernel-source-2.6.9/README.headers.gz.
+ .
+ If you wish to use this package to create a custom Linux kernel, then
+ it is suggested that you investigate the package kernel-package,
+ which has been designed to ease the task of creating kernel image
+ packages. 
+
+Package: kernel-doc-2.6.9
+Architecture: all
+Section: doc
+Priority: optional
+Provides: kernel-doc-2.6
+Depends: coreutils | fileutils (>= 4.0)
+Description: Linux kernel specific documentation for version 2.6.9
+ This package provides the various readme's in the 2.6.9 kernel
+ Documentation/ subdirectory: these typically contain kernel-specific
+ installation notes for some drivers for example. See
+ /usr/share/doc/kernel-doc-X.X.XX/Documentation/00-INDEX for a list of what
+ is contained in each file.  Please read the Changes file, as it
+ contains information about the problems, which may result by
+ upgrading your kernel.
+
+Package: kernel-patch-debian-2.6.9
+Architecture: all
+Section: devel
+Priority: optional
+Depends: bzip2
+Suggests: kernel-source-2.6.9
+Description: Debian patches to Linux 2.6.9
+ This package includes the patches used to produce the prepackaged
+ kernel-source-2.6.9 package.  Note that these patches do NOT apply
+ against a pristine Linux 2.6.9 kernel but only against
+ kernel-source-2.6.9_2.6.9.orig.tar.gz from the Debian archive.
+
+Package: kernel-tree-2.6.9
+Architecture: all
+Section: devel
+Priority: optional
+Depends: kernel-patch-debian-2.6.9 (= ${Source-Version}), ${kt-depends}
+Provides: ${kt-provides}
+Description: Linux kernel tree for building prepackaged Debian kernel images
+ This meta package is used as a build-time dependency of prepackaged
+ Debian kernel-image packages.  Its dependencies are structured so that a
+ complete kernel tree with Debian patches applied will be available after
+ this package is installed.  It also contains the upstream changelog file.
+ .
+ For those intending to use this package as a build-time dependency, this
+ package provides a list of virtual packages that guarantees the availability
+ of a particular Debian revision of the kernel tree.  The
+ kernel-image-2.6.9-i386 package is an example of this.
+

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/copyright
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/copyright	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/copyright	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,36 @@
+This is the Debian GNU/Linux prepackaged version of the Linux kernel.
+Linux was written by Linus Torvalds <Linus.Torvalds at cs.Helsinki.FI>
+and others.
+
+This package was put together by Simon Shapiro <Shimon at i-Connect.Net>, from
+sources retrieved from directories under
+ftp.cs.helsinki.fi:/pub/Software/Linux/Kernel/
+The sources may be found at most Linux ftp sites, including 
+ftp://ftp.kernel.org/pub/linux/kernel/
+
+This package was then maintained by Sven Rudolph.
+
+This package was maintained by Herbert Xu <herbert at debian.org>
+from March 1997 to May 2004.
+
+This package is currently maintained by the
+Debian Kernel Team <debian-kernel at lists.debian.org>
+
+Linux is copyrighted by Linus Torvalds and others.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+On Debian GNU/Linux systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/make-substvars
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/make-substvars	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/make-substvars	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+upstream=$1
+
+ktdepends="kt-depends="
+ktprovides="kt-provides="
+
+for series in debian/patches/series/*; do
+	base=$(basename $series)
+	ktdepends="${ktdepends}kernel-source-$upstream (= $base) | "
+	ktprovides="${ktprovides}kernel-tree-$base, "
+done
+
+ktprovides=${ktprovides%, }
+ktdepends=${ktdepends%| }
+
+echo $ktdepends
+echo $ktprovides
+
+# vim:ts=4:noet:ai

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/SG_IO-safe-commands-1.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/SG_IO-safe-commands-1.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/SG_IO-safe-commands-1.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,63 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: READ_BUFFER_CAPACITY as read-ok command
+## DP: Patch author: Daniel Drake <dsd at gentoo.org>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# origin: axboe (BitKeeper)
+# cset: 1.2457 (2.6) key=418a4f0df36yYLVdEKUY8xRMnS3HfA
+# inclusion: upstream
+# descrition: [PATCH] add READ_BUFFER_CAPACITY as read-ok command
+# revision date: Fri, 05 Nov 2004 17:18:42 +0900
+#
+# rset: ChangeSet|1.2456..1.2457
+# rset: include/linux/cdrom.h|1.24..1.25
+# rset: drivers/block/scsi_ioctl.c|1.57..1.58
+#
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/04 07:47:25-08:00 axboe at suse.de 
+#   [PATCH] add READ_BUFFER_CAPACITY as read-ok command
+#   
+#   Patch is from Daniel Drake <dsd at gentoo.org>
+#   
+#   Signed-off-by: Jens Axboe <axboe at suse.de>
+#   Signed-off-by: Daniel Drake <dsd at gentoo.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# include/linux/cdrom.h
+#   2004/11/03 14:01:16-08:00 axboe at suse.de +1 -0
+#   add READ_BUFFER_CAPACITY as read-ok command
+# 
+# drivers/block/scsi_ioctl.c
+#   2004/11/03 14:05:08-08:00 axboe at suse.de +1 -0
+#   add READ_BUFFER_CAPACITY as read-ok command
+# 
+diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
+--- a/drivers/block/scsi_ioctl.c	2004-11-05 17:18:42 +09:00
++++ b/drivers/block/scsi_ioctl.c	2004-11-05 17:18:42 +09:00
+@@ -139,6 +139,7 @@
+ 		safe_for_read(GPCMD_PAUSE_RESUME),
+ 
+ 		/* CD/DVD data reading */
++		safe_for_read(GPCMD_READ_BUFFER_CAPACITY),
+ 		safe_for_read(GPCMD_READ_CD),
+ 		safe_for_read(GPCMD_READ_CD_MSF),
+ 		safe_for_read(GPCMD_READ_DISC_INFO),
+diff -Nru a/include/linux/cdrom.h b/include/linux/cdrom.h
+--- a/include/linux/cdrom.h	2004-11-05 17:18:42 +09:00
++++ b/include/linux/cdrom.h	2004-11-05 17:18:42 +09:00
+@@ -452,6 +452,7 @@
+ #define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL  0x1e
+ #define GPCMD_READ_10			    0x28
+ #define GPCMD_READ_12			    0xa8
++#define GPCMD_READ_BUFFER_CAPACITY	    0x5c
+ #define GPCMD_READ_CDVD_CAPACITY	    0x25
+ #define GPCMD_READ_CD			    0xbe
+ #define GPCMD_READ_CD_MSF		    0xb9

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aic79xx-nohw.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aic79xx-nohw.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aic79xx-nohw.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,50 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Handle loaded but no hardware present properly in aic79xx
+## DP: Patch author: Christoph Hellwig <hch at lst.de>
+## DP: Upstream status: submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- 1.56/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-08-25 01:09:04 +02:00
++++ edited/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-09-06 20:46:53 +02:00
+@@ -851,6 +851,7 @@
+ {
+ 	struct	ahd_softc *ahd;
+ 	int     found;
++	int	error = 0;
+ 
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ 	/*
+@@ -902,7 +903,9 @@
+ 	ahd_list_lockinit();
+ 
+ #ifdef CONFIG_PCI
+-	ahd_linux_pci_init();
++	error = ahd_linux_pci_init();
++	if (error)
++		return error;
+ #endif
+ 
+ 	/*
+@@ -919,7 +922,7 @@
+ 	spin_lock_irq(&io_request_lock);
+ #endif
+ 	aic79xx_detect_complete++;
+-	return (found);
++	return 0;
+ }
+ 
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+@@ -5073,7 +5076,7 @@
+ ahd_linux_init(void)
+ {
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+-       return (ahd_linux_detect(&aic79xx_driver_template) ? 0 : -ENODEV);
++	return ahd_linux_detect(&aic79xx_driver_template);
+ #else
+ 	scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template);
+ 	if (aic79xx_driver_template.present == 0) {

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alpha-writeq-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alpha-writeq-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alpha-writeq-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,20 @@
+diff -urN RC9-bk4-disable-DI/include/asm-alpha/io.h RC9-bk4-alpha-writeq-fix/include/asm-alpha/io.h
+--- RC9-bk4-disable-DI/include/asm-alpha/io.h	Mon Oct 18 22:05:06 2004
++++ RC9-bk4-alpha-writeq-fix/include/asm-alpha/io.h	Wed Oct 20 13:45:47 2004
+@@ -658,6 +658,16 @@
+ #define dma_cache_wback(_start,_size)		do { } while (0)
+ #define dma_cache_wback_inv(_start,_size)	do { } while (0)
+ 
++/*
++ * Some mucking forons use if[n]def writeq to check if platform has it.
++ * It's a bloody bad idea and we probably want ARCH_HAS_WRITEQ for them
++ * to play with; for now just use cpp anti-recursion logics and make sure
++ * that damn thing is defined and expands to itself.
++ */
++
++#define writeq writeq
++#define readq readq
++
+ #endif /* __KERNEL__ */
+ 
+ #endif /* __ALPHA_IO_H */

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alsa-module-load-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alsa-module-load-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/alsa-module-load-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,50 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: [ALSA]  suppress auto-loading of modules in module_init().
+## DP: Patch author: Takashi Iwai <tiwai at suse.de>
+## DP: Upstream status: currently in -mm tree, not yet in linus'.
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/09/06 20:18:03+02:00 perex at suse.cz 
+#   [ALSA]  suppress auto-loading of modules in module_init().
+#   
+#   ALSA sequencer
+#   The auto-loading of sequencer modules is suppressed in module_init().
+#   The recent module-init-tools may cause blocking.
+#   
+#   Signed-off-by: Takashi Iwai <tiwai at suse.de>
+# 
+# sound/core/seq/seq_clientmgr.c
+#   2004/09/01 14:25:27+02:00 perex at suse.cz +4 -1
+#   [ALSA]  suppress auto-loading of modules in module_init().
+#   
+#   D:2004/09/01 20:25:27
+#   C:ALSA sequencer
+#   F:core/seq/seq_clientmgr.c:1.34->1.35 
+#   L:The auto-loading of sequencer modules is suppressed in module_init().
+#   L:The recent module-init-tools may cause blocking.
+#   Signed-off-by: Takashi Iwai <tiwai at suse.de>
+# 
+diff -Nru a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
+--- a/sound/core/seq/seq_clientmgr.c	2004-09-21 21:03:33 -07:00
++++ b/sound/core/seq/seq_clientmgr.c	2004-09-21 21:03:33 -07:00
+@@ -156,7 +156,10 @@
+ 					card_requested[card] = 1;
+ 					snd_request_card(card);
+ 				}
+-				snd_seq_device_load_drivers();
++				/* FIXME: may cause blocking when called from
++				 * module_init(), so disable this feature
++				 */
++				/* snd_seq_device_load_drivers(); */
+ 			}
+ 		}
+ 		spin_lock_irqsave(&clients_lock, flags);
+

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aout-loader-fixes.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aout-loader-fixes.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/aout-loader-fixes.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,69 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: [PATCH] a.out: error check on set_brk
+## DP: Patch author: Chris Wright <chrisw at osdl.org>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/16 17:39:02-08:00 chrisw at osdl.org 
+#   [PATCH] a.out: error check on set_brk
+#   
+#   It's possible for do_brk() to fail during set_brk() when exec'ing and
+#   a.out.  This was noted with Florian's a.out binary and overcommit set to
+#   0. 
+#   
+#   Capture this error and terminate properly.
+#   
+#   Signed-off-by: Chris Wright <chrisw at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# fs/binfmt_aout.c
+#   2004/11/11 22:28:58-08:00 chrisw at osdl.org +14 -5
+#   a.out: error check on set_brk
+# 
+diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
+--- a/fs/binfmt_aout.c	2004-11-21 11:38:03 -08:00
++++ b/fs/binfmt_aout.c	2004-11-21 11:38:03 -08:00
+@@ -43,13 +43,18 @@
+ 	.min_coredump	= PAGE_SIZE
+ };
+ 
+-static void set_brk(unsigned long start, unsigned long end)
++#define BAD_ADDR(x)	((unsigned long)(x) >= TASK_SIZE)
++
++static int set_brk(unsigned long start, unsigned long end)
+ {
+ 	start = PAGE_ALIGN(start);
+ 	end = PAGE_ALIGN(end);
+-	if (end <= start)
+-		return;
+-	do_brk(start, end - start);
++	if (end > start) {
++		unsigned long addr = do_brk(start, end - start);
++		if (BAD_ADDR(addr))
++			return addr;
++	}
++	return 0;
+ }
+ 
+ /*
+@@ -413,7 +418,11 @@
+ beyond_if:
+ 	set_binfmt(&aout_format);
+ 
+-	set_brk(current->mm->start_brk, current->mm->brk);
++	retval = set_brk(current->mm->start_brk, current->mm->brk);
++	if (retval < 0) {
++		send_sig(SIGKILL, current, 0);
++		return retval;
++	}
+ 
+ 	retval = setup_arg_pages(bprm, EXSTACK_DEFAULT);
+ 	if (retval < 0) { 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix-2.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix-2.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix-2.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,157 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: libata: PCI IDE legacy mode fix
+## DP: Patch author: Bartlomiej Zolnierkiewicz <bzolnier at gmail.com>
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/10/11 20:11:55-04:00 bzolnier at elka.pw.edu.pl 
+#   [PATCH] libata: PCI IDE legacy mode fix
+#   
+#   In PCI IDE legacy mode ap->port_no is incorrectly set to zero for
+#   the second port.  Fix it by adding ->hard_port_no to struct ata_probe_ent
+#   and struct ata_port (per Jeff's suggestion) and teaching ata_piix.c
+#   to use it instead of ->port_no.
+#   
+#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier at gmail.com>
+# 
+# drivers/scsi/ata_piix.c
+#   2004/10/11 15:52:22-04:00 bzolnier at elka.pw.edu.pl +10 -10
+#   PCI IDE legacy mode fix
+# 
+# drivers/scsi/libata-core.c
+#   2004/10/11 15:52:22-04:00 bzolnier at elka.pw.edu.pl +8 -0
+#   PCI IDE legacy mode fix
+# 
+# include/linux/libata.h
+#   2004/10/11 15:52:22-04:00 bzolnier at elka.pw.edu.pl +2 -0
+#   PCI IDE legacy mode fix
+# 
+diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
+--- a/drivers/scsi/ata_piix.c	2004-11-24 22:45:54 -08:00
++++ b/drivers/scsi/ata_piix.c	2004-11-24 22:45:54 -08:00
+@@ -268,7 +268,7 @@
+ 		goto cbl40;
+ 
+ 	/* check BIOS cable detect results */
+-	mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
++	mask = ap->hard_port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
+ 	pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
+ 	if ((tmp & mask) == 0)
+ 		goto cbl40;
+@@ -294,7 +294,7 @@
+ static void piix_pata_phy_reset(struct ata_port *ap)
+ {
+ 	if (!pci_test_config_bits(ap->host_set->pdev,
+-				  &piix_enable_bits[ap->port_no])) {
++				  &piix_enable_bits[ap->hard_port_no])) {
+ 		ata_port_disable(ap);
+ 		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ 		return;
+@@ -327,8 +327,8 @@
+ 	int orig_mask, mask, i;
+ 	u8 pcs;
+ 
+-	mask = (PIIX_PORT_PRESENT << ap->port_no) |
+-	       (PIIX_PORT_ENABLED << ap->port_no);
++	mask = (PIIX_PORT_PRESENT << ap->hard_port_no) |
++	       (PIIX_PORT_ENABLED << ap->hard_port_no);
+ 
+ 	pci_read_config_byte(pdev, ICH5_PCS, &pcs);
+ 	orig_mask = (int) pcs & 0xff;
+@@ -345,7 +345,7 @@
+ 		mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i);
+ 
+ 		if ((orig_mask & mask) == mask)
+-			if (combined || (i == ap->port_no))
++			if (combined || (i == ap->hard_port_no))
+ 				return 1;
+ 	}
+ 
+@@ -394,7 +394,7 @@
+ 	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
+ 	struct pci_dev *dev	= ap->host_set->pdev;
+ 	unsigned int is_slave	= (adev->devno != 0);
+-	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
++	unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40;
+ 	unsigned int slave_port	= 0x44;
+ 	u16 master_data;
+ 	u8 slave_data;
+@@ -412,10 +412,10 @@
+ 		/* enable PPE, IE and TIME */
+ 		master_data |= 0x0070;
+ 		pci_read_config_byte(dev, slave_port, &slave_data);
+-		slave_data &= (ap->port_no ? 0x0f : 0xf0);
++		slave_data &= (ap->hard_port_no ? 0x0f : 0xf0);
+ 		slave_data |=
+ 			(timings[pio][0] << 2) |
+-			(timings[pio][1] << (ap->port_no ? 4 : 0));
++			(timings[pio][1] << (ap->hard_port_no ? 4 : 0));
+ 	} else {
+ 		master_data &= 0xccf8;
+ 		/* enable PPE, IE and TIME */
+@@ -445,9 +445,9 @@
+ {
+ 	unsigned int udma	= adev->dma_mode; /* FIXME: MWDMA too */
+ 	struct pci_dev *dev	= ap->host_set->pdev;
+-	u8 maslave		= ap->port_no ? 0x42 : 0x40;
++	u8 maslave		= ap->hard_port_no ? 0x42 : 0x40;
+ 	u8 speed		= udma;
+-	unsigned int drive_dn	= (ap->port_no ? 2 : 0) + adev->devno;
++	unsigned int drive_dn	= (ap->hard_port_no ? 2 : 0) + adev->devno;
+ 	int a_speed		= 3 << (drive_dn * 4);
+ 	int u_flag		= 1 << drive_dn;
+ 	int v_flag		= 0x01 << drive_dn;
+diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
+--- a/drivers/scsi/libata-core.c	2004-11-24 22:45:54 -08:00
++++ b/drivers/scsi/libata-core.c	2004-11-24 22:45:54 -08:00
+@@ -3032,6 +3032,8 @@
+ 	ap->ctl = ATA_DEVCTL_OBS;
+ 	ap->host_set = host_set;
+ 	ap->port_no = port_no;
++	ap->hard_port_no =
++		ent->legacy_mode ? ent->hard_port_no : port_no;
+ 	ap->pio_mask = ent->pio_mask;
+ 	ap->mwdma_mask = ent->mwdma_mask;
+ 	ap->udma_mask = ent->udma_mask;
+@@ -3338,8 +3340,14 @@
+ 	probe_ent[0].n_ports = 1;
+ 	probe_ent[0].irq = 14;
+ 
++	probe_ent[0].hard_port_no = 0;
++	probe_ent[0].legacy_mode = 1;
++
+ 	probe_ent[1].n_ports = 1;
+ 	probe_ent[1].irq = 15;
++
++	probe_ent[1].hard_port_no = 1;
++	probe_ent[1].legacy_mode = 1;
+ 
+ 	probe_ent[0].port[0].cmd_addr = 0x1f0;
+ 	probe_ent[0].port[0].altstatus_addr =
+diff -Nru a/include/linux/libata.h b/include/linux/libata.h
+--- a/include/linux/libata.h	2004-11-24 22:45:54 -08:00
++++ b/include/linux/libata.h	2004-11-24 22:45:54 -08:00
+@@ -189,6 +189,7 @@
+ 	Scsi_Host_Template	*sht;
+ 	struct ata_ioports	port[ATA_MAX_PORTS];
+ 	unsigned int		n_ports;
++	unsigned int		hard_port_no;
+ 	unsigned int		pio_mask;
+ 	unsigned int		mwdma_mask;
+ 	unsigned int		udma_mask;
+@@ -273,6 +274,7 @@
+ 	unsigned long		flags;	/* ATA_FLAG_xxx */
+ 	unsigned int		id;	/* unique id req'd by scsi midlyr */
+ 	unsigned int		port_no; /* unique port #; from zero */
++	unsigned int		hard_port_no;	/* hardware port #; from zero */
+ 
+ 	struct ata_prd		*prd;	 /* our SG list */
+ 	dma_addr_t		prd_dma; /* and its DMA mapping */

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ata_piix-combinde-mode-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,40 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Fix ata_piix detection for combined mode (#270194)
+## DP: Patch author: Stuart Hayes <Stuart_Hayes at dell.com>
+## DP: Upstream status: submitted (according to original author)
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- kernel-source-2.6.8-orig/drivers/scsi/ata_piix.c	2004-08-14 07:36:57.000000000 +0200
++++ kernel-source-2.6.8/drivers/scsi/ata_piix.c	2004-09-18 14:54:19.574912216 +0200
+@@ -272,8 +272,25 @@
+ 
+ static void piix_pata_phy_reset(struct ata_port *ap)
+ {
++	unsigned int controller;
++
++	/*
++	 * In combined legacy mode, port number is not the same as
++	 * primary/secondary controller.
++	 */
++	switch (ap->ioaddr.cmd_addr) {
++	case 0x1f0:
++		controller = 0;
++		break;
++	case 0x170:
++		controller = 1;
++		break;
++	default:
++		controller = ap->port_no;
++ 	}
++
+ 	if (!pci_test_config_bits(ap->host_set->pdev,
+-				  &piix_enable_bits[ap->port_no])) {
++				  &piix_enable_bits[controller])) {
+ 		ata_port_disable(ap);
+ 		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+ 		return;

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/dm_io-ENOMEM-goof.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/dm_io-ENOMEM-goof.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/dm_io-ENOMEM-goof.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,93 @@
+# origin: Debian (joshk) -> LKML
+# cset: n/a
+# inclusion: n/a
+# revision date: 2004-11-08
+
+Path: main.gmane.org!not-for-mail
+From: Nigel Cunningham <ncunningham at linuxmail.org>
+Newsgroups: gmane.linux.kernel
+Subject: PATCH (Trivial): Fix dm_io.c oops in low memory conditions.
+Date: Tue, 09 Nov 2004 14:44:45 +1100
+Lines: 34
+Approved: news at gmane.org
+Message-ID: <1099971769.10988.6.camel at desktop.cunninghams>
+Reply-To: ncunningham at linuxmail.org
+NNTP-Posting-Host: deer.gmane.org
+X-Trace: sea.gmane.org 1099972242 16923 80.91.229.6 (9 Nov 2004 03:50:42
+	GMT)
+X-Complaints-To: usenet at sea.gmane.org
+NNTP-Posting-Date: Tue, 9 Nov 2004 03:50:42 +0000 (UTC)
+Original-X-From:
+	linux-kernel-owner+glk-linux-kernel=40m.gmane.org-S261210AbUKIDrY at vger.kern
+	el.org Tue Nov 09 04:50:31 2004
+Return-path:
+	<linux-kernel-owner+glk-linux-kernel=40m.gmane.org-S261210AbUKIDrY at vger.ker
+	nel.org>
+Original-Received: from vger.kernel.org ([12.107.209.244])
+	by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian))
+	id 1CRN1b-0007fY-00
+	for <glk-linux-kernel at gmane.org>; Tue, 09 Nov 2004 04:50:31 +0100
+Original-Received: (majordomo at vger.kernel.org) by vger.kernel.org via
+	listexpand
+	id S261210AbUKIDrY (ORCPT <rfc822;glk-linux-kernel at m.gmane.org>);
+	Mon, 8 Nov 2004 22:47:24 -0500
+Original-Received: (majordomo at vger.kernel.org) by vger.kernel.org id
+	S261229AbUKIDqL
+	(ORCPT <rfc822;linux-kernel-outgoing>);
+	Mon, 8 Nov 2004 22:46:11 -0500
+Original-Received: from pop5-1.us4.outblaze.com ([205.158.62.125]:940 "HELO
+	pop5-1.us4.outblaze.com") by vger.kernel.org with SMTP
+	id S261210AbUKIDp7 (ORCPT <rfc822;linux-kernel at vger.kernel.org>);
+	Mon, 8 Nov 2004 22:45:59 -0500
+Original-Received: (qmail 14504 invoked from network); 9 Nov 2004 03:45:58
+	-0000
+Original-Received: from unknown (HELO ?203.194.46.144?)
+	(ncunningham at linuxmail.org@203.194.46.144)  by pop5-1.us4.outblaze.com with
+	SMTP; 9 Nov 2004 03:45:57 -0000
+Original-To: Linux Kernel Mailing List <linux-kernel at vger.kernel.org>,
+	Andrew Morton <akpm at digeo.com>,
+	Linus Torvalds <torvalds at osdl.org>
+X-Mailer: Ximian Evolution 1.4.6-1mdk
+Original-Sender: linux-kernel-owner at vger.kernel.org
+Precedence: bulk
+X-Mailing-List: linux-kernel at vger.kernel.org
+Xref: main.gmane.org gmane.linux.kernel:253634
+X-Report-Spam: http://spam.gmane.org/gmane.linux.kernel:253634
+MIME-Version: 1.0
+Content-Type: text/plain
+Content-Transfer-Encoding: 7bit
+
+Hi.
+
+If you call drivers/md/dm-io.c:resize_pool on an empty pool and
+mempool_create is unable to make the pool, the condition is not handled
+correctly, resulting in an oops in mempool_destroy.
+
+Please apply.
+
+Regards,
+
+Nigel
+
+diff -ruN 900-dm-low-memory-fix-old/drivers/md/dm-io.c 900-dm-low-memory-fix-new/drivers/md/dm-io.c
+--- 900-dm-low-memory-fix-old/drivers/md/dm-io.c	2004-11-09 14:35:09.234557768 +1100
++++ 900-dm-low-memory-fix-new/drivers/md/dm-io.c	2004-11-09 13:34:36.000000000 +1100
+@@ -265,7 +265,7 @@
+ 		/* create new pool */
+ 		_io_pool = mempool_create(new_ios, alloc_io, free_io, NULL);
+ 		if (!_io_pool)
+-			r = -ENOMEM;
++			return -ENOMEM;
+ 
+ 		r = bio_set_init(&_bios, "dm-io", 512, 1);
+ 		if (r) {
+
+-- 
+Nigel Cunningham
+Pastoral Worker
+Christian Reformed Church of Tuggeranong
+PO Box 1004, Tuggeranong, ACT 2901
+
+You see, at just the right time, when we were still powerless, Christ
+died for the ungodly.		-- Romans 5:6
+

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/doc-post_halloween.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/doc-post_halloween.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/doc-post_halloween.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,1289 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: add post-halloween-2.6.txt
+## DP: Patch author: unknown
+## DP: Upstream status: not submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN kernel-source-2.6.6/Documentation/post-halloween-2.6.txt kernel-source-2.6.6-1/Documentation/post-halloween-2.6.txt
+--- kernel-source-2.6.6/Documentation/post-halloween-2.6.txt	1970-01-01 10:00:00.000000000 +1000
++++ kernel-source-2.6.6-1/Documentation/post-halloween-2.6.txt	2004-02-23 08:01:43.000000000 +1100
+@@ -0,0 +1,1274 @@
++
++                     The post-halloween document. v0.48
++                        (aka, 2.6 - what to expect)
++
++                    Dave Jones <davej at codemonkey.org.uk>
++
++                          (Updated as of 2.6.0)
++
++This document explains some of the new functionality to be found in the 2.6
++Linux kernel, some pitfalls you may encounter, and also points out some new
++features which could really use testing.
++Note, that "contact foo at bar.com" below also implies that you should also
++cc: linux-kernel at vger.kernel.org.
++
++Latest version of this document can always be found at
++http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt
++
++Thanks to many [far too many to list] people for valuable feedback.
++
++Note, that this document is somewhat x86-centric, but most features
++documented here affect all platforms anyway.
++
++Translations:
++Spanish - http://www.terra.es/personal/diegocg/post-halloween-2.6.es.txt
++German  - http://www.kubieziel.de/computer/halloween-german.html
++Polish  - http://soltysiak.com/linux/post-halloween-2.6.pl.txt
++pt_BR   - http://www.maluco.com.br/thiago/docs/post-halloween-2.6-pt_BR.txt
++
++
++Applying patches.
++~~~~~~~~~~~~~~~~~
++- In 2.4 and previous kernels, the recommended way to apply patches was
++  to use a command line such as ...
++  gzip -cd patchXX.gz | patch -p0
++  In 2.6, Linus started adding an extra path element to the diffs,
++  so using -p1 in the untarred 'to be patched' directory is necessary.
++
++Reporting bugs.
++~~~~~~~~~~~~~~~
++Most large subsystems of the kernel have their own mailing list.
++Mailing these with bug reports is always good. If in doubt, send
++them to linux-kernel at vger.kernel.org
++
++    ACPI      - acpi-devel at lists.sourceforge.net
++    Bluetooth - bluez-devel at lists.sourceforge.net
++    Ext2      - ext2-devel at lists.sourceforge.net
++    Firewire  - linux1394-devel at lists.sourceforge.net
++    SCSI      - linux-scsi at vger.kernel.org
++    USB       - linux-usb-users at lists.sourceforge.net
++    XFS       - linux-xfs at oss.sgi.com
++
++Known gotchas.
++~~~~~~~~~~~~~~
++Certain known bugs are being reported over and over. Here are the
++workarounds.
++- Blank screen after decompressing kernel?
++  Make sure your .config has
++   CONFIG_INPUT=y
++   CONFIG_VT=y
++   CONFIG_VGA_CONSOLE=y
++   CONFIG_VT_CONSOLE=y
++  A lot of people have discovered that taking their .config from 2.4 and
++  running make oldconfig to pick up new options leads to problems, notably
++  with CONFIG_VT not being set.
++- An additional bug biting some people is that NICs fail to receive packets
++  (usually notable by a NIC not getting a DHCP lease for eg, despite being
++   sent one by the server). Booting with "noapic" "acpi=off" or a combination
++  of both fixes this for most people.
++- (Possibly linked to above bug) VIA APIC routing is currently broken.
++  boot with 'noapic'.
++- Can't load any modules? You need updated tools (See modules section below).
++- depmod reports Unresolved symbols?  depmod from modutils instead of
++  depmod from module-init-tools is first in $PATH (might be different
++  $PATHs as $USER and $ROOT)
++
++
++Regressions.
++~~~~~~~~~~~~
++(Things not expected to work just yet)
++- The hptraid/promise drivers for proprietary RAID formats are currently
++  non functional, and will probably be converted to use device-mapper.
++- Some filesystems still need work (Intermezzo, UFS, HFS, HPFS..)
++  - UMSDOS fs is currently missing, pending rewrite.
++  - EFS (has a blocksize problem, depending on the device that the
++    filesystem is being mounted on)
++- A number of drivers don't compile currently due to them needing various
++  work to convert them to the new APIs
++- The format of /proc/stat changed, which could break some
++  applications that still depend on the old layout.
++- Some people seem to have trouble running rpm, most notably Red Hat 9 users.
++  This is a known bug of rpm.
++  Workaround: run "export LD_ASSUME_KERNEL=2.2.5", before running rpm.
++  This is thought to be a bug related to db4 and O_DIRECT interaction.
++
++
++Stuff needing forward porting from 2.4.
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++- HFSPlus
++- SuperH 64
++
++
++Removed features.
++~~~~~~~~~~~~~~~~~
++- khttpd is gone.
++- Older Direct Rendering Manager (DRM) support (For XFree86 4.0)
++  has been removed. Upgrade to XFree86 4.1.0 or higher.
++- LVM1 has been removed. See Device-mapper below.
++- The system call table is no longer exported. Any module that relied
++  on this previously will no longer work.
++- Soundmodem hamradio support has been removed. Its functionality
++  has been superceded by a userspace replacement.
++  http://www.baycom.org/~tom/ham/soundmodem
++- Direct booting from floppy is no longer supported.
++  You should now use a boot loader program such as syslinux instead.
++  "make bzdisk" continues to work (now using syslinux).
++- Callout tty devices (/dev/cua) have been deprecated since 2.1.90pre2.
++  Support is now removed.
++
++
++Deprecated/obsolete features.
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++- devfs will be obsoleted in favour of udev (http://www.kernel.org/pub/linux/utils/kernel/hotplug/)
++- boot time root= parsing changed.
++  ramdisks are now ram<n> instead of rd<n> and cm206 is cm206cd (instead of
++  cm206).
++- usbdevfs will be going away in 2.7. The same filesystem can
++  be mounted as 'usbfs' in recent 2.4 kernels, and in 2.5.52
++  and above, which is what the filesystem will furthermore be
++  known as.
++- elvtune is deprecated (as are the ioctl's it used).
++  Instead, the io scheduler tunables are exported in sysfs (see below)
++  in the /sys/block/<device>/queue/iosched directory.
++  Jens wrote a document explaining the tunables of the new scheduler at
++  http://www.lib.uaa.alaska.edu/linux-kernel/archive/2002-Week-44/att-deadline-iosched.txt
++- Using sysctls by numeric values is deprecated, and will go away
++  in the next development series.
++
++
++Modules.
++~~~~~~~~
++- The in-kernel module loader was reimplemented.
++- You need replacement module utilities from
++  http://www.kernel.org/pub/linux/kernel/people/rusty/modules/
++- A backwards compatible set of module utilities is also available
++  from the same URL in RPM format.
++- Debian sarge/sid or Conectiva snapshot users can just use
++  'apt-get install module-init-tools'
++- Modules now free stuff marked with __init or __initdata.
++- For Red Hat users, there's another pitfall in "/etc/rc.sysinit".
++  During startup, the script sets up the binary used to dynamically load
++  modules stored at "/proc/sys/kernel/modprobe". The initscript looks
++  for "/proc/ksyms", but since it doesn't exist in 2.6 kernels, the
++  binary used is "/sbin/true" instead.
++
++  This, eventually, will keep modules from working. Red Hat users will
++  have to patch the "/etc/rc.sysinit" script to set
++  "/proc/sys/kernel/modprobe" to "/sbin/modprobe", even
++  when "/proc/ksyms" doesn't exist.
++- Modules now have a .ko suffix instead of .o
++- Some (older) versions of 'mkinitrd' don't search for modules
++  that end with .ko, so update your mkinitrd if this is a problem.
++
++
++Kernel build system.
++~~~~~~~~~~~~~~~~~~~~
++- The build system is much improved compared to 2.4.
++  You should notice quicker builds, and less spontaneous rebuilds
++  of files on subsequent builds from already built trees.
++- There are new graphical config tools.
++  "make xconfig" now requires the qt libraries.
++  "make gconfig" uses gtk libraries.
++- Make menuconfig/oldconfig has no user-visible changes other than speed,
++  whilst numerous improvements have been made.
++- Several new debug targets exist: 'allyesconfig' 'allnoconfig' 'allmodconfig'.
++- Note: The new configuration system is not CML2 related.
++- Also note: Whilst some ideas were taken from it, Keith Owens'
++  kbuild-2.5 project was not integrated.
++- "make" is now the preferred command, without a target; it does <arch-zimage>
++  and modules.
++- "make -jN" is now the preferred parallel-make execution.
++  Do not bother to provide "MAKE=xxx"
++- The build is now much less verbose.  If you want to see exactly what's
++  going on, try "make V=1" or set KBUILD_VERBOSE=1 in your environment.
++- 'make kernel/mm.o' will build the named file, provided a
++  corresponding source exists. This also works for (non-composite)
++  modules. (FIXME: broken for modules right now?)
++- 'make kernel/' will compile all files in a subdirectory and below.
++- There is no need to run 'make dep' at any stage.
++- 'make help' provides a list of typical targets, including debugging targets.
++- You can now build in a separate tree from the source by doing
++  make O=builddir
++
++
++IO subsystem.
++~~~~~~~~~~~~~
++- You should notice considerable throughput improvements over 2.4 due
++  to much reworking of the block and the memory management layers.
++- Report any regressions in this area to Jens Axboe <axboe at suse.de>
++  and Andrew Morton <akpm at osdl.org>
++- Two different IO elevators are available. The default is the
++  anticipatory IO scheduler. You can select the deadline scheduler by
++  booting with "elevator=deadline" on the kernel command line.
++- For some workloads the anticipatory scheduler is around 10% slower
++  than deadline. Most notably, database workloads which seek all over the
++  disk performing reads and synchronous writes. Database folks will likely
++  want to boot with elevator=deadline to get that last bit of performance back.
++- Assorted changes throughout the block layer meant various block
++  device drivers had a large scale cleanup whilst being updated to
++  newer APIs.
++- The size and alignment of O_DIRECT file IO requests now matches that
++  of the device, not the filesystem.  Typically this means that you
++  can perform O_DIRECT IO with 512-byte granularity rather than 4k.
++  But if you rely upon this, your application will not work on 2.4 kernels
++  and will not work on some devices.
++
++
++block device size support.
++~~~~~~~~~~~~~~~~~~~~~~~~~~
++- Thanks to work done by Peter Chubb, block devices can now access up to
++  16TB on 32-bit architectures, and up to 8EB on 64-bit architectures.
++- To use the new BLKGETSZ64 ioctls, you'll need updated file-utils.
++  (Currently only jfsutils 1.0.20 has this change, patches for other
++   filesystems are still pending merging)
++- The old 'struct statfs' is not able to describe large devices - the
++  statfs() system call will now return -EOVERFLOW for such devices.
++  A new system call called statfs64() with a new structure has been added
++  to support large devices. It it unknown at time of writing how many
++  userspace utilities have been converted to take advantage of this
++  syscall when available.
++
++
++POSIX ACLs & Extended attributes.
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++- Userspace tools available at http://acl.bestbits.at
++
++
++VM Changes.
++~~~~~~~~~~~
++- Version zero swap partitions are no longer supported (everything is
++  using v1 now anyway - rerun mkswap if in doubt).
++  Linux 2.0.x requires v0 swap space, Linux v2.1.117 and later
++  support v1.  mkswap(8) can format swap space in either format.
++- The actual 'reverse mappings' part of Rik van Riel's rmap vm was merged.
++  VM behaviour under certain loads should improve.
++- VM misbehaviour should be reported to linux-mm at kvack.org
++- The VM explicitly checks for sparse swapfiles, and aborts if one is found.
++- /proc/sys/vm/swappiness defines the kernel's preference for pagecache over
++  mapped memory. Setting it to 100 (percent) makes it treat both types of
++  memory equally. Setting it to zero makes the kernel very much prefer to
++  reclaim plain pagecache rather than mapped-into-pagetables memory.
++- The bdflush() syscall is now officially deprecated. The syscall
++  does nothing, and prints a stern warning to users. The functionality
++  is replaced by the pdflush daemons.
++- Due to various changes, swap files should be just as fast as swap partitions.
++- In 2.4, up to 64 swap files were possible. In 2.6, this number is reduced
++  to 32.  Like 2.4, these files can be up to 64GB in size, though you will
++  need a recent util-linux to have a mkswap utility that supports >2GB
++
++
++Kernel preemption.
++~~~~~~~~~~~~~~~~~~
++- The much talked about preemption patches made it into 2.6.
++  With this included you should notice much lower latencies especially
++  in demanding multimedia applications. 
++- Note, there are still cases where preemption must be temporarily disabled
++  where we do not. These areas occur in places where per-CPU data is used.
++- If you get "xxx exited with preempt count=n" messages in syslog,
++  don't panic, these are non fatal, but are somewhat unclean.
++  (Something is taking a lock, and exiting without unlocking)
++- If you DO notice high latency with kernel preemption enabled in
++  a specific code path, please report that to Andrew Morton <akpm at osdl.org>
++  and Robert Love <rml at tech9.net>.
++  The report should be something like "the latency in my xyz application
++  hits xxx ms when I do foo but is normally yyy" where foo is an action
++  like "unlink a huge directory tree".
++
++
++Process scheduler improvements.
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++- Another much talked about feature. Ingo Molnar reworked the process
++  scheduler to use an O(1) algorithm.  In operation, you should notice
++  no changes with low loads, and increased scalability with large numbers
++  of processes, especially on large SMP systems.
++- Scheduler is now Hyperthreading SMP aware and will disperse processes
++  over physically different CPUs, instead of just over logical CPUs.
++- Robert Love wrote various utilities for changing behaviour of the
++  scheduler (binding processes to CPUs etc). You can find these tools at
++  http://tech9.net/rml/schedutils
++- The behavior of sched_yield() changed a lot.  A task that uses
++  this system call should now expect to sleep for possibly a very
++  long time.  Tasks that do not really desire to give up the
++  processor for a while should probably not make heavy use of this
++  function.  Unfortunately, some GUI programs (like Open Office)
++  do make excessive use of this call and under load their
++  performance is poor.  It seems this new 2.6 behavior is optimal
++  but some user-space applications may need fixing.
++- The above applies to use of yield() in the kernel, too.
++- 2.6 adds system calls for manipulating a task's processor
++  affinity: sched_getaffinity() and sched_setaffinity()
++- Regressions to mingo at redhat.com and rml at tech9.net
++- Debian users who encounter effects such as skips in mp3
++  playback, jerky mouse movement may want to stop the
++  X server from renicing itself to -10
++  You can alter this permanently with 'dpkg-reconfigure xserver-common';
++  if you elect not to have /etc/X11/Xwrapper.config managed by debconf,
++  simply edit it directly.
++- Balancing of IRQs between multiple CPUs should be handled using the
++  irqbalance (http://people.redhat.com/arjanv/irqbalance/) program.
++- David Mosberger maintains a webpage containing some current 'known gotchas'
++  of the O(1) scheduler at http://www.hpl.hp.com/research/linux/kernel/o1.php
++
++
++PCI.
++~~~~
++- PCI domain support has been added.  For most people, this just means that
++  all PCI slot names are extended with "0000:" on the front, but for people
++  with bigger servers it means they're able to access all their PCI devices.
++- More hotplug drivers have been added, including a fake PCI hotplug driver
++  so people without specialised hardware can test hotplug features.
++
++Random.
++~~~~~~~
++- /dev/hwrandom got support for some new hardware (now also backported to 2.4)
++  such as the HW RNG on newer VIA Cyrix CPUs.
++- rng-tools can be found at http://sourceforge.net/projects/gkernel
++
++
++Fast userspace mutexes (Futexes).
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++- Rusty Russell added functionality that allows userspace to have
++  fast mutexes that only use syscalls when there is contention. Used by
++  NPTL.
++- Additional information on futexes can be found in Ulrich Dreppers
++  paper on the subject at http://people.redhat.com/drepper/futex.pdf
++- Bert Hubert has written some documentation on this functionality
++  at http://ds9a.nl/futex-manpages
++
++
++epoll
++~~~~~
++Davide Libenzi wrote an event based poll replacement that got
++included in 2.6.  More info available at
++http://www.xmailserver.org/linux-patches/nio-improve.html
++http://lwn.net/Articles/13587/
++
++
++Threading improvements.
++~~~~~~~~~~~~~~~~~~~~~~~
++- Ingo Molnar put a lot of work into threading improvements for 2.6.
++  Some of the features of this work are:
++  -  Generic pid allocator (arbitrary number of PIDs with no slowdown,
++     unified pidhash).
++  -  Thread Local Storage syscalls
++  -  sys_clone() enhancements (CLONE_SETTLS, CLONE_PARENT_SETTID, CLONE_SETTID,
++     CLONE_CLEARTID, CLONE_DETACHED)
++  -  POSIX thread signals stuff (atomic signals, shared signals, etc.)
++  -  Per-CPU GDT
++  -  Threaded coredumping support
++  -  sys_exit() speedups (O(1) exit)
++  -  Generic, improved futexes, vcache
++  -  New, threading related ptrace features
++  -  exit/fork task cache
++  -  /proc updates for threading
++  -  API changes for threading.
++- Users should notice a significant speedup in basic thread operations.
++  This is true to a lesser extent even for old-threading userspace libraries 
++  such as LinuxThreads.
++- Regressions should go to Ingo Molnar <mingo at redhat.com> and
++  phil-list at redhat.com.  Regressions could happen in the area of signal
++  handling and related threading semantics, plus coredumping.
++- Native Posix Threading Library (NPTL).
++  Ulrich Drepper worked closely with Ingo on the threading enhancements, and
++  developed a 1:1 model threading library. You can find out more about NPTL at
++  http://people.redhat.com/drepper/nptl-design.pdf
++
++
++Enhanced coredumping. 
++~~~~~~~~~~~~~~~~~~~~~
++- 2.6 offers you the ability to configure the way core files are
++  named through a /proc/sys/kernel/core_pattern file.
++  You can use various format identifiers in this name to affect
++  how the core dump is named.
++
++    %p - insert pid into filename
++    %u - insert current uid into filename
++    %g - insert current gid into filename
++    %s - insert signal that caused the coredump into the filename
++    %t - insert UNIX time that the coredump occurred into filename
++    %h - insert hostname where the coredump happened into filename
++    %e - insert coredumping executable name into filename
++
++  You should ensure that the string does not exceed 64 bytes.
++- Multithreaded processes can now dump core
++
++
++Input layer.
++~~~~~~~~~~~~
++- Possibly the most visible change to the end user. If misconfigured,
++  you'll find that your keyboard/mouse/other input device will no longer work.
++  2.6 offers a much more flexible interface to devices such as keyboards.
++- The downside is more confusing options.
++  In the "Input device support" menu, be sure to enable at least the following.
++
++                    --- Input I/O drivers
++                    < > Serial i/o support
++                    < >   i8042 PC Keyboard controller
++                    [ ] Keyboards
++                    [ ] Mice
++
++  (Also choose the relevant keyboard/mouse from the list)
++
++- If you find your keyboard/mouse still don't work, edit the file
++  drivers/input/serio/i8042.c, and replace the #undef DEBUG
++  with a #define DEBUG, recompile and reinstall.
++
++  When you boot, you should now see a lot more debugging information.
++  Forward this information to Vojtech Pavlik <vojtech at suse.cz>
++
++- If you use a KVM switcher, and experience problems, booting with the boot
++  time argument 'psmouse_noext' should fix your problems.
++- Users of multimedia keys without X will see changes in how the kernel
++  handles those keys. People who customize keymaps or keycodes in 2.4
++  may need to make some changes in 2.6
++- Users wanting support for the PC speaker need to enable CONFIG_INPUT_PCSPKR,
++  or you won't get a single beep.
++- Synaptics touchpad users may be interested to check out
++  http://w1.894.telia.com/~u89404340/touchpad/
++- In 2.4 users of Japanese keyboards were able to type '|' or
++  '\' characters without loading any custom keymap on the
++  console.  With the keymap in 2.6, this is not possible
++  anymore.  People with these keyboards have to load a keymap
++  with loadkeys rebuilt from the source, since loadkeys in some
++  vendor distributions cannot load keycodes larger than 127.
++  There is a patch to fix this, but it has not been integrated
++  (http://tinyurl.com/t75a).
++
++PnP layer.
++~~~~~~~~~~
++- Support for plug and play devices such as early ISAPnP cards has improved a
++  lot in the 2.6 kernel. The new code behaves more closely to the code
++  handling PCI devices (probe, remove etc callbacks), and also merges
++  PnP BIOS access code.
++- Report any regressions in plug & play functionality to
++  Adam Belay <ambx1 at neo.rr.com>
++
++
++ALSA.
++~~~~~
++- The advanced linux sound architecture was merged into 2.6.
++  This offers considerably improved functionality over the older OSS drivers,
++  but requires new userspace tools.
++- Several distros have shipped ALSA for some time, so you may already have the
++  necessary tools. If not, you can find them at http://www.alsa-project.org/
++- ALSA can emulate OSS interface using the snd_pcm_oss/snd_pcm_mixer
++  modules, if your card produces nothing but silence, you may need to run
++  alsamixer to unmute channels wich /dev/mixer doesn't see
++- Note that the OSS drivers are also still functional, and still present.
++  Many features/fixes that went into 2.4 are still not applied to these
++  drivers, and it's still unclear if they will remain when 2.6 ships.
++  The long term goal is to get everyone moved over to (the superior) ALSA.
++
++
++AGP.
++~~~~
++- The agpgart driver got a long overdue cleanup which involved
++  splitting it into an agpgart core, and per-chipset drivers.
++  You may need to adjust your modules configuration to autoload
++  the chipset drivers on loading the agpgart module.
++- Generic AGP 3.0 support is now included.
++
++DRI.
++~~~~
++- Direct rendering in 2.6 hasn't had much (if any?) testing on
++  older versions of XFree86. Feedback on whether 4.1 works would
++  be useful.
++
++
++Faster system calls.
++~~~~~~~~~~~~~~~~~~~~
++- Systems that support the SYSENTER extension (Basically Intel Pentium-II
++  and above, and AMD Athlons) now have a faster method of making the
++  transition from userspace to kernelspace when a syscall is performed.
++- Pentium Pro also has SYSENTER, but due to errata, is unusable.
++- Without an updated glibc, this will not be noticable.
++- VMWare 4 users may get crashes due to this.
++  Zwane Mwaikambo wrote a patch for a "nosysenter" option which is worth
++  googling for if there isn't a vmware update available.
++- Regressions to torvalds at osdl.org and libc-alpha at sources.redhat.com
++
++
++procps.
++~~~~~~~
++- The 2.6 /proc filesystems changed some statistics, which confuse older
++  versions of procps. Rik van Riel and Robert Love have been maintaining a
++  version of procps during the development of 2.6 which tracks changes to
++  /proc which you can find at http://tech9.net/rml/procps/
++- Alternatively, the procps by Albert Cahalan now supports the altered formats
++  since v3.0.5  -- http://procps.sf.net/
++- The /proc/meminfo format changed slightly which also broke gtop in strange
++  ways. Likely this also broke some of the KDE/GNOME panel applets.
++
++
++Framebuffer layer.
++~~~~~~~~~~~~~~~~~~
++- James Simmons has reworked the framebuffer/console layer considerably for
++  2.6. Support for some cards is still lagging a little, but it should be
++  functionally no different than previous incarnations.
++- boot time arguments may have changed depending on your driver.
++  an example of the change is..
++    append = "video=radeon:1024x768-24 at 100"
++  needs to become..
++    append = "video=radeonfb:1024x768-24 at 100"
++- Current userspace tools (fbset for eg) are not yet updated,
++  and won't function as expected.
++- The VESA framebuffer now enables MTRRs for the framebuffer memory range during
++  initialisation (Note: PCI cards only).
++  If you notice screen corruption, please report this, along with an lspci output,
++  so your card can be blacklisted.
++- Any problems should go to <jsimmons at infradead.org>
++
++
++IDE.
++~~~~
++- The IDE code rewrite was subject to much criticism in early 2.5.x, which
++  put off a lot of people from testing. This work was then subsequently
++  dropped, and reverted back to a 2.4.18 IDE status.
++  Since then additional work has occurred, but not to the extent
++  of the first cleanup attempts.
++- Known problems with the current IDE code. 
++  o  Simplex IDE devices (eg Ali15x3) are missing DMA sometimes
++  o  Most PCMCIA devices have unload races and may oops on eject
++  o  Modular IDE does not yet work, modular IDE PCI modules sometimes
++     oops on loading
++  o  ide-scsi is completely broken in 2.6 currently. Known problem.
++     If you need it either use 2.4 or fix it 8)
++- IDE disk geometry translators like OnTrack, EZ Partition, Disk Manager
++  are no longer autodetected. The only way forward is to remove the translator
++  from the drive, and start over, or use boot parameters depending on the
++  type of remapper used :-
++    hdx=remap63   - add 63 to each sector (For OnTrack DM)
++    hdx=remap     - remap 0->1 (For EZDrive)
++- See also the CD Recording section for some important changes
++  related to IDE CD writers.
++
++IDE TCQ.
++~~~~~~~~
++- Tagged command queueing for IDE devices has been included.
++- Not all combinations of controllers & devices may like this,
++  so handle with care.
++  READ AS: ** Don't use IDE TCQ on any data you value.
++  It's likely bad combinations will be blacklisted as and when discovered.
++
++- If you didn't choose the "TCQ on by default" option, you can enable
++  it by using the command
++
++    echo "using_tcq:32" > /proc/ide/hdX/settings
++
++  (replacing 32 with 0 disables TCQ again).
++
++- Report success/failure stories to Jens Axboe <axboe at suse.de> with
++  inclusion of hdparm -i /dev/hdX, and lspci output.
++
++
++SCSI.
++~~~~~
++- Various SCSI drivers still need work, and don't even compile.
++- Various drivers currently lack error handling.
++  These drivers will cause warnings during compilation due to
++  missing abort: & reset: functions.
++- Note, that some drivers have had these members removed, but still
++  lack error handling. Those noticed so far are ncr53c8xxx, sym53c8xx
++- large dev_t support allowing thousands of disks to be
++  supported (was 128 or 256 in the 2.4 series)
++- major code cleanup, initially to support the block layer (bio)
++  improvements have led to:
++   - better throughput (?) [less double handling of data]
++   - per HBA locks (there was a single io_request_lock in
++     the 2.4 series)
++   - more flexible interface to HBA drivers
++   - better hotplug support, especially for USB mass storage
++     and ieee1394 sbp2 devices [well it's work_in_progress]
++- improved error processing and scanning code (support for
++  large, sparse lun spaces)
++- lots of scsi driver internals available via sysfs
++
++
++v4l2.
++~~~~~
++- The video4linux API finally got its long awaited cleanup.
++- xawtv, bttv and most other existing v4l tools are also compatible
++  with the new v4l2 layer. You should notice no loss in functionality.
++- See http://bytesex.org/v4l/ for more information.
++
++
++Quota reworking.
++~~~~~~~~~~~~~~~~
++The new quota system needs new tools. Supports 32 bit uids.
++http://www.sf.net/projects/linuxquota/
++
++
++CD Recording.
++~~~~~~~~~~~~~
++- Jens Axboe added the ability to use DMA for writing CDs on
++  ATAPI devices. Writing CDs should be much faster than it
++  was in 2.4, and also less prone to buffer underruns and the like.
++- With a recent cdrecord, you also no longer need ide-scsi in order to use
++  an IDE CD writer.
++- Ripping audio tracks off of CDs now also uses DMA and should be
++  notably faster. You can also find an updated cdda2wav at:
++  *.kernel.org/pub/linux/kernel/people/axboe/tools/
++- Send good/bad reports of audio extraction with cdda2wav and burning with
++  the cdrecord to Jens Axboe <axboe at suse.de>
++- Currently only 'open by device name' works in cdrecord.
++  cdrecord -dev=/dev/hdX -inq
++- More info at http://lwn.net/Articles/13538/ & http://lwn.net/Articles/13160/
++
++
++USB:
++~~~~
++- USB host controller drivers were renamed in 2.6. They are now
++   uhci-hcd for UHCI controllers.
++   ohci-hcd for OHCI controllers.
++   ehci-hcd for EHCI (USB 2.0) controllers.
++- Very little user visible changes, the only noticable 'major' change
++  is that there is now only one UHCI driver. As noted elsewhere, usbdevfs 
++  was renamed to usbfs.
++- USB-storage has changed behaviour. A device which is disconnected and
++  then reconnected is not reassociated with the old /dev node.
++- USB storage also got several performance enhancements.
++
++- USB 'gadget' support.
++  There's a new "USB Gadget" API supporting USB devices that
++  run Linux inside.  Examples include PDAs, cable modems,
++  and some printers.  That API is how the driver for the
++  USB Device Controller (UDC) hardware talks with portable
++  "gadget drivers".  A gadget driver is what makes that
++  hardware act like a "network link" or a "printer".
++		                                                                                           
++  When you don't want to write a gadget driver in the kernel,
++  then "gadgetfs" lets you do it in user mode programs.
++  Each endpoint appears as a single file, so it's a lot
++  simpler than "usbfs".  Currently it's purely synchronous,
++  but it should be natural for someone to add AIO support.
++		                                                                                           
++  See http://www.linux-usb.org/gadget for more information
++  about this API framework, including a pthreaded example
++  "gadgetfs" program.  See the 2.6 kerneldoc for API info.
++		
++
++Nanosecond stat:
++~~~~~~~~~~~~~~~~
++The stat64() syscall was changed to return jiffies granularity.
++This allows make(1) to make better decisions on whether or not it
++needs to recompile a file. Not all filesystems may support such precision.
++
++
++Filesystems:
++~~~~~~~~~~~~
++A number of additional filesystems have made their way into 2.6.
++Currently it supports: ext2, ext3, reiserfs, jfs, xfs, minix, romfs,
++iso9660, udf, msdos, vfat, ntfs (ro), adfs, amiga ffs, apple macintosh hfs,
++BeOS befs (ro), bfs, efs (ro), cramfs, free vxfs, os/2 hpfs, qnx4fs,
++sysvfs, ufs.
++Whilst these have had testing out of tree, the level of testing
++after merging is unparalleled. Be wary of trusting data to immature
++filesystems.  A number of new features and improvements have also
++been made to the existing filesystems from 2.4.
++
++Reports of stress testing with the various tools available would
++be beneficial.
++
++
++Generic VFS changes.
++~~~~~~~~~~~~~~~~~~~~
++- Since Linux 2.5.1 it is possible to atomically move a subtree to
++  another place. The usage is...
++   mount --move olddir newdir
++- Since 2.5.43, dmask=value sets the umask applied to directories only.
++  The default is the umask of the current process.
++  The fmask=value sets the umask applied to regular files only.
++  Again, the default is the umask of the current process.
++- Directories can now be marked as synchronous using chattr +S,
++  so that all changes will be immediately written to disk.
++  Note, this does not guarantee atomicity, at least not for all filesystems
++  and for all operations.  You *can* be guaranteed that system calls will
++  not return until the changes are on disk; note though that this does have
++  has some significant performance impacts.
++
++
++
++devfs.
++~~~~~~
++- devfs was somewhat stripped down and a lot of duplicate functionality
++  was removed. You now need to enable CONFIG_DEVPTS_FS=y and mount
++  the devpts filesystem in the same manner you would if you were not
++  using devfs.
++
++
++EXT2.
++~~~~~
++- 2.5.49 included an extension to ext2 which will cause it to not attach
++  buffer_head structures to file or directory pagecache at all, ever.
++  This is for the big highmem machines.  It is enabled via the `-o nobh'
++  mount option.
++- The ext2 filesystem is now using finer-grained locking which yields reduced
++  context switch rates and higher throughput on large SMP machines.
++
++
++EXT3.
++~~~~~
++- The ext3 filesystem has gained indexed directory support, which offers
++  considerable performance gains when used on filesystems with directories
++  containing large numbers of files.
++- In order to use the htree feature, you need at least version 1.32 of
++  e2fsprogs.
++- Existing filesystems can be converted using the command
++
++    tune2fs -O dir_index /dev/hdXXX
++
++- The latest e2fsprogs can be found at
++  http://prdownloads.sourceforge.net/e2fsprogs
++- The ext2 and ext3 filesystems have new file allocations policies (the "Orlov
++  allocator") which will place subdirectories closer together on-disk.  This
++  tends to mean that operations which touch many files in a directory tree are
++  much faster if that tree was created under a 2.6 kernel.
++
++Reiserfs.
++~~~~~~~~~
++- Reiserfs now supports inode attributes such as immutable.
++  (Also included in 2.4.17, so not really 'new').
++- Relocated/non-standard size journal support (also backported
++  to 2.4.22pre3)
++- Support for writes larger than 4KB in size, which means speedups
++  on large file writes, esp in append mode, should also be more
++  SMP friendly.
++- Variable blocksize support. (Ie, you can choose any blocksize
++  in the range of 1024 .. PAGE_CACHE_SIZE, must be power of 2).
++
++
++NFS.
++~~~~
++- Basic support has been added for NFSv4 (server and client)
++- Additionally, kNFSD now supports transport over TCP.
++  This experimental feature is also backported to 2.4.20
++- Interoperability reports with other OS's would be useful.
++- v1.0.3 of nfs-utils supports the newer 2.6 kernels change
++  of kdev_t type. You can grab it at http://nfs.sourceforge.net
++- Problems to nfs at lists.sourceforge.net
++
++
++NTFS.
++~~~~~
++- A new, rewritten NTFS driver was merged for 2.6. It has the
++  following main benefits over the old driver:
++  - SMP and reentrant safe
++  - support bigger than 4 kB cluster sizes
++  - full support for sparse files on W2K/XP/W2K3
++  - mmap() support
++  - More stable, and much faster than the previous NTFS driver.
++  - Still read-only, but with safe file overwrite support without changes
++  to the file size
++  - More information is available at http://linux-ntfs.sf.net
++
++
++sysfs.
++~~~~~~
++In simple terms, the sysfs filesystem is a saner way for
++drivers to export their innards than /proc.
++This filesystem is always compiled in, and can be mounted
++just like another virtual filesystem. No userspace tools
++beyond cat(1) and echo(1) are needed. tree(1) is also good for
++viewing its overall structure.
++
++    mount -t sysfs none /sys
++
++See Documentation/filesystems/sysfs.txt for more info.
++
++
++JFS.
++~~~~
++IBM's JFS was merged for 2.6. (And backported to 2.4.20, but
++it was still a new feature here first. You can read more about JFS at
++http://www-124.ibm.com/developerworks/oss/jfs/index.html
++
++
++XFS.
++~~~~
++The SGI XFS filesystem has been merged, and has a number of userspace
++features. Users are encouraged to read http://oss.sgi.com/projects/xfs
++for more information.
++The various utilities for creating and manipulating XFS volumes can
++be found on SGI's ftp server:
++ftp://oss.sgi.com/projects/xfs/download/download/cmd_tars/xfsprogs-2.5.4.src.tar.gz
++
++
++CIFS.
++~~~~~
++Support utilities and documentation for the common internet file system (CIFS)
++can be found at http://us1.samba.org/samba/Linux_CIFS_client.html
++
++
++FAT.
++~~~~
++CVF (Compressed VFAT) support has been removed. This means you
++will no longer be able to access DriveSpace partitions.
++
++
++HugeTLBfs.
++~~~~~~~~~~
++Files in this filesystem are backed by large pages if the CPU
++supports them. See Documentation/vm/hugetlbpage.txt for more details.
++
++
++Internal filesystems.
++~~~~~~~~~~~~~~~~~~~~~
++/proc/filesystems will contain several filesystems that are not
++mountable in userspace, but are used internally by the kernel
++to keep track of things. Amongst these filesystems are futexfs 
++and eventpollfs.
++
++
++Kernel Asynchronous I/O (AIO) Support
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++Support for kernel AIO has been included in 2.6. 
++
++AIO enables even a single application thread to overlap I/O 
++operations with other processing, by providing an interface
++for submitting one or more i/o requests in one system call
++(io_submit) without waiting for completion, and a separate 
++interface (io_getevents) to reap completed i/o operations
++associated with a given completion group.
++
++The following is a quick summary of what works today as 
++expected:
++- AIO read and write on raw (and O_DIRECT on blockdev)
++- AIO read and write on files opened with O_DIRECT on
++  ext2, ext3, jfs, xfs
++
++And what doesn't work as expected or is not currently 
++supported:
++- AIO read and write on files opened without O_DIRECT
++  (i.e. normal buffered filesystem AIO). On ext2, ext3,
++  jfs, xfs and nfs, these do not return an explicit
++  error, but quietly default to synchronous or rather 
++  non-AIO behaviour (i.e io_submit waits for i/o to complete 
++  in these cases). For most other filesystems, -EINVAL is 
++  reported.
++- AIO fsync (not supported for any filesystem)
++- AIO read and write on sockets (doesn't return an
++  explicit error, but quietly defaults to synchronous
++  or rather non-AIO behaviour)
++
++You need to install libaio-0.3.92 (available at 
++http://www.kernel.org/pub/linux/kernel/people/bcrl/aio/) 
++if you are writing AIO applications which use the native 
++AIO interfaces.
++
++More info is available at http://lse.sf.net/io/aio.html
++
++
++Profiling.
++~~~~~~~~~~
++- A system wide performance profiler (Oprofile) has been included in 2.6.
++  With this option compiled in, you'll get an oprofilefs filesystem
++  which you can mount, that the userspace utilities talk to.
++  You can find out more at http://oprofile.sf.net/
++- You need a fixed readprofile utility for 2.6.
++  Present in util-linux as of 2.11z
++
++
++
++Improved BIOS table support.
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++- Linux now supports various new BIOS extensions.
++
++
++Simple boot flag support.
++~~~~~~~~~~~~~~~~~~~~~~~~~
++The SBF specification is an x86 BIOS extension that allows improved
++system boot speeds. It does this by marking a CMOS field to say
++"I booted okay, skip extensive POST next reboot".
++Userspace tool is at http://www.codemonkey.org.uk/projects/sbf/sbf.c
++More info on SBF is at http://www.microsoft.com/hwdev/resources/specs/simp_bios.asp
++
++
++EDD Support.
++~~~~~~~~~~~~
++- Support for BIOS Enhanced Disk Drive Services (EDD) was added,
++  which exports information on what the BIOS thinks is the boot
++  drive and other useful info to /sys/firmware/edd
++- Matt Domsch is interested in hearing success/fails on this code
++  with some simple tests decribed at http://domsch.com/linux/edd30/results.html
++
++
++Improved system monitoring.
++~~~~~~~~~~~~~~~~~~~~~~~~~~~
++- lm_sensors.
++  - Shipped in vendors kernels for years, lm_sensors is now part of mainline.
++    It does however have a different interface. (/sysfs instead of /proc
++  - http://www.xs4all.nl/~thospel/ASIS/bin/psensors is a handy script
++    for parsing the new sysfs fields.
++- IPMI. (Intelligent Platform Management Interface)
++  - IPMI is a standard for monitoring the hardware in a system.
++  - Project home page: http://openipmi.sourceforge.net
++  - Specification: http://www.intel.com/design/servers/ipmi/spec.htm
++
++
++x86 CPU detection.
++~~~~~~~~~~~~~~~~~~
++- The CPU detection code got a pretty hefty shake up. To be certain your
++  CPU has all relevant workarounds applied, be sure to check that it was
++  detected correctly. cat /proc/cpuinfo will tell what the kernel thinks it is.
++- Likewise, the x86 MTRR driver got a considerable makeover.
++  Check that XFree86 sets up MTRRs in the same way it did in 2.4
++  (Failures will get logged in /var/log/XFree86.log)
++- Early PII Xeon processors and possibly other early PII processors
++  require microcode updates either from the BIOS or the microcode driver
++  to work around CPU bugs the O(1) scheduler exposes.
++  You can find the relevant microcode tools at
++  http://www.urbanmyth.org/microcode/
++- Any regressions in both should go to mochel at osdl.org Cc: davej at codemonkey.org.uk
++
++
++Extra tainting.
++~~~~~~~~~~~~~~~
++Running certain AMD processors in SMP boxes is out of spec, and will taint
++the kernel with the 'S' flag.  Running 2 Athlon XPs for example may seem to
++work fine, but may also introduce difficult to pin down bugs.
++In time it's likely this tainting will be extended to cover other out of
++spec cases.
++
++Additionally, the new modules interface will taint the kernel if you try
++to 'force' a module to load with insmod -f.
++
++
++Power management.
++~~~~~~~~~~~~~~~~~
++- 2.6 contains a more up to date snapshot of the ACPI driver. Should
++  you experience any problems booting, try booting with the argument
++  "acpi=off" to rule out any ACPI interaction. ACPI has a much more involved
++  role in bringing the system up in 2.6 than it did in 2.4
++- The old "acpismp=force" boot option is now obsolete, and will be ignored
++  due to the old "mini ACPI" parser being removed.
++- software suspend is still in development, and in need of more work.
++  Use with SMP and/or PREEMPT not advised.
++- The ACPI code will do basic sanity checks on the DMI structure in the BIOS
++  to determine the date it was written. BIOSes older than year 2000 are
++  assumed to be broken. In some circumstances, this assumption is wrong.
++  If you see a message saying ACPI is disabled for this reason, try booting
++  with acpi=force. If things work fine, send the output of dmidecode
++  (http://www.nongnu.org/dmidecode/) to acpi-devel at lists.sf.net
++  with an explanation of why your BIOS shouldn't be blacklisted.
++
++CPU frequency scaling.
++~~~~~~~~~~~~~~~~~~~~~~
++Certain processors have the facility to scale their voltage/clockspeed.
++2.6 introduces an interface to this feature, see Documentation/cpufreq
++for more information. This functionality also covers features like
++Intel's speedstep, and the Powernow! feature present in mobile AMD Athlons.
++In addition to x86 variants, this framework also supports various ARM CPUs.
++You can find a userspace daemon that monitors battery life and
++adjusts accordingly at: http://sourceforge.net/projects/cpufreqd
++
++
++Background polling of MCE.
++~~~~~~~~~~~~~~~~~~~~~~~~~~
++The machine check handler has been extended so that it regularly polls
++for any problems on AMD Athlon, and Intel Pentium 4 systems.
++This may result in machine check exceptions occuring more frequently
++than they did in 2.4 on out of spec systems (Overclocking/inadequate
++cooling/underated PSU etc..).
++
++
++LVM2 - DeviceMapper.
++~~~~~~~~~~~~~~~~~~~~
++The LVM1 code was removed wholesale, and replaced with a much better
++designed 'device mapper'.
++- This is backwards compatible with the LVM1 disk format.
++- Device mapper does require new tools to manage volumes however.
++  You can get these from ftp://ftp.sistina.com/pub/LVM2/tools/
++
++
++Debugging options.
++~~~~~~~~~~~~~~~~~~
++During the stabilising period, it's likely that the debugging options
++in the kernel hacking menu will trigger quite a few problems.
++Please report any of these problems to linux-kernel at vger.kernel.org
++rather than just disabling the relevant CONFIG_ options.
++
++Merging of kksymoops means that the kernel will now spit out
++automatically decoded oopses (no more feeding them to ksymoops).
++For this reason, you should always enable the option in the
++kernel hacking menu labelled "Load all symbols for debugging/kksymoops".
++
++Testing with CONFIG_PREEMPT will also increase the amount of debug
++code that gets enabled in the kernel. Kernel preemption gives us
++the ability to do a whole slew of debugging checks like sleeping
++with locks held, scheduling while atomic, exiting with locks held, etc.
++
++
++Compiler issues.
++~~~~~~~~~~~~~~~~
++- The recommended compiler (for x86) is still 2.95.3.
++- When compiled with a modern gcc (Ie gcc 3.x), 2.6 will use additional
++  optimisations that 2.4 didn't. This may shake out compiler bugs that
++  2.4 didn't expose.
++- Do not use gcc 3.0.x on x86 due to a stack pointer handling bug.
++- gcc 2.96 is not supported with CONFIG_FRAME_POINTER=y due to a stack
++  pointer handling bug.
++
++
++Security concerns.
++~~~~~~~~~~~~~~~~~~
++Several security issues solved in 2.4 may not yet be forward ported
++to 2.6. For this reason 2.6.x kernels should not be tested on
++untrusted systems.  Testing known 2.4 exploits and reporting results
++is useful.
++
++SELinux.
++~~~~~~~~
++NSA Security-Enhanced Linux (SELinux) was merged in 2.6.
++SELinux defaults to not being config'd in.  If you
++config it in it defaults to enabled.  If you also config the bootparam
++you can use that param to disable it, otherwise selinux=1 is redundant
++as that's the default.
++
++You can obtain SELinux tools and an example policy configuration from
++http://www.nsa.gov/selinux
++
++
++
++Networking.
++~~~~~~~~~~~
++- ebtables
++  The bridging firewall code was merged. To manage these you'll
++  need the ebtables tool available from
++  http://users.pandora.be/bart.de.schuymer/ebtables/
++  More on bridge-nf can be found at http://bridge.sourceforge.net
++- Bridged packets can now be 'seen' by iptables.
++- IPSec
++  Linux finally has IPSec support in mainline.  Use the KAME tools port on
++  http://sourceforge.net/projects/ipsec-tools
++  For more info see http://www.lib.uaa.alaska.edu/linux-kernel/archive/2002-Week-44/1127.html
++  Also Bert Hubert has a howto at http://lartc.org/howto/lartc.ipsec.html
++  Additionally, ipsec-utils is at http://sourceforge.net/projects/ipsec-tools
++  Herbert Xu also has patches against FreeSWAN 2.00 to allow its userspace
++  to use the 2.6 IPSec functionality. They can be downloaded from
++  http://gondor.apana.org.au/~herbert/freeswan/
++  An additional HOWTO is at http://www.ipsec-howto.org
++- Some applications may trigger the kernel to spit out warnings about
++  'process xxx using obsolete setsockopt SO_BSDCOMPAT' .
++  - Bind 9.2.2 checks for #ifdef SO_BSDCOMPAT in <asm/socket.h> correctly,
++    so a recompile is all that is needed.
++  - bind9-host from debian testing triggers, though the 'host' package doesn't.
++  - process `snmpd' is using obsolete setsockopt SO_BSDCOMPAT
++  - process `snmptrapd' is using obsolete setsockopt SO_BSDCOMPAT
++  - ntop uses obsolete (PF_INET,SOCK_PACKET)
++- Users of boxes with >1 NIC may find that for eg, eth0 and eth1 refer to
++  the opposites of what they did in 2.4.   This is a bug that will be fixed
++  before 2.6.0.  One option (or management workaround) for this is to use
++  'nameif' to name Ethernet interfaces.  There is a HOWTO for doing this at
++  <http://xenotime.net/linux/doc/network-interface-names.txt>
++- Support for various new RFCs.
++  - RFC3173 (IP Payload Compression).
++  - RFC3041 (IPv6 Privacy Extensions).
++  - RFC2473 (IPv6 in IPv6 tunnels).
++  - RFC2960 (SCTP - see below).
++- Linux reaches congestion collapse when subjected to heavy network load.
++  NAPI fixes this amongst other things and therefore improving network
++  performance.
++  More info at http://www.cyberus.ca/~hadi/usenix-paper.tgz and
++  ftp://robur.slu.se/pub/Linux/net-development/NAPI/
++- IPVS (IP Virtual Server)
++  http://www.linuxvirtualserver.org/
++- RFC 2960 - SCTP (Stream Control Transmission Protocol)
++  SCTP is an IP based, message oriented reliable transport protocol with
++  congestion control, support for transparent multi-homing and multiple
++  ordered streams of messages. RFC2960 defines the core protocol.
++  More information about the protocol can be found at
++    http://www.ietf.org/rfc/rfc2960.txt
++  and about the Linux kernel implementation at
++    http://lksctp.sourceforge.net
++- ANSI/IEEE 802.2 LLC type 2 Support
++  Full implementation of LLC 1 and 2 stack, used by Appletalk, IPX and Token
++  Ring, also needed for the out of the tree, not yet functional NetBEUI
++  stack and for the for Linux SNA.
++                                                                                
++  This is based on the stack released under the GPL by Procom Inc. for the
++  2.0.30 Linux kernel.
++
++
++Crypto
++~~~~~~
++- A generic crypto API has been merged, offering support for various
++  algorithms (HMAC,MD4,MD5,SHA-1,SHA256,SHA384,SHA512,DES,Triple DES EDE,
++  Blowfish, Twofish, Serpent, AES, CAST5, CAST6)
++
++- This functionality is used by IPSec and the crypto-loop.  It's possible
++  that it will later also be available for use in userspace through a crypto
++  device, possibly compatible with the OpenBSD crypto userspace.
++
++- The in-kernel loopback device can now do crypto using the CryptoAPI.
++  May need new userspace tools.
++
++- A 2.4->2.6 cryptoloop migration guide is at http://clemens.endorphin.org/Cryptoloop_Migration_Guide.html
++
++Ports.
++~~~~~~
++- 2.6 features support for several new architectures.
++  - x86-64 (AMD Hammer)
++  - ppc64
++  - UML (User mode Linux)
++    See http://user-mode-linux.sf.net for more information.
++  - uCLinux: m68k(w/o MMU), h8300 and v850.  sh also added a uCLinux option.
++- The 64 bit s390x port was collapsed into a single port, appearing
++  as a config option in the base s390 arch.
++- In the opposite direction, arm26 was split out from arm.
++- x86 architecture also got 'subarch' support to support 'strange' x86
++  boxes (usually big boy toys). Currently supported subarchs include
++  - ES7000
++  - PC9800 (incomplete merge)
++  - VISWS (Was in 2.4, but now maintained again)
++  - Voyager. (http://www.hansenpartnership.com/voyager/)
++
++
++- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
++Revision history:
++0.48 - gadgetfs
++       cryptoloop howto URL.
++       Mailing list pointers.
++0.47 - Add futex paper URL.
++       Correct libc-alpha mailing list.
++       Jeff Garzik shouldn't get IRQ routing problems
++       Clarify syslinux necessity for boot disks.
++       Add depmod to common gotchas
++       Add EFS regression
++       Add mkinitrd note to modules section.
++       Various grammar cleanups
++       Mention tree(1) in sysfs section
++       SELinux corrections.
++       Duh, numerical sysctls are deprecated not syscalls.
++       Document seperate build dir feature.
++       /proc/stat changes broke more than just DOTS.
++       Add Japanese keyboard issue to input section.
++0.46 - Update akpm's email address.
++       Mention LLC in the networking section.
++       Added link to 2.6 migration guide.
++0.45 - DEVFS is obsolete.
++       Add pt_BR translation.
++0.44 - lm_sensors.
++       x86 subarch support.
++       Add link to Joseph Pranevich's 2.6 doc.
++       Mention chattr +S
++       Update dmidecode URL
++       Fix sbf.c URL
++       Fix typos (s/proprietory/proprietary/)
++       add URL to patched cdda2wav.
++       Mention which filesystems does 2.6 actually supports.
++       Add a small note about SELinux
++       Add a few more RFCs which we now support in the Networking section
++       Change IPVS to IPVS (IP Virtual Server)
++       Mention additional encryption algorithms that crypto api supports
++       Add a few things to TODO section
++       Add URL to AIO.
++       Polish translation URL added.
++       Fix up a stray davej at suse.de that I missed.
++       Update spanish translation URL.
++0.43 - oprofile URL changed.
++       Update Linus' email       
++       Drop report of buggy Red Hat 3.2.2-5 gcc.
++       Remove reference to Jens' hacked cdrecord, standard version is now ok.
++       PC Speaker note added.
++       Mention elevator=deadline for database folks.
++       Merge two deprecated sections.
++       Update URL to xfsprogs.
++       Mention Conectiva module-init-tools
++       Mention acpi=force, and DMI blacklist.
++       DRI CFT on X4.1
++       Pentium Pro SYSENTER is broken.
++       Update Alans list of IDE bugs
++       Add geometry translator workarounds.
++       Mention swapfile limitations.
++       Update Reiserfs new features.
++       Move some features marked as 'deprecated' to 'removed'.
++       Add 'needs forward porting' section.
++       Pointer to synaptics touchpad driver webpage.
++       Update ipsec utils URL.
++       Mention usb-storage changes.
++       Modules are now .ko instead of .o
++       Mention how to change elevator on command line.
++       Document statfs64()
++       ext3 data=journal mode should now be fixed.
++       Fix iosched pathname.
++       Document USB changes.
++       Add SCTP to Networking.
++       s/2.5/2.6/ in most of the doc.
++       Mention AIO.
++       Add additional IPSEC howto URL.
++       Deprecate numeric sysctls
++0.42 - CONFIG_LOG_BUF_SHIFT is now sanity checked by Kconfig
++       Hyperthreading scheduler improvements.
++       ALSA OSS emulation.
++       32bit uids in new quota.
++       Not all filesystems support nanosecond stat.
++       Note that NTFS still isn't R/W
++       Mention CryptoLoop.
++0.41 - V=0 is now default. Document V=1
++       s/Redhat/Red Hat/ everywhere.
++       Added vmware sysenter note.
++       MTRR for vesafb
++       Various grammar fixes.
++       Selectable elevators.
++       PCI domains
++0.40 - Callout tty devices are removed.
++       Added note about modules in Red Hat 9
++0.39 - irqbalance note added.
++       Added ntop, snmp tools obsolete messages.
++       Added link to David Mosberger's O(1) page.
++       Mention Herbert Xu's FreeSWAN patches.
++       Add CONFIG_VGA_CONSOLE to the list of gotchas.
++       Add note about 2.4 .config's to gotchas.
++       Reword devpts note.
++0.38 - Fixed URL to nameif
++0.37 - devfs users now need to mount devpts.
++       mention h8300 port.    
++       mentioned NTFS rewrite.
++0.36 - Include Doug Gilberts 'positive SCSI spin'.
++       Mention NAPI.
++       Reword the CPU bug workaround that the O(1) scheduler exposes.
++       Added 'Known Gotchas' section
++0.35 - Note about KDE panel applets.
++       mount --move, dmask, fmask
++       Removed note about oprofile utilities being underdeveloped.
++       Mention ext2 locking, and ext2/ext3 orlov allocator.
++0.34 - Remove people.redhat.com NPTL URLs on Ulrich Dreppers request.
++       Added note about s390x going away.
++       Various kbuild updates.
++       Note about swap files.
++       Added note about -p1 vs -p0
++       Lots of typo fixes from Randy Dunlap.
++       RPM from RH9 seems to have problems.
++0.33 - Networking RFCs section added.
++0.32 - Added Soundmodem userspace replacement URL.
++0.31 - ext3 data=journal breakage noted.
++0.30 - Athlon powernow is now supported.
++0.29 - Mention NIC renumbering and ACPI/APIC NIC bugs. 
++0.28 - SO_BSDCOMPAT obsolete messages, nfsutils.
++0.27 - radeon -> radeonfb
++0.26 - Added info about readprofile.
++0.25 - Added cdrecord example. Added URL to Spanish translation.
++0.1->0.24 - Unrecorded history
++
++- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
++Other Links.
++http://www.kernelnewbies.org/status/
++http://bugzilla.kernel.org/
++http://www.kniggit.net/wwol26.html
++http://thomer.com/linux/migrate-to-2.6.html
++
++
++TODO:  (Please mail me a few lines about these if you are
++         the owner of these).
++
++ PCI IDs (new_id, agpgart try_unsupported)
++ libsysfs
++ kdev_t changes?
++ ISDN rewrite?
++ AFS
++ DVB
++ Hangcheck timer
++ /proc/sysrq-trigger
++ libata
++ initramfs ?
++

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-blacklist-toshiba.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-blacklist-toshiba.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-blacklist-toshiba.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,21 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: blacklist "TOSHIBA CD-ROM XM-1702BC" in drivers/ide/ide-dma.c
+## DP: Patch author: unknown
+## DP: Upstream status: not submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- kernel-source-2.6.6/drivers/ide/ide-dma.c	2004-04-05 19:49:28.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/ide/ide-dma.c	2004-04-05 20:54:34.000000000 +1000
+@@ -125,6 +125,7 @@
+ 	{ "HITACHI CDR-8335"	,	"ALL"		},
+ 	{ "HITACHI CDR-8435"	,	"ALL"		},
+ 	{ "Toshiba CD-ROM XM-6202B"	,	"ALL"		},
++	{ "TOSHIBA CD-ROM XM-1702BC"	,	"ALL"		},
+ 	{ "CD-532E-A"		,	"ALL"		},
+ 	{ "E-IDE CD-ROM CR-840",	"ALL"		},
+ 	{ "CD-ROM Drive/F5A",	"ALL"		},

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-ricoh.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-ricoh.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-ide-dma-ricoh.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,21 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: bogus blacklist RICOH CD-R/RW MP7083A
+## DP: Patch author: Srihari Vijayaraghavan <sriharivijayaraghavan at yahoo.com.au>
+## DP: Upstream status: backport 2.6.10-rc2
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- a/drivers/ide/ide-dma.c	2004-11-18 11:37:48 -08:00
++++ b/drivers/ide/ide-dma.c	2004-11-18 11:37:48 -08:00
+@@ -129,7 +129,6 @@
+ 	{ "CD-532E-A"		,	"ALL"		},
+ 	{ "E-IDE CD-ROM CR-840",	"ALL"		},
+ 	{ "CD-ROM Drive/F5A",	"ALL"		},
+-	{ "RICOH CD-R/RW MP7083A",	"ALL"		},
+ 	{ "WPI CDD-820",		"ALL"		},
+ 	{ "SAMSUNG CD-ROM SC-148C",	"ALL"		},
+ 	{ "SAMSUNG CD-ROM SC-148F",	"ALL"		},

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-input-psaux-hacks.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-input-psaux-hacks.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-input-psaux-hacks.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,53 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: add INPUT_MOUSEDEV_PSAUX_ENABLE
+## DP: Patch author: Herbert Xu
+## DP: Upstream status: not submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- kernel-source-2.6.6/drivers/input/Kconfig	2004-03-11 13:55:22.000000000 +1100
++++ kernel-source-2.6.6-1/drivers/input/Kconfig	2004-01-27 21:05:58.000000000 +1100
+@@ -65,6 +65,11 @@
+ 	  screen resolution you are using to correctly scale the data. If
+ 	  you're not using a digitizer, this value is ignored.
+ 
++config INPUT_MOUSEDEV_PSAUX_ENABLE
++	bool "Enable /dev/psaux device by default"
++	default y
++	depends on INPUT_MOUSEDEV_PSAUX
++
+ config INPUT_JOYDEV
+ 	tristate "Joystick interface"
+ 	depends on INPUT
+--- kernel-source-2.6.6/drivers/input/mousedev.c	2004-03-11 13:55:44.000000000 +1100
++++ kernel-source-2.6.6-1/drivers/input/mousedev.c	2004-02-05 20:20:54.000000000 +1100
+@@ -47,6 +47,16 @@
+ module_param(yres, uint, 0);
+ MODULE_PARM_DESC(yres, "Vertical screen resolution");
+ 
++#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
++#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX_ENABLE
++#define psaux 1
++#else
++static int psaux;
++module_param(psaux, uint, 0);
++MODULE_PARM_DESC(psaux, "Enable legacy /dev/psaux interface");
++#endif
++#endif
++
+ struct mousedev {
+ 	int exist;
+ 	int open;
+@@ -572,7 +582,7 @@
+ 				NULL, "mice");
+ 
+ #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
+-	if (!(psaux_registered = !misc_register(&psaux_mouse)))
++	if (psaux && !(psaux_registered = !misc_register(&psaux_mouse)))
+ 		printk(KERN_WARNING "mice: could not misc_register the device\n");
+ #endif
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-8139too-locking.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-8139too-locking.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-8139too-locking.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,78 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: fix deadlock on shutdown in drivers/net/8139too.c
+## DP: Patch author: Herbert Xu
+## DP: Upstream status: discussed with viro and jgarzik, probably wants an
+## DP: Upstream status: interruptible rtnl_lock variant
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- kernel-source-2.6.6/drivers/net/8139too.c	2004-05-10 19:47:54.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/net/8139too.c	2004-05-10 22:21:32.000000000 +1000
+@@ -112,6 +112,7 @@
+ #include <linux/crc32.h>
+ #include <linux/suspend.h>
+ #include <asm/io.h>
++#include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+ #include <asm/irq.h>
+ 
+@@ -590,6 +591,7 @@
+ 	struct rtl_extra_stats xstats;
+ 	int time_to_die;
+ 	struct mii_if_info mii;
++	struct semaphore mdio_sem;
+ 	unsigned int regs_len;
+ };
+ 
+@@ -1025,6 +1027,7 @@
+ 	tp->mii.mdio_write = mdio_write;
+ 	tp->mii.phy_id_mask = 0x3f;
+ 	tp->mii.reg_num_mask = 0x1f;
++	init_MUTEX (&tp->mdio_sem);
+ 
+ 	/* dev is fully set up and ready to use now */
+ 	DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
+@@ -1633,9 +1636,10 @@
+ 		if (tp->time_to_die)
+ 			break;
+ 
+-		rtnl_lock ();
++		if (down_interruptible (&tp->mdio_sem))
++			break;
+ 		rtl8139_thread_iter (dev, tp, tp->mmio_addr);
+-		rtnl_unlock ();
++		up (&tp->mdio_sem);
+ 	}
+ 
+ 	complete_and_exit (&tp->thr_exited, 0);
+@@ -2221,9 +2225,9 @@
+ 		ret = kill_proc (tp->thr_pid, SIGTERM, 1);
+ 		if (ret) {
+ 			printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
+-			return ret;
++		} else {
++			wait_for_completion (&tp->thr_exited);
+ 		}
+-		wait_for_completion (&tp->thr_exited);
+ 	}
+ 	
+ 	if (netif_msg_ifdown(tp))
+@@ -2464,10 +2468,14 @@
+ 	if (!netif_running(dev))
+ 		return -EINVAL;
+ 
++	if (down_interruptible (&np->mdio_sem))
++		return -ERESTARTSYS;
++
+ 	spin_lock_irq(&np->lock);
+ 	rc = generic_mii_ioctl(&np->mii, if_mii(rq), cmd, NULL);
+ 	spin_unlock_irq(&np->lock);
+ 
++	up (&np->mdio_sem);
+ 	return rc;
+ }
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-tg3-readd.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-tg3-readd.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-net-tg3-readd.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,8000 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: re-add tg3.c with firmware loading support
+## DP: Patch author: Nathaneal Nerode, Jens Schmalzing
+## DP: Upstream status: rejected
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- orig/drivers/net/Kconfig	2004-08-14 03:27:18.000000000 -0400
++++ mod/drivers/net/Kconfig	2004-08-14 03:27:34.000000000 -0400
+@@ -2125,6 +2125,7 @@
+ config TIGON3
+ 	tristate "Broadcom Tigon3 support"
+ 	depends on PCI
++	select FW_LOADER
+ 	help
+ 	  This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
+ 
+--- orig/drivers/net/tg3.c	2004-08-12 14:33:47.000000000 -0400
++++ mod/drivers/net/tg3.c	2004-08-14 03:25:04.000000000 -0400
+@@ -0,0 +1,7976 @@
++/*
++ * tg3.c: Broadcom Tigon3 ethernet driver.
++ *
++ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem at redhat.com)
++ * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik at pobox.com)
++ * Copyright (C) 2004 Sun Microsystems Inc.
++ * Portions copyright 2004 Nathanael Nerode  <neroden at gcc.gnu.org>
++ */
++
++#include <linux/config.h>
++
++#include <linux/module.h>
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/compiler.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/if_vlan.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/workqueue.h>
++
++#include <linux/firmware.h>
++
++#include <net/checksum.h>
++
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/byteorder.h>
++#include <asm/uaccess.h>
++
++#ifdef CONFIG_SPARC64
++#include <asm/idprom.h>
++#include <asm/oplib.h>
++#include <asm/pbm.h>
++#endif
++
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++#define TG3_VLAN_TAG_USED 1
++#else
++#define TG3_VLAN_TAG_USED 0
++#endif
++
++#ifdef NETIF_F_TSO
++#define TG3_TSO_SUPPORT	1
++#else
++#define TG3_TSO_SUPPORT	0
++#endif
++
++#include "tg3.h"
++
++#define DRV_MODULE_NAME		"tg3"
++#define PFX DRV_MODULE_NAME	": "
++#define DRV_MODULE_VERSION	"3.8"
++#define DRV_MODULE_RELDATE	"July 14, 2004"
++
++#define TG3_DEF_MAC_MODE	0
++#define TG3_DEF_RX_MODE		0
++#define TG3_DEF_TX_MODE		0
++#define TG3_DEF_MSG_ENABLE	  \
++	(NETIF_MSG_DRV		| \
++	 NETIF_MSG_PROBE	| \
++	 NETIF_MSG_LINK		| \
++	 NETIF_MSG_TIMER	| \
++	 NETIF_MSG_IFDOWN	| \
++	 NETIF_MSG_IFUP		| \
++	 NETIF_MSG_RX_ERR	| \
++	 NETIF_MSG_TX_ERR)
++
++/* length of time before we decide the hardware is borked,
++ * and dev->tx_timeout() should be called to fix the problem
++ */
++#define TG3_TX_TIMEOUT			(5 * HZ)
++
++/* hardware minimum and maximum for a single frame's data payload */
++#define TG3_MIN_MTU			60
++#define TG3_MAX_MTU(tp)	\
++	((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && \
++	  GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) ? 9000 : 1500)
++
++/* These numbers seem to be hard coded in the NIC firmware somehow.
++ * You can't change the ring sizes, but you can change where you place
++ * them in the NIC onboard memory.
++ */
++#define TG3_RX_RING_SIZE		512
++#define TG3_DEF_RX_RING_PENDING		200
++#define TG3_RX_JUMBO_RING_SIZE		256
++#define TG3_DEF_RX_JUMBO_RING_PENDING	100
++
++/* Do not place this n-ring entries value into the tp struct itself,
++ * we really want to expose these constants to GCC so that modulo et
++ * al.  operations are done with shifts and masks instead of with
++ * hw multiply/modulo instructions.  Another solution would be to
++ * replace things like '% foo' with '& (foo - 1)'.
++ */
++#define TG3_RX_RCB_RING_SIZE(tp)	\
++	((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || \
++	  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ? \
++	 512 : 1024)
++
++#define TG3_TX_RING_SIZE		512
++#define TG3_DEF_TX_RING_PENDING		(TG3_TX_RING_SIZE - 1)
++
++#define TG3_RX_RING_BYTES	(sizeof(struct tg3_rx_buffer_desc) * \
++				 TG3_RX_RING_SIZE)
++#define TG3_RX_JUMBO_RING_BYTES	(sizeof(struct tg3_rx_buffer_desc) * \
++			         TG3_RX_JUMBO_RING_SIZE)
++#define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \
++			           TG3_RX_RCB_RING_SIZE(tp))
++#define TG3_TX_RING_BYTES	(sizeof(struct tg3_tx_buffer_desc) * \
++				 TG3_TX_RING_SIZE)
++#define TX_RING_GAP(TP)	\
++	(TG3_TX_RING_SIZE - (TP)->tx_pending)
++#define TX_BUFFS_AVAIL(TP)						\
++	(((TP)->tx_cons <= (TP)->tx_prod) ?				\
++	  (TP)->tx_cons + (TP)->tx_pending - (TP)->tx_prod :		\
++	  (TP)->tx_cons - (TP)->tx_prod - TX_RING_GAP(TP))
++#define NEXT_TX(N)		(((N) + 1) & (TG3_TX_RING_SIZE - 1))
++
++#define RX_PKT_BUF_SZ		(1536 + tp->rx_offset + 64)
++#define RX_JUMBO_PKT_BUF_SZ	(9046 + tp->rx_offset + 64)
++
++/* minimum number of free TX descriptors required to wake up TX process */
++#define TG3_TX_WAKEUP_THRESH		(TG3_TX_RING_SIZE / 4)
++
++/* number of ETHTOOL_GSTATS u64's */
++#define TG3_NUM_STATS		(sizeof(struct tg3_ethtool_stats)/sizeof(u64))
++
++static char version[] __devinitdata =
++	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
++
++MODULE_AUTHOR("David S. Miller (davem at redhat.com) and Jeff Garzik (jgarzik at pobox.com)");
++MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
++MODULE_LICENSE("GPL");
++MODULE_PARM(tg3_debug, "i");
++MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
++
++static int tg3_debug = -1;	/* -1 == use TG3_DEF_MSG_ENABLE as value */
++
++static struct pci_device_id tg3_pci_tbl[] = {
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3,
++	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++	{ 0, }
++};
++
++MODULE_DEVICE_TABLE(pci, tg3_pci_tbl);
++
++struct {
++	char string[ETH_GSTRING_LEN];
++} ethtool_stats_keys[TG3_NUM_STATS] = {
++	{ "rx_octets" },
++	{ "rx_fragments" },
++	{ "rx_ucast_packets" },
++	{ "rx_mcast_packets" },
++	{ "rx_bcast_packets" },
++	{ "rx_fcs_errors" },
++	{ "rx_align_errors" },
++	{ "rx_xon_pause_rcvd" },
++	{ "rx_xoff_pause_rcvd" },
++	{ "rx_mac_ctrl_rcvd" },
++	{ "rx_xoff_entered" },
++	{ "rx_frame_too_long_errors" },
++	{ "rx_jabbers" },
++	{ "rx_undersize_packets" },
++	{ "rx_in_length_errors" },
++	{ "rx_out_length_errors" },
++	{ "rx_64_or_less_octet_packets" },
++	{ "rx_65_to_127_octet_packets" },
++	{ "rx_128_to_255_octet_packets" },
++	{ "rx_256_to_511_octet_packets" },
++	{ "rx_512_to_1023_octet_packets" },
++	{ "rx_1024_to_1522_octet_packets" },
++	{ "rx_1523_to_2047_octet_packets" },
++	{ "rx_2048_to_4095_octet_packets" },
++	{ "rx_4096_to_8191_octet_packets" },
++	{ "rx_8192_to_9022_octet_packets" },
++
++	{ "tx_octets" },
++	{ "tx_collisions" },
++
++	{ "tx_xon_sent" },
++	{ "tx_xoff_sent" },
++	{ "tx_flow_control" },
++	{ "tx_mac_errors" },
++	{ "tx_single_collisions" },
++	{ "tx_mult_collisions" },
++	{ "tx_deferred" },
++	{ "tx_excessive_collisions" },
++	{ "tx_late_collisions" },
++	{ "tx_collide_2times" },
++	{ "tx_collide_3times" },
++	{ "tx_collide_4times" },
++	{ "tx_collide_5times" },
++	{ "tx_collide_6times" },
++	{ "tx_collide_7times" },
++	{ "tx_collide_8times" },
++	{ "tx_collide_9times" },
++	{ "tx_collide_10times" },
++	{ "tx_collide_11times" },
++	{ "tx_collide_12times" },
++	{ "tx_collide_13times" },
++	{ "tx_collide_14times" },
++	{ "tx_collide_15times" },
++	{ "tx_ucast_packets" },
++	{ "tx_mcast_packets" },
++	{ "tx_bcast_packets" },
++	{ "tx_carrier_sense_errors" },
++	{ "tx_discards" },
++	{ "tx_errors" },
++
++	{ "dma_writeq_full" },
++	{ "dma_write_prioq_full" },
++	{ "rxbds_empty" },
++	{ "rx_discards" },
++	{ "rx_errors" },
++	{ "rx_threshold_hit" },
++
++	{ "dma_readq_full" },
++	{ "dma_read_prioq_full" },
++	{ "tx_comp_queue_full" },
++
++	{ "ring_set_send_prod_index" },
++	{ "ring_status_update" },
++	{ "nic_irqs" },
++	{ "nic_avoided_irqs" },
++	{ "nic_tx_threshold_hit" }
++};
++
++static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
++{
++	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
++		unsigned long flags;
++
++		spin_lock_irqsave(&tp->indirect_lock, flags);
++		pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
++		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
++		spin_unlock_irqrestore(&tp->indirect_lock, flags);
++	} else {
++		writel(val, tp->regs + off);
++		if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0)
++			readl(tp->regs + off);
++	}
++}
++
++static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
++{
++	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
++		unsigned long flags;
++
++		spin_lock_irqsave(&tp->indirect_lock, flags);
++		pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
++		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
++		spin_unlock_irqrestore(&tp->indirect_lock, flags);
++	} else {
++		unsigned long dest = tp->regs + off;
++		writel(val, dest);
++		readl(dest);    /* always flush PCI write */
++	}
++}
++
++static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
++{
++	unsigned long mbox = tp->regs + off;
++	writel(val, mbox);
++	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
++		readl(mbox);
++}
++
++static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
++{
++	unsigned long mbox = tp->regs + off;
++	writel(val, mbox);
++	if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
++		writel(val, mbox);
++	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
++		readl(mbox);
++}
++
++#define tw32_mailbox(reg, val)  writel(((val) & 0xffffffff), tp->regs + (reg))
++#define tw32_rx_mbox(reg, val)  _tw32_rx_mbox(tp, reg, val)
++#define tw32_tx_mbox(reg, val)  _tw32_tx_mbox(tp, reg, val)
++
++#define tw32(reg,val)		tg3_write_indirect_reg32(tp,(reg),(val))
++#define tw32_f(reg,val)		_tw32_flush(tp,(reg),(val))
++#define tw16(reg,val)		writew(((val) & 0xffff), tp->regs + (reg))
++#define tw8(reg,val)		writeb(((val) & 0xff), tp->regs + (reg))
++#define tr32(reg)		readl(tp->regs + (reg))
++#define tr16(reg)		readw(tp->regs + (reg))
++#define tr8(reg)		readb(tp->regs + (reg))
++
++static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&tp->indirect_lock, flags);
++	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
++	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
++
++	/* Always leave this as zero. */
++	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
++	spin_unlock_irqrestore(&tp->indirect_lock, flags);
++}
++
++static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&tp->indirect_lock, flags);
++	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
++	pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
++
++	/* Always leave this as zero. */
++	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
++	spin_unlock_irqrestore(&tp->indirect_lock, flags);
++}
++
++static void tg3_disable_ints(struct tg3 *tp)
++{
++	tw32(TG3PCI_MISC_HOST_CTRL,
++	     (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
++	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
++	tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
++}
++
++static inline void tg3_cond_int(struct tg3 *tp)
++{
++	if (tp->hw_status->status & SD_STATUS_UPDATED)
++		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
++}
++
++static void tg3_enable_ints(struct tg3 *tp)
++{
++	tw32(TG3PCI_MISC_HOST_CTRL,
++	     (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
++	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
++	tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
++
++	tg3_cond_int(tp);
++}
++
++static inline void tg3_netif_stop(struct tg3 *tp)
++{
++	netif_poll_disable(tp->dev);
++	netif_tx_disable(tp->dev);
++}
++
++static inline void tg3_netif_start(struct tg3 *tp)
++{
++	netif_wake_queue(tp->dev);
++	/* NOTE: unconditional netif_wake_queue is only appropriate
++	 * so long as all callers are assured to have free tx slots
++	 * (such as after tg3_init_hw)
++	 */
++	netif_poll_enable(tp->dev);
++	tg3_cond_int(tp);
++}
++
++static void tg3_switch_clocks(struct tg3 *tp)
++{
++	u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
++	u32 orig_clock_ctrl;
++
++	orig_clock_ctrl = clock_ctrl;
++	clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN |
++		       CLOCK_CTRL_CLKRUN_OENABLE |
++		       0x1f);
++	tp->pci_clock_ctrl = clock_ctrl;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
++	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
++		tw32_f(TG3PCI_CLOCK_CTRL,
++		     clock_ctrl |
++		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
++		udelay(40);
++		tw32_f(TG3PCI_CLOCK_CTRL,
++		     clock_ctrl | (CLOCK_CTRL_ALTCLK));
++		udelay(40);
++	}
++	tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl);
++	udelay(40);
++}
++
++#define PHY_BUSY_LOOPS	5000
++
++static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
++{
++	u32 frame_val;
++	int loops, ret;
++
++	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
++		tw32_f(MAC_MI_MODE,
++		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
++		udelay(80);
++	}
++
++	*val = 0xffffffff;
++
++	frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
++		      MI_COM_PHY_ADDR_MASK);
++	frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
++		      MI_COM_REG_ADDR_MASK);
++	frame_val |= (MI_COM_CMD_READ | MI_COM_START);
++	
++	tw32_f(MAC_MI_COM, frame_val);
++
++	loops = PHY_BUSY_LOOPS;
++	while (loops-- > 0) {
++		udelay(10);
++		frame_val = tr32(MAC_MI_COM);
++
++		if ((frame_val & MI_COM_BUSY) == 0) {
++			udelay(5);
++			frame_val = tr32(MAC_MI_COM);
++			break;
++		}
++	}
++
++	ret = -EBUSY;
++	if (loops > 0) {
++		*val = frame_val & MI_COM_DATA_MASK;
++		ret = 0;
++	}
++
++	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
++		tw32_f(MAC_MI_MODE, tp->mi_mode);
++		udelay(80);
++	}
++
++	return ret;
++}
++
++static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
++{
++	u32 frame_val;
++	int loops, ret;
++
++	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
++		tw32_f(MAC_MI_MODE,
++		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
++		udelay(80);
++	}
++
++	frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
++		      MI_COM_PHY_ADDR_MASK);
++	frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
++		      MI_COM_REG_ADDR_MASK);
++	frame_val |= (val & MI_COM_DATA_MASK);
++	frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
++	
++	tw32_f(MAC_MI_COM, frame_val);
++
++	loops = PHY_BUSY_LOOPS;
++	while (loops-- > 0) {
++		udelay(10);
++		frame_val = tr32(MAC_MI_COM);
++		if ((frame_val & MI_COM_BUSY) == 0) {
++			udelay(5);
++			frame_val = tr32(MAC_MI_COM);
++			break;
++		}
++	}
++
++	ret = -EBUSY;
++	if (loops > 0)
++		ret = 0;
++
++	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
++		tw32_f(MAC_MI_MODE, tp->mi_mode);
++		udelay(80);
++	}
++
++	return ret;
++}
++
++static void tg3_phy_set_wirespeed(struct tg3 *tp)
++{
++	u32 val;
++
++	if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED)
++		return;
++
++	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007);
++	tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
++	tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4)));
++}
++
++static int tg3_bmcr_reset(struct tg3 *tp)
++{
++	u32 phy_control;
++	int limit, err;
++
++	/* OK, reset it, and poll the BMCR_RESET bit until it
++	 * clears or we time out.
++	 */
++	phy_control = BMCR_RESET;
++	err = tg3_writephy(tp, MII_BMCR, phy_control);
++	if (err != 0)
++		return -EBUSY;
++
++	limit = 5000;
++	while (limit--) {
++		err = tg3_readphy(tp, MII_BMCR, &phy_control);
++		if (err != 0)
++			return -EBUSY;
++
++		if ((phy_control & BMCR_RESET) == 0) {
++			udelay(40);
++			break;
++		}
++		udelay(10);
++	}
++	if (limit <= 0)
++		return -EBUSY;
++
++	return 0;
++}
++
++static int tg3_wait_macro_done(struct tg3 *tp)
++{
++	int limit = 100;
++
++	while (limit--) {
++		u32 tmp32;
++
++		tg3_readphy(tp, 0x16, &tmp32);
++		if ((tmp32 & 0x1000) == 0)
++			break;
++	}
++	if (limit <= 0)
++		return -EBUSY;
++
++	return 0;
++}
++
++static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
++{
++	static const u32 test_pat[4][6] = {
++	{ 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
++	{ 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
++	{ 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
++	{ 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
++	};
++	int chan;
++
++	for (chan = 0; chan < 4; chan++) {
++		int i;
++
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
++			     (chan * 0x2000) | 0x0200);
++		tg3_writephy(tp, 0x16, 0x0002);
++
++		for (i = 0; i < 6; i++)
++			tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
++				     test_pat[chan][i]);
++
++		tg3_writephy(tp, 0x16, 0x0202);
++		if (tg3_wait_macro_done(tp)) {
++			*resetp = 1;
++			return -EBUSY;
++		}
++
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
++			     (chan * 0x2000) | 0x0200);
++		tg3_writephy(tp, 0x16, 0x0082);
++		if (tg3_wait_macro_done(tp)) {
++			*resetp = 1;
++			return -EBUSY;
++		}
++
++		tg3_writephy(tp, 0x16, 0x0802);
++		if (tg3_wait_macro_done(tp)) {
++			*resetp = 1;
++			return -EBUSY;
++		}
++
++		for (i = 0; i < 6; i += 2) {
++			u32 low, high;
++
++			tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low);
++			tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high);
++			if (tg3_wait_macro_done(tp)) {
++				*resetp = 1;
++				return -EBUSY;
++			}
++			low &= 0x7fff;
++			high &= 0x000f;
++			if (low != test_pat[chan][i] ||
++			    high != test_pat[chan][i+1]) {
++				tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
++				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
++				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
++
++				return -EBUSY;
++			}
++		}
++	}
++
++	return 0;
++}
++
++static int tg3_phy_reset_chanpat(struct tg3 *tp)
++{
++	int chan;
++
++	for (chan = 0; chan < 4; chan++) {
++		int i;
++
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
++			     (chan * 0x2000) | 0x0200);
++		tg3_writephy(tp, 0x16, 0x0002);
++		for (i = 0; i < 6; i++)
++			tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
++		tg3_writephy(tp, 0x16, 0x0202);
++		if (tg3_wait_macro_done(tp))
++			return -EBUSY;
++	}
++
++	return 0;
++}
++
++static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
++{
++	u32 reg32, phy9_orig;
++	int retries, do_phy_reset, err;
++
++	retries = 10;
++	do_phy_reset = 1;
++	do {
++		if (do_phy_reset) {
++			err = tg3_bmcr_reset(tp);
++			if (err)
++				return err;
++			do_phy_reset = 0;
++		}
++
++		/* Disable transmitter and interrupt.  */
++		tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
++		reg32 |= 0x3000;
++		tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
++
++		/* Set full-duplex, 1000 mbps.  */
++		tg3_writephy(tp, MII_BMCR,
++			     BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
++
++		/* Set to master mode.  */
++		tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig);
++		tg3_writephy(tp, MII_TG3_CTRL,
++			     (MII_TG3_CTRL_AS_MASTER |
++			      MII_TG3_CTRL_ENABLE_AS_MASTER));
++
++		/* Enable SM_DSP_CLOCK and 6dB.  */
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
++
++		/* Block the PHY control access.  */
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
++		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800);
++
++		err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
++		if (!err)
++			break;
++	} while (--retries);
++
++	err = tg3_phy_reset_chanpat(tp);
++	if (err)
++		return err;
++
++	tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
++	tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000);
++
++	tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
++	tg3_writephy(tp, 0x16, 0x0000);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
++		/* Set Extended packet length bit for jumbo frames */
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4400);
++	}
++	else {
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
++	}
++
++	tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
++
++	tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
++	reg32 &= ~0x3000;
++	tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
++
++	return err;
++}
++
++/* This will reset the tigon3 PHY if there is no valid
++ * link unless the FORCE argument is non-zero.
++ */
++static int tg3_phy_reset(struct tg3 *tp)
++{
++	u32 phy_status;
++	int err;
++
++	err  = tg3_readphy(tp, MII_BMSR, &phy_status);
++	err |= tg3_readphy(tp, MII_BMSR, &phy_status);
++	if (err != 0)
++		return -EBUSY;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
++		err = tg3_phy_reset_5703_4_5(tp);
++		if (err)
++			return err;
++		goto out;
++	}
++
++	err = tg3_bmcr_reset(tp);
++	if (err)
++		return err;
++
++out:
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
++		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
++		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0323);
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
++	}
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_5704_A0_BUG) {
++		tg3_writephy(tp, 0x1c, 0x8d68);
++		tg3_writephy(tp, 0x1c, 0x8d68);
++	}
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_BER_BUG) {
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
++		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x310b);
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
++		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x9506);
++		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x401f);
++		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2);
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
++	}
++	/* Set Extended packet length bit (bit 14) on all chips that */
++	/* support jumbo frames */
++	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
++		/* Cannot do read-modify-write on 5401 */
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20);
++	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++		   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++		u32 phy_reg;
++
++		/* Set bit 14 with read-modify-write to preserve other bits */
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007);
++		tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg);
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000);
++	}
++	tg3_phy_set_wirespeed(tp);
++	return 0;
++}
++
++static void tg3_frob_aux_power(struct tg3 *tp)
++{
++	struct tg3 *tp_peer = tp;
++
++	if ((tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) != 0)
++		return;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
++		tp_peer = pci_get_drvdata(tp->pdev_peer);
++		if (!tp_peer)
++			BUG();
++	}
++
++
++	if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 ||
++	    (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) {
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
++			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
++			     (GRC_LCLCTRL_GPIO_OE0 |
++			      GRC_LCLCTRL_GPIO_OE1 |
++			      GRC_LCLCTRL_GPIO_OE2 |
++			      GRC_LCLCTRL_GPIO_OUTPUT0 |
++			      GRC_LCLCTRL_GPIO_OUTPUT1));
++			udelay(100);
++		} else {
++			if (tp_peer != tp &&
++			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
++				return;
++
++			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
++			     (GRC_LCLCTRL_GPIO_OE0 |
++			      GRC_LCLCTRL_GPIO_OE1 |
++			      GRC_LCLCTRL_GPIO_OE2 |
++			      GRC_LCLCTRL_GPIO_OUTPUT1 |
++			      GRC_LCLCTRL_GPIO_OUTPUT2));
++			udelay(100);
++
++			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
++			     (GRC_LCLCTRL_GPIO_OE0 |
++			      GRC_LCLCTRL_GPIO_OE1 |
++			      GRC_LCLCTRL_GPIO_OE2 |
++			      GRC_LCLCTRL_GPIO_OUTPUT0 |
++			      GRC_LCLCTRL_GPIO_OUTPUT1 |
++			      GRC_LCLCTRL_GPIO_OUTPUT2));
++			udelay(100);
++
++			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
++			     (GRC_LCLCTRL_GPIO_OE0 |
++			      GRC_LCLCTRL_GPIO_OE1 |
++			      GRC_LCLCTRL_GPIO_OE2 |
++			      GRC_LCLCTRL_GPIO_OUTPUT0 |
++			      GRC_LCLCTRL_GPIO_OUTPUT1));
++			udelay(100);
++		}
++	} else {
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
++		    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
++			if (tp_peer != tp &&
++			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
++				return;
++
++			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
++			     (GRC_LCLCTRL_GPIO_OE1 |
++			      GRC_LCLCTRL_GPIO_OUTPUT1));
++			udelay(100);
++
++			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
++			     (GRC_LCLCTRL_GPIO_OE1));
++			udelay(100);
++
++			tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
++			     (GRC_LCLCTRL_GPIO_OE1 |
++			      GRC_LCLCTRL_GPIO_OUTPUT1));
++			udelay(100);
++		}
++	}
++}
++
++static int tg3_setup_phy(struct tg3 *, int);
++
++#define RESET_KIND_SHUTDOWN	0
++#define RESET_KIND_INIT		1
++#define RESET_KIND_SUSPEND	2
++
++static void tg3_write_sig_post_reset(struct tg3 *, int);
++
++static int tg3_set_power_state(struct tg3 *tp, int state)
++{
++	u32 misc_host_ctrl;
++	u16 power_control, power_caps;
++	int pm = tp->pm_cap;
++
++	/* Make sure register accesses (indirect or otherwise)
++	 * will function correctly.
++	 */
++	pci_write_config_dword(tp->pdev,
++			       TG3PCI_MISC_HOST_CTRL,
++			       tp->misc_host_ctrl);
++
++	pci_read_config_word(tp->pdev,
++			     pm + PCI_PM_CTRL,
++			     &power_control);
++	power_control |= PCI_PM_CTRL_PME_STATUS;
++	power_control &= ~(PCI_PM_CTRL_STATE_MASK);
++	switch (state) {
++	case 0:
++		power_control |= 0;
++		pci_write_config_word(tp->pdev,
++				      pm + PCI_PM_CTRL,
++				      power_control);
++		tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
++		udelay(100);
++
++		return 0;
++
++	case 1:
++		power_control |= 1;
++		break;
++
++	case 2:
++		power_control |= 2;
++		break;
++
++	case 3:
++		power_control |= 3;
++		break;
++
++	default:
++		printk(KERN_WARNING PFX "%s: Invalid power state (%d) "
++		       "requested.\n",
++		       tp->dev->name, state);
++		return -EINVAL;
++	};
++
++	power_control |= PCI_PM_CTRL_PME_ENABLE;
++
++	misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
++	tw32(TG3PCI_MISC_HOST_CTRL,
++	     misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
++
++	if (tp->link_config.phy_is_low_power == 0) {
++		tp->link_config.phy_is_low_power = 1;
++		tp->link_config.orig_speed = tp->link_config.speed;
++		tp->link_config.orig_duplex = tp->link_config.duplex;
++		tp->link_config.orig_autoneg = tp->link_config.autoneg;
++	}
++
++	if (tp->phy_id != PHY_ID_SERDES) {
++		tp->link_config.speed = SPEED_10;
++		tp->link_config.duplex = DUPLEX_HALF;
++		tp->link_config.autoneg = AUTONEG_ENABLE;
++		tg3_setup_phy(tp, 0);
++	}
++
++	pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
++
++	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
++		u32 mac_mode;
++
++		if (tp->phy_id != PHY_ID_SERDES) {
++			tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
++			udelay(40);
++
++			mac_mode = MAC_MODE_PORT_MODE_MII;
++
++			if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
++			    !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
++				mac_mode |= MAC_MODE_LINK_POLARITY;
++		} else {
++			mac_mode = MAC_MODE_PORT_MODE_TBI;
++		}
++
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
++			tw32(MAC_LED_CTRL, tp->led_ctrl);
++
++		if (((power_caps & PCI_PM_CAP_PME_D3cold) &&
++		     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
++			mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
++
++		tw32_f(MAC_MODE, mac_mode);
++		udelay(100);
++
++		tw32_f(MAC_RX_MODE, RX_MODE_ENABLE);
++		udelay(10);
++	}
++
++	if (!(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB) &&
++	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
++		u32 base_val;
++
++		base_val = tp->pci_clock_ctrl;
++		base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
++			     CLOCK_CTRL_TXCLK_DISABLE);
++
++		tw32_f(TG3PCI_CLOCK_CTRL, base_val |
++		     CLOCK_CTRL_ALTCLK |
++		     CLOCK_CTRL_PWRDOWN_PLL133);
++		udelay(40);
++	} else if (!((GET_ASIC_REV(tp->pci_chip_rev_id) == 5750) &&
++		     (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
++		u32 newbits1, newbits2;
++
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
++			newbits1 = (CLOCK_CTRL_RXCLK_DISABLE |
++				    CLOCK_CTRL_TXCLK_DISABLE |
++				    CLOCK_CTRL_ALTCLK);
++			newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
++		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++			   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++			newbits1 = CLOCK_CTRL_625_CORE;
++			newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
++		} else {
++			newbits1 = CLOCK_CTRL_ALTCLK;
++			newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
++		}
++
++		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1);
++		udelay(40);
++
++		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
++		udelay(40);
++
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++		    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++			u32 newbits3;
++
++			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
++				newbits3 = (CLOCK_CTRL_RXCLK_DISABLE |
++					    CLOCK_CTRL_TXCLK_DISABLE |
++					    CLOCK_CTRL_44MHZ_CORE);
++			} else {
++				newbits3 = CLOCK_CTRL_44MHZ_CORE;
++			}
++
++			tw32_f(TG3PCI_CLOCK_CTRL,
++					 tp->pci_clock_ctrl | newbits3);
++			udelay(40);
++		}
++	}
++
++	tg3_frob_aux_power(tp);
++
++	/* Finally, set the new power state. */
++	pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
++
++	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
++
++	return 0;
++}
++
++static void tg3_link_report(struct tg3 *tp)
++{
++	if (!netif_carrier_ok(tp->dev)) {
++		printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name);
++	} else {
++		printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n",
++		       tp->dev->name,
++		       (tp->link_config.active_speed == SPEED_1000 ?
++			1000 :
++			(tp->link_config.active_speed == SPEED_100 ?
++			 100 : 10)),
++		       (tp->link_config.active_duplex == DUPLEX_FULL ?
++			"full" : "half"));
++
++		printk(KERN_INFO PFX "%s: Flow control is %s for TX and "
++		       "%s for RX.\n",
++		       tp->dev->name,
++		       (tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "on" : "off",
++		       (tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "on" : "off");
++	}
++}
++
++static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv)
++{
++	u32 new_tg3_flags = 0;
++	u32 old_rx_mode = tp->rx_mode;
++	u32 old_tx_mode = tp->tx_mode;
++
++	if (local_adv & ADVERTISE_PAUSE_CAP) {
++		if (local_adv & ADVERTISE_PAUSE_ASYM) {
++			if (remote_adv & LPA_PAUSE_CAP)
++				new_tg3_flags |=
++					(TG3_FLAG_RX_PAUSE |
++					 TG3_FLAG_TX_PAUSE);
++			else if (remote_adv & LPA_PAUSE_ASYM)
++				new_tg3_flags |=
++					(TG3_FLAG_RX_PAUSE);
++		} else {
++			if (remote_adv & LPA_PAUSE_CAP)
++				new_tg3_flags |=
++					(TG3_FLAG_RX_PAUSE |
++					 TG3_FLAG_TX_PAUSE);
++		}
++	} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
++		if ((remote_adv & LPA_PAUSE_CAP) &&
++		    (remote_adv & LPA_PAUSE_ASYM))
++			new_tg3_flags |= TG3_FLAG_TX_PAUSE;
++	}
++
++	tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
++	tp->tg3_flags |= new_tg3_flags;
++
++	if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
++		tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
++	else
++		tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
++
++	if (old_rx_mode != tp->rx_mode) {
++		tw32_f(MAC_RX_MODE, tp->rx_mode);
++	}
++	
++	if (new_tg3_flags & TG3_FLAG_TX_PAUSE)
++		tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
++	else
++		tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
++
++	if (old_tx_mode != tp->tx_mode) {
++		tw32_f(MAC_TX_MODE, tp->tx_mode);
++	}
++}
++
++static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
++{
++	switch (val & MII_TG3_AUX_STAT_SPDMASK) {
++	case MII_TG3_AUX_STAT_10HALF:
++		*speed = SPEED_10;
++		*duplex = DUPLEX_HALF;
++		break;
++
++	case MII_TG3_AUX_STAT_10FULL:
++		*speed = SPEED_10;
++		*duplex = DUPLEX_FULL;
++		break;
++
++	case MII_TG3_AUX_STAT_100HALF:
++		*speed = SPEED_100;
++		*duplex = DUPLEX_HALF;
++		break;
++
++	case MII_TG3_AUX_STAT_100FULL:
++		*speed = SPEED_100;
++		*duplex = DUPLEX_FULL;
++		break;
++
++	case MII_TG3_AUX_STAT_1000HALF:
++		*speed = SPEED_1000;
++		*duplex = DUPLEX_HALF;
++		break;
++
++	case MII_TG3_AUX_STAT_1000FULL:
++		*speed = SPEED_1000;
++		*duplex = DUPLEX_FULL;
++		break;
++
++	default:
++		*speed = SPEED_INVALID;
++		*duplex = DUPLEX_INVALID;
++		break;
++	};
++}
++
++static int tg3_phy_copper_begin(struct tg3 *tp)
++{
++	u32 new_adv;
++	int i;
++
++	if (tp->link_config.phy_is_low_power) {
++		/* Entering low power mode.  Disable gigabit and
++		 * 100baseT advertisements.
++		 */
++		tg3_writephy(tp, MII_TG3_CTRL, 0);
++
++		new_adv = (ADVERTISE_10HALF | ADVERTISE_10FULL |
++			   ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
++		if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)
++			new_adv |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
++
++		tg3_writephy(tp, MII_ADVERTISE, new_adv);
++	} else if (tp->link_config.speed == SPEED_INVALID) {
++		tp->link_config.advertising =
++			(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
++			 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
++			 ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
++			 ADVERTISED_Autoneg | ADVERTISED_MII);
++
++		if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
++			tp->link_config.advertising &=
++				~(ADVERTISED_1000baseT_Half |
++				  ADVERTISED_1000baseT_Full);
++
++		new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
++		if (tp->link_config.advertising & ADVERTISED_10baseT_Half)
++			new_adv |= ADVERTISE_10HALF;
++		if (tp->link_config.advertising & ADVERTISED_10baseT_Full)
++			new_adv |= ADVERTISE_10FULL;
++		if (tp->link_config.advertising & ADVERTISED_100baseT_Half)
++			new_adv |= ADVERTISE_100HALF;
++		if (tp->link_config.advertising & ADVERTISED_100baseT_Full)
++			new_adv |= ADVERTISE_100FULL;
++		tg3_writephy(tp, MII_ADVERTISE, new_adv);
++
++		if (tp->link_config.advertising &
++		    (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) {
++			new_adv = 0;
++			if (tp->link_config.advertising & ADVERTISED_1000baseT_Half)
++				new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
++			if (tp->link_config.advertising & ADVERTISED_1000baseT_Full)
++				new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
++			if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) &&
++			    (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
++			     tp->pci_chip_rev_id == CHIPREV_ID_5701_B0))
++				new_adv |= (MII_TG3_CTRL_AS_MASTER |
++					    MII_TG3_CTRL_ENABLE_AS_MASTER);
++			tg3_writephy(tp, MII_TG3_CTRL, new_adv);
++		} else {
++			tg3_writephy(tp, MII_TG3_CTRL, 0);
++		}
++	} else {
++		/* Asking for a specific link mode. */
++		if (tp->link_config.speed == SPEED_1000) {
++			new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
++			tg3_writephy(tp, MII_ADVERTISE, new_adv);
++
++			if (tp->link_config.duplex == DUPLEX_FULL)
++				new_adv = MII_TG3_CTRL_ADV_1000_FULL;
++			else
++				new_adv = MII_TG3_CTRL_ADV_1000_HALF;
++			if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
++			    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
++				new_adv |= (MII_TG3_CTRL_AS_MASTER |
++					    MII_TG3_CTRL_ENABLE_AS_MASTER);
++			tg3_writephy(tp, MII_TG3_CTRL, new_adv);
++		} else {
++			tg3_writephy(tp, MII_TG3_CTRL, 0);
++
++			new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
++			if (tp->link_config.speed == SPEED_100) {
++				if (tp->link_config.duplex == DUPLEX_FULL)
++					new_adv |= ADVERTISE_100FULL;
++				else
++					new_adv |= ADVERTISE_100HALF;
++			} else {
++				if (tp->link_config.duplex == DUPLEX_FULL)
++					new_adv |= ADVERTISE_10FULL;
++				else
++					new_adv |= ADVERTISE_10HALF;
++			}
++			tg3_writephy(tp, MII_ADVERTISE, new_adv);
++		}
++	}
++
++	if (tp->link_config.autoneg == AUTONEG_DISABLE &&
++	    tp->link_config.speed != SPEED_INVALID) {
++		u32 bmcr, orig_bmcr;
++
++		tp->link_config.active_speed = tp->link_config.speed;
++		tp->link_config.active_duplex = tp->link_config.duplex;
++
++		bmcr = 0;
++		switch (tp->link_config.speed) {
++		default:
++		case SPEED_10:
++			break;
++
++		case SPEED_100:
++			bmcr |= BMCR_SPEED100;
++			break;
++
++		case SPEED_1000:
++			bmcr |= TG3_BMCR_SPEED1000;
++			break;
++		};
++
++		if (tp->link_config.duplex == DUPLEX_FULL)
++			bmcr |= BMCR_FULLDPLX;
++
++		tg3_readphy(tp, MII_BMCR, &orig_bmcr);
++		if (bmcr != orig_bmcr) {
++			tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
++			for (i = 0; i < 1500; i++) {
++				u32 tmp;
++
++				udelay(10);
++				tg3_readphy(tp, MII_BMSR, &tmp);
++				tg3_readphy(tp, MII_BMSR, &tmp);
++				if (!(tmp & BMSR_LSTATUS)) {
++					udelay(40);
++					break;
++				}
++			}
++			tg3_writephy(tp, MII_BMCR, bmcr);
++			udelay(40);
++		}
++	} else {
++		tg3_writephy(tp, MII_BMCR,
++			     BMCR_ANENABLE | BMCR_ANRESTART);
++	}
++
++	return 0;
++}
++
++static int tg3_init_5401phy_dsp(struct tg3 *tp)
++{
++	int err;
++
++	/* Turn off tap power management. */
++	/* Set Extended packet length bit */
++	err  = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20);
++
++	err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0012);
++	err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x1804);
++
++	err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0013);
++	err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x1204);
++
++	err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8006);
++	err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0132);
++
++	err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8006);
++	err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0232);
++
++	err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
++	err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0a20);
++
++	udelay(40);
++
++	return err;
++}
++
++static int tg3_copper_is_advertising_all(struct tg3 *tp)
++{
++	u32 adv_reg, all_mask;
++
++	tg3_readphy(tp, MII_ADVERTISE, &adv_reg);
++	all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL |
++		    ADVERTISE_100HALF | ADVERTISE_100FULL);
++	if ((adv_reg & all_mask) != all_mask)
++		return 0;
++	if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
++		u32 tg3_ctrl;
++
++		tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl);
++		all_mask = (MII_TG3_CTRL_ADV_1000_HALF |
++			    MII_TG3_CTRL_ADV_1000_FULL);
++		if ((tg3_ctrl & all_mask) != all_mask)
++			return 0;
++	}
++	return 1;
++}
++
++static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
++{
++	int current_link_up;
++	u32 bmsr, dummy;
++	u16 current_speed;
++	u8 current_duplex;
++	int i, err;
++
++	tw32(MAC_EVENT, 0);
++
++	tw32_f(MAC_STATUS,
++	     (MAC_STATUS_SYNC_CHANGED |
++	      MAC_STATUS_CFG_CHANGED |
++	      MAC_STATUS_MI_COMPLETION |
++	      MAC_STATUS_LNKSTATE_CHANGED));
++	udelay(40);
++
++	tp->mi_mode = MAC_MI_MODE_BASE;
++	tw32_f(MAC_MI_MODE, tp->mi_mode);
++	udelay(80);
++
++	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
++
++	/* Some third-party PHYs need to be reset on link going
++	 * down.
++	 */
++	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
++	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
++	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
++	    netif_carrier_ok(tp->dev)) {
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++		if (!(bmsr & BMSR_LSTATUS))
++			force_reset = 1;
++	}
++	if (force_reset)
++		tg3_phy_reset(tp);
++
++	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++
++		if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE))
++			bmsr = 0;
++
++		if (!(bmsr & BMSR_LSTATUS)) {
++			err = tg3_init_5401phy_dsp(tp);
++			if (err)
++				return err;
++
++			tg3_readphy(tp, MII_BMSR, &bmsr);
++			for (i = 0; i < 1000; i++) {
++				udelay(10);
++				tg3_readphy(tp, MII_BMSR, &bmsr);
++				if (bmsr & BMSR_LSTATUS) {
++					udelay(40);
++					break;
++				}
++			}
++
++			if ((tp->phy_id & PHY_ID_REV_MASK) == PHY_REV_BCM5401_B0 &&
++			    !(bmsr & BMSR_LSTATUS) &&
++			    tp->link_config.active_speed == SPEED_1000) {
++				err = tg3_phy_reset(tp);
++				if (!err)
++					err = tg3_init_5401phy_dsp(tp);
++				if (err)
++					return err;
++			}
++		}
++	} else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
++		   tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
++		/* 5701 {A0,B0} CRC bug workaround */
++		tg3_writephy(tp, 0x15, 0x0a75);
++		tg3_writephy(tp, 0x1c, 0x8c68);
++		tg3_writephy(tp, 0x1c, 0x8d68);
++		tg3_writephy(tp, 0x1c, 0x8c68);
++	}
++
++	/* Clear pending interrupts... */
++	tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
++	tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
++
++	if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT)
++		tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
++	else
++		tg3_writephy(tp, MII_TG3_IMASK, ~0);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
++		if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
++			tg3_writephy(tp, MII_TG3_EXT_CTRL,
++				     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
++		else
++			tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
++	}
++
++	current_link_up = 0;
++	current_speed = SPEED_INVALID;
++	current_duplex = DUPLEX_INVALID;
++
++	bmsr = 0;
++	for (i = 0; i < 100; i++) {
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++		if (bmsr & BMSR_LSTATUS)
++			break;
++		udelay(40);
++	}
++
++	if (bmsr & BMSR_LSTATUS) {
++		u32 aux_stat, bmcr;
++
++		tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
++		for (i = 0; i < 2000; i++) {
++			udelay(10);
++			tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
++			if (aux_stat)
++				break;
++		}
++
++		tg3_aux_stat_to_speed_duplex(tp, aux_stat,
++					     &current_speed,
++					     &current_duplex);
++
++		bmcr = 0;
++		for (i = 0; i < 200; i++) {
++			tg3_readphy(tp, MII_BMCR, &bmcr);
++			tg3_readphy(tp, MII_BMCR, &bmcr);
++			if (bmcr && bmcr != 0x7fff)
++				break;
++			udelay(10);
++		}
++
++		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
++			if (bmcr & BMCR_ANENABLE) {
++				current_link_up = 1;
++
++				/* Force autoneg restart if we are exiting
++				 * low power mode.
++				 */
++				if (!tg3_copper_is_advertising_all(tp))
++					current_link_up = 0;
++			} else {
++				current_link_up = 0;
++			}
++		} else {
++			if (!(bmcr & BMCR_ANENABLE) &&
++			    tp->link_config.speed == current_speed &&
++			    tp->link_config.duplex == current_duplex) {
++				current_link_up = 1;
++			} else {
++				current_link_up = 0;
++			}
++		}
++
++		tp->link_config.active_speed = current_speed;
++		tp->link_config.active_duplex = current_duplex;
++	}
++
++	if (current_link_up == 1 &&
++	    (tp->link_config.active_duplex == DUPLEX_FULL) &&
++	    (tp->link_config.autoneg == AUTONEG_ENABLE)) {
++		u32 local_adv, remote_adv;
++
++		tg3_readphy(tp, MII_ADVERTISE, &local_adv);
++		local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
++
++		tg3_readphy(tp, MII_LPA, &remote_adv);
++		remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
++
++		/* If we are not advertising full pause capability,
++		 * something is wrong.  Bring the link down and reconfigure.
++		 */
++		if (local_adv != ADVERTISE_PAUSE_CAP) {
++			current_link_up = 0;
++		} else {
++			tg3_setup_flow_control(tp, local_adv, remote_adv);
++		}
++	}
++
++	if (current_link_up == 0) {
++		u32 tmp;
++
++		tg3_phy_copper_begin(tp);
++
++		tg3_readphy(tp, MII_BMSR, &tmp);
++		tg3_readphy(tp, MII_BMSR, &tmp);
++		if (tmp & BMSR_LSTATUS)
++			current_link_up = 1;
++	}
++
++	tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
++	if (current_link_up == 1) {
++		if (tp->link_config.active_speed == SPEED_100 ||
++		    tp->link_config.active_speed == SPEED_10)
++			tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
++		else
++			tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
++	} else
++		tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
++
++	tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
++	if (tp->link_config.active_duplex == DUPLEX_HALF)
++		tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
++
++	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
++		if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) ||
++		    (current_link_up == 1 &&
++		     tp->link_config.active_speed == SPEED_10))
++			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
++	} else {
++		if (current_link_up == 1)
++			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
++	}
++
++	/* ??? Without this setting Netgear GA302T PHY does not
++	 * ??? send/receive packets...
++	 */
++	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 &&
++	    tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
++		tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
++		tw32_f(MAC_MI_MODE, tp->mi_mode);
++		udelay(80);
++	}
++
++	tw32_f(MAC_MODE, tp->mac_mode);
++	udelay(40);
++
++	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
++		/* Polled via timer. */
++		tw32_f(MAC_EVENT, 0);
++	} else {
++		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
++	}
++	udelay(40);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
++	    current_link_up == 1 &&
++	    tp->link_config.active_speed == SPEED_1000 &&
++	    ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ||
++	     (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) {
++		udelay(120);
++		tw32_f(MAC_STATUS,
++		     (MAC_STATUS_SYNC_CHANGED |
++		      MAC_STATUS_CFG_CHANGED));
++		udelay(40);
++		tg3_write_mem(tp,
++			      NIC_SRAM_FIRMWARE_MBOX,
++			      NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
++	}
++
++	if (current_link_up != netif_carrier_ok(tp->dev)) {
++		if (current_link_up)
++			netif_carrier_on(tp->dev);
++		else
++			netif_carrier_off(tp->dev);
++		tg3_link_report(tp);
++	}
++
++	return 0;
++}
++
++struct tg3_fiber_aneginfo {
++	int state;
++#define ANEG_STATE_UNKNOWN		0
++#define ANEG_STATE_AN_ENABLE		1
++#define ANEG_STATE_RESTART_INIT		2
++#define ANEG_STATE_RESTART		3
++#define ANEG_STATE_DISABLE_LINK_OK	4
++#define ANEG_STATE_ABILITY_DETECT_INIT	5
++#define ANEG_STATE_ABILITY_DETECT	6
++#define ANEG_STATE_ACK_DETECT_INIT	7
++#define ANEG_STATE_ACK_DETECT		8
++#define ANEG_STATE_COMPLETE_ACK_INIT	9
++#define ANEG_STATE_COMPLETE_ACK		10
++#define ANEG_STATE_IDLE_DETECT_INIT	11
++#define ANEG_STATE_IDLE_DETECT		12
++#define ANEG_STATE_LINK_OK		13
++#define ANEG_STATE_NEXT_PAGE_WAIT_INIT	14
++#define ANEG_STATE_NEXT_PAGE_WAIT	15
++
++	u32 flags;
++#define MR_AN_ENABLE		0x00000001
++#define MR_RESTART_AN		0x00000002
++#define MR_AN_COMPLETE		0x00000004
++#define MR_PAGE_RX		0x00000008
++#define MR_NP_LOADED		0x00000010
++#define MR_TOGGLE_TX		0x00000020
++#define MR_LP_ADV_FULL_DUPLEX	0x00000040
++#define MR_LP_ADV_HALF_DUPLEX	0x00000080
++#define MR_LP_ADV_SYM_PAUSE	0x00000100
++#define MR_LP_ADV_ASYM_PAUSE	0x00000200
++#define MR_LP_ADV_REMOTE_FAULT1	0x00000400
++#define MR_LP_ADV_REMOTE_FAULT2	0x00000800
++#define MR_LP_ADV_NEXT_PAGE	0x00001000
++#define MR_TOGGLE_RX		0x00002000
++#define MR_NP_RX		0x00004000
++
++#define MR_LINK_OK		0x80000000
++
++	unsigned long link_time, cur_time;
++
++	u32 ability_match_cfg;
++	int ability_match_count;
++
++	char ability_match, idle_match, ack_match;
++
++	u32 txconfig, rxconfig;
++#define ANEG_CFG_NP		0x00000080
++#define ANEG_CFG_ACK		0x00000040
++#define ANEG_CFG_RF2		0x00000020
++#define ANEG_CFG_RF1		0x00000010
++#define ANEG_CFG_PS2		0x00000001
++#define ANEG_CFG_PS1		0x00008000
++#define ANEG_CFG_HD		0x00004000
++#define ANEG_CFG_FD		0x00002000
++#define ANEG_CFG_INVAL		0x00001f06
++
++};
++#define ANEG_OK		0
++#define ANEG_DONE	1
++#define ANEG_TIMER_ENAB	2
++#define ANEG_FAILED	-1
++
++#define ANEG_STATE_SETTLE_TIME	10000
++
++static int tg3_fiber_aneg_smachine(struct tg3 *tp,
++				   struct tg3_fiber_aneginfo *ap)
++{
++	unsigned long delta;
++	u32 rx_cfg_reg;
++	int ret;
++
++	if (ap->state == ANEG_STATE_UNKNOWN) {
++		ap->rxconfig = 0;
++		ap->link_time = 0;
++		ap->cur_time = 0;
++		ap->ability_match_cfg = 0;
++		ap->ability_match_count = 0;
++		ap->ability_match = 0;
++		ap->idle_match = 0;
++		ap->ack_match = 0;
++	}
++	ap->cur_time++;
++
++	if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
++		rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
++
++		if (rx_cfg_reg != ap->ability_match_cfg) {
++			ap->ability_match_cfg = rx_cfg_reg;
++			ap->ability_match = 0;
++			ap->ability_match_count = 0;
++		} else {
++			if (++ap->ability_match_count > 1) {
++				ap->ability_match = 1;
++				ap->ability_match_cfg = rx_cfg_reg;
++			}
++		}
++		if (rx_cfg_reg & ANEG_CFG_ACK)
++			ap->ack_match = 1;
++		else
++			ap->ack_match = 0;
++
++		ap->idle_match = 0;
++	} else {
++		ap->idle_match = 1;
++		ap->ability_match_cfg = 0;
++		ap->ability_match_count = 0;
++		ap->ability_match = 0;
++		ap->ack_match = 0;
++
++		rx_cfg_reg = 0;
++	}
++
++	ap->rxconfig = rx_cfg_reg;
++	ret = ANEG_OK;
++
++	switch(ap->state) {
++	case ANEG_STATE_UNKNOWN:
++		if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
++			ap->state = ANEG_STATE_AN_ENABLE;
++
++		/* fallthru */
++	case ANEG_STATE_AN_ENABLE:
++		ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
++		if (ap->flags & MR_AN_ENABLE) {
++			ap->link_time = 0;
++			ap->cur_time = 0;
++			ap->ability_match_cfg = 0;
++			ap->ability_match_count = 0;
++			ap->ability_match = 0;
++			ap->idle_match = 0;
++			ap->ack_match = 0;
++
++			ap->state = ANEG_STATE_RESTART_INIT;
++		} else {
++			ap->state = ANEG_STATE_DISABLE_LINK_OK;
++		}
++		break;
++
++	case ANEG_STATE_RESTART_INIT:
++		ap->link_time = ap->cur_time;
++		ap->flags &= ~(MR_NP_LOADED);
++		ap->txconfig = 0;
++		tw32(MAC_TX_AUTO_NEG, 0);
++		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
++		tw32_f(MAC_MODE, tp->mac_mode);
++		udelay(40);
++
++		ret = ANEG_TIMER_ENAB;
++		ap->state = ANEG_STATE_RESTART;
++
++		/* fallthru */
++	case ANEG_STATE_RESTART:
++		delta = ap->cur_time - ap->link_time;
++		if (delta > ANEG_STATE_SETTLE_TIME) {
++			ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
++		} else {
++			ret = ANEG_TIMER_ENAB;
++		}
++		break;
++
++	case ANEG_STATE_DISABLE_LINK_OK:
++		ret = ANEG_DONE;
++		break;
++
++	case ANEG_STATE_ABILITY_DETECT_INIT:
++		ap->flags &= ~(MR_TOGGLE_TX);
++		ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
++		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
++		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
++		tw32_f(MAC_MODE, tp->mac_mode);
++		udelay(40);
++
++		ap->state = ANEG_STATE_ABILITY_DETECT;
++		break;
++
++	case ANEG_STATE_ABILITY_DETECT:
++		if (ap->ability_match != 0 && ap->rxconfig != 0) {
++			ap->state = ANEG_STATE_ACK_DETECT_INIT;
++		}
++		break;
++
++	case ANEG_STATE_ACK_DETECT_INIT:
++		ap->txconfig |= ANEG_CFG_ACK;
++		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
++		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
++		tw32_f(MAC_MODE, tp->mac_mode);
++		udelay(40);
++
++		ap->state = ANEG_STATE_ACK_DETECT;
++
++		/* fallthru */
++	case ANEG_STATE_ACK_DETECT:
++		if (ap->ack_match != 0) {
++			if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
++			    (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
++				ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
++			} else {
++				ap->state = ANEG_STATE_AN_ENABLE;
++			}
++		} else if (ap->ability_match != 0 &&
++			   ap->rxconfig == 0) {
++			ap->state = ANEG_STATE_AN_ENABLE;
++		}
++		break;
++
++	case ANEG_STATE_COMPLETE_ACK_INIT:
++		if (ap->rxconfig & ANEG_CFG_INVAL) {
++			ret = ANEG_FAILED;
++			break;
++		}
++		ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
++			       MR_LP_ADV_HALF_DUPLEX |
++			       MR_LP_ADV_SYM_PAUSE |
++			       MR_LP_ADV_ASYM_PAUSE |
++			       MR_LP_ADV_REMOTE_FAULT1 |
++			       MR_LP_ADV_REMOTE_FAULT2 |
++			       MR_LP_ADV_NEXT_PAGE |
++			       MR_TOGGLE_RX |
++			       MR_NP_RX);
++		if (ap->rxconfig & ANEG_CFG_FD)
++			ap->flags |= MR_LP_ADV_FULL_DUPLEX;
++		if (ap->rxconfig & ANEG_CFG_HD)
++			ap->flags |= MR_LP_ADV_HALF_DUPLEX;
++		if (ap->rxconfig & ANEG_CFG_PS1)
++			ap->flags |= MR_LP_ADV_SYM_PAUSE;
++		if (ap->rxconfig & ANEG_CFG_PS2)
++			ap->flags |= MR_LP_ADV_ASYM_PAUSE;
++		if (ap->rxconfig & ANEG_CFG_RF1)
++			ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
++		if (ap->rxconfig & ANEG_CFG_RF2)
++			ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
++		if (ap->rxconfig & ANEG_CFG_NP)
++			ap->flags |= MR_LP_ADV_NEXT_PAGE;
++
++		ap->link_time = ap->cur_time;
++
++		ap->flags ^= (MR_TOGGLE_TX);
++		if (ap->rxconfig & 0x0008)
++			ap->flags |= MR_TOGGLE_RX;
++		if (ap->rxconfig & ANEG_CFG_NP)
++			ap->flags |= MR_NP_RX;
++		ap->flags |= MR_PAGE_RX;
++
++		ap->state = ANEG_STATE_COMPLETE_ACK;
++		ret = ANEG_TIMER_ENAB;
++		break;
++
++	case ANEG_STATE_COMPLETE_ACK:
++		if (ap->ability_match != 0 &&
++		    ap->rxconfig == 0) {
++			ap->state = ANEG_STATE_AN_ENABLE;
++			break;
++		}
++		delta = ap->cur_time - ap->link_time;
++		if (delta > ANEG_STATE_SETTLE_TIME) {
++			if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
++				ap->state = ANEG_STATE_IDLE_DETECT_INIT;
++			} else {
++				if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
++				    !(ap->flags & MR_NP_RX)) {
++					ap->state = ANEG_STATE_IDLE_DETECT_INIT;
++				} else {
++					ret = ANEG_FAILED;
++				}
++			}
++		}
++		break;
++
++	case ANEG_STATE_IDLE_DETECT_INIT:
++		ap->link_time = ap->cur_time;
++		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
++		tw32_f(MAC_MODE, tp->mac_mode);
++		udelay(40);
++
++		ap->state = ANEG_STATE_IDLE_DETECT;
++		ret = ANEG_TIMER_ENAB;
++		break;
++
++	case ANEG_STATE_IDLE_DETECT:
++		if (ap->ability_match != 0 &&
++		    ap->rxconfig == 0) {
++			ap->state = ANEG_STATE_AN_ENABLE;
++			break;
++		}
++		delta = ap->cur_time - ap->link_time;
++		if (delta > ANEG_STATE_SETTLE_TIME) {
++			/* XXX another gem from the Broadcom driver :( */
++			ap->state = ANEG_STATE_LINK_OK;
++		}
++		break;
++
++	case ANEG_STATE_LINK_OK:
++		ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);
++		ret = ANEG_DONE;
++		break;
++
++	case ANEG_STATE_NEXT_PAGE_WAIT_INIT:
++		/* ??? unimplemented */
++		break;
++
++	case ANEG_STATE_NEXT_PAGE_WAIT:
++		/* ??? unimplemented */
++		break;
++
++	default:
++		ret = ANEG_FAILED;
++		break;
++	};
++
++	return ret;
++}
++
++static int fiber_autoneg(struct tg3 *tp, u32 *flags)
++{
++	int res = 0;
++
++	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
++		u32 dig_status;
++
++		dig_status = tr32(SG_DIG_STATUS);
++		*flags = 0;
++		if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
++			*flags |= MR_LP_ADV_ASYM_PAUSE;
++		if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
++			*flags |= MR_LP_ADV_SYM_PAUSE;
++
++		if ((dig_status & SG_DIG_AUTONEG_COMPLETE) &&
++		    !(dig_status & (SG_DIG_AUTONEG_ERROR |
++				    SG_DIG_PARTNER_FAULT_MASK)))
++			res = 1;
++	} else {
++		struct tg3_fiber_aneginfo aninfo;
++		int status = ANEG_FAILED;
++		unsigned int tick;
++		u32 tmp;
++
++		tw32_f(MAC_TX_AUTO_NEG, 0);
++
++		tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
++		tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
++		udelay(40);
++
++		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
++		udelay(40);
++
++		memset(&aninfo, 0, sizeof(aninfo));
++		aninfo.flags |= MR_AN_ENABLE;
++		aninfo.state = ANEG_STATE_UNKNOWN;
++		aninfo.cur_time = 0;
++		tick = 0;
++		while (++tick < 195000) {
++			status = tg3_fiber_aneg_smachine(tp, &aninfo);
++			if (status == ANEG_DONE || status == ANEG_FAILED)
++				break;
++
++			udelay(1);
++		}
++
++		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
++		tw32_f(MAC_MODE, tp->mac_mode);
++		udelay(40);
++
++		*flags = aninfo.flags;
++
++		if (status == ANEG_DONE &&
++		    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
++				     MR_LP_ADV_FULL_DUPLEX)))
++			res = 1;
++	}
++
++	return res;
++}
++
++static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
++{
++	u32 orig_pause_cfg;
++	u16 orig_active_speed;
++	u8 orig_active_duplex;
++	int current_link_up;
++	int i;
++
++	orig_pause_cfg =
++		(tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
++				  TG3_FLAG_TX_PAUSE));
++	orig_active_speed = tp->link_config.active_speed;
++	orig_active_duplex = tp->link_config.active_duplex;
++
++	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
++	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
++	tw32_f(MAC_MODE, tp->mac_mode);
++	udelay(40);
++
++	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
++		/* Allow time for the hardware to auto-negotiate (195ms) */
++		unsigned int tick = 0;
++
++		while (++tick < 195000) { 
++			if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
++				break;
++			udelay(1);
++		}
++		if (tick >= 195000)
++			printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
++			    tp->dev->name);
++	}
++
++	/* Reset when initting first time or we have a link. */
++	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
++	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
++		/* Set PLL lock range. */
++		tg3_writephy(tp, 0x16, 0x8007);
++
++		/* SW reset */
++		tg3_writephy(tp, MII_BMCR, BMCR_RESET);
++
++		/* Wait for reset to complete. */
++		/* XXX schedule_timeout() ... */
++		for (i = 0; i < 500; i++)
++			udelay(10);
++
++		/* Config mode; select PMA/Ch 1 regs. */
++		tg3_writephy(tp, 0x10, 0x8411);
++
++		/* Enable auto-lock and comdet, select txclk for tx. */
++		tg3_writephy(tp, 0x11, 0x0a10);
++
++		tg3_writephy(tp, 0x18, 0x00a0);
++		tg3_writephy(tp, 0x16, 0x41ff);
++
++		/* Assert and deassert POR. */
++		tg3_writephy(tp, 0x13, 0x0400);
++		udelay(40);
++		tg3_writephy(tp, 0x13, 0x0000);
++
++		tg3_writephy(tp, 0x11, 0x0a50);
++		udelay(40);
++		tg3_writephy(tp, 0x11, 0x0a10);
++
++		/* Wait for signal to stabilize */
++		/* XXX schedule_timeout() ... */
++		for (i = 0; i < 15000; i++)
++			udelay(10);
++
++		/* Deselect the channel register so we can read the PHYID
++		 * later.
++		 */
++		tg3_writephy(tp, 0x10, 0x8011);
++	}
++
++	/* Enable link change interrupt unless serdes polling.  */
++	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
++		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
++	else
++		tw32_f(MAC_EVENT, 0);
++	udelay(40);
++
++	current_link_up = 0;
++ 	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
++		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
++			u32 flags;
++  
++			if (fiber_autoneg(tp, &flags)) {
++				u32 local_adv, remote_adv;
++
++				local_adv = ADVERTISE_PAUSE_CAP;
++				remote_adv = 0;
++				if (flags & MR_LP_ADV_SYM_PAUSE)
++  					remote_adv |= LPA_PAUSE_CAP;
++				if (flags & MR_LP_ADV_ASYM_PAUSE)
++					remote_adv |= LPA_PAUSE_ASYM;
++
++				tg3_setup_flow_control(tp, local_adv, remote_adv);
++
++				tp->tg3_flags |=
++					TG3_FLAG_GOT_SERDES_FLOWCTL;
++				current_link_up = 1;
++			}
++			for (i = 0; i < 60; i++) {
++				udelay(20);
++				tw32_f(MAC_STATUS,
++				     (MAC_STATUS_SYNC_CHANGED |
++				      MAC_STATUS_CFG_CHANGED));
++				udelay(40);
++				if ((tr32(MAC_STATUS) &
++				     (MAC_STATUS_SYNC_CHANGED |
++				      MAC_STATUS_CFG_CHANGED)) == 0)
++					break;
++			}
++			if (current_link_up == 0 &&
++			    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
++				current_link_up = 1;
++			}
++		} else {
++			/* Forcing 1000FD link up. */
++			current_link_up = 1;
++			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
++		}
++	} else
++		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
++
++	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
++	tw32_f(MAC_MODE, tp->mac_mode);
++	udelay(40);
++
++	tp->hw_status->status =
++		(SD_STATUS_UPDATED |
++		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
++
++	for (i = 0; i < 100; i++) {
++		udelay(20);
++		tw32_f(MAC_STATUS,
++		     (MAC_STATUS_SYNC_CHANGED |
++		      MAC_STATUS_CFG_CHANGED));
++		udelay(40);
++		if ((tr32(MAC_STATUS) &
++		     (MAC_STATUS_SYNC_CHANGED |
++		      MAC_STATUS_CFG_CHANGED)) == 0)
++			break;
++	}
++
++	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
++		current_link_up = 0;
++
++	if (current_link_up == 1) {
++		tp->link_config.active_speed = SPEED_1000;
++		tp->link_config.active_duplex = DUPLEX_FULL;
++		tw32(MAC_LED_CTRL, (tp->led_ctrl |
++				    LED_CTRL_LNKLED_OVERRIDE |
++				    LED_CTRL_1000MBPS_ON));
++	} else {
++		tp->link_config.active_speed = SPEED_INVALID;
++		tp->link_config.active_duplex = DUPLEX_INVALID;
++		tw32(MAC_LED_CTRL, (tp->led_ctrl |
++				    LED_CTRL_LNKLED_OVERRIDE |
++				    LED_CTRL_TRAFFIC_OVERRIDE));
++	}
++
++	if (current_link_up != netif_carrier_ok(tp->dev)) {
++		if (current_link_up)
++			netif_carrier_on(tp->dev);
++		else
++			netif_carrier_off(tp->dev);
++		tg3_link_report(tp);
++	} else {
++		u32 now_pause_cfg =
++			tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
++					 TG3_FLAG_TX_PAUSE);
++		if (orig_pause_cfg != now_pause_cfg ||
++		    orig_active_speed != tp->link_config.active_speed ||
++		    orig_active_duplex != tp->link_config.active_duplex)
++			tg3_link_report(tp);
++	}
++
++	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
++		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
++		udelay(40);
++		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
++			tw32_f(MAC_MODE, tp->mac_mode);
++			udelay(40);
++		}
++	}
++
++	return 0;
++}
++
++static int tg3_setup_phy(struct tg3 *tp, int force_reset)
++{
++	int err;
++
++	if (tp->phy_id == PHY_ID_SERDES) {
++		err = tg3_setup_fiber_phy(tp, force_reset);
++	} else {
++		err = tg3_setup_copper_phy(tp, force_reset);
++	}
++
++	if (tp->link_config.active_speed == SPEED_1000 &&
++	    tp->link_config.active_duplex == DUPLEX_HALF)
++		tw32(MAC_TX_LENGTHS,
++		     ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
++		      (6 << TX_LENGTHS_IPG_SHIFT) |
++		      (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
++	else
++		tw32(MAC_TX_LENGTHS,
++		     ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
++		      (6 << TX_LENGTHS_IPG_SHIFT) |
++		      (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++		if (netif_carrier_ok(tp->dev)) {
++			tw32(HOSTCC_STAT_COAL_TICKS,
++			     DEFAULT_STAT_COAL_TICKS);
++		} else {
++			tw32(HOSTCC_STAT_COAL_TICKS, 0);
++		}
++	}
++
++	return err;
++}
++
++/* Tigon3 never reports partial packet sends.  So we do not
++ * need special logic to handle SKBs that have not had all
++ * of their frags sent yet, like SunGEM does.
++ */
++static void tg3_tx(struct tg3 *tp)
++{
++	u32 hw_idx = tp->hw_status->idx[0].tx_consumer;
++	u32 sw_idx = tp->tx_cons;
++
++	while (sw_idx != hw_idx) {
++		struct tx_ring_info *ri = &tp->tx_buffers[sw_idx];
++		struct sk_buff *skb = ri->skb;
++		int i;
++
++		if (unlikely(skb == NULL))
++			BUG();
++
++		pci_unmap_single(tp->pdev,
++				 pci_unmap_addr(ri, mapping),
++				 skb_headlen(skb),
++				 PCI_DMA_TODEVICE);
++
++		ri->skb = NULL;
++
++		sw_idx = NEXT_TX(sw_idx);
++
++		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
++			if (unlikely(sw_idx == hw_idx))
++				BUG();
++
++			ri = &tp->tx_buffers[sw_idx];
++			if (unlikely(ri->skb != NULL))
++				BUG();
++
++			pci_unmap_page(tp->pdev,
++				       pci_unmap_addr(ri, mapping),
++				       skb_shinfo(skb)->frags[i].size,
++				       PCI_DMA_TODEVICE);
++
++			sw_idx = NEXT_TX(sw_idx);
++		}
++
++		dev_kfree_skb_irq(skb);
++	}
++
++	tp->tx_cons = sw_idx;
++
++	if (netif_queue_stopped(tp->dev) &&
++	    (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
++		netif_wake_queue(tp->dev);
++}
++
++/* Returns size of skb allocated or < 0 on error.
++ *
++ * We only need to fill in the address because the other members
++ * of the RX descriptor are invariant, see tg3_init_rings.
++ *
++ * Note the purposeful assymetry of cpu vs. chip accesses.  For
++ * posting buffers we only dirty the first cache line of the RX
++ * descriptor (containing the address).  Whereas for the RX status
++ * buffers the cpu only reads the last cacheline of the RX descriptor
++ * (to fetch the error flags, vlan tag, checksum, and opaque cookie).
++ */
++static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key,
++			    int src_idx, u32 dest_idx_unmasked)
++{
++	struct tg3_rx_buffer_desc *desc;
++	struct ring_info *map, *src_map;
++	struct sk_buff *skb;
++	dma_addr_t mapping;
++	int skb_size, dest_idx;
++
++	src_map = NULL;
++	switch (opaque_key) {
++	case RXD_OPAQUE_RING_STD:
++		dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
++		desc = &tp->rx_std[dest_idx];
++		map = &tp->rx_std_buffers[dest_idx];
++		if (src_idx >= 0)
++			src_map = &tp->rx_std_buffers[src_idx];
++		skb_size = RX_PKT_BUF_SZ;
++		break;
++
++	case RXD_OPAQUE_RING_JUMBO:
++		dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
++		desc = &tp->rx_jumbo[dest_idx];
++		map = &tp->rx_jumbo_buffers[dest_idx];
++		if (src_idx >= 0)
++			src_map = &tp->rx_jumbo_buffers[src_idx];
++		skb_size = RX_JUMBO_PKT_BUF_SZ;
++		break;
++
++	default:
++		return -EINVAL;
++	};
++
++	/* Do not overwrite any of the map or rp information
++	 * until we are sure we can commit to a new buffer.
++	 *
++	 * Callers depend upon this behavior and assume that
++	 * we leave everything unchanged if we fail.
++	 */
++	skb = dev_alloc_skb(skb_size);
++	if (skb == NULL)
++		return -ENOMEM;
++
++	skb->dev = tp->dev;
++	skb_reserve(skb, tp->rx_offset);
++
++	mapping = pci_map_single(tp->pdev, skb->data,
++				 skb_size - tp->rx_offset,
++				 PCI_DMA_FROMDEVICE);
++
++	map->skb = skb;
++	pci_unmap_addr_set(map, mapping, mapping);
++
++	if (src_map != NULL)
++		src_map->skb = NULL;
++
++	desc->addr_hi = ((u64)mapping >> 32);
++	desc->addr_lo = ((u64)mapping & 0xffffffff);
++
++	return skb_size;
++}
++
++/* We only need to move over in the address because the other
++ * members of the RX descriptor are invariant.  See notes above
++ * tg3_alloc_rx_skb for full details.
++ */
++static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key,
++			   int src_idx, u32 dest_idx_unmasked)
++{
++	struct tg3_rx_buffer_desc *src_desc, *dest_desc;
++	struct ring_info *src_map, *dest_map;
++	int dest_idx;
++
++	switch (opaque_key) {
++	case RXD_OPAQUE_RING_STD:
++		dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
++		dest_desc = &tp->rx_std[dest_idx];
++		dest_map = &tp->rx_std_buffers[dest_idx];
++		src_desc = &tp->rx_std[src_idx];
++		src_map = &tp->rx_std_buffers[src_idx];
++		break;
++
++	case RXD_OPAQUE_RING_JUMBO:
++		dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
++		dest_desc = &tp->rx_jumbo[dest_idx];
++		dest_map = &tp->rx_jumbo_buffers[dest_idx];
++		src_desc = &tp->rx_jumbo[src_idx];
++		src_map = &tp->rx_jumbo_buffers[src_idx];
++		break;
++
++	default:
++		return;
++	};
++
++	dest_map->skb = src_map->skb;
++	pci_unmap_addr_set(dest_map, mapping,
++			   pci_unmap_addr(src_map, mapping));
++	dest_desc->addr_hi = src_desc->addr_hi;
++	dest_desc->addr_lo = src_desc->addr_lo;
++
++	src_map->skb = NULL;
++}
++
++#if TG3_VLAN_TAG_USED
++static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag)
++{
++	return vlan_hwaccel_receive_skb(skb, tp->vlgrp, vlan_tag);
++}
++#endif
++
++/* The RX ring scheme is composed of multiple rings which post fresh
++ * buffers to the chip, and one special ring the chip uses to report
++ * status back to the host.
++ *
++ * The special ring reports the status of received packets to the
++ * host.  The chip does not write into the original descriptor the
++ * RX buffer was obtained from.  The chip simply takes the original
++ * descriptor as provided by the host, updates the status and length
++ * field, then writes this into the next status ring entry.
++ *
++ * Each ring the host uses to post buffers to the chip is described
++ * by a TG3_BDINFO entry in the chips SRAM area.  When a packet arrives,
++ * it is first placed into the on-chip ram.  When the packet's length
++ * is known, it walks down the TG3_BDINFO entries to select the ring.
++ * Each TG3_BDINFO specifies a MAXLEN field and the first TG3_BDINFO
++ * which is within the range of the new packet's length is chosen.
++ *
++ * The "separate ring for rx status" scheme may sound queer, but it makes
++ * sense from a cache coherency perspective.  If only the host writes
++ * to the buffer post rings, and only the chip writes to the rx status
++ * rings, then cache lines never move beyond shared-modified state.
++ * If both the host and chip were to write into the same ring, cache line
++ * eviction could occur since both entities want it in an exclusive state.
++ */
++static int tg3_rx(struct tg3 *tp, int budget)
++{
++	u32 work_mask;
++	u32 rx_rcb_ptr = tp->rx_rcb_ptr;
++	u16 hw_idx, sw_idx;
++	int received;
++
++	hw_idx = tp->hw_status->idx[0].rx_producer;
++	/*
++	 * We need to order the read of hw_idx and the read of
++	 * the opaque cookie.
++	 */
++	rmb();
++	sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp);
++	work_mask = 0;
++	received = 0;
++	while (sw_idx != hw_idx && budget > 0) {
++		struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx];
++		unsigned int len;
++		struct sk_buff *skb;
++		dma_addr_t dma_addr;
++		u32 opaque_key, desc_idx, *post_ptr;
++
++		desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
++		opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
++		if (opaque_key == RXD_OPAQUE_RING_STD) {
++			dma_addr = pci_unmap_addr(&tp->rx_std_buffers[desc_idx],
++						  mapping);
++			skb = tp->rx_std_buffers[desc_idx].skb;
++			post_ptr = &tp->rx_std_ptr;
++		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
++			dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx],
++						  mapping);
++			skb = tp->rx_jumbo_buffers[desc_idx].skb;
++			post_ptr = &tp->rx_jumbo_ptr;
++		}
++		else {
++			goto next_pkt_nopost;
++		}
++
++		work_mask |= opaque_key;
++
++		if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
++		    (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
++		drop_it:
++			tg3_recycle_rx(tp, opaque_key,
++				       desc_idx, *post_ptr);
++		drop_it_no_recycle:
++			/* Other statistics kept track of by card. */
++			tp->net_stats.rx_dropped++;
++			goto next_pkt;
++		}
++
++		len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */
++
++		if (len > RX_COPY_THRESHOLD) {
++			int skb_size;
++
++			skb_size = tg3_alloc_rx_skb(tp, opaque_key,
++						    desc_idx, *post_ptr);
++			if (skb_size < 0)
++				goto drop_it;
++
++			pci_unmap_single(tp->pdev, dma_addr,
++					 skb_size - tp->rx_offset,
++					 PCI_DMA_FROMDEVICE);
++
++			skb_put(skb, len);
++		} else {
++			struct sk_buff *copy_skb;
++
++			tg3_recycle_rx(tp, opaque_key,
++				       desc_idx, *post_ptr);
++
++			copy_skb = dev_alloc_skb(len + 2);
++			if (copy_skb == NULL)
++				goto drop_it_no_recycle;
++
++			copy_skb->dev = tp->dev;
++			skb_reserve(copy_skb, 2);
++			skb_put(copy_skb, len);
++			pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
++			memcpy(copy_skb->data, skb->data, len);
++			pci_dma_sync_single_for_device(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
++
++			/* We'll reuse the original ring buffer. */
++			skb = copy_skb;
++		}
++
++		if ((tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) &&
++		    (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) &&
++		    (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK)
++		      >> RXD_TCPCSUM_SHIFT) == 0xffff))
++			skb->ip_summed = CHECKSUM_UNNECESSARY;
++		else
++			skb->ip_summed = CHECKSUM_NONE;
++
++		skb->protocol = eth_type_trans(skb, tp->dev);
++#if TG3_VLAN_TAG_USED
++		if (tp->vlgrp != NULL &&
++		    desc->type_flags & RXD_FLAG_VLAN) {
++			tg3_vlan_rx(tp, skb,
++				    desc->err_vlan & RXD_VLAN_MASK);
++		} else
++#endif
++			netif_receive_skb(skb);
++
++		tp->dev->last_rx = jiffies;
++		received++;
++		budget--;
++
++next_pkt:
++		(*post_ptr)++;
++next_pkt_nopost:
++		rx_rcb_ptr++;
++		sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp);
++	}
++
++	/* ACK the status ring. */
++	tp->rx_rcb_ptr = rx_rcb_ptr;
++	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW,
++		     (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp)));
++
++	/* Refill RX ring(s). */
++	if (work_mask & RXD_OPAQUE_RING_STD) {
++		sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE;
++		tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
++			     sw_idx);
++	}
++	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
++		sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE;
++		tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
++			     sw_idx);
++	}
++
++	return received;
++}
++
++static int tg3_poll(struct net_device *netdev, int *budget)
++{
++	struct tg3 *tp = netdev_priv(netdev);
++	struct tg3_hw_status *sblk = tp->hw_status;
++	unsigned long flags;
++	int done;
++
++	spin_lock_irqsave(&tp->lock, flags);
++
++	/* handle link change and other phy events */
++	if (!(tp->tg3_flags &
++	      (TG3_FLAG_USE_LINKCHG_REG |
++	       TG3_FLAG_POLL_SERDES))) {
++		if (sblk->status & SD_STATUS_LINK_CHG) {
++			sblk->status = SD_STATUS_UPDATED |
++				(sblk->status & ~SD_STATUS_LINK_CHG);
++			tg3_setup_phy(tp, 0);
++		}
++	}
++
++	/* run TX completion thread */
++	if (sblk->idx[0].tx_consumer != tp->tx_cons) {
++		spin_lock(&tp->tx_lock);
++		tg3_tx(tp);
++		spin_unlock(&tp->tx_lock);
++	}
++
++	spin_unlock_irqrestore(&tp->lock, flags);
++
++	/* run RX thread, within the bounds set by NAPI.
++	 * All RX "locking" is done by ensuring outside
++	 * code synchronizes with dev->poll()
++	 */
++	done = 1;
++	if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
++		int orig_budget = *budget;
++		int work_done;
++
++		if (orig_budget > netdev->quota)
++			orig_budget = netdev->quota;
++
++		work_done = tg3_rx(tp, orig_budget);
++
++		*budget -= work_done;
++		netdev->quota -= work_done;
++
++		if (work_done >= orig_budget)
++			done = 0;
++	}
++
++	/* if no more work, tell net stack and NIC we're done */
++	if (done) {
++		spin_lock_irqsave(&tp->lock, flags);
++		__netif_rx_complete(netdev);
++		tg3_enable_ints(tp);
++		spin_unlock_irqrestore(&tp->lock, flags);
++	}
++
++	return (done ? 0 : 1);
++}
++
++static inline unsigned int tg3_has_work(struct net_device *dev, struct tg3 *tp)
++{
++	struct tg3_hw_status *sblk = tp->hw_status;
++	unsigned int work_exists = 0;
++
++	/* check for phy events */
++	if (!(tp->tg3_flags &
++	      (TG3_FLAG_USE_LINKCHG_REG |
++	       TG3_FLAG_POLL_SERDES))) {
++		if (sblk->status & SD_STATUS_LINK_CHG)
++			work_exists = 1;
++	}
++	/* check for RX/TX work to do */
++	if (sblk->idx[0].tx_consumer != tp->tx_cons ||
++	    sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
++		work_exists = 1;
++
++	return work_exists;
++}
++
++static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++	struct net_device *dev = dev_id;
++	struct tg3 *tp = netdev_priv(dev);
++	struct tg3_hw_status *sblk = tp->hw_status;
++	unsigned long flags;
++	unsigned int handled = 1;
++
++	spin_lock_irqsave(&tp->lock, flags);
++
++	if (sblk->status & SD_STATUS_UPDATED) {
++		/*
++		 * writing any value to intr-mbox-0 clears PCI INTA# and
++		 * chip-internal interrupt pending events.
++		 * writing non-zero to intr-mbox-0 additional tells the
++		 * NIC to stop sending us irqs, engaging "in-intr-handler"
++		 * event coalescing.
++		 */
++		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
++			     0x00000001);
++		/*
++		 * Flush PCI write.  This also guarantees that our
++		 * status block has been flushed to host memory.
++		 */
++		tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
++		sblk->status &= ~SD_STATUS_UPDATED;
++
++		if (likely(tg3_has_work(dev, tp)))
++			netif_rx_schedule(dev);		/* schedule NAPI poll */
++		else {
++			/* no work, shared interrupt perhaps?  re-enable
++			 * interrupts, and flush that PCI write
++			 */
++			tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
++			     	0x00000000);
++			tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
++		}
++	} else {	/* shared interrupt */
++		handled = 0;
++	}
++
++	spin_unlock_irqrestore(&tp->lock, flags);
++
++	return IRQ_RETVAL(handled);
++}
++
++static int tg3_init_hw(struct tg3 *);
++static int tg3_halt(struct tg3 *);
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++static void tg3_poll_controller(struct net_device *dev)
++{
++	tg3_interrupt(dev->irq, dev, NULL);
++}
++#endif
++
++static void tg3_reset_task(void *_data)
++{
++	struct tg3 *tp = _data;
++	unsigned int restart_timer;
++
++	tg3_netif_stop(tp);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
++	tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
++
++	tg3_halt(tp);
++	tg3_init_hw(tp);
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	tg3_netif_start(tp);
++
++	if (restart_timer)
++		mod_timer(&tp->timer, jiffies + 1);
++}
++
++static void tg3_tx_timeout(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++
++	printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
++	       dev->name);
++
++	schedule_work(&tp->reset_task);
++}
++
++static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
++
++static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
++				       u32 guilty_entry, int guilty_len,
++				       u32 last_plus_one, u32 *start, u32 mss)
++{
++	struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
++	dma_addr_t new_addr;
++	u32 entry = *start;
++	int i;
++
++	if (!new_skb) {
++		dev_kfree_skb(skb);
++		return -1;
++	}
++
++	/* New SKB is guaranteed to be linear. */
++	entry = *start;
++	new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
++				  PCI_DMA_TODEVICE);
++	tg3_set_txd(tp, entry, new_addr, new_skb->len,
++		    (skb->ip_summed == CHECKSUM_HW) ?
++		    TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1));
++	*start = NEXT_TX(entry);
++
++	/* Now clean up the sw ring entries. */
++	i = 0;
++	while (entry != last_plus_one) {
++		int len;
++
++		if (i == 0)
++			len = skb_headlen(skb);
++		else
++			len = skb_shinfo(skb)->frags[i-1].size;
++		pci_unmap_single(tp->pdev,
++				 pci_unmap_addr(&tp->tx_buffers[entry], mapping),
++				 len, PCI_DMA_TODEVICE);
++		if (i == 0) {
++			tp->tx_buffers[entry].skb = new_skb;
++			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, new_addr);
++		} else {
++			tp->tx_buffers[entry].skb = NULL;
++		}
++		entry = NEXT_TX(entry);
++	}
++
++	dev_kfree_skb(skb);
++
++	return 0;
++}
++
++static void tg3_set_txd(struct tg3 *tp, int entry,
++			dma_addr_t mapping, int len, u32 flags,
++			u32 mss_and_is_end)
++{
++	int is_end = (mss_and_is_end & 0x1);
++	u32 mss = (mss_and_is_end >> 1);
++	u32 vlan_tag = 0;
++
++	if (is_end)
++		flags |= TXD_FLAG_END;
++	if (flags & TXD_FLAG_VLAN) {
++		vlan_tag = flags >> 16;
++		flags &= 0xffff;
++	}
++	vlan_tag |= (mss << TXD_MSS_SHIFT);
++	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
++		struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
++
++		txd->addr_hi = ((u64) mapping >> 32);
++		txd->addr_lo = ((u64) mapping & 0xffffffff);
++		txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
++		txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
++	} else {
++		struct tx_ring_info *txr = &tp->tx_buffers[entry];
++		unsigned long txd;
++
++		txd = (tp->regs +
++		       NIC_SRAM_WIN_BASE +
++		       NIC_SRAM_TX_BUFFER_DESC);
++		txd += (entry * TXD_SIZE);
++
++		/* Save some PIOs */
++		if (sizeof(dma_addr_t) != sizeof(u32))
++			writel(((u64) mapping >> 32),
++			       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
++
++		writel(((u64) mapping & 0xffffffff),
++		       txd + TXD_ADDR + TG3_64BIT_REG_LOW);
++		writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS);
++		if (txr->prev_vlan_tag != vlan_tag) {
++			writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG);
++			txr->prev_vlan_tag = vlan_tag;
++		}
++	}
++}
++
++static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
++{
++	u32 base = (u32) mapping & 0xffffffff;
++
++	return ((base > 0xffffdcc0) &&
++		(base + len + 8 < base));
++}
++
++static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	dma_addr_t mapping;
++	unsigned int i;
++	u32 len, entry, base_flags, mss;
++	int would_hit_hwbug;
++	unsigned long flags;
++
++	len = skb_headlen(skb);
++
++	/* No BH disabling for tx_lock here.  We are running in BH disabled
++	 * context and TX reclaim runs via tp->poll inside of a software
++	 * interrupt.  Rejoice!
++	 *
++	 * Actually, things are not so simple.  If we are to take a hw
++	 * IRQ here, we can deadlock, consider:
++	 *
++	 *       CPU1		CPU2
++	 *   tg3_start_xmit
++	 *   take tp->tx_lock
++	 *			tg3_timer
++	 *			take tp->lock
++	 *   tg3_interrupt
++	 *   spin on tp->lock
++	 *			spin on tp->tx_lock
++	 *
++	 * So we really do need to disable interrupts when taking
++	 * tx_lock here.
++	 */
++	spin_lock_irqsave(&tp->tx_lock, flags);
++
++	/* This is a hard error, log it. */
++	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
++		netif_stop_queue(dev);
++		spin_unlock_irqrestore(&tp->tx_lock, flags);
++		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
++		       dev->name);
++		return 1;
++	}
++
++	entry = tp->tx_prod;
++	base_flags = 0;
++	if (skb->ip_summed == CHECKSUM_HW)
++		base_flags |= TXD_FLAG_TCPUDP_CSUM;
++#if TG3_TSO_SUPPORT != 0
++	mss = 0;
++	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
++	    (mss = skb_shinfo(skb)->tso_size) != 0) {
++		int tcp_opt_len, ip_tcp_len;
++
++		tcp_opt_len = ((skb->h.th->doff - 5) * 4);
++		ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
++
++		base_flags |= (TXD_FLAG_CPU_PRE_DMA |
++			       TXD_FLAG_CPU_POST_DMA);
++
++		skb->nh.iph->check = 0;
++		skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
++		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
++						      skb->nh.iph->daddr,
++						      0, IPPROTO_TCP, 0);
++
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
++			if (tcp_opt_len || skb->nh.iph->ihl > 5) {
++				int tsflags;
++
++				tsflags = ((skb->nh.iph->ihl - 5) +
++					   (tcp_opt_len >> 2));
++				mss |= (tsflags << 11);
++			}
++		} else {
++			if (tcp_opt_len || skb->nh.iph->ihl > 5) {
++				int tsflags;
++
++				tsflags = ((skb->nh.iph->ihl - 5) +
++					   (tcp_opt_len >> 2));
++				base_flags |= tsflags << 12;
++			}
++		}
++	}
++#else
++	mss = 0;
++#endif
++#if TG3_VLAN_TAG_USED
++	if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
++		base_flags |= (TXD_FLAG_VLAN |
++			       (vlan_tx_tag_get(skb) << 16));
++#endif
++
++	/* Queue skb data, a.k.a. the main skb fragment. */
++	mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
++
++	tp->tx_buffers[entry].skb = skb;
++	pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
++
++	would_hit_hwbug = 0;
++
++	if (tg3_4g_overflow_test(mapping, len))
++		would_hit_hwbug = entry + 1;
++
++	tg3_set_txd(tp, entry, mapping, len, base_flags,
++		    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
++
++	entry = NEXT_TX(entry);
++
++	/* Now loop through additional data fragments, and queue them. */
++	if (skb_shinfo(skb)->nr_frags > 0) {
++		unsigned int i, last;
++
++		last = skb_shinfo(skb)->nr_frags - 1;
++		for (i = 0; i <= last; i++) {
++			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
++
++			len = frag->size;
++			mapping = pci_map_page(tp->pdev,
++					       frag->page,
++					       frag->page_offset,
++					       len, PCI_DMA_TODEVICE);
++
++			tp->tx_buffers[entry].skb = NULL;
++			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
++
++			if (tg3_4g_overflow_test(mapping, len)) {
++				/* Only one should match. */
++				if (would_hit_hwbug)
++					BUG();
++				would_hit_hwbug = entry + 1;
++			}
++
++			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++				tg3_set_txd(tp, entry, mapping, len,
++					    base_flags, (i == last)|(mss << 1));
++			else
++				tg3_set_txd(tp, entry, mapping, len,
++					    base_flags, (i == last));
++
++			entry = NEXT_TX(entry);
++		}
++	}
++
++	if (would_hit_hwbug) {
++		u32 last_plus_one = entry;
++		u32 start;
++		unsigned int len = 0;
++
++		would_hit_hwbug -= 1;
++		entry = entry - 1 - skb_shinfo(skb)->nr_frags;
++		entry &= (TG3_TX_RING_SIZE - 1);
++		start = entry;
++		i = 0;
++		while (entry != last_plus_one) {
++			if (i == 0)
++				len = skb_headlen(skb);
++			else
++				len = skb_shinfo(skb)->frags[i-1].size;
++
++			if (entry == would_hit_hwbug)
++				break;
++
++			i++;
++			entry = NEXT_TX(entry);
++
++		}
++
++		/* If the workaround fails due to memory/mapping
++		 * failure, silently drop this packet.
++		 */
++		if (tigon3_4gb_hwbug_workaround(tp, skb,
++						entry, len,
++						last_plus_one,
++						&start, mss))
++			goto out_unlock;
++
++		entry = start;
++	}
++
++	/* Packets are ready, update Tx producer idx local and on card. */
++	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
++		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
++			      TG3_64BIT_REG_LOW), entry);
++	} else {
++		/* First, make sure tg3 sees last descriptor fully
++		 * in SRAM.
++		 */
++		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
++			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
++
++		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
++			      TG3_64BIT_REG_LOW), entry);
++	}
++
++	tp->tx_prod = entry;
++	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
++		netif_stop_queue(dev);
++
++out_unlock:
++	spin_unlock_irqrestore(&tp->tx_lock, flags);
++
++	dev->trans_start = jiffies;
++
++	return 0;
++}
++
++static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
++			       int new_mtu)
++{
++	dev->mtu = new_mtu;
++
++	if (new_mtu > ETH_DATA_LEN)
++		tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_JUMBO_ENABLE;
++}
++
++static int tg3_change_mtu(struct net_device *dev, int new_mtu)
++{
++	struct tg3 *tp = netdev_priv(dev);
++
++	if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
++		return -EINVAL;
++
++	if (!netif_running(dev)) {
++		/* We'll just catch it later when the
++		 * device is up'd.
++		 */
++		tg3_set_mtu(dev, tp, new_mtu);
++		return 0;
++	}
++
++	tg3_netif_stop(tp);
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	tg3_halt(tp);
++
++	tg3_set_mtu(dev, tp, new_mtu);
++
++	tg3_init_hw(tp);
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++	tg3_netif_start(tp);
++
++	return 0;
++}
++
++/* Free up pending packets in all rx/tx rings.
++ *
++ * The chip has been shut down and the driver detached from
++ * the networking, so no interrupts or new tx packets will
++ * end up in the driver.  tp->{tx,}lock is not held and we are not
++ * in an interrupt context and thus may sleep.
++ */
++static void tg3_free_rings(struct tg3 *tp)
++{
++	struct ring_info *rxp;
++	int i;
++
++	for (i = 0; i < TG3_RX_RING_SIZE; i++) {
++		rxp = &tp->rx_std_buffers[i];
++
++		if (rxp->skb == NULL)
++			continue;
++		pci_unmap_single(tp->pdev,
++				 pci_unmap_addr(rxp, mapping),
++				 RX_PKT_BUF_SZ - tp->rx_offset,
++				 PCI_DMA_FROMDEVICE);
++		dev_kfree_skb_any(rxp->skb);
++		rxp->skb = NULL;
++	}
++
++	for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) {
++		rxp = &tp->rx_jumbo_buffers[i];
++
++		if (rxp->skb == NULL)
++			continue;
++		pci_unmap_single(tp->pdev,
++				 pci_unmap_addr(rxp, mapping),
++				 RX_JUMBO_PKT_BUF_SZ - tp->rx_offset,
++				 PCI_DMA_FROMDEVICE);
++		dev_kfree_skb_any(rxp->skb);
++		rxp->skb = NULL;
++	}
++
++	for (i = 0; i < TG3_TX_RING_SIZE; ) {
++		struct tx_ring_info *txp;
++		struct sk_buff *skb;
++		int j;
++
++		txp = &tp->tx_buffers[i];
++		skb = txp->skb;
++
++		if (skb == NULL) {
++			i++;
++			continue;
++		}
++
++		pci_unmap_single(tp->pdev,
++				 pci_unmap_addr(txp, mapping),
++				 skb_headlen(skb),
++				 PCI_DMA_TODEVICE);
++		txp->skb = NULL;
++
++		i++;
++
++		for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) {
++			txp = &tp->tx_buffers[i & (TG3_TX_RING_SIZE - 1)];
++			pci_unmap_page(tp->pdev,
++				       pci_unmap_addr(txp, mapping),
++				       skb_shinfo(skb)->frags[j].size,
++				       PCI_DMA_TODEVICE);
++			i++;
++		}
++
++		dev_kfree_skb_any(skb);
++	}
++}
++
++/* Initialize tx/rx rings for packet processing.
++ *
++ * The chip has been shut down and the driver detached from
++ * the networking, so no interrupts or new tx packets will
++ * end up in the driver.  tp->{tx,}lock are held and thus
++ * we may not sleep.
++ */
++static void tg3_init_rings(struct tg3 *tp)
++{
++	unsigned long start, end;
++	u32 i;
++
++	/* Free up all the SKBs. */
++	tg3_free_rings(tp);
++
++	/* Zero out all descriptors. */
++	memset(tp->rx_std, 0, TG3_RX_RING_BYTES);
++	memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES);
++	memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
++
++	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
++		memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
++	} else {
++		start = (tp->regs +
++			 NIC_SRAM_WIN_BASE +
++			 NIC_SRAM_TX_BUFFER_DESC);
++		end = start + TG3_TX_RING_BYTES;
++		while (start < end) {
++			writel(0, start);
++			start += 4;
++		}
++		for (i = 0; i < TG3_TX_RING_SIZE; i++)
++			tp->tx_buffers[i].prev_vlan_tag = 0;
++	}
++
++	/* Initialize invariants of the rings, we only set this
++	 * stuff once.  This works because the card does not
++	 * write into the rx buffer posting rings.
++	 */
++	for (i = 0; i < TG3_RX_RING_SIZE; i++) {
++		struct tg3_rx_buffer_desc *rxd;
++
++		rxd = &tp->rx_std[i];
++		rxd->idx_len = (RX_PKT_BUF_SZ - tp->rx_offset - 64)
++			<< RXD_LEN_SHIFT;
++		rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT);
++		rxd->opaque = (RXD_OPAQUE_RING_STD |
++			       (i << RXD_OPAQUE_INDEX_SHIFT));
++	}
++
++	if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) {
++		for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) {
++			struct tg3_rx_buffer_desc *rxd;
++
++			rxd = &tp->rx_jumbo[i];
++			rxd->idx_len = (RX_JUMBO_PKT_BUF_SZ - tp->rx_offset - 64)
++				<< RXD_LEN_SHIFT;
++			rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT) |
++				RXD_FLAG_JUMBO;
++			rxd->opaque = (RXD_OPAQUE_RING_JUMBO |
++			       (i << RXD_OPAQUE_INDEX_SHIFT));
++		}
++	}
++
++	/* Now allocate fresh SKBs for each rx ring. */
++	for (i = 0; i < tp->rx_pending; i++) {
++		if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_STD,
++				     -1, i) < 0)
++			break;
++	}
++
++	if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) {
++		for (i = 0; i < tp->rx_jumbo_pending; i++) {
++			if (tg3_alloc_rx_skb(tp, RXD_OPAQUE_RING_JUMBO,
++					     -1, i) < 0)
++				break;
++		}
++	}
++}
++
++/*
++ * Must not be invoked with interrupt sources disabled and
++ * the hardware shutdown down.
++ */
++static void tg3_free_consistent(struct tg3 *tp)
++{
++	if (tp->rx_std_buffers) {
++		kfree(tp->rx_std_buffers);
++		tp->rx_std_buffers = NULL;
++	}
++	if (tp->rx_std) {
++		pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES,
++				    tp->rx_std, tp->rx_std_mapping);
++		tp->rx_std = NULL;
++	}
++	if (tp->rx_jumbo) {
++		pci_free_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES,
++				    tp->rx_jumbo, tp->rx_jumbo_mapping);
++		tp->rx_jumbo = NULL;
++	}
++	if (tp->rx_rcb) {
++		pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
++				    tp->rx_rcb, tp->rx_rcb_mapping);
++		tp->rx_rcb = NULL;
++	}
++	if (tp->tx_ring) {
++		pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES,
++			tp->tx_ring, tp->tx_desc_mapping);
++		tp->tx_ring = NULL;
++	}
++	if (tp->hw_status) {
++		pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
++				    tp->hw_status, tp->status_mapping);
++		tp->hw_status = NULL;
++	}
++	if (tp->hw_stats) {
++		pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats),
++				    tp->hw_stats, tp->stats_mapping);
++		tp->hw_stats = NULL;
++	}
++}
++
++/*
++ * Must not be invoked with interrupt sources disabled and
++ * the hardware shutdown down.  Can sleep.
++ */
++static int tg3_alloc_consistent(struct tg3 *tp)
++{
++	tp->rx_std_buffers = kmalloc((sizeof(struct ring_info) *
++				      (TG3_RX_RING_SIZE +
++				       TG3_RX_JUMBO_RING_SIZE)) +
++				     (sizeof(struct tx_ring_info) *
++				      TG3_TX_RING_SIZE),
++				     GFP_KERNEL);
++	if (!tp->rx_std_buffers)
++		return -ENOMEM;
++
++	memset(tp->rx_std_buffers, 0,
++	       (sizeof(struct ring_info) *
++		(TG3_RX_RING_SIZE +
++		 TG3_RX_JUMBO_RING_SIZE)) +
++	       (sizeof(struct tx_ring_info) *
++		TG3_TX_RING_SIZE));
++
++	tp->rx_jumbo_buffers = &tp->rx_std_buffers[TG3_RX_RING_SIZE];
++	tp->tx_buffers = (struct tx_ring_info *)
++		&tp->rx_jumbo_buffers[TG3_RX_JUMBO_RING_SIZE];
++
++	tp->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES,
++					  &tp->rx_std_mapping);
++	if (!tp->rx_std)
++		goto err_out;
++
++	tp->rx_jumbo = pci_alloc_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES,
++					    &tp->rx_jumbo_mapping);
++
++	if (!tp->rx_jumbo)
++		goto err_out;
++
++	tp->rx_rcb = pci_alloc_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
++					  &tp->rx_rcb_mapping);
++	if (!tp->rx_rcb)
++		goto err_out;
++
++	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
++		tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
++						   &tp->tx_desc_mapping);
++		if (!tp->tx_ring)
++			goto err_out;
++	} else {
++		tp->tx_ring = NULL;
++		tp->tx_desc_mapping = 0;
++	}
++
++	tp->hw_status = pci_alloc_consistent(tp->pdev,
++					     TG3_HW_STATUS_SIZE,
++					     &tp->status_mapping);
++	if (!tp->hw_status)
++		goto err_out;
++
++	tp->hw_stats = pci_alloc_consistent(tp->pdev,
++					    sizeof(struct tg3_hw_stats),
++					    &tp->stats_mapping);
++	if (!tp->hw_stats)
++		goto err_out;
++
++	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
++	memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
++
++	return 0;
++
++err_out:
++	tg3_free_consistent(tp);
++	return -ENOMEM;
++}
++
++#define MAX_WAIT_CNT 1000
++
++/* To stop a block, clear the enable bit and poll till it
++ * clears.  tp->lock is held.
++ */
++static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit)
++{
++	unsigned int i;
++	u32 val;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		switch (ofs) {
++		case RCVLSC_MODE:
++		case DMAC_MODE:
++		case MBFREE_MODE:
++		case BUFMGR_MODE:
++		case MEMARB_MODE:
++			/* We can't enable/disable these bits of the
++			 * 5705/5750, just say success.
++			 */
++			return 0;
++
++		default:
++			break;
++		};
++	}
++
++	val = tr32(ofs);
++	val &= ~enable_bit;
++	tw32_f(ofs, val);
++
++	for (i = 0; i < MAX_WAIT_CNT; i++) {
++		udelay(100);
++		val = tr32(ofs);
++		if ((val & enable_bit) == 0)
++			break;
++	}
++
++	if (i == MAX_WAIT_CNT) {
++		printk(KERN_ERR PFX "tg3_stop_block timed out, "
++		       "ofs=%lx enable_bit=%x\n",
++		       ofs, enable_bit);
++		return -ENODEV;
++	}
++
++	return 0;
++}
++
++/* tp->lock is held. */
++static int tg3_abort_hw(struct tg3 *tp)
++{
++	int i, err;
++
++	tg3_disable_ints(tp);
++
++	tp->rx_mode &= ~RX_MODE_ENABLE;
++	tw32_f(MAC_RX_MODE, tp->rx_mode);
++	udelay(10);
++
++	err  = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE);
++	err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE);
++	err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE);
++
++	err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE);
++	err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE);
++	err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
++	err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE);
++	if (err)
++		goto out;
++
++	tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
++	tw32_f(MAC_MODE, tp->mac_mode);
++	udelay(40);
++
++	tp->tx_mode &= ~TX_MODE_ENABLE;
++	tw32_f(MAC_TX_MODE, tp->tx_mode);
++
++	for (i = 0; i < MAX_WAIT_CNT; i++) {
++		udelay(100);
++		if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
++			break;
++	}
++	if (i >= MAX_WAIT_CNT) {
++		printk(KERN_ERR PFX "tg3_abort_hw timed out for %s, "
++		       "TX_MODE_ENABLE will not clear MAC_TX_MODE=%08x\n",
++		       tp->dev->name, tr32(MAC_TX_MODE));
++		return -ENODEV;
++	}
++
++	err  = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE);
++	err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
++
++	tw32(FTQ_RESET, 0xffffffff);
++	tw32(FTQ_RESET, 0x00000000);
++
++	err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
++	err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
++	if (err)
++		goto out;
++
++	if (tp->hw_status)
++		memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
++	if (tp->hw_stats)
++		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
++
++out:
++	return err;
++}
++
++/* tp->lock is held. */
++static int tg3_nvram_lock(struct tg3 *tp)
++{
++	if (tp->tg3_flags & TG3_FLAG_NVRAM) {
++		int i;
++
++		tw32(NVRAM_SWARB, SWARB_REQ_SET1);
++		for (i = 0; i < 8000; i++) {
++			if (tr32(NVRAM_SWARB) & SWARB_GNT1)
++				break;
++			udelay(20);
++		}
++		if (i == 8000)
++			return -ENODEV;
++	}
++	return 0;
++}
++
++/* tp->lock is held. */
++static void tg3_nvram_unlock(struct tg3 *tp)
++{
++	if (tp->tg3_flags & TG3_FLAG_NVRAM)
++		tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
++}
++
++/* tp->lock is held. */
++static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
++{
++	tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
++		      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
++
++	if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
++		switch (kind) {
++		case RESET_KIND_INIT:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_START);
++			break;
++
++		case RESET_KIND_SHUTDOWN:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_UNLOAD);
++			break;
++
++		case RESET_KIND_SUSPEND:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_SUSPEND);
++			break;
++
++		default:
++			break;
++		};
++	}
++}
++
++/* tp->lock is held. */
++static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
++{
++	if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
++		switch (kind) {
++		case RESET_KIND_INIT:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_START_DONE);
++			break;
++
++		case RESET_KIND_SHUTDOWN:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_UNLOAD_DONE);
++			break;
++
++		default:
++			break;
++		};
++	}
++}
++
++/* tp->lock is held. */
++static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
++{
++	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
++		switch (kind) {
++		case RESET_KIND_INIT:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_START);
++			break;
++
++		case RESET_KIND_SHUTDOWN:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_UNLOAD);
++			break;
++
++		case RESET_KIND_SUSPEND:
++			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
++				      DRV_STATE_SUSPEND);
++			break;
++
++		default:
++			break;
++		};
++	}
++}
++
++/* tp->lock is held. */
++static int tg3_chip_reset(struct tg3 *tp)
++{
++	u32 val;
++	u32 flags_save;
++	int i;
++
++	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704))
++		tg3_nvram_lock(tp);
++
++	/*
++	 * We must avoid the readl() that normally takes place.
++	 * It locks machines, causes machine checks, and other
++	 * fun things.  So, temporarily disable the 5701
++	 * hardware workaround, while we do the reset.
++	 */
++	flags_save = tp->tg3_flags;
++	tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG;
++
++	/* do the reset */
++	val = GRC_MISC_CFG_CORECLK_RESET;
++
++	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
++		if (tr32(0x7e2c) == 0x60) {
++			tw32(0x7e2c, 0x20);
++		}
++		if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
++			tw32(GRC_MISC_CFG, (1 << 29));
++			val |= (1 << 29);
++		}
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
++	tw32(GRC_MISC_CFG, val);
++
++	/* restore 5701 hardware bug workaround flag */
++	tp->tg3_flags = flags_save;
++
++	/* Unfortunately, we have to delay before the PCI read back.
++	 * Some 575X chips even will not respond to a PCI cfg access
++	 * when the reset command is given to the chip.
++	 *
++	 * How do these hardware designers expect things to work
++	 * properly if the PCI write is posted for a long period
++	 * of time?  It is always necessary to have some method by
++	 * which a register read back can occur to push the write
++	 * out which does the reset.
++	 *
++	 * For most tg3 variants the trick below was working.
++	 * Ho hum...
++	 */
++	udelay(120);
++
++	/* Flush PCI posted writes.  The normal MMIO registers
++	 * are inaccessible at this time so this is the only
++	 * way to make this reliably (actually, this is no longer
++	 * the case, see above).  I tried to use indirect
++	 * register read/write but this upset some 5701 variants.
++	 */
++	pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
++
++	udelay(120);
++
++	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
++		if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
++			int i;
++			u32 cfg_val;
++
++			/* Wait for link training to complete.  */
++			for (i = 0; i < 5000; i++)
++				udelay(100);
++
++			pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
++			pci_write_config_dword(tp->pdev, 0xc4,
++					       cfg_val | (1 << 15));
++		}
++		/* Set PCIE max payload size and clear error status.  */
++		pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
++	}
++
++	/* Re-enable indirect register accesses. */
++	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
++			       tp->misc_host_ctrl);
++
++	/* Set MAX PCI retry to zero. */
++	val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
++	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
++		val |= PCISTATE_RETRY_SAME_DMA;
++	pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
++
++	pci_restore_state(tp->pdev, tp->pci_cfg_state);
++
++	/* Make sure PCI-X relaxed ordering bit is clear. */
++	pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
++	val &= ~PCIX_CAPS_RELAXED_ORDERING;
++	pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
++
++	tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
++
++	tw32(GRC_MODE, tp->grc_mode);
++
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
++		u32 val = tr32(0xc4);
++
++		tw32(0xc4, val | (1 << 15));
++	}
++
++	if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
++		tp->pci_clock_ctrl |= CLOCK_CTRL_CLKRUN_OENABLE;
++		if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)
++			tp->pci_clock_ctrl |= CLOCK_CTRL_FORCE_CLKRUN;
++		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
++	}
++
++	if (tp->phy_id == PHY_ID_SERDES) {
++		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
++		tw32_f(MAC_MODE, tp->mac_mode);
++	} else
++		tw32_f(MAC_MODE, 0);
++	udelay(40);
++
++	/* Wait for firmware initialization to complete. */
++	for (i = 0; i < 100000; i++) {
++		tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
++		if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
++			break;
++		udelay(10);
++	}
++	if (i >= 100000 &&
++	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
++		printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
++		       "firmware will not restart magic=%08x\n",
++		       tp->dev->name, val);
++		return -ENODEV;
++	}
++
++	if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
++	    tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
++		u32 val = tr32(0x7c00);
++
++		tw32(0x7c00, val | (1 << 25));
++	}
++
++	/* Reprobe ASF enable state.  */
++	tp->tg3_flags &= ~TG3_FLAG_ENABLE_ASF;
++	tp->tg3_flags2 &= ~TG3_FLG2_ASF_NEW_HANDSHAKE;
++	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
++	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
++		u32 nic_cfg;
++
++		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
++		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
++			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
++			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
++		}
++	}
++
++	return 0;
++}
++
++/* tp->lock is held. */
++static void tg3_stop_fw(struct tg3 *tp)
++{
++	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
++		u32 val;
++		int i;
++
++		tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
++		val = tr32(GRC_RX_CPU_EVENT);
++		val |= (1 << 14);
++		tw32(GRC_RX_CPU_EVENT, val);
++
++		/* Wait for RX cpu to ACK the event.  */
++		for (i = 0; i < 100; i++) {
++			if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14)))
++				break;
++			udelay(1);
++		}
++	}
++}
++
++/* tp->lock is held. */
++static int tg3_halt(struct tg3 *tp)
++{
++	int err;
++
++	tg3_stop_fw(tp);
++
++	tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN);
++
++	tg3_abort_hw(tp);
++	err = tg3_chip_reset(tp);
++
++	tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN);
++	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
++
++	if (err)
++		return err;
++
++	return 0;
++}
++
++#define RX_CPU_SCRATCH_BASE	0x30000
++#define RX_CPU_SCRATCH_SIZE	0x04000
++#define TX_CPU_SCRATCH_BASE	0x34000
++#define TX_CPU_SCRATCH_SIZE	0x04000
++
++/* tp->lock is held. */
++static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
++{
++	int i;
++
++	if (offset == TX_CPU_BASE &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
++		BUG();
++
++	if (offset == RX_CPU_BASE) {
++		for (i = 0; i < 10000; i++) {
++			tw32(offset + CPU_STATE, 0xffffffff);
++			tw32(offset + CPU_MODE,  CPU_MODE_HALT);
++			if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
++				break;
++		}
++
++		tw32(offset + CPU_STATE, 0xffffffff);
++		tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
++		udelay(10);
++	} else {
++		for (i = 0; i < 10000; i++) {
++			tw32(offset + CPU_STATE, 0xffffffff);
++			tw32(offset + CPU_MODE,  CPU_MODE_HALT);
++			if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
++				break;
++		}
++	}
++
++	if (i >= 10000) {
++		printk(KERN_ERR PFX "tg3_reset_cpu timed out for %s, "
++		       "and %s CPU\n",
++		       tp->dev->name,
++		       (offset == RX_CPU_BASE ? "RX" : "TX"));
++		return -ENODEV;
++	}
++	return 0;
++}
++
++struct fw_info {
++	unsigned int text_base;
++	unsigned int text_len;
++	u32 *text_data;
++	unsigned int rodata_base;
++	unsigned int rodata_len;
++	u32 *rodata_data;
++	unsigned int data_base;
++	unsigned int data_len;
++	u32 *data_data;
++	unsigned int sbss_len;
++	unsigned int bss_len;
++};
++
++/* We are forced to store these firmware bits in memory for the duration
++ * of the module load, because they are loaded to hardware in a context
++ * where it is unsafe to sleep, and fixing this would require a lot of
++ * code refactoring.  :-P  However, they're only filled if the hardware
++ * needs them; otherwise they are NULL and do not need to be dealt with.
++ */
++
++static struct fw_info *tg3_fw_5701_a0;
++
++#if TG3_TSO_SUPPORT != 0
++static struct fw_info *tg3_fw_tso;
++static struct fw_info *tg3_fw_tso5;
++#endif /* TG3_TSO_SUPPORT */
++
++/* Wipe out one fw_info structure; it must be fully allocated */
++static void tg3_release_firmware(struct fw_info **info_ptr) {
++	struct fw_info *info = *info_ptr;
++	if (!info)
++		return;
++	kfree(info->data_data);
++	kfree(info->rodata_data);
++	kfree(info->text_data);
++	kfree(info);
++	*info_ptr = NULL;
++}
++
++/* Allocate and fill 'info' from a file in userspace.
++ * This *must* be called in user context where sleeping is allowed.
++ * We require the firmware file to be in a certain binary format:
++ * little-endian (so that it's platform-independent -- heh)
++ * struct fw_info fields in this order:
++ * text_base, text_len, rodata_base, rodata_len, data_base, data_len
++ * ('unsigned int' fields as 32-bit integers)
++ * text_data, rodata_data, data_data
++ * ('u32*' fields as a whole bunch of 32-bit integers)
++ */
++static int __devinit tg3_request_firmware(struct fw_info **info_ptr,
++					  const char *filename,
++					  const struct tg3 *tp)
++{
++	int err, i;
++	int text_zero, rodata_zero, data_zero;
++	const struct firmware *fw_entry;
++	struct fw_info *info;
++	u32 *data;
++	unsigned int len;
++
++	if (*info_ptr)
++		return 0;
++
++	err = request_firmware(&fw_entry, filename, &tp->pdev->dev);
++	if (err) {
++		printk(KERN_WARNING PFX "tg3_request_firmware (%s): "
++		       "Couldn't get firmware \"%s\".\n",
++		       tp->dev->name, filename);
++		goto cleanup_out;
++	}
++
++	len = fw_entry->size;
++	if (len < 44) {
++		printk(KERN_WARNING PFX "tg3_request_firmware (%s): "
++		       "Firmware \"%s\" is too short.\n",
++		       tp->dev->name, filename);
++		err = -EINVAL;
++		goto cleanup_firmware;
++	}
++	len -= 44;
++
++	info = kmalloc(sizeof(*info), GFP_KERNEL);
++	if (!info) {
++		err = -ENOMEM;
++		goto cleanup_firmware;
++	}
++
++	data = (u32 *)fw_entry->data;
++
++	info->text_base = le32_to_cpu(data[0]);
++	info->text_len = le32_to_cpu(data[1]);
++	text_zero = data[2];
++
++	info->rodata_base = le32_to_cpu(data[3]);
++	info->rodata_len = le32_to_cpu(data[4]);
++	rodata_zero = data[5];
++
++	info->data_base = le32_to_cpu(data[6]);
++	info->data_len = le32_to_cpu(data[7]);
++	data_zero = data[8];
++
++	info->sbss_len = le32_to_cpu(data[9]);
++	info->bss_len = le32_to_cpu(data[10]);
++
++	data += 11;
++
++	if (len != (!text_zero ? info->text_len : 0) +
++		   (!rodata_zero ? info->rodata_len : 0) +
++		   (!data_zero ? info->data_len : 0)) {
++		printk(KERN_WARNING PFX "tg3_request_firmware (%s): "
++		       "Firmware \"%s\" length doesn't add up.\n",
++		       tp->dev->name, filename);
++		err = -EINVAL;
++		goto cleanup_info;
++	}
++
++	info->text_data = NULL;
++	if (!text_zero) {
++		info->text_data = kmalloc(info->text_len, GFP_KERNEL);
++		if (info->text_data == NULL) {
++			err = -ENOMEM;
++			goto cleanup_info;
++		}
++		for (i = 0; i < info->text_len / 4; i++)
++			info->text_data[i] = le32_to_cpu(*data++);
++	}
++
++	info->rodata_data = NULL;
++	if (!rodata_zero) {
++		info->rodata_data = kmalloc(info->rodata_len, GFP_KERNEL);
++		if (info->rodata_data == NULL) {
++			err = -ENOMEM;
++			goto cleanup_text;
++		}
++		for (i = 0; i < info->rodata_len / 4; i++)
++			info->rodata_data[i] = le32_to_cpu(*data++);
++	}
++
++	info->data_data = NULL;
++	if (!data_zero) {
++		info->data_data = kmalloc(info->data_len, GFP_KERNEL);
++		if (info->data_data == NULL) {
++			err = -ENOMEM;
++			goto cleanup_rodata;
++		}
++		for (i = 0; i < info->data_len / 4; i++)
++			info->data_data[i] = le32_to_cpu(*data++);
++	}
++
++	*info_ptr = info;
++	err = 0;
++
++cleanup_firmware:
++	release_firmware(fw_entry);
++cleanup_out:
++	return err;
++
++cleanup_rodata:
++	kfree(info->rodata_data);
++cleanup_text:
++	kfree(info->text_data);
++cleanup_info:
++	kfree(info);
++	goto cleanup_firmware;
++}
++
++/* tp->lock is held. */
++static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base,
++				 int cpu_scratch_size, struct fw_info *info)
++{
++	int err, i;
++	u32 orig_tg3_flags = tp->tg3_flags;
++	void (*write_op)(struct tg3 *, u32, u32);
++
++	if (cpu_base == TX_CPU_BASE &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
++		printk(KERN_ERR PFX "tg3_load_firmware_cpu: Trying to load "
++		       "TX cpu firmware on %s which is 5705.\n",
++		       tp->dev->name);
++		return -EINVAL;
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
++		write_op = tg3_write_mem;
++	else
++		write_op = tg3_write_indirect_reg32;
++
++	/* Force use of PCI config space for indirect register
++	 * write calls.
++	 */
++	tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
++
++	err = tg3_halt_cpu(tp, cpu_base);
++	if (err)
++		goto out;
++
++	for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
++		write_op(tp, cpu_scratch_base + i, 0);
++	tw32(cpu_base + CPU_STATE, 0xffffffff);
++	tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
++	for (i = 0; i < (info->text_len / sizeof(u32)); i++)
++		write_op(tp, (cpu_scratch_base +
++			      (info->text_base & 0xffff) +
++			      (i * sizeof(u32))),
++			 (info->text_data ?
++			  info->text_data[i] : 0));
++	for (i = 0; i < (info->rodata_len / sizeof(u32)); i++)
++		write_op(tp, (cpu_scratch_base +
++			      (info->rodata_base & 0xffff) +
++			      (i * sizeof(u32))),
++			 (info->rodata_data ?
++			  info->rodata_data[i] : 0));
++	for (i = 0; i < (info->data_len / sizeof(u32)); i++)
++		write_op(tp, (cpu_scratch_base +
++			      (info->data_base & 0xffff) +
++			      (i * sizeof(u32))),
++			 (info->data_data ?
++			  info->data_data[i] : 0));
++
++	err = 0;
++
++out:
++	tp->tg3_flags = orig_tg3_flags;
++	return err;
++}
++
++/* tp->lock is held. */
++static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
++{
++	int err, i;
++
++	err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
++				    RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
++				    tg3_fw_5701_a0);
++	if (err)
++		return err;
++
++	err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
++				    TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
++				    tg3_fw_5701_a0);
++	if (err)
++		return err;
++
++	/* Now startup only the RX cpu. */
++	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
++	tw32_f(RX_CPU_BASE + CPU_PC, tg3_fw_5701_a0->text_base);
++
++	for (i = 0; i < 5; i++) {
++		if (tr32(RX_CPU_BASE + CPU_PC) == tg3_fw_5701_a0->text_base)
++			break;
++		tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
++		tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
++		tw32_f(RX_CPU_BASE + CPU_PC,  tg3_fw_5701_a0->text_base);
++		udelay(1000);
++	}
++	if (i >= 5) {
++		printk(KERN_ERR PFX "tg3_load_firmware fails for %s "
++		       "to set RX CPU PC, is %08x should be %08x\n",
++		       tp->dev->name, tr32(RX_CPU_BASE + CPU_PC),
++		       tg3_fw_5701_a0->text_base);
++		return -ENODEV;
++	}
++	tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
++	tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
++
++	return 0;
++}
++
++#if TG3_TSO_SUPPORT != 0
++
++/* tp->lock is held. */
++static int tg3_load_tso_firmware(struct tg3 *tp)
++{
++	struct fw_info *info;
++	unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
++	int err, i;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		return 0;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
++		info = tg3_fw_tso5;
++		cpu_base = RX_CPU_BASE;
++		cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
++		cpu_scratch_size = (info->text_len +
++				    info->rodata_len +
++				    info->data_len +
++				    info->sbss_len +
++				    info->bss_len);
++	} else {
++		info = tg3_fw_tso;
++		cpu_base = TX_CPU_BASE;
++		cpu_scratch_base = TX_CPU_SCRATCH_BASE;
++		cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
++	}
++
++	err = tg3_load_firmware_cpu(tp, cpu_base,
++				    cpu_scratch_base, cpu_scratch_size,
++				    info);
++	if (err)
++		return err;
++
++	/* Now startup the cpu. */
++	tw32(cpu_base + CPU_STATE, 0xffffffff);
++	tw32_f(cpu_base + CPU_PC,  info->text_base);
++
++	for (i = 0; i < 5; i++) {
++		if (tr32(cpu_base + CPU_PC) == info->text_base)
++			break;
++		tw32(cpu_base + CPU_STATE, 0xffffffff);
++		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
++		tw32_f(cpu_base + CPU_PC,  info->text_base);
++		udelay(1000);
++	}
++	if (i >= 5) {
++		printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s "
++		       "to set CPU PC, is %08x should be %08x\n",
++		       tp->dev->name, tr32(cpu_base + CPU_PC),
++		       info->text_base);
++		return -ENODEV;
++	}
++	tw32(cpu_base + CPU_STATE, 0xffffffff);
++	tw32_f(cpu_base + CPU_MODE,  0x00000000);
++	return 0;
++}
++
++#endif /* TG3_TSO_SUPPORT != 0 */
++
++/* tp->lock is held. */
++static void __tg3_set_mac_addr(struct tg3 *tp)
++{
++	u32 addr_high, addr_low;
++	int i;
++
++	addr_high = ((tp->dev->dev_addr[0] << 8) |
++		     tp->dev->dev_addr[1]);
++	addr_low = ((tp->dev->dev_addr[2] << 24) |
++		    (tp->dev->dev_addr[3] << 16) |
++		    (tp->dev->dev_addr[4] <<  8) |
++		    (tp->dev->dev_addr[5] <<  0));
++	for (i = 0; i < 4; i++) {
++		tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
++		tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
++		for (i = 0; i < 12; i++) {
++			tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
++			tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
++		}
++	}
++
++	addr_high = (tp->dev->dev_addr[0] +
++		     tp->dev->dev_addr[1] +
++		     tp->dev->dev_addr[2] +
++		     tp->dev->dev_addr[3] +
++		     tp->dev->dev_addr[4] +
++		     tp->dev->dev_addr[5]) &
++		TX_BACKOFF_SEED_MASK;
++	tw32(MAC_TX_BACKOFF_SEED, addr_high);
++}
++
++static int tg3_set_mac_addr(struct net_device *dev, void *p)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	struct sockaddr *addr = p;
++
++	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++
++	spin_lock_irq(&tp->lock);
++	__tg3_set_mac_addr(tp);
++	spin_unlock_irq(&tp->lock);
++
++	return 0;
++}
++
++/* tp->lock is held. */
++static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
++			   dma_addr_t mapping, u32 maxlen_flags,
++			   u32 nic_addr)
++{
++	tg3_write_mem(tp,
++		      (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH),
++		      ((u64) mapping >> 32));
++	tg3_write_mem(tp,
++		      (bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW),
++		      ((u64) mapping & 0xffffffff));
++	tg3_write_mem(tp,
++		      (bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS),
++		       maxlen_flags);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)
++		tg3_write_mem(tp,
++			      (bdinfo_addr + TG3_BDINFO_NIC_ADDR),
++			      nic_addr);
++}
++
++static void __tg3_set_rx_mode(struct net_device *);
++
++/* tp->lock is held. */
++static int tg3_reset_hw(struct tg3 *tp)
++{
++	u32 val, rdmac_mode;
++	int i, err, limit;
++
++	tg3_disable_ints(tp);
++
++	tg3_stop_fw(tp);
++
++	tg3_write_sig_pre_reset(tp, RESET_KIND_INIT);
++
++	if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
++		err = tg3_abort_hw(tp);
++		if (err)
++			return err;
++	}
++
++	err = tg3_chip_reset(tp);
++	if (err)
++		return err;
++
++	tg3_write_sig_legacy(tp, RESET_KIND_INIT);
++
++	/* This works around an issue with Athlon chipsets on
++	 * B3 tigon3 silicon.  This bit has no effect on any
++	 * other revision.  But do not set this on PCI Express
++	 * chips.
++	 */
++	if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
++		tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
++	tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
++
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
++	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
++		val = tr32(TG3PCI_PCISTATE);
++		val |= PCISTATE_RETRY_SAME_DMA;
++		tw32(TG3PCI_PCISTATE, val);
++	}
++
++	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) {
++		/* Enable some hw fixes.  */
++		val = tr32(TG3PCI_MSI_DATA);
++		val |= (1 << 26) | (1 << 28) | (1 << 29);
++		tw32(TG3PCI_MSI_DATA, val);
++	}
++
++	/* Descriptor ring init may make accesses to the
++	 * NIC SRAM area to setup the TX descriptors, so we
++	 * can only do this after the hardware has been
++	 * successfully reset.
++	 */
++	tg3_init_rings(tp);
++
++	/* This value is determined during the probe time DMA
++	 * engine test, tg3_test_dma.
++	 */
++	tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
++
++	tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
++			  GRC_MODE_4X_NIC_SEND_RINGS |
++			  GRC_MODE_NO_TX_PHDR_CSUM |
++			  GRC_MODE_NO_RX_PHDR_CSUM);
++	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS)
++		tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
++	else
++		tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS;
++	if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
++		tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
++	if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
++		tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
++
++	tw32(GRC_MODE,
++	     tp->grc_mode |
++	     (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
++
++	/* Setup the timer prescalar register.  Clock is always 66Mhz. */
++	val = tr32(GRC_MISC_CFG);
++	val &= ~0xff;
++	val |= (65 << GRC_MISC_CFG_PRESCALAR_SHIFT);
++	tw32(GRC_MISC_CFG, val);
++
++	/* Initialize MBUF/DESC pool. */
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		/* Do nothing.  */
++	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
++		tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
++			tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
++		else
++			tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
++		tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
++		tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
++	}
++#if TG3_TSO_SUPPORT != 0
++	else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
++		int fw_len;
++
++		fw_len = (tg3_fw_tso5->text_len +
++			  tg3_fw_tso5->rodata_len +
++			  tg3_fw_tso5->data_len +
++			  tg3_fw_tso5->sbss_len +
++			  tg3_fw_tso5->bss_len);
++		fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1);
++		tw32(BUFMGR_MB_POOL_ADDR,
++		     NIC_SRAM_MBUF_POOL_BASE5705 + fw_len);
++		tw32(BUFMGR_MB_POOL_SIZE,
++		     NIC_SRAM_MBUF_POOL_SIZE5705 - fw_len - 0xa00);
++	}
++#endif
++
++	if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) {
++		tw32(BUFMGR_MB_RDMA_LOW_WATER,
++		     tp->bufmgr_config.mbuf_read_dma_low_water);
++		tw32(BUFMGR_MB_MACRX_LOW_WATER,
++		     tp->bufmgr_config.mbuf_mac_rx_low_water);
++		tw32(BUFMGR_MB_HIGH_WATER,
++		     tp->bufmgr_config.mbuf_high_water);
++	} else {
++		tw32(BUFMGR_MB_RDMA_LOW_WATER,
++		     tp->bufmgr_config.mbuf_read_dma_low_water_jumbo);
++		tw32(BUFMGR_MB_MACRX_LOW_WATER,
++		     tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo);
++		tw32(BUFMGR_MB_HIGH_WATER,
++		     tp->bufmgr_config.mbuf_high_water_jumbo);
++	}
++	tw32(BUFMGR_DMA_LOW_WATER,
++	     tp->bufmgr_config.dma_low_water);
++	tw32(BUFMGR_DMA_HIGH_WATER,
++	     tp->bufmgr_config.dma_high_water);
++
++	tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
++	for (i = 0; i < 2000; i++) {
++		if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
++			break;
++		udelay(10);
++	}
++	if (i >= 2000) {
++		printk(KERN_ERR PFX "tg3_reset_hw cannot enable BUFMGR for %s.\n",
++		       tp->dev->name);
++		return -ENODEV;
++	}
++
++	/* Setup replenish threshold. */
++	tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8);
++
++	/* Initialize TG3_BDINFO's at:
++	 *  RCVDBDI_STD_BD:	standard eth size rx ring
++	 *  RCVDBDI_JUMBO_BD:	jumbo frame rx ring
++	 *  RCVDBDI_MINI_BD:	small frame rx ring (??? does not work)
++	 *
++	 * like so:
++	 *  TG3_BDINFO_HOST_ADDR:	high/low parts of DMA address of ring
++	 *  TG3_BDINFO_MAXLEN_FLAGS:	(rx max buffer size << 16) |
++	 *                              ring attribute flags
++	 *  TG3_BDINFO_NIC_ADDR:	location of descriptors in nic SRAM
++	 *
++	 * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries.
++	 * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries.
++	 *
++	 * The size of each ring is fixed in the firmware, but the location is
++	 * configurable.
++	 */
++	tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH,
++	     ((u64) tp->rx_std_mapping >> 32));
++	tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
++	     ((u64) tp->rx_std_mapping & 0xffffffff));
++	tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR,
++	     NIC_SRAM_RX_BUFFER_DESC);
++
++	/* Don't even try to program the JUMBO/MINI buffer descriptor
++	 * configs on 5705.
++	 */
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS,
++		     RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT);
++	} else {
++		tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS,
++		     RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT);
++
++		tw32(RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS,
++		     BDINFO_FLAGS_DISABLED);
++
++		/* Setup replenish threshold. */
++		tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8);
++
++		if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) {
++			tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH,
++			     ((u64) tp->rx_jumbo_mapping >> 32));
++			tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
++			     ((u64) tp->rx_jumbo_mapping & 0xffffffff));
++			tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS,
++			     RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT);
++			tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR,
++			     NIC_SRAM_RX_JUMBO_BUFFER_DESC);
++		} else {
++			tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS,
++			     BDINFO_FLAGS_DISABLED);
++		}
++
++	}
++
++	/* There is only one send ring on 5705/5750, no need to explicitly
++	 * disable the others.
++	 */
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++		/* Clear out send RCB ring in SRAM. */
++		for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
++			tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
++				      BDINFO_FLAGS_DISABLED);
++	}
++
++	tp->tx_prod = 0;
++	tp->tx_cons = 0;
++	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
++	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
++
++	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
++		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
++			       tp->tx_desc_mapping,
++			       (TG3_TX_RING_SIZE <<
++				BDINFO_FLAGS_MAXLEN_SHIFT),
++			       NIC_SRAM_TX_BUFFER_DESC);
++	} else {
++		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
++			       0,
++			       BDINFO_FLAGS_DISABLED,
++			       NIC_SRAM_TX_BUFFER_DESC);
++	}
++
++	/* There is only one receive return ring on 5705/5750, no need
++	 * to explicitly disable the others.
++	 */
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++		for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK;
++		     i += TG3_BDINFO_SIZE) {
++			tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
++				      BDINFO_FLAGS_DISABLED);
++		}
++	}
++
++	tp->rx_rcb_ptr = 0;
++	tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
++
++	tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB,
++		       tp->rx_rcb_mapping,
++		       (TG3_RX_RCB_RING_SIZE(tp) <<
++			BDINFO_FLAGS_MAXLEN_SHIFT),
++		       0);
++
++	tp->rx_std_ptr = tp->rx_pending;
++	tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
++		     tp->rx_std_ptr);
++
++	tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) ?
++						tp->rx_jumbo_pending : 0;
++	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
++		     tp->rx_jumbo_ptr);
++
++	/* Initialize MAC address and backoff seed. */
++	__tg3_set_mac_addr(tp);
++
++	/* MTU + ethernet header + FCS + optional VLAN tag */
++	tw32(MAC_RX_MTU_SIZE, tp->dev->mtu + ETH_HLEN + 8);
++
++	/* The slot time is changed by tg3_setup_phy if we
++	 * run at gigabit with half duplex.
++	 */
++	tw32(MAC_TX_LENGTHS,
++	     (2 << TX_LENGTHS_IPG_CRS_SHIFT) |
++	     (6 << TX_LENGTHS_IPG_SHIFT) |
++	     (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
++
++	/* Receive rules. */
++	tw32(MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS);
++	tw32(RCVLPC_CONFIG, 0x0181);
++
++	/* Calculate RDMAC_MODE setting early, we need it to determine
++	 * the RCVLPC_STATE_ENABLE mask.
++	 */
++	rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
++		      RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
++		      RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
++		      RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
++		      RDMAC_MODE_LNGREAD_ENAB);
++	if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
++		rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
++	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
++	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
++	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
++		if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
++		    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
++		     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
++			rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
++		} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
++			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
++			rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
++		}
++	}
++
++#if TG3_TSO_SUPPORT != 0
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		rdmac_mode |= (1 << 27);
++#endif
++
++	/* Receive/send statistics. */
++	if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
++	    (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
++		val = tr32(RCVLPC_STATS_ENABLE);
++		val &= ~RCVLPC_STATSENAB_LNGBRST_RFIX;
++		tw32(RCVLPC_STATS_ENABLE, val);
++	} else {
++		tw32(RCVLPC_STATS_ENABLE, 0xffffff);
++	}
++	tw32(RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE);
++	tw32(SNDDATAI_STATSENAB, 0xffffff);
++	tw32(SNDDATAI_STATSCTRL,
++	     (SNDDATAI_SCTRL_ENABLE |
++	      SNDDATAI_SCTRL_FASTUPD));
++
++	/* Setup host coalescing engine. */
++	tw32(HOSTCC_MODE, 0);
++	for (i = 0; i < 2000; i++) {
++		if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE))
++			break;
++		udelay(10);
++	}
++
++	tw32(HOSTCC_RXCOL_TICKS, 0);
++	tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
++	tw32(HOSTCC_RXMAX_FRAMES, 1);
++	tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++		tw32(HOSTCC_RXCOAL_TICK_INT, 0);
++		tw32(HOSTCC_TXCOAL_TICK_INT, 0);
++	}
++	tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
++	tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
++
++	/* set status block DMA address */
++	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
++	     ((u64) tp->status_mapping >> 32));
++	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
++	     ((u64) tp->status_mapping & 0xffffffff));
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++		/* Status/statistics block address.  See tg3_timer,
++		 * the tg3_periodic_fetch_stats call there, and
++		 * tg3_get_stats to see how this works for 5705/5750 chips.
++		 */
++		tw32(HOSTCC_STAT_COAL_TICKS,
++		     DEFAULT_STAT_COAL_TICKS);
++		tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
++		     ((u64) tp->stats_mapping >> 32));
++		tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
++		     ((u64) tp->stats_mapping & 0xffffffff));
++		tw32(HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK);
++		tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK);
++	}
++
++	tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode);
++
++	tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE);
++	tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE);
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
++		tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
++
++	/* Clear statistics/status block in chip, and status block in ram. */
++	for (i = NIC_SRAM_STATS_BLK;
++	     i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
++	     i += sizeof(u32)) {
++		tg3_write_mem(tp, i, 0);
++		udelay(40);
++	}
++	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
++
++	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
++		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
++	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
++	udelay(40);
++
++	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
++		tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
++				       GRC_LCLCTRL_GPIO_OUTPUT1);
++	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
++	udelay(100);
++
++	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
++	tr32(MAILBOX_INTERRUPT_0);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
++		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
++		udelay(40);
++	}
++
++	val = (WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
++	       WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
++	       WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
++	       WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
++	       WDMAC_MODE_LNGREAD_ENAB);
++
++	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
++	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		if ((tp->tg3_flags & TG3_FLG2_TSO_CAPABLE) &&
++		    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
++		     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
++			/* nothing */
++		} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
++			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
++			   !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
++			val |= WDMAC_MODE_RX_ACCEL;
++		}
++	}
++
++	tw32_f(WDMAC_MODE, val);
++	udelay(40);
++
++	if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
++		val = tr32(TG3PCI_X_CAPS);
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
++			val &= ~PCIX_CAPS_BURST_MASK;
++			val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
++		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
++			val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
++			val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
++			if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
++				val |= (tp->split_mode_max_reqs <<
++					PCIX_CAPS_SPLIT_SHIFT);
++		}
++		tw32(TG3PCI_X_CAPS, val);
++	}
++
++	tw32_f(RDMAC_MODE, rdmac_mode);
++	udelay(40);
++
++	tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
++		tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
++	tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
++	tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
++	tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
++	tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
++	tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
++#if TG3_TSO_SUPPORT != 0
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
++#endif
++	tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE);
++	tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
++
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
++		err = tg3_load_5701_a0_firmware_fix(tp);
++		if (err)
++			return err;
++	}
++
++#if TG3_TSO_SUPPORT != 0
++	if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
++		err = tg3_load_tso_firmware(tp);
++		if (err)
++			return err;
++	}
++#endif
++
++	tp->tx_mode = TX_MODE_ENABLE;
++	tw32_f(MAC_TX_MODE, tp->tx_mode);
++	udelay(100);
++
++	tp->rx_mode = RX_MODE_ENABLE;
++	tw32_f(MAC_RX_MODE, tp->rx_mode);
++	udelay(10);
++
++	if (tp->link_config.phy_is_low_power) {
++		tp->link_config.phy_is_low_power = 0;
++		tp->link_config.speed = tp->link_config.orig_speed;
++		tp->link_config.duplex = tp->link_config.orig_duplex;
++		tp->link_config.autoneg = tp->link_config.orig_autoneg;
++	}
++
++	tp->mi_mode = MAC_MI_MODE_BASE;
++	tw32_f(MAC_MI_MODE, tp->mi_mode);
++	udelay(80);
++
++	tw32(MAC_LED_CTRL, tp->led_ctrl);
++
++	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
++	if (tp->phy_id == PHY_ID_SERDES) {
++		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
++		udelay(10);
++	}
++	tw32_f(MAC_RX_MODE, tp->rx_mode);
++	udelay(10);
++
++	if (tp->phy_id == PHY_ID_SERDES) {
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
++			/* Set drive transmission level to 1.2V  */
++			val = tr32(MAC_SERDES_CFG);
++			val &= 0xfffff000;
++			val |= 0x880;
++			tw32(MAC_SERDES_CFG, val);
++		}
++		if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
++			tw32(MAC_SERDES_CFG, 0x616000);
++	}
++
++	/* Prevent chip from dropping frames when flow control
++	 * is enabled.
++	 */
++	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
++	    tp->phy_id == PHY_ID_SERDES) {
++		/* Enable hardware link auto-negotiation */
++		u32 digctrl, txctrl;
++
++		digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
++		    SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
++		    (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
++		    SG_DIG_GBIC_ENABLE;
++
++		txctrl = tr32(MAC_SERDES_CFG);
++		tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
++		tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
++		tr32(SG_DIG_CTRL);
++		udelay(5);
++		tw32_f(SG_DIG_CTRL, digctrl);
++
++		tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
++	}
++
++	err = tg3_setup_phy(tp, 1);
++	if (err)
++		return err;
++
++	if (tp->phy_id != PHY_ID_SERDES) {
++		u32 tmp;
++
++		/* Clear CRC stats. */
++		tg3_readphy(tp, 0x1e, &tmp);
++		tg3_writephy(tp, 0x1e, tmp | 0x8000);
++		tg3_readphy(tp, 0x14, &tmp);
++	}
++
++	__tg3_set_rx_mode(tp->dev);
++
++	/* Initialize receive rules. */
++	tw32(MAC_RCV_RULE_0,  0xc2000000 & RCV_RULE_DISABLE_MASK);
++	tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK);
++	tw32(MAC_RCV_RULE_1,  0x86000004 & RCV_RULE_DISABLE_MASK);
++	tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		limit = 8;
++	else
++		limit = 16;
++	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF)
++		limit -= 4;
++	switch (limit) {
++	case 16:
++		tw32(MAC_RCV_RULE_15,  0); tw32(MAC_RCV_VALUE_15,  0);
++	case 15:
++		tw32(MAC_RCV_RULE_14,  0); tw32(MAC_RCV_VALUE_14,  0);
++	case 14:
++		tw32(MAC_RCV_RULE_13,  0); tw32(MAC_RCV_VALUE_13,  0);
++	case 13:
++		tw32(MAC_RCV_RULE_12,  0); tw32(MAC_RCV_VALUE_12,  0);
++	case 12:
++		tw32(MAC_RCV_RULE_11,  0); tw32(MAC_RCV_VALUE_11,  0);
++	case 11:
++		tw32(MAC_RCV_RULE_10,  0); tw32(MAC_RCV_VALUE_10,  0);
++	case 10:
++		tw32(MAC_RCV_RULE_9,  0); tw32(MAC_RCV_VALUE_9,  0);
++	case 9:
++		tw32(MAC_RCV_RULE_8,  0); tw32(MAC_RCV_VALUE_8,  0);
++	case 8:
++		tw32(MAC_RCV_RULE_7,  0); tw32(MAC_RCV_VALUE_7,  0);
++	case 7:
++		tw32(MAC_RCV_RULE_6,  0); tw32(MAC_RCV_VALUE_6,  0);
++	case 6:
++		tw32(MAC_RCV_RULE_5,  0); tw32(MAC_RCV_VALUE_5,  0);
++	case 5:
++		tw32(MAC_RCV_RULE_4,  0); tw32(MAC_RCV_VALUE_4,  0);
++	case 4:
++		/* tw32(MAC_RCV_RULE_3,  0); tw32(MAC_RCV_VALUE_3,  0); */
++	case 3:
++		/* tw32(MAC_RCV_RULE_2,  0); tw32(MAC_RCV_VALUE_2,  0); */
++	case 2:
++	case 1:
++
++	default:
++		break;
++	};
++
++	tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
++
++	if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)
++		tg3_enable_ints(tp);
++
++	return 0;
++}
++
++/* Called at device open time to get the chip ready for
++ * packet processing.  Invoked with tp->lock held.
++ */
++static int tg3_init_hw(struct tg3 *tp)
++{
++	int err;
++
++	/* Force the chip into D0. */
++	err = tg3_set_power_state(tp, 0);
++	if (err)
++		goto out;
++
++	tg3_switch_clocks(tp);
++
++	tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
++
++	err = tg3_reset_hw(tp);
++
++out:
++	return err;
++}
++
++#define TG3_STAT_ADD32(PSTAT, REG) \
++do {	u32 __val = tr32(REG); \
++	(PSTAT)->low += __val; \
++	if ((PSTAT)->low < __val) \
++		(PSTAT)->high += 1; \
++} while (0)
++
++static void tg3_periodic_fetch_stats(struct tg3 *tp)
++{
++	struct tg3_hw_stats *sp = tp->hw_stats;
++
++	if (!netif_carrier_ok(tp->dev))
++		return;
++
++	TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS);
++	TG3_STAT_ADD32(&sp->tx_collisions, MAC_TX_STATS_COLLISIONS);
++	TG3_STAT_ADD32(&sp->tx_xon_sent, MAC_TX_STATS_XON_SENT);
++	TG3_STAT_ADD32(&sp->tx_xoff_sent, MAC_TX_STATS_XOFF_SENT);
++	TG3_STAT_ADD32(&sp->tx_mac_errors, MAC_TX_STATS_MAC_ERRORS);
++	TG3_STAT_ADD32(&sp->tx_single_collisions, MAC_TX_STATS_SINGLE_COLLISIONS);
++	TG3_STAT_ADD32(&sp->tx_mult_collisions, MAC_TX_STATS_MULT_COLLISIONS);
++	TG3_STAT_ADD32(&sp->tx_deferred, MAC_TX_STATS_DEFERRED);
++	TG3_STAT_ADD32(&sp->tx_excessive_collisions, MAC_TX_STATS_EXCESSIVE_COL);
++	TG3_STAT_ADD32(&sp->tx_late_collisions, MAC_TX_STATS_LATE_COL);
++	TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST);
++	TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST);
++	TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST);
++
++	TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS);
++	TG3_STAT_ADD32(&sp->rx_fragments, MAC_RX_STATS_FRAGMENTS);
++	TG3_STAT_ADD32(&sp->rx_ucast_packets, MAC_RX_STATS_UCAST);
++	TG3_STAT_ADD32(&sp->rx_mcast_packets, MAC_RX_STATS_MCAST);
++	TG3_STAT_ADD32(&sp->rx_bcast_packets, MAC_RX_STATS_BCAST);
++	TG3_STAT_ADD32(&sp->rx_fcs_errors, MAC_RX_STATS_FCS_ERRORS);
++	TG3_STAT_ADD32(&sp->rx_align_errors, MAC_RX_STATS_ALIGN_ERRORS);
++	TG3_STAT_ADD32(&sp->rx_xon_pause_rcvd, MAC_RX_STATS_XON_PAUSE_RECVD);
++	TG3_STAT_ADD32(&sp->rx_xoff_pause_rcvd, MAC_RX_STATS_XOFF_PAUSE_RECVD);
++	TG3_STAT_ADD32(&sp->rx_mac_ctrl_rcvd, MAC_RX_STATS_MAC_CTRL_RECVD);
++	TG3_STAT_ADD32(&sp->rx_xoff_entered, MAC_RX_STATS_XOFF_ENTERED);
++	TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG);
++	TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS);
++	TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE);
++}
++
++static void tg3_timer(unsigned long __opaque)
++{
++	struct tg3 *tp = (struct tg3 *) __opaque;
++	unsigned long flags;
++
++	spin_lock_irqsave(&tp->lock, flags);
++	spin_lock(&tp->tx_lock);
++
++	/* All of this garbage is because when using non-tagged
++	 * IRQ status the mailbox/status_block protocol the chip
++	 * uses with the cpu is race prone.
++	 */
++	if (tp->hw_status->status & SD_STATUS_UPDATED) {
++		tw32(GRC_LOCAL_CTRL,
++		     tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
++	} else {
++		tw32(HOSTCC_MODE, tp->coalesce_mode |
++		     (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
++	}
++
++	if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
++		tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
++		spin_unlock(&tp->tx_lock);
++		spin_unlock_irqrestore(&tp->lock, flags);
++		schedule_work(&tp->reset_task);
++		return;
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		tg3_periodic_fetch_stats(tp);
++
++	/* This part only runs once per second. */
++	if (!--tp->timer_counter) {
++		if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
++			u32 mac_stat;
++			int phy_event;
++
++			mac_stat = tr32(MAC_STATUS);
++
++			phy_event = 0;
++			if (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) {
++				if (mac_stat & MAC_STATUS_MI_INTERRUPT)
++					phy_event = 1;
++			} else if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)
++				phy_event = 1;
++
++			if (phy_event)
++				tg3_setup_phy(tp, 0);
++		} else if (tp->tg3_flags & TG3_FLAG_POLL_SERDES) {
++			u32 mac_stat = tr32(MAC_STATUS);
++			int need_setup = 0;
++
++			if (netif_carrier_ok(tp->dev) &&
++			    (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) {
++				need_setup = 1;
++			}
++			if (! netif_carrier_ok(tp->dev) &&
++			    (mac_stat & MAC_STATUS_PCS_SYNCED)) {
++				need_setup = 1;
++			}
++			if (need_setup) {
++				tw32_f(MAC_MODE,
++				     (tp->mac_mode &
++				      ~MAC_MODE_PORT_MODE_MASK));
++				udelay(40);
++				tw32_f(MAC_MODE, tp->mac_mode);
++				udelay(40);
++				tg3_setup_phy(tp, 0);
++			}
++		}
++
++		tp->timer_counter = tp->timer_multiplier;
++	}
++
++	/* Heartbeat is only sent once every 120 seconds.  */
++	if (!--tp->asf_counter) {
++		if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
++			u32 val;
++
++			tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_ALIVE);
++			tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4);
++			tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 3);
++			val = tr32(GRC_RX_CPU_EVENT);
++			val |= (1 << 14);
++			tw32(GRC_RX_CPU_EVENT, val);
++		}
++		tp->asf_counter = tp->asf_multiplier;
++	}
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irqrestore(&tp->lock, flags);
++
++	tp->timer.expires = jiffies + tp->timer_offset;
++	add_timer(&tp->timer);
++}
++
++static int tg3_open(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	int err;
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	tg3_disable_ints(tp);
++	tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	/* If you move this call, make sure TG3_FLAG_HOST_TXDS in
++	 * tp->tg3_flags is accurate at that new place.
++	 */
++	err = tg3_alloc_consistent(tp);
++	if (err)
++		return err;
++
++	err = request_irq(dev->irq, tg3_interrupt,
++			  SA_SHIRQ, dev->name, dev);
++
++	if (err) {
++		tg3_free_consistent(tp);
++		return err;
++	}
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	err = tg3_init_hw(tp);
++	if (err) {
++		tg3_halt(tp);
++		tg3_free_rings(tp);
++	} else {
++		tp->timer_offset = HZ / 10;
++		tp->timer_counter = tp->timer_multiplier = 10;
++		tp->asf_counter = tp->asf_multiplier = (10 * 120);
++
++		init_timer(&tp->timer);
++		tp->timer.expires = jiffies + tp->timer_offset;
++		tp->timer.data = (unsigned long) tp;
++		tp->timer.function = tg3_timer;
++		add_timer(&tp->timer);
++
++		tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
++	}
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	if (err) {
++		free_irq(dev->irq, dev);
++		tg3_free_consistent(tp);
++		return err;
++	}
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	tg3_enable_ints(tp);
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	netif_start_queue(dev);
++
++	return 0;
++}
++
++#if 0
++/*static*/ void tg3_dump_state(struct tg3 *tp)
++{
++	u32 val32, val32_2, val32_3, val32_4, val32_5;
++	u16 val16;
++	int i;
++
++	pci_read_config_word(tp->pdev, PCI_STATUS, &val16);
++	pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &val32);
++	printk("DEBUG: PCI status [%04x] TG3PCI state[%08x]\n",
++	       val16, val32);
++
++	/* MAC block */
++	printk("DEBUG: MAC_MODE[%08x] MAC_STATUS[%08x]\n",
++	       tr32(MAC_MODE), tr32(MAC_STATUS));
++	printk("       MAC_EVENT[%08x] MAC_LED_CTRL[%08x]\n",
++	       tr32(MAC_EVENT), tr32(MAC_LED_CTRL));
++	printk("DEBUG: MAC_TX_MODE[%08x] MAC_TX_STATUS[%08x]\n",
++	       tr32(MAC_TX_MODE), tr32(MAC_TX_STATUS));
++	printk("       MAC_RX_MODE[%08x] MAC_RX_STATUS[%08x]\n",
++	       tr32(MAC_RX_MODE), tr32(MAC_RX_STATUS));
++
++	/* Send data initiator control block */
++	printk("DEBUG: SNDDATAI_MODE[%08x] SNDDATAI_STATUS[%08x]\n",
++	       tr32(SNDDATAI_MODE), tr32(SNDDATAI_STATUS));
++	printk("       SNDDATAI_STATSCTRL[%08x]\n",
++	       tr32(SNDDATAI_STATSCTRL));
++
++	/* Send data completion control block */
++	printk("DEBUG: SNDDATAC_MODE[%08x]\n", tr32(SNDDATAC_MODE));
++
++	/* Send BD ring selector block */
++	printk("DEBUG: SNDBDS_MODE[%08x] SNDBDS_STATUS[%08x]\n",
++	       tr32(SNDBDS_MODE), tr32(SNDBDS_STATUS));
++
++	/* Send BD initiator control block */
++	printk("DEBUG: SNDBDI_MODE[%08x] SNDBDI_STATUS[%08x]\n",
++	       tr32(SNDBDI_MODE), tr32(SNDBDI_STATUS));
++
++	/* Send BD completion control block */
++	printk("DEBUG: SNDBDC_MODE[%08x]\n", tr32(SNDBDC_MODE));
++
++	/* Receive list placement control block */
++	printk("DEBUG: RCVLPC_MODE[%08x] RCVLPC_STATUS[%08x]\n",
++	       tr32(RCVLPC_MODE), tr32(RCVLPC_STATUS));
++	printk("       RCVLPC_STATSCTRL[%08x]\n",
++	       tr32(RCVLPC_STATSCTRL));
++
++	/* Receive data and receive BD initiator control block */
++	printk("DEBUG: RCVDBDI_MODE[%08x] RCVDBDI_STATUS[%08x]\n",
++	       tr32(RCVDBDI_MODE), tr32(RCVDBDI_STATUS));
++
++	/* Receive data completion control block */
++	printk("DEBUG: RCVDCC_MODE[%08x]\n",
++	       tr32(RCVDCC_MODE));
++
++	/* Receive BD initiator control block */
++	printk("DEBUG: RCVBDI_MODE[%08x] RCVBDI_STATUS[%08x]\n",
++	       tr32(RCVBDI_MODE), tr32(RCVBDI_STATUS));
++
++	/* Receive BD completion control block */
++	printk("DEBUG: RCVCC_MODE[%08x] RCVCC_STATUS[%08x]\n",
++	       tr32(RCVCC_MODE), tr32(RCVCC_STATUS));
++
++	/* Receive list selector control block */
++	printk("DEBUG: RCVLSC_MODE[%08x] RCVLSC_STATUS[%08x]\n",
++	       tr32(RCVLSC_MODE), tr32(RCVLSC_STATUS));
++
++	/* Mbuf cluster free block */
++	printk("DEBUG: MBFREE_MODE[%08x] MBFREE_STATUS[%08x]\n",
++	       tr32(MBFREE_MODE), tr32(MBFREE_STATUS));
++
++	/* Host coalescing control block */
++	printk("DEBUG: HOSTCC_MODE[%08x] HOSTCC_STATUS[%08x]\n",
++	       tr32(HOSTCC_MODE), tr32(HOSTCC_STATUS));
++	printk("DEBUG: HOSTCC_STATS_BLK_HOST_ADDR[%08x%08x]\n",
++	       tr32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH),
++	       tr32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW));
++	printk("DEBUG: HOSTCC_STATUS_BLK_HOST_ADDR[%08x%08x]\n",
++	       tr32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH),
++	       tr32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW));
++	printk("DEBUG: HOSTCC_STATS_BLK_NIC_ADDR[%08x]\n",
++	       tr32(HOSTCC_STATS_BLK_NIC_ADDR));
++	printk("DEBUG: HOSTCC_STATUS_BLK_NIC_ADDR[%08x]\n",
++	       tr32(HOSTCC_STATUS_BLK_NIC_ADDR));
++
++	/* Memory arbiter control block */
++	printk("DEBUG: MEMARB_MODE[%08x] MEMARB_STATUS[%08x]\n",
++	       tr32(MEMARB_MODE), tr32(MEMARB_STATUS));
++
++	/* Buffer manager control block */
++	printk("DEBUG: BUFMGR_MODE[%08x] BUFMGR_STATUS[%08x]\n",
++	       tr32(BUFMGR_MODE), tr32(BUFMGR_STATUS));
++	printk("DEBUG: BUFMGR_MB_POOL_ADDR[%08x] BUFMGR_MB_POOL_SIZE[%08x]\n",
++	       tr32(BUFMGR_MB_POOL_ADDR), tr32(BUFMGR_MB_POOL_SIZE));
++	printk("DEBUG: BUFMGR_DMA_DESC_POOL_ADDR[%08x] "
++	       "BUFMGR_DMA_DESC_POOL_SIZE[%08x]\n",
++	       tr32(BUFMGR_DMA_DESC_POOL_ADDR),
++	       tr32(BUFMGR_DMA_DESC_POOL_SIZE));
++
++	/* Read DMA control block */
++	printk("DEBUG: RDMAC_MODE[%08x] RDMAC_STATUS[%08x]\n",
++	       tr32(RDMAC_MODE), tr32(RDMAC_STATUS));
++
++	/* Write DMA control block */
++	printk("DEBUG: WDMAC_MODE[%08x] WDMAC_STATUS[%08x]\n",
++	       tr32(WDMAC_MODE), tr32(WDMAC_STATUS));
++
++	/* DMA completion block */
++	printk("DEBUG: DMAC_MODE[%08x]\n",
++	       tr32(DMAC_MODE));
++
++	/* GRC block */
++	printk("DEBUG: GRC_MODE[%08x] GRC_MISC_CFG[%08x]\n",
++	       tr32(GRC_MODE), tr32(GRC_MISC_CFG));
++	printk("DEBUG: GRC_LOCAL_CTRL[%08x]\n",
++	       tr32(GRC_LOCAL_CTRL));
++
++	/* TG3_BDINFOs */
++	printk("DEBUG: RCVDBDI_JUMBO_BD[%08x%08x:%08x:%08x]\n",
++	       tr32(RCVDBDI_JUMBO_BD + 0x0),
++	       tr32(RCVDBDI_JUMBO_BD + 0x4),
++	       tr32(RCVDBDI_JUMBO_BD + 0x8),
++	       tr32(RCVDBDI_JUMBO_BD + 0xc));
++	printk("DEBUG: RCVDBDI_STD_BD[%08x%08x:%08x:%08x]\n",
++	       tr32(RCVDBDI_STD_BD + 0x0),
++	       tr32(RCVDBDI_STD_BD + 0x4),
++	       tr32(RCVDBDI_STD_BD + 0x8),
++	       tr32(RCVDBDI_STD_BD + 0xc));
++	printk("DEBUG: RCVDBDI_MINI_BD[%08x%08x:%08x:%08x]\n",
++	       tr32(RCVDBDI_MINI_BD + 0x0),
++	       tr32(RCVDBDI_MINI_BD + 0x4),
++	       tr32(RCVDBDI_MINI_BD + 0x8),
++	       tr32(RCVDBDI_MINI_BD + 0xc));
++
++	tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0x0, &val32);
++	tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0x4, &val32_2);
++	tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0x8, &val32_3);
++	tg3_read_mem(tp, NIC_SRAM_SEND_RCB + 0xc, &val32_4);
++	printk("DEBUG: SRAM_SEND_RCB_0[%08x%08x:%08x:%08x]\n",
++	       val32, val32_2, val32_3, val32_4);
++
++	tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0x0, &val32);
++	tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0x4, &val32_2);
++	tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0x8, &val32_3);
++	tg3_read_mem(tp, NIC_SRAM_RCV_RET_RCB + 0xc, &val32_4);
++	printk("DEBUG: SRAM_RCV_RET_RCB_0[%08x%08x:%08x:%08x]\n",
++	       val32, val32_2, val32_3, val32_4);
++
++	tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x0, &val32);
++	tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x4, &val32_2);
++	tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x8, &val32_3);
++	tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0xc, &val32_4);
++	tg3_read_mem(tp, NIC_SRAM_STATUS_BLK + 0x10, &val32_5);
++	printk("DEBUG: SRAM_STATUS_BLK[%08x:%08x:%08x:%08x:%08x]\n",
++	       val32, val32_2, val32_3, val32_4, val32_5);
++
++	/* SW status block */
++	printk("DEBUG: Host status block [%08x:%08x:(%04x:%04x:%04x):(%04x:%04x)]\n",
++	       tp->hw_status->status,
++	       tp->hw_status->status_tag,
++	       tp->hw_status->rx_jumbo_consumer,
++	       tp->hw_status->rx_consumer,
++	       tp->hw_status->rx_mini_consumer,
++	       tp->hw_status->idx[0].rx_producer,
++	       tp->hw_status->idx[0].tx_consumer);
++
++	/* SW statistics block */
++	printk("DEBUG: Host statistics block [%08x:%08x:%08x:%08x]\n",
++	       ((u32 *)tp->hw_stats)[0],
++	       ((u32 *)tp->hw_stats)[1],
++	       ((u32 *)tp->hw_stats)[2],
++	       ((u32 *)tp->hw_stats)[3]);
++
++	/* Mailboxes */
++	printk("DEBUG: SNDHOST_PROD[%08x%08x] SNDNIC_PROD[%08x%08x]\n",
++	       tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x0),
++	       tr32(MAILBOX_SNDHOST_PROD_IDX_0 + 0x4),
++	       tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x0),
++	       tr32(MAILBOX_SNDNIC_PROD_IDX_0 + 0x4));
++
++	/* NIC side send descriptors. */
++	for (i = 0; i < 6; i++) {
++		unsigned long txd;
++
++		txd = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_TX_BUFFER_DESC
++			+ (i * sizeof(struct tg3_tx_buffer_desc));
++		printk("DEBUG: NIC TXD(%d)[%08x:%08x:%08x:%08x]\n",
++		       i,
++		       readl(txd + 0x0), readl(txd + 0x4),
++		       readl(txd + 0x8), readl(txd + 0xc));
++	}
++
++	/* NIC side RX descriptors. */
++	for (i = 0; i < 6; i++) {
++		unsigned long rxd;
++
++		rxd = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_RX_BUFFER_DESC
++			+ (i * sizeof(struct tg3_rx_buffer_desc));
++		printk("DEBUG: NIC RXD_STD(%d)[0][%08x:%08x:%08x:%08x]\n",
++		       i,
++		       readl(rxd + 0x0), readl(rxd + 0x4),
++		       readl(rxd + 0x8), readl(rxd + 0xc));
++		rxd += (4 * sizeof(u32));
++		printk("DEBUG: NIC RXD_STD(%d)[1][%08x:%08x:%08x:%08x]\n",
++		       i,
++		       readl(rxd + 0x0), readl(rxd + 0x4),
++		       readl(rxd + 0x8), readl(rxd + 0xc));
++	}
++
++	for (i = 0; i < 6; i++) {
++		unsigned long rxd;
++
++		rxd = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_RX_JUMBO_BUFFER_DESC
++			+ (i * sizeof(struct tg3_rx_buffer_desc));
++		printk("DEBUG: NIC RXD_JUMBO(%d)[0][%08x:%08x:%08x:%08x]\n",
++		       i,
++		       readl(rxd + 0x0), readl(rxd + 0x4),
++		       readl(rxd + 0x8), readl(rxd + 0xc));
++		rxd += (4 * sizeof(u32));
++		printk("DEBUG: NIC RXD_JUMBO(%d)[1][%08x:%08x:%08x:%08x]\n",
++		       i,
++		       readl(rxd + 0x0), readl(rxd + 0x4),
++		       readl(rxd + 0x8), readl(rxd + 0xc));
++	}
++}
++#endif
++
++static struct net_device_stats *tg3_get_stats(struct net_device *);
++static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);
++
++static int tg3_close(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++
++	netif_stop_queue(dev);
++
++	del_timer_sync(&tp->timer);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++#if 0
++	tg3_dump_state(tp);
++#endif
++
++	tg3_disable_ints(tp);
++
++	tg3_halt(tp);
++	tg3_free_rings(tp);
++	tp->tg3_flags &=
++		~(TG3_FLAG_INIT_COMPLETE |
++		  TG3_FLAG_GOT_SERDES_FLOWCTL);
++	netif_carrier_off(tp->dev);
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	free_irq(dev->irq, dev);
++
++	memcpy(&tp->net_stats_prev, tg3_get_stats(tp->dev),
++	       sizeof(tp->net_stats_prev));
++	memcpy(&tp->estats_prev, tg3_get_estats(tp),
++	       sizeof(tp->estats_prev));
++
++	tg3_free_consistent(tp);
++
++	return 0;
++}
++
++static inline unsigned long get_stat64(tg3_stat64_t *val)
++{
++	unsigned long ret;
++
++#if (BITS_PER_LONG == 32)
++	ret = val->low;
++#else
++	ret = ((u64)val->high << 32) | ((u64)val->low);
++#endif
++	return ret;
++}
++
++static unsigned long calc_crc_errors(struct tg3 *tp)
++{
++	struct tg3_hw_stats *hw_stats = tp->hw_stats;
++
++	if (tp->phy_id != PHY_ID_SERDES &&
++	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
++		unsigned long flags;
++		u32 val;
++
++		spin_lock_irqsave(&tp->lock, flags);
++		tg3_readphy(tp, 0x1e, &val);
++		tg3_writephy(tp, 0x1e, val | 0x8000);
++		tg3_readphy(tp, 0x14, &val);
++		spin_unlock_irqrestore(&tp->lock, flags);
++
++		tp->phy_crc_errors += val;
++
++		return tp->phy_crc_errors;
++	}
++
++	return get_stat64(&hw_stats->rx_fcs_errors);
++}
++
++#define ESTAT_ADD(member) \
++	estats->member =	old_estats->member + \
++				get_stat64(&hw_stats->member)
++
++static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
++{
++	struct tg3_ethtool_stats *estats = &tp->estats;
++	struct tg3_ethtool_stats *old_estats = &tp->estats_prev;
++	struct tg3_hw_stats *hw_stats = tp->hw_stats;
++
++	if (!hw_stats)
++		return old_estats;
++
++	ESTAT_ADD(rx_octets);
++	ESTAT_ADD(rx_fragments);
++	ESTAT_ADD(rx_ucast_packets);
++	ESTAT_ADD(rx_mcast_packets);
++	ESTAT_ADD(rx_bcast_packets);
++	ESTAT_ADD(rx_fcs_errors);
++	ESTAT_ADD(rx_align_errors);
++	ESTAT_ADD(rx_xon_pause_rcvd);
++	ESTAT_ADD(rx_xoff_pause_rcvd);
++	ESTAT_ADD(rx_mac_ctrl_rcvd);
++	ESTAT_ADD(rx_xoff_entered);
++	ESTAT_ADD(rx_frame_too_long_errors);
++	ESTAT_ADD(rx_jabbers);
++	ESTAT_ADD(rx_undersize_packets);
++	ESTAT_ADD(rx_in_length_errors);
++	ESTAT_ADD(rx_out_length_errors);
++	ESTAT_ADD(rx_64_or_less_octet_packets);
++	ESTAT_ADD(rx_65_to_127_octet_packets);
++	ESTAT_ADD(rx_128_to_255_octet_packets);
++	ESTAT_ADD(rx_256_to_511_octet_packets);
++	ESTAT_ADD(rx_512_to_1023_octet_packets);
++	ESTAT_ADD(rx_1024_to_1522_octet_packets);
++	ESTAT_ADD(rx_1523_to_2047_octet_packets);
++	ESTAT_ADD(rx_2048_to_4095_octet_packets);
++	ESTAT_ADD(rx_4096_to_8191_octet_packets);
++	ESTAT_ADD(rx_8192_to_9022_octet_packets);
++
++	ESTAT_ADD(tx_octets);
++	ESTAT_ADD(tx_collisions);
++	ESTAT_ADD(tx_xon_sent);
++	ESTAT_ADD(tx_xoff_sent);
++	ESTAT_ADD(tx_flow_control);
++	ESTAT_ADD(tx_mac_errors);
++	ESTAT_ADD(tx_single_collisions);
++	ESTAT_ADD(tx_mult_collisions);
++	ESTAT_ADD(tx_deferred);
++	ESTAT_ADD(tx_excessive_collisions);
++	ESTAT_ADD(tx_late_collisions);
++	ESTAT_ADD(tx_collide_2times);
++	ESTAT_ADD(tx_collide_3times);
++	ESTAT_ADD(tx_collide_4times);
++	ESTAT_ADD(tx_collide_5times);
++	ESTAT_ADD(tx_collide_6times);
++	ESTAT_ADD(tx_collide_7times);
++	ESTAT_ADD(tx_collide_8times);
++	ESTAT_ADD(tx_collide_9times);
++	ESTAT_ADD(tx_collide_10times);
++	ESTAT_ADD(tx_collide_11times);
++	ESTAT_ADD(tx_collide_12times);
++	ESTAT_ADD(tx_collide_13times);
++	ESTAT_ADD(tx_collide_14times);
++	ESTAT_ADD(tx_collide_15times);
++	ESTAT_ADD(tx_ucast_packets);
++	ESTAT_ADD(tx_mcast_packets);
++	ESTAT_ADD(tx_bcast_packets);
++	ESTAT_ADD(tx_carrier_sense_errors);
++	ESTAT_ADD(tx_discards);
++	ESTAT_ADD(tx_errors);
++
++	ESTAT_ADD(dma_writeq_full);
++	ESTAT_ADD(dma_write_prioq_full);
++	ESTAT_ADD(rxbds_empty);
++	ESTAT_ADD(rx_discards);
++	ESTAT_ADD(rx_errors);
++	ESTAT_ADD(rx_threshold_hit);
++
++	ESTAT_ADD(dma_readq_full);
++	ESTAT_ADD(dma_read_prioq_full);
++	ESTAT_ADD(tx_comp_queue_full);
++
++	ESTAT_ADD(ring_set_send_prod_index);
++	ESTAT_ADD(ring_status_update);
++	ESTAT_ADD(nic_irqs);
++	ESTAT_ADD(nic_avoided_irqs);
++	ESTAT_ADD(nic_tx_threshold_hit);
++
++	return estats;
++}
++
++static struct net_device_stats *tg3_get_stats(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	struct net_device_stats *stats = &tp->net_stats;
++	struct net_device_stats *old_stats = &tp->net_stats_prev;
++	struct tg3_hw_stats *hw_stats = tp->hw_stats;
++
++	if (!hw_stats)
++		return old_stats;
++
++	stats->rx_packets = old_stats->rx_packets +
++		get_stat64(&hw_stats->rx_ucast_packets) +
++		get_stat64(&hw_stats->rx_mcast_packets) +
++		get_stat64(&hw_stats->rx_bcast_packets);
++		
++	stats->tx_packets = old_stats->tx_packets +
++		get_stat64(&hw_stats->tx_ucast_packets) +
++		get_stat64(&hw_stats->tx_mcast_packets) +
++		get_stat64(&hw_stats->tx_bcast_packets);
++
++	stats->rx_bytes = old_stats->rx_bytes +
++		get_stat64(&hw_stats->rx_octets);
++	stats->tx_bytes = old_stats->tx_bytes +
++		get_stat64(&hw_stats->tx_octets);
++
++	stats->rx_errors = old_stats->rx_errors +
++		get_stat64(&hw_stats->rx_errors) +
++		get_stat64(&hw_stats->rx_discards);
++	stats->tx_errors = old_stats->tx_errors +
++		get_stat64(&hw_stats->tx_errors) +
++		get_stat64(&hw_stats->tx_mac_errors) +
++		get_stat64(&hw_stats->tx_carrier_sense_errors) +
++		get_stat64(&hw_stats->tx_discards);
++
++	stats->multicast = old_stats->multicast +
++		get_stat64(&hw_stats->rx_mcast_packets);
++	stats->collisions = old_stats->collisions +
++		get_stat64(&hw_stats->tx_collisions);
++
++	stats->rx_length_errors = old_stats->rx_length_errors +
++		get_stat64(&hw_stats->rx_frame_too_long_errors) +
++		get_stat64(&hw_stats->rx_undersize_packets);
++
++	stats->rx_over_errors = old_stats->rx_over_errors +
++		get_stat64(&hw_stats->rxbds_empty);
++	stats->rx_frame_errors = old_stats->rx_frame_errors +
++		get_stat64(&hw_stats->rx_align_errors);
++	stats->tx_aborted_errors = old_stats->tx_aborted_errors +
++		get_stat64(&hw_stats->tx_discards);
++	stats->tx_carrier_errors = old_stats->tx_carrier_errors +
++		get_stat64(&hw_stats->tx_carrier_sense_errors);
++
++	stats->rx_crc_errors = old_stats->rx_crc_errors +
++		calc_crc_errors(tp);
++
++	return stats;
++}
++
++static inline u32 calc_crc(unsigned char *buf, int len)
++{
++	u32 reg;
++	u32 tmp;
++	int j, k;
++
++	reg = 0xffffffff;
++
++	for (j = 0; j < len; j++) {
++		reg ^= buf[j];
++
++		for (k = 0; k < 8; k++) {
++			tmp = reg & 0x01;
++
++			reg >>= 1;
++
++			if (tmp) {
++				reg ^= 0xedb88320;
++			}
++		}
++	}
++
++	return ~reg;
++}
++
++static void tg3_set_multi(struct tg3 *tp, unsigned int accept_all)
++{
++	/* accept or reject all multicast frames */
++	tw32(MAC_HASH_REG_0, accept_all ? 0xffffffff : 0);
++	tw32(MAC_HASH_REG_1, accept_all ? 0xffffffff : 0);
++	tw32(MAC_HASH_REG_2, accept_all ? 0xffffffff : 0);
++	tw32(MAC_HASH_REG_3, accept_all ? 0xffffffff : 0);
++}
++
++static void __tg3_set_rx_mode(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	u32 rx_mode;
++
++	rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
++				  RX_MODE_KEEP_VLAN_TAG);
++
++	/* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG
++	 * flag clear.
++	 */
++#if TG3_VLAN_TAG_USED
++	if (!tp->vlgrp &&
++	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
++		rx_mode |= RX_MODE_KEEP_VLAN_TAG;
++#else
++	/* By definition, VLAN is disabled always in this
++	 * case.
++	 */
++	if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
++		rx_mode |= RX_MODE_KEEP_VLAN_TAG;
++#endif
++
++	if (dev->flags & IFF_PROMISC) {
++		/* Promiscuous mode. */
++		rx_mode |= RX_MODE_PROMISC;
++	} else if (dev->flags & IFF_ALLMULTI) {
++		/* Accept all multicast. */
++		tg3_set_multi (tp, 1);
++	} else if (dev->mc_count < 1) {
++		/* Reject all multicast. */
++		tg3_set_multi (tp, 0);
++	} else {
++		/* Accept one or more multicast(s). */
++		struct dev_mc_list *mclist;
++		unsigned int i;
++		u32 mc_filter[4] = { 0, };
++		u32 regidx;
++		u32 bit;
++		u32 crc;
++
++		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
++		     i++, mclist = mclist->next) {
++
++			crc = calc_crc (mclist->dmi_addr, ETH_ALEN);
++			bit = ~crc & 0x7f;
++			regidx = (bit & 0x60) >> 5;
++			bit &= 0x1f;
++			mc_filter[regidx] |= (1 << bit);
++		}
++
++		tw32(MAC_HASH_REG_0, mc_filter[0]);
++		tw32(MAC_HASH_REG_1, mc_filter[1]);
++		tw32(MAC_HASH_REG_2, mc_filter[2]);
++		tw32(MAC_HASH_REG_3, mc_filter[3]);
++	}
++
++	if (rx_mode != tp->rx_mode) {
++		tp->rx_mode = rx_mode;
++		tw32_f(MAC_RX_MODE, rx_mode);
++		udelay(10);
++	}
++}
++
++static void tg3_set_rx_mode(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++
++	spin_lock_irq(&tp->lock);
++	__tg3_set_rx_mode(dev);
++	spin_unlock_irq(&tp->lock);
++}
++
++#define TG3_REGDUMP_LEN		(32 * 1024)
++
++static int tg3_get_regs_len(struct net_device *dev)
++{
++	return TG3_REGDUMP_LEN;
++}
++
++static void tg3_get_regs(struct net_device *dev,
++		struct ethtool_regs *regs, void *_p)
++{
++	u32 *p = _p;
++	struct tg3 *tp = netdev_priv(dev);
++	u8 *orig_p = _p;
++	int i;
++
++	regs->version = 0;
++
++	memset(p, 0, TG3_REGDUMP_LEN);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++#define __GET_REG32(reg)	(*(p)++ = tr32(reg))
++#define GET_REG32_LOOP(base,len)		\
++do {	p = (u32 *)(orig_p + (base));		\
++	for (i = 0; i < len; i += 4)		\
++		__GET_REG32((base) + i);	\
++} while (0)
++#define GET_REG32_1(reg)			\
++do {	p = (u32 *)(orig_p + (reg));		\
++	__GET_REG32((reg));			\
++} while (0)
++
++	GET_REG32_LOOP(TG3PCI_VENDOR, 0xb0);
++	GET_REG32_LOOP(MAILBOX_INTERRUPT_0, 0x200);
++	GET_REG32_LOOP(MAC_MODE, 0x4f0);
++	GET_REG32_LOOP(SNDDATAI_MODE, 0xe0);
++	GET_REG32_1(SNDDATAC_MODE);
++	GET_REG32_LOOP(SNDBDS_MODE, 0x80);
++	GET_REG32_LOOP(SNDBDI_MODE, 0x48);
++	GET_REG32_1(SNDBDC_MODE);
++	GET_REG32_LOOP(RCVLPC_MODE, 0x20);
++	GET_REG32_LOOP(RCVLPC_SELLST_BASE, 0x15c);
++	GET_REG32_LOOP(RCVDBDI_MODE, 0x0c);
++	GET_REG32_LOOP(RCVDBDI_JUMBO_BD, 0x3c);
++	GET_REG32_LOOP(RCVDBDI_BD_PROD_IDX_0, 0x44);
++	GET_REG32_1(RCVDCC_MODE);
++	GET_REG32_LOOP(RCVBDI_MODE, 0x20);
++	GET_REG32_LOOP(RCVCC_MODE, 0x14);
++	GET_REG32_LOOP(RCVLSC_MODE, 0x08);
++	GET_REG32_1(MBFREE_MODE);
++	GET_REG32_LOOP(HOSTCC_MODE, 0x100);
++	GET_REG32_LOOP(MEMARB_MODE, 0x10);
++	GET_REG32_LOOP(BUFMGR_MODE, 0x58);
++	GET_REG32_LOOP(RDMAC_MODE, 0x08);
++	GET_REG32_LOOP(WDMAC_MODE, 0x08);
++	GET_REG32_LOOP(RX_CPU_BASE, 0x280);
++	GET_REG32_LOOP(TX_CPU_BASE, 0x280);
++	GET_REG32_LOOP(GRCMBOX_INTERRUPT_0, 0x110);
++	GET_REG32_LOOP(FTQ_RESET, 0x120);
++	GET_REG32_LOOP(MSGINT_MODE, 0x0c);
++	GET_REG32_1(DMAC_MODE);
++	GET_REG32_LOOP(GRC_MODE, 0x4c);
++	if (tp->tg3_flags & TG3_FLAG_NVRAM)
++		GET_REG32_LOOP(NVRAM_CMD, 0x24);
++
++#undef __GET_REG32
++#undef GET_REG32_LOOP
++#undef GET_REG32_1
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++}
++
++static int tg3_get_eeprom_len(struct net_device *dev)
++{
++	return EEPROM_CHIP_SIZE;
++}
++
++static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp,
++						 u32 offset, u32 *val);
++static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
++{
++	struct tg3 *tp = dev->priv;
++	int ret;
++	u8  *pd;
++	u32 i, offset, len, val, b_offset, b_count;
++
++	offset = eeprom->offset;
++	len = eeprom->len;
++	eeprom->len = 0;
++
++	ret = tg3_nvram_read_using_eeprom(tp, 0, &eeprom->magic);
++	if (ret)
++		return ret;
++	eeprom->magic = swab32(eeprom->magic);
++
++	if (offset & 3) {
++		/* adjustments to start on required 4 byte boundary */
++		b_offset = offset & 3;
++		b_count = 4 - b_offset;
++		if (b_count > len) {
++			/* i.e. offset=1 len=2 */
++			b_count = len;
++		}
++		ret = tg3_nvram_read_using_eeprom(tp, offset-b_offset, &val);
++		if (ret)
++			return ret;
++		memcpy(data, ((char*)&val) + b_offset, b_count);
++		len -= b_count;
++		offset += b_count;
++	        eeprom->len += b_count;
++	}
++
++	/* read bytes upto the last 4 byte boundary */
++	pd = &data[eeprom->len];
++	for (i = 0; i < (len - (len & 3)); i += 4) {
++		ret = tg3_nvram_read_using_eeprom(tp, offset + i, 
++				(u32*)(pd + i));
++		if (ret) {
++			eeprom->len += i;
++			return ret;
++		}
++	}
++	eeprom->len += i;
++
++	if (len & 3) {
++		/* read last bytes not ending on 4 byte boundary */
++		pd = &data[eeprom->len];
++		b_count = len & 3;
++		b_offset = offset + len - b_count;
++		ret = tg3_nvram_read_using_eeprom(tp, b_offset, &val);
++		if (ret)
++			return ret;
++		memcpy(pd, ((char*)&val), b_count);
++		eeprom->len += b_count;
++	}
++	return 0;
++}
++
++static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++  	struct tg3 *tp = netdev_priv(dev);
++  
++	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
++					tp->link_config.phy_is_low_power)
++		return -EAGAIN;
++
++	cmd->supported = (SUPPORTED_Autoneg);
++
++	if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
++		cmd->supported |= (SUPPORTED_1000baseT_Half |
++				   SUPPORTED_1000baseT_Full);
++
++	if (tp->phy_id != PHY_ID_SERDES)
++		cmd->supported |= (SUPPORTED_100baseT_Half |
++				  SUPPORTED_100baseT_Full |
++				  SUPPORTED_10baseT_Half |
++				  SUPPORTED_10baseT_Full |
++				  SUPPORTED_MII);
++	else
++		cmd->supported |= SUPPORTED_FIBRE;
++  
++	cmd->advertising = tp->link_config.advertising;
++	cmd->speed = tp->link_config.active_speed;
++	cmd->duplex = tp->link_config.active_duplex;
++	cmd->port = 0;
++	cmd->phy_address = PHY_ADDR;
++	cmd->transceiver = 0;
++	cmd->autoneg = tp->link_config.autoneg;
++	cmd->maxtxpkt = 0;
++	cmd->maxrxpkt = 0;
++	return 0;
++}
++  
++static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
++	    tp->link_config.phy_is_low_power)
++		return -EAGAIN;
++
++	if (tp->phy_id == PHY_ID_SERDES) {
++		/* These are the only valid advertisement bits allowed.  */
++		if (cmd->autoneg == AUTONEG_ENABLE &&
++		    (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
++					  ADVERTISED_1000baseT_Full |
++					  ADVERTISED_Autoneg |
++					  ADVERTISED_FIBRE)))
++			return -EINVAL;
++	}
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	tp->link_config.autoneg = cmd->autoneg;
++	if (cmd->autoneg == AUTONEG_ENABLE) {
++		tp->link_config.advertising = cmd->advertising;
++		tp->link_config.speed = SPEED_INVALID;
++		tp->link_config.duplex = DUPLEX_INVALID;
++	} else {
++		tp->link_config.advertising = 0;
++		tp->link_config.speed = cmd->speed;
++		tp->link_config.duplex = cmd->duplex;
++  	}
++  
++	tg3_setup_phy(tp, 1);
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++  
++	return 0;
++}
++  
++static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	strcpy(info->driver, DRV_MODULE_NAME);
++	strcpy(info->version, DRV_MODULE_VERSION);
++	strcpy(info->bus_info, pci_name(tp->pdev));
++}
++  
++static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	wol->supported = WAKE_MAGIC;
++	wol->wolopts = 0;
++	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
++		wol->wolopts = WAKE_MAGIC;
++	memset(&wol->sopass, 0, sizeof(wol->sopass));
++}
++  
++static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	if (wol->wolopts & ~WAKE_MAGIC)
++		return -EINVAL;
++	if ((wol->wolopts & WAKE_MAGIC) &&
++	    tp->phy_id == PHY_ID_SERDES &&
++	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
++		return -EINVAL;
++  
++	spin_lock_irq(&tp->lock);
++	if (wol->wolopts & WAKE_MAGIC)
++		tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
++	spin_unlock_irq(&tp->lock);
++  
++	return 0;
++}
++  
++static u32 tg3_get_msglevel(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	return tp->msg_enable;
++}
++  
++static void tg3_set_msglevel(struct net_device *dev, u32 value)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	tp->msg_enable = value;
++}
++  
++#if TG3_TSO_SUPPORT != 0
++static int tg3_set_tso(struct net_device *dev, u32 value)
++{
++	struct tg3 *tp = netdev_priv(dev);
++
++	if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
++		if (value)
++			return -EINVAL;
++		return 0;
++	}
++	return ethtool_op_set_tso(dev, value);
++}
++#endif
++  
++static int tg3_nway_reset(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	u32 bmcr;
++	int r;
++  
++	spin_lock_irq(&tp->lock);
++	tg3_readphy(tp, MII_BMCR, &bmcr);
++	tg3_readphy(tp, MII_BMCR, &bmcr);
++	r = -EINVAL;
++	if (bmcr & BMCR_ANENABLE) {
++		tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
++		r = 0;
++	}
++	spin_unlock_irq(&tp->lock);
++  
++	return r;
++}
++  
++static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	ering->rx_max_pending = TG3_RX_RING_SIZE - 1;
++	ering->rx_mini_max_pending = 0;
++	ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1;
++
++	ering->rx_pending = tp->rx_pending;
++	ering->rx_mini_pending = 0;
++	ering->rx_jumbo_pending = tp->rx_jumbo_pending;
++	ering->tx_pending = tp->tx_pending;
++}
++  
++static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
++	    (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
++	    (ering->tx_pending > TG3_TX_RING_SIZE - 1))
++		return -EINVAL;
++  
++	tg3_netif_stop(tp);
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++  
++	tp->rx_pending = ering->rx_pending;
++
++	if ((tp->tg3_flags2 & TG3_FLG2_MAX_RXPEND_64) &&
++	    tp->rx_pending > 63)
++		tp->rx_pending = 63;
++	tp->rx_jumbo_pending = ering->rx_jumbo_pending;
++	tp->tx_pending = ering->tx_pending;
++
++	tg3_halt(tp);
++	tg3_init_hw(tp);
++	netif_wake_queue(tp->dev);
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++	tg3_netif_start(tp);
++  
++	return 0;
++}
++  
++static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
++	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0;
++	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0;
++}
++  
++static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	tg3_netif_stop(tp);
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++	if (epause->autoneg)
++		tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
++	if (epause->rx_pause)
++		tp->tg3_flags |= TG3_FLAG_PAUSE_RX;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX;
++	if (epause->tx_pause)
++		tp->tg3_flags |= TG3_FLAG_PAUSE_TX;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
++	tg3_halt(tp);
++	tg3_init_hw(tp);
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++	tg3_netif_start(tp);
++  
++	return 0;
++}
++  
++static u32 tg3_get_rx_csum(struct net_device *dev)
++{
++	struct tg3 *tp = netdev_priv(dev);
++	return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0;
++}
++  
++static int tg3_set_rx_csum(struct net_device *dev, u32 data)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) {
++		if (data != 0)
++			return -EINVAL;
++  		return 0;
++  	}
++  
++	spin_lock_irq(&tp->lock);
++	if (data)
++		tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
++	spin_unlock_irq(&tp->lock);
++  
++	return 0;
++}
++  
++static int tg3_set_tx_csum(struct net_device *dev, u32 data)
++{
++	struct tg3 *tp = netdev_priv(dev);
++  
++	if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) {
++		if (data != 0)
++			return -EINVAL;
++  		return 0;
++  	}
++  
++	if (data)
++		dev->features |= NETIF_F_IP_CSUM;
++	else
++		dev->features &= ~NETIF_F_IP_CSUM;
++
++	return 0;
++}
++
++static int tg3_get_stats_count (struct net_device *dev)
++{
++	return TG3_NUM_STATS;
++}
++
++static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
++{
++	switch (stringset) {
++	case ETH_SS_STATS:
++		memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
++		break;
++	default:
++		WARN_ON(1);	/* we need a WARN() */
++		break;
++	}
++}
++
++static void tg3_get_ethtool_stats (struct net_device *dev,
++				   struct ethtool_stats *estats, u64 *tmp_stats)
++{
++	struct tg3 *tp = dev->priv;
++	memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
++}
++
++static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
++{
++	struct mii_ioctl_data *data = if_mii(ifr);
++	struct tg3 *tp = netdev_priv(dev);
++	int err;
++
++	switch(cmd) {
++	case SIOCGMIIPHY:
++		data->phy_id = PHY_ADDR;
++
++		/* fallthru */
++	case SIOCGMIIREG: {
++		u32 mii_regval;
++
++		if (tp->phy_id == PHY_ID_SERDES)
++			break;			/* We have no PHY */
++
++		spin_lock_irq(&tp->lock);
++		err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
++		spin_unlock_irq(&tp->lock);
++
++		data->val_out = mii_regval;
++
++		return err;
++	}
++
++	case SIOCSMIIREG:
++		if (tp->phy_id == PHY_ID_SERDES)
++			break;			/* We have no PHY */
++
++		if (!capable(CAP_NET_ADMIN))
++			return -EPERM;
++
++		spin_lock_irq(&tp->lock);
++		err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in);
++		spin_unlock_irq(&tp->lock);
++
++		return err;
++
++	default:
++		/* do nothing */
++		break;
++	}
++	return -EOPNOTSUPP;
++}
++
++#if TG3_VLAN_TAG_USED
++static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
++{
++	struct tg3 *tp = netdev_priv(dev);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	tp->vlgrp = grp;
++
++	/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
++	__tg3_set_rx_mode(dev);
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++}
++
++static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
++{
++	struct tg3 *tp = netdev_priv(dev);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++	if (tp->vlgrp)
++		tp->vlgrp->vlan_devices[vid] = NULL;
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++}
++#endif
++
++static struct ethtool_ops tg3_ethtool_ops = {
++	.get_settings		= tg3_get_settings,
++	.set_settings		= tg3_set_settings,
++	.get_drvinfo		= tg3_get_drvinfo,
++	.get_regs_len		= tg3_get_regs_len,
++	.get_regs		= tg3_get_regs,
++	.get_wol		= tg3_get_wol,
++	.set_wol		= tg3_set_wol,
++	.get_msglevel		= tg3_get_msglevel,
++	.set_msglevel		= tg3_set_msglevel,
++	.nway_reset		= tg3_nway_reset,
++	.get_link		= ethtool_op_get_link,
++	.get_eeprom_len		= tg3_get_eeprom_len,
++	.get_eeprom		= tg3_get_eeprom,
++	.get_ringparam		= tg3_get_ringparam,
++	.set_ringparam		= tg3_set_ringparam,
++	.get_pauseparam		= tg3_get_pauseparam,
++	.set_pauseparam		= tg3_set_pauseparam,
++	.get_rx_csum		= tg3_get_rx_csum,
++	.set_rx_csum		= tg3_set_rx_csum,
++	.get_tx_csum		= ethtool_op_get_tx_csum,
++	.set_tx_csum		= tg3_set_tx_csum,
++	.get_sg			= ethtool_op_get_sg,
++	.set_sg			= ethtool_op_set_sg,
++#if TG3_TSO_SUPPORT != 0
++	.get_tso		= ethtool_op_get_tso,
++	.set_tso		= tg3_set_tso,
++#endif
++	.get_strings		= tg3_get_strings,
++	.get_stats_count	= tg3_get_stats_count,
++	.get_ethtool_stats	= tg3_get_ethtool_stats,
++};
++
++/* Chips other than 5700/5701 use the NVRAM for fetching info. */
++static void __devinit tg3_nvram_init(struct tg3 *tp)
++{
++	int j;
++
++	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
++		return;
++
++	tw32_f(GRC_EEPROM_ADDR,
++	     (EEPROM_ADDR_FSM_RESET |
++	      (EEPROM_DEFAULT_CLOCK_PERIOD <<
++	       EEPROM_ADDR_CLKPERD_SHIFT)));
++
++	/* XXX schedule_timeout() ... */
++	for (j = 0; j < 100; j++)
++		udelay(10);
++
++	/* Enable seeprom accesses. */
++	tw32_f(GRC_LOCAL_CTRL,
++	     tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
++	udelay(100);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
++		u32 nvcfg1;
++
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++			u32 nvaccess = tr32(NVRAM_ACCESS);
++
++			tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
++		}
++
++		nvcfg1 = tr32(NVRAM_CFG1);
++
++		tp->tg3_flags |= TG3_FLAG_NVRAM;
++		if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
++			if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE)
++				tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
++		} else {
++			nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
++			tw32(NVRAM_CFG1, nvcfg1);
++		}
++
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++			u32 nvaccess = tr32(NVRAM_ACCESS);
++
++			tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
++		}
++	} else {
++		tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
++	}
++}
++
++static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp,
++						 u32 offset, u32 *val)
++{
++	u32 tmp;
++	int i;
++
++	if (offset > EEPROM_ADDR_ADDR_MASK ||
++	    (offset % 4) != 0)
++		return -EINVAL;
++
++	tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
++					EEPROM_ADDR_DEVID_MASK |
++					EEPROM_ADDR_READ);
++	tw32(GRC_EEPROM_ADDR,
++	     tmp |
++	     (0 << EEPROM_ADDR_DEVID_SHIFT) |
++	     ((offset << EEPROM_ADDR_ADDR_SHIFT) &
++	      EEPROM_ADDR_ADDR_MASK) |
++	     EEPROM_ADDR_READ | EEPROM_ADDR_START);
++
++	for (i = 0; i < 10000; i++) {
++		tmp = tr32(GRC_EEPROM_ADDR);
++
++		if (tmp & EEPROM_ADDR_COMPLETE)
++			break;
++		udelay(100);
++	}
++	if (!(tmp & EEPROM_ADDR_COMPLETE))
++		return -EBUSY;
++
++	*val = tr32(GRC_EEPROM_DATA);
++	return 0;
++}
++
++static int __devinit tg3_nvram_read(struct tg3 *tp,
++				    u32 offset, u32 *val)
++{
++	int i;
++
++	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
++		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n");
++		return -EINVAL;
++	}
++
++	if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
++		return tg3_nvram_read_using_eeprom(tp, offset, val);
++
++	if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED)
++		offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) <<
++			  NVRAM_BUFFERED_PAGE_POS) +
++			(offset % NVRAM_BUFFERED_PAGE_SIZE);
++
++	if (offset > NVRAM_ADDR_MSK)
++		return -EINVAL;
++
++	tg3_nvram_lock(tp);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		u32 nvaccess = tr32(NVRAM_ACCESS);
++
++		tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
++	}
++
++	tw32(NVRAM_ADDR, offset);
++	tw32(NVRAM_CMD,
++	     NVRAM_CMD_RD | NVRAM_CMD_GO |
++	     NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
++
++	/* Wait for done bit to clear. */
++	for (i = 0; i < 1000; i++) {
++		udelay(10);
++		if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
++			udelay(10);
++			*val = swab32(tr32(NVRAM_RDDATA));
++			break;
++		}
++	}
++
++	tg3_nvram_unlock(tp);
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		u32 nvaccess = tr32(NVRAM_ACCESS);
++
++		tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
++	}
++
++	if (i >= 1000)
++		return -EBUSY;
++
++	return 0;
++}
++
++struct subsys_tbl_ent {
++	u16 subsys_vendor, subsys_devid;
++	u32 phy_id;
++};
++
++static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
++	/* Broadcom boards. */
++	{ PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES  }, /* BCM95700A9 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x8009, PHY_ID_BCM5703 }, /* BCM95703Ax2 */
++
++	/* 3com boards. */
++	{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
++	{ PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
++	{ PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES  }, /* 3C996SX */
++	{ PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
++	{ PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
++
++	/* DELL boards. */
++	{ PCI_VENDOR_ID_DELL, 0x00d1, PHY_ID_BCM5401 }, /* VIPER */
++	{ PCI_VENDOR_ID_DELL, 0x0106, PHY_ID_BCM5401 }, /* JAGUAR */
++	{ PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */
++	{ PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */
++
++	/* Compaq boards. */
++	{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
++	{ PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
++	{ PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES  }, /* CHANGELING */
++	{ PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
++	{ PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */
++
++	/* IBM boards. */
++	{ PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */
++};
++
++static int __devinit tg3_phy_probe(struct tg3 *tp)
++{
++	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
++	u32 hw_phy_id, hw_phy_id_masked;
++	u32 val;
++	int i, eeprom_signature_found, err;
++
++	tp->phy_id = PHY_ID_INVALID;
++	for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) {
++		if ((subsys_id_to_phy_id[i].subsys_vendor ==
++		     tp->pdev->subsystem_vendor) &&
++		    (subsys_id_to_phy_id[i].subsys_devid ==
++		     tp->pdev->subsystem_device)) {
++			tp->phy_id = subsys_id_to_phy_id[i].phy_id;
++			break;
++		}
++	}
++
++	eeprom_phy_id = PHY_ID_INVALID;
++	eeprom_signature_found = 0;
++	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
++	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
++		u32 nic_cfg, led_cfg;
++
++		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
++		tp->nic_sram_data_cfg = nic_cfg;
++
++		eeprom_signature_found = 1;
++
++		if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
++		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
++			eeprom_phy_id = PHY_ID_SERDES;
++		} else {
++			u32 nic_phy_id;
++
++			tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
++			if (nic_phy_id != 0) {
++				u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
++				u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
++
++				eeprom_phy_id  = (id1 >> 16) << 10;
++				eeprom_phy_id |= (id2 & 0xfc00) << 16;
++				eeprom_phy_id |= (id2 & 0x03ff) <<  0;
++			}
++		}
++
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++			tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
++			led_cfg &= (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
++				    SHASTA_EXT_LED_MODE_MASK);
++		} else
++			led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK;
++
++		switch (led_cfg) {
++		default:
++		case NIC_SRAM_DATA_CFG_LED_MODE_PHY_1:
++			tp->led_ctrl = LED_CTRL_MODE_PHY_1;
++			break;
++
++		case NIC_SRAM_DATA_CFG_LED_MODE_PHY_2:
++			tp->led_ctrl = LED_CTRL_MODE_PHY_2;
++			break;
++
++		case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
++			tp->led_ctrl = LED_CTRL_MODE_MAC;
++			break;
++
++		case SHASTA_EXT_LED_SHARED:
++			tp->led_ctrl = LED_CTRL_MODE_SHARED;
++			if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
++			    tp->pci_chip_rev_id != CHIPREV_ID_5750_A1)
++				tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
++						 LED_CTRL_MODE_PHY_2);
++			break;
++
++		case SHASTA_EXT_LED_MAC:
++			tp->led_ctrl = LED_CTRL_MODE_SHASTA_MAC;
++			break;
++
++		case SHASTA_EXT_LED_COMBO:
++			tp->led_ctrl = LED_CTRL_MODE_COMBO;
++			if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)
++				tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
++						 LED_CTRL_MODE_PHY_2);
++			break;
++
++		};
++
++		if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++		     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) &&
++		    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
++			tp->led_ctrl = LED_CTRL_MODE_PHY_2;
++
++		if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
++		     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
++		     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) &&
++		    (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
++			tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
++
++		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
++			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
++			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
++		}
++		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
++			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
++	}
++
++	/* Reading the PHY ID register can conflict with ASF
++	 * firwmare access to the PHY hardware.
++	 */
++	err = 0;
++	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
++		hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID;
++	} else {
++		/* Now read the physical PHY_ID from the chip and verify
++		 * that it is sane.  If it doesn't look good, we fall back
++		 * to either the hard-coded table based PHY_ID and failing
++		 * that the value found in the eeprom area.
++		 */
++		err |= tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
++		err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
++
++		hw_phy_id  = (hw_phy_id_1 & 0xffff) << 10;
++		hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
++		hw_phy_id |= (hw_phy_id_2 & 0x03ff) <<  0;
++
++		hw_phy_id_masked = hw_phy_id & PHY_ID_MASK;
++	}
++
++	if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
++		tp->phy_id = hw_phy_id;
++	} else {
++		/* phy_id currently holds the value found in the
++		 * subsys_id_to_phy_id[] table or PHY_ID_INVALID
++		 * if a match was not found there.
++		 */
++		if (tp->phy_id == PHY_ID_INVALID) {
++			if (!eeprom_signature_found ||
++			    !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
++				return -ENODEV;
++			tp->phy_id = eeprom_phy_id;
++		}
++	}
++
++	if (tp->phy_id != PHY_ID_SERDES &&
++	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
++		u32 bmsr, adv_reg, tg3_ctrl;
++
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++		tg3_readphy(tp, MII_BMSR, &bmsr);
++
++		if (bmsr & BMSR_LSTATUS)
++			goto skip_phy_reset;
++		    
++		err = tg3_phy_reset(tp);
++		if (err)
++			return err;
++
++		adv_reg = (ADVERTISE_10HALF | ADVERTISE_10FULL |
++			   ADVERTISE_100HALF | ADVERTISE_100FULL |
++			   ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
++		tg3_ctrl = 0;
++		if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
++			tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
++				    MII_TG3_CTRL_ADV_1000_FULL);
++			if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
++			    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
++				tg3_ctrl |= (MII_TG3_CTRL_AS_MASTER |
++					     MII_TG3_CTRL_ENABLE_AS_MASTER);
++		}
++
++		if (!tg3_copper_is_advertising_all(tp)) {
++			tg3_writephy(tp, MII_ADVERTISE, adv_reg);
++
++			if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
++				tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl);
++
++			tg3_writephy(tp, MII_BMCR,
++				     BMCR_ANENABLE | BMCR_ANRESTART);
++		}
++		tg3_phy_set_wirespeed(tp);
++
++		tg3_writephy(tp, MII_ADVERTISE, adv_reg);
++		if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
++			tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl);
++	}
++
++skip_phy_reset:
++	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
++		err = tg3_init_5401phy_dsp(tp);
++		if (err)
++			return err;
++	}
++
++	if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) {
++		err = tg3_init_5401phy_dsp(tp);
++	}
++
++	if (!eeprom_signature_found)
++		tp->led_ctrl = LED_CTRL_MODE_PHY_1;
++
++	if (tp->phy_id == PHY_ID_SERDES)
++		tp->link_config.advertising =
++			(ADVERTISED_1000baseT_Half |
++			 ADVERTISED_1000baseT_Full |
++			 ADVERTISED_Autoneg |
++			 ADVERTISED_FIBRE);
++	if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
++		tp->link_config.advertising &=
++			~(ADVERTISED_1000baseT_Half |
++			  ADVERTISED_1000baseT_Full);
++
++	return err;
++}
++
++static void __devinit tg3_read_partno(struct tg3 *tp)
++{
++	unsigned char vpd_data[256];
++	int i;
++
++	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
++		/* Sun decided not to put the necessary bits in the
++		 * NVRAM of their onboard tg3 parts :(
++		 */
++		strcpy(tp->board_part_number, "Sun 5704");
++		return;
++	}
++
++	for (i = 0; i < 256; i += 4) {
++		u32 tmp;
++
++		if (tg3_nvram_read(tp, 0x100 + i, &tmp))
++			goto out_not_found;
++
++		vpd_data[i + 0] = ((tmp >>  0) & 0xff);
++		vpd_data[i + 1] = ((tmp >>  8) & 0xff);
++		vpd_data[i + 2] = ((tmp >> 16) & 0xff);
++		vpd_data[i + 3] = ((tmp >> 24) & 0xff);
++	}
++
++	/* Now parse and find the part number. */
++	for (i = 0; i < 256; ) {
++		unsigned char val = vpd_data[i];
++		int block_end;
++
++		if (val == 0x82 || val == 0x91) {
++			i = (i + 3 +
++			     (vpd_data[i + 1] +
++			      (vpd_data[i + 2] << 8)));
++			continue;
++		}
++
++		if (val != 0x90)
++			goto out_not_found;
++
++		block_end = (i + 3 +
++			     (vpd_data[i + 1] +
++			      (vpd_data[i + 2] << 8)));
++		i += 3;
++		while (i < block_end) {
++			if (vpd_data[i + 0] == 'P' &&
++			    vpd_data[i + 1] == 'N') {
++				int partno_len = vpd_data[i + 2];
++
++				if (partno_len > 24)
++					goto out_not_found;
++
++				memcpy(tp->board_part_number,
++				       &vpd_data[i + 3],
++				       partno_len);
++
++				/* Success. */
++				return;
++			}
++		}
++
++		/* Part number not found. */
++		goto out_not_found;
++	}
++
++out_not_found:
++	strcpy(tp->board_part_number, "none");
++}
++
++#ifdef CONFIG_SPARC64
++static int __devinit tg3_is_sun_5704(struct tg3 *tp)
++{
++	struct pci_dev *pdev = tp->pdev;
++	struct pcidev_cookie *pcp = pdev->sysdata;
++
++	if (pcp != NULL) {
++		int node = pcp->prom_node;
++		u32 venid, devid;
++		int err;
++
++		err = prom_getproperty(node, "subsystem-vendor-id",
++				       (char *) &venid, sizeof(venid));
++		if (err == 0 || err == -1)
++			return 0;
++		err = prom_getproperty(node, "subsystem-id",
++				       (char *) &devid, sizeof(devid));
++		if (err == 0 || err == -1)
++			return 0;
++
++		if (venid == PCI_VENDOR_ID_SUN &&
++		    devid == PCI_DEVICE_ID_TIGON3_5704)
++			return 1;
++	}
++	return 0;
++}
++#endif
++
++static int __devinit tg3_get_invariants(struct tg3 *tp)
++{
++	u32 misc_ctrl_reg;
++	u32 cacheline_sz_reg;
++	u32 pci_state_reg, grc_misc_cfg;
++	u32 val;
++	u16 pci_cmd;
++	int err;
++
++#ifdef CONFIG_SPARC64
++	if (tg3_is_sun_5704(tp))
++		tp->tg3_flags2 |= TG3_FLG2_SUN_5704;
++#endif
++
++	/* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write
++	 * reordering to the mailbox registers done by the host
++	 * controller can cause major troubles.  We read back from
++	 * every mailbox register write to force the writes to be
++	 * posted to the chip in order.
++	 */
++	if (pci_find_device(PCI_VENDOR_ID_INTEL,
++			    PCI_DEVICE_ID_INTEL_82801AA_8, NULL) ||
++	    pci_find_device(PCI_VENDOR_ID_INTEL,
++			    PCI_DEVICE_ID_INTEL_82801AB_8, NULL) ||
++	    pci_find_device(PCI_VENDOR_ID_INTEL,
++			    PCI_DEVICE_ID_INTEL_82801BA_11, NULL) ||
++	    pci_find_device(PCI_VENDOR_ID_INTEL,
++			    PCI_DEVICE_ID_INTEL_82801BA_6, NULL) ||
++	    pci_find_device(PCI_VENDOR_ID_AMD,
++			    PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL))
++		tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
++
++	/* Force memory write invalidate off.  If we leave it on,
++	 * then on 5700_BX chips we have to enable a workaround.
++	 * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
++	 * to match the cacheline size.  The Broadcom driver have this
++	 * workaround but turns MWI off all the times so never uses
++	 * it.  This seems to suggest that the workaround is insufficient.
++	 */
++	pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
++	pci_cmd &= ~PCI_COMMAND_INVALIDATE;
++	pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
++
++	/* It is absolutely critical that TG3PCI_MISC_HOST_CTRL
++	 * has the register indirect write enable bit set before
++	 * we try to access any of the MMIO registers.  It is also
++	 * critical that the PCI-X hw workaround situation is decided
++	 * before that as well.
++	 */
++	pci_read_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
++			      &misc_ctrl_reg);
++
++	tp->pci_chip_rev_id = (misc_ctrl_reg >>
++			       MISC_HOST_CTRL_CHIPREV_SHIFT);
++
++	/* Initialize misc host control in PCI block. */
++	tp->misc_host_ctrl |= (misc_ctrl_reg &
++			       MISC_HOST_CTRL_CHIPREV);
++	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
++			       tp->misc_host_ctrl);
++
++	pci_read_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
++			      &cacheline_sz_reg);
++
++	tp->pci_cacheline_sz = (cacheline_sz_reg >>  0) & 0xff;
++	tp->pci_lat_timer    = (cacheline_sz_reg >>  8) & 0xff;
++	tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
++	tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
++
++	if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
++		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
++	    tp->pci_lat_timer < 64) {
++		tp->pci_lat_timer = 64;
++
++		cacheline_sz_reg  = ((tp->pci_cacheline_sz & 0xff) <<  0);
++		cacheline_sz_reg |= ((tp->pci_lat_timer    & 0xff) <<  8);
++		cacheline_sz_reg |= ((tp->pci_hdr_type     & 0xff) << 16);
++		cacheline_sz_reg |= ((tp->pci_bist         & 0xff) << 24);
++
++		pci_write_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
++				       cacheline_sz_reg);
++	}
++
++	pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
++			      &pci_state_reg);
++
++	if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
++		tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
++
++		/* If this is a 5700 BX chipset, and we are in PCI-X
++		 * mode, enable register write workaround.
++		 *
++		 * The workaround is to use indirect register accesses
++		 * for all chip writes not to mailbox registers.
++		 */
++		if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
++			u32 pm_reg;
++			u16 pci_cmd;
++
++			tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
++
++			/* The chip can have it's power management PCI config
++			 * space registers clobbered due to this bug.
++			 * So explicitly force the chip into D0 here.
++			 */
++			pci_read_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT,
++					      &pm_reg);
++			pm_reg &= ~PCI_PM_CTRL_STATE_MASK;
++			pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */;
++			pci_write_config_dword(tp->pdev, TG3PCI_PM_CTRL_STAT,
++					       pm_reg);
++
++			/* Also, force SERR#/PERR# in PCI command. */
++			pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
++			pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
++			pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd);
++		}
++	}
++
++	/* Back to back register writes can cause problems on this chip,
++	 * the workaround is to read back all reg writes except those to
++	 * mailbox regs.  See tg3_write_indirect_reg32().
++	 *
++	 * PCI Express 5750_A0 rev chips need this workaround too.
++	 */
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
++	    ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
++	     tp->pci_chip_rev_id == CHIPREV_ID_5750_A0))
++		tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG;
++
++	if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
++		tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
++	if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
++		tp->tg3_flags |= TG3_FLAG_PCI_32BIT;
++
++	/* Chip-specific fixup from Broadcom driver */
++	if ((tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) &&
++	    (!(pci_state_reg & PCISTATE_RETRY_SAME_DMA))) {
++		pci_state_reg |= PCISTATE_RETRY_SAME_DMA;
++		pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
++	}
++
++	/* Force the chip into D0. */
++	err = tg3_set_power_state(tp, 0);
++	if (err) {
++		printk(KERN_ERR PFX "(%s) transition to D0 failed\n",
++		       pci_name(tp->pdev));
++		return err;
++	}
++
++	/* 5700 B0 chips do not support checksumming correctly due
++	 * to hardware bugs.
++	 */
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
++		tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
++
++	/* Pseudo-header checksum is done by hardware logic and not
++	 * the offload processers, so make the chip do the pseudo-
++	 * header checksums on receive.  For transmit it is more
++	 * convenient to do the pseudo-header checksum in software
++	 * as Linux does that on transmit for us in all cases.
++	 */
++	tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM;
++	tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM;
++
++	/* Derive initial jumbo mode from MTU assigned in
++	 * ether_setup() via the alloc_etherdev() call
++	 */
++	if (tp->dev->mtu > ETH_DATA_LEN)
++		tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE;
++
++	/* Determine WakeOnLan speed to use. */
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++	    tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
++	    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0 ||
++	    tp->pci_chip_rev_id == CHIPREV_ID_5701_B2) {
++		tp->tg3_flags &= ~(TG3_FLAG_WOL_SPEED_100MB);
++	} else {
++		tp->tg3_flags |= TG3_FLAG_WOL_SPEED_100MB;
++	}
++
++	/* A few boards don't want Ethernet at WireSpeed phy feature */
++	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
++	    ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
++	     (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
++	     (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)))
++		tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED;
++
++	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX ||
++	    GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX)
++		tp->tg3_flags2 |= TG3_FLG2_PHY_ADC_BUG;
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
++		tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
++
++	/* Only 5701 and later support tagged irq status mode.
++	 * Also, 5788 chips cannot use tagged irq status.
++	 *
++	 * However, since we are using NAPI avoid tagged irq status
++	 * because the interrupt condition is more difficult to
++	 * fully clear in that mode.
++	 */
++	tp->coalesce_mode = 0;
++
++	if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
++	    GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
++		tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
++
++	/* Initialize MAC MI mode, polling disabled. */
++	tw32_f(MAC_MI_MODE, tp->mi_mode);
++	udelay(80);
++
++	/* Initialize data/descriptor byte/word swapping. */
++	val = tr32(GRC_MODE);
++	val &= GRC_MODE_HOST_STACKUP;
++	tw32(GRC_MODE, val | tp->grc_mode);
++
++	tg3_switch_clocks(tp);
++
++	/* Clear this out for sanity. */
++	tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
++
++	pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
++			      &pci_state_reg);
++	if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
++	    (tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) == 0) {
++		u32 chiprevid = GET_CHIP_REV_ID(tp->misc_host_ctrl);
++
++		if (chiprevid == CHIPREV_ID_5701_A0 ||
++		    chiprevid == CHIPREV_ID_5701_B0 ||
++		    chiprevid == CHIPREV_ID_5701_B2 ||
++		    chiprevid == CHIPREV_ID_5701_B5) {
++			unsigned long sram_base;
++
++			/* Write some dummy words into the SRAM status block
++			 * area, see if it reads back correctly.  If the return
++			 * value is bad, force enable the PCIX workaround.
++			 */
++			sram_base = tp->regs + NIC_SRAM_WIN_BASE + NIC_SRAM_STATS_BLK;
++
++			writel(0x00000000, sram_base);
++			writel(0x00000000, sram_base + 4);
++			writel(0xffffffff, sram_base + 4);
++			if (readl(sram_base) != 0x00000000)
++				tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
++		}
++	}
++
++	udelay(50);
++	tg3_nvram_init(tp);
++
++	/* Always use host TXDs, it performs better in particular
++	 * with multi-frag packets.  The tests below are kept here
++	 * as documentation should we change this decision again
++	 * in the future.
++	 */
++	tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
++
++#if 0
++	/* Determine if TX descriptors will reside in
++	 * main memory or in the chip SRAM.
++	 */
++	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++		tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
++#endif
++
++	grc_misc_cfg = tr32(GRC_MISC_CFG);
++	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
++	    grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
++		tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
++		tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
++	    (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
++	     grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
++		tp->tg3_flags2 |= TG3_FLG2_IS_5788;
++
++	/* these are limited to 10/100 only */
++	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
++	     (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
++	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
++	     tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
++	     (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
++	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
++	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
++	    (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
++	     tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F))
++		tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
++
++	err = tg3_phy_probe(tp);
++	if (err) {
++		printk(KERN_ERR PFX "(%s) phy probe failed, err %d\n",
++		       pci_name(tp->pdev), err);
++		/* ... but do not return immediately ... */
++	}
++
++	tg3_read_partno(tp);
++
++	if (tp->phy_id == PHY_ID_SERDES) {
++		tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
++	} else {
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
++			tp->tg3_flags |= TG3_FLAG_USE_MI_INTERRUPT;
++		else
++			tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
++	}
++
++	/* 5700 {AX,BX} chips have a broken status block link
++	 * change bit implementation, so we must use the
++	 * status register in those cases.
++	 */
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
++		tp->tg3_flags |= TG3_FLAG_USE_LINKCHG_REG;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_USE_LINKCHG_REG;
++
++	/* The led_ctrl is set during tg3_phy_probe, here we might
++	 * have to force the link status polling mechanism based
++	 * upon subsystem IDs.
++	 */
++	if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
++	    tp->phy_id != PHY_ID_SERDES) {
++		tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
++				  TG3_FLAG_USE_LINKCHG_REG);
++	}
++
++	/* For all SERDES we poll the MAC status register. */
++	if (tp->phy_id == PHY_ID_SERDES)
++		tp->tg3_flags |= TG3_FLAG_POLL_SERDES;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
++
++	/* 5700 BX chips need to have their TX producer index mailboxes
++	 * written twice to workaround a bug.
++	 */
++	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
++		tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
++	else
++		tp->tg3_flags &= ~TG3_FLAG_TXD_MBOX_HWBUG;
++
++	/* It seems all chips can get confused if TX buffers
++	 * straddle the 4GB address boundary in some cases.
++	 */
++	tp->dev->hard_start_xmit = tg3_start_xmit;
++
++	tp->rx_offset = 2;
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
++	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
++		tp->rx_offset = 0;
++
++	/* By default, disable wake-on-lan.  User can change this
++	 * using ETHTOOL_SWOL.
++	 */
++	tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
++
++	return err;
++}
++
++#ifdef CONFIG_SPARC64
++static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
++{
++	struct net_device *dev = tp->dev;
++	struct pci_dev *pdev = tp->pdev;
++	struct pcidev_cookie *pcp = pdev->sysdata;
++
++	if (pcp != NULL) {
++		int node = pcp->prom_node;
++
++		if (prom_getproplen(node, "local-mac-address") == 6) {
++			prom_getproperty(node, "local-mac-address",
++					 dev->dev_addr, 6);
++			return 0;
++		}
++	}
++	return -ENODEV;
++}
++
++static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
++{
++	struct net_device *dev = tp->dev;
++
++	memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
++	return 0;
++}
++#endif
++
++static int __devinit tg3_get_device_address(struct tg3 *tp)
++{
++	struct net_device *dev = tp->dev;
++	u32 hi, lo, mac_offset;
++
++#ifdef CONFIG_SPARC64
++	if (!tg3_get_macaddr_sparc(tp))
++		return 0;
++#endif
++
++	mac_offset = 0x7c;
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
++	    !(tp->tg3_flags & TG3_FLG2_SUN_5704)) {
++		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
++			mac_offset = 0xcc;
++		if (tg3_nvram_lock(tp))
++			tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
++		else
++			tg3_nvram_unlock(tp);
++	}
++
++	/* First try to get it from MAC address mailbox. */
++	tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
++	if ((hi >> 16) == 0x484b) {
++		dev->dev_addr[0] = (hi >>  8) & 0xff;
++		dev->dev_addr[1] = (hi >>  0) & 0xff;
++
++		tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_LOW_MBOX, &lo);
++		dev->dev_addr[2] = (lo >> 24) & 0xff;
++		dev->dev_addr[3] = (lo >> 16) & 0xff;
++		dev->dev_addr[4] = (lo >>  8) & 0xff;
++		dev->dev_addr[5] = (lo >>  0) & 0xff;
++	}
++	/* Next, try NVRAM. */
++	else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) &&
++		 !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
++		 !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
++		dev->dev_addr[0] = ((hi >> 16) & 0xff);
++		dev->dev_addr[1] = ((hi >> 24) & 0xff);
++		dev->dev_addr[2] = ((lo >>  0) & 0xff);
++		dev->dev_addr[3] = ((lo >>  8) & 0xff);
++		dev->dev_addr[4] = ((lo >> 16) & 0xff);
++		dev->dev_addr[5] = ((lo >> 24) & 0xff);
++	}
++	/* Finally just fetch it out of the MAC control regs. */
++	else {
++		hi = tr32(MAC_ADDR_0_HIGH);
++		lo = tr32(MAC_ADDR_0_LOW);
++
++		dev->dev_addr[5] = lo & 0xff;
++		dev->dev_addr[4] = (lo >> 8) & 0xff;
++		dev->dev_addr[3] = (lo >> 16) & 0xff;
++		dev->dev_addr[2] = (lo >> 24) & 0xff;
++		dev->dev_addr[1] = hi & 0xff;
++		dev->dev_addr[0] = (hi >> 8) & 0xff;
++	}
++
++	if (!is_valid_ether_addr(&dev->dev_addr[0])) {
++#ifdef CONFIG_SPARC64
++		if (!tg3_get_default_macaddr_sparc(tp))
++			return 0;
++#endif
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
++{
++	struct tg3_internal_buffer_desc test_desc;
++	u32 sram_dma_descs;
++	int i, ret;
++
++	sram_dma_descs = NIC_SRAM_DMA_DESC_POOL_BASE;
++
++	tw32(FTQ_RCVBD_COMP_FIFO_ENQDEQ, 0);
++	tw32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ, 0);
++	tw32(RDMAC_STATUS, 0);
++	tw32(WDMAC_STATUS, 0);
++
++	tw32(BUFMGR_MODE, 0);
++	tw32(FTQ_RESET, 0);
++
++	test_desc.addr_hi = ((u64) buf_dma) >> 32;
++	test_desc.addr_lo = buf_dma & 0xffffffff;
++	test_desc.nic_mbuf = 0x00002100;
++	test_desc.len = size;
++
++	/*
++	 * HP ZX1 was seeing test failures for 5701 cards running at 33Mhz
++	 * the *second* time the tg3 driver was getting loaded after an
++	 * initial scan.
++	 *
++	 * Broadcom tells me:
++	 *   ...the DMA engine is connected to the GRC block and a DMA
++	 *   reset may affect the GRC block in some unpredictable way...
++	 *   The behavior of resets to individual blocks has not been tested.
++	 *
++	 * Broadcom noted the GRC reset will also reset all sub-components.
++	 */
++	if (to_device) {
++		test_desc.cqid_sqid = (13 << 8) | 2;
++
++		tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE);
++		udelay(40);
++	} else {
++		test_desc.cqid_sqid = (16 << 8) | 7;
++
++		tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE);
++		udelay(40);
++	}
++	test_desc.flags = 0x00000005;
++
++	for (i = 0; i < (sizeof(test_desc) / sizeof(u32)); i++) {
++		u32 val;
++
++		val = *(((u32 *)&test_desc) + i);
++		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR,
++				       sram_dma_descs + (i * sizeof(u32)));
++		pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
++	}
++	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
++
++	if (to_device) {
++		tw32(FTQ_DMA_HIGH_READ_FIFO_ENQDEQ, sram_dma_descs);
++	} else {
++		tw32(FTQ_DMA_HIGH_WRITE_FIFO_ENQDEQ, sram_dma_descs);
++	}
++
++	ret = -ENODEV;
++	for (i = 0; i < 40; i++) {
++		u32 val;
++
++		if (to_device)
++			val = tr32(FTQ_RCVBD_COMP_FIFO_ENQDEQ);
++		else
++			val = tr32(FTQ_RCVDATA_COMP_FIFO_ENQDEQ);
++		if ((val & 0xffff) == sram_dma_descs) {
++			ret = 0;
++			break;
++		}
++
++		udelay(100);
++	}
++
++	return ret;
++}
++
++#define TEST_BUFFER_SIZE	0x400
++
++static int __devinit tg3_test_dma(struct tg3 *tp)
++{
++	dma_addr_t buf_dma;
++	u32 *buf;
++	int ret;
++
++	buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma);
++	if (!buf) {
++		ret = -ENOMEM;
++		goto out_nofree;
++	}
++
++	tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
++			  (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
++
++#ifndef CONFIG_X86
++	{
++		u8 byte;
++		int cacheline_size;
++		pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
++
++		if (byte == 0)
++			cacheline_size = 1024;
++		else
++			cacheline_size = (int) byte * 4;
++
++		switch (cacheline_size) {
++		case 16:
++		case 32:
++		case 64:
++		case 128:
++			if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
++			    !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
++				tp->dma_rwctrl |=
++					DMA_RWCTRL_WRITE_BNDRY_384_PCIX;
++				break;
++			} else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
++				tp->dma_rwctrl &=
++					~(DMA_RWCTRL_PCI_WRITE_CMD);
++				tp->dma_rwctrl |=
++					DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
++				break;
++			}
++			/* fallthrough */
++		case 256:
++			if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
++			    !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
++				tp->dma_rwctrl |=
++					DMA_RWCTRL_WRITE_BNDRY_256;
++			else if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
++				tp->dma_rwctrl |=
++					DMA_RWCTRL_WRITE_BNDRY_256_PCIX;
++		};
++	}
++#endif
++
++	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
++		tp->dma_rwctrl |= 0x001f0000;
++	} else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
++			tp->dma_rwctrl |= 0x003f0000;
++		else
++			tp->dma_rwctrl |= 0x003f000f;
++	} else {
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
++		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
++			u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
++
++			if (ccval == 0x6 || ccval == 0x7)
++				tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
++
++			/* Set bit 23 to renable PCIX hw bug fix */
++			tp->dma_rwctrl |= 0x009f0000;
++		} else {
++			tp->dma_rwctrl |= 0x001b000f;
++		}
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
++		tp->dma_rwctrl &= 0xfffffff0;
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
++		/* Remove this if it causes problems for some boards. */
++		tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT;
++
++		/* On 5700/5701 chips, we need to set this bit.
++		 * Otherwise the chip will issue cacheline transactions
++		 * to streamable DMA memory with not all the byte
++		 * enables turned on.  This is an error on several
++		 * RISC PCI controllers, in particular sparc64.
++		 *
++		 * On 5703/5704 chips, this bit has been reassigned
++		 * a different meaning.  In particular, it is used
++		 * on those chips to enable a PCI-X workaround.
++		 */
++		tp->dma_rwctrl |= DMA_RWCTRL_ASSERT_ALL_BE;
++	}
++
++	tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
++
++#if 0
++	/* Unneeded, already done by tg3_get_invariants.  */
++	tg3_switch_clocks(tp);
++#endif
++
++	ret = 0;
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
++	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
++		goto out;
++
++	while (1) {
++		u32 *p = buf, i;
++
++		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++)
++			p[i] = i;
++
++		/* Send the buffer to the chip. */
++		ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1);
++		if (ret) {
++			printk(KERN_ERR "tg3_test_dma() Write the buffer failed %d\n", ret);
++			break;
++		}
++
++#if 0
++		/* validate data reached card RAM correctly. */
++		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
++			u32 val;
++			tg3_read_mem(tp, 0x2100 + (i*4), &val);
++			if (le32_to_cpu(val) != p[i]) {
++				printk(KERN_ERR "  tg3_test_dma()  Card buffer corrupted on write! (%d != %d)\n", val, i);
++				/* ret = -ENODEV here? */
++			}
++			p[i] = 0;
++		}
++#endif
++		/* Now read it back. */
++		ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0);
++		if (ret) {
++			printk(KERN_ERR "tg3_test_dma() Read the buffer failed %d\n", ret);
++
++			break;
++		}
++
++		/* Verify it. */
++		for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
++			if (p[i] == i)
++				continue;
++
++			if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) ==
++			    DMA_RWCTRL_WRITE_BNDRY_DISAB) {
++				tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
++				tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
++				break;
++			} else {
++				printk(KERN_ERR "tg3_test_dma() buffer corrupted on read back! (%d != %d)\n", p[i], i);
++				ret = -ENODEV;
++				goto out;
++			}
++		}
++
++		if (i == (TEST_BUFFER_SIZE / sizeof(u32))) {
++			/* Success. */
++			ret = 0;
++			break;
++		}
++	}
++
++out:
++	pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma);
++out_nofree:
++	return ret;
++}
++
++static void __devinit tg3_init_link_config(struct tg3 *tp)
++{
++	tp->link_config.advertising =
++		(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
++		 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
++		 ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
++		 ADVERTISED_Autoneg | ADVERTISED_MII);
++	tp->link_config.speed = SPEED_INVALID;
++	tp->link_config.duplex = DUPLEX_INVALID;
++	tp->link_config.autoneg = AUTONEG_ENABLE;
++	netif_carrier_off(tp->dev);
++	tp->link_config.active_speed = SPEED_INVALID;
++	tp->link_config.active_duplex = DUPLEX_INVALID;
++	tp->link_config.phy_is_low_power = 0;
++	tp->link_config.orig_speed = SPEED_INVALID;
++	tp->link_config.orig_duplex = DUPLEX_INVALID;
++	tp->link_config.orig_autoneg = AUTONEG_INVALID;
++}
++
++static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
++{
++	tp->bufmgr_config.mbuf_read_dma_low_water =
++		DEFAULT_MB_RDMA_LOW_WATER;
++	tp->bufmgr_config.mbuf_mac_rx_low_water =
++		DEFAULT_MB_MACRX_LOW_WATER;
++	tp->bufmgr_config.mbuf_high_water =
++		DEFAULT_MB_HIGH_WATER;
++
++	tp->bufmgr_config.mbuf_read_dma_low_water_jumbo =
++		DEFAULT_MB_RDMA_LOW_WATER_JUMBO;
++	tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo =
++		DEFAULT_MB_MACRX_LOW_WATER_JUMBO;
++	tp->bufmgr_config.mbuf_high_water_jumbo =
++		DEFAULT_MB_HIGH_WATER_JUMBO;
++
++	tp->bufmgr_config.dma_low_water = DEFAULT_DMA_LOW_WATER;
++	tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
++}
++
++static char * __devinit tg3_phy_string(struct tg3 *tp)
++{
++	switch (tp->phy_id & PHY_ID_MASK) {
++	case PHY_ID_BCM5400:	return "5400";
++	case PHY_ID_BCM5401:	return "5401";
++	case PHY_ID_BCM5411:	return "5411";
++	case PHY_ID_BCM5701:	return "5701";
++	case PHY_ID_BCM5703:	return "5703";
++	case PHY_ID_BCM5704:	return "5704";
++	case PHY_ID_BCM5705:	return "5705";
++	case PHY_ID_BCM5750:	return "5750";
++	case PHY_ID_BCM8002:	return "8002";
++	case PHY_ID_SERDES:	return "serdes";
++	default:		return "unknown";
++	};
++}
++
++static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
++{
++	struct pci_dev *peer;
++	unsigned int func, devnr = tp->pdev->devfn & ~7;
++
++	for (func = 0; func < 8; func++) {
++		peer = pci_get_slot(tp->pdev->bus, devnr | func);
++		if (peer && peer != tp->pdev)
++			break;
++		pci_dev_put(peer);
++	}
++	if (!peer || peer == tp->pdev)
++		BUG();
++
++	/*
++	 * We don't need to keep the refcount elevated; there's no way
++	 * to remove one half of this device without removing the other
++	 */
++	pci_dev_put(peer);
++
++	return peer;
++}
++
++static int __devinit tg3_init_one(struct pci_dev *pdev,
++				  const struct pci_device_id *ent)
++{
++	static int tg3_version_printed = 0;
++	unsigned long tg3reg_base, tg3reg_len;
++	struct net_device *dev;
++	struct tg3 *tp;
++	int i, err, pci_using_dac, pm_cap;
++
++	if (tg3_version_printed++ == 0)
++		printk(KERN_INFO "%s", version);
++
++	err = pci_enable_device(pdev);
++	if (err) {
++		printk(KERN_ERR PFX "Cannot enable PCI device, "
++		       "aborting.\n");
++		return err;
++	}
++
++	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
++		printk(KERN_ERR PFX "Cannot find proper PCI device "
++		       "base address, aborting.\n");
++		err = -ENODEV;
++		goto err_out_disable_pdev;
++	}
++
++	err = pci_request_regions(pdev, DRV_MODULE_NAME);
++	if (err) {
++		printk(KERN_ERR PFX "Cannot obtain PCI resources, "
++		       "aborting.\n");
++		goto err_out_disable_pdev;
++	}
++
++	pci_set_master(pdev);
++
++	/* Find power-management capability. */
++	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
++	if (pm_cap == 0) {
++		printk(KERN_ERR PFX "Cannot find PowerManagement capability, "
++		       "aborting.\n");
++		err = -EIO;
++		goto err_out_free_res;
++	}
++
++	/* Configure DMA attributes. */
++	err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
++	if (!err) {
++		pci_using_dac = 1;
++		err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
++		if (err < 0) {
++			printk(KERN_ERR PFX "Unable to obtain 64 bit DMA "
++			       "for consistent allocations\n");
++			goto err_out_free_res;
++		}
++	} else {
++		err = pci_set_dma_mask(pdev, 0xffffffffULL);
++		if (err) {
++			printk(KERN_ERR PFX "No usable DMA configuration, "
++			       "aborting.\n");
++			goto err_out_free_res;
++		}
++		pci_using_dac = 0;
++	}
++
++	tg3reg_base = pci_resource_start(pdev, 0);
++	tg3reg_len = pci_resource_len(pdev, 0);
++
++	dev = alloc_etherdev(sizeof(*tp));
++	if (!dev) {
++		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
++		err = -ENOMEM;
++		goto err_out_free_res;
++	}
++
++	SET_MODULE_OWNER(dev);
++	SET_NETDEV_DEV(dev, &pdev->dev);
++
++	if (pci_using_dac)
++		dev->features |= NETIF_F_HIGHDMA;
++#if TG3_VLAN_TAG_USED
++	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
++	dev->vlan_rx_register = tg3_vlan_rx_register;
++	dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
++#endif
++
++	tp = netdev_priv(dev);
++	tp->pdev = pdev;
++	tp->dev = dev;
++	tp->pm_cap = pm_cap;
++	tp->mac_mode = TG3_DEF_MAC_MODE;
++	tp->rx_mode = TG3_DEF_RX_MODE;
++	tp->tx_mode = TG3_DEF_TX_MODE;
++	tp->mi_mode = MAC_MI_MODE_BASE;
++	if (tg3_debug > 0)
++		tp->msg_enable = tg3_debug;
++	else
++		tp->msg_enable = TG3_DEF_MSG_ENABLE;
++
++	/* The word/byte swap controls here control register access byte
++	 * swapping.  DMA data byte swapping is controlled in the GRC_MODE
++	 * setting below.
++	 */
++	tp->misc_host_ctrl =
++		MISC_HOST_CTRL_MASK_PCI_INT |
++		MISC_HOST_CTRL_WORD_SWAP |
++		MISC_HOST_CTRL_INDIR_ACCESS |
++		MISC_HOST_CTRL_PCISTATE_RW;
++
++	/* The NONFRM (non-frame) byte/word swap controls take effect
++	 * on descriptor entries, anything which isn't packet data.
++	 *
++	 * The StrongARM chips on the board (one for tx, one for rx)
++	 * are running in big-endian mode.
++	 */
++	tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA |
++			GRC_MODE_WSWAP_NONFRM_DATA);
++#ifdef __BIG_ENDIAN
++	tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
++#endif
++	spin_lock_init(&tp->lock);
++	spin_lock_init(&tp->tx_lock);
++	spin_lock_init(&tp->indirect_lock);
++	INIT_WORK(&tp->reset_task, tg3_reset_task, tp);
++
++	tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
++	if (tp->regs == 0UL) {
++		printk(KERN_ERR PFX "Cannot map device registers, "
++		       "aborting.\n");
++		err = -ENOMEM;
++		goto err_out_free_dev;
++	}
++
++	tg3_init_link_config(tp);
++
++	tg3_init_bufmgr_config(tp);
++
++	tp->rx_pending = TG3_DEF_RX_RING_PENDING;
++	tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
++	tp->tx_pending = TG3_DEF_TX_RING_PENDING;
++
++	dev->open = tg3_open;
++	dev->stop = tg3_close;
++	dev->get_stats = tg3_get_stats;
++	dev->set_multicast_list = tg3_set_rx_mode;
++	dev->set_mac_address = tg3_set_mac_addr;
++	dev->do_ioctl = tg3_ioctl;
++	dev->tx_timeout = tg3_tx_timeout;
++	dev->poll = tg3_poll;
++	dev->ethtool_ops = &tg3_ethtool_ops;
++	dev->weight = 64;
++	dev->watchdog_timeo = TG3_TX_TIMEOUT;
++	dev->change_mtu = tg3_change_mtu;
++	dev->irq = pdev->irq;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++	dev->poll_controller = tg3_poll_controller;
++#endif
++
++	err = tg3_get_invariants(tp);
++	if (err) {
++		printk(KERN_ERR PFX "Problem fetching invariants of chip, "
++		       "aborting.\n");
++		goto err_out_iounmap;
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		tp->bufmgr_config.mbuf_read_dma_low_water =
++			DEFAULT_MB_RDMA_LOW_WATER_5705;
++		tp->bufmgr_config.mbuf_mac_rx_low_water =
++			DEFAULT_MB_MACRX_LOW_WATER_5705;
++		tp->bufmgr_config.mbuf_high_water =
++			DEFAULT_MB_HIGH_WATER_5705;
++	}
++
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
++		/* Ick.  This needs firmware loading. */
++		err = tg3_request_firmware(&tg3_fw_5701_a0,
++					   "tg3/5701_a0-0.0.0", tp);
++		if (err)
++			goto err_out_iounmap;
++	}
++
++#if TG3_TSO_SUPPORT != 0
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
++	    tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 ||
++	    ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 &&
++	     GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) {
++		tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
++	} else {
++		const char *name;
++
++		name = "tg3/tso-1.4.0";
++		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
++			/* 5705 needs a special version of the TSO firmware. */
++			name = "tg3/tso_5705-1.1.0";
++		}
++		err = tg3_request_firmware(&tg3_fw_tso5, name, tp);
++		if (err) {
++			/* We can function without TSO; pretend it's
++			 * not supported. */
++			printk(KERN_INFO PFX "%s: Firmware \"%s\" not "
++			       "loaded; continuing without TSO.\n",
++			       tp->dev->name, name);
++			tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
++		} else
++			tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
++	}
++
++	/* TSO is off by default, user can enable using ethtool.  */
++#if 0
++	if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)
++		dev->features |= NETIF_F_TSO;
++#endif
++
++#endif
++
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 &&
++	    !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) &&
++	    !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) {
++		tp->tg3_flags2 |= TG3_FLG2_MAX_RXPEND_64;
++		tp->rx_pending = 63;
++	}
++
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
++		tp->pdev_peer = tg3_find_5704_peer(tp);
++
++	err = tg3_get_device_address(tp);
++	if (err) {
++		printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
++		       "aborting.\n");
++		goto err_out_iounmap;
++	}
++
++	/*
++	 * Reset chip in case UNDI or EFI driver did not shutdown
++	 * DMA self test will enable WDMAC and we'll see (spurious)
++	 * pending DMA on the PCI bus at that point.
++	 */
++	if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
++	    (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
++		pci_save_state(tp->pdev, tp->pci_cfg_state);
++		tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
++		tg3_halt(tp);
++	}
++
++	err = tg3_test_dma(tp);
++	if (err) {
++		printk(KERN_ERR PFX "DMA engine test failed, aborting.\n");
++		goto err_out_iounmap;
++	}
++
++	/* Tigon3 can do ipv4 only... and some chips have buggy
++	 * checksumming.
++	 */
++	if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
++		dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
++		tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
++	} else
++		tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
++
++	if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
++		dev->features &= ~NETIF_F_HIGHDMA;
++
++	err = register_netdev(dev);
++	if (err) {
++		printk(KERN_ERR PFX "Cannot register net device, "
++		       "aborting.\n");
++		goto err_out_iounmap;
++	}
++
++	pci_set_drvdata(pdev, dev);
++
++	/* Now that we have fully setup the chip, save away a snapshot
++	 * of the PCI config space.  We need to restore this after
++	 * GRC_MISC_CFG core clock resets and some resume events.
++	 */
++	pci_save_state(tp->pdev, tp->pci_cfg_state);
++
++	printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ",
++	       dev->name,
++	       tp->board_part_number,
++	       tp->pci_chip_rev_id,
++	       tg3_phy_string(tp),
++	       ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""),
++	       ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ?
++		((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
++		((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
++	       ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"),
++	       (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
++
++	for (i = 0; i < 6; i++)
++		printk("%2.2x%c", dev->dev_addr[i],
++		       i == 5 ? '\n' : ':');
++
++	printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] "
++	       "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
++	       "TSOcap[%d] \n",
++	       dev->name,
++	       (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0,
++	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
++	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
++	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
++	       (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
++	       (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
++	       (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
++	       (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
++
++	return 0;
++
++err_out_iounmap:
++	iounmap((void *) tp->regs);
++
++err_out_free_dev:
++	free_netdev(dev);
++
++err_out_free_res:
++	pci_release_regions(pdev);
++
++err_out_disable_pdev:
++	pci_disable_device(pdev);
++	pci_set_drvdata(pdev, NULL);
++	return err;
++}
++
++static void __devexit tg3_remove_one(struct pci_dev *pdev)
++{
++	struct net_device *dev = pci_get_drvdata(pdev);
++
++	if (dev) {
++		struct tg3 *tp = netdev_priv(dev);
++
++		unregister_netdev(dev);
++		iounmap((void *)tp->regs);
++		free_netdev(dev);
++		pci_release_regions(pdev);
++		pci_disable_device(pdev);
++		pci_set_drvdata(pdev, NULL);
++	}
++}
++
++static int tg3_suspend(struct pci_dev *pdev, u32 state)
++{
++	struct net_device *dev = pci_get_drvdata(pdev);
++	struct tg3 *tp = netdev_priv(dev);
++	int err;
++
++	if (!netif_running(dev))
++		return 0;
++
++	tg3_netif_stop(tp);
++
++	del_timer_sync(&tp->timer);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++	tg3_disable_ints(tp);
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	netif_device_detach(dev);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++	tg3_halt(tp);
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	err = tg3_set_power_state(tp, state);
++	if (err) {
++		spin_lock_irq(&tp->lock);
++		spin_lock(&tp->tx_lock);
++
++		tg3_init_hw(tp);
++
++		tp->timer.expires = jiffies + tp->timer_offset;
++		add_timer(&tp->timer);
++
++		spin_unlock(&tp->tx_lock);
++		spin_unlock_irq(&tp->lock);
++
++		netif_device_attach(dev);
++		tg3_netif_start(tp);
++	}
++
++	return err;
++}
++
++static int tg3_resume(struct pci_dev *pdev)
++{
++	struct net_device *dev = pci_get_drvdata(pdev);
++	struct tg3 *tp = netdev_priv(dev);
++	int err;
++
++	if (!netif_running(dev))
++		return 0;
++
++	pci_restore_state(tp->pdev, tp->pci_cfg_state);
++
++	err = tg3_set_power_state(tp, 0);
++	if (err)
++		return err;
++
++	netif_device_attach(dev);
++
++	spin_lock_irq(&tp->lock);
++	spin_lock(&tp->tx_lock);
++
++	tg3_init_hw(tp);
++
++	tp->timer.expires = jiffies + tp->timer_offset;
++	add_timer(&tp->timer);
++
++	tg3_enable_ints(tp);
++
++	spin_unlock(&tp->tx_lock);
++	spin_unlock_irq(&tp->lock);
++
++	tg3_netif_start(tp);
++
++	return 0;
++}
++
++static struct pci_driver tg3_driver = {
++	.name		= DRV_MODULE_NAME,
++	.id_table	= tg3_pci_tbl,
++	.probe		= tg3_init_one,
++	.remove		= __devexit_p(tg3_remove_one),
++	.suspend	= tg3_suspend,
++	.resume		= tg3_resume
++};
++
++static int __init tg3_init(void)
++{
++	return pci_module_init(&tg3_driver);
++}
++
++static void __exit tg3_cleanup(void)
++{
++	/* Clean up any leftover firmware.  We can't currently
++	 * do this in tg3_remove_one, because we don't know whether
++	 * any of the other devices need the firmware. */
++	tg3_release_firmware(&tg3_fw_5701_a0);
++#if TG3_TSO_SUPPORT != 0
++	tg3_release_firmware(&tg3_fw_tso5);
++	tg3_release_firmware(&tg3_fw_tso);
++#endif /* TG3_TSO_SUPPORT */
++
++	pci_unregister_driver(&tg3_driver);
++}
++
++module_init(tg3_init);
++module_exit(tg3_cleanup);

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-pci-quirks-via8233a.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-pci-quirks-via8233a.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-pci-quirks-via8233a.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,23 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Resolves problem in correctly detecting 8233A sound card
+## DP: Patch author: David Shaohua <shaohua.li at intel.com>
+## DP: Backport author: David Sterratt <david.c.sterratt at ed.ac.uk>
+## DP: Upstream status: pending (http://bugme.osdl.org/show_bug.cgi?id=3175)
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+===== drivers/pci/quirks.c 1.50 vs edited =====
+--- 1.50/drivers/pci/quirks.c	2004-08-24 08:33:40 +08:00
++++ edited/drivers/pci/quirks.c	2004-09-24 10:43:02 +08:00
+@@ -494,6 +494,7 @@ static void __devinit quirk_via_irqpic(s
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_2,	quirk_via_irqpic );
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_5,	quirk_via_irqpic );
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_6,	quirk_via_irqpic );
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8233_5,	quirk_via_irqpic );
+ 
+ 
+ /*

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi-generic_proc_info.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi-generic_proc_info.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi-generic_proc_info.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,92 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: restore generic SCSI proc_info function in drivers/scsi/scsi_proc.c
+## DP: Patch author: unknown
+## DP: Upstream status: rejected
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN kernel-source-2.6.6/drivers/scsi/scsi_proc.c kernel-source-2.6.6-1/drivers/scsi/scsi_proc.c
+--- kernel-source-2.6.6/drivers/scsi/scsi_proc.c	2004-03-11 13:55:22.000000000 +1100
++++ kernel-source-2.6.6-1/drivers/scsi/scsi_proc.c	2004-02-16 18:23:47.000000000 +1100
+@@ -42,13 +42,47 @@
+ /* Protect sht->present and sht->proc_dir */
+ static DECLARE_MUTEX(global_host_template_sem);
+ 
++/* Used if the driver currently has no own support for /proc/scsi */
++static int generic_proc_info(char *buffer, char **start, off_t offset,
++			     int count, const char *(*info)(struct Scsi_Host *),
++			     struct Scsi_Host *shost)
++{
++	int len, pos, begin = 0;
++	static const char noprocfs[] =
++		"The driver does not yet support the proc-fs\n";
++
++	if (info && shost)
++		len = sprintf(buffer, "%s\n", info(shost));
++	else
++		len = sprintf(buffer, "%s\n", noprocfs);
++
++	pos = len;
++	if (pos < offset) {
++		len = 0;
++		begin = pos;
++	}
++
++	*start = buffer + (offset - begin);
++	len -= (offset - begin);
++	if (len > count)
++		len = count;
++
++	return len;
++}
++
+ static int proc_scsi_read(char *buffer, char **start, off_t offset,
+ 			  int length, int *eof, void *data)
+ {
+ 	struct Scsi_Host *shost = data;
+ 	int n;
+ 
+-	n = shost->hostt->proc_info(shost, buffer, start, offset, length, 0);
++	if (shost->hostt->proc_info == NULL)
++		n = generic_proc_info(buffer, start, offset, length,
++				      shost->hostt->info, shost);
++	else
++		n = shost->hostt->proc_info(shost, buffer, start, offset,
++					   length, 0);
++
+ 	*eof = (n < length);
+ 
+ 	return n;
+@@ -62,6 +96,8 @@
+ 	char *page;
+ 	char *start;
+     
++	if (!shost->hostt->proc_info)
++		return -ENOSYS;
+ 	if (count > PROC_BLOCK_SIZE)
+ 		return -EOVERFLOW;
+ 
+@@ -79,9 +115,6 @@
+ 
+ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
+ {
+-	if (!sht->proc_info)
+-		return;
+-
+ 	down(&global_host_template_sem);
+ 	if (!sht->present++) {
+ 		sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
+@@ -96,9 +129,6 @@
+ 
+ void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
+ {
+-	if (!sht->proc_info)
+-		return;
+-
+ 	down(&global_host_template_sem);
+ 	if (!--sht->present && sht->proc_dir) {
+ 		remove_proc_entry(sht->proc_name, proc_scsi);

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi_changer.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi_changer.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-scsi_changer.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,1537 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: SCSI Media Changer - http://bytesex.org/patches/
+## DP: Patch author: unknown
+## DP: Upstream status: not submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN kernel-source-2.6.6/Documentation/scsi-changer.txt kernel-source-2.6.6-1/Documentation/scsi-changer.txt
+--- kernel-source-2.6.6/Documentation/scsi-changer.txt	1970-01-01 10:00:00.000000000 +1000
++++ kernel-source-2.6.6-1/Documentation/scsi-changer.txt	2004-03-17 21:24:11.000000000 +1100
+@@ -0,0 +1,184 @@
++
++README for the SCSI media changer driver
++========================================
++
++This is a driver for SCSI Medium Changer devices, which are listed
++with "Type: Medium Changer" in /proc/scsi/scsi.
++
++This is for *real* Jukeboxes.  It is *not* supported to work with
++common small CD-ROM changers, neither one-lun-per-slot SCSI changers
++nor IDE drives.
++
++Userland tools available from: http://bytesex.org/changer.html
++
++
++General Information
++-------------------
++
++First some words about how changers work: A changer has 2 (possibly
++more) SCSI ID's. One for the changer device which controls the robot,
++and one for the device which actually reads and writes the data. The
++later may be anything, a MOD, a CD-ROM, a tape or whatever. For the
++changer device this is a "don't care", he *only* shuffles around the
++media, nothing else.
++
++
++The SCSI changer model is complex, compared to - for example - IDE-CD
++changers. But it allows to handle nearly all possible cases. It knows
++4 different types of changer elements:
++
++  media transport - this one shuffles around the media, i.e. the
++                    transport arm.  Also known as "picker".
++  storage         - a slot which can hold a media.
++  import/export   - the same as above, but is accessable from outside,
++                    i.e. there the operator (you !) can use this to
++                    fill in and remove media from the changer.
++		    Sometimes named "mailslot".
++  data transfer   - this is the device which reads/writes, i.e. the
++		    CD-ROM / Tape / whatever drive.
++
++None of these is limited to one: A huge Jukebox could have slots for
++123 CD-ROM's, 5 CD-ROM readers (and therefore 6 SCSI ID's: the changer
++and each CD-ROM) and 2 transport arms. No problem to handle.
++
++
++How it is implemented
++---------------------
++
++I implemented the driver as character device driver with a NetBSD-like
++ioctl interface. Just grabbed NetBSD's header file and one of the
++other linux SCSI device drivers as starting point. The interface
++should be source code compatible with NetBSD. So if there is any
++software (anybody knows ???) which supports a BSDish changer driver,
++it should work with this driver too.
++
++Over time a few more ioctls where added, volume tag support for example
++wasn't covered by the NetBSD ioctl API.
++
++
++Current State
++-------------
++
++Support for more than one transport arm is not implemented yet (and
++nobody asked for it so far...).
++
++I test and use the driver myself with a 35 slot cdrom jukebox from
++Grundig.  I got some reports telling it works ok with tape autoloaders
++(Exabyte, HP and DEC).  Some People use this driver with amanda.  It
++works fine with small (11 slots) and a huge (4 MOs, 88 slots)
++magneto-optical Jukebox.  Probably with lots of other changers too, most
++(but not all :-) people mail me only if it does *not* work...
++
++I don't have any device lists, neither black-list nor white-list.  Thus
++it is quite useless to ask me whenever a specific device is supported or
++not.  In theory every changer device which supports the SCSI-2 media
++changer command set should work out-of-the-box with this driver.  If it
++doesn't, it is a bug.  Either within the driver or within the firmware
++of the changer device.
++
++
++Using it
++--------
++
++This is a character device with major number is 86, so use
++"mknod /dev/sch0 c 86 0" to create the special file for the driver.
++
++If the module finds the changer, it prints some messages about the
++device [ try "dmesg" if you don't see anything ] and should show up in
++/proc/devices. If not....  some changers use ID ? / LUN 0 for the
++device and ID ? / LUN 1 for the robot mechanism. But Linux does *not*
++look for LUN's other than 0 as default, becauce there are to many
++broken devices. So you can try:
++
++  1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi
++     (replace ID with the SCSI-ID of the device)
++  2) boot the kernel with "max_scsi_luns=1" on the command line
++     (append="max_scsi_luns=1" in lilo.conf should do the trick)
++
++
++Trouble?
++--------
++
++If you insmod the driver with "insmod debug=1", it will be verbose and
++prints a lot of stuff to the syslog.  Compiling the kernel with
++CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot
++because the kernel will translate the error codes into human-readable
++strings then.
++
++You can display these messages with the dmesg command (or check the
++logfiles).  If you email me some question becauce of a problem with the
++driver, please include these messages.
++
++
++Insmod options
++--------------
++
++debug=0/1
++	Enable debug messages (see above, default: 0).
++
++verbose=0/1
++	Be verbose (default: 1).
++
++init=0/1
++	Send INITIALIZE ELEMENT STATUS command to the changer
++	at insmod time (default: 1).
++
++check_busy=0/1
++	When moving media from/to data transfer elements, check
++	whenever the device is busy and refuse to move if so
++	(default: 1).
++
++timeout_init=<seconds>
++	timeout for the INITIALIZE ELEMENT STATUS command
++	(default: 3600).
++
++timeout_move=<seconds>
++	timeout for all other commands (default: 120).
++
++dt_id=<id1>,<id2>,...
++dt_lun=<lun1>,<lun2>,...
++	These two allow to specify the SCSI ID and LUN for the data
++	transfer elements.  You likely don't need this as the jukebox
++	should provide this information.  But some devices don't ...
++
++vendor_firsts=
++vendor_counts=
++vendor_labels=
++	These insmod options can be used to tell the driver that there
++	are some vendor-specific element types.  Grundig for example
++	does this.  Some jukeboxes have a printer to label fresh burned
++	CDs, which is addressed as element 0xc000 (type 5).  To tell the
++	driver about this vendor-specific element, use this:
++		$ insmod ch			\
++			vendor_firsts=0xc000	\
++			vendor_counts=1		\
++			vendor_labels=printer
++	All three insmod options accept up to four comma-separated
++	values, this way you can configure the element types 5-8.
++	You likely need the SCSI specs for the device in question to
++	find the correct values as they are not covered by the SCSI-2
++	standard.
++
++
++Credits
++-------
++
++I wrote this driver using the famous mailing-patches-around-the-world
++method.  With (more or less) help from:
++
++	Daniel Moehwald <moehwald at hdg.de>
++	Dane Jasper <dane at sonic.net>
++	R. Scott Bailey <sbailey at dsddi.eds.com>
++	Jonathan Corbet <corbet at atd.ucar.edu>
++
++Special thanks go to
++	Martin Kuehne <Martin.KUEHNE at GRUNDIG.com>
++for a old, second-hand (but full functional) cdrom jukebox which I use
++to develop/test driver and tools now.
++
++Have fun,
++
++   Gerd
++
++-- 
++Gerd Knorr <kraxel at bytesex.org>
+diff -urN kernel-source-2.6.6/drivers/scsi/Kconfig kernel-source-2.6.6-1/drivers/scsi/Kconfig
+--- kernel-source-2.6.6/drivers/scsi/Kconfig	2004-05-10 19:47:58.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/scsi/Kconfig	2004-05-10 22:21:38.000000000 +1000
+@@ -137,6 +137,24 @@
+ 
+ 	  If unsure, say N.
+ 
++config CHR_DEV_SCH
++	tristate "SCSI media changer support"
++	depends on SCSI
++	---help---
++	  This is a driver for SCSI media changers.  Most common devices are
++	  tape libraries and MOD/CDROM jukeboxes.  *Real* jukeboxes, you
++	  don't need this for those tiny 6-slot cdrom changers.  Media
++	  changers are listed as "Type: Medium Changer" in /proc/scsi/scsi.
++	  If you have such hardware and want to use it with linux, say Y
++	  here.  Check <file:Documentation/scsi-changer.txt> for details.
++	
++	  If you want to compile this as a module ( = code which can be
++	  inserted in and removed from the running kernel whenever you want),
++	  say M here and read <file:Documentation/modules.txt> and
++	  <file:Documentation/scsi.txt>. The module will be called ch.o.
++	  If unsure, say N.
++	
++
+ comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
+ 	depends on SCSI
+ 
+diff -urN kernel-source-2.6.6/drivers/scsi/Makefile kernel-source-2.6.6-1/drivers/scsi/Makefile
+--- kernel-source-2.6.6/drivers/scsi/Makefile	2004-05-10 19:47:58.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/scsi/Makefile	2004-05-10 22:21:38.000000000 +1000
+@@ -132,6 +131,7 @@
+ obj-$(CONFIG_BLK_DEV_SD)	+= sd_mod.o
+ obj-$(CONFIG_BLK_DEV_SR)	+= sr_mod.o
+ obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
++obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
+ 
+ scsi_mod-y			+= scsi.o hosts.o scsi_ioctl.o constants.o \
+ 				   scsicam.o scsi_error.o scsi_lib.o \
+diff -urN kernel-source-2.6.6/drivers/scsi/ch.c kernel-source-2.6.6-1/drivers/scsi/ch.c
+--- kernel-source-2.6.6/drivers/scsi/ch.c	1970-01-01 10:00:00.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/scsi/ch.c	2004-03-17 21:24:11.000000000 +1100
+@@ -0,0 +1,1085 @@
++/*
++ * SCSI Media Changer device driver for Linux 2.6
++ *
++ *     (c) 1996-2003 Gerd Knorr <kraxel at bytesex.org>
++ *
++ */
++
++#define VERSION "0.22"
++
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/major.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/blkdev.h>
++#include <linux/completion.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ioctl32.h>
++#include <linux/compat.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++
++#include <linux/chio.h>			/* here are all the ioctls */
++
++#define MAJOR_NR	SCSI_CHANGER_MAJOR
++
++#define CH_DT_MAX       16
++#define CH_TYPES        8
++
++#include <scsi/scsi_cmnd.h>
++#include <scsi/scsi_driver.h>
++#include <scsi/scsi_ioctl.h>
++
++#include "scsi.h"
++#include "hosts.h"
++
++MODULE_SUPPORTED_DEVICE("sch");
++MODULE_DESCRIPTION("device driver for scsi media changer devices");
++MODULE_AUTHOR("Gerd Knorr <kraxel at bytesex.org>");
++MODULE_LICENSE("GPL");
++
++static int check_busy = 1;
++MODULE_PARM(check_busy,"i");
++MODULE_PARM_DESC(check_busy, \
++    "enable/disable busy check for data transfer elements (default: on)");
++
++static int init = 1;
++MODULE_PARM(init,"i");
++MODULE_PARM_DESC(init, \
++    "initialize element status on driver load (default: on)");
++
++static int timeout_move = 300;
++MODULE_PARM(timeout_move,"i");
++MODULE_PARM_DESC(timeout_move,"timeout for move commands "
++		 "(default: 300 seconds)");
++
++static int timeout_init = 3600;
++MODULE_PARM(timeout_init,"i");
++MODULE_PARM_DESC(timeout_init,"timeout for INITIALIZE ELEMENT STATUS "
++		 "(default: 3600 seconds)");
++
++static int verbose = 1;
++MODULE_PARM(verbose,"i");
++MODULE_PARM_DESC(verbose,"be verbose (default: on)");
++
++static int debug = 0;
++MODULE_PARM(debug,"i");
++MODULE_PARM_DESC(debug,"enable/disable debug messages, also prints more "
++		 "detailed sense codes on scsi errors (default: off)");
++
++static int dt_id[CH_DT_MAX] = { [ 0 ... (CH_DT_MAX-1) ] = -1 };
++static int dt_lun[CH_DT_MAX];
++MODULE_PARM(dt_id,"1-" __MODULE_STRING(CH_DT_MAX) "i");
++MODULE_PARM(dt_lun,"1-" __MODULE_STRING(CH_DT_MAX) "i");
++
++/* tell the driver about vendor-specific slots */
++static int vendor_firsts[CH_TYPES-4];
++static int vendor_counts[CH_TYPES-4];
++static char *vendor_labels[CH_TYPES-4];
++MODULE_PARM(vendor_firsts,"1-4i");
++MODULE_PARM(vendor_counts,"1-4i");
++MODULE_PARM(vendor_labels,"1-4s");
++
++#define dprintk(fmt, arg...)    if (debug) \
++        printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg)
++#define vprintk(fmt, arg...)    if (verbose) \
++        printk(KERN_INFO "%s: " fmt, ch->name, ##arg)
++
++/* ------------------------------------------------------------------- */
++
++#define MAX_RETRIES   1
++
++static int  ch_probe(struct device *);
++static int  ch_remove(struct device *);
++static int  ch_open(struct inode * inode, struct file * filp);
++static int  ch_release(struct inode * inode, struct file * filp);
++static int  ch_ioctl(struct inode * inode, struct file * filp,
++		     unsigned int cmd, unsigned long arg);
++
++typedef struct {
++	struct list_head    list;
++	int                 minor;
++	char                name[8];
++	Scsi_Device  	    *device;
++	Scsi_Device         **dt;        /* ptrs to data transfer elements */
++	u_int               firsts[CH_TYPES];
++	u_int               counts[CH_TYPES];
++	u_int               unit_attention;
++	u_int		    voltags;
++	struct semaphore    lock;
++} scsi_changer;
++
++static LIST_HEAD(ch_devlist);
++static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED;
++static int ch_devcount;
++
++struct scsi_driver ch_template =
++{
++	.owner     	= THIS_MODULE,
++	.gendrv     	= {
++		.name	= "ch",
++		.probe  = ch_probe,
++		.remove = ch_remove,
++	},
++};
++
++static struct file_operations changer_fops =
++{
++	.owner      = THIS_MODULE,
++	.open       = ch_open,
++	.release    = ch_release,
++	.ioctl      = ch_ioctl,
++};
++
++static struct {
++	unsigned char  sense;
++	unsigned char  asc;
++	unsigned char  ascq;
++	int	       errno;
++} err[] = {
++/* Just filled in what looks right. Hav'nt checked any standard paper for
++   these errno assignments, so they may be wrong... */
++	{
++		.sense  = ILLEGAL_REQUEST,
++		.asc    = 0x21,
++		.ascq   = 0x01,
++		.errno  = EBADSLT, /* Invalid element address */
++	},{
++		.sense  = ILLEGAL_REQUEST,
++		.asc    = 0x28,
++		.ascq   = 0x01,
++		.errno  = EBADE,   /* Import or export element accessed */
++	},{
++		.sense  = ILLEGAL_REQUEST,
++		.asc    = 0x3B,
++		.ascq   = 0x0D,
++		.errno  = EXFULL,  /* Medium destination element full */
++	},{
++		.sense  = ILLEGAL_REQUEST,
++		.asc    = 0x3B,
++		.ascq   = 0x0E,
++		.errno  = EBADE,   /* Medium source element empty */
++	},{
++		.sense  = ILLEGAL_REQUEST,
++		.asc    = 0x20,
++		.ascq   = 0x00,
++		.errno  = EBADRQC, /* Invalid command operation code */
++	},{
++	        /* end of list */
++	}
++};
++
++/* ------------------------------------------------------------------- */
++/* ioctl32 compat                                                      */
++
++#ifdef CONFIG_COMPAT
++
++struct changer_element_status32 {
++	int		ces_type;
++	compat_uptr_t	ces_data;
++};
++#define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)
++
++static struct {
++	unsigned int cmd;
++	int          reg;
++} ioctl32_cmds[] = {
++	{ .cmd = CHIOMOVE      },
++	{ .cmd = CHIOEXCHANGE  },
++	{ .cmd = CHIOPOSITION  },
++	{ .cmd = CHIOGPICKER   },
++	{ .cmd = CHIOSPICKER   },
++	{ .cmd = CHIOGPARAMS   },
++	{ .cmd = CHIOGELEM     },
++	{ .cmd = CHIOINITELEM  },
++	{ .cmd = CHIOSVOLTAG   },
++	{ .cmd = CHIOGVPARAMS  },
++	{ .cmd = CHIOGSTATUS32 },
++};
++
++static int ioctl32_register(void)
++{
++	unsigned int i;
++	int err;
++
++	for (i = 0; i < ARRAY_SIZE(ioctl32_cmds); i++) {
++		err = register_ioctl32_conversion(ioctl32_cmds[i].cmd,NULL);
++		if (err >= 0)
++			ioctl32_cmds[i].reg++;
++	}
++	return 0;
++}
++static int ioctl32_unregister(void)
++{
++	unsigned int i;
++	
++	for (i = 0; i < ARRAY_SIZE(ioctl32_cmds); i++) {
++		if (ioctl32_cmds[i].reg) {
++			unregister_ioctl32_conversion(ioctl32_cmds[i].cmd);
++			ioctl32_cmds[i].reg--;
++		}
++	}
++	return 0;
++}
++
++#else
++
++static int ioctl32_register(void)   { return 0; }
++static int ioctl32_unregister(void) { return 0; }
++
++#endif
++
++/* ------------------------------------------------------------------- */
++
++static int ch_find_errno(unsigned char *sense_buffer)
++{
++	int i,errno = 0;
++
++	/* Check to see if additional sense information is available */
++	if (sense_buffer[7]  > 5 &&
++	    sense_buffer[12] != 0) {
++		for (i = 0; err[i].errno != 0; i++) {
++			if (err[i].sense == sense_buffer[ 2] &&
++			    err[i].asc   == sense_buffer[12] &&
++			    err[i].ascq  == sense_buffer[13]) {
++				errno = -err[i].errno;
++				break;
++			}
++		}
++	}
++	if (errno == 0)
++		errno = -EIO;
++	return errno;
++}
++
++static void
++ch_request_done (Scsi_Cmnd * sc)
++{
++	sc->request->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
++        if (sc->request->waiting != NULL)
++		complete(sc->request->waiting);
++}
++
++static int
++ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
++	   void *buffer, unsigned buflength)
++{
++	int errno, retries = 0, timeout;
++	DECLARE_COMPLETION(wait);
++	Scsi_Request *sr;
++	
++	sr = scsi_allocate_request(ch->device, GFP_ATOMIC);
++	if (NULL == sr)
++		return -ENOMEM;
++
++ retry:
++	errno = 0;
++	if (debug) {
++		dprintk("command: %s","");
++		print_command(cmd);
++	}
++
++	sr->sr_request->waiting = &wait;
++	timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
++		? timeout_init : timeout_move;
++	scsi_do_req(sr, cmd, buffer, buflength, ch_request_done,
++		    timeout * HZ, MAX_RETRIES);
++	wait_for_completion(&wait);
++	sr->sr_request->waiting = NULL;
++
++	dprintk("result: 0x%x\n",sr->sr_result);
++	if (driver_byte(sr->sr_result) != 0) {
++		if (debug)
++			print_req_sense(ch->name, sr);
++		errno = ch_find_errno(sr->sr_sense_buffer);
++
++		switch(sr->sr_sense_buffer[2] & 0xf) {
++		case UNIT_ATTENTION:
++			ch->unit_attention = 1;
++			if (retries++ < 3)
++				goto retry;
++			break;
++		}
++	}
++	scsi_release_request(sr);
++	return errno;
++}
++
++/* ------------------------------------------------------------------------ */
++
++static int
++ch_elem_to_typecode(scsi_changer *ch, u_int elem)
++{
++	int i;
++	
++	for (i = 0; i < CH_TYPES; i++) {
++		if (elem >= ch->firsts[i]  &&
++		    elem <  ch->firsts[i] +
++	            ch->counts[i])
++			return i+1;
++	}
++	return 0;
++}
++
++static int
++ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
++{
++	u_char  cmd[12];
++	u_char  *buffer;
++	int     result;
++	
++	buffer = kmalloc(512, GFP_KERNEL);
++	if(!buffer)
++		return -ENOMEM;
++	
++ retry:
++	memset(cmd,0,sizeof(cmd));
++	cmd[0] = READ_ELEMENT_STATUS;
++	cmd[1] = (ch->device->lun << 5) | 
++		(ch->voltags ? 0x10 : 0) |
++		ch_elem_to_typecode(ch,elem);
++	cmd[2] = (elem >> 8) & 0xff;
++	cmd[3] = elem        & 0xff;
++	cmd[5] = 1;
++	cmd[9] = 255;
++	if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256))) {
++		if (((buffer[16] << 8) | buffer[17]) != elem) {
++			dprintk("asked for element 0x%02x, got 0x%02x\n",
++				elem,(buffer[16] << 8) | buffer[17]);
++			kfree(buffer);
++			return -EIO;
++		}
++		memcpy(data,buffer+16,16);
++	} else {
++		if (ch->voltags) {
++			ch->voltags = 0;
++			vprintk("device has no volume tag support%s\n","");
++			goto retry;
++		}
++		dprintk("READ ELEMENT STATUS for element 0x%x failed\n",elem);
++	}
++	kfree(buffer);
++	return result;
++}
++
++static int 
++ch_init_elem(scsi_changer *ch)
++{
++	int err;
++	u_char cmd[6];
++
++	vprintk("INITIALIZE ELEMENT STATUS, may take some time ...%s\n","");
++	memset(cmd,0,sizeof(cmd));
++	cmd[0] = INITIALIZE_ELEMENT_STATUS;
++	cmd[1] = ch->device->lun << 5;
++	err = ch_do_scsi(ch, cmd, NULL, 0);
++	vprintk("... finished%s\n","");
++	return err;
++}
++
++static int
++ch_readconfig(scsi_changer *ch)
++{
++	u_char  cmd[10], data[16];
++	u_char  *buffer;
++	int     result,id,lun,i;
++	u_int   elem;
++	
++	buffer = kmalloc(512, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++	memset(buffer,0,512);
++	
++	memset(cmd,0,sizeof(cmd));
++	cmd[0] = MODE_SENSE;
++	cmd[1] = ch->device->lun << 5;
++	cmd[2] = 0x1d;
++	cmd[4] = 255;
++	result = ch_do_scsi(ch, cmd, buffer, 255);
++	if (0 != result) {
++		cmd[1] |= (1<<3);
++		result  = ch_do_scsi(ch, cmd, buffer, 255);
++	}
++	if (0 == result) {
++		ch->firsts[CHET_MT] =
++			(buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7];
++		ch->counts[CHET_MT] =
++			(buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9];
++		ch->firsts[CHET_ST] =
++			(buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11];
++		ch->counts[CHET_ST] =
++			(buffer[buffer[3]+12] << 8) | buffer[buffer[3]+13];
++		ch->firsts[CHET_IE] =
++			(buffer[buffer[3]+14] << 8) | buffer[buffer[3]+15];
++		ch->counts[CHET_IE] =
++			(buffer[buffer[3]+16] << 8) | buffer[buffer[3]+17];
++		ch->firsts[CHET_DT] =
++			(buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19];
++		ch->counts[CHET_DT] =
++			(buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21];
++		vprintk("type #1 (mt): 0x%x+%d [medium transport]\n",
++			ch->firsts[CHET_MT],
++			ch->counts[CHET_MT]);
++		vprintk("type #2 (st): 0x%x+%d [storage]\n",
++			ch->firsts[CHET_ST],
++			ch->counts[CHET_ST]);
++		vprintk("type #3 (ie): 0x%x+%d [import/export]\n",
++			ch->firsts[CHET_IE],
++			ch->counts[CHET_IE]);
++		vprintk("type #4 (dt): 0x%x+%d [data transfer]\n",
++			ch->firsts[CHET_DT],
++			ch->counts[CHET_DT]);
++	} else {
++		vprintk("reading element address assigment page failed!%s\n",
++			"");
++	}
++	
++	/* vendor specific element types */
++	for (i = 0; i < 4; i++) {
++		if (0 == vendor_counts[i])
++			continue;
++		if (NULL == vendor_labels[i])
++			continue;
++		ch->firsts[CHET_V1+i] = vendor_firsts[i];
++		ch->counts[CHET_V1+i] = vendor_counts[i];
++		vprintk("type #%d (v%d): 0x%x+%d [%s, vendor specific]\n",
++			i+5,i+1,vendor_firsts[i],vendor_counts[i],
++			vendor_labels[i]);
++	}
++
++	/* look up the devices of the data transfer elements */
++	ch->dt =
++		kmalloc(ch->counts[CHET_DT]*sizeof(Scsi_Device*),
++			GFP_ATOMIC);
++	for (elem = 0; elem < ch->counts[CHET_DT]; elem++) {
++		id  = -1;
++		lun = 0;
++		if (-1 != dt_id[elem]) {
++			id  = dt_id[elem];
++			lun = dt_lun[elem];
++			vprintk("dt 0x%x: [insmod option] ",
++				elem+ch->firsts[CHET_DT]);
++		} else if (0 != ch_read_element_status
++			   (ch,elem+ch->firsts[CHET_DT],data)) {
++			vprintk("dt 0x%x: READ ELEMENT STATUS failed\n",
++				elem+ch->firsts[CHET_DT]);
++		} else {
++			vprintk("dt 0x%x: ",elem+ch->firsts[CHET_DT]);
++			if (data[6] & 0x80) {
++				if (verbose)
++					printk("not this SCSI bus\n");
++				ch->dt[elem] = NULL;
++			} else if (0 == (data[6] & 0x30)) {
++				if (verbose)
++					printk("ID/LUN unknown\n");
++				ch->dt[elem] = NULL;
++			} else {
++				id  = ch->device->id;
++				lun = 0;
++				if (data[6] & 0x20) id  = data[7];
++				if (data[6] & 0x10) lun = data[6] & 7;
++			}
++		}
++		if (-1 != id) {
++			if (verbose)
++				printk("ID %i, LUN %i, ",id,lun);
++			ch->dt[elem] =
++				scsi_device_lookup(ch->device->host,
++						   ch->device->channel,
++						   id,lun);
++			if (!ch->dt[elem]) {
++				/* should not happen */
++				if (verbose)
++					printk("Huh? device not found!\n");
++			} else {
++				if (verbose)
++					printk("name: %8.8s %16.16s %4.4s\n",
++					       ch->dt[elem]->vendor,
++					       ch->dt[elem]->model,
++					       ch->dt[elem]->rev);
++			}
++		}
++	}
++	ch->voltags = 1;
++	kfree(buffer);
++
++	return 0;
++}
++
++/* ------------------------------------------------------------------------ */
++
++static int
++ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
++{
++	u_char  cmd[10];
++	
++	dprintk("position: 0x%x\n",elem);
++	if (0 == trans)
++		trans = ch->firsts[CHET_MT];
++	memset(cmd,0,sizeof(cmd));
++	cmd[0]  = POSITION_TO_ELEMENT;
++	cmd[1]  = ch->device->lun << 5;
++	cmd[2]  = (trans >> 8) & 0xff;
++	cmd[3]  =  trans       & 0xff;
++	cmd[4]  = (elem  >> 8) & 0xff;
++	cmd[5]  =  elem        & 0xff;
++	cmd[8]  = rotate ? 1 : 0;
++	return ch_do_scsi(ch, cmd, NULL,0);
++}
++
++static int
++ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
++{
++	u_char  cmd[12];
++	
++	dprintk("move: 0x%x => 0x%x\n",src,dest);
++	if (0 == trans)
++		trans = ch->firsts[CHET_MT];
++	memset(cmd,0,sizeof(cmd));
++	cmd[0]  = MOVE_MEDIUM;
++	cmd[1]  = ch->device->lun << 5;
++	cmd[2]  = (trans >> 8) & 0xff;
++	cmd[3]  =  trans       & 0xff;
++	cmd[4]  = (src   >> 8) & 0xff;
++	cmd[5]  =  src         & 0xff;
++	cmd[6]  = (dest  >> 8) & 0xff;
++	cmd[7]  =  dest        & 0xff;
++	cmd[10] = rotate ? 1 : 0;
++	return ch_do_scsi(ch, cmd, NULL,0);
++}
++
++static int
++ch_exchange(scsi_changer *ch, u_int trans, u_int src,
++	    u_int dest1, u_int dest2, int rotate1, int rotate2)
++{
++	u_char  cmd[12];
++	
++	dprintk("exchange: 0x%x => 0x%x => 0x%x\n",
++		src,dest1,dest2);
++	if (0 == trans)
++		trans = ch->firsts[CHET_MT];
++	memset(cmd,0,sizeof(cmd));
++	cmd[0]  = EXCHANGE_MEDIUM;
++	cmd[1]  = ch->device->lun << 5;
++	cmd[2]  = (trans >> 8) & 0xff;
++	cmd[3]  =  trans       & 0xff;
++	cmd[4]  = (src   >> 8) & 0xff;
++	cmd[5]  =  src         & 0xff;
++	cmd[6]  = (dest1 >> 8) & 0xff;
++	cmd[7]  =  dest1       & 0xff;
++	cmd[8]  = (dest2 >> 8) & 0xff;
++	cmd[9]  =  dest2       & 0xff;
++	cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
++	
++	return ch_do_scsi(ch, cmd, NULL,0);
++}
++
++static void
++ch_check_voltag(char *tag)
++{
++	int i;
++
++	for (i = 0; i < 32; i++) {
++		/* restrict to ascii */
++		if (tag[i] >= 0x7f || tag[i] < 0x20)
++			tag[i] = ' ';
++		/* don't allow search wildcards */
++		if (tag[i] == '?' ||
++		    tag[i] == '*')
++			tag[i] = ' ';
++	}
++}
++
++static int
++ch_set_voltag(scsi_changer *ch, u_int elem,
++	      int alternate, int clear, u_char *tag)
++{
++	u_char  cmd[12];
++	u_char  *buffer;
++	int result;
++
++	buffer = kmalloc(512, GFP_KERNEL);
++	if (!buffer)
++		return -ENOMEM;
++	memset(buffer,0,512);
++
++	dprintk("%s %s voltag: 0x%x => \"%s\"\n",
++		clear     ? "clear"     : "set",
++		alternate ? "alternate" : "primary",
++		elem, tag);
++	memset(cmd,0,sizeof(cmd));
++	cmd[0]  = SEND_VOLUME_TAG;
++	cmd[1] = (ch->device->lun << 5) | 
++		ch_elem_to_typecode(ch,elem);
++	cmd[2] = (elem >> 8) & 0xff;
++	cmd[3] = elem        & 0xff;
++	cmd[5] = clear
++		? (alternate ? 0x0d : 0x0c)
++		: (alternate ? 0x0b : 0x0a);
++	
++	cmd[9] = 255;
++
++	memcpy(buffer,tag,32);
++	ch_check_voltag(buffer);
++
++	result = ch_do_scsi(ch, cmd, buffer, 256);
++	kfree(buffer);
++	return result;
++}
++
++static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest)
++{
++	int retval = 0;
++	u_char data[16];
++	unsigned int i;
++	
++	down(&ch->lock);
++	for (i = 0; i < ch->counts[type]; i++) {
++		if (0 != ch_read_element_status
++		    (ch, ch->firsts[type]+i,data)) {
++			retval = -EIO;
++			break;
++		}
++		put_user(data[2], dest+i);
++		if (data[2] & CESTATUS_EXCEPT)
++			vprintk("element 0x%x: asc=0x%x, ascq=0x%x\n",
++				ch->firsts[type]+i,
++				(int)data[4],(int)data[5]);
++		retval = ch_read_element_status
++			(ch, ch->firsts[type]+i,data);
++		if (0 != retval)
++			break;
++	}
++	up(&ch->lock);
++	return retval;
++}
++
++/* ------------------------------------------------------------------------ */
++
++static int
++ch_release(struct inode *inode, struct file *file)
++{
++	scsi_changer *ch = file->private_data;
++
++	scsi_device_put(ch->device);
++	file->private_data = NULL;
++	return 0;
++}
++
++static int
++ch_open(struct inode *inode, struct file *file)
++{
++	struct list_head *item;
++	scsi_changer *tmp, *ch;
++	int minor = iminor(inode);
++
++	spin_lock(&ch_devlist_lock);
++	ch = NULL;
++	list_for_each(item,&ch_devlist) {
++		tmp = list_entry(item, scsi_changer, list);
++		if (tmp->minor == minor)
++			ch = tmp;
++	}
++	if (NULL == ch || scsi_device_get(ch->device)) {
++		spin_unlock(&ch_devlist_lock);
++		return -ENXIO;
++	}
++	spin_unlock(&ch_devlist_lock);
++
++	file->private_data = ch;
++	return 0;
++}
++
++static int
++ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
++{
++	if (type >= CH_TYPES  ||  unit >= ch->counts[type])
++		return -1;
++	return 0;
++}
++
++/* for data transfer elements: check if they are busy */
++static int
++ch_is_busy(scsi_changer *ch, int type, int unit)
++{
++#if 0 /* hmm, access_count is gone :-/ */
++	if (!check_busy)
++		return 0;
++	if (type != CHET_DT)
++		return 0;
++	if (!ch->dt[unit])
++		return 0;
++	return atomic_read(&ch->dt[unit]->access_count);
++#else
++	return 0;
++#endif
++}
++
++static int ch_ioctl(struct inode * inode, struct file * file,
++		    unsigned int cmd, unsigned long arg)
++{
++	scsi_changer *ch = file->private_data;
++	int retval;
++	
++	switch (cmd) {
++	case CHIOGPARAMS:
++	{
++		struct changer_params params;
++		
++		params.cp_curpicker = 0;
++		params.cp_npickers  = ch->counts[CHET_MT];
++		params.cp_nslots    = ch->counts[CHET_ST];
++		params.cp_nportals  = ch->counts[CHET_IE];
++		params.cp_ndrives   = ch->counts[CHET_DT];
++		
++		if (copy_to_user((void *) arg, &params, sizeof(params)))
++			return -EFAULT;
++		return 0;
++	}
++	case CHIOGVPARAMS:
++	{
++		struct changer_vendor_params vparams;
++
++		memset(&vparams,0,sizeof(vparams));
++		if (ch->counts[CHET_V1]) {
++			vparams.cvp_n1  = ch->counts[CHET_V1];
++			strncpy(vparams.cvp_label1,vendor_labels[0],16);
++		}
++		if (ch->counts[CHET_V2]) {
++			vparams.cvp_n2  = ch->counts[CHET_V2];
++			strncpy(vparams.cvp_label2,vendor_labels[1],16);
++		}
++		if (ch->counts[CHET_V3]) {
++			vparams.cvp_n3  = ch->counts[CHET_V3];
++			strncpy(vparams.cvp_label3,vendor_labels[2],16);
++		}
++		if (ch->counts[CHET_V4]) {
++			vparams.cvp_n4  = ch->counts[CHET_V4];
++			strncpy(vparams.cvp_label4,vendor_labels[3],16);
++		}
++		if (copy_to_user((void *) arg, &vparams, sizeof(vparams)))
++			return -EFAULT;
++		return 0;
++	}
++	
++	case CHIOPOSITION:
++	{
++		struct changer_position pos;
++		
++		if (copy_from_user(&pos, (void*)arg, sizeof (pos)))
++			return -EFAULT;
++
++		if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
++			dprintk("CHIOPOSITION: invalid parameter%s\n","");
++			return -EBADSLT;
++		}
++		down(&ch->lock);
++		retval = ch_position(ch,0,
++				     ch->firsts[pos.cp_type] + pos.cp_unit,
++				     pos.cp_flags & CP_INVERT);
++		up(&ch->lock);
++		return retval;
++	}
++	
++	case CHIOMOVE:
++	{
++		struct changer_move mv;
++
++		if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
++			return -EFAULT;
++
++		if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
++		    0 != ch_checkrange(ch, mv.cm_totype,   mv.cm_tounit  )) {
++			dprintk("CHIOMOVE: invalid parameter%s\n","");
++			return -EBADSLT;
++		}
++		if (ch_is_busy(ch, mv.cm_fromtype, mv.cm_fromunit) ||
++		    ch_is_busy(ch, mv.cm_totype,   mv.cm_tounit  ))
++			return -EBUSY;
++		
++		down(&ch->lock);
++		retval = ch_move(ch,0,
++				 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
++				 ch->firsts[mv.cm_totype]   + mv.cm_tounit,
++				 mv.cm_flags & CM_INVERT);
++		up(&ch->lock);
++		return retval;
++	}
++
++	case CHIOEXCHANGE:
++	{
++		struct changer_exchange mv;
++		
++		if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
++			return -EFAULT;
++
++		if (0 != ch_checkrange(ch, mv.ce_srctype,  mv.ce_srcunit ) ||
++		    0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) ||
++		    0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) {
++			dprintk("CHIOEXCHANGE: invalid parameter%s\n","");
++			return -EBADSLT;
++		}
++		if (0 != ch_is_busy(ch, mv.ce_srctype,  mv.ce_srcunit ) ||
++		    0 != ch_is_busy(ch, mv.ce_fdsttype, mv.ce_fdstunit) ||
++		    0 != ch_is_busy(ch, mv.ce_sdsttype, mv.ce_sdstunit))
++			return -EBUSY;
++		
++		down(&ch->lock);
++		retval = ch_exchange
++			(ch,0,
++			 ch->firsts[mv.ce_srctype]  + mv.ce_srcunit,
++			 ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
++			 ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
++			 mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
++		up(&ch->lock);
++		return retval;
++	}
++
++	case CHIOGSTATUS:
++	{
++		struct changer_element_status ces;
++		
++		if (copy_from_user(&ces, (void*)arg, sizeof (ces)))
++			return -EFAULT;
++		if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
++			return -EINVAL;
++
++		return ch_gstatus(ch, ces.ces_type, ces.ces_data);
++	}
++
++#ifdef CONFIG_COMPAT
++	case CHIOGSTATUS32:
++	{
++		struct changer_element_status32 ces32;
++		unsigned char *data;
++		
++		if (copy_from_user(&ces32, (void*)arg, sizeof (ces32)))
++			return -EFAULT;
++		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
++			return -EINVAL;
++
++		data = compat_ptr(ces32.ces_data);
++		return ch_gstatus(ch, ces32.ces_type, data);
++	}
++#endif
++    
++	case CHIOGELEM:
++	{
++		struct changer_get_element cge;
++		u_char  cmd[12];
++		u_char  *buffer;
++		unsigned int elem;
++		int     result,i;
++		
++		if (copy_from_user(&cge, (void*)arg, sizeof (cge)))
++			return -EFAULT;
++
++		if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
++			return -EINVAL;
++		elem = ch->firsts[cge.cge_type] + cge.cge_unit;
++		
++		buffer = kmalloc(512, GFP_KERNEL);
++		if (!buffer)
++			return -ENOMEM;
++		down(&ch->lock);
++		
++	voltag_retry:
++		memset(cmd,0,sizeof(cmd));
++		cmd[0] = READ_ELEMENT_STATUS;
++		cmd[1] = (ch->device->lun << 5) |
++			(ch->voltags ? 0x10 : 0) |
++			ch_elem_to_typecode(ch,elem);
++		cmd[2] = (elem >> 8) & 0xff;
++		cmd[3] = elem        & 0xff;
++		cmd[5] = 1;
++		cmd[9] = 255;
++		
++		if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256))) {
++			cge.cge_status = buffer[18];
++			cge.cge_flags = 0;
++			if (buffer[18] & CESTATUS_EXCEPT) {
++				/* FIXME: fill cge_errno */
++			}
++			if (buffer[25] & 0x80) {
++				cge.cge_flags |= CGE_SRC;
++				if (buffer[25] & 0x40)
++					cge.cge_flags |= CGE_INVERT;
++				elem = (buffer[26]<<8) | buffer[27];
++				for (i = 0; i < 4; i++) {
++					if (elem >= ch->firsts[i] &&
++					    elem <  ch->firsts[i] + ch->counts[i]) {
++						cge.cge_srctype = i;
++						cge.cge_srcunit = elem-ch->firsts[i];
++					}
++				}
++			}
++			if ((buffer[22] & 0x30) == 0x30) {
++				cge.cge_flags |= CGE_IDLUN;
++				cge.cge_id  = buffer[23];
++				cge.cge_lun = buffer[22] & 7;
++			}
++			if (buffer[9] & 0x80) {
++				cge.cge_flags |= CGE_PVOLTAG;
++				memcpy(cge.cge_pvoltag,buffer+28,36);
++			}
++			if (buffer[9] & 0x40) {
++				cge.cge_flags |= CGE_AVOLTAG;
++				memcpy(cge.cge_avoltag,buffer+64,36);
++			}
++		} else if (ch->voltags) {
++			ch->voltags = 0;
++			vprintk("device has no volume tag support%s\n","");
++			goto voltag_retry;
++		}
++		kfree(buffer);
++		up(&ch->lock);
++		
++		if (copy_to_user((void*)arg, &cge, sizeof (cge)))
++			return -EFAULT;
++		return result;
++	}
++
++	case CHIOINITELEM:
++	{
++		down(&ch->lock);
++		retval = ch_init_elem(ch);
++		up(&ch->lock);
++		return retval;
++	}
++		
++	case CHIOSVOLTAG:
++	{
++		struct changer_set_voltag csv;
++		int elem;
++
++		if (copy_from_user(&csv, (void*)arg, sizeof(csv)))
++			return -EFAULT;
++
++		if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
++			dprintk("CHIOSVOLTAG: invalid parameter%s\n","");
++			return -EBADSLT;
++		}
++		elem = ch->firsts[csv.csv_type] + csv.csv_unit;
++		down(&ch->lock);
++		retval = ch_set_voltag(ch, elem,
++				       csv.csv_flags & CSV_AVOLTAG,
++				       csv.csv_flags & CSV_CLEARTAG,
++				       csv.csv_voltag);
++		up(&ch->lock);
++		return retval;
++	}
++
++	default:
++		return scsi_ioctl(ch->device, cmd, (void*)arg);
++
++	}
++}
++
++/* ------------------------------------------------------------------------ */
++
++static int ch_probe(struct device *dev)
++{
++	struct scsi_device *sd = to_scsi_device(dev);
++	scsi_changer *ch;
++	
++	if (sd->type != TYPE_MEDIUM_CHANGER)
++		return -ENODEV;
++    
++	ch = kmalloc(sizeof(*ch), GFP_KERNEL);
++	if (NULL == ch)
++		return -ENOMEM;
++
++	memset(ch,0,sizeof(*ch));
++	ch->minor = ch_devcount;
++	sprintf(ch->name,"ch%d",ch->minor);
++	init_MUTEX(&ch->lock);
++	ch->device = sd;
++	ch_readconfig(ch);
++	if (init)
++		ch_init_elem(ch);
++
++	devfs_mk_cdev(MKDEV(MAJOR_NR,ch->minor),
++		      S_IFCHR | S_IRUGO | S_IWUGO, ch->name);
++
++	printk(KERN_INFO "Attached scsi changer %s "
++	       "at scsi%d, channel %d, id %d, lun %d\n", 
++	       ch->name, sd->host->host_no, sd->channel, sd->id, sd->lun);
++	
++	spin_lock(&ch_devlist_lock);
++	list_add_tail(&ch->list,&ch_devlist);
++	ch_devcount++;
++	spin_unlock(&ch_devlist_lock);
++	return 0;
++}
++
++static int ch_remove(struct device *dev)
++{
++	struct scsi_device *sd = to_scsi_device(dev);
++	struct list_head *item;
++	scsi_changer *tmp, *ch;
++
++	spin_lock(&ch_devlist_lock);
++	ch = NULL;
++	list_for_each(item,&ch_devlist) {
++		tmp = list_entry(item, scsi_changer, list);
++		if (tmp->device == sd)
++			ch = tmp;
++	}
++	BUG_ON(NULL == ch);
++	list_del(&ch->list);
++	spin_unlock(&ch_devlist_lock);
++
++	devfs_remove(ch->name);
++	kfree(ch->dt);
++	kfree(ch);
++	ch_devcount--;
++	return 0;
++}
++
++static int __init init_ch_module(void)
++{
++	int rc;
++	
++	printk(KERN_INFO "SCSI Media Changer driver v" VERSION
++	       " for Linux " UTS_RELEASE "\n");
++	rc = register_chrdev(MAJOR_NR,"ch",&changer_fops);
++	if (rc < 0) {
++		printk("Unable to get major %d for SCSI-Changer\n",
++		       MAJOR_NR);
++		return rc;
++	}
++	ioctl32_register();
++	rc = scsi_register_driver(&ch_template.gendrv);
++	if (rc < 0)
++		goto fail1;
++	return 0;
++
++ fail1:
++	ioctl32_unregister();
++	unregister_chrdev(MAJOR_NR, "ch");
++	return rc;
++}
++
++static void __exit exit_ch_module(void) 
++{
++	scsi_unregister_driver(&ch_template.gendrv);
++	unregister_chrdev(MAJOR_NR, "ch");
++	ioctl32_unregister();
++}
++
++module_init(init_ch_module);
++module_exit(exit_ch_module);
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff -urN kernel-source-2.6.6/include/linux/chio.h kernel-source-2.6.6-1/include/linux/chio.h
+--- kernel-source-2.6.6/include/linux/chio.h	1970-01-01 10:00:00.000000000 +1000
++++ kernel-source-2.6.6-1/include/linux/chio.h	2004-03-17 21:24:11.000000000 +1100
+@@ -0,0 +1,168 @@
++/*
++ * ioctl interface for the scsi media changer driver
++ */
++
++/* changer element types */
++#define CHET_MT   0	/* media transport element (robot) */
++#define CHET_ST   1	/* storage element (media slots) */
++#define CHET_IE   2	/* import/export element */
++#define CHET_DT   3	/* data transfer element (tape/cdrom/whatever) */
++#define CHET_V1   4	/* vendor specific #1 */
++#define CHET_V2   5	/* vendor specific #2 */
++#define CHET_V3   6	/* vendor specific #3 */
++#define CHET_V4   7	/* vendor specific #4 */
++
++
++/*
++ * CHIOGPARAMS
++ *    query changer properties
++ *
++ * CHIOVGPARAMS
++ *    query vendor-specific element types
++ *
++ *    accessing elements works by specifing type and unit of the element.
++ *    for eample, storage elements are addressed with type = CHET_ST and
++ *    unit = 0 .. cp_nslots-1
++ *
++ */
++struct changer_params {
++	int cp_curpicker;  /* current transport element */
++	int cp_npickers;   /* number of transport elements      (CHET_MT) */
++	int cp_nslots;     /* number of storage elements        (CHET_ST) */
++	int cp_nportals;   /* number of import/export elements  (CHET_IE) */
++	int cp_ndrives;    /* number of data transfer elements  (CHET_DT) */
++};
++struct changer_vendor_params {
++	int  cvp_n1;       /* number of vendor specific elems   (CHET_V1) */
++	char cvp_label1[16];
++	int  cvp_n2;       /* number of vendor specific elems   (CHET_V2) */
++	char cvp_label2[16];
++	int  cvp_n3;       /* number of vendor specific elems   (CHET_V3) */
++	char cvp_label3[16];
++	int  cvp_n4;       /* number of vendor specific elems   (CHET_V4) */
++	char cvp_label4[16];
++	int  reserved[8];
++};
++
++
++/*
++ * CHIOMOVE
++ *    move a medium from one element to another
++ */
++struct changer_move {
++	int cm_fromtype;	/* type/unit of source element */
++	int cm_fromunit;	
++	int cm_totype;	/* type/unit of destination element */
++	int cm_tounit;
++	int cm_flags;
++};
++#define CM_INVERT   1   /* flag: rotate media (for double-sided like MOD) */
++
++
++/*
++ * CHIOEXCHANGE
++ *    move one medium from element #1 to element #2,
++ *    and another one from element #2 to element #3.
++ *    element #1 and #3 are allowed to be identical.
++ */
++struct changer_exchange {
++	int ce_srctype;	    /* type/unit of element #1 */
++	int ce_srcunit;
++	int ce_fdsttype;    /* type/unit of element #2 */
++	int ce_fdstunit;
++	int ce_sdsttype;    /* type/unit of element #3 */
++	int ce_sdstunit;
++	int ce_flags;
++};
++#define CE_INVERT1   1
++#define CE_INVERT2   2
++
++
++/*
++ * CHIOPOSITION
++ *    move the transport element (robot arm) to a specific element.
++ */
++struct changer_position {
++	int cp_type;
++	int cp_unit;
++	int cp_flags;
++};
++#define CP_INVERT   1
++
++
++/*
++ * CHIOGSTATUS
++ *    get element status for all elements of a specific type
++ */
++struct changer_element_status {
++	int             ces_type;
++	unsigned char   *ces_data;
++};
++#define CESTATUS_FULL     0x01 /* full */
++#define CESTATUS_IMPEXP   0x02	/* media was imported (inserted by sysop) */
++#define CESTATUS_EXCEPT   0x04	/* error condition */
++#define CESTATUS_ACCESS   0x08	/* access allowed */
++#define CESTATUS_EXENAB   0x10	/* element can export media */
++#define CESTATUS_INENAB   0x20	/* element can import media */
++
++
++/*
++ * CHIOGELEM
++ *    get more detailed status informtion for a single element
++ */
++struct changer_get_element {
++	int	cge_type;	 /* type/unit */
++	int	cge_unit;
++	int	cge_status;      /* status */
++	int     cge_errno;       /* errno */
++	int     cge_srctype;     /* source element of the last move/exchange */
++	int     cge_srcunit;
++	int     cge_id;          /* scsi id  (for data transfer elements) */
++	int     cge_lun;         /* scsi lun (for data transfer elements) */
++	char    cge_pvoltag[36]; /* primary volume tag */
++	char    cge_avoltag[36]; /* alternate volume tag */
++	int     cge_flags;
++};
++/* flags */
++#define CGE_ERRNO     0x01       /* errno available       */
++#define CGE_INVERT    0x02       /* media inverted        */
++#define CGE_SRC       0x04       /* media src available   */
++#define CGE_IDLUN     0x08       /* ID+LUN available      */
++#define CGE_PVOLTAG   0x10       /* primary volume tag available */
++#define CGE_AVOLTAG   0x20       /* alternate volume tag available */
++
++
++/*
++ * CHIOSVOLTAG
++ *    set volume tag
++ */
++struct changer_set_voltag {
++	int	csv_type;	 /* type/unit */
++	int	csv_unit;
++	char    csv_voltag[36];  /* volume tag */
++	int     csv_flags;
++};
++#define CSV_PVOLTAG   0x01       /* primary volume tag */
++#define CSV_AVOLTAG   0x02       /* alternate volume tag */
++#define CSV_CLEARTAG  0x04       /* clear volume tag */
++
++/* ioctls */
++#define CHIOMOVE       _IOW('c', 1,struct changer_move)
++#define CHIOEXCHANGE   _IOW('c', 2,struct changer_exchange)
++#define CHIOPOSITION   _IOW('c', 3,struct changer_position)
++#define CHIOGPICKER    _IOR('c', 4,int)                        /* not impl. */
++#define CHIOSPICKER    _IOW('c', 5,int)                        /* not impl. */
++#define CHIOGPARAMS    _IOR('c', 6,struct changer_params)
++#define CHIOGSTATUS    _IOW('c', 8,struct changer_element_status)
++#define CHIOGELEM      _IOW('c',16,struct changer_get_element)
++#define CHIOINITELEM   _IO('c',17)
++#define CHIOSVOLTAG    _IOW('c',18,struct changer_set_voltag)
++#define CHIOGVPARAMS   _IOR('c',19,struct changer_vendor_params)
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * Local variables:
++ * c-basic-offset: 8
++ * End:
++ */
+diff -urN kernel-source-2.6.6/include/linux/major.h kernel-source-2.6.6-1/include/linux/major.h
+--- kernel-source-2.6.6/include/linux/major.h	2004-04-05 19:49:42.000000000 +1000
++++ kernel-source-2.6.6-1/include/linux/major.h	2004-04-05 20:54:51.000000000 +1000
+@@ -101,6 +101,7 @@
+ #define I2O_MAJOR		80	/* 80->87 */
+ 
+ #define SHMIQ_MAJOR		85   /* Linux/mips, SGI /dev/shmiq */
++#define SCSI_CHANGER_MAJOR      86
+ 
+ #define IDE6_MAJOR		88
+ #define IDE7_MAJOR		89
+diff -urN kernel-source-2.6.6/include/scsi/scsi.h kernel-source-2.6.6-1/include/scsi/scsi.h
+--- kernel-source-2.6.6/include/scsi/scsi.h	2004-04-05 19:49:43.000000000 +1000
++++ kernel-source-2.6.6-1/include/scsi/scsi.h	2004-04-05 20:54:52.000000000 +1000
+@@ -41,6 +41,7 @@
+ #define FORMAT_UNIT           0x04
+ #define READ_BLOCK_LIMITS     0x05
+ #define REASSIGN_BLOCKS       0x07
++#define INITIALIZE_ELEMENT_STATUS 0x07
+ #define READ_6                0x08
+ #define WRITE_6               0x0a
+ #define SEEK_6                0x0b
+@@ -65,6 +66,7 @@
+ #define READ_10               0x28
+ #define WRITE_10              0x2a
+ #define SEEK_10               0x2b
++#define POSITION_TO_ELEMENT   0x2b
+ #define WRITE_VERIFY          0x2e
+ #define VERIFY                0x2f
+ #define SEARCH_HIGH           0x30
+@@ -97,6 +99,7 @@
+ #define PERSISTENT_RESERVE_OUT 0x5f
+ #define REPORT_LUNS           0xa0
+ #define MOVE_MEDIUM           0xa5
++#define EXCHANGE_MEDIUM       0xa6
+ #define READ_12               0xa8
+ #define WRITE_12              0xaa
+ #define WRITE_VERIFY_12       0xae

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-8250-ioremap-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-8250-ioremap-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-8250-ioremap-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,50 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Don't ioremap if MMIO uart has a mapbase, but no membase
+## DP: Patch author: Alex Williamson <alex.williamson at hp.com>
+## DP: Upstream status: submitted; but not accepted as code is being rewritten
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+
+  The iounmap/ioremap path in serial8250_release/request_port is
+terribly unbalanced.  The UPF_IOREMAP flag is used to determine if a
+port gets ioremap'd, but plays no part in whether it gets iounmap'd.
+It's easy to see how an MMIO serial port can be passed through
+uart_set_info and end up with an unmapped membase.  The results is a
+non-functional UART or worse.  I've tried to generate some discussion on
+the proper fix for this, but I haven't succeeded.  I propose the patch
+below as a safe compromise.  An MMIO uart w/ a mapbase, but no membase
+doesn't seem viable to me.  Thanks,
+
+	Alex
+
+-- 
+Signed-off-by: Alex Williamson <alex.williamson at hp.com>
+
+===== drivers/serial/8250.c 1.77 vs edited =====
+--- 1.77/drivers/serial/8250.c	2004-10-25 06:05:26 -06:00
++++ edited/drivers/serial/8250.c	2004-10-28 13:18:01 -06:00
+@@ -1858,7 +1858,11 @@
+ 	/*
+ 	 * If we have a mapbase, then request that as well.
+ 	 */
+-	if (ret == 0 && up->port.flags & UPF_IOREMAP) {
++	if (ret == 0 && ((up->port.flags & UPF_IOREMAP) ||
++	                 (up->port.iotype == UPIO_MEM &&
++	                  up->port.mapbase &&
++	                  !up->port.membase))) {
++
+ 		int size = res->end - res->start + 1;
+ 
+ 		up->port.membase = ioremap(up->port.mapbase, size);
+
+
+
+To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
+the body of a message to majordomo at vger.kernel.org
+More majordomo info at  http://vger.kernel.org/majordomo-info.html
+Please read the FAQ at  http://www.tux.org/lkml/

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-sn_console-up-buildfix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-sn_console-up-buildfix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-serial-sn_console-up-buildfix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,49 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Build fix for sn_console driver
+## DP: Patch author: Jesse Barnes <jbarnes at sgi.com>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/08/24 11:31:37-07:00 jbarnes at engr.sgi.com 
+#   [PATCH] fix sn_console for CONFIG_SMP=n
+#   
+#   I found that sn_console was missing an include and a fix if CONFIG_SMP=n.  
+#   This patch fixes up the two small problems I found.
+#   
+#   Signed-off-by: Jesse Barnes <jbarnes at sgi.com>
+#   Signed-off-by: Andrew Morton <akpm at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# drivers/serial/sn_console.c
+#   2004/08/24 02:08:49-07:00 jbarnes at engr.sgi.com +3 -0
+#   fix sn_console for CONFIG_SMP=n
+# 
+diff -Nru a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
+--- a/drivers/serial/sn_console.c	2004-11-05 17:05:12 -08:00
++++ b/drivers/serial/sn_console.c	2004-11-05 17:05:12 -08:00
+@@ -50,6 +50,7 @@
+ #include <linux/miscdevice.h>
+ #include <linux/serial_core.h>
+ 
++#include <asm/io.h>
+ #include <asm/sn/simulator.h>
+ #include <asm/sn/sn2/sn_private.h>
+ #include <asm/sn/sn_sal.h>
+@@ -1086,7 +1087,9 @@
+ 			spin_unlock_irqrestore(&port->sc_port.lock, flags);
+ 
+ 			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
++#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+ 		}
++#endif
+ 	}
+ 	else {
+ 		/* Not yet registered with serial core - simple case */

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-1.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-1.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-1.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,127 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: USB Storage: ignore bogus residue values
+## DP: Patch author: Matthew Dharm
+## DP: Upstream status: included
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# origin: mdharm-usb (BitKeeper)
+# cset: 1.1939.1.51 (2.6) key=415b022fporD8taxknvj32O-ZXJNNw
+# inclusion: upstream
+# descrition: [PATCH] USB Storage: ignore bogus residue values
+# revision date: Mon, 08 Nov 2004 12:56:12 +0900
+#
+# rset: ChangeSet|1.1939.1.50..1.1939.1.51
+# rset: drivers/usb/storage/transport.c|1.108..1.109
+# rset: drivers/usb/storage/usb.h|1.45..1.46
+# rset: drivers/usb/storage/unusual_devs.h|1.118..1.119
+#
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/09/29 11:42:55-07:00 mdharm-usb at one-eyed-alien.net 
+#   [PATCH] USB Storage: ignore bogus residue values
+#   
+#   This patch allows usb-storage to ignore the reported residue values when
+#   required by some devices.  A few devices are included... I know more are
+#   waiting to be merged into unusual_devs.h
+#   
+#   In case anyone is curious... yes, these are broken devices.
+#   
+#   Signed-off-by: Alan Stern <stern at rowland.harvard.edu>
+#   Signed-off-by: Matthew Dharm <mdharm-usb at one-eyed-alien.net>
+#   Signed-off-by: Greg Kroah-Hartman <greg at kroah.com>
+# 
+# drivers/usb/storage/usb.h
+#   2004/09/26 05:59:06-07:00 mdharm-usb at one-eyed-alien.net +1 -0
+#   USB Storage: ignore bogus residue values
+# 
+# drivers/usb/storage/unusual_devs.h
+#   2004/09/26 05:59:06-07:00 mdharm-usb at one-eyed-alien.net +22 -1
+#   USB Storage: ignore bogus residue values
+# 
+# drivers/usb/storage/transport.c
+#   2004/09/26 05:59:06-07:00 mdharm-usb at one-eyed-alien.net +7 -2
+#   USB Storage: ignore bogus residue values
+# 
+diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+--- a/drivers/usb/storage/transport.c	2004-11-08 12:56:12 +09:00
++++ b/drivers/usb/storage/transport.c	2004-11-08 12:56:12 +09:00
+@@ -1055,8 +1055,13 @@
+ 
+ 	/* try to compute the actual residue, based on how much data
+ 	 * was really transferred and what the device tells us */
+-	residue = min(residue, transfer_length);
+-	srb->resid = max(srb->resid, (int) residue);
++	if (residue) {
++		if (!(us->flags & US_FL_IGNORE_RESIDUE) ||
++				srb->sc_data_direction == DMA_TO_DEVICE) {
++			residue = min(residue, transfer_length);
++			srb->resid = max(srb->resid, (int) residue);
++		}
++	}
+ 
+ 	/* based on the status code, we report good or bad */
+ 	switch (bcs->Status) {
+diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+--- a/drivers/usb/storage/unusual_devs.h	2004-11-08 12:56:12 +09:00
++++ b/drivers/usb/storage/unusual_devs.h	2004-11-08 12:56:12 +09:00
+@@ -268,6 +268,13 @@
+ 		US_SC_8070, US_PR_BULK, NULL,
+ 		US_FL_FIX_INQUIRY ),
+ 
++/* Reported by Iacopo Spalletti <avvisi at spalletti.it> */
++UNUSUAL_DEV(  0x052b, 0x1807, 0x0100, 0x0100,
++		"Tekom Technologies, Inc",
++		"300_CAMERA",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE ),
++
+ /* This entry is needed because the device reports Sub=ff */
+ UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450, 
+ 		"Sony",
+@@ -811,7 +818,14 @@
+ 		"Solid state disk",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_FIX_INQUIRY ),
+-		
++
++/* Reported by Rastislav Stanik <rs_kernel at yahoo.com> */
++UNUSUAL_DEV(  0x0ea0, 0x6828, 0x0110, 0x0110,
++		"USB",
++		"Flash Disk",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE ),
++
+ /* Reported by Kevin Cernekee <kpc-usbdev at gelato.uiuc.edu>
+  * Tested on hardware version 1.10.
+  * Entry is needed only for the initializer function override.
+@@ -832,6 +846,13 @@
+ 		"EasyDisk Portable Device",
+ 		US_SC_DEVICE, US_PR_DEVICE, NULL,
+ 		US_FL_MODE_XLATE ),
++
++/* Reported by Kotrla Vitezslav <kotrla at ceb.cz> */
++UNUSUAL_DEV(  0x1370, 0x6828, 0x0110, 0x0110,
++		"SWISSBIT",
++		"Black Silver",
++		US_SC_DEVICE, US_PR_DEVICE, NULL,
++		US_FL_IGNORE_RESIDUE ),
+ 
+ #ifdef CONFIG_USB_STORAGE_SDDR55
+ UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999, 
+diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+--- a/drivers/usb/storage/usb.h	2004-11-08 12:56:12 +09:00
++++ b/drivers/usb/storage/usb.h	2004-11-08 12:56:12 +09:00
+@@ -73,6 +73,7 @@
+ #define US_FL_SCM_MULT_TARG   0x00000020 /* supports multiple targets	    */
+ #define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs faking   */
+ #define US_FL_FIX_CAPACITY    0x00000080 /* READ CAPACITY response too big  */
++#define US_FL_IGNORE_RESIDUE  0x00000100 /* reported residue is wrong	    */
+ 
+ /* Dynamic flag definitions: used in set_bit() etc. */
+ #define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-2.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-2.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-usb-storage-transport-2.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,84 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: USB Storage: revert GetMaxLUN strictness
+## DP: Patch author: Matthew Dharm
+## DP: Upstream status: included
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# origin: mdharm-usb (BitKeeper)
+# cset: 1.1939.1.52 (2.6) key=415b02497EnNJinuYxLfmOEWKsUNdw
+# inclusion: upstream
+# descrition: [PATCH] USB Storage: revert GetMaxLUN strictness
+# revision date: Mon, 08 Nov 2004 12:56:29 +0900
+#
+# rset: ChangeSet|1.1939.1.51..1.1939.1.52
+# rset: drivers/usb/storage/transport.c|1.109..1.110
+#
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/09/29 11:43:21-07:00 mdharm-usb at one-eyed-alien.net 
+#   [PATCH] USB Storage: revert GetMaxLUN strictness
+#   
+#   This is patch as384.  It reverts some of our sanity checks on the GetMaxLUN
+#   part of the Bulk-only protocol.  Apparently, this is one area where vendors
+#   can't even get close to correct.  So, in the face of any sort of error, we
+#   assume a single LUN.
+#   
+#   We also include some comments so we don't make this mistake again.
+#   
+#   
+#   Signed-off-by: Alan Stern <stern at rowland.harvard.edu>
+#   Signed-off-by: Matthew Dharm <mdharm-usb at one-eyed-alien.net>
+#   Signed-off-by: Greg Kroah-Hartman <greg at kroah.com>
+# 
+# drivers/usb/storage/transport.c
+#   2004/09/26 06:06:12-07:00 mdharm-usb at one-eyed-alien.net +9 -7
+#   USB Storage: revert GetMaxLUN strictness
+# 
+diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+--- a/drivers/usb/storage/transport.c	2004-11-08 12:56:29 +09:00
++++ b/drivers/usb/storage/transport.c	2004-11-08 12:56:29 +09:00
+@@ -911,7 +911,6 @@
+ 	int result;
+ 
+ 	/* issue the command */
+-	us->iobuf[0] = 0;
+ 	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
+ 				 US_BULK_GET_MAX_LUN, 
+ 				 USB_DIR_IN | USB_TYPE_CLASS | 
+@@ -922,7 +921,7 @@
+ 		  result, us->iobuf[0]);
+ 
+ 	/* if we have a successful request, return the result */
+-	if (result >= 0)
++	if (result > 0)
+ 		return us->iobuf[0];
+ 
+ 	/* 
+@@ -934,13 +933,16 @@
+ 	if (result == -EPIPE) {
+ 		usb_stor_clear_halt(us, us->recv_bulk_pipe);
+ 		usb_stor_clear_halt(us, us->send_bulk_pipe);
+-		/* return the default -- no LUNs */
+-		return 0;
+ 	}
+ 
+-	/* An answer or a STALL are the only valid responses.  If we get
+-	 * something else, return an indication of error */
+-	return -1;
++	/*
++	 * Some devices don't like GetMaxLUN.  They may STALL the control
++	 * pipe, they may return a zero-length result, they may do nothing at
++	 * all and timeout, or they may fail in even more bizarrely creative
++	 * ways.  In these cases the best approach is to use the default
++	 * value: only one LUN.
++	 */
++	return 0;
+ }
+ 
+ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-video-fm2fb-build-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-video-fm2fb-build-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/drivers-video-fm2fb-build-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,51 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description:  FrameMaster II build fix
+## DP: Patch author: Geert Uytterhoeven <geert at linux-m68k.org>
+## DP: Upstream status: backport 2.6.9-bk4
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -Nru a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
+--- a/drivers/video/fm2fb.c	2004-10-21 06:21:06 -07:00
++++ b/drivers/video/fm2fb.c	2004-10-21 06:21:07 -07:00
+@@ -292,18 +292,7 @@
+ 	return 0;
+ }
+ 
+-int __init fm2fb_setup(char *options);
+-
+-int __init fm2fb_init(void)
+-{
+-	char *option = NULL;
+-
+-	if (fb_get_options("fm2fb", &option))
+-		return -ENODEV;
+-	fm2fb_setup(option);
+-	return zorro_register_driver(&fm2fb_driver);
+-}
+-
++int __init fm2fb_setup(char *options)
+ {
+ 	char *this_opt;
+ 
+@@ -317,6 +306,16 @@
+ 			fm2fb_mode = FM2FB_MODE_NTSC;
+ 	}
+ 	return 0;
++}
++
++int __init fm2fb_init(void)
++{
++	char *option = NULL;
++
++	if (fb_get_options("fm2fb", &option))
++		return -ENODEV;
++	fm2fb_setup(option);
++	return zorro_register_driver(&fm2fb_driver);
+ }
+ 
+ module_init(fm2fb_init);

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes-the-return.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes-the-return.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes-the-return.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,53 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: [PATCH] binfmt_elf: handle p_filesz == 0 on PT_INTERP section
+## DP: Patch author: Jakub Jelinek <jakub at redhat.com>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/16 17:38:30-08:00 chrisw at osdl.org 
+#   [PATCH] binfmt_elf: handle p_filesz == 0 on PT_INTERP section
+#   
+#   Jakub Jelinek points out that current fix has an underflow problem
+#   if elf_ppnt->p_filesz == 0.  Fix that up, and also stop overwriting
+#   interpreter buffer, simply check that it's NULL-terminated.
+#   
+#   From: Jakub Jelinek <jakub at redhat.com>
+#   Signed-off-by: Chris Wright <chrisw at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# fs/binfmt_elf.c
+#   2004/11/16 11:01:21-08:00 chrisw at osdl.org +5 -2
+#   binfmt_elf: handle p_filesz == 0 on PT_INTERP section
+# 
+diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+--- a/fs/binfmt_elf.c	2004-11-21 11:32:30 -08:00
++++ b/fs/binfmt_elf.c	2004-11-21 11:32:30 -08:00
+@@ -576,7 +576,8 @@
+ 			 */
+ 
+ 			retval = -ENOMEM;
+-			if (elf_ppnt->p_filesz > PATH_MAX)
++			if (elf_ppnt->p_filesz > PATH_MAX || 
++			    elf_ppnt->p_filesz == 0)
+ 				goto out_free_file;
+ 			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
+ 							   GFP_KERNEL);
+@@ -592,7 +593,9 @@
+ 				goto out_free_interp;
+ 			}
+ 			/* make sure path is NULL terminated */
+-			elf_interpreter[elf_ppnt->p_filesz - 1] = '\0';
++			retval = -EINVAL;
++			if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
++				goto out_free_interp;
+ 
+ 			/* If the program interpreter is one of these two,
+ 			 * then assume an iBCS2 image. Otherwise assume

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/elf-loader-fixes.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,101 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Correct handle various failures in ELF loader
+## DP: Patch author: Chris Wright <chrisw at osdl.org>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/10 10:33:00-08:00 chrisw at osdl.org 
+#   [PATCH] binfmt_elf: handle partial reads gracefully
+#   
+#   Make sure kernel reads full size of elf data.  Error out if mmap fails
+#   when mapping any sections of the executable.  Make sure interpreter
+#   string is NULL terminated. 
+#   
+#   Signed-off-by: Chris Wright <chrisw at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# fs/binfmt_elf.c
+#   2004/11/10 09:45:38-08:00 chrisw at osdl.org +24 -7
+#   binfmt_elf: handle partial reads gracefully
+# 
+diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+--- a/fs/binfmt_elf.c	2004-11-11 09:33:22 -08:00
++++ b/fs/binfmt_elf.c	2004-11-11 09:33:22 -08:00
+@@ -335,9 +335,12 @@
+ 		goto out;
+ 
+ 	retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size);
+-	error = retval;
+-	if (retval < 0)
++	error = -EIO;
++	if (retval != size) {
++		if (retval < 0)
++			error = retval;	
+ 		goto out_close;
++	}
+ 
+ 	eppnt = elf_phdata;
+ 	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
+@@ -532,8 +535,11 @@
+ 		goto out;
+ 
+ 	retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size);
+-	if (retval < 0)
++	if (retval != size) {
++		if (retval >= 0)
++			retval = -EIO;
+ 		goto out_free_ph;
++	}
+ 
+ 	files = current->files;		/* Refcounted so ok */
+ 	retval = unshare_files();
+@@ -580,8 +586,14 @@
+ 			retval = kernel_read(bprm->file, elf_ppnt->p_offset,
+ 					   elf_interpreter,
+ 					   elf_ppnt->p_filesz);
+-			if (retval < 0)
++			if (retval != elf_ppnt->p_filesz) {
++				if (retval >= 0)
++					retval = -EIO;
+ 				goto out_free_interp;
++			}
++			/* make sure path is NULL terminated */
++			elf_interpreter[elf_ppnt->p_filesz - 1] = '\0';
++
+ 			/* If the program interpreter is one of these two,
+ 			 * then assume an iBCS2 image. Otherwise assume
+ 			 * a native linux image.
+@@ -616,8 +628,11 @@
+ 			if (IS_ERR(interpreter))
+ 				goto out_free_interp;
+ 			retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
+-			if (retval < 0)
++			if (retval != BINPRM_BUF_SIZE) {
++				if (retval >= 0)
++					retval = -EIO;
+ 				goto out_free_dentry;
++			}
+ 
+ 			/* Get the exec headers */
+ 			loc->interp_ex = *((struct exec *) bprm->buf);
+@@ -776,8 +791,10 @@
+ 		}
+ 
+ 		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
+-		if (BAD_ADDR(error))
+-			continue;
++		if (BAD_ADDR(error)) {
++			send_sig(SIGKILL, current, 0);
++			goto out_free_dentry;
++		}
+ 
+ 		if (!load_addr_set) {
+ 			load_addr_set = 1;

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-asfs.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-asfs.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-asfs.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,5026 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: add support for the Amiga SmartFilesystem (asfs), 1.0beta7
+## DP: Patch author: Marek Szyprowski
+## DP: Upstream status: not submitted
+## DP: Reference: http://home.elka.pw.edu.pl/~mszyprow/programy/asfs/
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN linux-2.6.3/Documentation/filesystems/00-INDEX linux-2.6.3-asfs-1.0b7/Documentation/filesystems/00-INDEX
+--- linux-2.6.3/Documentation/filesystems/00-INDEX	2004-03-22 17:34:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/Documentation/filesystems/00-INDEX	2004-03-22 17:34:00.000000000 +0100
+@@ -6,6 +6,8 @@
+ 	- info and mount options for the Acorn Advanced Disc Filing System.
+ affs.txt
+ 	- info and mount options for the Amiga Fast File System.
++asfs.txt
++	- info and mount options for the Amiga Smart File System.
+ bfs.txt
+ 	- info for the SCO UnixWare Boot Filesystem (BFS).
+ cifs.txt
+diff -urN linux-2.6.3/Documentation/filesystems/asfs.txt linux-2.6.3-asfs-1.0b7/Documentation/filesystems/asfs.txt
+--- linux-2.6.3/Documentation/filesystems/asfs.txt	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/Documentation/filesystems/asfs.txt	2004-06-17 00:47:17.000000000 +0200
+@@ -0,0 +1,150 @@
++
++Amiga SmartFileSystem, Linux implementation
++===========================================
++
++ASFS is a Amiga Smart FileSystem driver for Linux. It supports reading
++files and directories. From version 1.0 there is also an experimental 
++(almost full) write support. Experimental means that it hasn't been 
++tested enough yet, so use it with care. Symbolic links (in AmigaOS
++called soft links) are also supported read/write. Read notes below 
++about symlinks support.
++
++
++Unsupported features of Amiga SFS
++================================
++
++ASFS currently does not support safe-delete feature of Amiga SFS 
++filesystem. It simply deletes files instead of moving them to 
++".recycled" directory. It also doesn't remove files from ".recycled" 
++directory, when there is no space left on drive. 
++
++If there is no space left, you need to manually remove files from 
++".recycled" directory. Also if you want to delete a file in a safe 
++way, you need to move it to ".recycled" directory by hand.
++
++Because of all of above, the amount of free space on disk does not 
++include space used by all files from ".recycled" directory.
++
++
++Limitations
++===========
++
++There is no Amiga protection bits into Linux permission bits tranlation
++and vice versa. If you need this feature, mail me.
++
++ASFS will always keep some amount of blocks free. This means that you 
++cannot fill the drive completely. It is because Amiga SFS uses some 
++special methods of writing data (called safe write), which needs some
++additional free space.
++
++File systems with unfinished transactions (this happens when system crashed
++during writing data to disk on AmigaOS/MorphOS) will be mounted read-only
++to protect data. The only way to fix such filesystem is to mount it under
++AmigaOS or MorphOS.
++
++Do not try to mount and write to filesystem with errors. Bad things will
++happen.
++
++
++Mount options for the ASFS
++==========================
++
++setuid=uid	
++		This sets the owner of all files and directories in the file
++		system to uid.
++
++setgid=gid	
++		Same as above, but for gid.
++
++mode=mode	
++		Sets the mode flags to the given (octal) value. Directories 
++		will get an x permission if the corresponding r bit is set.
++		The default mode is 0644, which means that everybody are allowed 
++		to read files, but only root can write to them.
++		(for directories this means also that search bits are set).
++
++prefix=path	
++		Path will be prefixed to every absolute path name of symbolic 
++		links on an ASFS/AFFS partition. Default = "/". (See below.)
++
++volume=name
++		When symbolic links with an absolute path are created
++		on an ASFS/AFFS partition, name will be prepended as the
++		volume name. Default = "" (empty string). (See below.)
++
++lowercasevol
++		Translate all volume names in symlinks to lower case.
++		Disabled by default. (See below.)
++
++Symbolic links
++==============
++
++Although the Amiga and Linux file systems resemble each other, there
++are some, not always subtle, differences. One of them becomes apparent
++with symbolic links. While Linux has a file system with exactly one
++root directory, the Amiga has a separate root directory for each
++file system (for example, partition, floppy disk, ...). With the Amiga,
++these entities are called "volumes". They have symbolic names which
++can be used to access them. Thus, symbolic links can point to a
++different volume. ASFS turns the volume name into a directory name
++and prepends the prefix path (see prefix option) to it. When option
++"lowercasevol" is set, it also translates volume names to lower case.
++If the volume name is the same as a name given in "volume" option,
++it will be ignored and an absolute path will be created.
++
++Example:
++You mount all your Amiga partitions under /amiga/<volume> (where
++<volume> is the name of the volume), and you give options
++`prefix="/amiga/",volume="Linux",lowercasevol' when mounting all your 
++ASFS partitions. (They might be "User", "WB" and "Graphics", the mount 
++points /amiga/user, /amiga/wb and /amiga/graphics). 
++
++A symbolic link referring to "USER:sc/include/dos/dos.h" will be 
++translated to "/amiga/user/sc/include/dos/dos.h".
++A symbolic link referring to "Linux:etc/fstab" will be translated to
++"/etc/fstab".
++If you create a symlink referring to "/amiga/graphics/data/pict.jpg",
++it will be saved as "graphics:data/pict.jpg".
++If you create a symlink referring to "/boot/System.map", it will be 
++saved as "Linux:boot/System.map".
++
++
++Other information
++=================
++
++Supported block sizes are: 512, 1024, 2048 and 4096 bytes. Larger blocks
++speed up almost everything at the expense of wasted disk space. The speed
++gain above 4K seems not really worth the price, so you don't lose too
++much here, either.
++
++This file system has been tested on Motorola PPC and 68k, as well as 
++Intel x86 systems. I don't know, if it works on other Linux systems.
++
++This filesystem is in BETA STAGE. This means that driver MIGHT corrupt
++or damage data on your disk. Remember! YOU USE IT ON YOUR OWN RISK! 
++
++I made almost all I could to minimalize this risk. On my systems several 
++gigabytes has been succesfully copied from and to SFS disks. I would also 
++appreciate any infomation if this filesystem works on your system or not. 
++See next paragraph for my email.
++
++Some parts of this documentation has been adapted from AFFS driver docs.
++
++
++Author, contact and copyright infos
++===================================
++
++ASFS has been written by Marek 'March' Szyprowski <marek at amiga.pl>.
++Mail me if you have any suggestions or found a bug.
++
++Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek at amiga.pl>
++
++Thanks to Marcin Kurek (Morgoth/Dreamolers-CAPS) for help and parts 
++of original amiga version of SmartFilesystem source code. 
++
++SmartFilesystem is copyrighted (C) 2003,2004 by: John Hendrikx, 
++Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
++
++The ASFS driver is realased under the terms of of the GNU General 
++Public License. See source code for more details.
++
+diff -urN linux-2.6.3/fs/asfs/adminspace.c linux-2.6.3-asfs-1.0b7/fs/asfs/adminspace.c
+--- linux-2.6.3/fs/asfs/adminspace.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/adminspace.c	2004-06-13 21:03:49.000000000 +0200
+@@ -0,0 +1,446 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *
++ * This file contains some parts of the original amiga version of 
++ * SmartFilesystem source code.
++ *
++ * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
++ * Ralph Schmidt, Emmanuel Lesueur, David Gerber, and Marcin Kurek
++ * 
++ * Adapted and modified by Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include "asfs_fs.h"
++#include "bitfuncs.h"
++
++#include <asm/byteorder.h>
++
++#ifdef CONFIG_ASFS_RW
++
++static int setfreeblocks(struct super_block *sb, u32 freeblocks)
++{
++	struct buffer_head *bh;
++	if ((bh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
++		struct fsRootInfo *ri = (struct fsRootInfo *) ((u8 *) bh->b_data + sb->s_blocksize - sizeof(struct fsRootInfo));
++		ASFS_SB(sb)->freeblocks = freeblocks;
++		ri->freeblocks = cpu_to_be32(freeblocks);
++		asfs_bstore(sb, bh);
++		asfs_brelse(bh);
++		return 0;
++	}
++	return -EIO;
++}
++
++static inline int enoughspace(struct super_block *sb, u32 blocks)
++{
++	if (ASFS_SB(sb)->freeblocks - ASFS_ALWAYSFREE < blocks)
++		return FALSE;
++
++	return TRUE;
++}
++
++	/* Determines the amount of free blocks starting from block /block/.
++	   If there are no blocks found or if there was an error -1 is returned,
++	   otherwise this function will count the number of free blocks until
++	   an allocated block is encountered or until maxneeded has been
++	   exceeded. */
++
++static int availablespace(struct super_block *sb, u32 block, u32 maxneeded)
++{
++	struct buffer_head *bh = NULL;
++	struct fsBitmap *b;
++	u32 longs = ASFS_SB(sb)->blocks_inbitmap >> 5;
++	u32 maxbitmapblock = ASFS_SB(sb)->bitmapbase + ASFS_SB(sb)->blocks_bitmap;
++	int blocksfound = 0;
++	u32 bitstart;
++	int bitend;
++	u32 nextblock = ASFS_SB(sb)->bitmapbase + block / ASFS_SB(sb)->blocks_inbitmap;
++
++	bitstart = block % ASFS_SB(sb)->blocks_inbitmap;
++
++	while (nextblock < maxbitmapblock && (bh = asfs_breadcheck(sb, nextblock++, ASFS_BITMAP_ID))) {
++		b = (void *) bh->b_data;
++
++		if ((bitend = bmffz(b->bitmap, longs, bitstart)) >= 0) {
++			blocksfound += bitend - bitstart;
++			asfs_brelse(bh);
++			return blocksfound;
++		}
++		blocksfound += ASFS_SB(sb)->blocks_inbitmap - bitstart;
++		if (blocksfound >= maxneeded) {
++			asfs_brelse(bh);
++			return blocksfound;
++		}
++		bitstart = 0;
++		asfs_brelse(bh);
++	}
++
++	if (bh == NULL)
++		return (-1);
++
++	return (blocksfound);
++}
++
++int asfs_findspace(struct super_block *sb, u32 maxneeded, u32 start, u32 end, u32 * returned_block, u32 * returned_blocks)
++{
++	struct buffer_head *bh;
++	u32 longs = ASFS_SB(sb)->blocks_inbitmap >> 5;
++	u32 space = 0;
++	u32 block;
++	u32 bitmapblock = ASFS_SB(sb)->bitmapbase + start / ASFS_SB(sb)->blocks_inbitmap;
++	u32 breakpoint;
++	int bitstart, bitend;
++	int reads;
++
++	if (enoughspace(sb, maxneeded) == FALSE) {
++		*returned_block = 0;
++		*returned_blocks = 0;
++		return -ENOSPC;
++	}
++
++	if (start >= ASFS_SB(sb)->totalblocks)
++		start -= ASFS_SB(sb)->totalblocks;
++
++	if (end == 0)
++		end = ASFS_SB(sb)->totalblocks;
++
++	reads = ((end - 1) / ASFS_SB(sb)->blocks_inbitmap) + 1 - start / ASFS_SB(sb)->blocks_inbitmap;
++
++	if (start >= end)
++		reads += (ASFS_SB(sb)->totalblocks - 1) / ASFS_SB(sb)->blocks_inbitmap + 1;
++
++	breakpoint = (start < end ? end : ASFS_SB(sb)->totalblocks);
++
++	*returned_block = 0;
++	*returned_blocks = 0;
++
++	bitend = start % ASFS_SB(sb)->blocks_inbitmap;
++	block = start - bitend;
++
++	while ((bh = asfs_breadcheck(sb, bitmapblock++, ASFS_BITMAP_ID))) {
++		struct fsBitmap *b = (void *) bh->b_data;
++		u32 localbreakpoint = breakpoint - block;
++
++		if (localbreakpoint > ASFS_SB(sb)->blocks_inbitmap)
++			localbreakpoint = ASFS_SB(sb)->blocks_inbitmap;
++
++		/* At this point space contains the amount of free blocks at
++		   the end of the previous bitmap block.  If there are no
++		   free blocks at the start of this bitmap block, space will
++		   be set to zero, since in that case the space isn't adjacent. */
++
++		while ((bitstart = bmffo(b->bitmap, longs, bitend)) < ASFS_SB(sb)->blocks_inbitmap) {
++			/* found the start of an empty space, now find out how large it is */
++
++			if (bitstart >= localbreakpoint)
++				break;
++
++			if (bitstart != 0)
++				space = 0;
++
++			bitend = bmffz(b->bitmap, longs, bitstart);
++
++			if (bitend > localbreakpoint)
++				bitend = localbreakpoint;
++
++			space += bitend - bitstart;
++
++			if (*returned_blocks < space) {
++				*returned_block = block + bitend - space;
++				if (space >= maxneeded) {
++					*returned_blocks = maxneeded;
++					asfs_brelse(bh);
++					return 0;
++				}
++				*returned_blocks = space;
++			}
++
++			if (bitend >= localbreakpoint)
++				break;
++		}
++
++		if (--reads == 0)
++			break;
++
++		/* no (more) empty spaces found in this block */
++
++		if (bitend != ASFS_SB(sb)->blocks_inbitmap)
++			space = 0;
++
++		bitend = 0;
++		block += ASFS_SB(sb)->blocks_inbitmap;
++
++		if (block >= ASFS_SB(sb)->totalblocks) {
++			block = 0;
++			space = 0;
++			breakpoint = end;
++			bitmapblock = ASFS_SB(sb)->bitmapbase;
++		}
++		asfs_brelse(bh);
++	}
++
++	if (bh == NULL)
++		return -EIO;
++
++	asfs_brelse(bh);
++
++	if (*returned_blocks == 0)
++		return -ENOSPC;
++	else
++		return 0;
++}
++
++int asfs_markspace(struct super_block *sb, u32 block, u32 blocks)
++{
++	int errorcode;
++
++	asfs_debug("markspace: Marking %d blocks from block %d\n", blocks, block);
++
++	if ((availablespace(sb, block, blocks)) < blocks) {
++		printk("ASFS: Attempted to mark %d blocks from block %d, but some of them were already full!\n", blocks, block);
++		return -EIO;
++	}
++
++	if ((errorcode = setfreeblocks(sb, ASFS_SB(sb)->freeblocks - blocks)) == 0) {
++		struct buffer_head *bh;
++		u32 skipblocks = block / ASFS_SB(sb)->blocks_inbitmap;
++		u32 longs = (sb->s_blocksize - sizeof(struct fsBitmap)) >> 2;
++		u32 bitmapblock;
++
++		block -= skipblocks * ASFS_SB(sb)->blocks_inbitmap;
++		bitmapblock = ASFS_SB(sb)->bitmapbase + skipblocks;
++
++		while (blocks > 0) {
++			if ((bh = asfs_breadcheck(sb, bitmapblock++, ASFS_BITMAP_ID))) {
++				struct fsBitmap *b = (void *) bh->b_data;
++
++				blocks -= bmclr(b->bitmap, longs, block, blocks);
++				block = 0;
++
++				asfs_bstore(sb, bh);
++				asfs_brelse(bh);
++			} else
++				return -EIO;
++		}
++	}
++
++	return (errorcode);
++}
++
++	/* This function checks the bitmap and tries to locate at least /blocksneeded/
++	   adjacent unused blocks.  If found it sets returned_block to the start block
++	   and returns no error.  If not found, ERROR_DISK_IS_FULL is returned and
++	   returned_block is set to zero.  Any other errors are returned as well. */
++
++static inline int internalfindspace(struct super_block *sb, u32 blocksneeded, u32 startblock, u32 endblock, u32 * returned_block)
++{
++	u32 blocks;
++	int errorcode;
++
++	if ((errorcode = asfs_findspace(sb, blocksneeded, startblock, endblock, returned_block, &blocks)) == 0)
++		if (blocks != blocksneeded)
++			return -ENOSPC;
++
++	return errorcode;
++}
++
++static int findandmarkspace(struct super_block *sb, u32 blocksneeded, u32 * returned_block)
++{
++	int errorcode;
++
++	if (enoughspace(sb, blocksneeded) != FALSE) {
++		if ((errorcode = internalfindspace(sb, blocksneeded, 0, ASFS_SB(sb)->totalblocks, returned_block)) == 0)
++			errorcode = asfs_markspace(sb, *returned_block, blocksneeded);
++	} else
++		errorcode = -ENOSPC;
++
++	return (errorcode);
++}
++
++/* ************************** */
++
++int asfs_freespace(struct super_block *sb, u32 block, u32 blocks)
++{
++	int errorcode;
++
++	asfs_debug("freespace: Freeing %d blocks from block %d\n", blocks, block);
++
++	if ((errorcode = setfreeblocks(sb, ASFS_SB(sb)->freeblocks + blocks)) == 0) {
++		struct buffer_head *bh;
++		u32 skipblocks = block / ASFS_SB(sb)->blocks_inbitmap;
++		u32 longs = (sb->s_blocksize - sizeof(struct fsBitmap)) >> 2;
++		u32 bitmapblock;
++
++		block -= skipblocks * ASFS_SB(sb)->blocks_inbitmap;
++		bitmapblock = ASFS_SB(sb)->bitmapbase + skipblocks;
++
++		while (blocks > 0) {
++			if ((bh = asfs_breadcheck(sb, bitmapblock++, ASFS_BITMAP_ID))) {
++				struct fsBitmap *b = (void *) bh->b_data;
++
++				blocks -= bmset(b->bitmap, longs, block, blocks);
++				block = 0;
++
++				asfs_bstore(sb, bh);
++				asfs_brelse(bh);
++			} else
++				return -EIO;
++		}
++	}
++
++	return (errorcode);
++}
++
++/*************** admin space containers ****************/
++
++int asfs_allocadminspace(struct super_block *sb, u32 *returned_block)
++{
++	struct buffer_head *bh;
++	u32 adminspaceblock = ASFS_SB(sb)->adminspacecontainer;
++	int errorcode = -EIO;
++
++	asfs_debug("allocadminspace: allocating new block\n");
++
++	while ((bh = asfs_breadcheck(sb, adminspaceblock, ASFS_ADMINSPACECONTAINER_ID))) {
++		struct fsAdminSpaceContainer *asc1 = (void *) bh->b_data;
++		struct fsAdminSpace *as1 = asc1->adminspace;
++		int adminspaces1 = (sb->s_blocksize - sizeof(struct fsAdminSpaceContainer)) / sizeof(struct fsAdminSpace);
++
++		while (adminspaces1-- > 0) {
++			s16 bitoffset;
++
++			if (as1->space != 0 && (bitoffset = bfffz(be32_to_cpu(as1->bits), 0)) >= 0) {
++				u32 emptyadminblock = be32_to_cpu(as1->space) + bitoffset;
++				as1->bits |= cpu_to_be32(1 << (31 - bitoffset));
++				asfs_bstore(sb, bh);
++				*returned_block = emptyadminblock;
++				asfs_brelse(bh);
++				asfs_debug("allocadminspace: found block %d\n", *returned_block);
++				return 0;
++			}
++			as1++;
++		}
++
++		adminspaceblock = be32_to_cpu(asc1->next);
++		asfs_brelse(bh);
++
++		if (adminspaceblock == 0) {
++			u32 startblock;
++
++			asfs_debug("allocadminspace: allocating new adminspace area\n");
++
++			/* If we get here it means current adminspace areas are all filled.
++			   We would now need to find a new area and create a fsAdminSpace
++			   structure in one of the AdminSpaceContainer blocks.  If these
++			   don't have any room left for new adminspace areas a new
++			   AdminSpaceContainer would have to be created first which is
++			   placed as the first block in the newly found admin area. */
++
++			adminspaceblock = ASFS_SB(sb)->adminspacecontainer;
++
++			if ((errorcode = findandmarkspace(sb, 32, &startblock)))
++				return errorcode;
++
++			while ((bh = asfs_breadcheck(sb, adminspaceblock, ASFS_ADMINSPACECONTAINER_ID))) {
++				struct fsAdminSpaceContainer *asc2 = (void *) bh->b_data;
++				struct fsAdminSpace *as2 = asc2->adminspace;
++				int adminspaces2 = (sb->s_blocksize - sizeof(struct fsAdminSpaceContainer)) / sizeof(struct fsAdminSpace);
++
++				while (adminspaces2-- > 0 && as2->space != 0)
++					as2++;
++
++				if (adminspaces2 >= 0) {	/* Found a unused AdminSpace in this AdminSpaceContainer! */
++					as2->space = cpu_to_be32(startblock);
++					as2->bits = 0;
++					asfs_bstore(sb, bh);
++					asfs_brelse(bh);
++					break;
++				}
++
++				if (asc2->next == 0) {
++					/* Oh-oh... we marked our new adminspace area in use, but we couldn't
++					   find space to store a fsAdminSpace structure in the existing
++					   fsAdminSpaceContainer blocks.  This means we need to create and
++					   link a new fsAdminSpaceContainer as the first block in our newly
++					   marked adminspace. */
++
++					asc2->next = cpu_to_be32(startblock);
++					asfs_bstore(sb, bh);
++					asfs_brelse(bh);
++
++					/* Now preparing new AdminSpaceContainer */
++
++					if ((bh = asfs_getzeroblk(sb, startblock)) == NULL)
++						return -EIO;
++
++					asc2 = (void *) bh->b_data;
++					asc2->bheader.id = cpu_to_be32(ASFS_ADMINSPACECONTAINER_ID);
++					asc2->bheader.ownblock = cpu_to_be32(startblock);
++					asc2->previous = cpu_to_be32(adminspaceblock);
++					asc2->adminspace[0].space = cpu_to_be32(startblock);
++					asc2->adminspace[0].bits = cpu_to_be32(0x80000000);
++					asc2->bits = 32;
++
++					asfs_bstore(sb, bh);
++					asfs_brelse(bh);
++
++					adminspaceblock = startblock;
++					break;	/* Breaks through to outer loop! */
++				}
++				adminspaceblock = be32_to_cpu(asc2->next);
++				asfs_brelse(bh);
++			}
++		}
++	}
++	return errorcode;
++}
++
++int asfs_freeadminspace(struct super_block *sb, u32 block)
++{
++	struct buffer_head *bh;
++	u32 adminspaceblock = ASFS_SB(sb)->adminspacecontainer;
++
++	asfs_debug("freeadminspace: Entry -- freeing block %d\n", block);
++
++	while ((bh = asfs_breadcheck(sb, adminspaceblock, ASFS_ADMINSPACECONTAINER_ID))) {
++		struct fsAdminSpaceContainer *asc = (void *) bh->b_data;
++		struct fsAdminSpace *as = asc->adminspace;
++		int adminspaces = (sb->s_blocksize - sizeof(struct fsAdminSpaceContainer)) / sizeof(struct fsAdminSpace);
++
++		while (adminspaces-- > 0) {
++			if (block >= be32_to_cpu(as->space) && block < be32_to_cpu(as->space) + 32) {
++				s16 bitoffset = block - be32_to_cpu(as->space);
++				asfs_debug("freeadminspace: Block to be freed is located in AdminSpaceContainer block at %d\n", adminspaceblock);
++				as->bits &= cpu_to_be32(~(1 << (31 - bitoffset)));
++				asfs_bstore(sb, bh);
++				asfs_brelse(bh);
++				return 0;
++			}
++			as++;
++		}
++
++		if ((adminspaceblock = be32_to_cpu(asc->next)) == 0)
++			break;
++
++		asfs_brelse(bh);
++	}
++
++	if (bh != NULL) {
++		asfs_brelse(bh);
++		printk("ASFS: Unable to free an administration block. The block cannot be found.");
++		return -ENOENT;
++	}
++
++	return -EIO;
++}
++
++#endif
+diff -urN linux-2.6.3/fs/asfs/asfs_fs.h linux-2.6.3-asfs-1.0b7/fs/asfs/asfs_fs.h
+--- linux-2.6.3/fs/asfs/asfs_fs.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/asfs_fs.h	2004-06-10 19:28:16.000000000 +0200
+@@ -0,0 +1,227 @@
++#ifndef __LINUX_ASFS_FS_H
++#define __LINUX_ASFS_FS_H
++
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <asm/byteorder.h>
++#include <linux/amigasfs.h>
++
++#define asfs_debug(fmt,arg...) /* no debug at all */
++//#define asfs_debug(fmt,arg...) printk(fmt,##arg)  /* general debug infos */
++
++#if !defined (__BIG_ENDIAN) && !defined (__LITTLE_ENDIAN)
++#error Endianes must be known for ASFS to work. Sorry.
++#endif
++
++#define ASFS_DEFAULT_UID 0
++#define ASFS_DEFAULT_GID 0
++#define ASFS_DEFAULT_MODE 0644	/* default permission bits for files, dirs have same permission, but with "x" set */
++
++/* Extent structure located in RAM (e.g. inside inode structure), 
++   currently used to store last used extent */
++
++struct inramExtent {
++	u32 startblock;	/* Block from begginig of the file */
++	u32 key;
++	u32 next;
++	u16 blocks;
++};
++
++/* inode in-kernel data */
++
++struct asfs_inode_info {
++	u32 firstblock;
++	u32 hashtable;
++	int modified;
++	loff_t mmu_private;
++	struct inramExtent ext_cache;
++	struct inode vfs_inode;
++};
++
++/* short cut to get to the asfs specific inode data */
++static inline struct asfs_inode_info *ASFS_I(struct inode *inode)
++{
++   return list_entry(inode, struct asfs_inode_info, vfs_inode);
++}
++
++/* Amiga SFS superblock in-core data */
++
++struct asfs_sb_info {
++	u32 totalblocks;
++	u32 rootobjectcontainer;
++	u32 extentbnoderoot;
++	u32 objectnoderoot;
++
++	u32 adminspacecontainer;
++	u32 bitmapbase;
++	u32 freeblocks;
++	u32 blocks_inbitmap;
++	u32 blocks_bitmap;
++	u32 block_rovingblockptr;
++
++	uid_t uid;
++	gid_t gid;
++	umode_t mode;
++	u16 flags;
++	char *prefix;
++	char *root_volume;		/* Volume prefix for absolute symlinks. */
++};
++
++/* short cut to get to the asfs specific sb data */
++static inline struct asfs_sb_info *ASFS_SB(struct super_block *sb)
++{
++	return sb->s_fs_info;
++}
++ 
++/* io inline code */
++
++u32 asfs_calcchecksum(void *block, u32 blocksize);
++
++static inline int
++asfs_check_block(struct fsBlockHeader *block, u32 blocksize, u32 n, u32 id)
++{
++	if (asfs_calcchecksum(block, blocksize) ==
++	    be32_to_cpu(((struct fsBlockHeader *) block)->checksum) &&
++	    n == be32_to_cpu(((struct fsBlockHeader *) block)->ownblock) &&
++	    id == be32_to_cpu(((struct fsBlockHeader *) block)->id))
++		return TRUE;
++	return FALSE;
++}
++
++/* get fs structure from block and do some checks... */
++static inline struct buffer_head *
++asfs_breadcheck(struct super_block *sb, u32 n, u32 type)
++{
++	struct buffer_head *bh;
++	if ((bh = sb_bread(sb, n))) {
++		if (asfs_check_block ((void *)bh->b_data, sb->s_blocksize, n, type)) {
++			return bh;	/* all okay */
++		}
++		brelse(bh);
++	}
++	return NULL;		/* error */
++}
++
++static inline struct buffer_head *
++asfs_getzeroblk(struct super_block *sb, int block)
++{
++	struct buffer_head *bh;
++	bh = sb_getblk(sb, block);
++	lock_buffer(bh);
++	memset(bh->b_data, 0, sb->s_blocksize);
++	set_buffer_uptodate(bh);
++	unlock_buffer(bh);
++	return bh;
++}
++
++static inline void 
++asfs_bstore(struct super_block *sb, struct buffer_head *bh)
++{
++	((struct fsBlockHeader *) (bh->b_data))->checksum =
++	    cpu_to_be32(asfs_calcchecksum(bh->b_data, sb->s_blocksize));
++	mark_buffer_dirty(bh);
++}
++
++static inline void asfs_brelse(struct buffer_head *bh)
++{
++	brelse(bh);
++}
++
++static inline void dec_count(struct inode *inode)
++{
++	inode->i_nlink--;
++	mark_inode_dirty(inode);
++}
++
++/* all prototypes */
++
++/* adminspace.c */
++int asfs_allocadminspace(struct super_block *sb, u32 * block);
++int asfs_freeadminspace(struct super_block *sb, u32 block);
++int asfs_markspace(struct super_block *sb, u32 block, u32 blocks);
++int asfs_freespace(struct super_block *sb, u32 block, u32 blocks);
++int asfs_findspace(struct super_block *sb, u32 maxneeded, u32 start, u32 end,
++	      u32 * returned_block, u32 * returned_blocks);
++
++/* dir.c */
++int asfs_readdir(struct file *filp, void *dirent, filldir_t filldir);
++struct dentry *asfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd);
++
++/* extents.c */
++int asfs_getextent(struct super_block *sb, u32 key, struct buffer_head **ret_bh,
++	      struct fsExtentBNode **ret_ebn);
++int asfs_deletebnode(struct super_block *sb, struct buffer_head *cb, u32 key);
++int asfs_deleteextents(struct super_block *sb, u32 key);
++int asfs_addblocks(struct super_block *sb, u16 blocks, u32 newspace,
++	      u32 objectnode, u32 * io_lastextentbnode);
++
++/* file.c */
++int asfs_readpage(struct file *file, struct page *page);
++sector_t asfs_bmap(struct address_space *mapping, sector_t block);
++int asfs_writepage(struct page *page, struct writeback_control *wbc);
++int asfs_prepare_write(struct file *file, struct page *page, unsigned from,
++		       unsigned to);
++void asfs_truncate(struct inode *inode);
++int asfs_file_open(struct inode *inode, struct file *filp);
++int asfs_file_release(struct inode *inode, struct file *filp);
++
++/* inode.c */
++struct inode *asfs_get_root_inode(struct super_block *sb);
++void asfs_read_locked_inode(struct inode *inode, void *arg);
++int asfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd);
++int asfs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
++int asfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
++int asfs_rmdir(struct inode *dir, struct dentry *dentry);
++int asfs_unlink(struct inode *dir, struct dentry *dentry);
++int asfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++		struct inode *new_dir, struct dentry *new_dentry);
++int asfs_notify_change(struct dentry *dentry, struct iattr *attr);
++
++/* namei */
++u8 asfs_lowerchar(u8 c);
++int asfs_namecmp(u8 *s, u8 *ct, int casesensitive);
++u16 asfs_hash(u8 *name, int casesensitive);
++
++/* nodes */
++int asfs_getnode(struct super_block *sb, u32 nodeno,
++	    struct buffer_head **ret_bh, struct fsObjectNode **ret_node);
++int asfs_createnode(struct super_block *sb, struct buffer_head **returned_cb,
++	       struct fsNode **returned_node, u32 * returned_nodeno);
++int asfs_deletenode(struct super_block *sb, u32 objectnode);
++
++/* objects */
++struct fsObject *asfs_nextobject(struct fsObject *obj);
++struct fsObject *asfs_find_obj_by_name(struct super_block *sb,
++		struct fsObjectContainer *objcont, u8 * name);
++int asfs_readobject(struct super_block *sb, u32 objectnode,
++	       struct buffer_head **cb, struct fsObject **returned_object);
++int asfs_createobject(struct super_block *sb, struct buffer_head **io_cb,
++		 struct fsObject **io_o, struct fsObject *src_o,
++		 u8 * objname, int force);
++int asfs_deleteobject(struct super_block *sb, struct buffer_head *cb,
++		 struct fsObject *o);
++int asfs_renameobject(struct super_block *sb, struct buffer_head *cb1,
++		 struct fsObject *o1, struct buffer_head *cbparent,
++		 struct fsObject *oparent, u8 * newname);
++
++int asfs_addblockstofile(struct super_block *sb, struct buffer_head *objcb,
++		    struct fsObject *o, u32 blocks, u32 * newspace,
++		    u32 * addedblocks);
++int asfs_truncateblocksinfile(struct super_block *sb, struct buffer_head *bh,
++			 struct fsObject *o, u32 newsize);
++
++/* super.c */
++struct super_block *asfs_read_super(struct super_block *sb, void *data,
++				    int silent);
++void asfs_put_super(struct super_block *sb);
++int asfs_statfs(struct super_block *sb, struct kstatfs *buf);
++int asfs_remount(struct super_block *sb, int *flags, char *data);
++struct inode *asfs_alloc_inode(struct super_block *sb);
++void asfs_destroy_inode(struct inode *inode);
++
++/* symlink.c */
++int asfs_symlink_readpage(struct file *file, struct page *page);
++int asfs_write_symlink(struct inode *symfile, const char *symname);
++
++#endif
+diff -urN linux-2.6.3/fs/asfs/bitfuncs.c linux-2.6.3-asfs-1.0b7/fs/asfs/bitfuncs.c
+--- linux-2.6.3/fs/asfs/bitfuncs.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/bitfuncs.c	2004-06-14 17:38:04.000000000 +0200
+@@ -0,0 +1,171 @@
++/*
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/types.h>
++#include <asm/byteorder.h>
++#include "bitfuncs.h"
++
++/* Bitmap (bm) functions:
++   These functions perform bit-operations on regions of memory which
++   are a multiple of 4 bytes in length. Bitmap is in bigendian byte order.
++*/
++
++/* This function finds the first set bit in a region of memory starting
++   with /bitoffset/.  The region of memory is /longs/ longs long.  It
++   returns the bitoffset of the first set bit it finds. */
++
++int bmffo(u32 *bitmap, int longs, int bitoffset)
++{
++	u32 *scan = bitmap;
++	int longoffset, bit;
++
++	longoffset = bitoffset >> 5;
++	longs -= longoffset;
++	scan += longoffset;
++
++	bitoffset = bitoffset & 0x1F;
++
++	if (bitoffset != 0) {
++		if ((bit = bfffo(be32_to_cpu(*scan), bitoffset)) >= 0) {
++			return (bit + ((scan - bitmap) << 5));
++		}
++		scan++;
++		longs--;
++	}
++
++	while (longs-- > 0) {
++		if (*scan++ != 0) {
++			return (bfffo(be32_to_cpu(*--scan), 0) + ((scan - bitmap) << 5));
++		}
++	}
++
++	return (-1);
++}
++
++/* This function finds the first unset bit in a region of memory starting
++   with /bitoffset/.  The region of memory is /longs/ longs long.  It
++   returns the bitoffset of the first unset bit it finds. */
++
++int bmffz(u32 *bitmap, int longs, int bitoffset)
++{
++	u32 *scan = bitmap;
++	int longoffset, bit;
++
++	longoffset = bitoffset >> 5;
++	longs -= longoffset;
++	scan += longoffset;
++
++	bitoffset = bitoffset & 0x1F;
++
++	if (bitoffset != 0) {
++		if ((bit = bfffz(be32_to_cpu(*scan), bitoffset)) >= 0) {
++			return (bit + ((scan - bitmap) << 5));
++		}
++		scan++;
++		longs--;
++	}
++
++	while (longs-- > 0) {
++		if (*scan++ != 0xFFFFFFFF) {
++			return (bfffz(be32_to_cpu(*--scan), 0) + ((scan - bitmap) << 5));
++		}
++	}
++
++	return (-1);
++}
++
++/* This function clears /bits/ bits in a region of memory starting
++   with /bitoffset/.  The region of memory is /longs/ longs long.  If
++   the region of memory is too small to clear /bits/ bits then this
++   function exits after having cleared all bits till the end of the
++   memory region.  In any case it returns the number of bits which
++   were actually cleared. */
++
++int bmclr(u32 *bitmap, int longs, int bitoffset, int bits)
++{
++	u32 *scan = bitmap;
++	int longoffset;
++	int orgbits = bits;
++
++	longoffset = bitoffset >> 5;
++	longs -= longoffset;
++	scan += longoffset;
++
++	bitoffset = bitoffset & 0x1F;
++
++	if (bitoffset != 0) {
++		if (bits < 32) {
++			*scan = cpu_to_be32(bfclr(be32_to_cpu(*scan), bitoffset, bits));
++		} else {
++			*scan = cpu_to_be32(bfclr(be32_to_cpu(*scan), bitoffset, 32));
++		}
++		scan++;
++		longs--;
++		bits -= 32 - bitoffset;
++	}
++
++	while (bits > 0 && longs-- > 0) {
++		if (bits > 31) {
++			*scan++ = 0;
++		} else {
++			*scan = cpu_to_be32(bfclr(be32_to_cpu(*scan), 0, bits));
++		}
++		bits -= 32;
++	}
++
++	if (bits <= 0) {
++		return (orgbits);
++	}
++	return (orgbits - bits);
++}
++
++/* This function sets /bits/ bits in a region of memory starting
++   with /bitoffset/.  The region of memory is /longs/ longs long.  If
++   the region of memory is too small to set /bits/ bits then this
++   function exits after having set all bits till the end of the
++   memory region.  In any case it returns the number of bits which
++   were actually set. */
++
++int bmset(u32 *bitmap, int longs, int bitoffset, int bits)
++{
++	u32 *scan = bitmap;
++	int longoffset;
++	int orgbits = bits;
++
++	longoffset = bitoffset >> 5;
++	longs -= longoffset;
++	scan += longoffset;
++
++	bitoffset = bitoffset & 0x1F;
++
++	if (bitoffset != 0) {
++		if (bits < 32) {
++			*scan = cpu_to_be32(bfset(be32_to_cpu(*scan), bitoffset, bits));
++		} else {
++			*scan = cpu_to_be32(bfset(be32_to_cpu(*scan), bitoffset, 32));
++		}
++		scan++;
++		longs--;
++		bits -= 32 - bitoffset;
++	}
++
++	while (bits > 0 && longs-- > 0) {
++		if (bits > 31) {
++			*scan++ = 0xFFFFFFFF;
++		} else {
++			*scan = cpu_to_be32(bfset(be32_to_cpu(*scan), 0, bits));
++		}
++		bits -= 32;
++	}
++
++	if (bits <= 0) {
++		return (orgbits);
++	}
++	return (orgbits - bits);
++}
+diff -urN linux-2.6.3/fs/asfs/bitfuncs.h linux-2.6.3-asfs-1.0b7/fs/asfs/bitfuncs.h
+--- linux-2.6.3/fs/asfs/bitfuncs.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/bitfuncs.h	2004-06-10 18:57:14.000000000 +0200
+@@ -0,0 +1,58 @@
++/*
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#ifndef __BITFUNCS_H
++#define __BITFUNCS_H
++
++#include <linux/types.h>
++#include <asm/byteorder.h>
++
++#include <asm/bitops.h>
++
++/* Finds first set bit in /data/ starting at /bitoffset/.  This function
++   considers the MSB to be the first bit. */
++static inline int bfffo(u32 data, int bitoffset)
++{
++	u32 mask = 0xffffffff >> bitoffset;
++	data &= mask;
++	return data == 0 ? -1 : 32-fls(data);
++}
++
++/* Finds first zero bit in /data/ starting at /bitoffset/.  This function
++   considers the MSB to be the first bit. */
++static inline int bfffz(u32 data, int bitoffset)
++{
++	return bfffo(~data, bitoffset);
++}
++
++/* Sets /bits/ bits starting from /bitoffset/ in /data/.
++   /bits/ must be between 1 and 32. */
++static inline u32 bfset(u32 data, int bitoffset, int bits)
++{
++	u32 mask = ~((1 << (32 - bits)) - 1);
++	mask >>= bitoffset;
++	return data | mask;
++}
++
++/* Clears /bits/ bits starting from /bitoffset/ in /data/.
++   /bits/ must be between 1 and 32. */
++static inline u32 bfclr(u32 data, int bitoffset, int bits)
++{
++	u32 mask = ~((1 << (32 - bits)) - 1);
++	mask >>= bitoffset;
++	return data & ~mask;
++}
++
++/* bm??? functions assumes that in-memory bitmap is in bigendian byte order */
++int bmffo(u32 *, int, int);
++int bmffz(u32 *, int, int);
++int bmclr(u32 *, int, int, int);
++int bmset(u32 *, int, int, int);
++
++#endif
+diff -urN linux-2.6.3/fs/asfs/Changes linux-2.6.3-asfs-1.0b7/fs/asfs/Changes
+--- linux-2.6.3/fs/asfs/Changes	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/Changes	2004-06-25 22:44:01.646070896 +0200
+@@ -0,0 +1,101 @@
++
++Amiga Smart File System, Linux implementation
++
++Please direct bug reports to: marek at amiga.pl
++
++History:
++
++v1.0beta7 (25.06.2004)
++- small changes in documentation
++- code clean up: bitfuncs.c, super.c, inode.c, *.h, Makefile, added 
++  asfs_ prefix to function names, made some functions static
++  (big thanks to Christoph Hellwig for advice!)
++- fixed minor bugs (inode leak in super.c, not-realesed buffer during 
++  object renaming in inode.c)
++- now files/dirs are created with global ownership/permission bits
++
++v1.0beta6 (04.06.2004)
++- fixed: ASFS_SB(sb)->flags was always zero in 2.6.x code
++
++v1.0beta5 (07.05.2004)
++- finally fixed a problem with file size attrib. not being written
++  to disk
++- fixed some problems with GCC 3.x and debug enabled
++
++v1.0beta4 (12.04.2004)
++- removed dummy asfs_notify_change (this fixes major bug introduced
++  in 1.0beta3 - file size wasn't written to disk) until it will 
++  be implemented completely
++
++v1.0beta3 (22.03.2004) - still beta
++- updated for 2.6.x kernels VFS changes
++- code clean-up 
++- added dummy asfs_notify_change (chmod now returns no errors)
++- added symlinks write support
++- fixed: ASFS_SB(sb)->flags was always zero
++
++v1.0beta2 (11.01.2004) - special version for Pegasos][ kernel
++- separated read and write functions, can be compiled also
++  as read-only fs
++
++v1.0beta1 (02.12.2003) - first public beta with write support
++- added dentry hashing/comparing routines
++- code clean-up
++
++v1.0aplha4 (30.11.2003) - preparing for first public beta
++- fixed some problems with renaming/moving files
++- fixed two major bugs, which didn't occur when fs was mounted
++  on loopback device (newly allocated blocks were not written to
++  disk and state bits were not set correctly on newly mapped file
++  blocks)
++- fixed many small bugs in io code (some buffers were not freed)
++- added/modified sb locks in asfs_lookup and asfs_getblock
++- fixed serious bug in file block allocation routines
++
++v1.0aplha3 (23.11.2003)
++- added (hopefully) all byteswap code, should now work again on 
++  little-endian systems (also with write support!)
++- updated documentation
++
++v1.0alpha2 (13.11.2003) 
++- now alocates file blocks in chunks during one request
++- fixed some dead-locks, other fixes
++
++v1.0alpha (02.11.2003) - first working version with full write support
++- too much to list it here ;)
++
++... (working on write support)
++
++v0.7 (12.10.2003) - internal realase
++- added asfs_breadcheck, modified asfs_get_node, asfs_search_BTree, 
++  no more from_be32/16 macros, other...
++- code splitted into several files
++
++v0.6 (04.09.2003) - final read-only version
++- added support for HashTables, directory scaning should be
++  MUCH faster now
++- added checking of block IDs before reading any data from block
++
++v0.5 (19.07.2003)
++- added simple but effective extent cache - real speed-up 
++  in reading large files
++- added read support for symlinks - based on AFFS symlinks
++
++v0.4 (10.07.2003)
++- third code clean-up (thanks to Roman Zippel for advice)
++- now uses generic readpage and readinode routines
++
++v0.3beta (17.06.2003)
++- second code clean-up
++
++v0.2beta2 (15.06.2003)
++- fixed yet another stupid bug - driver can't read root block on little-endian systems
++v0.2beta (15.06.2003)
++- fixed stupid bug - now files have 'file' flag (S_IFREG) set...
++- added mount options to set uid, gid and mode of files and dirs
++- made hidden files & dirs really hidden (= not listed in directories)
++- code clean-up
++
++v0.1beta (11.06.2003) 
++- after many kernel crashes, finally got it! 
++- first working read-only filesystem driver
+diff -urN linux-2.6.3/fs/asfs/dir.c linux-2.6.3-asfs-1.0b7/fs/asfs/dir.c
+--- linux-2.6.3/fs/asfs/dir.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/dir.c	2004-06-17 00:44:35.000000000 +0200
+@@ -0,0 +1,217 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *
++ * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++
++extern struct dentry_operations asfs_dentry_operations;
++
++int asfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
++{
++	struct inode *dir = filp->f_dentry->d_inode;
++	struct super_block *sb = dir->i_sb;
++	unsigned long f_pos;
++	int stored = 0;
++
++	struct buffer_head *bh;
++	struct fsObjectContainer *objcont;
++	struct fsObject *obj;
++	u32 block;
++	int startnode;
++	int add;
++
++	asfs_debug("asfs_readdir:\n");
++
++	if (filp->f_pos == ASFS_SB(sb)->totalblocks)
++		return stored;
++
++	f_pos = filp->f_pos;
++
++	if (f_pos == 0) {
++		filp->private_data = (void *)0;
++		if (filldir(dirent, ".", 1, f_pos, dir->i_ino, DT_DIR) < 0)
++			return 0;
++		filp->f_pos = f_pos = 1;
++		stored++;
++	}
++	if (f_pos == 1) {
++		if (filldir(dirent, "..", 2, f_pos, parent_ino(filp->f_dentry), DT_DIR) < 0)
++			return stored;
++		filp->f_pos = f_pos = 2;
++		stored++;
++	}
++
++	if (ASFS_I(dir)->firstblock == 0) {	/* empty directory */
++		filp->f_pos = ASFS_SB(sb)->totalblocks;
++		ASFS_I(dir)->modified = 0;
++		return stored;
++	}
++
++	if (f_pos == 2) {	/* reading directory from its beginning */
++		block = ASFS_I(dir)->firstblock;
++		add = 1;
++		startnode = 0;
++	} else {
++		startnode = (int)filp->private_data;
++		add = 0;
++		if (ASFS_I(dir)->modified == 0)
++			block = f_pos;
++		else
++			block = ASFS_I(dir)->firstblock;
++	}
++
++	do {
++		if (!(bh = asfs_breadcheck(sb, block, ASFS_OBJECTCONTAINER_ID)))
++			return stored;
++		objcont = (struct fsObjectContainer *) bh->b_data;
++		obj = &(objcont->object[0]);
++
++		while (be32_to_cpu(obj->objectnode) > 0 && 
++		      ((char *)obj - (char *)objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
++
++			if (!add && be32_to_cpu(obj->objectnode) == startnode)
++				add++;
++
++			if (add && !(obj->bits & OTYPE_HIDDEN)) {
++				unsigned int type;
++				asfs_debug("ASFS: DirFilling: entry #%d \"%s\" (node %u offset %u), type %x\n", \
++				           stored, obj->name, be32_to_cpu(obj->objectnode), block, obj->bits);
++				filp->f_pos = block;
++
++				if (obj->bits & OTYPE_DIR)
++					type = DT_DIR;
++				else if (obj->bits & OTYPE_LINK && !(obj->bits & OTYPE_HARDLINK))
++					type = DT_LNK;
++				else
++					type = DT_REG;
++
++				if (filldir(dirent, obj->name, strlen(obj->name), block, be32_to_cpu(obj->objectnode), type) < 0) {
++					filp->private_data = (void *)be32_to_cpu(obj->objectnode);
++					ASFS_I(dir)->modified = 0;
++					asfs_debug("ASFS: DirFilling: to be continued...\n");
++					asfs_brelse(bh);
++					return stored;
++				}
++				stored++;
++			}
++			obj = asfs_nextobject(obj);
++		}
++		block = be32_to_cpu(objcont->next);
++		asfs_brelse(bh);
++
++	} while (block != 0);
++
++	filp->f_pos = ASFS_SB(sb)->totalblocks;
++	ASFS_I(dir)->modified = 0;
++
++	return stored;
++}
++
++struct dentry *asfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
++{
++	int res = -EACCES;       /* placeholder for "no data here" */
++	struct inode *inode;
++	struct super_block *sb = dir->i_sb;
++	u8 *name = (u8 *) dentry->d_name.name;
++	struct buffer_head *bh;
++	struct fsObject *obj;
++
++	asfs_debug("asfs_lookup: (searching \"%s\"...) ", name);
++
++	lock_super(sb);
++
++	if (ASFS_I(dir)->hashtable != 0) {	/* hashtable block is available, quick search */
++		struct fsObjectNode *node_p;
++		struct buffer_head *node_bh;
++		u32 node;
++		u16 hash16;
++
++		asfs_debug("(quick search) ");
++
++		if (!(bh = asfs_breadcheck(sb, ASFS_I(dir)->hashtable, ASFS_HASHTABLE_ID))) {
++			unlock_super(sb);
++			return ERR_PTR(res);
++		}
++		hash16 = asfs_hash(name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE); 
++		node = be32_to_cpu(((struct fsHashTable *) bh->b_data)->hashentry[HASHCHAIN(hash16)]);
++		asfs_brelse(bh);
++
++		while (node != 0) {
++			if (asfs_getnode(sb, node, &node_bh, &node_p) != 0)
++				goto not_found;
++			if (be16_to_cpu(node_p->hash16) == hash16) {
++				if (!(bh = asfs_breadcheck(sb, be32_to_cpu(node_p->node.data), ASFS_OBJECTCONTAINER_ID))) {
++					asfs_brelse(node_bh);
++					unlock_super(sb);
++					return ERR_PTR(res);
++				}
++				if ((obj = asfs_find_obj_by_name(sb, (struct fsObjectContainer *) bh->b_data, name)) != NULL) {
++					asfs_brelse(node_bh);
++					goto found_inode;
++				}
++				asfs_brelse(bh);
++			}
++			node = be32_to_cpu(node_p->next);
++			asfs_brelse(node_bh);
++		}
++	} else { /* hashtable not available, long search */
++		struct fsObjectContainer *objcont;
++		u32 block;
++
++		asfs_debug("(long search) ");
++
++		block = ASFS_I(dir)->firstblock;
++		while (block != 0) {
++			if (!(bh = asfs_breadcheck(sb, block, ASFS_OBJECTCONTAINER_ID))) {
++				unlock_super(sb);
++				return ERR_PTR(res);
++			}
++			objcont = (struct fsObjectContainer *) bh->b_data;
++			if ((obj = asfs_find_obj_by_name(sb, objcont, name)) != NULL)
++				goto found_inode;
++			block = be32_to_cpu(objcont->next);
++			asfs_brelse(bh);
++		}
++	}
++
++not_found:
++	unlock_super(sb);
++	inode = NULL;
++	asfs_debug("object not found.\n");
++	if (0) {
++found_inode:
++		unlock_super(sb);
++		if (!(inode = iget_locked(sb, be32_to_cpu(obj->objectnode)))) {
++			asfs_debug("ASFS: Strange - no inode allocated.\n");
++			return ERR_PTR(res);
++		}
++		if (inode->i_state & I_NEW) {
++			asfs_read_locked_inode(inode, obj);
++			unlock_new_inode(inode);
++		}
++		asfs_brelse(bh);
++	}
++	res = 0;
++	dentry->d_op = &asfs_dentry_operations;
++	d_add(dentry, inode);
++	return ERR_PTR(res);
++}
+diff -urN linux-2.6.3/fs/asfs/extents.c linux-2.6.3-asfs-1.0b7/fs/asfs/extents.c
+--- linux-2.6.3/fs/asfs/extents.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/extents.c	2004-06-10 17:56:26.000000000 +0200
+@@ -0,0 +1,586 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *
++ * This file contains some parts of the original amiga version of 
++ * SmartFilesystem source code.
++ *
++ * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
++ * Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
++ * 
++ * Adapted and modified by Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++
++	/* This function looks for the BNode equal to the key.  If no
++	   exact match is available then the BNode which is slightly
++	   lower than key will be returned.  If no such BNode exists
++	   either, then the first BNode in this block is returned.
++
++	   This function will return the first BNode even if there
++	   are no BNode's at all in this block (this can only happen
++	   for the Root of the tree).  Be sure to check if the Root
++	   is not empty before calling this function. */
++
++static struct BNode *searchforbnode(u32 key, struct BTreeContainer *tc)
++{
++	struct BNode *tn;
++	s16 n = be16_to_cpu(tc->nodecount) - 1;
++
++	tn = (struct BNode *) ((u8 *) tc->bnode + n * tc->nodesize);
++	for (;;) {
++		if (n <= 0 || key >= be32_to_cpu(tn->key))
++			return tn;
++
++		tn = (struct BNode *) ((u8 *) tn - tc->nodesize);
++		n--;
++	}
++}
++
++/* This function finds the BNode with the given key.  If no exact match can be
++   found then this function will return either the next or previous closest
++   match (don't rely on this).
++
++   If there were no BNode's at all, then *returned_bh will be NULL. */
++
++static int findbnode(struct super_block *sb, u32 key, struct buffer_head **returned_bh, struct BNode **returned_bnode)
++{
++	u32 rootblock = ASFS_SB(sb)->extentbnoderoot;
++
++	asfs_debug("findbnode: Looking for BNode with key %d\n", key);
++
++	while ((*returned_bh = asfs_breadcheck(sb, rootblock, ASFS_BNODECONTAINER_ID))) {
++		struct fsBNodeContainer *bnc = (void *) (*returned_bh)->b_data;
++		struct BTreeContainer *btc = &bnc->btc;
++
++		if (btc->nodecount == 0) {
++			*returned_bnode = NULL;
++			break;
++		}
++
++		*returned_bnode = searchforbnode(key, btc);
++		if (btc->isleaf == TRUE)
++			break;
++
++		rootblock = be32_to_cpu((*returned_bnode)->data);
++		asfs_brelse(*returned_bh);
++	}
++
++	if (*returned_bh == NULL)
++		return -EIO;
++
++	return 0;
++}
++
++int asfs_getextent(struct super_block *sb, u32 key, struct buffer_head **ret_bh, struct fsExtentBNode **ret_ebn)
++{
++	int result;
++	if ((result = findbnode(sb, key, ret_bh, (struct BNode **)ret_ebn)) == 0) 
++		if (be32_to_cpu((*ret_ebn)->key) != key) {
++			brelse(*ret_bh);
++			*ret_bh = NULL;
++			return -ENOENT;
++		}
++
++	return result;
++}
++
++#ifdef CONFIG_ASFS_RW
++
++	/* This routine inserts a node sorted into a BTreeContainer.  It does
++	   this by starting at the end, and moving the nodes one by one to
++	   a higher slot until the empty slot has the correct position for
++	   this key.  Donot use this function on completely filled
++	   BTreeContainers! */
++
++static struct BNode *insertbnode(u32 key, struct BTreeContainer *btc)
++{
++	struct BNode *bn;
++	bn = (struct BNode *) ((u8 *) btc->bnode + btc->nodesize * (be16_to_cpu(btc->nodecount) - 1));
++
++	for (;;) {
++		if (bn < btc->bnode || key > be32_to_cpu(bn->key)) {
++			bn = (struct BNode *) ((u8 *) bn + btc->nodesize);
++			bn->key = cpu_to_be32(key);
++			btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + 1);
++			break;
++		} else 
++			memmove((u8 *)bn + btc->nodesize, bn, btc->nodesize);
++
++		bn = (struct BNode *) ((u8 *) bn - btc->nodesize);
++	}
++
++	return bn;
++}
++
++static int getparentbtreecontainer(struct super_block *sb, struct buffer_head *bh, struct buffer_head **parent_bh)
++{
++	u32 rootblock = ASFS_SB(sb)->extentbnoderoot;
++	u32 childkey = be32_to_cpu(((struct fsBNodeContainer *) bh->b_data)->btc.bnode[0].key);
++	u32 childblock = be32_to_cpu(((struct fsBNodeContainer *) bh->b_data)->bheader.ownblock);
++
++	asfs_debug("getparentbtreecontainer: Getting parent of block %d\n", childblock);
++
++	/* This function gets the BTreeContainer parent of the passed in buffer_head. If
++	   there is no parent this function sets dest_cont io_bh to NULL */
++
++	if (rootblock != childblock) {
++		while ((*parent_bh = asfs_breadcheck(sb, rootblock, ASFS_BNODECONTAINER_ID))) {
++			struct fsBNodeContainer *bnc = (void *) (*parent_bh)->b_data;
++			struct BTreeContainer *btc = &bnc->btc;
++			struct BNode *bn;
++			s16 n = be16_to_cpu(btc->nodecount);
++
++			if (btc->isleaf == TRUE) {
++				asfs_brelse(*parent_bh);
++				break;
++			}
++
++			while (n-- > 0)
++				if (be32_to_cpu(btc->bnode[n].data) == childblock)
++					return 0;	/* Found parent!! */
++
++			bn = searchforbnode(childkey, btc);	/* This searchforbnode() doesn't have to get EXACT key matches. */
++			rootblock = be32_to_cpu(bn->data);
++			asfs_brelse(*parent_bh);
++		}
++		if (*parent_bh == NULL)
++			return -EIO;
++	}
++
++	*parent_bh = NULL;
++	return 0;
++}
++
++/* Spits a btreecontainer. It realses passed in bh! */
++
++static int splitbtreecontainer(struct super_block *sb, struct buffer_head *bh)
++{
++	struct buffer_head *bhparent;
++	struct BNode *bn;
++	int errorcode;
++
++	asfs_debug("splitbtreecontainer: splitting block %u\n", be32_to_cpu(((struct fsBlockHeader *) bh->b_data)->ownblock));
++
++	if ((errorcode = getparentbtreecontainer(sb, bh, &bhparent)) == 0) {
++		if (bhparent == NULL) {
++			u32 newbcontblock;
++			u32 bcontblock;
++			/* We need to create Root tree-container - adding new level to extent tree */
++
++			asfs_debug("splitbtreecontainer: creating root tree-container.\n");
++
++			bhparent = bh;
++			if ((errorcode = asfs_allocadminspace(sb, &newbcontblock)) == 0 && (bh = asfs_getzeroblk(sb, newbcontblock))) {
++				struct fsBNodeContainer *bnc = (void *) bh->b_data;
++				struct fsBNodeContainer *bncparent = (void *) bhparent->b_data;
++				struct BTreeContainer *btcparent = &bncparent->btc;
++
++				bcontblock = be32_to_cpu(bncparent->bheader.ownblock);
++				memcpy(bh->b_data, bhparent->b_data, sb->s_blocksize);
++				bnc->bheader.ownblock = cpu_to_be32(newbcontblock);
++				asfs_bstore(sb, bh);
++
++				memset(bhparent->b_data, '\0', sb->s_blocksize);	/* Not strictly needed, but makes things more clear. */
++				bncparent->bheader.id = cpu_to_be32(ASFS_BNODECONTAINER_ID);
++				bncparent->bheader.ownblock = cpu_to_be32(bcontblock);
++				btcparent->isleaf = FALSE;
++				btcparent->nodesize = sizeof(struct BNode);
++				btcparent->nodecount = 0;
++
++				bn = insertbnode(0, btcparent);
++				bn->data = cpu_to_be32(newbcontblock);
++
++				asfs_bstore(sb, bhparent);
++			}
++			if (bh == NULL)
++				errorcode = -EIO;
++		}
++
++		if (errorcode == 0) {
++			struct fsBNodeContainer *bncparent = (void *) bhparent->b_data;
++			struct BTreeContainer *btcparent = &bncparent->btc;
++			int branches1 = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btcparent->nodesize;
++
++			if (be16_to_cpu(btcparent->nodecount) == branches1) {
++				/* We need to split the parent tree-container first! */
++				if ((errorcode = splitbtreecontainer(sb, bhparent)) == 0) {
++					/* bhparent might have changed after the split and has been released */
++					if ((errorcode = getparentbtreecontainer(sb, bh, &bhparent)) == 0) {	
++						bncparent = (void *) bhparent->b_data;
++						btcparent = &bncparent->btc;
++					}
++				}
++			}
++
++			if (errorcode == 0) {
++				u32 newbcontblock;
++				struct buffer_head *bhnew;
++
++				/* We can split this container and add it to the parent
++				   because the parent has enough room. */
++
++				if ((errorcode = asfs_allocadminspace(sb, &newbcontblock)) == 0 && (bhnew = asfs_getzeroblk(sb, newbcontblock))) {
++					struct fsBNodeContainer *bncnew = (void *) bhnew->b_data;
++					struct BTreeContainer *btcnew = &bncnew->btc;
++					struct fsBNodeContainer *bnc = (void *) bh->b_data;
++					struct BTreeContainer *btc = &bnc->btc;
++					int branches2 = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btc->nodesize;
++					u32 newkey;
++
++					bncnew->bheader.id = cpu_to_be32(ASFS_BNODECONTAINER_ID);
++					bncnew->bheader.ownblock = cpu_to_be32(newbcontblock);
++
++					btcnew->isleaf = btc->isleaf;
++					btcnew->nodesize = btc->nodesize;
++
++					btcnew->nodecount = cpu_to_be16(branches2 - branches2 / 2);
++
++					memcpy(btcnew->bnode, (u8 *) btc->bnode + branches2 / 2 * btc->nodesize, (branches2 - branches2 / 2) * btc->nodesize);
++					newkey = be32_to_cpu(btcnew->bnode[0].key);
++
++					asfs_bstore(sb, bhnew);
++					asfs_brelse(bhnew);
++
++					btc->nodecount = cpu_to_be16(branches2 / 2);
++					asfs_bstore(sb, bh);
++
++					bn = insertbnode(newkey, btcparent);
++					bn->data = cpu_to_be32(newbcontblock);
++					asfs_bstore(sb, bhparent);
++				}
++			}
++		}
++		asfs_brelse(bhparent);
++	}
++	asfs_brelse(bh);
++
++	return errorcode;
++}
++
++/* Returns created extentbnode - returned_bh need to saved and realesed in caller funkction! */
++
++int createextentbnode(struct super_block *sb, u32 key, struct buffer_head **returned_bh, struct BNode **returned_bnode)
++{
++	int errorcode;
++
++	asfs_debug("createbnode: Creating BNode with key %d\n", key);
++
++	while ((errorcode = findbnode(sb, key, returned_bh, returned_bnode)) == 0) {
++		struct fsBNodeContainer *bnc = (void *) (*returned_bh)->b_data;
++		struct BTreeContainer *btc = &bnc->btc;
++		int extbranches = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btc->nodesize;
++
++		asfs_debug("createbnode: findbnode found block %d\n", be32_to_cpu(((struct fsBlockHeader *) (*returned_bh)->b_data)->ownblock));
++
++		if (be16_to_cpu(btc->nodecount) < extbranches) {
++			/* Simply insert new node in this BTreeContainer */
++			asfs_debug("createbnode: Simple insert\n");
++			*returned_bnode = insertbnode(key, btc);
++			break;
++		} else if ((errorcode = splitbtreecontainer(sb, *returned_bh)) != 0)
++			break;
++
++		/* Loop and try insert it the normal way again :-) */
++	}
++
++	return (errorcode);
++}
++
++
++/* This routine removes a node from a BTreeContainer indentified
++   by its key.  If no such key exists this routine does nothing.
++   It correctly handles empty BTreeContainers. */
++
++static void removebnode(u32 key, struct BTreeContainer *btc)
++{
++	struct BNode *bn = btc->bnode;
++	int n = 0;
++
++	asfs_debug("removebnode: key %d\n", key);
++
++	while (n < be16_to_cpu(btc->nodecount)) {
++		if (be32_to_cpu(bn->key) == key) {
++			btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) - 1);
++			memmove(bn, (u8 *) bn + btc->nodesize, (be16_to_cpu(btc->nodecount) - n) * btc->nodesize);
++			break;
++		}
++		bn = (struct BNode *) ((u8 *) bn + btc->nodesize);
++		n++;
++	}
++}
++
++int asfs_deletebnode(struct super_block *sb, struct buffer_head *bh, u32 key)
++{
++	struct fsBNodeContainer *bnc1 = (void *) bh->b_data;
++	struct BTreeContainer *btc = &bnc1->btc;
++	u16 branches = (sb->s_blocksize - sizeof(struct fsBNodeContainer)) / btc->nodesize;
++	int errorcode = 0;
++
++	/* Deletes specified internal node. */
++
++	removebnode(key, btc);
++	asfs_bstore(sb, bh);
++
++	/* Now checks if the container still contains enough nodes,
++	   and takes action accordingly. */
++
++	asfs_debug("deletebnode: branches = %d, btc->nodecount = %d\n", branches, be16_to_cpu(btc->nodecount));
++
++	if (be16_to_cpu(btc->nodecount) < (branches + 1) / 2) {
++		struct buffer_head *bhparent;
++		struct buffer_head *bhsec;
++
++		/* nodecount has become to low.  We need to merge this Container
++		   with a neighbouring Container, or we need to steal a few nodes
++		   from a neighbouring Container. */
++
++		/* We get the parent of the container here, so we can find out what
++		   containers neighbour the container which currently hasn't got enough nodes. */
++
++		if ((errorcode = getparentbtreecontainer(sb, bh, &bhparent)) == 0) {
++			if (bhparent != NULL) {
++				struct fsBNodeContainer *bncparent = (void *) bhparent->b_data;
++				struct BTreeContainer *btcparent = &bncparent->btc;
++				s16 n;
++
++				asfs_debug("deletebnode: get parent returned block %d.\n", be32_to_cpu(((struct fsBlockHeader *) bhparent->b_data)->ownblock));
++
++				for (n = 0; n < be16_to_cpu(btcparent->nodecount); n++)
++					if (btcparent->bnode[n].data == bnc1->bheader.ownblock)
++						break;
++				/* n is now the offset of our own bnode. */
++
++				if (n < be16_to_cpu(btcparent->nodecount) - 1) {	/* Check if we have a next neighbour. */
++					asfs_debug("deletebnode: using next container - merging blocks %d and %d\n", be32_to_cpu(bnc1->bheader.ownblock), be32_to_cpu(btcparent->bnode[n+1].data));
++
++					if ((bhsec = asfs_breadcheck(sb, be32_to_cpu(btcparent->bnode[n + 1].data), ASFS_BNODECONTAINER_ID))) {
++						struct fsBNodeContainer *bnc_next = (void *) bhsec->b_data;
++						struct BTreeContainer *btc_next = &bnc_next->btc;
++
++						if (be16_to_cpu(btc_next->nodecount) + be16_to_cpu(btc->nodecount) > branches) {	/* Check if we need to steal nodes. */
++							s16 nodestosteal = (be16_to_cpu(btc_next->nodecount) + be16_to_cpu(btc->nodecount)) / 2 - be16_to_cpu(btc->nodecount);
++
++							/* Merging them is not possible.  Steal a few nodes then. */
++							memcpy((u8 *) btc->bnode + be16_to_cpu(btc->nodecount) * btc->nodesize, btc_next->bnode, nodestosteal * btc->nodesize);
++							btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + nodestosteal);
++							asfs_bstore(sb, bh);
++
++							memcpy(btc_next->bnode, (u8 *) btc_next->bnode + btc_next->nodesize * nodestosteal,
++							       btc->nodesize * (be16_to_cpu(btc_next->nodecount) - nodestosteal));
++							btc_next->nodecount = cpu_to_be16(be16_to_cpu(btc_next->nodecount) - nodestosteal);
++							asfs_bstore(sb, bhsec);
++
++							btcparent->bnode[n + 1].key = btc_next->bnode[0].key;
++							asfs_bstore(sb, bhparent);
++						} else {	/* Merging is possible. */
++							memcpy((u8 *) btc->bnode + btc->nodesize * be16_to_cpu(btc->nodecount), btc_next->bnode, btc->nodesize * be16_to_cpu(btc_next->nodecount));
++							btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + be16_to_cpu(btc_next->nodecount));
++							asfs_bstore(sb, bh);
++
++							if ((errorcode = asfs_freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *) bhsec->b_data)->ownblock))) == 0)
++								errorcode = asfs_deletebnode(sb, bhparent, be32_to_cpu(btcparent->bnode[n + 1].key));
++						}
++						asfs_brelse(bhsec);
++					}
++				} else if (n > 0) {	/* Check if we have a previous neighbour. */
++					asfs_debug("deletebnode: using prev container.\n");
++
++					if ((bhsec = asfs_breadcheck(sb, be32_to_cpu(btcparent->bnode[n - 1].data), ASFS_BNODECONTAINER_ID)) == 0) {
++						struct fsBNodeContainer *bnc2 = (void *) bhsec->b_data;
++						struct BTreeContainer *btc2 = &bnc2->btc;
++
++						if (be16_to_cpu(btc2->nodecount) + be16_to_cpu(btc->nodecount) > branches) {
++							/* Merging them is not possible.  Steal a few nodes then. */
++							s16 nodestosteal = (be16_to_cpu(btc2->nodecount) + be16_to_cpu(btc->nodecount)) / 2 - be16_to_cpu(btc->nodecount);
++
++							memmove((u8 *) btc->bnode + nodestosteal * btc->nodesize, btc->bnode, be16_to_cpu(btc->nodecount) * btc->nodesize);
++							btc->nodecount = cpu_to_be16(be16_to_cpu(btc->nodecount) + nodestosteal);
++							memcpy(btc->bnode, (u8 *) btc2->bnode + (be16_to_cpu(btc2->nodecount) - nodestosteal) * btc2->nodesize, nodestosteal * btc->nodesize);
++
++							asfs_bstore(sb, bh);
++
++							btc2->nodecount = cpu_to_be16(be16_to_cpu(btc2->nodecount) - nodestosteal);
++							asfs_bstore(sb, bhsec);
++
++							btcparent->bnode[n].key = btc->bnode[0].key;
++							asfs_bstore(sb, bhparent);
++						} else {	/* Merging is possible. */
++							memcpy((u8 *) btc2->bnode + be16_to_cpu(btc2->nodecount) * btc2->nodesize, btc->bnode, be16_to_cpu(btc->nodecount) * btc->nodesize);
++							btc2->nodecount = cpu_to_be16(be16_to_cpu(btc2->nodecount) + be16_to_cpu(btc->nodecount));
++							asfs_bstore(sb, bhsec);
++
++							if ((errorcode = asfs_freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *) bhsec->b_data)->ownblock))) == 0)
++								errorcode = asfs_deletebnode(sb, bhparent, be32_to_cpu(btcparent->bnode[n].key));
++						}
++						asfs_brelse(bhsec);
++					}
++				}
++				/*      else    
++				   {
++				   // Never happens, except for root and then we don't care.
++				   } */
++			} else if (btc->nodecount == 1) {
++				/* No parent, so must be root. */
++
++				asfs_debug("deletebnode: no parent so must be root\n");
++
++				if (btc->isleaf == FALSE) {
++					struct fsBNodeContainer *bnc3 = (void *) bh->b_data;
++
++					/* The current root has only 1 node.  We now copy the data of this node into the
++					   root and promote that data to be the new root.  The rootblock number stays the
++					   same that way. */
++
++					if ((bhsec = asfs_breadcheck(sb, be32_to_cpu(btc->bnode[0].data), ASFS_BNODECONTAINER_ID))) {
++						u32 blockno = be32_to_cpu(((struct fsBlockHeader *) bh->b_data)->ownblock);
++						memcpy(bh->b_data, bhsec->b_data, sb->s_blocksize);
++						bnc3->bheader.ownblock = cpu_to_be32(blockno);
++
++						asfs_bstore(sb, bh);
++						errorcode = asfs_freeadminspace(sb, be32_to_cpu(((struct fsBlockHeader *) bhsec->b_data)->ownblock));
++						asfs_brelse(bhsec);
++					} else
++						errorcode = -EIO;
++				}
++				/* If not, then root contains leafs. */
++			}
++
++			asfs_debug("deletebnode: almost done\n");
++			/* otherwise, it must be the root, and the root is allowed
++			   to contain less than the minimum amount of nodes. */
++
++		}
++		if (bhparent != NULL)
++			asfs_brelse(bhparent);
++	}
++
++	return errorcode;
++}
++
++   /* Deletes an fsExtentBNode structure by key and any fsExtentBNodes linked to it.
++      This function DOES NOT fix the next pointer in a possible fsExtentBNode which
++      might have been pointing to the first BNode we are deleting.  Make sure you check
++      this yourself, if needed.
++
++      If key is zero, than this function does nothing. */
++
++int asfs_deleteextents(struct super_block *sb, u32 key)
++{
++	struct buffer_head *bh;
++	struct fsExtentBNode *ebn;
++	int errorcode = 0;
++
++	asfs_debug("deleteextents: Entry -- deleting extents from key %d\n", key);
++
++	while (key != 0 && (errorcode = findbnode(sb, key, &bh, (struct BNode **) &ebn)) == 0) {
++		/* node to be deleted located. */
++		key = be32_to_cpu(ebn->next);
++		if ((errorcode = asfs_freespace(sb, be32_to_cpu(ebn->key), be16_to_cpu(ebn->blocks))) != 0)
++			break;
++
++		if ((errorcode = asfs_deletebnode(sb, bh, be32_to_cpu(ebn->key))) != 0)
++			break;
++
++		asfs_brelse(bh);
++	}
++
++	return (errorcode);
++}
++
++   /* This function adds /blocks/ blocks starting at block /newspace/ to a file
++      identified by /objectnode/ and /lastextentbnode/.  /io_lastextentbnode/ can
++      be zero if there is no ExtentBNode chain attached to this file yet.
++      /blocks/ ranges from 1 to 8192.  To be able to extend Extents which are
++      almost full, it is wise to make this value no higher than 8192 blocks.
++      /io_lastextentbnode/ will contain the new lastextentbnode value when this
++      function completes.
++      If there was no chain yet, then this function will create a new one.  */
++
++int asfs_addblocks(struct super_block *sb, u16 blocks, u32 newspace, u32 objectnode, u32 *io_lastextentbnode)
++{
++	struct buffer_head *bh;
++	struct fsExtentBNode *ebn;
++	int errorcode = 0;
++
++	if (*io_lastextentbnode != 0) {
++		/* There was already a ExtentBNode chain for this file.  Extending it. */
++
++		asfs_debug("  addblocks: Extending existing ExtentBNode chain.\n");
++
++		if ((errorcode = asfs_getextent(sb, *io_lastextentbnode, &bh, &ebn)) == 0) {
++			if (be32_to_cpu(ebn->key) + be16_to_cpu(ebn->blocks) == newspace && be16_to_cpu(ebn->blocks) + blocks < 65536) {
++				/* It is possible to extent the last ExtentBNode! */
++				asfs_debug("  addblocks: Extending last ExtentBNode.\n");
++
++				ebn->blocks = cpu_to_be16(be16_to_cpu(ebn->blocks) + blocks);
++
++				asfs_bstore(sb, bh);
++				asfs_brelse(bh);
++			} else {
++				/* It isn't possible to extent the last ExtentBNode so we create
++				   a new one and link it to the last ExtentBNode. */
++
++				ebn->next = cpu_to_be32(newspace);
++				asfs_bstore(sb, bh);
++				asfs_brelse(bh);
++
++				if ((errorcode = createextentbnode(sb, newspace, &bh, (struct BNode **) &ebn)) == 0) {
++					asfs_debug("  addblocks: Created new ExtentBNode.\n");
++
++					ebn->key = cpu_to_be32(newspace);
++					ebn->prev = cpu_to_be32(*io_lastextentbnode);
++					ebn->next = 0;
++					ebn->blocks = cpu_to_be16(blocks);
++
++					*io_lastextentbnode = newspace;
++
++					asfs_bstore(sb, bh);
++					asfs_brelse(bh);
++
++					ASFS_SB(sb)->block_rovingblockptr = newspace + blocks;
++
++	/* to be changed in the future */
++/*					if (ASFS_SB(sb)->block_rovingblockptr >= ASFS_SB(sb)->totalblocks)
++						ASFS_SB(sb)->block_rovingblockptr = 0;*/
++				}
++			}
++		}
++	} else {
++		/* There is no ExtentBNode chain yet for this file.  Attaching one! */
++		if ((errorcode = createextentbnode(sb, newspace, &bh, (struct BNode **) &ebn)) == 0) {
++			asfs_debug("  addblocks: Created new ExtentBNode chain.\n");
++
++			ebn->key = cpu_to_be32(newspace);
++			ebn->prev = cpu_to_be32(objectnode + 0x80000000);
++			ebn->next = 0;
++			ebn->blocks = cpu_to_be16(blocks);
++
++			*io_lastextentbnode = newspace;
++
++			asfs_bstore(sb, bh);
++			asfs_brelse(bh);
++
++			ASFS_SB(sb)->block_rovingblockptr = newspace + blocks;
++
++/*			if (ASFS_SB(sb)->block_rovingblockptr >= ASFS_SB(sb)->totalblocks)
++				ASFS_SB(sb)->block_rovingblockptr = 0;*/
++		}
++	}
++
++	asfs_debug("  addblocks: done.\n");
++
++	return errorcode;
++}
++#endif
+diff -urN linux-2.6.3/fs/asfs/file.c linux-2.6.3-asfs-1.0b7/fs/asfs/file.c
+--- linux-2.6.3/fs/asfs/file.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/file.c	2004-06-10 01:42:01.000000000 +0200
+@@ -0,0 +1,251 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *  
++ * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/pagemap.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++
++static int
++asfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
++{
++	struct buffer_head *ebn_bh;
++	struct fsExtentBNode extent, *ebn_p;
++	u32 filedata;
++	unsigned long pos;
++	struct super_block *sb = inode->i_sb;
++#ifdef CONFIG_ASFS_RW
++	int error;
++	struct buffer_head *bh;
++	struct fsObject *obj;
++#endif
++
++	asfs_debug("ASFS: get_block(%lu, %ld, %d)\n", inode->i_ino, block, create);
++
++	if (block < 0) {
++		printk(KERN_ERR "ASFS: asfsget_block: requested block (%ld) < 0!\n", block);
++		return -EIO;
++	} else if (block >= inode->i_blocks && !create) {
++		printk(KERN_ERR "ASFS: asfsget_block: strange block request %ld!\n", block);
++		return -EIO;
++	} 
++
++	if (create)
++#ifdef CONFIG_ASFS_RW
++		ASFS_I(inode)->modified = TRUE;
++#else
++		return -EROFS;
++#endif
++
++	if (block < inode->i_blocks)
++		create = 0;
++
++	lock_super(sb);
++
++#ifdef CONFIG_ASFS_RW
++	if (create) {
++		int blockstoadd;
++		u32 newspace, addedblocks;
++
++		blockstoadd = block - inode->i_blocks + 1;
++
++		if (blockstoadd < ASFS_BLOCKCHUNKS)
++			blockstoadd = ASFS_BLOCKCHUNKS;
++ 
++		asfs_debug("ASFS get_block: Trying to add %d blocks to file\n", blockstoadd);
++		
++		if ((error = asfs_readobject(sb, inode->i_ino, &bh, &obj)) != 0) {
++			unlock_super(sb);
++			return error;
++		}
++
++		if ((error = asfs_addblockstofile(sb, bh, obj, blockstoadd, &newspace, &addedblocks)) != 0) {
++			asfs_brelse(bh);
++			unlock_super(sb);
++			return error;
++		}
++		ASFS_I(inode)->mmu_private += addedblocks * sb->s_blocksize;
++		inode->i_blocks += addedblocks;
++		ASFS_I(inode)->ext_cache.key = 0;
++		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
++		asfs_brelse(bh);
++	}
++#endif
++
++	if (ASFS_I(inode)->ext_cache.key > 0 && ASFS_I(inode)->ext_cache.startblock <= block) {
++		extent.key = ASFS_I(inode)->ext_cache.key;
++		extent.next = ASFS_I(inode)->ext_cache.next;
++		extent.blocks = ASFS_I(inode)->ext_cache.blocks;
++		pos = ASFS_I(inode)->ext_cache.startblock;
++	} else {
++		if (asfs_getextent(inode->i_sb, ASFS_I(inode)->firstblock, &ebn_bh, &ebn_p) != 0) {
++			unlock_super(sb);
++			return -EIO;
++		}
++		extent.key = be32_to_cpu(ebn_p->key);
++		extent.next = be32_to_cpu(ebn_p->next);
++		extent.blocks = be16_to_cpu(ebn_p->blocks);
++		pos = 0;
++		asfs_brelse(ebn_bh);
++	}
++	ebn_p = &extent;
++	filedata = ebn_p->next;
++
++	while (pos + ebn_p->blocks <= block && ebn_p->next != 0 && pos < inode->i_blocks) {
++		pos += ebn_p->blocks;
++		if (asfs_getextent(inode->i_sb, filedata, &ebn_bh, &ebn_p) != 0) {
++			unlock_super(sb);
++			return -EIO;
++		}
++		extent.key = be32_to_cpu(ebn_p->key);
++		extent.next = be32_to_cpu(ebn_p->next);
++		extent.blocks = be16_to_cpu(ebn_p->blocks);
++		ebn_p = &extent;	
++		filedata = ebn_p->next;
++		asfs_brelse(ebn_bh);
++	}
++
++	unlock_super(sb);
++
++	map_bh(bh_result, inode->i_sb, (sector_t) (ebn_p->key + block - pos));
++
++	if (create)
++		set_buffer_new(bh_result);
++
++	asfs_debug("ASFS: get_block - mapped block %lu\n", ebn_p->key + block - pos);
++
++	ASFS_I(inode)->ext_cache.startblock = pos;
++	ASFS_I(inode)->ext_cache.key = ebn_p->key;
++	ASFS_I(inode)->ext_cache.next = ebn_p->next;
++	ASFS_I(inode)->ext_cache.blocks = ebn_p->blocks;
++
++	return 0;
++}
++
++int asfs_readpage(struct file *file, struct page *page)
++{
++	asfs_debug("ASFS: %s\n", __FUNCTION__);
++	return block_read_full_page(page, asfs_get_block);
++}
++
++sector_t asfs_bmap(struct address_space *mapping, sector_t block)
++{
++	asfs_debug("ASFS: %s\n", __FUNCTION__);
++	return generic_block_bmap(mapping,block,asfs_get_block);
++}
++
++#ifdef CONFIG_ASFS_RW
++
++int asfs_writepage(struct page *page, struct writeback_control *wbc)
++{
++	asfs_debug("ASFS: %s\n", __FUNCTION__);
++	return block_write_full_page(page, asfs_get_block, wbc);
++}
++
++int asfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
++{
++	asfs_debug("ASFS: %s\n", __FUNCTION__);
++	return cont_prepare_write(page, from, to, asfs_get_block, &ASFS_I(page->mapping->host)->mmu_private);
++}
++
++void asfs_truncate(struct inode *inode)
++{
++	struct super_block *sb = inode->i_sb;
++	struct buffer_head *bh;
++	struct fsObject *obj;
++
++	asfs_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)\n",
++		 (u32)inode->i_ino, (u32)ASFS_I(inode)->mmu_private, (u32)inode->i_size);
++
++	if (inode->i_size > ASFS_I(inode)->mmu_private) {
++		printk("ASFS: enlarging file is not supported yet\n");
++		return;
++	}
++
++	lock_super(sb);
++
++	if ((asfs_readobject(sb, inode->i_ino, &bh, &obj)) != 0) {
++		unlock_super(sb);
++		return;
++	}
++
++	if (asfs_truncateblocksinfile(sb, bh, obj, inode->i_size) != 0) {
++		asfs_brelse(bh);
++		unlock_super(sb);
++		return;
++	}
++		
++	obj->object.file.size = cpu_to_be32(inode->i_size);
++	ASFS_I(inode)->mmu_private = inode->i_size;
++	ASFS_I(inode)->modified = TRUE;
++	inode->i_blocks = (be32_to_cpu(obj->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
++	asfs_bstore(sb, bh);
++	asfs_brelse(bh);
++
++	unlock_super(sb);
++}
++
++int asfs_file_open(struct inode *inode, struct file *filp)
++{
++	if (atomic_read(&filp->f_count) != 1)
++		return 0;
++	asfs_debug("ASFS: file open (node %d)\n", (int)inode->i_ino);
++	return 0;
++}
++
++int asfs_file_release(struct inode *inode, struct file *filp)
++{
++	int error = 0;
++
++	asfs_debug("ASFS: file release (node %d oc %d)\n", (int)inode->i_ino, atomic_read(&filp->f_count));
++
++	if (atomic_read(&filp->f_count) != 0)
++		return 0;
++
++	if (ASFS_I(inode)->modified == TRUE) {
++		struct buffer_head *bh;
++		struct fsObject *obj;
++		lock_super(inode->i_sb);
++
++		if ((error = asfs_readobject(inode->i_sb, inode->i_ino, &bh, &obj)) != 0) {
++			unlock_super(inode->i_sb);
++			return error;
++		}
++
++		obj->datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
++		if (inode->i_mode & S_IFREG) {
++			error = asfs_truncateblocksinfile(inode->i_sb, bh, obj, (u32)inode->i_size);
++			obj->object.file.size = cpu_to_be32(inode->i_size);
++			ASFS_I(inode)->mmu_private = inode->i_size;
++			inode->i_blocks = (be32_to_cpu(obj->object.file.size) + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
++		}
++		asfs_bstore(inode->i_sb, bh);
++
++		unlock_super(inode->i_sb);
++
++		asfs_brelse(bh);
++	}
++	ASFS_I(inode)->modified = FALSE;
++
++	return error;
++}
++
++#endif
+diff -urN linux-2.6.3/fs/asfs/inode.c linux-2.6.3-asfs-1.0b7/fs/asfs/inode.c
+--- linux-2.6.3/fs/asfs/inode.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/inode.c	2004-06-17 00:39:10.000000000 +0200
+@@ -0,0 +1,414 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *  
++ * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/smp_lock.h>
++#include <linux/time.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/dirent.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++
++/* Mapping from our types to the kernel */
++
++static struct address_space_operations asfs_aops = {
++	.readpage	= asfs_readpage,
++	.sync_page	= block_sync_page,
++	.bmap		= asfs_bmap,
++#ifdef CONFIG_ASFS_RW
++	.writepage	= asfs_writepage,
++	.prepare_write = asfs_prepare_write,
++	.commit_write = generic_commit_write,
++#endif
++};
++
++static struct file_operations asfs_file_operations = {
++	.llseek		= generic_file_llseek,
++	.read		= generic_file_read,
++	.mmap		= generic_file_mmap,
++#ifdef CONFIG_ASFS_RW
++	.write		= generic_file_write,
++	.open		= asfs_file_open,
++	.release	= asfs_file_release,
++	.fsync		= file_fsync,
++#endif
++};
++
++static struct file_operations asfs_dir_operations = {
++	.read		= generic_read_dir,
++	.readdir	= asfs_readdir,
++};
++
++static struct inode_operations asfs_dir_inode_operations = {
++	.lookup		= asfs_lookup,
++#ifdef CONFIG_ASFS_RW
++	.create		= asfs_create,
++	.unlink		= asfs_unlink,
++	.symlink	= asfs_symlink,
++	.mkdir		= asfs_mkdir,
++	.rmdir		= asfs_rmdir,
++	.rename		= asfs_rename,
++/*	.setattr	= asfs_notify_change,*/
++#endif
++};
++
++static struct inode_operations asfs_file_inode_operations = {
++#ifdef CONFIG_ASFS_RW
++	.truncate	= asfs_truncate,
++/*	.setattr		= asfs_notify_change,*/
++#endif
++};
++
++static struct address_space_operations asfs_symlink_aops = {
++	.readpage	= asfs_symlink_readpage,
++};
++
++static struct inode_operations asfs_symlink_inode_operations = {
++	.readlink	= page_readlink,
++	.follow_link	= page_follow_link,
++#ifdef CONFIG_ASFS_RW
++/*	.setattr	= asfs_notify_change,*/
++#endif
++};
++
++void asfs_read_locked_inode(struct inode *inode, void *arg)
++{
++	struct super_block *sb = inode->i_sb;
++	struct fsObject *obj = arg;
++
++	inode->i_mode = ASFS_SB(sb)->mode;
++	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = be32_to_cpu(obj->datemodified) + (365*8+2)*24*60*60;  
++	/* Linux: seconds since 01-01-1970, AmigaSFS: seconds since 01-01-1978 */
++	inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_atime.tv_nsec = 0;
++	inode->i_uid = ASFS_SB(sb)->uid;
++	inode->i_gid = ASFS_SB(sb)->gid;
++
++	asfs_debug("asfs_read_inode2: Setting-up node %lu... ", inode->i_ino);
++
++	if (obj->bits & OTYPE_DIR) {
++		asfs_debug("dir (FirstdirBlock: %u, HashTable %u)\n", \
++		           be32_to_cpu(obj->object.dir.firstdirblock), be32_to_cpu(obj->object.dir.hashtable));
++
++		inode->i_size = 0;
++		inode->i_op = &asfs_dir_inode_operations;
++		inode->i_fop = &asfs_dir_operations;
++		inode->i_mode |= S_IFDIR | ((inode->i_mode & 0400) ? 0100 : 0) | 
++		              ((inode->i_mode & 0040) ? 0010 : 0) | ((inode->i_mode & 0004) ? 0001 : 0);
++		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.dir.firstdirblock);
++		ASFS_I(inode)->hashtable = be32_to_cpu(obj->object.dir.hashtable);
++		ASFS_I(inode)->modified = 0;
++	} else if (obj->bits & OTYPE_LINK && !(obj->bits & OTYPE_HARDLINK)) {
++		asfs_debug("symlink\n");
++		inode->i_size = 0;
++		inode->i_op = &asfs_symlink_inode_operations;
++		inode->i_mapping->a_ops = &asfs_symlink_aops;
++		inode->i_mode |= S_IFLNK | S_IRWXUGO;
++		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
++	} else {
++		asfs_debug("file (Size: %u, FirstBlock: %u)\n", be32_to_cpu(obj->object.file.size), be32_to_cpu(obj->object.file.data));
++		inode->i_size = be32_to_cpu(obj->object.file.size);
++		inode->i_blocks = (be32_to_cpu(obj->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
++		inode->i_op = &asfs_file_inode_operations;
++		inode->i_fop = &asfs_file_operations;
++		inode->i_mapping->a_ops = &asfs_aops;
++		inode->i_mode |= S_IFREG;
++		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
++		ASFS_I(inode)->ext_cache.startblock = 0;
++		ASFS_I(inode)->ext_cache.key = 0;
++		ASFS_I(inode)->mmu_private = inode->i_size;
++	}
++	return;	
++}
++
++struct inode *asfs_get_root_inode(struct super_block *sb)
++{
++	struct inode *result = NULL;
++	struct fsObject *obj;
++	struct buffer_head *bh;
++
++	asfs_debug("asfs_get_root_inode\n");
++
++	if ((bh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
++		obj = &(((struct fsObjectContainer *)bh->b_data)->object[0]);
++		if (be32_to_cpu(obj->objectnode) > 0)
++			result = iget_locked(sb, be32_to_cpu(obj->objectnode));
++
++		if (result != NULL && result->i_state & I_NEW) {
++			asfs_read_locked_inode(result, obj);
++			unlock_new_inode(result);
++		}
++		asfs_brelse(bh);
++	}
++	return result;
++}
++
++#ifdef CONFIG_ASFS_RW
++
++static void asfs_sync_dir_inode(struct inode *dir, struct fsObject *obj)
++{
++	ASFS_I(dir)->firstblock = be32_to_cpu(obj->object.dir.firstdirblock);
++	ASFS_I(dir)->modified = 1;
++	dir->i_mtime = dir->i_atime = dir->i_ctime = CURRENT_TIME;
++	obj->datemodified = cpu_to_be32(dir->i_mtime.tv_sec - (365*8+2)*24*60*60);
++}
++
++enum { it_file, it_dir, it_link };
++
++static int asfs_create_object(struct inode *dir, struct dentry *dentry, int mode, int type, const char *symname)
++{
++	int error;
++	struct super_block *sb = dir->i_sb;
++	struct inode *inode;
++	struct buffer_head *bh, *dir_bh;
++	struct fsObject obj_data, *dir_obj, *obj;
++	u8 *name = (u8 *) dentry->d_name.name;
++
++	asfs_debug("asfs_create_obj %s in dir node %d\n", name, (int)dir->i_ino);
++
++	sb = dir->i_sb;
++	inode = new_inode(sb);
++	if (!inode)
++		return -ENOMEM;
++
++	memset(&obj_data, 0, sizeof(struct fsObject));
++
++	obj_data.protection = cpu_to_be32(FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
++	obj_data.datemodified = cpu_to_be32(inode->i_mtime.tv_sec - (365*8+2)*24*60*60);
++	switch (type) {
++	case it_dir:
++		obj_data.bits = OTYPE_DIR;
++		break;
++	case it_link:
++		obj_data.bits = OTYPE_LINK;
++		break;
++	default:
++		break;
++	}
++
++	lock_super(sb);
++
++	if ((error = asfs_readobject(sb, dir->i_ino, &dir_bh, &dir_obj)) != 0) {
++		dec_count(inode);
++		unlock_super(sb);
++		return error;
++	}
++
++	bh = dir_bh;
++	obj = dir_obj;
++
++	if ((error = asfs_createobject(sb, &bh, &obj, &obj_data, name, FALSE)) != 0) {
++		asfs_brelse(dir_bh);
++		dec_count(inode);
++		unlock_super(sb);
++		return error;
++	}
++
++	inode->i_ino = be32_to_cpu(obj->objectnode);
++	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
++	inode->i_size = inode->i_blocks = inode->i_blksize = 0;
++	inode->i_uid = dir->i_uid;
++	inode->i_gid = dir->i_gid;
++	inode->i_mode = mode | ASFS_SB(sb)->mode;
++
++	switch (type) {
++	case it_dir:
++		inode->i_mode |= S_IFDIR;
++		inode->i_op = &asfs_dir_inode_operations;
++		inode->i_fop = &asfs_dir_operations;
++		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.dir.firstdirblock);
++		ASFS_I(inode)->hashtable = be32_to_cpu(obj->object.dir.hashtable);
++		ASFS_I(inode)->modified = 0;
++		break;
++	case it_file:
++		inode->i_mode |= S_IFREG;
++		inode->i_op = &asfs_file_inode_operations;
++		inode->i_fop = &asfs_file_operations;
++		inode->i_mapping->a_ops = &asfs_aops;
++		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
++		ASFS_I(inode)->ext_cache.startblock = 0;
++		ASFS_I(inode)->ext_cache.key = 0;
++		ASFS_I(inode)->mmu_private = inode->i_size;
++		break;
++	case it_link:
++		inode->i_mode = S_IFLNK | S_IRWXUGO;
++		inode->i_op = &page_symlink_inode_operations;
++		inode->i_mapping->a_ops = &asfs_symlink_aops;
++		ASFS_I(inode)->firstblock = be32_to_cpu(obj->object.file.data);
++		error = asfs_write_symlink(inode, symname);
++		break;
++	default:
++		break;
++	}
++
++	asfs_bstore(sb, bh);
++	insert_inode_hash(inode);
++	mark_inode_dirty(inode);
++	d_instantiate(dentry, inode);
++	asfs_sync_dir_inode(dir, dir_obj);
++	asfs_bstore(sb, dir_bh); 
++
++	unlock_super(sb);
++	asfs_brelse(bh);
++	asfs_brelse(dir_bh);
++	
++	return error;
++}
++
++int asfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
++{
++	return asfs_create_object(dir, dentry, mode, it_file, NULL);
++}
++
++int asfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++	return asfs_create_object(dir, dentry, mode, it_dir, NULL);
++}
++
++int asfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
++{
++	return asfs_create_object(dir, dentry, 0, it_link, symname);
++}
++
++int asfs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++	asfs_debug("ASFS: %s\n", __FUNCTION__);
++
++	if (ASFS_I(dentry->d_inode)->firstblock != 0)
++		return -ENOTEMPTY;
++	
++	return asfs_unlink(dir, dentry);
++}
++
++int asfs_unlink(struct inode *dir, struct dentry *dentry)
++{
++	struct inode *inode = dentry->d_inode;
++	int error;
++	struct super_block *sb = dir->i_sb;
++	struct buffer_head *bh, *dir_bh;
++	struct fsObject *dir_obj, *obj;
++
++	asfs_debug("ASFS: %s\n", __FUNCTION__);
++
++	lock_super(sb);
++
++	if ((error = asfs_readobject(sb, inode->i_ino, &bh, &obj)) != 0) {
++		unlock_super(sb);
++		return error;
++	}
++	if ((error = asfs_deleteobject(sb, bh, obj)) != 0) {
++		asfs_brelse(bh);
++		unlock_super(sb);
++		return error;
++	}
++	asfs_brelse(bh);
++
++	/* directory data could change after removing the object */
++	if ((error = asfs_readobject(sb, dir->i_ino, &dir_bh, &dir_obj)) != 0) {
++		unlock_super(sb);
++		return error;
++	}
++
++	asfs_sync_dir_inode(dir, dir_obj);
++	asfs_bstore(sb, dir_bh); 
++
++	dec_count(inode);
++	unlock_super(sb);
++	asfs_brelse(dir_bh);
++
++	return 0;
++}
++
++int asfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
++{
++	struct super_block *sb = old_dir->i_sb;
++	struct buffer_head *src_bh, *old_bh, *new_bh;
++	int error;
++	struct fsObject *src_obj, *old_obj, *new_obj;
++
++	asfs_debug("ASFS: rename (old=%u,\"%*s\" to new=%u,\"%*s\")\n",
++		 (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
++		 (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
++
++	/* Unlink destination if it already exists */
++	if (new_dentry->d_inode) 
++		if ((error = asfs_unlink(new_dir, new_dentry)) != 0)
++			return error;
++
++	lock_super(sb);
++
++	if ((error = asfs_readobject(sb, old_dentry->d_inode->i_ino, &src_bh, &src_obj)) != 0) {
++		unlock_super(sb);
++		return error;
++	}
++	if ((error = asfs_readobject(sb, new_dir->i_ino, &new_bh, &new_obj)) != 0) {
++		asfs_brelse(src_bh);
++		unlock_super(sb);
++		return error;
++	}
++
++	if ((error = asfs_renameobject(sb, src_bh, src_obj, new_bh, new_obj, (u8 *) new_dentry->d_name.name)) != 0) {
++		asfs_brelse(src_bh);
++		asfs_brelse(new_bh);
++		unlock_super(sb);
++		return error;
++	}
++	asfs_brelse(src_bh);
++	asfs_brelse(new_bh);
++
++	if ((error = asfs_readobject(sb, old_dir->i_ino, &old_bh, &old_obj)) != 0) {
++		unlock_super(sb);
++		return error;
++	}
++	if ((error = asfs_readobject(sb, new_dir->i_ino, &new_bh, &new_obj)) != 0) {
++		asfs_brelse(old_bh);
++		unlock_super(sb);
++		return error;
++	}
++
++	asfs_sync_dir_inode(old_dir, old_obj);
++	asfs_sync_dir_inode(new_dir, new_obj);
++
++	asfs_bstore(sb, new_bh);	
++	asfs_bstore(sb, old_bh);
++
++	unlock_super(sb);
++	asfs_brelse(old_bh);
++	asfs_brelse(new_bh);
++
++	mark_inode_dirty(old_dir);
++	mark_inode_dirty(new_dir);
++
++	return 0;
++}
++
++/*
++int asfs_notify_change(struct dentry *dentry, struct iattr *attr)
++{
++	struct inode *inode = dentry->d_inode;
++	int error = 0;
++
++	asfs_debug("ASFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
++
++	error = inode_change_ok(inode,attr);
++
++	return error;
++}
++*/
++#endif
+diff -urN linux-2.6.3/fs/asfs/Makefile linux-2.6.3-asfs-1.0b7/fs/asfs/Makefile
+--- linux-2.6.3/fs/asfs/Makefile	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/Makefile	2004-06-09 21:23:40.000000000 +0200
+@@ -0,0 +1,8 @@
++#
++# Makefile for the linux asfs filesystem routines.
++#
++
++obj-$(CONFIG_ASFS_FS) += asfs.o
++
++asfs-y += dir.o extents.o file.o inode.o namei.o nodes.o objects.o super.o symlink.o
++asfs-$(CONFIG_ASFS_RW) += adminspace.o bitfuncs.o 
+diff -urN linux-2.6.3/fs/asfs/namei.c linux-2.6.3-asfs-1.0b7/fs/asfs/namei.c
+--- linux-2.6.3/fs/asfs/namei.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/namei.c	2004-06-10 01:41:51.000000000 +0200
+@@ -0,0 +1,155 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *
++ * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/string.h>
++#include "asfs_fs.h"
++
++static inline u8 asfs_upperchar(u8 c)
++{
++	if ((c >= 224 && c <= 254 && c != 247) || (c >= 'a' && c <= 'z'))
++		c -= 32;
++	return (c);
++}
++
++u8 asfs_lowerchar(u8 c)
++{
++	if ((c >= 192 && c <= 222 && c != 215) || (c >= 'A' && c <= 'Z'))
++		c += 32;
++	return (c);
++}
++
++/* Check if the name is valid for a asfs object. */
++
++static inline int asfs_check_name(const u8 *name, int len)
++{
++	int i;
++
++	if (len > ASFS_MAXFN)
++		return -ENAMETOOLONG;
++
++	for (i = 0; i < len; i++)
++		if (name[i] < ' ' || name[i] == ':' || (name[i] > 0x7e && name[i] < 0xa0))
++			return -EINVAL;
++
++	return 0;
++}
++
++/* Note: the dentry argument is the parent dentry. */
++
++static int asfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
++{
++	struct super_block *sb = dentry->d_inode->i_sb;
++	const u8 *name = qstr->name;
++	unsigned long hash;
++	int i;
++
++	i = asfs_check_name(qstr->name,qstr->len);
++	if (i)
++		return i;
++
++	hash = init_name_hash();
++
++	if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE)
++		for (i=qstr->len; i > 0; name++, i--)
++			hash = partial_name_hash(*name, hash);
++	else
++		for (i=qstr->len; i > 0; name++, i--)
++			hash = partial_name_hash(asfs_upperchar(*name), hash);
++
++	qstr->hash = end_name_hash(hash);
++
++	return 0;
++}
++
++static int asfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
++{
++	struct super_block *sb = dentry->d_inode->i_sb;
++	const u8 *aname = a->name;
++	const u8 *bname = b->name;
++	int len;
++
++	/* 'a' is the qstr of an already existing dentry, so the name
++	 * must be valid. 'b' must be validated first.
++	 */
++
++	if (asfs_check_name(b->name,b->len))
++		return 1;
++
++	if (a->len != b->len)
++		return 1;
++
++	if (ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE) {
++		for (len=a->len; len > 0; len--)
++			if (*aname++ != *bname++)
++				return 1;
++	} else {
++		for (len=a->len; len > 0; len--)
++			if (asfs_upperchar(*aname++) != asfs_upperchar(*bname++))
++				return 1;
++	}
++
++	return 0;
++}
++
++struct dentry_operations asfs_dentry_operations = {
++	d_hash:		asfs_hash_dentry,
++	d_compare:	asfs_compare_dentry,
++};
++
++int asfs_namecmp(u8 *s, u8 *ct, int casesensitive)
++{
++	if (casesensitive) {
++		while (*s == *ct && *ct != '\0' && *ct != '/') {
++			s++;
++			ct++;
++		}
++	} else {
++		while (asfs_upperchar(*s) == asfs_upperchar(*ct) && *ct != '\0'
++		       && *ct != '/') {
++			s++;
++			ct++;
++		}
++	}
++	return (*s == '\0' && (*ct == '\0' || *ct == '/')) ? 0 : *ct - *s;
++}
++
++u16 asfs_hash(u8 *name, int casesensitive)
++{
++	u16 hashval = 0;
++	while (name[hashval] != 0 && name[hashval] != '/')
++		hashval++;
++	if (casesensitive) {
++		u8 c = *name;
++		while (c != 0 && c != '/') {
++			hashval = hashval * 13 + c;
++			c = *++name;
++		}
++	} else {
++		u8 c = *name;
++		while (c != 0 && c != '/') {
++			hashval = hashval * 13 + asfs_upperchar(c);
++			c = *++name;
++		}
++	}
++	return hashval;
++}
++
+diff -urN linux-2.6.3/fs/asfs/nodes.c linux-2.6.3-asfs-1.0b7/fs/asfs/nodes.c
+--- linux-2.6.3/fs/asfs/nodes.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/nodes.c	2004-06-10 01:41:46.000000000 +0200
+@@ -0,0 +1,455 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *
++ * This file contains some parts of the original amiga version of 
++ * SmartFilesystem source code.
++ *
++ * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
++ * Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
++ * 
++ * Adapted and modified by Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++
++/* Finds a specific node by number. */
++int asfs_getnode(struct super_block *sb, u32 nodeno, struct buffer_head **ret_bh, struct fsObjectNode **ret_node)
++{
++	struct buffer_head *bh;
++	struct fsNodeContainer *nodecont;
++	u32 nodeindex = ASFS_SB(sb)->objectnoderoot;
++
++	while ((bh = asfs_breadcheck(sb, nodeindex, ASFS_NODECONTAINER_ID))) {
++		nodecont = (struct fsNodeContainer *) bh->b_data;
++
++		if (be32_to_cpu(nodecont->nodes) == 1) {
++			*ret_node = (struct fsObjectNode *) ((u8 *) nodecont->node + NODE_STRUCT_SIZE * (nodeno - be32_to_cpu(nodecont->nodenumber)));
++			*ret_bh = bh;
++			return 0;
++		} else {
++			u16 containerentry = (nodeno - be32_to_cpu(nodecont->nodenumber)) / be32_to_cpu(nodecont->nodes);
++			nodeindex = be32_to_cpu(nodecont->node[containerentry]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
++		}
++		asfs_brelse(bh);
++	}
++	if (bh == NULL)
++		return -EIO;
++	return -ENOENT;
++}
++
++#ifdef CONFIG_ASFS_RW
++
++	/* Looks for the parent of the passed-in buffer_head (fsNodeContainer)
++	   starting from the root.  It returns an error if any error occured.
++	   If error is 0 and io_bh is NULL as well, then there was no parent (ie,
++	   you asked parent of the root).  Otherwise io_bh should contain the
++	   parent of the passed-in NodeContainer. */
++
++static int parentnodecontainer(struct super_block *sb, struct buffer_head **io_bh)
++{
++	u32 noderoot = ASFS_SB(sb)->objectnoderoot;
++	u32 childblock = be32_to_cpu(((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock);
++	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) (*io_bh)->b_data)->nodenumber);
++	int errorcode = 0;
++
++	if (noderoot == childblock) {
++		*io_bh = NULL;
++		return 0;
++	}
++
++	while ((*io_bh = asfs_breadcheck(sb, noderoot, ASFS_NODECONTAINER_ID))) {
++		struct fsNodeContainer *nc = (void *) (*io_bh)->b_data;
++
++		if (be32_to_cpu(nc->nodes) == 1) {
++			/* We've descended the tree to a leaf NodeContainer, something
++			   which should never happen if the passed-in io_bh had
++			   contained a valid fsNodeContainer. */
++			printk("ASFS: Failed to locate the parent NodeContainer - node tree is corrupted!\n");
++			*io_bh = NULL;
++			return -EIO;
++		} else {
++			u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
++			noderoot = be32_to_cpu(nc->node[containerentry]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
++		}
++
++		if (noderoot == childblock)
++			break;
++
++		asfs_brelse(*io_bh);
++	}
++
++	if (*io_bh == NULL)
++		return -EIO;
++
++	return errorcode;
++}
++
++
++static int isfull(struct super_block *sb, struct fsNodeContainer *nc)
++{
++	u32 *p = nc->node;
++	s16 n = NODECONT_BLOCK_COUNT;
++
++	while (--n >= 0) {
++		if (*p == 0 || (be32_to_cpu(*p) & 0x00000001) == 0) {
++			break;
++		}
++		p++;
++	}
++
++	return n < 0;
++}
++
++static int markparentfull(struct super_block *sb, struct buffer_head *bh)
++{
++	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) (bh->b_data))->nodenumber);
++	int errorcode;
++
++	if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
++		struct fsNodeContainer *nc = (void *) bh->b_data;
++		u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
++
++		nc->node[containerentry] = cpu_to_be32(be32_to_cpu(nc->node[containerentry]) | 0x00000001);
++
++		asfs_bstore(sb, bh);
++
++		if (isfull(sb, nc)) {	/* This container now is full as well!  Mark the next higher up container too then! */
++			return markparentfull(sb, bh);
++		}
++		asfs_brelse(bh);
++	}
++
++	return errorcode;
++}
++
++static int addnewnodelevel(struct super_block *sb, u16 nodesize)
++{
++	struct buffer_head *bh;
++	u32 noderoot = ASFS_SB(sb)->objectnoderoot;
++	int errorcode;
++
++	/* Adds a new level to the Node tree. */
++
++	asfs_debug("addnewnodelevel: Entry\n");
++
++	if ((bh = asfs_breadcheck(sb, noderoot, ASFS_NODECONTAINER_ID))) {
++		struct buffer_head *newbh;
++		u32 newblock;
++
++		if ((errorcode = asfs_allocadminspace(sb, &newblock)) == 0 && (newbh = asfs_getzeroblk(sb, newblock))) {
++			struct fsNodeContainer *nc = (void *) bh->b_data;
++			struct fsNodeContainer *newnc = (void *) newbh->b_data;
++
++			/* The newly allocated block will become a copy of the current root. */
++
++			newnc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
++			newnc->bheader.ownblock = cpu_to_be32(newblock);
++			newnc->nodenumber = nc->nodenumber;
++			newnc->nodes = nc->nodes;
++			memcpy(newnc->node, nc->node, sb->s_blocksize - sizeof(struct fsNodeContainer));
++
++			asfs_bstore(sb, newbh);
++			asfs_brelse(newbh);
++
++			/* The current root will now be transformed into a new root. */
++
++			if (be32_to_cpu(nc->nodes) == 1)
++				nc->nodes = cpu_to_be32((sb->s_blocksize - sizeof(struct fsNodeContainer)) / nodesize);
++			else
++				nc->nodes = cpu_to_be32(be32_to_cpu(nc->nodes) * NODECONT_BLOCK_COUNT);
++
++			nc->node[0] = cpu_to_be32((newblock << (sb->s_blocksize_bits - ASFS_BLCKFACCURACY)) + 1);	/* Tree is full from that point! */
++			memset(&nc->node[1], 0, sb->s_blocksize - sizeof(struct fsNodeContainer) - 4);
++
++			asfs_bstore(sb, bh);
++		}
++		asfs_brelse(bh);
++	} else
++		errorcode = -EIO;
++
++	return errorcode;
++}
++
++static int createnodecontainer(struct super_block *sb, u32 nodenumber, u32 nodes, u32 * returned_block)
++{
++	struct buffer_head *bh;
++	int errorcode;
++	u32 newblock;
++
++	asfs_debug("createnodecontainer: nodenumber = %u, nodes = %u\n", nodenumber, nodes);
++
++	if ((errorcode = asfs_allocadminspace(sb, &newblock)) == 0 && (bh = asfs_getzeroblk(sb, newblock))) {
++		struct fsNodeContainer *nc = (void *) bh->b_data;
++
++		nc->bheader.id = cpu_to_be32(ASFS_NODECONTAINER_ID);
++		nc->bheader.ownblock = cpu_to_be32(newblock);
++
++		nc->nodenumber = cpu_to_be32(nodenumber);
++		nc->nodes = cpu_to_be32(nodes);
++
++		asfs_bstore(sb, bh);
++		asfs_brelse(bh);
++		*returned_block = newblock;
++	}
++
++	return errorcode;
++}
++
++	/* This function creates a new fsNode structure in a fsNodeContainer.  If needed
++	   it will create a new fsNodeContainers and a new fsNodeIndexContainer. */
++
++int asfs_createnode(struct super_block *sb, struct buffer_head **returned_bh, struct fsNode **returned_node, u32 * returned_nodeno)
++{
++	u16 nodecount = (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE;
++	u32 noderoot = ASFS_SB(sb)->objectnoderoot;
++	u32 nodeindex = noderoot;
++	int errorcode = 0;
++
++	while ((*returned_bh = asfs_breadcheck(sb, nodeindex, ASFS_NODECONTAINER_ID))) {
++		struct fsNodeContainer *nc = (void *) (*returned_bh)->b_data;
++
++		if (be32_to_cpu(nc->nodes) == 1) {	/* Is it a leaf-container? */
++			struct fsNode *n;
++			s16 i = nodecount;
++
++			n = (struct fsNode *) nc->node;
++
++			while (i-- > 0) {
++				if (n->data == 0)
++					break;
++
++				n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
++			}
++
++			if (i >= 0) {
++				/* Found an empty fsNode structure! */
++				*returned_node = n;
++				*returned_nodeno = be32_to_cpu(nc->nodenumber) + ((u8 *) n - (u8 *) nc->node) / NODE_STRUCT_SIZE;
++
++				asfs_debug("createnode: Created Node %d\n", *returned_nodeno);
++
++				/* Below we continue to look through the NodeContainer block.  We skip the entry
++				   we found to be unused, and see if there are any more unused entries.  If we
++				   do not find any more unused entries then this container is now full. */
++
++				n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
++
++				while (i-- > 0) {
++					if (n->data == 0)
++						break;
++
++					n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
++				}
++
++				if (i < 0) {
++					/* No more empty fsNode structures in this block.  Mark parent full. */
++					errorcode = markparentfull(sb, *returned_bh);
++				}
++
++				return errorcode;
++			} else {
++				/* What happened now is that we found a leaf-container which was
++				   completely filled.  In practice this should only happen when there
++				   is only a single NodeContainer (only this container), or when there
++				   was an error in one of the full-bits in a higher level container. */
++
++				if (noderoot != nodeindex) {
++					/*** Hmmm... it looks like there was a damaged full-bit or something.
++					     In this case we'd probably better call markcontainerfull. */
++
++					printk("ASFS: Couldn't find empty Node in NodeContainer while NodeIndexContainer indicated there should be one!\n");
++
++					errorcode = -ENOSPC;
++					break;
++				} else {
++					/* Container is completely filled. */
++
++					if ((errorcode = addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
++						return errorcode;
++
++					nodeindex = noderoot;
++				}
++			}
++		} else {	/* This isn't a leaf container */
++			u32 *p = nc->node;
++			s16 i = NODECONT_BLOCK_COUNT;
++
++			/* We've read a normal container */
++
++			while (i-- > 0) {
++				if (*p != 0 && (be32_to_cpu(*p) & 0x00000001) == 0)
++					break;
++
++				p++;
++			}
++
++			if (i >= 0) {
++				/* Found a not completely filled Container */
++
++				nodeindex = be32_to_cpu(*p) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY);
++			} else {
++				/* Everything in the NodeIndexContainer was completely filled.  There possibly
++				   are some unused pointers in this block however.  */
++
++				asfs_debug("createnode: NodeContainer at block has no empty Nodes.\n");
++
++				p = nc->node;
++				i = NODECONT_BLOCK_COUNT;
++
++				while (i-- > 0) {
++					if (*p == 0)
++						break;
++
++					p++;
++				}
++
++				if (i >= 0) {
++					u32 newblock;
++					u32 nodes;
++
++					/* Found an unused Container pointer */
++
++					if (be32_to_cpu(nc->nodes) == (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE) {
++						nodes = 1;
++					} else {
++						nodes = be32_to_cpu(nc->nodes) / NODECONT_BLOCK_COUNT;
++					}
++
++					if ((errorcode = createnodecontainer(sb, be32_to_cpu(nc->nodenumber) + (p - nc->node) * be32_to_cpu(nc->nodes), nodes, &newblock)) != 0) {
++						break;
++					}
++
++					*p = cpu_to_be32(newblock << (sb->s_blocksize_bits - ASFS_BLCKFACCURACY));
++
++					asfs_bstore(sb, *returned_bh);
++				} else {
++					/* Container is completely filled.  This must be the top-level NodeIndex container
++					   as otherwise the full-bit would have been wrong! */
++
++					if ((errorcode = addnewnodelevel(sb, NODE_STRUCT_SIZE)) != 0)
++						break;
++
++					nodeindex = noderoot;
++				}
++			}
++		}
++		asfs_brelse(*returned_bh);
++	}
++
++	if (*returned_bh == NULL)
++		return -EIO;
++
++	return (errorcode);
++}
++
++static int markparentempty(struct super_block *sb, struct buffer_head *bh)
++{
++	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) bh->b_data)->nodenumber);
++	int errorcode;
++
++	if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != 0) {
++		struct fsNodeContainer *nc = (void *) bh->b_data;
++		int wasfull;
++		u16 containerentry = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
++
++		wasfull = isfull(sb, nc);
++
++		nc->node[containerentry] = cpu_to_be32(be32_to_cpu(nc->node[containerentry]) & ~0x00000001);
++
++		asfs_bstore(sb, bh);
++
++		if (wasfull) {
++			/* This container was completely full before!  Mark the next higher up container too then! */
++			return markparentempty(sb, bh);
++		}
++		asfs_brelse(bh);
++	}
++
++	return errorcode;
++}
++
++static int freecontainer(struct super_block *sb, struct buffer_head *bh)
++{
++	u32 nodenumber = be32_to_cpu(((struct fsNodeContainer *) bh->b_data)->nodenumber);
++	int errorcode;
++
++	if ((errorcode = parentnodecontainer(sb, &bh)) == 0 && bh != NULL) {	/* This line also prevents the freeing of the noderoot. */
++		struct fsNodeContainer *nc = (void *) bh->b_data;
++		u16 containerindex = (nodenumber - be32_to_cpu(nc->nodenumber)) / be32_to_cpu(nc->nodes);
++
++		if ((errorcode = asfs_freeadminspace(sb, be32_to_cpu(nc->node[containerindex]) >> (sb->s_blocksize_bits - ASFS_BLCKFACCURACY))) == 0) {
++			u32 *p = nc->node;
++			s16 n = NODECONT_BLOCK_COUNT;
++
++			nc->node[containerindex] = 0;
++			asfs_bstore(sb, bh);
++
++			while (n-- > 0)
++				if (*p++ != 0)
++					break;
++
++			if (n < 0) {	/* This container is now completely empty!  Free this NodeIndexContainer too then! */
++				return freecontainer(sb, bh);
++			}
++		}
++		asfs_brelse(bh);
++	}
++
++	return errorcode;
++}
++
++static int internaldeletenode(struct super_block *sb, struct buffer_head *bh, struct fsNode *n)
++{
++	struct fsNodeContainer *nc = (void *) bh->b_data;
++	u16 nodecount = (sb->s_blocksize - sizeof(struct fsNodeContainer)) / NODE_STRUCT_SIZE;
++	s16 i = nodecount;
++	s16 empty = 0;
++	int errorcode = 0;
++
++	n->data = 0;
++	n = (struct fsNode *) nc->node;
++
++	while (i-- > 0) {
++		if (n->data == 0)
++			empty++;
++
++		n = (struct fsNode *) ((u8 *) n + NODE_STRUCT_SIZE);
++	}
++
++	asfs_bstore(sb, bh);
++
++	if (empty == 1)		/* NodeContainer was completely full before, so we need to mark it empty now. */
++		errorcode = markparentempty(sb, bh);
++	else if (empty == nodecount)	/* NodeContainer is now completely empty!  Free it! */
++		errorcode = freecontainer(sb, bh);
++
++	return (errorcode);
++}
++
++int asfs_deletenode(struct super_block *sb, u32 objectnode)
++{
++	struct buffer_head *bh;
++	struct fsObjectNode *on;
++	int errorcode;
++
++	asfs_debug("deletenode: Deleting Node %d\n", objectnode);
++
++	if ((errorcode = asfs_getnode(sb, objectnode, &bh, &on)) == 0)
++		errorcode = internaldeletenode(sb, bh, (struct fsNode *) on);
++
++	asfs_brelse(bh);
++	return (errorcode);
++}
++
++#endif
+diff -urN linux-2.6.3/fs/asfs/objects.c linux-2.6.3-asfs-1.0b7/fs/asfs/objects.c
+--- linux-2.6.3/fs/asfs/objects.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/objects.c	2004-06-10 17:16:10.000000000 +0200
+@@ -0,0 +1,765 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *
++ * This file contains some parts of the original amiga version of 
++ * SmartFilesystem source code.
++ *
++ * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
++ * Ralph Schmidt, Emmanuel Lesueur, David Gerber, and Marcin Kurek
++ * 
++ * Adapted and modified by Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++
++struct fsObject *asfs_nextobject(struct fsObject *obj)
++{
++	int i;
++	u8 *p = obj->name;
++
++	for (i = 2; i > 0; p++)
++		if (*p == '\0')
++			i--;
++	if ((p - (u8 *) obj) & 0x01)
++		p++;
++
++	return ((struct fsObject *) p);
++}
++
++struct fsObject *asfs_find_obj_by_name(struct super_block *sb, struct fsObjectContainer *objcont, u8 * name)
++{
++	struct fsObject *obj;
++
++	obj = &(objcont->object[0]);
++	while (be32_to_cpu(obj->objectnode) > 0 && ((char *) obj - (char *) objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
++		if (asfs_namecmp(obj->name, name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE) == 0) {
++			asfs_debug("Object found! Node %u, Name %s, Type %x, inCont %u\n", be32_to_cpu(obj->objectnode), obj->name, obj->bits, be32_to_cpu(objcont->bheader.ownblock));
++			return obj;
++		}
++		obj = asfs_nextobject(obj);
++	}
++	return NULL;
++}
++
++#ifdef CONFIG_ASFS_RW
++
++struct fsObject *find_obj_by_node(struct super_block *sb, struct fsObjectContainer *objcont, u32 objnode)
++{
++	struct fsObject *obj;
++
++	obj = &(objcont->object[0]);
++	while (be32_to_cpu(obj->objectnode) > 0 && ((char *) obj - (char *) objcont) + sizeof(struct fsObject) + 2 < sb->s_blocksize) {
++		if (be32_to_cpu(obj->objectnode) == objnode) {
++			return obj;
++		}
++		obj = asfs_nextobject(obj);
++	}
++	return NULL;
++}
++
++int asfs_readobject(struct super_block *sb, u32 objectnode, struct buffer_head **bh, struct fsObject **returned_object)
++{
++	struct fsObjectNode *on;
++	int errorcode;
++	u32 contblock;
++
++	asfs_debug("Seaching object - node %d\n", objectnode);
++
++	if ((errorcode = asfs_getnode(sb, objectnode, bh, &on)) != 0)
++		return errorcode;
++	contblock = be32_to_cpu(on->node.data);
++	asfs_brelse(*bh);
++
++	if (contblock > 0 && (*bh = asfs_breadcheck(sb, contblock, ASFS_OBJECTCONTAINER_ID))) {
++		*returned_object = find_obj_by_node(sb, (void *) (*bh)->b_data, objectnode);
++		if (*returned_object == NULL) {
++			brelse(*bh);
++			*bh = NULL;
++			return -ENOENT;
++		}
++		return 0;
++	} else
++		return -EIO;
++}
++
++static int removeobjectcontainer(struct super_block *sb, struct buffer_head *bh)
++{
++	struct fsObjectContainer *oc = (void *) bh->b_data;
++	int errorcode;
++	struct buffer_head *block;
++
++	asfs_debug("removeobjectcontainer: block %u\n", be32_to_cpu(oc->bheader.ownblock));
++
++	if (oc->next != 0 && oc->next != oc->bheader.ownblock) {
++		struct fsObjectContainer *next_oc;
++
++		if ((block = asfs_breadcheck(sb, be32_to_cpu(oc->next), ASFS_OBJECTCONTAINER_ID)) == NULL)
++			return -EIO;
++
++		next_oc = (void *) block->b_data;
++		next_oc->previous = oc->previous;
++
++		asfs_bstore(sb, block);
++		asfs_brelse(block);
++	}
++
++	if (oc->previous != 0 && oc->previous != oc->bheader.ownblock) {
++		struct fsObjectContainer *previous_oc;
++
++		if ((block = asfs_breadcheck(sb, be32_to_cpu(oc->previous), ASFS_OBJECTCONTAINER_ID)) == NULL)
++			return -EIO;
++
++		previous_oc = (void *) block->b_data;
++		previous_oc->next = oc->next;
++
++		asfs_bstore(sb, block);
++		asfs_brelse(block);
++	} else {
++		struct fsObject *parent_o;
++
++		if ((errorcode = asfs_readobject(sb, be32_to_cpu(oc->parent), &block, &parent_o)) != 0)
++			return (errorcode);
++
++		parent_o->object.dir.firstdirblock = oc->next;
++
++		asfs_bstore(sb, block);
++		asfs_brelse(block);
++	}
++
++	if ((errorcode = asfs_freeadminspace(sb, be32_to_cpu(oc->bheader.ownblock))) != 0)
++		return (errorcode);
++
++	return (0);
++}
++
++static int setrecycledinfodiff(struct super_block *sb, s32 deletedfiles, s32 deletedblocks)
++{
++	struct buffer_head *bh;
++
++	if ((bh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
++		struct fsRootInfo *ri = (struct fsRootInfo *) ((u8 *) bh->b_data + sb->s_blocksize - sizeof(struct fsRootInfo));
++
++		ri->deletedfiles = cpu_to_be32(be32_to_cpu(ri->deletedfiles) + deletedfiles);
++		ri->deletedblocks = cpu_to_be32(be32_to_cpu(ri->deletedblocks) + deletedblocks);
++
++		asfs_bstore(sb, bh);
++		asfs_brelse(bh);
++	} else
++		return -EIO;
++	return 0;
++}
++
++	/* This function removes the fsObject structure passed in from the passed
++	   buffer_head.  If the ObjectContainer becomes completely empty it will be 
++	   delinked from the ObjectContainer chain and marked free for reuse.
++	   This function doesn't delink the object from the hashchain! */
++
++static int simpleremoveobject(struct super_block *sb, struct buffer_head *bh, struct fsObject *o)
++{
++	struct fsObjectContainer *oc = (void *) bh->b_data;
++	int errorcode = 0;
++
++	asfs_debug("simpleremoveobject:\n");
++
++	if (be32_to_cpu(oc->parent) == ASFS_RECYCLEDNODE) {
++		/* This object is removed from the Recycled directory. */
++		if ((errorcode = setrecycledinfodiff(sb, -1, -((be32_to_cpu(o->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits))) != 0)
++			return errorcode;
++	}
++
++	if ((asfs_nextobject(oc->object))->name[0] == '\0')
++		errorcode = removeobjectcontainer(sb, bh);
++	else {
++		struct fsObject *nexto;
++		int objlen;
++
++		nexto = asfs_nextobject(o);
++		objlen = (u8 *) nexto - (u8 *) o;
++
++		memmove(o, nexto, sb->s_blocksize - ((u8 *) nexto - (u8 *) oc));
++		memset((u8 *) oc + sb->s_blocksize - objlen, 0, objlen);
++
++		asfs_bstore(sb, bh);
++	}
++	return errorcode;
++}
++
++/* This function delinks the passed in ObjectNode from its hash-chain.  Handy when deleting
++   the object, or when renaming/moving it. */
++
++static int dehashobjectquick(struct super_block *sb, u32 objectnode, u8 *name, u32 parentobjectnode)
++{
++	struct fsObject *o;
++	int errorcode;
++	struct buffer_head *block;
++
++	asfs_debug("dehashobject: Delinking object %d (=ObjectNode) from hashchain. Parentnode = %d\n", objectnode, parentobjectnode);
++
++	if ((errorcode = asfs_readobject(sb, parentobjectnode, &block, &o)) == 0 && o->object.dir.hashtable != 0) {
++		u32 hashtable = be32_to_cpu(o->object.dir.hashtable);
++		asfs_brelse(block);
++
++		if ((block = asfs_breadcheck(sb, hashtable, ASFS_HASHTABLE_ID))) {
++			struct buffer_head *node_bh;
++			struct fsObjectNode *onptr, on;
++			struct fsHashTable *ht = (void *) block->b_data;
++			u32 nexthash;
++
++			if ((errorcode = asfs_getnode(sb, objectnode, &node_bh, &onptr)) == 0) {
++				u16 hashchain;
++
++				asfs_debug("dehashobject: Read HashTable block of parent object of object to be delinked\n");
++
++				hashchain = HASHCHAIN(asfs_hash(name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE));
++				nexthash = be32_to_cpu(ht->hashentry[hashchain]);
++
++				if (nexthash == objectnode) {
++					/* The hashtable directly points to the fsObject to be delinked.  We simply
++					   modify the Hashtable to point to the new nexthash entry. */
++
++					asfs_debug("dehashobject: The hashtable points directly to the to be delinked object\n");
++
++					ht->hashentry[hashchain] = onptr->next;
++					asfs_bstore(sb, block);
++				} else {
++					struct fsObjectNode *onsearch = 0;
++
++					on = *onptr;
++
++					asfs_debug("dehashobject: Walking through hashchain\n");
++
++					while (nexthash != 0 && nexthash != objectnode) {
++						asfs_brelse(node_bh);
++						if ((errorcode = asfs_getnode(sb, nexthash, &node_bh, &onsearch)) != 0)
++							break;
++						nexthash = be32_to_cpu(onsearch->next);
++					}
++
++					if (errorcode == 0) {
++						if (nexthash != 0) {
++							/* Previous fsObjectNode found in hash chain.  Modify the fsObjectNode to 'skip' the
++							   ObjectNode which is being delinked from the hash chain. */
++
++							onsearch->next = on.next;
++							asfs_bstore(sb, node_bh);
++						} else {
++							printk("ASFS: Hashchain of object %d is corrupt or incorrectly linked.", objectnode);
++
++							/*** This is strange.  We have been looking for the fsObjectNode which is located before the
++							     passed in fsObjectNode in the hash-chain.  However, we never found the
++							     fsObjectNode reffered to in the hash-chain!  Has to be somekind
++							     of internal error... */
++
++							errorcode = -ENOENT;
++						}
++					}
++				}
++				asfs_brelse(node_bh);
++			}
++			asfs_brelse(block);
++		}
++	}
++	return errorcode;
++}
++
++
++	/* This function removes an object from any directory.  It takes care
++	   of delinking the object from the hashchain and also frees the
++	   objectnode number. */
++
++static int removeobject(struct super_block *sb, struct buffer_head *bh, struct fsObject *o)
++{
++	struct fsObjectContainer *oc = (void *) bh->b_data;
++	int errorcode;
++
++	asfs_debug("removeobject\n");
++
++	if ((errorcode = dehashobjectquick(sb, be32_to_cpu(o->objectnode), o->name, be32_to_cpu(oc->parent))) == 0) {
++		u32 objectnode = be32_to_cpu(o->objectnode);
++
++		if ((errorcode = simpleremoveobject(sb, bh, o)) == 0)
++			errorcode = asfs_deletenode(sb, objectnode);
++	}
++
++	return (errorcode);
++}
++
++	/* This function deletes the specified object. */
++int asfs_deleteobject(struct super_block *sb, struct buffer_head *bh, struct fsObject *o)
++{
++	int errorcode = 0;
++
++	asfs_debug("deleteobject: Entry -- deleting object %d (%s)\n", be32_to_cpu(o->objectnode), o->name);
++
++	if ((o->bits & OTYPE_DIR) == 0 || o->object.dir.firstdirblock == 0) {
++		u8 bits = o->bits;
++		u32 hashblckno = be32_to_cpu(o->object.dir.hashtable);
++		u32 extentbnode = be32_to_cpu(o->object.file.data);
++
++		if ((errorcode = removeobject(sb, bh, o)) == 0) {
++			if ((bits & OTYPE_LINK) != 0) {
++				asfs_debug("deleteobject: Object is soft link!\n");
++				errorcode = asfs_freeadminspace(sb, extentbnode);
++			} else if ((bits & OTYPE_DIR) != 0) {
++				asfs_debug("deleteobject: Object is a directory!\n");
++				errorcode = asfs_freeadminspace(sb, hashblckno);
++			} else {
++				asfs_debug("deleteobject: Object is a file\n");
++				if (extentbnode != 0)
++					errorcode = asfs_deleteextents(sb, extentbnode);
++			}
++		}
++	}
++
++	return (errorcode);
++}
++
++	/* This function takes a HashBlock pointer, an ObjectNode and an ObjectName.
++	   If there is a hashblock, then this function will correctly link the object
++	   into the hashchain.  If there isn't a hashblock (=0) then this function
++	   does nothing.  */
++
++static int hashobject(struct super_block *sb, u32 hashblock, struct fsObjectNode *on, u32 nodeno, u8 *objectname)
++{
++	struct buffer_head *hash_bh;
++
++	asfs_debug("hashobject, using hashblock %d\n", hashblock);
++	if (hashblock == 0)
++		return 0;
++
++	if ((hash_bh = asfs_breadcheck(sb, hashblock, ASFS_HASHTABLE_ID))) {
++		struct fsHashTable *ht = (void *) hash_bh->b_data;
++		u32 nexthash;
++		u16 hashvalue, hashchain;
++
++		hashvalue = asfs_hash(objectname, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE);
++		hashchain = HASHCHAIN(hashvalue);
++		nexthash = be32_to_cpu(ht->hashentry[hashchain]);
++
++		ht->hashentry[hashchain] = cpu_to_be32(nodeno);
++
++		asfs_bstore(sb, hash_bh);
++		asfs_brelse(hash_bh);
++
++		on->next = cpu_to_be32(nexthash);
++		on->hash16 = cpu_to_be16(hashvalue);
++	} else
++		return -EIO;
++
++	return 0;
++}
++
++	/* This function returns a pointer to the first unused byte in
++	   an ObjectContainer. */
++
++static u8 *emptyspaceinobjectcontainer(struct super_block *sb, struct fsObjectContainer *oc)
++{
++	struct fsObject *o = oc->object;
++	u8 *endadr;
++
++	endadr = (u8 *) oc + sb->s_blocksize - sizeof(struct fsObject) - 2;
++
++	while ((u8 *) o < endadr && o->name[0] != 0)
++		o = asfs_nextobject(o);
++
++	return (u8 *) o;
++}
++
++	/* This function will look in the directory indicated by io_o
++	   for an ObjectContainer block which contains bytesneeded free
++	   bytes.  If none is found then this function simply creates a
++	   new ObjectContainer and adds that to the indicated directory. */
++
++static int findobjectspace(struct super_block *sb, struct buffer_head **io_bh, struct fsObject **io_o, u32 bytesneeded)
++{
++	struct buffer_head *bhparent = *io_bh;
++	struct fsObject *oparent = *io_o;
++	struct buffer_head *bh;
++	u32 nextblock = be32_to_cpu(oparent->object.dir.firstdirblock);
++	int errorcode = 0;
++
++	asfs_debug("findobjectspace: Looking for %u bytes in directory with ObjectNode number %d (in block %d)\n", bytesneeded, be32_to_cpu((*io_o)->objectnode),
++		   be32_to_cpu(((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock));
++
++	while (nextblock != 0 && (bh = asfs_breadcheck(sb, nextblock, ASFS_OBJECTCONTAINER_ID))) {
++		struct fsObjectContainer *oc = (void *) bh->b_data;
++		u8 *emptyspace;
++
++		/* We need to find out how much free space this ObjectContainer has */
++
++		emptyspace = emptyspaceinobjectcontainer(sb, oc);
++
++		if ((u8 *) oc + sb->s_blocksize - emptyspace >= bytesneeded) {
++			/* We found enough space in one of the ObjectContainer blocks!!
++			   We return a struct fsObject *. */
++			*io_bh = bh;
++			*io_o = (struct fsObject *) emptyspace;
++			break;
++		}
++		nextblock = be32_to_cpu(oc->next);
++		asfs_brelse(bh);
++	}
++
++	if (nextblock == 0) {
++		u32 newcontblock;
++		/* If we get here, we traversed the *entire* directory (ough!) and found no empty
++		   space large enough for our entry.  We allocate new space and add it to this
++		   directory. */
++
++		if ((errorcode = asfs_allocadminspace(sb, &newcontblock)) == 0 && (bh = asfs_getzeroblk(sb, newcontblock))) {
++			struct fsObjectContainer *oc = (void *) bh->b_data;
++			struct buffer_head *bhnext;
++
++			asfs_debug("findobjectspace: No room was found, allocated new block at %u\n", newcontblock);
++
++			/* Allocated new block.  We will now link it to the START of the directory chain
++			   so the new free space can be found quickly when more entries need to be added. */
++
++			oc->bheader.id = cpu_to_be32(ASFS_OBJECTCONTAINER_ID);
++			oc->bheader.ownblock = cpu_to_be32(newcontblock);
++			oc->parent = oparent->objectnode;
++			oc->next = oparent->object.dir.firstdirblock;
++			oc->previous = 0;
++
++			oparent->object.dir.firstdirblock = cpu_to_be32(newcontblock);
++
++			asfs_bstore(sb, bhparent);
++
++			if (oc->next != 0 && (bhnext = asfs_breadcheck(sb, be32_to_cpu(oc->next), ASFS_OBJECTCONTAINER_ID))) {
++				struct fsObjectContainer *ocnext = (void *) bhnext->b_data;
++				ocnext->previous = cpu_to_be32(newcontblock);
++				asfs_bstore(sb, bhnext);
++				asfs_brelse(bhnext);
++			}
++
++			*io_bh = bh;
++			*io_o = oc->object;
++		}
++	}
++
++	asfs_debug("findobjectspace: new object will be in container block %u\n", be32_to_cpu(((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock));
++
++	return (errorcode);
++}
++
++/* io_bh & io_o refer to the direct parent of the new object.  Objectname is the
++	name of the new object (name only). Does not realese io_bh !!! */
++
++int asfs_createobject(struct super_block *sb, struct buffer_head **io_bh, struct fsObject **io_o, struct fsObject *src_o, u8 *objectname, int force)
++{
++	int errorcode;
++	u32 object_size;
++	u32 hashblock = be32_to_cpu((*io_o)->object.dir.hashtable);
++
++	asfs_debug("createobject: Creating object '%s' in dir '%s'.\n", objectname, (*io_o)->name);
++
++	if (!force && ASFS_SB(sb)->freeblocks < ASFS_ALWAYSFREE)
++		return -ENOSPC;
++
++	if (!force && be32_to_cpu((*io_o)->objectnode) == ASFS_RECYCLEDNODE)
++		return -EINVAL;
++
++	object_size = sizeof(struct fsObject) + strlen(objectname) + 2;
++
++	if ((errorcode = findobjectspace(sb, io_bh, io_o, object_size)) == 0) {
++		struct fsObject *o2 = *io_o;
++		u8 *name = o2->name;
++		u8 *objname = objectname;
++		struct buffer_head *node_bh;
++		struct fsObjectNode *on;
++		u32 nodeno;
++
++		**io_o = *src_o;	/* Copying whole object data... */
++
++		while (*objname != 0)	/* Copying name */
++			*name++ = *objname++;
++
++		*name++ = 0;
++		*name = 0;	/* zero byte for comment */
++
++		if (o2->objectnode != 0)	/* ObjectNode reuse or creation */
++			errorcode = asfs_getnode(sb, o2->objectnode, &node_bh, &on);
++		else {
++			if ((errorcode = asfs_createnode(sb, &node_bh, (struct fsNode **) &on, &nodeno)) == 0) {
++				on->hash16 = cpu_to_be16(asfs_hash(o2->name, ASFS_SB(sb)->flags & ASFS_ROOTBITS_CASESENSITIVE));
++				o2->objectnode = cpu_to_be32(nodeno);
++			}
++			asfs_debug("createnode returned with errorcode: %d\n", errorcode);
++		}
++
++		if (errorcode == 0) {	/* in io_bh there is a container with created object */
++			on->node.data = ((struct fsBlockHeader *) (*io_bh)->b_data)->ownblock;
++			if ((errorcode = hashobject(sb, hashblock, on, be32_to_cpu(o2->objectnode), objectname)) == 0) {
++				asfs_bstore(sb, node_bh);
++				asfs_brelse(node_bh);
++			} else
++				errorcode = -EIO;
++		}
++
++		if (errorcode == 0) {	/* HashBlock reuse or creation:*/
++
++			if ((o2->bits & OTYPE_DIR) != 0 && o2->object.dir.hashtable == 0) {
++				struct buffer_head *hashbh;
++				u32 hashblock;
++
++				asfs_debug("creating Hashblock\n");
++
++				if ((errorcode = asfs_allocadminspace(sb, &hashblock)) == 0 && (hashbh = asfs_getzeroblk(sb, hashblock))) {	    
++					struct fsHashTable *ht = (void *) hashbh->b_data;
++
++					o2->object.dir.hashtable = cpu_to_be32(hashblock);
++
++					ht->bheader.id = cpu_to_be32(ASFS_HASHTABLE_ID);
++					ht->bheader.ownblock = cpu_to_be32(hashblock);
++					ht->parent = o2->objectnode;
++
++					asfs_bstore(sb, hashbh);
++					asfs_brelse(hashbh);
++				}
++			}
++		}
++
++		if (errorcode == 0) {	/* SoftLink creation: */
++			if ((o2->bits & (OTYPE_LINK | OTYPE_HARDLINK)) == OTYPE_LINK && o2->object.file.data == 0) {
++				struct buffer_head *bh2;
++				u32 slinkblock;
++
++				if ((errorcode = asfs_allocadminspace(sb, &slinkblock)) == 0 && (bh2 = asfs_getzeroblk(sb, slinkblock))) {
++					struct fsSoftLink *sl = (void *) bh2->b_data;
++					o2->object.file.data = cpu_to_be32(slinkblock);
++					sl->bheader.id = cpu_to_be32(ASFS_SOFTLINK_ID);
++					sl->bheader.ownblock = cpu_to_be32(slinkblock);
++					sl->parent = o2->objectnode;
++					sl->next = 0;
++					sl->previous = 0;
++					asfs_bstore(sb, bh2);
++					asfs_brelse(bh2);
++				}
++			}
++		}
++	}
++	asfs_debug("createobject: done.\n");
++
++	return (errorcode);
++}
++
++	/* This function extends the file object 'o' with a number  of blocks 
++		(hopefully, if any blocks has been found!). Only new Extents will 
++      be created -- the size of the file will not be altered, and changing 
++		it is left up to the caller.  If the file did not have any blocks 
++		yet, then the o->object.file.data will be set to the first (new) 
++		ExtentBNode. It returns the number of added blocks through 
++		addedblocks pointer */
++
++int asfs_addblockstofile(struct super_block *sb, struct buffer_head *objbh, struct fsObject *o, u32 blocks, u32 * newspace, u32 * addedblocks)
++{
++	u32 lastextentbnode;
++	int errorcode = 0;
++	struct fsExtentBNode *ebnp;
++	struct buffer_head *block = NULL;
++
++
++	asfs_debug("extendblocksinfile: Trying to increasing number of blocks by %d.\n", blocks);
++
++	lastextentbnode = be32_to_cpu(o->object.file.data);
++
++	if (lastextentbnode != 0) {
++		while (lastextentbnode != 0 && errorcode == 0) {
++			if (block != NULL)
++				asfs_brelse(block);
++			errorcode = asfs_getextent(sb, lastextentbnode, &block, &ebnp);
++			lastextentbnode = be32_to_cpu(ebnp->next);
++		}
++		lastextentbnode = be32_to_cpu(ebnp->key);
++	}
++
++	if (errorcode == 0) {
++		u32 searchstart;
++
++		u32 found_block;
++		u32 found_blocks;
++
++		*addedblocks = 0;
++		*newspace = 0;
++
++		if (lastextentbnode != 0)
++			searchstart = be32_to_cpu(ebnp->key) + be16_to_cpu(ebnp->blocks);
++		else
++			searchstart = 0; //ASFS_SB(sb)->block_rovingblockptr;
++
++		if ((errorcode = asfs_findspace(sb, blocks, searchstart, searchstart, &found_block, &found_blocks)) != 0) {
++			asfs_brelse(block);
++			asfs_debug("extendblocksinfile: findspace returned %s\n", errorcode == -ENOSPC ? "ENOSPC" : "error");
++			return errorcode;
++		}
++
++		blocks = found_blocks;
++		errorcode = asfs_markspace(sb, found_block, found_blocks);
++		*addedblocks = found_blocks;
++		*newspace = found_block;
++
++		asfs_debug("extendblocksinfile: block = %u, lastextentbnode = %u, extentblocks = %d\n", found_block, lastextentbnode, blocks);
++
++		if ((errorcode = asfs_addblocks(sb, blocks, found_block, be32_to_cpu(o->objectnode), &lastextentbnode)) != 0) {
++			asfs_debug("extendblocksinfile: addblocks returned errorcode %d\n", errorcode);
++			return errorcode;
++		}
++
++		if (o->object.file.data == 0)
++			o->object.file.data = cpu_to_be32(lastextentbnode);
++	}
++
++	if (block)
++		asfs_brelse(block);
++	asfs_bstore(sb, objbh);
++
++	asfs_debug("addblockstofile: done. added %d blocks\n", *addedblocks);
++
++	return errorcode;
++}
++
++	/* The Object indicated by bh1 & o1, gets renamed to newname and placed
++	   in the directory indicated by bhparent & oparent. */
++
++int asfs_renameobject(struct super_block *sb, struct buffer_head *bh1, struct fsObject *o1, struct buffer_head *bhparent, struct fsObject *oparent, u8 * newname)
++{
++	struct fsObject object;
++	u32 oldparentnode = be32_to_cpu(((struct fsObjectContainer *) bh1->b_data)->parent);
++	u8 oldname[107];
++	int errorcode;
++
++	asfs_debug("renameobject: Renaming '%s' to '%s' in dir '%s'\n", o1->name, newname, oparent->name);
++
++	object = *o1;
++	strcpy(oldname, o1->name);
++
++	if ((errorcode = dehashobjectquick(sb, be32_to_cpu(o1->objectnode), o1->name, oldparentnode)) == 0) {
++		u32 parentobjectnode = be32_to_cpu(oparent->objectnode);
++
++		if ((errorcode = simpleremoveobject(sb, bh1, o1)) == 0) {
++			struct buffer_head *bh2 = bhparent;
++			struct fsObject *o2;
++
++			/* oparent might changed after simpleremoveobject */
++			oparent = o2 = find_obj_by_node(sb, (struct fsObjectContainer *) bhparent->b_data, parentobjectnode);
++
++			/* In goes the Parent bh & o, out comes the New object's bh & o :-) */
++			if ((errorcode = asfs_createobject(sb, &bh2, &o2, &object, newname, TRUE)) == 0) {
++				asfs_bstore(sb, bh2);
++				if (be32_to_cpu(oparent->objectnode) == ASFS_RECYCLEDNODE) {
++					asfs_debug("renameobject: Updating recycled dir info\n");
++					if ((errorcode = setrecycledinfodiff(sb, 1, (be32_to_cpu(o2->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits)) != 0) {
++						brelse(bh2);
++						return errorcode;
++					}
++				}
++				brelse(bh2);
++				asfs_debug("renameobject: Succesfully created & stored new object.\n");
++			} else { /* recreate object in old place, maybe this will not fail, but who knows... */
++				asfs_debug("renameobject: Creating new object failed. Trying to recreate it in source directory.\n");
++				if (asfs_readobject(sb, oldparentnode, &bh1, &o1) == 0) {
++					struct buffer_head *bh2 = bh1;
++					if (asfs_createobject(sb, &bh2, &o1, &object, oldname, TRUE) == 0) {
++						asfs_bstore(sb, bh2);
++						if (oldparentnode == ASFS_RECYCLEDNODE) {
++							asfs_debug("renameobject: Updating recycled dir info\n");
++							setrecycledinfodiff(sb, 1, (be32_to_cpu(o1->object.file.size) + sb->s_blocksize - 1) >> sb->s_blocksize_bits);
++						}
++						brelse(bh2);
++					}
++					brelse(bh1);
++				}
++			}
++		}
++	}
++	return errorcode;
++}
++
++		/* Truncates the specified file to /newsize/ bytes */
++
++int asfs_truncateblocksinfile(struct super_block *sb, struct buffer_head *bh, struct fsObject *o, u32 newsize)
++{
++	struct buffer_head *ebh;
++	struct fsExtentBNode *ebn;
++	int errorcode;
++	u32 pos = 0;
++	u32 newblocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
++	u32 filedata = be32_to_cpu(o->object.file.data);
++	u32 eprev, ekey;
++	u16 eblocks;
++
++	asfs_debug("trucateblocksinfile: newsize %u\n", newsize);
++
++	if (filedata == 0)
++		return 0;
++
++	for (;;) {
++		if ((errorcode = asfs_getextent(sb, filedata, &ebh, &ebn)) != 0)
++			return errorcode;
++		if (pos + be16_to_cpu(ebn->blocks) >= newblocks)
++			break;
++		pos += be16_to_cpu(ebn->blocks);
++		if ((filedata = be32_to_cpu(ebn->next)) == 0)
++			break;
++		asfs_brelse(ebh);
++	};
++
++	eblocks = newblocks - pos;
++	ekey = be32_to_cpu(ebn->key);
++	eprev = be32_to_cpu(ebn->prev);
++
++	if (be16_to_cpu(ebn->blocks) < eblocks) {
++		printk("ASFS: Extent chain is too short or damaged!\n");
++		asfs_brelse(ebh);
++		return -ENOENT;
++	}
++	if (be16_to_cpu(ebn->blocks) - eblocks > 0 && (errorcode = asfs_freespace(sb, be32_to_cpu(ebn->key) + eblocks, be16_to_cpu(ebn->blocks) - eblocks)) != 0) {
++		asfs_brelse(ebh);
++		return errorcode;
++	}
++	if (be32_to_cpu(ebn->next) > 0 && (errorcode = asfs_deleteextents(sb, be32_to_cpu(ebn->next))) != 0) {
++		asfs_brelse(ebh);
++		return errorcode;
++	}
++	ebn->blocks = cpu_to_be16(eblocks);
++	ebn->next = 0;
++	asfs_bstore(sb, ebh);
++
++	if (eblocks == 0) {
++		if (eprev & MSB_MASK) {
++			o->object.file.data = 0;
++			asfs_bstore(sb, bh);
++		} else {
++			struct buffer_head *ebhp;
++			struct fsExtentBNode *ebnp;
++
++			if ((errorcode = asfs_getextent(sb, eprev & !MSB_MASK, &ebhp, &ebnp)) != 0) {
++				asfs_brelse(ebh);
++				return errorcode;
++			}
++
++			ebnp->next = 0;
++			asfs_bstore(sb, ebhp);
++			asfs_brelse(ebhp);
++		}
++		if ((errorcode = asfs_deletebnode(sb, ebh, ekey)) != 0) {
++			asfs_brelse(ebh);
++			return errorcode;
++		}
++	}
++	asfs_brelse(ebh);
++
++	return 0;
++}
++#endif
+diff -urN linux-2.6.3/fs/asfs/super.c linux-2.6.3-asfs-1.0b7/fs/asfs/super.c
+--- linux-2.6.3/fs/asfs/super.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/super.c	2004-06-25 22:44:25.119502392 +0200
+@@ -0,0 +1,437 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ *
++ * version: 1.0beta7 for 2.6.x kernel
++ *  
++ * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ *
++ * Thanks to Marcin Kurek (Morgoth/Dreamolers-CAPS) for help and parts 
++ * of original amiga version of SmartFilesystem source code. 
++ *
++ * SmartFilesystem is copyrighted (C) 2003 by: John Hendrikx, 
++ * Ralph Schmidt, Emmanuel Lesueur, David Gerber and Marcin Kurek
++ * 
++ *
++ * ASFS is based on the Amiga FFS filesystem for Linux
++ * Copyright (C) 1993  Ray Burr
++ * Copyright (C) 1996  Hans-Joachim Widmaier
++ *
++ * Earlier versions were based on the Linux implementation of 
++ * the ROMFS file system
++ * Copyright (C) 1997-1999  Janos Farkas <chexum at shadow.banki.hu>
++ *
++ * ASFS used some parts of the smbfs filesystem:
++ * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
++ * Copyright (C) 1997 by Volker Lendecke
++ *
++ * and parts of the Minix filesystem additionally
++ * Copyright (C) 1991, 1992  Linus Torvalds
++ * Copyright (C) 1996  Gertjan van Wingerde 
++ *
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++/* todo:
++ * - remove bugs
++ * - add missing features (maybe safe-delete, other...)
++ * - create other fs tools like mkfs.asfs and fsck.asfs, some data-recovery tools
++ */
++
++#define ASFS_VERSION "1.0beta7 (25.06.2004)"
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/smp_lock.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/parser.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++#include <asm/uaccess.h>
++
++u32 asfs_calcchecksum(void *block, u32 blocksize)
++{
++	u32 *data = block, checksum = 1;
++	while (blocksize > 0) {
++		checksum += be32_to_cpu(*data++);
++		blocksize -= 4;
++	}
++	checksum -= be32_to_cpu(((struct fsBlockHeader *)block)->checksum);
++	return -checksum;
++}
++
++static struct super_operations asfs_ops = {
++	.alloc_inode	= asfs_alloc_inode,
++	.destroy_inode	= asfs_destroy_inode,
++	.put_super		= asfs_put_super,
++	.statfs			= asfs_statfs,
++#ifdef CONFIG_ASFS_RW
++	.remount_fs		= asfs_remount,
++#endif
++};
++
++extern struct dentry_operations asfs_dentry_operations;
++
++enum {
++	Opt_mode, Opt_setgid, Opt_setuid, Opt_prefix, Opt_volume, 
++	Opt_lcvol, Opt_ignore, Opt_err,
++};
++
++static match_table_t tokens = {
++	{Opt_mode, "mode=%o"},
++	{Opt_setgid, "setgid=%u"},
++	{Opt_setuid, "setuid=%u"},
++	{Opt_prefix, "prefix=%s"},
++	{Opt_volume, "volume=%s"},
++	{Opt_lcvol, "lowercasevol"},
++	{Opt_ignore, "grpquota"},
++	{Opt_ignore, "noquota"},
++	{Opt_ignore, "quota"},
++	{Opt_ignore, "usrquota"},
++	{Opt_err, NULL},
++};
++
++static int asfs_parse_options(char *options, struct super_block *sb)
++{
++	char *p;
++	substring_t args[MAX_OPT_ARGS];
++
++	if (!options)
++		return 1;
++	while ((p = strsep(&options, ",")) != NULL) {
++		int token, option;
++		if (!*p)
++			continue;
++		token = match_token(p, tokens, args);
++
++		switch (token) {
++		case Opt_mode:
++			if (match_octal(&args[0], &option))
++				goto no_arg;
++			ASFS_SB(sb)->mode = option & 0777;
++			break;
++		case Opt_setgid:
++			if (match_int(&args[0], &option))
++				goto no_arg;
++			ASFS_SB(sb)->gid = option;
++			break;
++		case Opt_setuid:
++			if (match_int(&args[0], &option))
++				goto no_arg;
++			ASFS_SB(sb)->uid = option;
++			break;
++		case Opt_prefix:
++			if (ASFS_SB(sb)->prefix) {
++				kfree(ASFS_SB(sb)->prefix);
++				ASFS_SB(sb)->prefix = NULL;
++			}
++			ASFS_SB(sb)->prefix = match_strdup(&args[0]);
++			if (! ASFS_SB(sb)->prefix)
++				return 0;
++			break;
++		case Opt_volume:
++			if (ASFS_SB(sb)->root_volume) {
++				kfree(ASFS_SB(sb)->root_volume);
++				ASFS_SB(sb)->root_volume = NULL;
++			}
++			ASFS_SB(sb)->root_volume = match_strdup(&args[0]);
++			if (! ASFS_SB(sb)->root_volume)
++				return 0;
++			break;
++		case Opt_lcvol:
++			ASFS_SB(sb)->flags |= ASFS_VOL_LOWERCASE;
++			break;
++		case Opt_ignore:
++		 	/* Silently ignore the quota options */
++			break;
++		default:
++no_arg:
++			printk("ASFS: Unrecognized mount option \"%s\" "
++					"or missing value\n", p);
++			return 0;
++		}
++	}
++	return 1;
++}
++
++static int asfs_fill_super(struct super_block *sb, void *data, int silent)
++{
++	struct asfs_sb_info *sbi;
++	struct buffer_head *bh;
++	struct fsRootBlock *rootblock;
++	struct inode *rootinode;
++
++	sbi = kmalloc(sizeof(struct asfs_sb_info), GFP_KERNEL);
++	if (!sbi)
++		return -ENOMEM;
++	sb->s_fs_info = sbi;
++
++	/* Fill in defaults */
++	ASFS_SB(sb)->uid = ASFS_DEFAULT_UID;
++	ASFS_SB(sb)->gid = ASFS_DEFAULT_GID;
++	ASFS_SB(sb)->mode = ASFS_DEFAULT_MODE;
++	ASFS_SB(sb)->prefix = NULL;
++	ASFS_SB(sb)->root_volume = NULL;
++	ASFS_SB(sb)->flags = 0;
++
++	if (!asfs_parse_options(data, sb)) {
++		printk(KERN_ERR "ASFS: Error parsing options\n");
++		return -EINVAL;
++	}
++
++	if (!sb_set_blocksize(sb, 512))
++		return -EINVAL;
++	sb->s_maxbytes = ASFS_MAXFILESIZE;
++
++	bh = sb_bread(sb, 0);
++	if (!bh) {
++		printk(KERN_ERR "ASFS: unable to read superblock\n");
++		return -EINVAL;
++	}
++
++	rootblock = (struct fsRootBlock *)bh->b_data;
++
++	if (be32_to_cpu(rootblock->bheader.id) == ASFS_ROOTID && 
++		be16_to_cpu(rootblock->version) == ASFS_STRUCTURE_VERISON) {
++
++		sb->s_blocksize = be32_to_cpu(rootblock->blocksize);
++		ASFS_SB(sb)->totalblocks = be32_to_cpu(rootblock->totalblocks);
++		ASFS_SB(sb)->rootobjectcontainer = be32_to_cpu(rootblock->rootobjectcontainer);
++		ASFS_SB(sb)->extentbnoderoot = be32_to_cpu(rootblock->extentbnoderoot);
++		ASFS_SB(sb)->objectnoderoot = be32_to_cpu(rootblock->objectnoderoot);
++		ASFS_SB(sb)->flags |= 0xff & rootblock->bits;
++		ASFS_SB(sb)->adminspacecontainer = be32_to_cpu(rootblock->adminspacecontainer);
++		ASFS_SB(sb)->bitmapbase = be32_to_cpu(rootblock->bitmapbase);
++		ASFS_SB(sb)->blocks_inbitmap = (sb->s_blocksize - sizeof(struct fsBitmap))<<3;  /* must be a multiple of 32 !! */
++		ASFS_SB(sb)->blocks_bitmap = (ASFS_SB(sb)->totalblocks + ASFS_SB(sb)->blocks_inbitmap - 1) / ASFS_SB(sb)->blocks_inbitmap;
++		ASFS_SB(sb)->block_rovingblockptr = 0;
++		asfs_brelse(bh);
++
++		if (!sb_set_blocksize(sb, sb->s_blocksize)) {
++			printk(KERN_ERR "ASFS: Found Amiga SFS RootBlock on dev %s, but blocksize %ld is not supported!\n", \
++			       sb->s_id, sb->s_blocksize);
++			return -EINVAL;
++		}
++
++		bh = sb_bread(sb, 0);
++		if (!bh) {
++			printk(KERN_ERR "ASFS: unable to read superblock\n");
++			goto out;
++		}
++		rootblock = (struct fsRootBlock *)bh->b_data;
++
++		if (asfs_check_block((void *)rootblock, sb->s_blocksize, 0, ASFS_ROOTID)) {
++#ifdef CONFIG_ASFS_RW
++			struct buffer_head *tmpbh;
++			if ((tmpbh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer, ASFS_OBJECTCONTAINER_ID))) {
++				struct fsRootInfo *ri = (struct fsRootInfo *)((u8 *)tmpbh->b_data + sb->s_blocksize - sizeof(struct fsRootInfo));
++				ASFS_SB(sb)->freeblocks = be32_to_cpu(ri->freeblocks);
++				asfs_brelse(tmpbh);
++			} else
++				ASFS_SB(sb)->freeblocks = 0;
++
++			if ((tmpbh = asfs_breadcheck(sb, ASFS_SB(sb)->rootobjectcontainer+2, ASFS_TRANSACTIONFAILURE_ID))) {
++				printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s, but it has unfinished transaction. Mounting read-only.\n", sb->s_id);
++				ASFS_SB(sb)->flags |= ASFS_READONLY;
++				asfs_brelse(tmpbh);
++			}
++
++			if ((tmpbh = asfs_breadcheck(sb, ASFS_SB(sb)->totalblocks-1, ASFS_ROOTID)) == NULL) {
++				printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s, but there is no second RootBlock! Mounting read-only.\n", sb->s_id);
++				ASFS_SB(sb)->flags |= ASFS_READONLY;
++				asfs_brelse(tmpbh);
++			}
++			if (!(ASFS_SB(sb)->flags & ASFS_READONLY))
++				printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s.\n", sb->s_id);
++#else
++			ASFS_SB(sb)->freeblocks = 0;
++			ASFS_SB(sb)->flags |= ASFS_READONLY;
++			printk(KERN_NOTICE "VFS: Found Amiga SFS RootBlock on dev %s.\n", sb->s_id);
++#endif
++		} else {
++			if (!silent)
++				printk(KERN_ERR "VFS: Found Amiga SFS RootBlock on dev %s, but it has checksum error!\n", \
++				       sb->s_id);
++			goto out;
++		}
++	} else {
++		if (!silent)
++			printk(KERN_ERR "VFS: Can't find a valid Amiga SFS filesystem on dev %s.\n", \
++			       sb->s_id);
++		goto out;
++	}
++
++	asfs_brelse(bh);
++
++	sb->s_magic = ASFS_MAGIC;
++	sb->s_flags |= MS_NODEV | MS_NOSUID;
++	if (ASFS_SB(sb)->flags & ASFS_READONLY) 
++		sb->s_flags |= MS_RDONLY;
++	sb->s_op = &asfs_ops;
++
++	if ((rootinode = asfs_get_root_inode(sb))) {
++		if ((sb->s_root = d_alloc_root(rootinode))) {
++			sb->s_root->d_op = &asfs_dentry_operations;
++			return 0;
++		}
++		iput(rootinode);
++	}
++	return -EINVAL;
++
++out:
++	asfs_brelse(bh);
++	return -EINVAL;
++
++}
++
++#ifdef CONFIG_ASFS_RW
++int asfs_remount(struct super_block *sb, int *flags, char *data)
++{
++	asfs_debug("ASFS: remount (flags=0x%x, opts=\"%s\")\n",*flags,data);
++
++	if (!asfs_parse_options(data,sb))
++		return -EINVAL;
++
++	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
++		return 0;
++
++	if (*flags & MS_RDONLY) {
++		sb->s_flags |= MS_RDONLY;
++	} else if (!(ASFS_SB(sb)->flags & ASFS_READONLY)) {
++		sb->s_flags &= ~MS_RDONLY;
++	} else {
++		printk("VFS: Can't remount Amiga SFS on dev %s read/write because of errors.", sb->s_id);
++		return -EINVAL;
++	}
++	return 0;
++}
++#endif
++
++void asfs_put_super(struct super_block *sb)
++{
++	struct asfs_sb_info *sbi = ASFS_SB(sb);
++
++	if (ASFS_SB(sb)->prefix)
++		kfree(ASFS_SB(sb)->prefix);
++	if (ASFS_SB(sb)->root_volume)
++		kfree(ASFS_SB(sb)->root_volume);
++
++	kfree(sbi);
++	sb->s_fs_info = NULL;
++	return;
++}
++
++/* That's simple too. */
++int asfs_statfs(struct super_block *sb, struct kstatfs *buf)
++{
++	buf->f_type = ASFS_MAGIC;
++	buf->f_bsize = sb->s_blocksize;
++	buf->f_bfree = buf->f_bavail = ASFS_SB(sb)->freeblocks;
++	buf->f_blocks = ASFS_SB(sb)->totalblocks;
++	buf->f_namelen = ASFS_MAXFN;
++	return 0;
++}
++
++/* --- new in 2.6.x --- */
++static kmem_cache_t * asfs_inode_cachep;
++
++struct inode *asfs_alloc_inode(struct super_block *sb)
++{
++	struct asfs_inode_info *ei;
++	ei = (struct asfs_inode_info *)kmem_cache_alloc(asfs_inode_cachep, SLAB_KERNEL);
++	if (!ei)
++		return NULL;
++	return &ei->vfs_inode;
++}
++
++void asfs_destroy_inode(struct inode *inode)
++{
++	kmem_cache_free(asfs_inode_cachep, ASFS_I(inode));
++}
++
++static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
++{
++	struct asfs_inode_info *ei = (struct asfs_inode_info *) foo;
++
++	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
++	    SLAB_CTOR_CONSTRUCTOR) {
++		inode_init_once(&ei->vfs_inode);
++	}
++}
++
++static int init_inodecache(void)
++{
++	asfs_inode_cachep = kmem_cache_create("asfs_inode_cache",
++					     sizeof(struct asfs_inode_info),
++					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
++					     init_once, NULL);
++	if (asfs_inode_cachep == NULL)
++		return -ENOMEM;
++	return 0;
++}
++
++static void destroy_inodecache(void)
++{
++	if (kmem_cache_destroy(asfs_inode_cachep))
++		printk(KERN_INFO "asfs_inode_cache: not all structures were freed\n");
++}
++
++static struct super_block *asfs_get_sb(struct file_system_type *fs_type,
++	int flags, const char *dev_name, void *data)
++{
++	return get_sb_bdev(fs_type, flags, dev_name, data, asfs_fill_super);
++}
++
++static struct file_system_type asfs_fs_type = {
++	.owner		= THIS_MODULE,
++	.name		= "asfs",
++	.get_sb		= asfs_get_sb,
++	.kill_sb	= kill_block_super,
++	.fs_flags	= FS_REQUIRES_DEV,
++};
++
++static int __init init_asfs_fs(void)
++{
++	int err = init_inodecache();
++	if (err)
++		goto out1;
++	err = register_filesystem(&asfs_fs_type);
++	if (err)
++		goto out;
++	return 0;
++out:
++	destroy_inodecache();
++out1:
++	return err;
++}
++
++static void __exit exit_asfs_fs(void)
++{
++	unregister_filesystem(&asfs_fs_type);
++	destroy_inodecache();
++}
++
++/* Yes, works even as a module... :) */
++
++#ifdef CONFIG_ASFS_RW
++MODULE_DESCRIPTION("Amiga Smart File System (read/write) support for Linux kernel 2.6.x v" ASFS_VERSION);
++#else
++MODULE_DESCRIPTION("Amiga Smart File System (read-only) support for Linux kernel 2.6.x v" ASFS_VERSION);
++#endif
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Marek Szyprowski <marek at amiga.pl>");
++
++module_init(init_asfs_fs)
++module_exit(exit_asfs_fs)
+diff -urN linux-2.6.3/fs/asfs/symlink.c linux-2.6.3-asfs-1.0b7/fs/asfs/symlink.c
+--- linux-2.6.3/fs/asfs/symlink.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/asfs/symlink.c	2004-06-10 01:41:24.000000000 +0200
+@@ -0,0 +1,165 @@
++/*
++ *
++ * Amiga Smart File System, Linux implementation
++ * version: 1.0beta7
++ *  
++ * Copyright (C) 2003,2004  Marek 'March' Szyprowski <marek at amiga.pl>
++ *
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/buffer_head.h>
++#include <linux/vfs.h>
++#include <linux/pagemap.h>
++#include "asfs_fs.h"
++
++#include <asm/byteorder.h>
++#include <asm/uaccess.h>
++
++int asfs_symlink_readpage(struct file *file, struct page *page)
++{
++	struct buffer_head *bh;
++	struct fsSoftLink *slinkcont;
++	struct inode *inode = page->mapping->host;
++	struct super_block *sb = inode->i_sb;
++	char *link = kmap(page);
++	int i = 0, j = 0;
++	char c, lc = 0, *prefix, *lf, *p;
++
++	if (!(bh = asfs_breadcheck(sb, ASFS_I(inode)->firstblock, ASFS_SOFTLINK_ID))) {
++		SetPageError(page);
++		kunmap(page);
++		unlock_page(page);
++		return -EIO;
++	}
++	slinkcont = (struct fsSoftLink *) bh->b_data;
++
++	lf = slinkcont->string;
++	prefix = ASFS_SB(sb)->prefix ? ASFS_SB(sb)->prefix : "/";
++
++	if ((p = strchr(lf,':'))) {	/* Handle assign or volume name */
++		if (ASFS_SB(sb)->root_volume &&
++		    strncmp(lf, ASFS_SB(sb)->root_volume, strlen(ASFS_SB(sb)->root_volume)) == 0) {
++			/* global root volume name found */
++			link[i++] = '/';
++			lf = p+1;
++		} else {
++			/* adding volume prefix */ 
++			while (i < 1023 && (c = prefix[i]))
++				link[i++] = c;
++			if (ASFS_SB(sb)->flags & ASFS_VOL_LOWERCASE) {
++				while (i < 1023 && lf[j] != ':')
++					link[i++] = asfs_lowerchar(lf[j++]);
++			} else {
++				while (i < 1023 && lf[j] != ':')
++					link[i++] = lf[j++];
++			}
++			if (i < 1023)
++				link[i++] = '/';
++			j++;
++		}
++		lc = '/';
++	}
++
++	while (i < 1023 && (c = lf[j])) {
++		if (c == '/' && lc == '/' && i < 1020) {	/* parent dir */
++			link[i++] = '.';
++			link[i++] = '.';
++		}
++		link[i++] = c;
++		lc = c;
++		j++;
++	}
++	link[i] = '\0';
++	SetPageUptodate(page);
++	kunmap(page);
++	unlock_page(page);
++	asfs_brelse(bh);
++	return 0;
++}
++
++#ifdef CONFIG_ASFS_RW
++
++int asfs_write_symlink(struct inode *symfile, const char *symname)
++{
++	struct super_block *sb = symfile->i_sb;
++	struct buffer_head *bh;
++	struct fsSoftLink *slinkcont;
++	char *p, c, lc;
++	int i, maxlen, pflen;
++
++	asfs_debug("asfs_write_symlink %s to node %d\n", symname, (int)symfile->i_ino);
++
++	if (!(bh = asfs_breadcheck(sb, ASFS_I(symfile)->firstblock, ASFS_SOFTLINK_ID))) {
++		unlock_super(sb);
++		return -EIO;
++	}
++	slinkcont = (struct fsSoftLink *) bh->b_data;
++
++	/* translating symlink target path */
++
++	maxlen = sb->s_blocksize - sizeof(struct fsSoftLink) - 2;
++	i  = 0;
++	p  = slinkcont->string;
++	lc = '/';
++
++	if (*symname == '/') {
++		while (*symname == '/')
++			symname++;
++		if (ASFS_SB(sb)->prefix &&
++		    strncmp(symname-1, ASFS_SB(sb)->prefix, (pflen = strlen(ASFS_SB(sb)->prefix))) == 0) {
++			/* found volume prefix, ommiting it */
++			symname += pflen;
++			while ((c = *symname++) != '/' && c != '\0') {
++				*p++ = c;
++				i++;
++			}
++			*p++ = ':';
++		} else if (ASFS_SB(sb)->root_volume) {	/* adding root volume name */
++			while (ASFS_SB(sb)->root_volume[i])
++				*p++ = ASFS_SB(sb)->root_volume[i++];
++			*p++ = ':';
++		} else {	/* do nothing */
++			*p++ = '/';
++		}
++		i++;
++	}
++
++	while (i < maxlen && (c = *symname++)) {
++		if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
++			*p++ = '/';
++			i++;
++			symname += 2;
++			lc = '/';
++		} else if (c == '.' && lc == '/' && *symname == '/') {
++			symname++;
++			lc = '/';
++		} else {
++			*p++ = c;
++			lc   = c;
++			i++;
++		}
++		if (lc == '/')
++			while (*symname == '/')
++				symname++;
++	}
++	*p = 0;
++
++	asfs_bstore(sb, bh);
++	asfs_brelse(bh);
++
++	unlock_super(sb);
++	
++	return 0;
++}
++
++#endif
+diff -urN linux-2.6.3/fs/Kconfig linux-2.6.3-asfs-1.0b7/fs/Kconfig
+--- linux-2.6.3/fs/Kconfig	2004-03-22 17:34:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/Kconfig	2004-06-17 00:31:43.000000000 +0200
+@@ -963,6 +963,37 @@
+ 	  To compile this file system support as a module, choose M here: the
+ 	  module will be called affs.  If unsure, say N.
+ 
++config ASFS_FS
++	tristate "Amiga SFS file system support (EXPERIMENTAL)"
++	depends on EXPERIMENTAL
++	help
++
++	  The Amiga Smart FileSystem (SFS) is the file system used on hard 
++	  disks by Amiga(tm) and MorphOS(tm) systems.  Say Y if you want 
++	  to be able to read files from an Amiga SFS partition on your hard 
++	  drive.
++
++	  For more information read <file:Documentation/filesystems/asfs.txt>
++
++	  To compile this file system support as a module, choose M here: the
++	  module will be called asfs.
++
++	  If unsure, say N.
++
++config ASFS_RW
++	bool "Amiga SFS write support (DANGEROUS)"
++	depends on ASFS_FS
++	help
++
++	  If you say Y here, you will be able to write to ASFS file
++	  systems as well as read from them. The read-write support in ASFS
++	  is in beta stage. This means that useing it to write files to SFS 
++	  partitions is DANGEROUS and COULD corrupt the filesystem.
++
++	  For more information read <file:Documentation/filesystems/asfs.txt>
++
++	  If unsure, say N.
++
+ config HFS_FS
+ 	tristate "Apple Macintosh file system support (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL
+diff -urN linux-2.6.3/fs/Makefile linux-2.6.3-asfs-1.0b7/fs/Makefile
+--- linux-2.6.3/fs/Makefile	2004-03-22 17:34:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/fs/Makefile	2004-03-22 18:22:00.000000000 +0100
+@@ -80,6 +80,7 @@
+ obj-$(CONFIG_JFFS_FS)		+= jffs/
+ obj-$(CONFIG_JFFS2_FS)		+= jffs2/
+ obj-$(CONFIG_AFFS_FS)		+= affs/
++obj-$(CONFIG_ASFS_FS)		+= asfs/
+ obj-$(CONFIG_ROMFS_FS)		+= romfs/
+ obj-$(CONFIG_QNX4FS_FS)		+= qnx4/
+ obj-$(CONFIG_AUTOFS_FS)		+= autofs/
+diff -urN linux-2.6.3/include/linux/amigasfs.h linux-2.6.3-asfs-1.0b7/include/linux/amigasfs.h
+--- linux-2.6.3/include/linux/amigasfs.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.3-asfs-1.0b7/include/linux/amigasfs.h	2004-06-10 19:24:37.000000000 +0200
+@@ -0,0 +1,276 @@
++#ifndef __LINUX_AMIGASFS_H
++#define __LINUX_AMIGASFS_H
++
++#include <linux/types.h>
++
++/* some helper macros... */
++#define ASFS_MAKE_ID(a,b,c,d) (((a)&0xff)<<24|((b)&0xff)<<16|((c)&0xff)<<8|((d)&0xff))
++
++/* Amiga SFS block IDs */
++#define ASFS_ROOTID                 ASFS_MAKE_ID('S','F','S','\0')
++#define ASFS_OBJECTCONTAINER_ID     ASFS_MAKE_ID('O','B','J','C')
++#define ASFS_BNODECONTAINER_ID      ASFS_MAKE_ID('B','N','D','C')
++#define ASFS_NODECONTAINER_ID       ASFS_MAKE_ID('N','D','C',' ')
++#define ASFS_HASHTABLE_ID           ASFS_MAKE_ID('H','T','A','B')
++#define ASFS_SOFTLINK_ID            ASFS_MAKE_ID('S','L','N','K')
++#define ASFS_ADMINSPACECONTAINER_ID ASFS_MAKE_ID('A','D','M','C')
++#define ASFS_BITMAP_ID              ASFS_MAKE_ID('B','T','M','P')
++#define ASFS_TRANSACTIONFAILURE_ID  ASFS_MAKE_ID('T','R','F','A')
++
++/* Amiga SFS defines and magic values */
++
++#define ASFS_MAGIC 0xa0ff
++#define ASFS_MAXFN (105u)
++#define ASFS_MAXFILESIZE 0x8FFFFFFE
++
++#define ASFS_STRUCTURE_VERISON (3)
++#define ASFS_BLCKFACCURACY	(5)
++
++#define ASFS_ROOTBITS_CASESENSITIVE (128)
++#define ASFS_READONLY (512)
++#define ASFS_VOL_LOWERCASE (1024)
++
++#define ASFS_ROOTNODE   (1)
++#define ASFS_RECYCLEDNODE (2)
++
++#define OTYPE_HIDDEN      (1)
++#define OTYPE_HARDLINK    (32)
++#define OTYPE_LINK        (64)
++#define OTYPE_DIR         (128)
++
++#define MSB_MASK (1ul << 31)
++
++#define NODE_STRUCT_SIZE (10)	/* (sizeof(struct fsObjectNode)) */
++#define NODECONT_BLOCK_COUNT ((sb->s_blocksize - sizeof(struct fsNodeContainer)) / sizeof(u32))
++
++#define ASFS_ALWAYSFREE (16)		/* keep this amount of blocks free */
++
++#define ASFS_BLOCKCHUNKS (16)		/* try to allocate this number of blocks in one request */
++
++#ifndef TRUE
++#define TRUE		1
++#endif
++#ifndef FALSE
++#define FALSE		0
++#endif
++
++/* amigados protection bits */
++
++#define FIBB_SCRIPT    6	/* program is a script (execute) file */
++#define FIBB_PURE      5	/* program is reentrant and rexecutable */
++#define FIBB_ARCHIVE   4	/* cleared whenever file is changed */
++#define FIBB_READ      3	/* ignored by old filesystem */
++#define FIBB_WRITE     2	/* ignored by old filesystem */
++#define FIBB_EXECUTE   1	/* ignored by system, used by Shell */
++#define FIBB_DELETE    0	/* prevent file from being deleted */
++
++#define FIBF_SCRIPT    (1<<FIBB_SCRIPT)
++#define FIBF_PURE      (1<<FIBB_PURE)
++#define FIBF_ARCHIVE   (1<<FIBB_ARCHIVE)
++#define FIBF_READ      (1<<FIBB_READ)
++#define FIBF_WRITE     (1<<FIBB_WRITE)
++#define FIBF_EXECUTE   (1<<FIBB_EXECUTE)
++#define FIBF_DELETE    (1<<FIBB_DELETE)
++
++/* name hashing macro */
++
++#define HASHCHAIN(x) (u16)(x % (u16)(((sb->s_blocksize) - sizeof(struct fsHashTable))>>2))
++
++/* Each block has its own header with checksum and id, its called fsBlockHeader */
++
++struct fsBlockHeader {
++	u32 id;			/* 4 character id string of this block */
++	u32 checksum;		/* The checksum */
++	u32 ownblock;		/* The blocknumber of the block this block is stored at */
++};
++
++/* On-disk "super block", called fsRootBlock */
++
++struct fsRootBlock {
++	struct fsBlockHeader bheader;
++
++	u16 version;		/* Version number of the filesystem block structure */
++	u16 sequencenumber;	/* The Root with the highest sequencenumber is valid */
++
++	u32 datecreated;	/* Creation date (when first formatted).  Cannot be changed. */
++	u8 bits;		/* various settings, see defines below. */
++	u8 pad1;
++	u16 pad2;
++
++	u32 reserved1[2];
++
++	u32 firstbyteh;		/* The first byte of our partition from the start of the */
++	u32 firstbyte;		/* disk.  firstbyteh = upper 32 bits, firstbyte = lower 32 bits. */
++
++	u32 lastbyteh;		/* The last byte of our partition, excluding this one. */
++	u32 lastbyte;
++
++	u32 totalblocks;	/* size of this partition in blocks */
++	u32 blocksize;		/* blocksize used */
++
++	u32 reserved2[2];
++	u32 reserved3[8];
++
++	u32 bitmapbase;		/* location of the bitmap */
++	u32 adminspacecontainer;	/* location of first adminspace container */
++	u32 rootobjectcontainer;	/* location of the root objectcontainer */
++	u32 extentbnoderoot;	/* location of the root of the extentbnode B-tree */
++	u32 objectnoderoot;	/* location of the root of the objectnode tree */
++
++	u32 reserved4[3];
++};
++
++/* On disk inode, called fsObject */
++
++struct fsObject {
++	u16 owneruid;
++	u16 ownergid;
++	u32 objectnode;
++	u32 protection;
++
++	union {
++		struct {
++			u32 data;
++			u32 size;
++		} file;
++
++		struct {
++			u32 hashtable;	/* for directories & root, 0 means no hashblock */
++			u32 firstdirblock;
++		} dir;
++	} object;
++
++	u32 datemodified;
++	u8 bits;
++
++	u8 name[0];
++	u8 comment[0];
++};
++
++/* On disk block containging a number of fsObjects */
++
++struct fsObjectContainer {
++	struct fsBlockHeader bheader;
++
++	u32 parent;
++	u32 next;
++	u32 previous;		/* 0 for the first block in the directory chain */
++
++	struct fsObject object[0];
++};
++
++/* BTree structures, used to collect file data position on disk */
++
++struct fsExtentBNode {
++	u32 key;		/* data! */
++	u32 next;
++	u32 prev;
++	u16 blocks;		/* The size in blocks of the region this Extent controls */
++};
++
++struct BNode {
++	u32 key;
++	u32 data;
++};
++
++struct BTreeContainer {
++	u16 nodecount;
++	u8 isleaf;
++	u8 nodesize;		/* Must be a multiple of 2 */
++
++	struct BNode bnode[0];
++};
++
++/* On disk block with BTreeContainer */
++
++struct fsBNodeContainer {
++	struct fsBlockHeader bheader;
++	struct BTreeContainer btc;
++};
++
++/* On disk block  with soft link data */
++
++struct fsSoftLink {
++	struct fsBlockHeader bheader;
++	u32 parent;
++	u32 next;
++	u32 previous;
++	u8 string[0];
++};
++
++/* On disk block with hashtable data */
++
++struct fsHashTable {
++	struct fsBlockHeader bheader;
++	u32 parent;
++	u32 hashentry[0];
++};
++
++/* On disk block with node index and some helper structures */
++
++struct fsNodeContainer {
++	struct fsBlockHeader bheader;
++	u32 nodenumber;
++	u32 nodes;
++	u32 node[0];
++};
++
++struct fsNode {
++	u32 data;
++};
++
++struct fsObjectNode {
++	struct fsNode node;
++	u32 next;
++	u16 hash16;
++} __attribute__ ((packed));
++
++/* Some adminspace and bitmap block structures */
++
++struct fsAdminSpace {
++	u32 space;
++	u32 bits;		
++/* Set bits are used blocks, bit 31 is	the first block in the AdminSpace. */
++};
++
++struct fsAdminSpaceContainer {
++	struct fsBlockHeader bheader;
++
++	u32 next;
++	u32 previous;
++
++	u8 bits;
++	u8 pad1;
++	u16 pad2;
++
++	struct fsAdminSpace adminspace[0];
++};
++
++struct fsBitmap {
++	struct fsBlockHeader bheader;
++
++	u32 bitmap[0];
++
++/* Bits are 1 if the block is free, and 0 if full.
++   Bitmap must consist of an integral number of longwords. */
++};
++
++/* The fsRootInfo structure has all kinds of information about the format
++   of the disk. */
++
++struct fsRootInfo {
++	u32 deletedblocks;	/* Amount in blocks which deleted files consume. */
++	u32 deletedfiles;	/* Number of deleted files in recycled. */
++	u32 freeblocks;		/* Cached number of free blocks on disk. */
++
++	u32 datecreated;
++
++	u32 lastallocatedblock;	/* Block which was most recently allocated */
++	u32 lastallocatedadminspace;	/* AdminSpaceContainer which most recently was used to allocate a block */
++	u32 lastallocatedextentnode;	/* ExtentNode which was most recently created */
++	u32 lastallocatedobjectnode;	/* ObjectNode which was most recently created */
++
++	u32 rovingpointer;
++};
++
++#endif

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-ext3-directio-leak-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-ext3-directio-leak-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-ext3-directio-leak-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,23 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: ext3 directio block leak fix
+## DP: Patch author: Andrew Morton <akpm at osdl.org>
+## DP: Upstream status: backport 2.6.9-bk5
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
+--- a/fs/ext3/inode.c	2004-10-21 06:30:23 -07:00
++++ b/fs/ext3/inode.c	2004-10-21 06:30:23 -07:00
+@@ -1589,7 +1589,7 @@
+ 	if (handle) {
+ 		int err;
+ 
+-		if (orphan) 
++		if (orphan && inode->i_nlink)
+ 			ext3_orphan_del(handle, inode);
+ 		if (orphan && ret > 0) {
+ 			loff_t end = offset + ret;

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-tmpfs-free_inode-leak.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-tmpfs-free_inode-leak.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/fs-tmpfs-free_inode-leak.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,24 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: tmpfs free_inodes leak
+## DP: Patch author:  Hugh Dickins <hugh at veritas.com>
+## DP: Upstream status: backport 2.6.10-rc2
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- a/mm/shmem.c	2004-11-18 12:12:40 -08:00
++++ b/mm/shmem.c	2004-11-18 12:12:40 -08:00
+@@ -1221,6 +1221,10 @@
+ 		case S_IFLNK:
+ 			break;
+ 		}
++	} else if (sbinfo) {
++		spin_lock(&sbinfo->stat_lock);
++		sbinfo->free_inodes++;
++		spin_unlock(&sbinfo->stat_lock);
+ 	}
+ 	return inode;
+ }

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp-1-to-2.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp-1-to-2.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp-1-to-2.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,210 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: fix CONFIG_IA64_GENERIC compilation for UP (rev 2)
+## DP: Patch author: Jesse Barnes <jbarnes at sgi.com>
+## DP: Upstream status: submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN kernel-source-2.6.8.defconfig/arch/ia64/kernel/acpi.c kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/acpi.c
+--- kernel-source-2.6.8.defconfig/arch/ia64/kernel/acpi.c	2004-08-13 23:36:58.000000000 -0600
++++ kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/acpi.c	2004-08-15 15:49:38.000000000 -0600
+@@ -618,9 +618,11 @@
+ 			if (smp_boot_data.cpu_phys_id[cpu] != hard_smp_processor_id())
+ 				node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu];
+ 	}
+-	build_cpu_to_node_map();
+ # endif
+ #endif
++#ifdef CONFIG_ACPI_NUMA
++	build_cpu_to_node_map();
++#endif
+ 	/* Make boot-up look pretty */
+ 	printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
+ 	return 0;
+diff -urN kernel-source-2.6.8.defconfig/arch/ia64/kernel/cyclone.c kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/cyclone.c
+--- kernel-source-2.6.8.defconfig/arch/ia64/kernel/cyclone.c	2004-08-14 13:07:37.000000000 -0600
++++ kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/cyclone.c	2004-08-15 15:49:31.000000000 -0600
+@@ -1,8 +1,6 @@
+-#include <linux/module.h>
+ #include <linux/smp.h>
+ #include <linux/time.h>
+ #include <linux/errno.h>
+-#include <asm/io.h>
+ 
+ /* IBM Summit (EXA) Cyclone counter code*/
+ #define CYCLONE_CBAR_ADDR 0xFEB00CD0
+diff -urN kernel-source-2.6.8.defconfig/arch/ia64/kernel/numa.c kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/numa.c
+--- kernel-source-2.6.8.defconfig/arch/ia64/kernel/numa.c	2004-08-14 13:07:37.000000000 -0600
++++ kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/numa.c	2004-08-15 15:49:38.000000000 -0600
+@@ -1,46 +1,57 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * ia64 kernel NUMA specific stuff
++ *
++ * Copyright (C) 2002 Erich Focht <efocht at ess.nec.de>
++ * Copyright (C) 2004 Silicon Graphics, Inc.
++ *   Jesse Barnes <jbarnes at sgi.com>
++ */
+ #include <linux/config.h>
+ #include <linux/topology.h>
+ #include <linux/module.h>
+ #include <asm/processor.h>
+ #include <asm/smp.h>
+ 
+-#ifdef CONFIG_NUMA
+-
+-/* on which node is each logical CPU (one cacheline even for 64 CPUs) */
+ u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+ EXPORT_SYMBOL(cpu_to_node_map);
+-/* which logical CPUs are on which nodes */
++
+ cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+ 
+-/*
+- * Build cpu to node mapping and initialize the per node cpu masks.
++/**
++ * build_cpu_to_node_map - setup cpu to node and node to cpumask arrays
++ *
++ * Build cpu to node mapping and initialize the per node cpu masks using
++ * info from the node_cpuid array handed to us by ACPI.
+  */
+-void __init
+-build_cpu_to_node_map (void)
++void __init build_cpu_to_node_map(void)
+ {
+ 	int cpu, i, node;
+ 
+-	for(node=0; node<MAX_NUMNODES; node++)
++	for(node=0; node < MAX_NUMNODES; node++)
+ 		cpus_clear(node_to_cpu_mask[node]);
++
+ 	for(cpu = 0; cpu < NR_CPUS; ++cpu) {
+-		/*
+-		 * All Itanium NUMA platforms I know use ACPI, so maybe we
+-		 * can drop this ifdef completely.                    [EF]
+-		 */
+-#ifdef CONFIG_ACPI_NUMA
+ 		node = -1;
+ 		for (i = 0; i < NR_CPUS; ++i)
+ 			if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
+ 				node = node_cpuid[i].nid;
+ 				break;
+ 			}
+-#else
+-#		error Fixme: Dunno how to build CPU-to-node map.
+-#endif
+ 		cpu_to_node_map[cpu] = (node >= 0) ? node : 0;
+ 		if (node >= 0)
+ 			cpu_set(cpu, node_to_cpu_mask[node]);
+ 	}
+ }
+-
+-#endif /* CONFIG_NUMA */
+diff -urN kernel-source-2.6.8.defconfig/arch/ia64/kernel/setup.c kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/setup.c
+--- kernel-source-2.6.8.defconfig/arch/ia64/kernel/setup.c	2004-08-13 23:36:17.000000000 -0600
++++ kernel-source-2.6.8.newupfix.defconfig/arch/ia64/kernel/setup.c	2004-08-15 15:49:38.000000000 -0600
+@@ -317,11 +317,9 @@
+ 	machvec_init(acpi_get_sysname());
+ #endif
+ 
+-#ifdef CONFIG_SMP
+ 	/* If we register an early console, allow CPU 0 to printk */
+ 	if (!early_console_setup())
+ 		cpu_set(smp_processor_id(), cpu_online_map);
+-#endif
+ 
+ #ifdef CONFIG_ACPI_BOOT
+ 	/* Initialize the ACPI boot-time table parser */
+diff -urN kernel-source-2.6.8.defconfig/arch/ia64/mm/discontig.c kernel-source-2.6.8.newupfix.defconfig/arch/ia64/mm/discontig.c
+--- kernel-source-2.6.8.defconfig/arch/ia64/mm/discontig.c	2004-08-14 13:07:37.000000000 -0600
++++ kernel-source-2.6.8.newupfix.defconfig/arch/ia64/mm/discontig.c	2004-08-15 15:49:38.000000000 -0600
+@@ -398,8 +398,8 @@
+  */
+ static void __init initialize_pernode_data(void)
+ {
+-	int cpu, node;
+ 	pg_data_t *pgdat_list[NR_NODES];
++	int cpu, node;
+ 
+ 	for (node = 0; node < numnodes; node++)
+ 		pgdat_list[node] = mem_data[node].pgdat;
+@@ -409,12 +409,22 @@
+ 		memcpy(mem_data[node].node_data->pg_data_ptrs, pgdat_list,
+ 		       sizeof(pgdat_list));
+ 	}
+-
++#ifdef CONFIG_SMP
+ 	/* Set the node_data pointer for each per-cpu struct */
+ 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ 		node = node_cpuid[cpu].nid;
+ 		per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data;
+ 	}
++#else
++	{
++		struct cpuinfo_ia64 *cpu0_cpu_info;
++		cpu = 0;
++		node = node_cpuid[cpu].nid;
++		cpu0_cpu_info = (struct cpuinfo_ia64 *)(__phys_per_cpu_start +
++			((char *)&per_cpu__cpu_info - __per_cpu_start));
++		cpu0_cpu_info->node_data = mem_data[node].node_data;
++	}
++#endif /* CONFIG_SMP */
+ }
+ 
+ /**
+@@ -489,12 +499,11 @@
+ {
+ 	int cpu;
+ 
+-	if (smp_processor_id() == 0) {
+-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+-			per_cpu(local_per_cpu_offset, cpu) =
+-				__per_cpu_offset[cpu];
+-		}
+-	}
++	if (smp_processor_id() != 0)
++		return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
++
++	for (cpu = 0; cpu < NR_CPUS; cpu++)
++		per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
+ 
+ 	return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
+ }
+diff -urN kernel-source-2.6.8.defconfig/drivers/serial/sn_console.c kernel-source-2.6.8.newupfix.defconfig/drivers/serial/sn_console.c
+--- kernel-source-2.6.8.defconfig/drivers/serial/sn_console.c	2004-08-14 13:07:37.000000000 -0600
++++ kernel-source-2.6.8.newupfix.defconfig/drivers/serial/sn_console.c	2004-08-15 15:49:31.000000000 -0600
+@@ -50,7 +50,6 @@
+ #include <linux/miscdevice.h>
+ #include <linux/serial_core.h>
+ 
+-#include <asm/io.h>
+ #include <asm/sn/simulator.h>
+ #include <asm/sn/sn2/sn_private.h>
+ #include <asm/sn/sn_sal.h>
+@@ -1086,9 +1085,7 @@
+ 			spin_unlock_irqrestore(&port->sc_port.lock, flags);
+ 
+ 			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
+ 		}
+-#endif
+ 	}
+ 	else {
+ 		/* Not yet registered with serial core - simple case */

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-generic-no-smp.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,232 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: fix CONFIG_IA64_GENERIC compilation for UP
+## DP: Patch author: Jesse Barnes <jbarnes at sgi.com>
+## DP: Upstream status: submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
+--- a/arch/ia64/kernel/Makefile	2004-08-12 18:28:06 -07:00
++++ b/arch/ia64/kernel/Makefile	2004-08-12 18:28:06 -07:00
+@@ -15,6 +15,7 @@
+ obj-$(CONFIG_IOSAPIC)		+= iosapic.o
+ obj-$(CONFIG_MODULES)		+= module.o
+ obj-$(CONFIG_SMP)		+= smp.o smpboot.o
++obj-$(CONFIG_NUMA)		+= numa.o
+ obj-$(CONFIG_PERFMON)		+= perfmon_default_smpl.o
+ obj-$(CONFIG_IA64_CYCLONE)	+= cyclone.o
+ 
+diff -Nru a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
+--- /dev/null	Wed Dec 31 16:00:00 196900
++++ b/arch/ia64/kernel/numa.c	2004-08-12 18:28:06 -07:00
+@@ -0,0 +1,46 @@
++#include <linux/config.h>
++#include <linux/topology.h>
++#include <linux/module.h>
++#include <asm/processor.h>
++#include <asm/smp.h>
++
++#ifdef CONFIG_NUMA
++
++/* on which node is each logical CPU (one cacheline even for 64 CPUs) */
++u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
++EXPORT_SYMBOL(cpu_to_node_map);
++/* which logical CPUs are on which nodes */
++cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
++
++/*
++ * Build cpu to node mapping and initialize the per node cpu masks.
++ */
++void __init
++build_cpu_to_node_map (void)
++{
++	int cpu, i, node;
++
++	for(node=0; node<MAX_NUMNODES; node++)
++		cpus_clear(node_to_cpu_mask[node]);
++	for(cpu = 0; cpu < NR_CPUS; ++cpu) {
++		/*
++		 * All Itanium NUMA platforms I know use ACPI, so maybe we
++		 * can drop this ifdef completely.                    [EF]
++		 */
++#ifdef CONFIG_ACPI_NUMA
++		node = -1;
++		for (i = 0; i < NR_CPUS; ++i)
++			if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
++				node = node_cpuid[i].nid;
++				break;
++			}
++#else
++#		error Fixme: Dunno how to build CPU-to-node map.
++#endif
++		cpu_to_node_map[cpu] = (node >= 0) ? node : 0;
++		if (node >= 0)
++			cpu_set(cpu, node_to_cpu_mask[node]);
++	}
++}
++
++#endif /* CONFIG_NUMA */
+diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
+--- a/arch/ia64/kernel/smpboot.c	2004-08-12 18:28:06 -07:00
++++ b/arch/ia64/kernel/smpboot.c	2004-08-12 18:28:06 -07:00
+@@ -491,47 +491,6 @@
+ 	}
+ }
+ 
+-#ifdef CONFIG_NUMA
+-
+-/* on which node is each logical CPU (one cacheline even for 64 CPUs) */
+-u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+-EXPORT_SYMBOL(cpu_to_node_map);
+-/* which logical CPUs are on which nodes */
+-cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+-
+-/*
+- * Build cpu to node mapping and initialize the per node cpu masks.
+- */
+-void __init
+-build_cpu_to_node_map (void)
+-{
+-	int cpu, i, node;
+-
+-	for(node=0; node<MAX_NUMNODES; node++)
+-		cpus_clear(node_to_cpu_mask[node]);
+-	for(cpu = 0; cpu < NR_CPUS; ++cpu) {
+-		/*
+-		 * All Itanium NUMA platforms I know use ACPI, so maybe we
+-		 * can drop this ifdef completely.                    [EF]
+-		 */
+-#ifdef CONFIG_ACPI_NUMA
+-		node = -1;
+-		for (i = 0; i < NR_CPUS; ++i)
+-			if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
+-				node = node_cpuid[i].nid;
+-				break;
+-			}
+-#else
+-#		error Fixme: Dunno how to build CPU-to-node map.
+-#endif
+-		cpu_to_node_map[cpu] = (node >= 0) ? node : 0;
+-		if (node >= 0)
+-			cpu_set(cpu, node_to_cpu_mask[node]);
+-	}
+-}
+-
+-#endif /* CONFIG_NUMA */
+-
+ /*
+  * Cycle through the APs sending Wakeup IPIs to boot each.
+  */
+diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
+--- a/arch/ia64/mm/discontig.c	2004-08-12 18:28:06 -07:00
++++ b/arch/ia64/mm/discontig.c	2004-08-12 18:28:06 -07:00
+@@ -225,6 +225,33 @@
+ }
+ 
+ /**
++ * per_cpu_node_setup - setup per-cpu areas on each node
++ * @cpu_data: per-cpu area on this node
++ * @node: node to setup
++ *
++ * Copy the static per-cpu data into the region we just set aside and then
++ * setup __per_cpu_offset for each CPU on this node.  Return a pointer to
++ * the end of the area.
++ */
++static void *per_cpu_node_setup(void *cpu_data, int node)
++{
++#ifdef CONFIG_SMP
++	int cpu;
++
++	for (cpu = 0; cpu < NR_CPUS; cpu++) {
++		if (node == node_cpuid[cpu].nid) {
++			memcpy(__va(cpu_data), __phys_per_cpu_start,
++			       __per_cpu_end - __per_cpu_start);
++			__per_cpu_offset[cpu] = (char*)__va(cpu_data) -
++				__per_cpu_start;
++			cpu_data += PERCPU_PAGE_SIZE;
++		}
++	}
++#endif
++	return cpu_data;
++}
++
++/**
+  * find_pernode_space - allocate memory for memory map and per-node structures
+  * @start: physical start of range
+  * @len: length of range
+@@ -255,7 +282,7 @@
+ static int __init find_pernode_space(unsigned long start, unsigned long len,
+ 				     int node)
+ {
+-	unsigned long epfn, cpu, cpus;
++	unsigned long epfn, cpus;
+ 	unsigned long pernodesize = 0, pernode, pages, mapsize;
+ 	void *cpu_data;
+ 	struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+@@ -305,20 +332,7 @@
+ 		mem_data[node].pgdat->bdata = bdp;
+ 		pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
+ 
+-		/*
+-		 * Copy the static per-cpu data into the region we
+-		 * just set aside and then setup __per_cpu_offset
+-		 * for each CPU on this node.
+-		 */
+-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+-			if (node == node_cpuid[cpu].nid) {
+-				memcpy(__va(cpu_data), __phys_per_cpu_start,
+-				       __per_cpu_end - __per_cpu_start);
+-				__per_cpu_offset[cpu] = (char*)__va(cpu_data) -
+-					__per_cpu_start;
+-				cpu_data += PERCPU_PAGE_SIZE;
+-			}
+-		}
++		cpu_data = per_cpu_node_setup(cpu_data, node);
+ 	}
+ 
+ 	return 0;
+@@ -464,6 +478,7 @@
+ 	find_initrd();
+ }
+ 
++#ifdef CONFIG_SMP
+ /**
+  * per_cpu_init - setup per-cpu variables
+  *
+@@ -483,6 +498,7 @@
+ 
+ 	return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
+ }
++#endif /* CONFIG_SMP */
+ 
+ /**
+  * show_mem - give short summary of memory stats
+diff -Nru a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
+--- a/include/asm-ia64/smp.h	2004-08-12 18:28:06 -07:00
++++ b/include/asm-ia64/smp.h	2004-08-12 18:28:06 -07:00
+@@ -126,6 +126,7 @@
+ #else
+ 
+ #define cpu_logical_id(cpuid)		0
++#define cpu_physical_id(i)	((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
+ 
+ #endif /* CONFIG_SMP */
+ #endif /* _ASM_IA64_SMP_H */
+diff -Nru a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
+--- a/include/asm-ia64/sn/sn_cpuid.h	2004-08-12 18:28:06 -07:00
++++ b/include/asm-ia64/sn/sn_cpuid.h	2004-08-12 18:28:06 -07:00
+@@ -83,10 +83,6 @@
+  *
+  */
+ 
+-#ifndef CONFIG_SMP
+-#define cpu_physical_id(cpuid)			((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
+-#endif
+-
+ /*
+  * macros for some of these exist in sn/addrs.h & sn/arch.h, etc. However, 
+  * trying #include these files here causes circular dependencies.

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-hp-sba_iommu-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-hp-sba_iommu-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-hp-sba_iommu-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,53 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Fix a DMA mapping resource issue on HP ia64 systems
+## DP: Patch author: Nigel Croxon <nigel.croxon at hp.com>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/03 14:46:01-08:00 nigel.croxon at hp.com 
+#   [IA64-HP] Fix for bits_wanted in sba_iommu.c
+#   
+#   bits_wanted is expanded to bytes using the wrong shift value
+#   (when iovp_shift != PAGE_SHIFT), resulting in an explosion of
+#   used iommu resources.
+#   
+#   This potentially results in mistakenly running out of DMA mapping
+#   resources when the system is under *heavy* i/o load.
+#   
+#   Signed-off-by: Nigel Croxon <nigel.croxon at hp.com>
+#   Signed-off by: Alex Williamson <alex.williamson at hp.com>
+#   Signed-off-by: Tony Luck <tony.luck at intel.com>
+# 
+# arch/ia64/hp/common/sba_iommu.c
+#   2004/11/03 14:43:08-08:00 nigel.croxon at hp.com +2 -2
+#   Fix for bits_wanted in sba_iommu.c
+# 
+diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
+--- a/arch/ia64/hp/common/sba_iommu.c	2004-11-04 18:28:50 -08:00
++++ b/arch/ia64/hp/common/sba_iommu.c	2004-11-04 18:28:50 -08:00
+@@ -479,7 +479,7 @@
+ 	 * purges IOTLB entries in power-of-two sizes, so we also
+ 	 * allocate IOVA space in power-of-two sizes.
+ 	 */
+-	bits_wanted = 1UL << get_iovp_order(bits_wanted << PAGE_SHIFT);
++	bits_wanted = 1UL << get_iovp_order(bits_wanted << iovp_shift);
+ 
+ 	if (likely(bits_wanted == 1)) {
+ 		unsigned int bitshiftcnt;
+@@ -688,7 +688,7 @@
+ 	unsigned long m;
+ 
+ 	/* Round up to power-of-two size: see AR2305 note above */
+-	bits_not_wanted = 1UL << get_iovp_order(bits_not_wanted << PAGE_SHIFT);
++	bits_not_wanted = 1UL << get_iovp_order(bits_not_wanted << iovp_shift);
+ 	for (; bits_not_wanted > 0 ; res_ptr++) {
+ 		
+ 		if (unlikely(bits_not_wanted > BITS_PER_LONG)) {

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-mem-max_addr-cmdline-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-mem-max_addr-cmdline-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-mem-max_addr-cmdline-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,89 @@
+# origin: linux-ia64 (Alex Williamson <awilliam at fc.hp.com>)
+# cset: n/a
+# inclusion: submitted upstream
+# revision-date: 2004-10-11
+
+   This should hopefully fix all strange behavior with using mem= or
+max_addr= when trying to limit memory usage.  The current code has
+several problems with splitting granules and removing the dangling
+pieces on subsequent passes.  This potentially happened when mem_limit
+hits total_mem and any time we reduced the page count of an entry
+without updating first_non_wb_addr.  There was also an off by one in
+max_addr that caused an extra granule to get dropped sometimes.
+
+   With this change, there's some extra fuzz introduced that a max_addr
+specification will get rounded down to a granule boundary and memory
+quantity, when using mem=, will be within a granule size of the
+requested amount.  Let me know if anyone finds more problems with it.
+Thanks,
+
+	Alex
+
+-- 
+Signed-off-by: Alex Williamson <alex.williamson at hp.com>
+
+===== arch/ia64/kernel/efi.c 1.36 vs edited =====
+--- 1.36/arch/ia64/kernel/efi.c	2004-08-25 11:50:37 -06:00
++++ edited/arch/ia64/kernel/efi.c	2004-10-07 15:59:50 -06:00
+@@ -348,19 +348,31 @@
+ 			trim_top(md, last_granule_addr);
+ 
+ 		if (is_available_memory(md)) {
+-			if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > max_addr) {
+-				if (md->phys_addr > max_addr)
++			if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) {
++				if (md->phys_addr >= max_addr)
+ 					continue;
+ 				md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
++				first_non_wb_addr = max_addr;
+ 			}
+ 
+ 			if (total_mem >= mem_limit)
+ 				continue;
+-			total_mem += (md->num_pages << EFI_PAGE_SHIFT);
+-			if (total_mem > mem_limit) {
+-				md->num_pages -= ((total_mem - mem_limit) >> EFI_PAGE_SHIFT);
+-				max_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
++
++			if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
++				unsigned long limit_addr = md->phys_addr;
++
++				limit_addr += mem_limit - total_mem;
++				limit_addr &= ~(IA64_GRANULE_SIZE - 1);
++
++				if (md->phys_addr > limit_addr)
++					continue;
++
++				md->num_pages = (limit_addr - md->phys_addr) >>
++				                EFI_PAGE_SHIFT;
++				first_non_wb_addr = max_addr = md->phys_addr +
++				              (md->num_pages << EFI_PAGE_SHIFT);
+ 			}
++			total_mem += (md->num_pages << EFI_PAGE_SHIFT);
+ 
+ 			if (md->num_pages == 0)
+ 				continue;
+@@ -495,13 +507,14 @@
+ 	for (cp = saved_command_line; *cp; ) {
+ 		if (memcmp(cp, "mem=", 4) == 0) {
+ 			cp += 4;
+-			mem_limit = memparse(cp, &end) - 2;
++			mem_limit = memparse(cp, &end);
+ 			if (end != cp)
+ 				break;
+ 			cp = end;
+ 		} else if (memcmp(cp, "max_addr=", 9) == 0) {
+ 			cp += 9;
+-			max_addr = memparse(cp, &end) - 1;
++			max_addr = (memparse(cp, &end) &
++			            ~(IA64_GRANULE_SIZE - 1));
+ 			if (end != cp)
+ 				break;
+ 			cp = end;
+
+
+-
+To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
+the body of a message to majordomo at vger.kernel.org
+More majordomo info at  http://vger.kernel.org/majordomo-info.html
+

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-sn-move-irq-noop.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-sn-move-irq-noop.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64-sn-move-irq-noop.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,29 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Make sn_move_irq() a no-op on UP systems - fixes build
+## DP: Patch author: dann frazier <dannf at hp.com>
+## DP: Upstream status: code has been rewritten since - band-aid for 2.6.9
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- build-itanium/arch/ia64/sn/kernel/irq.c~	2004-10-18 15:53:22.000000000 -0600
++++ build-itanium/arch/ia64/sn/kernel/irq.c	2004-11-05 18:29:41.242076444 -0700
+@@ -74,6 +74,7 @@
+ 
+ static inline void sn_move_irq(int irq)
+ {
++#ifdef CONFIG_SMP
+ 	/* note - we hold desc->lock */
+ 	cpumask_t tmp;
+ 	irq_desc_t *desc = irq_descp(irq);
+@@ -85,6 +86,7 @@
+ 		}
+ 		cpus_clear(pending_irq_cpumask[irq]);
+ 	}
++#endif
+ }
+ 
+ static void

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64_cyclone_nosmp.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64_cyclone_nosmp.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ia64_cyclone_nosmp.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,34 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: fix cyclone build on IA64 for UP
+## DP: Patch author: Jesse Barnes <jbarnes at sgi.com>
+## DP: Upstream status: submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+
+fix ia64 cyclone build errors
+
+Signed-off-by: Randy Dunlap <rddunlap at osdl.org>
+
+diffstat:=
+ arch/ia64/kernel/cyclone.c |    3 +++
+ 1 files changed, 3 insertions(+)
+
+diff -Naurp ./arch/ia64/kernel/cyclone.c~ia64_no_smp ./arch/ia64/kernel/cyclone.c
+--- ./arch/ia64/kernel/cyclone.c~ia64_no_smp	Mon Aug 16 14:13:52 2004
++++ ./arch/ia64/kernel/cyclone.c	Mon Aug 16 14:06:26 2004
+@@ -1,7 +1,10 @@
++#include <linux/init.h>
+ #include <linux/smp.h>
+ #include <linux/time.h>
+ #include <linux/errno.h>
+ 
++#include <asm/io.h>
++
+ /* IBM Summit (EXA) Cyclone counter code*/
+ #define CYCLONE_CBAR_ADDR 0xFEB00CD0
+ #define CYCLONE_PMCC_OFFSET 0x51A0

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ipsec-missing_wakeup.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ipsec-missing_wakeup.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ipsec-missing_wakeup.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,67 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Wake up km_waitq after policy changes in net/xfrm/xfrm_policy.c
+## DP: Patch author: Herbert Xu
+## DP: Upstream status: rejected
+##
+## /---
+## |   Without this patch, the packet that caused this
+## |   ends up being dropped.
+## |
+## | Alexey is working on a better solution to this problem.
+## |
+## | Right now the semantics are horrible for packets that must
+## | be resolved by the key manager. The solution is to make a packet
+## | queue (much like that used for ARP resolution) that gets pushed out
+## | when the key manager finishes resolving or the operation times out.
+## |
+## | I have no idea what is the current state of that work... 
+## \---
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- kernel-source-2.6.6/net/xfrm/xfrm_policy.c	2004-04-05 19:49:45.000000000 +1000
++++ kernel-source-2.6.6-1/net/xfrm/xfrm_policy.c	2004-04-05 20:54:55.000000000 +1000
+@@ -361,6 +361,7 @@
+ 	if (delpol) {
+ 		xfrm_policy_kill(delpol);
+ 	}
++	wake_up(&km_waitq);
+ 	return 0;
+ }
+ 
+@@ -383,6 +384,7 @@
+ 	if (pol && delete) {
+ 		atomic_inc(&flow_cache_genid);
+ 		xfrm_policy_kill(pol);
++		wake_up(&km_waitq);
+ 	}
+ 	return pol;
+ }
+@@ -405,6 +407,7 @@
+ 	if (pol && delete) {
+ 		atomic_inc(&flow_cache_genid);
+ 		xfrm_policy_kill(pol);
++		wake_up(&km_waitq);
+ 	}
+ 	return pol;
+ }
+@@ -427,6 +430,7 @@
+ 	}
+ 	atomic_inc(&flow_cache_genid);
+ 	write_unlock_bh(&xfrm_policy_lock);
++	wake_up(&km_waitq);
+ }
+ 
+ int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*),
+@@ -555,6 +559,7 @@
+ 	if (old_pol) {
+ 		xfrm_policy_kill(old_pol);
+ 	}
++	wake_up(&km_waitq);
+ 	return 0;
+ }
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/marvell-pegasos.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/marvell-pegasos.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/marvell-pegasos.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,2315 @@
+#! /bin/sh -e 
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Add Pegasos2 support in mv64340_eth
+## DP: Patch author: Nicolas DET, Christoph Hewllwig
+## DP: Upstream status: not submitted, needs more work
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN linux-2.6.9.orig/drivers/net/Kconfig linux-2.6.9/drivers/net/Kconfig
+--- linux-2.6.9.orig/drivers/net/Kconfig	2004-10-18 23:55:06.000000000 +0200
++++ linux-2.6.9/drivers/net/Kconfig	2004-10-27 10:31:59.608481264 +0200
+@@ -2162,10 +2162,10 @@
+ 
+ config MV643XX_ETH
+ 	tristate "MV-643XX Ethernet support"
+-	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX
++	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || PPC_CHRP
+ 	help
+ 	  This driver supports the gigabit Ethernet on the Marvell MV643XX
+-	  chipset which is used in the Momenco Ocelot C and Jaguar ATX.
++	  chipset which is used in the Momenco Ocelot C, Jaguar ATX and Pegasos 	  II.
+ 
+ config MV643XX_ETH_0
+ 	bool "MV-643XX Port 0"
+diff -urN linux-2.6.9.orig/drivers/net/mv643xx_eth.c linux-2.6.9/drivers/net/mv643xx_eth.c
+--- linux-2.6.9.orig/drivers/net/mv643xx_eth.c	2004-10-18 23:53:50.000000000 +0200
++++ linux-2.6.9/drivers/net/mv643xx_eth.c	2004-10-27 10:31:59.675471080 +0200
+@@ -54,15 +54,27 @@
+ #include <asm/types.h>
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+-#include "mv643xx_eth.h"
+ 
+ /*
+  * The first part is the high level driver of the gigE ethernet ports. 
+  */
+ 
+ /* Definition for configuring driver */
++#define MV64340_NAPI
++
++#define __MV64340_HARDWARE_STATS__
++
++//#define MV64340_CHECKSUM_OFFLOAD_TX
++//#define __NICO_HARDWARE_CSUM__
++
++#define MV64340_COAL
++
++#undef __VERBOSE__
++
+ #undef MV64340_RX_QUEUE_FILL_ON_TASK
+ 
++#include "mv643xx_eth.h"
++
+ /* Constants */
+ #define EXTRA_BYTES 32
+ #define WRAP       ETH_HLEN + 2 + 4 + 16
+@@ -76,6 +88,8 @@
+ #endif
+ 
+ /* Static function declarations */
++static void eth_port_uc_addr_get(unsigned int PortNum,
++		                                 unsigned char *MacAddr);
+ static int mv64340_eth_real_open(struct net_device *);
+ static int mv64340_eth_real_stop(struct net_device *);
+ static int mv64340_eth_change_mtu(struct net_device *, int);
+@@ -85,9 +99,83 @@
+ static int mv64340_poll(struct net_device *dev, int *budget);
+ #endif
+ 
++#ifdef __PPC__
++// for PowerPC architecture (Pegasos II) we can for the moment put the chip base addr here
++// this is the bus adress, it will be io_remap
++unsigned long marvell_base = 0xf1000000;
++#endif
++
++
+ unsigned char prom_mac_addr_base[6];
+ unsigned long mv64340_sram_base;
+ 
++#ifdef __MV64340_HARDWARE_STATS__
++static inline unsigned long ethReadMibCounter(int port_num, int offset)
++{
++   return MV_READ(MV64340_ETH_MIB_COUNTERS_BASE(port_num) + offset);
++}
++
++static void mv64340_eth_update_stat (struct net_device *dev);
++static void mv64340_eth_update_stat (struct net_device *dev) 
++{
++  struct mv64340_private *mp = netdev_priv(dev);
++  struct net_device_stats *stats = &mp->stats;
++  unsigned int port_num = mp->port_num;
++  volatile unsigned int dummy;
++
++  /* These are false updates */
++  stats->rx_packets += (unsigned long)
++    ethReadMibCounter (port_num,
++                       ETH_MIB_GOOD_FRAMES_RECEIVED);
++  stats->tx_packets += (unsigned long) 
++    ethReadMibCounter (port_num,
++                       ETH_MIB_GOOD_FRAMES_SENT);
++  stats->rx_bytes   += (unsigned long) 
++    ethReadMibCounter (port_num,
++                       ETH_MIB_GOOD_OCTETS_RECEIVED_LOW);
++  /* 
++   * Ideally this should be as follows -
++   *
++   *   stats->rx_bytes   += stats->rx_bytes + 
++   * ((unsigned long) ethReadMibCounter (ethernet_private->port_num ,
++   * ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32);
++   *
++   * But the unsigned long in PowerPC and MIPS are 32bit. So the next read
++   * is just a dummy read for proper work of the GigE port
++   */
++  dummy =ethReadMibCounter (port_num,
++                            ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH);
++  stats->tx_bytes   += (unsigned long)
++      ethReadMibCounter (port_num,
++                         ETH_MIB_GOOD_OCTETS_SENT_LOW);
++  dummy = ethReadMibCounter (port_num,
++                             ETH_MIB_GOOD_OCTETS_SENT_HIGH);
++  stats->rx_errors  += (unsigned long)
++      ethReadMibCounter (port_num,
++                         ETH_MIB_MAC_RECEIVE_ERROR);
++  
++  /* Rx dropped is for received packet with CRC error */
++  stats->rx_dropped += 
++      (unsigned long) ethReadMibCounter (port_num,
++                                         ETH_MIB_BAD_CRC_EVENT);
++  stats->multicast  += (unsigned long)
++    ethReadMibCounter (port_num,
++                       ETH_MIB_MULTICAST_FRAMES_RECEIVED);
++  stats->collisions +=
++    (unsigned long) ethReadMibCounter (port_num,
++                                       ETH_MIB_COLLISION) + 
++    (unsigned long) ethReadMibCounter (port_num,
++                                       ETH_MIB_LATE_COLLISION);
++  /* detailed rx errors */
++  stats->rx_length_errors +=
++    (unsigned long) ethReadMibCounter (port_num,
++                                       ETH_MIB_UNDERSIZE_RECEIVED) +
++    (unsigned long) ethReadMibCounter (port_num,
++                                       ETH_MIB_OVERSIZE_RECEIVED);
++  /* detailed tx errors */  
++}  
++#endif // __HARDWARE_STATS__
++
+ /*
+  * Changes MTU (maximum transfer unit) of the gigabit ethenret port
+  *
+@@ -325,7 +413,9 @@
+ 			      unsigned int eth_int_cause_ext)
+ {
+ 	struct mv64340_private *mp = netdev_priv(dev);
++#ifndef __MV64340_HARDWARE_STATS__
+ 	struct net_device_stats *stats = &mp->stats;
++#endif
+ 	struct pkt_info pkt_info;
+ 	int released = 1;
+ 
+@@ -338,7 +428,9 @@
+ 	while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
+ 		if (pkt_info.cmd_sts & BIT0) {
+ 			printk("%s: Error in TX\n", dev->name);
++#ifndef __MV64340_HARDWARE_STATS__
+ 			stats->tx_errors++;
++#endif
+ 		}
+ 
+ 		/* 
+@@ -394,7 +486,9 @@
+ #endif
+ {
+ 	struct mv64340_private *mp = netdev_priv(dev);
++#ifndef __MV64340_HARDWARE_STATS__
+ 	struct net_device_stats *stats = &mp->stats;
++#endif
+ 	unsigned int received_packets = 0;
+ 	struct sk_buff *skb;
+ 	struct pkt_info pkt_info;
+@@ -410,8 +504,10 @@
+ 		budget--;
+ #endif
+ 		/* Update statistics. Note byte count includes 4 byte CRC count */
++#ifndef __MV64340_HARDWARE_STATS__
+ 		stats->rx_packets++;
+ 		stats->rx_bytes += pkt_info.byte_cnt;
++#endif
+ 		skb = (struct sk_buff *) pkt_info.return_info;
+ 		/*
+ 		 * In case received a packet without first / last bits on OR
+@@ -421,7 +517,9 @@
+ 		      & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
+ 		     (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
+ 		    || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
++#ifndef __MV64340_HARDWARE_STATS__
+ 			stats->rx_dropped++;
++#endif
+ 			if ((pkt_info.cmd_sts & (ETH_RX_FIRST_DESC |
+ 						 ETH_RX_LAST_DESC)) !=
+ 			    (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) {
+@@ -431,11 +529,15 @@
+ 					       " descriptors\n",
+ 					       dev->name);
+ 			}
++
++#ifndef __MV64340_HARDWARE_STATS__
+ 			if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)
+ 				stats->rx_errors++;
++#endif
+ 
+ 			dev_kfree_skb_irq(skb);
+ 		} else {
++			 struct ethhdr *EtherHeader = (struct ethhdr *) skb->data;
+ 			/*
+ 			 * The -4 is for the CRC in the trailer of the
+ 			 * received packet
+@@ -443,11 +545,47 @@
+ 			skb_put(skb, pkt_info.byte_cnt - 4);
+ 			skb->dev = dev;
+ 
+-			if (pkt_info.cmd_sts & ETH_LAYER_4_CHECKSUM_OK) {
+-				skb->ip_summed = CHECKSUM_UNNECESSARY;
+-				skb->csum = htons((pkt_info.cmd_sts
+-							& 0x0007fff8) >> 3);
++			if ( 
++				(skb->len > ETH_FRAME_LEN)
++				&& (EtherHeader->h_proto != 0x8870) 
++	       		   )
++	    		{
++	       			// Jumbo frame requiere a special EthernetType
++               			goto bad_frame;
++            		}
++
++			if (!(pkt_info.l4i_chk & BIT2)) // We only deal with non IP fragmented packet
++			{
++				u32 ALong = pkt_info.cmd_sts &
++					(ETH_FRAME_TYPE_IP_V_4      // -> has to be 1
++					 | ETH_FRAME_HEADER_OK      // -> has to be 1
++					 | ETH_LAYER_4_CHECKSUM_OK  // -> has to be 1
++					 | ETH_LAYER_2_IS_ETH_V_2   // -> has to be 1
++					 | ETH_OTHER_FRAME_TYPE);   // -> Has to be 0, 0-> TCP or UDP packet
++				
++				if (ALong == (ETH_LAYER_4_CHECKSUM_OK
++						 | ETH_FRAME_HEADER_OK
++						 | ETH_LAYER_2_IS_ETH_V_2
++						 | ETH_FRAME_TYPE_IP_V_4 )
++					)
++				{
++					{
++						skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++						// Nico:
++						// The Linux stack should ignore csum if ip_summed == CHECKSUM_UNNECESSARY
++						// then we could remove this line
++						// Also, we should be able to use CHECKSUM_HW with the Marvell
++						// However, I've been unable to discover what csum the Linux stack expected exacly
++						//skb->csum = htons((pkt_info.cmd_sts & 0x0007fff8) >> 3);
++						goto good_frame;
++					}
++				}
+ 			}
++bad_frame:
++			skb->ip_summed = CHECKSUM_NONE;
++
++good_frame:
+ 			skb->protocol = eth_type_trans(skb, dev);
+ #ifdef MV64340_NAPI
+ 			netif_receive_skb(skb);
+@@ -488,6 +626,13 @@
+ 		MV_READ(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+ 		INT_CAUSE_UNMASK_ALL_EXT;
+ 
++	/*
++	 * If no real interrupt occured, exit.
++	 * This can happen when using gigE interrupt coalescing mechanism or shared interrupt
++	 */
++	if ((eth_int_cause == 0x0) && (eth_int_cause_ext == 0x0))
++		return IRQ_NONE;
++
+ #ifdef MV64340_NAPI
+ 	if (!(eth_int_cause & 0x0007fffd)) {
+ 	/* Dont ack the Rx interrupt */
+@@ -560,13 +705,6 @@
+ 		}
+ 	}
+ 
+-	/*
+-	 * If no real interrupt occured, exit.
+-	 * This can happen when using gigE interrupt coalescing mechanism.
+-	 */
+-	if ((eth_int_cause == 0x0) && (eth_int_cause_ext == 0x0))
+-		return IRQ_NONE;
+-
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -608,7 +746,6 @@
+ 
+ 	return coal;
+ }
+-#endif
+ 
+ /*
+  * eth_port_set_tx_coal - Sets coalescing interrupt mechanism on TX path
+@@ -644,6 +781,8 @@
+ 	return coal;
+ }
+ 
++#endif
++
+ /*
+  * mv64340_eth_open
+  *
+@@ -663,10 +802,13 @@
+ 	unsigned int port_num = mp->port_num;
+ 	int err = err;
+ 
+-	spin_lock_irq(&mp->lock);
+-
++#if 0
+ 	err = request_irq(dev->irq, mv64340_eth_int_handler,
+ 	                  SA_INTERRUPT | SA_SAMPLE_RANDOM, dev->name, dev);
++#else
++	err = request_irq(dev->irq, &mv64340_eth_int_handler, SA_SHIRQ | SA_SAMPLE_RANDOM,
++			dev->name, dev);
++#endif
+ 
+ 	if (err) {
+ 		printk(KERN_ERR "Can not assign IRQ number to MV64340_eth%d\n",
+@@ -675,6 +817,8 @@
+ 		goto out;
+ 	}
+ 
++	spin_lock_irq(&mp->lock);
++
+ 	if (mv64340_eth_real_open(dev)) {
+ 		printk("%s: Error opening interface\n", dev->name);
+ 		err = -EBUSY;
+@@ -686,11 +830,10 @@
+ 	return 0;
+ 
+ out_free:
++	spin_unlock_irq(&mp->lock);
+ 	free_irq(dev->irq, dev);
+ 
+ out:
+-	spin_unlock_irq(&mp->lock);
+-
+ 	return err;
+ }
+ 
+@@ -826,7 +969,7 @@
+ 	/* Set Tx desc pointer in driver struct. */
+ 	mp->tx_curr_desc_q = 0;
+ 	mp->tx_used_desc_q = 0;
+-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
++#if defined(MV64340_CHECKSUM_OFFLOAD_TX) && !defined(__NICO_HARDWARE_CSUM__)
+         mp->tx_first_desc_q = 0;
+ #endif
+ 	/* Init Tx ring base and size parameters */
+@@ -915,7 +1058,7 @@
+ 				    mp->tx_desc_dma);
+ 		return -ENOMEM;
+ 	}
+-	memset(mp->p_rx_desc_area, 0, size);
++	memset( (void *) mp->p_rx_desc_area, 0, size);
+ 
+ 	if (!(ether_init_rx_desc_ring(mp, 0)))
+ 		panic("%s: Error initializing RX Ring", dev->name);
+@@ -929,10 +1072,10 @@
+ #ifdef MV64340_COAL
+ 	mp->rx_int_coal =
+ 		eth_port_set_rx_coal(port_num, 133000000, MV64340_RX_COAL);
+-#endif
+ 
+ 	mp->tx_int_coal =
+ 		eth_port_set_tx_coal (port_num, 133000000, MV64340_TX_COAL);  
++#endif
+ 
+ 	/* Increase the Rx side buffer size */
+ 
+@@ -1136,6 +1279,277 @@
+ }
+ #endif
+ 
++#ifdef __NICO_HARDWARE_CSUM__
++// New style xmit
++
++// Will fill pkt_info->l4ick and cmd_sts with good value
++static inline void mv64340_fill_pkt_info(struct sk_buff *skb, struct net_device *dev, struct pkt_info *pkt_info)
++{
++   struct iphdr *iph = skb->nh.iph;
++   u16 ip_frag = ntohs(iph->frag_off);
++
++   // We will generate csum on any frame we can
++   // even if ip_summed != CHECKSUM_HW
++#if 0
++   if (skb->ip_summed == CHECKSUM_HW)
++#else
++   static int count = 0;
++   if ( ((skb->ip_summed == CHECKSUM_HW) )
++       || ( (skb->protocol == ETH_P_IP) 
++	&& ( iph->protocol == IPPROTO_TCP ) 
++	&& ( count )
++	&& ( (ip_frag & (BIT13|BIT14)) == BIT14 ) // last frag, do not frag
++	)
++      )
++#endif
++   {
++      u32 ipheader_len = (iph->ihl << 11) & 0x00007800;
++      ++count;
++    
++      if  ( (ip_frag & 0x1fff) == 0) 
++      {
++         // Non fragmented/first IP packet
++         pkt_info->l4i_chk = 0;
++	 pkt_info->cmd_sts = ETH_LAYER_4_CHECKSUM_FIRST_DESC 
++		    	| ( (iph->protocol == IPPROTO_TCP) ? ETH_TCP_FRAME : ETH_UDP_FRAME) ;
++      }
++      else if (skb->ip_summed == CHECKSUM_HW) 
++      {
++         // Ok for non fragmented IP  we provide the partial csum
++	 // The stack seems to CSUM this packet itself
++	 // then this feature is untested
++	 //printk("fragmented IP packet\n");
++	 if (iph->protocol == IPPROTO_TCP)
++	 {
++	    pkt_info->cmd_sts = ETH_TCP_FRAME;
++            pkt_info->l4i_chk = skb->h.th->check;
++	 }
++	 else
++	 {
++	    pkt_info->cmd_sts = ETH_UDP_FRAME;
++	    pkt_info->l4i_chk = skb->h.uh->check;
++
++	 }   
++      } 
++
++#if 0
++// If you can send LLC/SNAP frame, then please test this
++      {
++         struct ethhdr * EthHeader = (struct ethhdr *)skb->data;
++	 if ( (EthHeader->h_proto < 0x0600) // the common way to detect LLC frame is to check the type/length field
++		||  (EthHeader->h_proto == 0x8870) ) // special case for Jumbo frame
++	 {
++	    pkt_info->cmd_sts |= ETH_LLC_SNAP_FORMAT;
++         }
++      }
++#endif   
++      // Finaly set all the flag in the cmd field
++      pkt_info->cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM
++	         | ETH_GEN_IP_V_4_CHECKSUM 
++		 | ( (skb->protocol == ETH_P_8021Q ) ? ETH_FRAME_SET_TO_VLAN : 0) // Need to be tested by someone with a VLAN network
++	         | ipheader_len;
++   }
++
++   else pkt_info->cmd_sts = 0; 
++}
++
++static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++   struct mv64340_private *ethernet_private = netdev_priv(dev);
++   //unsigned int port_num = ethernet_private->port_num;
++   struct pkt_info pkt_info;
++   unsigned long flags;
++   ETH_FUNC_RET_STATUS status;
++ #ifndef __MV64340_HARDWARE_STATS__
++   struct net_device_stats *stats = &ethernet_private->stats;
++ #endif
++
++   if (netif_queue_stopped(dev)) {
++      printk(KERN_ERR"%s: Tried sending packet when interface is stopped\n",dev->name);
++      return 1;
++   }
++
++   /* This is a hard error, log it. */
++   if ((MV64340_TX_QUEUE_SIZE - ethernet_private->tx_ring_skbs) <= (skb_shinfo(skb)->nr_frags + 1)) {
++      netif_stop_queue(dev);
++      printk(KERN_ERR"%s: Bug in mv64340_eth - Trying to transmit when queue full !\n", dev->name);
++      return 1;
++   }
++
++   /* Paranoid check - this shouldn't happen */
++   if (skb == NULL) {
++#ifndef __MV64340_HARDWARE_STATS__
++      stats->tx_dropped++;
++#endif
++      return 1;
++   }
++
++   spin_lock_irqsave(&ethernet_private->lock, flags);
++#ifdef MV64340_CHECKSUM_OFFLOAD_TX
++// Ok here we will handle Scatter (or not) skb -> fragmented data
++// - First if it's not framgented to as usual (FIRST/LAST, pci_map_single of the
++// data, and eth_port_send
++// - But if the data are fragmented( skb_is_nonlinear() ), then we have to send
++// the first (part of data) with FIRST, and chained the next one. The last one will have 
++//  ETH_TX_ENABLE_INTERRUPT and LAST
++//
++//  By the way, the stack seems to never give us framgmented skb, but it seens that
++//  it's better to support because the stack would not have to linearize the packet
++//  if it's framented (which cost CPU power). Therefore, as the Marvell can handle
++//  that kind of skb, let's support it!
++//
++//  Special warning about fragmented SKB
++//  As said above, the stack never gave me a such SKB, so it's untested.
++//  There can be a pb if the data to send are no cache align or if someone else 
++//  own data in the same cache line that the beginnig of the data ptr and the end
++//  Usually, the kernel/stack should take care to always align that to L1 cache line
++//  size, so everything should be ok, but if not, then it's a kernel bug, will lead 
++//  to pbs and it has to be fix
++//  This applies to the first packet as well as the others (page style ..).
++
++   if( skb_is_nonlinear(skb) )
++   {
++      // Skb fragmented
++      struct skb_shared_info *SharedInfo = skb_shinfo(skb);
++      int NumOfFrags = SharedInfo->nr_frags; // NumOfFrags = All the frags - the first one
++      int i;
++
++      // Send the first frag
++      mv64340_fill_pkt_info(skb, dev, &pkt_info); // For the first frame buffer we put all the needed (or not) flags
++      pkt_info.cmd_sts 		|= ETH_TX_FIRST_DESC;
++      pkt_info.byte_cnt 	= skb_headlen(skb);	// Size of the first frag as decribe in (http://efault.net/npat/docs_and_postings/net_device-features/net_device-features.txt)
++      pkt_info.buf_ptr 		= pci_map_single(0, skb->data, pkt_info.byte_cnt, PCI_DMA_TODEVICE);
++      pkt_info.return_info 	= NULL;
++
++      flush_dcache_range( (unsigned long) skb->data, (unsigned long) ( (u32) skb->data + pkt_info.byte_cnt) );
++      //printk("first frag %8.8x id=%8.8x len=%d, total len %d, cmd=%8.8x\n", pkt_info.buf_ptr, skb->nh.iph->id, skb_headlen(skb), skb->len, pkt_info.cmd_sts );
++      status = eth_port_send(ethernet_private, &pkt_info);
++      if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
++         printk(KERN_ERR "%s: Error on transmitting packet\n",dev->name);
++
++      // We have NumOfFrags left to send
++      if (!NumOfFrags)
++      {
++#ifdef __VERBOSE__
++         if (net_ratelimit() )printk(KERN_ERR "?? kernel bug ? fragmented SKB should at keast have 2 frags !\n");
++#endif
++      }
++      else	
++      {
++	 struct skb_frag_struct *CurrentFrag;
++	 int FrameSize = CurrentFrag->size;
++         for (i=0; i < (NumOfFrags-1) ; i++)
++         {
++            // This loop will send of the remaining frag (but no the last one)
++	    //
++	    // struct skb_frag_struct
++	    // {
++	    //    struct page *page;
++	    //    __u16 page_offset;
++	    //    __u16 size;
++	    // };
++	    CurrentFrag 	= &SharedInfo->frags[i];
++	    FrameSize 		= CurrentFrag->size;
++	    pkt_info.cmd_sts  	= 0L;
++	    pkt_info.l4i_chk 	= 0x0000;
++	    pkt_info.byte_cnt 	= FrameSize;
++	    pkt_info.buf_ptr  	= pci_map_page(0, 
++			 CurrentFrag->page,
++			 CurrentFrag->page_offset,
++		         FrameSize, 
++			 PCI_DMA_TODEVICE);
++
++	    pkt_info.return_info = NULL;
++            flush_dcache_range( 
++			 (unsigned long) ( (u32) page_address(CurrentFrag->page) + CurrentFrag->page_offset) ,
++			 (unsigned long) ( (u32) page_address(CurrentFrag->page) + CurrentFrag->page_offset + FrameSize ) );
++	    //printk("len %d cmd %8.8x\n", FrameSize, pkt_info.cmd_sts);
++            status = eth_port_send(ethernet_private, &pkt_info);
++            if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
++               printk(KERN_ERR "%s: Error on transmitting packet\n",dev->name);
++         }
++
++         // Ok now we send the last frag
++         CurrentFrag = &SharedInfo->frags[NumOfFrags-1];
++	 FrameSize = CurrentFrag->size;
++
++         pkt_info.cmd_sts  	= ETH_TX_LAST_DESC;
++	 pkt_info.l4i_chk 	= 0x0000;
++         pkt_info.byte_cnt 	= FrameSize;
++         pkt_info.buf_ptr  	= pci_map_page(0, 
++		 CurrentFrag->page,
++		 CurrentFrag->page_offset,
++		 FrameSize, 
++		 PCI_DMA_TODEVICE);
++	 pkt_info.return_info 	= skb;
++         flush_dcache_range( 
++		 (unsigned long) ( (u32) page_address(CurrentFrag->page) + CurrentFrag->page_offset) ,
++	         (unsigned long) ( (u32) page_address(CurrentFrag->page) + CurrentFrag->page_offset + FrameSize ) );
++
++	 //printk("len last %d, cmd %8.8x\n", FrameSize, pkt_info.cmd_sts);
++         status = eth_port_send(ethernet_private, &pkt_info);
++         if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
++            printk(KERN_ERR "%s: Error on transmitting packet\n",dev->name);
++      }
++      ethernet_private->tx_ring_skbs++;
++   }
++   else
++   {
++      // Ok, skb->data are linear -> just send the frame
++      mv64340_fill_pkt_info(skb, dev, &pkt_info);
++	   
++      pkt_info.cmd_sts |= ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
++
++      pkt_info.byte_cnt = skb->len;
++      pkt_info.buf_ptr = pci_map_single(0, skb->data, skb->len, PCI_DMA_TODEVICE);
++      pkt_info.return_info = skb;
++      // skb_alloc and friend always align head and data to cache line size
++      flush_dcache_range( (unsigned long) skb->head , (unsigned long) skb->end);
++      status = eth_port_send(ethernet_private, &pkt_info);
++
++      if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
++         printk(KERN_ERR "%s: Error on transmitting packet\n",dev->name);
++      ethernet_private->tx_ring_skbs++;
++   }
++#else // MV64340_CHECKSUM_OFFLOAD_TX
++   /* Update packet info data structure -- DMA owned, first last */
++   pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
++
++   pkt_info.byte_cnt = skb->len;
++   pkt_info.buf_ptr = pci_map_single(0, skb->data, skb->len, PCI_DMA_TODEVICE);
++
++   flush_dcache_range( (unsigned long) skb->head, (unsigned long) skb->end );
++   pkt_info.return_info = skb;
++   status = eth_port_send(ethernet_private, &pkt_info);
++   if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
++      printk(KERN_ERR "%s: Error on transmitting packet\n",dev->name);
++   ethernet_private->tx_ring_skbs++;
++#endif // MV64340_CHECKSUM_OFFLOAD_TX
++   /* Check if TX queue can handle another skb. If not, then
++    * signal higher layers to stop requesting TX
++    */
++   if (MV64340_TX_QUEUE_SIZE <= (ethernet_private->tx_ring_skbs + 1))
++      /*
++       * Stop getting skb's from upper layers.
++       * Getting skb's from upper layers will be enabled again after
++       * packets are released.
++       */
++       netif_stop_queue(dev);
++
++
++   /* Update statistics and start of transmittion time */
++#ifndef __MV64340_HARDWARE_STATS__
++   stats->tx_bytes += skb->len;
++   stats->tx_packets++;
++#endif
++   dev->trans_start = jiffies;
++
++   spin_unlock_irqrestore(&ethernet_private->lock, flags);
++   return 0;      /* success */
++}
++
++
++#else //__NICO_HARDWARE_CSUM__
+ /*
+  * mv64340_eth_start_xmit
+  *
+@@ -1150,7 +1564,9 @@
+ static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+ 	struct mv64340_private *mp = netdev_priv(dev);
++#ifndef __MV64340_HARDWARE_STATS__
+ 	struct net_device_stats *stats = &mp->stats;
++#endif
+ 	ETH_FUNC_RET_STATUS status;
+ 	unsigned long flags;
+ 	struct pkt_info pkt_info;
+@@ -1174,7 +1590,9 @@
+ 
+ 	/* Paranoid check - this shouldn't happen */
+ 	if (skb == NULL) {
++#ifndef __MV64340_HARDWARE_STATS__
+ 		stats->tx_dropped++;
++#endif
+ 		return 1;
+ 	}
+ 
+@@ -1209,11 +1627,20 @@
+                                         skb_headlen(skb), PCI_DMA_TODEVICE);
+                 pkt_info.return_info = 0;
+                 ipheader = skb->nh.iph->ihl << 11;
++
++		// Nico note:
++		// Liunx always generate the IP checksum (I guess because it's very fast to do)
++		// so we could remove ETH_GEN_IP_V_4_CHECKSUM here
+                 pkt_info.cmd_sts = ETH_TX_FIRST_DESC | 
+ 					ETH_GEN_TCP_UDP_CHECKSUM |
+ 					ETH_GEN_IP_V_4_CHECKSUM |
+                                         ipheader;
+ 		/* CPU already calculated pseudo header checksum. So, use it */
++		// Nico:
++		// A little warning here:
++		// for the first buffer of a packet, l4i_chk must be 0x0000
++		// the behaviour of the chip could be unexpected if the Linux stack
++		// gives us a non zero csum and we are in the first buffer
+                 pkt_info.l4i_chk = skb->h.th->check;
+                 status = eth_port_send(mp, &pkt_info);
+ 		if (status != ETH_OK) {
+@@ -1277,14 +1704,17 @@
+ 		netif_stop_queue(dev);
+ 
+ 	/* Update statistics and start of transmittion time */
++#ifndef __MV64340_HARDWARE_STATS__
+ 	stats->tx_bytes += skb->len;
+ 	stats->tx_packets++;
++#endif
+ 	dev->trans_start = jiffies;
+ 
+ 	spin_unlock_irqrestore(&mp->lock, flags);
+ 
+ 	return 0;		/* success */
+ }
++#endif // new style xmit
+ 
+ /*
+  * mv64340_eth_get_stats
+@@ -1300,6 +1730,10 @@
+ {
+ 	struct mv64340_private *mp = netdev_priv(dev);
+ 
++#ifdef __MV64340_HARDWARE_STATS__
++	mv64340_eth_update_stat(dev);
++#endif
++
+ 	return &mp->stats;
+ }
+ 
+@@ -1326,7 +1760,11 @@
+ 
+ 	mp = netdev_priv(dev);
+ 
++#ifdef __PPC__
++	dev->irq = 9;
++#else
+ 	dev->irq = ETH_PORT0_IRQ_NUM + port_num;
++#endif
+ 
+ 	dev->open = mv64340_eth_open;
+ 	dev->stop = mv64340_eth_stop;
+@@ -1335,6 +1773,12 @@
+ 	dev->set_mac_address = mv64340_eth_set_mac_address;
+ 	dev->set_multicast_list = mv64340_eth_set_rx_mode;
+ 
++#ifdef __MV64340_HARDWARE_STATS__
++	// reset the stats to zero
++	mv64340_eth_update_stat(dev);
++	memset(&mp->stats, 0x00, sizeof(mp->stats) );
++#endif
++
+ 	/* No need to Tx Timeout */
+ 	dev->tx_timeout = mv64340_eth_tx_timeout;
+ #ifdef MV64340_NAPI
+@@ -1367,9 +1811,13 @@
+ 
+ 	spin_lock_init(&mp->lock);
+ 
++#if defined(__powerpc__)
++	eth_port_uc_addr_get(port_num, dev->dev_addr); 
++#else
+ 	/* set MAC addresses */
+ 	memcpy(dev->dev_addr, prom_mac_addr_base, 6);
+ 	dev->dev_addr[5] += port_num;
++#endif
+ 
+ 	err = register_netdev(dev);
+ 	if (err)
+@@ -1386,8 +1834,17 @@
+ 	if (dev->features & NETIF_F_IP_CSUM)
+ 		printk("TX TCP/IP Checksumming Supported  \n");
+ 
+-	printk("RX TCP/UDP Checksum Offload ON, \n");
+-	printk("TX and RX Interrupt Coalescing ON \n");
++#ifdef MV64340_CHECKSUM_OFFLOAD_TX
++	printk("RX TCP/UDP Checksum Offload ON\n");
++#else
++	printk("RX TCP/UDP Checksum Offload OFF\n");
++#endif
++
++#ifdef MV64340_COAL
++	printk("TX and RX Interrupt Coalescing ON\n");
++#else
++	printk("TX and RX Interrupt Coalescing OFF\n");
++#endif
+ 
+ #ifdef MV64340_NAPI
+ 	printk("RX NAPI Enabled \n");
+@@ -1403,7 +1860,7 @@
+ 
+ static void mv64340_eth_remove(struct net_device *dev)
+ {
+-	struct mv64340_private *mp = netdev_priv(dev);
++	//struct mv64340_private *mp = netdev_priv(dev);
+ 
+ 	unregister_netdev(dev);
+ 	flush_scheduled_work();
+@@ -1427,6 +1884,12 @@
+ {
+ 	printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+ 
++#ifdef __PPC__
++	// First ioremap the Marvell base addr
++	marvell_base = (unsigned long) ioremap( marvell_base, 64*1024);
++	printk(KERN_NOTICE "MV-64340: Chip base remaped at 0x%8.8x\n", (int) marvell_base);
++#endif
++
+ #ifdef CONFIG_MV643XX_ETH_0
+ 	mv64340_dev0 = mv64340_eth_init(0);
+ 	if (!mv64340_dev0) {
+@@ -1770,6 +2233,10 @@
+ 	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num),
+ 		 mp->port_rx_queue_command);
+ 
++	// Nico
++	// Set the minimun RX frame to 40 in order to accept, short frame :-)
++	MV_WRITE(MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(eth_port_num), 40);
++
+ 	/* Check if link is up */
+ 	eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
+ 
+@@ -1816,6 +2283,23 @@
+ 	return;
+ }
+ 
++static void eth_port_uc_addr_get(unsigned int PortNum,
++				 unsigned char *MacAddr)
++{
++        u32 MacLow;
++        u32 MacHigh;
++
++        MacLow = MV_READ(MV64340_ETH_MAC_ADDR_LOW(PortNum));
++        MacHigh = MV_READ(MV64340_ETH_MAC_ADDR_HIGH(PortNum));
++
++        MacAddr[5] = (MacLow) & 0xff;
++        MacAddr[4] = (MacLow >> 8) & 0xff;
++        MacAddr[3] = (MacHigh) & 0xff;
++        MacAddr[2] = (MacHigh >> 8) & 0xff;
++        MacAddr[1] = (MacHigh >> 16) & 0xff;
++        MacAddr[0] = (MacHigh >> 24) & 0xff;
++}
++
+ /*
+  * eth_port_uc_addr - This function Set the port unicast address table
+  *
+@@ -1996,10 +2480,24 @@
+ 	unsigned int time_out = 50;
+ 	unsigned int phy_reg_data;
+ 
+-	/* Reset the PHY */
+-	eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
+-	phy_reg_data |= 0x8000;	/* Set bit 15 to reset the PHY */
+-	eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
++   	/* change to combined led mode LINK=green 100/1000=dual led*/
++   	eth_port_read_smi_reg(eth_port_num, 24, &phy_reg_data);
++   	phy_reg_data&=~0x0018;
++   	phy_reg_data|= 0x0010;
++   	eth_port_write_smi_reg(eth_port_num,24, phy_reg_data);
++   
++   	/* enable autocrossover in all modes */
++   	eth_port_read_smi_reg(eth_port_num, 16, &phy_reg_data);
++   	phy_reg_data&=~0x0060;
++   	phy_reg_data|= 0x0060;
++   	eth_port_write_smi_reg(eth_port_num,16, phy_reg_data);
++
++   	/* Reset the PHY and update reg0*/
++   	eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
++   	phy_reg_data &=~0x7fff;   /* clear unwanted*/
++   	phy_reg_data |= 0x1000;   /* enable auto negotiation*/
++   	phy_reg_data |= 0x8000;   /* Set bit 15 to reset the PHY */
++   	eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
+ 
+ 	/* Poll on the PHY LINK */
+ 	do {
+@@ -2273,6 +2771,165 @@
+  *
+  */
+ #ifdef  MV64340_CHECKSUM_OFFLOAD_TX
++
++#ifdef __NICO_HARDWARE_CSUM__
++
++/*
++ * Modified to include the first descriptor pointer in case of SG
++ */
++static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * p_eth_port_ctrl, struct pkt_info * p_pkt_info)
++{
++        int tx_desc_curr;
++	int tx_desc_used;
++	int tx_next_desc;
++        volatile struct eth_tx_desc *current_descriptor;
++        volatile struct eth_tx_desc *first_descriptor;
++        u32 command_status;
++
++        /* Do not process Tx ring in case of Tx ring resource error */
++        if (p_eth_port_ctrl->tx_resource_err)
++                return ETH_QUEUE_FULL;
++
++        /* Get the Tx Desc ring indexes */
++        tx_desc_curr = p_eth_port_ctrl->tx_curr_desc_q;
++        tx_desc_used = p_eth_port_ctrl->tx_used_desc_q;
++
++        current_descriptor = &(p_eth_port_ctrl->p_tx_desc_area[tx_desc_curr]);
++        if (current_descriptor == NULL)
++                return ETH_ERROR;
++
++        tx_next_desc = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
++        command_status = p_pkt_info->cmd_sts;
++
++        if (p_pkt_info->byte_cnt == 0)
++	{
++	    if (net_ratelimit() ) printk(KERN_ERR "MV6436x: Unable to a 0 byte buffer\n");
++            return ETH_ERROR;
++	}
++	
++        if ( (command_status & ETH_TX_FIRST_DESC) 
++		&& (command_status & ETH_TX_LAST_DESC) )
++	{
++             // We have a "normal" skb, act as usual
++	     
++	     //printk("Send opaque frag len=%d, currrent_ptr=%8.8x, next ptr=%8.8x\n", p_pkt_info->byte_cnt, virt_to_bus(current_descriptor), current_descriptor->next_desc_ptr);
++	     //
++
++             if (p_pkt_info->byte_cnt < 32)
++	     {
++	        if (net_ratelimit() ) printk(KERN_ERR "MV6436x: Unable to send a such small packet (%d bytes)\n", p_pkt_info->byte_cnt);
++		return ETH_ERROR;
++	     }
++	
++	     command_status |= ETH_ZERO_PADDING | ETH_GEN_CRC;
++
++             current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
++             current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
++	     current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
++	     current_descriptor->cmd_sts = command_status | ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
++
++	    
++             p_eth_port_ctrl->tx_skb[tx_desc_curr] = (struct sk_buff*)p_pkt_info->return_info;
++
++             mb();
++
++             /* Apply send command */
++             ETH_ENABLE_TX_QUEUE(p_eth_port_ctrl->port_num);
++	}
++
++	// Ok, we have a "multi-descriptor" packet -> fragmented SKB
++	else if (command_status & ETH_TX_FIRST_DESC) 
++	{
++		// First fragment, we fill the first packet desc
++		command_status |= ETH_GEN_CRC | ETH_BUFFER_OWNED_BY_DMA;
++
++                /* fill first descriptor */
++                first_descriptor = &(p_eth_port_ctrl->p_tx_desc_area[tx_desc_curr]);
++                first_descriptor->l4i_chk = p_pkt_info->l4i_chk;
++                first_descriptor->cmd_sts = command_status;
++                first_descriptor->byte_cnt = p_pkt_info->byte_cnt;
++                first_descriptor->buf_ptr = p_pkt_info->buf_ptr;
++
++                dma_cache_wback_inv((unsigned long)first_descriptor, sizeof(ETH_TX_DESC));
++		wmb();
++	
++		//printk("Send first frag len=%d cmd=%8.8x, pkt_ptr=%8.8x, next=%8.8x\n", p_pkt_info->byte_cnt, command_status,  virt_to_bus(first_descriptor),  first_descriptor->next_desc_ptr);
++		// Our first frag is ready
++		// So we return, we should receive the next (and maybe last) frag at the next call
++        }
++        else if (!(command_status & ETH_TX_LAST_DESC))
++	{
++		// We have just handle the first frag
++		// here, we take care of the "intermediate frag" aka
++		// non first and non last
++		//
++		// Note: if there are only 2 frags, then this case will not happen
++
++		command_status |= ETH_BUFFER_OWNED_BY_DMA;
++		
++	        current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
++	        current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
++		current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
++		current_descriptor->cmd_sts = command_status;
++
++		// For the Pegasos driver this is useless
++		// because the desc are in SRAM which is non-cacheable
++		// but it could be useful for other platfrom using the
++		// MV64362 which has no SRAM
++		dma_cache_wback_inv((unsigned long)current_descriptor, sizeof(ETH_TX_DESC));
++		wmb();
++
++		//printk("Send inter frag len=%d cmd=%8.8x, pkt_ptr=%8.8x, next=%8.8x\n", p_pkt_info->byte_cnt, current_descriptor->cmd_sts,  virt_to_bus(current_descriptor), current_descriptor->next_desc_ptr);
++		// This intermediate frag done
++		// at next call we will have either another frag like (unlikely) that
++		// of the last one (likely)
++	}
++	else
++	{
++		// And finaly, last frag
++		// set the usual stuff, the INTERRUPT flag and apply the command
++#ifdef __VERBOSE__
++		if ( (p_pkt_info->byte_cnt <= 8) && (p_pkt_info->buf_ptr & 0x7))
++		{
++		   if (net_ratelimit() )printk("MV6436x: Warning, trying to send a small (%d) and unaligned (0x%8.8x) packet fragement\n", p_pkt_info->byte_cnt, p_pkt_info->buf_ptr );
++		}
++#endif
++		command_status |= ETH_ZERO_PADDING
++			| ETH_BUFFER_OWNED_BY_DMA
++			| ETH_TX_ENABLE_INTERRUPT;
++		
++                current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
++	        current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
++		current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
++		current_descriptor->cmd_sts = command_status;
++
++                dma_cache_wback_inv((unsigned long)current_descriptor, sizeof(ETH_TX_DESC));
++                wmb();
++
++		/* Apply send command */
++		ETH_ENABLE_TX_QUEUE(p_eth_port_ctrl->port_num);
++
++		p_eth_port_ctrl->tx_skb[tx_desc_curr] = (struct sk_buff*)p_pkt_info->return_info;
++		// Done :-)
++        }
++	
++        // Usual ring update stuff
++	/* Finish Tx packet. Update first desc in case of Tx resource error */
++        tx_desc_curr = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
++
++        /* Update the current descriptor */
++        p_eth_port_ctrl->tx_curr_desc_q = tx_desc_curr;
++
++        /* Check for ring index overlap in the Tx desc ring */
++        if (tx_desc_curr == tx_desc_used) 
++	{
++           p_eth_port_ctrl->tx_resource_err = 1;
++           return ETH_QUEUE_LAST_RESOURCE;
++        }
++
++        return ETH_OK;
++}
++#else // __NICO_HARDWARE_CSUM__
+ /*
+  * Modified to include the first descriptor pointer in case of SG
+  */
+@@ -2297,6 +2954,9 @@
+ 		return ETH_ERROR;
+ 
+ 	tx_next_desc = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
++
++	// Nico: Warning ETH_ZERO_PADDING is only valid if the L flag is set
++	// the behaviour of the chip could be unexpected in that case
+ 	command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+ 
+ 	if (command_status & ETH_TX_FIRST_DESC) {
+@@ -2340,8 +3000,6 @@
+ 
+         mp->tx_skb[tx_desc_curr] = (struct sk_buff*) p_pkt_info->return_info;
+ 
+-        wmb();
+-
+         /* Set last desc with DMA ownership and interrupt enable. */
+         if (command_status & ETH_TX_LAST_DESC) {
+                 current_descriptor->cmd_sts = command_status |
+@@ -2350,14 +3008,14 @@
+ 
+ 		if (!(command_status & ETH_TX_FIRST_DESC))
+ 			first_descriptor->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA;
+-		wmb();
+-
+ 		first_chip_ptr = MV_READ(MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(mp->port_num));
+ 
+ 		/* Apply send command */
+ 		if (first_chip_ptr == 0x00000000)
+ 			MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(mp->port_num), (struct eth_tx_desc *) mp->tx_desc_dma + tx_first_desc);
+ 
++		mb();
++
+                 ETH_ENABLE_TX_QUEUE(mp->port_num);
+ 
+ 		/*
+@@ -2385,6 +3043,8 @@
+ 
+         return ETH_OK;
+ }
++#endif //__NICO_HARDWARE_CSUM__
++
+ #else
+ static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
+ 					 struct pkt_info * p_pkt_info)
+@@ -2413,6 +3073,7 @@
+ 	 * 64-bit boundary. We use the memory allocated for Tx descriptor.
+ 	 * This memory is located in TX_BUF_OFFSET_IN_DESC offset within the
+ 	 * Tx descriptor. */
++
+ 	if (p_pkt_info->byte_cnt <= 8) {
+ 		printk(KERN_ERR
+ 		       "You have failed in the < 8 bytes errata - fixme\n");
+@@ -2422,12 +3083,12 @@
+ 	current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+ 	mp->tx_skb[tx_desc_curr] = (struct sk_buff *) p_pkt_info->return_info;
+ 
+-	mb();
+-
+ 	/* Set last desc with DMA ownership and interrupt enable. */
+ 	current_descriptor->cmd_sts = command_status |
+ 			ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
+ 
++	mb();
++
+ 	/* Apply send command */
+ 	ETH_ENABLE_TX_QUEUE(mp->port_num);
+ 
+@@ -2566,6 +3227,8 @@
+ 	/* The following parameters are used to save readings from memory */
+ 	command_status = p_rx_desc->cmd_sts;
+ 
++	rmb();
++
+ 	/* Nothing to receive... */
+ 	if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+ 		return ETH_END_OF_JOB;
+diff -urN linux-2.6.9.orig/drivers/net/mv643xx_eth.h linux-2.6.9/drivers/net/mv643xx_eth.h
+--- linux-2.6.9.orig/drivers/net/mv643xx_eth.h	2004-10-18 23:54:08.000000000 +0200
++++ linux-2.6.9/drivers/net/mv643xx_eth.h	2004-10-27 10:31:59.677470776 +0200
+@@ -51,7 +51,7 @@
+ #define ETH_PORT2_IRQ_NUM ETH_PORT0_IRQ_NUM+2	/* main high register, bit1 */
+ 
+ /* Checksum offload for Tx works */
+-#define  MV64340_CHECKSUM_OFFLOAD_TX
++//#define  MV64340_CHECKSUM_OFFLOAD_TX
+ #define	 MV64340_NAPI
+ #define	 MV64340_TX_FAST_REFILL
+ #undef	 MV64340_COAL
+@@ -114,10 +114,18 @@
+ 
+ 
+ /* Default sdma control value */
++#ifdef __PPC__
++#define PORT_SDMA_CONFIG_VALUE			\
++			 ETH_RX_BURST_SIZE_4_64BIT 	|	\
++			 GT_ETH_IPG_INT_RX(0) 		|	\
++			 ETH_TX_BURST_SIZE_4_64BIT
++#else
+ #define PORT_SDMA_CONFIG_VALUE			\
+ 			 ETH_RX_BURST_SIZE_16_64BIT 	|	\
+ 			 GT_ETH_IPG_INT_RX(0) 		|	\
+ 			 ETH_TX_BURST_SIZE_16_64BIT;
++#endif
++
+ 
+ #define GT_ETH_IPG_INT_RX(value)                \
+             ((value & 0x3fff) << 8)
+@@ -417,6 +425,10 @@
+ #define ETH_TX_ENABLE_INTERRUPT             (BIT23)
+ #define ETH_AUTO_MODE                       (BIT30)
+ 
++
++// Useful def
++#define MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)                (0x247c + (port<<10))
++
+ /* typedefs */
+ 
+ typedef enum _eth_func_ret_status {
+diff -urN linux-2.6.9.orig/include/asm-ppc/marvell.h linux-2.6.9/include/asm-ppc/marvell.h
+--- linux-2.6.9.orig/include/asm-ppc/marvell.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.9/include/asm-ppc/marvell.h	2004-10-27 10:31:59.736461808 +0200
+@@ -0,0 +1,58 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2004 by Ralf Baechle
++ */
++#ifndef __ASM_PPC_MARVELL_H
++#define __ASM_PPC_MARVELL_H
++
++#include <asm/byteorder.h>
++#include <asm/system.h>
++
++extern unsigned long marvell_base;
++
++/*
++ * Because of an error/peculiarity in the Galileo chip, we need to swap the
++ * bytes when running bigendian.
++ */
++/*
++ * Nicolas DET:
++ * On PowerPC (especially for G4) we have to be careful about the re-ordering
++ * as aresult I add some mb() in the MV_xxxx macros
++*/
++#define __MV_READ(ofs)								\
++	(*(volatile u32 *)(marvell_base+(ofs)))					
++
++#define __MV_WRITE(ofs, data)							\
++	do { *(volatile u32 *)(marvell_base+(ofs)) = (data); } while (0)	
++
++#if 1
++extern inline u32 mv_read(u32 offset)
++{
++	u32 RegVal = le32_to_cpu(__MV_READ(offset));
++	rmb();
++	return RegVal;
++}
++
++extern inline void mv_write(u32 offset, u32 RegVal)
++{
++	__MV_WRITE(offset, cpu_to_le32(RegVal));
++	wmb();
++}
++
++#define MV_READ(ofs) 		mv_read( (u32) ofs)
++#define MV_WRITE(ofs, data) 	mv_write( (u32) ofs, (u32) data)
++
++#else
++#define MV_READ(ofs)		le32_to_cpu(__MV_READ(ofs))
++#define MV_WRITE(ofs, data)	__MV_WRITE(ofs, cpu_to_le32(data))
++#endif
++
++#define MV_SET_REG_BITS(ofs, bits)					\
++	(*((volatile u32 *)(marvell_base + (ofs)))) |= ((u32)cpu_to_le32(bits))
++#define MV_RESET_REG_BITS(ofs, bits)					\
++	(*((volatile u32 *)(marvell_base + (ofs)))) &= ~((u32)cpu_to_le32(bits))
++
++#endif	/* __ASM_PPC_MARVELL_H */
+diff -urN linux-2.6.9.orig/include/asm-ppc/mv643xx.h linux-2.6.9/include/asm-ppc/mv643xx.h
+--- linux-2.6.9.orig/include/asm-ppc/mv643xx.h	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.9/include/asm-ppc/mv643xx.h	2004-10-27 10:31:59.803451624 +0200
+@@ -0,0 +1,1070 @@
++/*
++ * mv64340.h - MV-64340 Internal registers definition file.
++ *
++ * Copyright 2002 Momentum Computer, Inc.
++ * 	Author: Matthew Dharm <mdharm at momenco.com>
++ * Copyright 2002 GALILEO TECHNOLOGY, LTD. 
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++#ifndef __ASM_MV64340_H
++#define __ASM_MV64340_H
++
++#include <asm/byteorder.h>
++
++/****************************************/
++/* Processor Address Space              */
++/****************************************/
++
++/* DDR SDRAM BAR and size registers */
++
++#define MV64340_CS_0_BASE_ADDR                                      0x008
++#define MV64340_CS_0_SIZE                                           0x010
++#define MV64340_CS_1_BASE_ADDR                                      0x208
++#define MV64340_CS_1_SIZE                                           0x210
++#define MV64340_CS_2_BASE_ADDR                                      0x018
++#define MV64340_CS_2_SIZE                                           0x020
++#define MV64340_CS_3_BASE_ADDR                                      0x218
++#define MV64340_CS_3_SIZE                                           0x220
++
++/* Devices BAR and size registers */
++
++#define MV64340_DEV_CS0_BASE_ADDR                                   0x028
++#define MV64340_DEV_CS0_SIZE                                        0x030
++#define MV64340_DEV_CS1_BASE_ADDR                                   0x228
++#define MV64340_DEV_CS1_SIZE                                        0x230
++#define MV64340_DEV_CS2_BASE_ADDR                                   0x248
++#define MV64340_DEV_CS2_SIZE                                        0x250
++#define MV64340_DEV_CS3_BASE_ADDR                                   0x038
++#define MV64340_DEV_CS3_SIZE                                        0x040
++#define MV64340_BOOTCS_BASE_ADDR                                    0x238
++#define MV64340_BOOTCS_SIZE                                         0x240
++
++/* PCI 0 BAR and size registers */
++
++#define MV64340_PCI_0_IO_BASE_ADDR                                  0x048
++#define MV64340_PCI_0_IO_SIZE                                       0x050
++#define MV64340_PCI_0_MEMORY0_BASE_ADDR                             0x058
++#define MV64340_PCI_0_MEMORY0_SIZE                                  0x060
++#define MV64340_PCI_0_MEMORY1_BASE_ADDR                             0x080
++#define MV64340_PCI_0_MEMORY1_SIZE                                  0x088
++#define MV64340_PCI_0_MEMORY2_BASE_ADDR                             0x258
++#define MV64340_PCI_0_MEMORY2_SIZE                                  0x260
++#define MV64340_PCI_0_MEMORY3_BASE_ADDR                             0x280
++#define MV64340_PCI_0_MEMORY3_SIZE                                  0x288
++
++/* PCI 1 BAR and size registers */
++#define MV64340_PCI_1_IO_BASE_ADDR                                  0x090
++#define MV64340_PCI_1_IO_SIZE                                       0x098
++#define MV64340_PCI_1_MEMORY0_BASE_ADDR                             0x0a0
++#define MV64340_PCI_1_MEMORY0_SIZE                                  0x0a8
++#define MV64340_PCI_1_MEMORY1_BASE_ADDR                             0x0b0
++#define MV64340_PCI_1_MEMORY1_SIZE                                  0x0b8
++#define MV64340_PCI_1_MEMORY2_BASE_ADDR                             0x2a0
++#define MV64340_PCI_1_MEMORY2_SIZE                                  0x2a8
++#define MV64340_PCI_1_MEMORY3_BASE_ADDR                             0x2b0
++#define MV64340_PCI_1_MEMORY3_SIZE                                  0x2b8
++
++/* SRAM base address */
++#define MV64340_INTEGRATED_SRAM_BASE_ADDR                           0x268
++
++/* internal registers space base address */
++#define MV64340_INTERNAL_SPACE_BASE_ADDR                            0x068
++
++/* Enables the CS , DEV_CS , PCI 0 and PCI 1 
++   windows above */
++#define MV64340_BASE_ADDR_ENABLE                                    0x278
++
++/****************************************/
++/* PCI remap registers                  */
++/****************************************/
++      /* PCI 0 */
++#define MV64340_PCI_0_IO_ADDR_REMAP                                 0x0f0
++#define MV64340_PCI_0_MEMORY0_LOW_ADDR_REMAP                        0x0f8
++#define MV64340_PCI_0_MEMORY0_HIGH_ADDR_REMAP                       0x320
++#define MV64340_PCI_0_MEMORY1_LOW_ADDR_REMAP                        0x100
++#define MV64340_PCI_0_MEMORY1_HIGH_ADDR_REMAP                       0x328
++#define MV64340_PCI_0_MEMORY2_LOW_ADDR_REMAP                        0x2f8
++#define MV64340_PCI_0_MEMORY2_HIGH_ADDR_REMAP                       0x330
++#define MV64340_PCI_0_MEMORY3_LOW_ADDR_REMAP                        0x300
++#define MV64340_PCI_0_MEMORY3_HIGH_ADDR_REMAP                       0x338
++      /* PCI 1 */
++#define MV64340_PCI_1_IO_ADDR_REMAP                                 0x108
++#define MV64340_PCI_1_MEMORY0_LOW_ADDR_REMAP                        0x110
++#define MV64340_PCI_1_MEMORY0_HIGH_ADDR_REMAP                       0x340
++#define MV64340_PCI_1_MEMORY1_LOW_ADDR_REMAP                        0x118
++#define MV64340_PCI_1_MEMORY1_HIGH_ADDR_REMAP                       0x348
++#define MV64340_PCI_1_MEMORY2_LOW_ADDR_REMAP                        0x310
++#define MV64340_PCI_1_MEMORY2_HIGH_ADDR_REMAP                       0x350
++#define MV64340_PCI_1_MEMORY3_LOW_ADDR_REMAP                        0x318
++#define MV64340_PCI_1_MEMORY3_HIGH_ADDR_REMAP                       0x358
++ 
++#define MV64340_CPU_PCI_0_HEADERS_RETARGET_CONTROL                  0x3b0
++#define MV64340_CPU_PCI_0_HEADERS_RETARGET_BASE                     0x3b8
++#define MV64340_CPU_PCI_1_HEADERS_RETARGET_CONTROL                  0x3c0
++#define MV64340_CPU_PCI_1_HEADERS_RETARGET_BASE                     0x3c8
++#define MV64340_CPU_GE_HEADERS_RETARGET_CONTROL                     0x3d0
++#define MV64340_CPU_GE_HEADERS_RETARGET_BASE                        0x3d8
++#define MV64340_CPU_IDMA_HEADERS_RETARGET_CONTROL                   0x3e0
++#define MV64340_CPU_IDMA_HEADERS_RETARGET_BASE                      0x3e8
++
++/****************************************/
++/*         CPU Control Registers        */
++/****************************************/
++
++#define MV64340_CPU_CONFIG                                          0x000
++#define MV64340_CPU_MODE                                            0x120
++#define MV64340_CPU_MASTER_CONTROL                                  0x160
++#define MV64340_CPU_CROSS_BAR_CONTROL_LOW                           0x150
++#define MV64340_CPU_CROSS_BAR_CONTROL_HIGH                          0x158
++#define MV64340_CPU_CROSS_BAR_TIMEOUT                               0x168
++
++/****************************************/
++/* SMP RegisterS                        */
++/****************************************/
++
++#define MV64340_SMP_WHO_AM_I                                        0x200
++#define MV64340_SMP_CPU0_DOORBELL                                   0x214
++#define MV64340_SMP_CPU0_DOORBELL_CLEAR                             0x21C
++#define MV64340_SMP_CPU1_DOORBELL                                   0x224
++#define MV64340_SMP_CPU1_DOORBELL_CLEAR                             0x22C
++#define MV64340_SMP_CPU0_DOORBELL_MASK                              0x234
++#define MV64340_SMP_CPU1_DOORBELL_MASK                              0x23C
++#define MV64340_SMP_SEMAPHOR0                                       0x244
++#define MV64340_SMP_SEMAPHOR1                                       0x24c
++#define MV64340_SMP_SEMAPHOR2                                       0x254
++#define MV64340_SMP_SEMAPHOR3                                       0x25c
++#define MV64340_SMP_SEMAPHOR4                                       0x264
++#define MV64340_SMP_SEMAPHOR5                                       0x26c
++#define MV64340_SMP_SEMAPHOR6                                       0x274
++#define MV64340_SMP_SEMAPHOR7                                       0x27c
++
++/****************************************/
++/*  CPU Sync Barrier Register           */
++/****************************************/
++
++#define MV64340_CPU_0_SYNC_BARRIER_TRIGGER                          0x0c0
++#define MV64340_CPU_0_SYNC_BARRIER_VIRTUAL                          0x0c8
++#define MV64340_CPU_1_SYNC_BARRIER_TRIGGER                          0x0d0
++#define MV64340_CPU_1_SYNC_BARRIER_VIRTUAL                          0x0d8
++
++/****************************************/
++/* CPU Access Protect                   */
++/****************************************/
++
++#define MV64340_CPU_PROTECT_WINDOW_0_BASE_ADDR                      0x180
++#define MV64340_CPU_PROTECT_WINDOW_0_SIZE                           0x188
++#define MV64340_CPU_PROTECT_WINDOW_1_BASE_ADDR                      0x190
++#define MV64340_CPU_PROTECT_WINDOW_1_SIZE                           0x198
++#define MV64340_CPU_PROTECT_WINDOW_2_BASE_ADDR                      0x1a0
++#define MV64340_CPU_PROTECT_WINDOW_2_SIZE                           0x1a8
++#define MV64340_CPU_PROTECT_WINDOW_3_BASE_ADDR                      0x1b0
++#define MV64340_CPU_PROTECT_WINDOW_3_SIZE                           0x1b8
++
++
++/****************************************/
++/*          CPU Error Report            */
++/****************************************/
++
++#define MV64340_CPU_ERROR_ADDR_LOW                                  0x070
++#define MV64340_CPU_ERROR_ADDR_HIGH                                 0x078
++#define MV64340_CPU_ERROR_DATA_LOW                                  0x128
++#define MV64340_CPU_ERROR_DATA_HIGH                                 0x130
++#define MV64340_CPU_ERROR_PARITY                                    0x138
++#define MV64340_CPU_ERROR_CAUSE                                     0x140
++#define MV64340_CPU_ERROR_MASK                                      0x148
++
++/****************************************/
++/*      CPU Interface Debug Registers 	*/
++/****************************************/
++
++#define MV64340_PUNIT_SLAVE_DEBUG_LOW                               0x360
++#define MV64340_PUNIT_SLAVE_DEBUG_HIGH                              0x368
++#define MV64340_PUNIT_MASTER_DEBUG_LOW                              0x370
++#define MV64340_PUNIT_MASTER_DEBUG_HIGH                             0x378
++#define MV64340_PUNIT_MMASK                                         0x3e4
++
++/****************************************/
++/*  Integrated SRAM Registers           */
++/****************************************/
++
++#define MV64340_SRAM_CONFIG                                         0x380
++#define MV64340_SRAM_TEST_MODE                                      0X3F4
++#define MV64340_SRAM_ERROR_CAUSE                                    0x388
++#define MV64340_SRAM_ERROR_ADDR                                     0x390
++#define MV64340_SRAM_ERROR_ADDR_HIGH                                0X3F8
++#define MV64340_SRAM_ERROR_DATA_LOW                                 0x398
++#define MV64340_SRAM_ERROR_DATA_HIGH                                0x3a0
++#define MV64340_SRAM_ERROR_DATA_PARITY                              0x3a8
++
++/****************************************/
++/* SDRAM Configuration                  */
++/****************************************/
++
++#define MV64340_SDRAM_CONFIG                                        0x1400
++#define MV64340_D_UNIT_CONTROL_LOW                                  0x1404
++#define MV64340_D_UNIT_CONTROL_HIGH                                 0x1424
++#define MV64340_SDRAM_TIMING_CONTROL_LOW                            0x1408
++#define MV64340_SDRAM_TIMING_CONTROL_HIGH                           0x140c
++#define MV64340_SDRAM_ADDR_CONTROL                                  0x1410
++#define MV64340_SDRAM_OPEN_PAGES_CONTROL                            0x1414
++#define MV64340_SDRAM_OPERATION                                     0x1418
++#define MV64340_SDRAM_MODE                                          0x141c
++#define MV64340_EXTENDED_DRAM_MODE                                  0x1420
++#define MV64340_SDRAM_CROSS_BAR_CONTROL_LOW                         0x1430
++#define MV64340_SDRAM_CROSS_BAR_CONTROL_HIGH                        0x1434
++#define MV64340_SDRAM_CROSS_BAR_TIMEOUT                             0x1438
++#define MV64340_SDRAM_ADDR_CTRL_PADS_CALIBRATION                    0x14c0
++#define MV64340_SDRAM_DATA_PADS_CALIBRATION                         0x14c4
++
++/****************************************/
++/* SDRAM Error Report                   */
++/****************************************/
++
++#define MV64340_SDRAM_ERROR_DATA_LOW                                0x1444
++#define MV64340_SDRAM_ERROR_DATA_HIGH                               0x1440
++#define MV64340_SDRAM_ERROR_ADDR                                    0x1450
++#define MV64340_SDRAM_RECEIVED_ECC                                  0x1448
++#define MV64340_SDRAM_CALCULATED_ECC                                0x144c
++#define MV64340_SDRAM_ECC_CONTROL                                   0x1454
++#define MV64340_SDRAM_ECC_ERROR_COUNTER                             0x1458
++
++/******************************************/
++/*  Controlled Delay Line (CDL) Registers */
++/******************************************/
++
++#define MV64340_DFCDL_CONFIG0                                       0x1480
++#define MV64340_DFCDL_CONFIG1                                       0x1484
++#define MV64340_DLL_WRITE                                           0x1488
++#define MV64340_DLL_READ                                            0x148c
++#define MV64340_SRAM_ADDR                                           0x1490
++#define MV64340_SRAM_DATA0                                          0x1494
++#define MV64340_SRAM_DATA1                                          0x1498
++#define MV64340_SRAM_DATA2                                          0x149c
++#define MV64340_DFCL_PROBE                                          0x14a0
++
++/******************************************/
++/*   Debug Registers                      */
++/******************************************/
++
++#define MV64340_DUNIT_DEBUG_LOW                                     0x1460
++#define MV64340_DUNIT_DEBUG_HIGH                                    0x1464
++#define MV64340_DUNIT_MMASK                                         0X1b40
++
++/****************************************/
++/* Device Parameters			*/
++/****************************************/
++
++#define MV64340_DEVICE_BANK0_PARAMETERS				    0x45c
++#define MV64340_DEVICE_BANK1_PARAMETERS				    0x460
++#define MV64340_DEVICE_BANK2_PARAMETERS				    0x464
++#define MV64340_DEVICE_BANK3_PARAMETERS				    0x468
++#define MV64340_DEVICE_BOOT_BANK_PARAMETERS			    0x46c
++#define MV64340_DEVICE_INTERFACE_CONTROL                            0x4c0
++#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_LOW              0x4c8
++#define MV64340_DEVICE_INTERFACE_CROSS_BAR_CONTROL_HIGH             0x4cc
++#define MV64340_DEVICE_INTERFACE_CROSS_BAR_TIMEOUT                  0x4c4
++
++/****************************************/
++/* Device interrupt registers		*/
++/****************************************/
++
++#define MV64340_DEVICE_INTERRUPT_CAUSE				    0x4d0
++#define MV64340_DEVICE_INTERRUPT_MASK				    0x4d4
++#define MV64340_DEVICE_ERROR_ADDR				    0x4d8
++#define MV64340_DEVICE_ERROR_DATA   				    0x4dc
++#define MV64340_DEVICE_ERROR_PARITY     			    0x4e0
++
++/****************************************/
++/* Device debug registers   		*/
++/****************************************/
++
++#define MV64340_DEVICE_DEBUG_LOW     				    0x4e4
++#define MV64340_DEVICE_DEBUG_HIGH     				    0x4e8
++#define MV64340_RUNIT_MMASK                                         0x4f0
++
++/****************************************/
++/* PCI Slave Address Decoding registers */
++/****************************************/
++
++#define MV64340_PCI_0_CS_0_BANK_SIZE                                0xc08
++#define MV64340_PCI_1_CS_0_BANK_SIZE                                0xc88
++#define MV64340_PCI_0_CS_1_BANK_SIZE                                0xd08
++#define MV64340_PCI_1_CS_1_BANK_SIZE                                0xd88
++#define MV64340_PCI_0_CS_2_BANK_SIZE                                0xc0c
++#define MV64340_PCI_1_CS_2_BANK_SIZE                                0xc8c
++#define MV64340_PCI_0_CS_3_BANK_SIZE                                0xd0c
++#define MV64340_PCI_1_CS_3_BANK_SIZE                                0xd8c
++#define MV64340_PCI_0_DEVCS_0_BANK_SIZE                             0xc10
++#define MV64340_PCI_1_DEVCS_0_BANK_SIZE                             0xc90
++#define MV64340_PCI_0_DEVCS_1_BANK_SIZE                             0xd10
++#define MV64340_PCI_1_DEVCS_1_BANK_SIZE                             0xd90
++#define MV64340_PCI_0_DEVCS_2_BANK_SIZE                             0xd18
++#define MV64340_PCI_1_DEVCS_2_BANK_SIZE                             0xd98
++#define MV64340_PCI_0_DEVCS_3_BANK_SIZE                             0xc14
++#define MV64340_PCI_1_DEVCS_3_BANK_SIZE                             0xc94
++#define MV64340_PCI_0_DEVCS_BOOT_BANK_SIZE                          0xd14
++#define MV64340_PCI_1_DEVCS_BOOT_BANK_SIZE                          0xd94
++#define MV64340_PCI_0_P2P_MEM0_BAR_SIZE                             0xd1c
++#define MV64340_PCI_1_P2P_MEM0_BAR_SIZE                             0xd9c
++#define MV64340_PCI_0_P2P_MEM1_BAR_SIZE                             0xd20
++#define MV64340_PCI_1_P2P_MEM1_BAR_SIZE                             0xda0
++#define MV64340_PCI_0_P2P_I_O_BAR_SIZE                              0xd24
++#define MV64340_PCI_1_P2P_I_O_BAR_SIZE                              0xda4
++#define MV64340_PCI_0_CPU_BAR_SIZE                                  0xd28
++#define MV64340_PCI_1_CPU_BAR_SIZE                                  0xda8
++#define MV64340_PCI_0_INTERNAL_SRAM_BAR_SIZE                        0xe00
++#define MV64340_PCI_1_INTERNAL_SRAM_BAR_SIZE                        0xe80
++#define MV64340_PCI_0_EXPANSION_ROM_BAR_SIZE                        0xd2c
++#define MV64340_PCI_1_EXPANSION_ROM_BAR_SIZE                        0xd9c
++#define MV64340_PCI_0_BASE_ADDR_REG_ENABLE                          0xc3c
++#define MV64340_PCI_1_BASE_ADDR_REG_ENABLE                          0xcbc
++#define MV64340_PCI_0_CS_0_BASE_ADDR_REMAP			    0xc48
++#define MV64340_PCI_1_CS_0_BASE_ADDR_REMAP			    0xcc8
++#define MV64340_PCI_0_CS_1_BASE_ADDR_REMAP			    0xd48
++#define MV64340_PCI_1_CS_1_BASE_ADDR_REMAP			    0xdc8
++#define MV64340_PCI_0_CS_2_BASE_ADDR_REMAP			    0xc4c
++#define MV64340_PCI_1_CS_2_BASE_ADDR_REMAP			    0xccc
++#define MV64340_PCI_0_CS_3_BASE_ADDR_REMAP			    0xd4c
++#define MV64340_PCI_1_CS_3_BASE_ADDR_REMAP			    0xdcc
++#define MV64340_PCI_0_CS_0_BASE_HIGH_ADDR_REMAP			    0xF04
++#define MV64340_PCI_1_CS_0_BASE_HIGH_ADDR_REMAP			    0xF84
++#define MV64340_PCI_0_CS_1_BASE_HIGH_ADDR_REMAP			    0xF08
++#define MV64340_PCI_1_CS_1_BASE_HIGH_ADDR_REMAP			    0xF88
++#define MV64340_PCI_0_CS_2_BASE_HIGH_ADDR_REMAP			    0xF0C
++#define MV64340_PCI_1_CS_2_BASE_HIGH_ADDR_REMAP			    0xF8C
++#define MV64340_PCI_0_CS_3_BASE_HIGH_ADDR_REMAP			    0xF10
++#define MV64340_PCI_1_CS_3_BASE_HIGH_ADDR_REMAP			    0xF90
++#define MV64340_PCI_0_DEVCS_0_BASE_ADDR_REMAP			    0xc50
++#define MV64340_PCI_1_DEVCS_0_BASE_ADDR_REMAP			    0xcd0
++#define MV64340_PCI_0_DEVCS_1_BASE_ADDR_REMAP			    0xd50
++#define MV64340_PCI_1_DEVCS_1_BASE_ADDR_REMAP			    0xdd0
++#define MV64340_PCI_0_DEVCS_2_BASE_ADDR_REMAP			    0xd58
++#define MV64340_PCI_1_DEVCS_2_BASE_ADDR_REMAP			    0xdd8
++#define MV64340_PCI_0_DEVCS_3_BASE_ADDR_REMAP           	    0xc54
++#define MV64340_PCI_1_DEVCS_3_BASE_ADDR_REMAP           	    0xcd4
++#define MV64340_PCI_0_DEVCS_BOOTCS_BASE_ADDR_REMAP      	    0xd54
++#define MV64340_PCI_1_DEVCS_BOOTCS_BASE_ADDR_REMAP      	    0xdd4
++#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xd5c
++#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_LOW                  0xddc
++#define MV64340_PCI_0_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xd60
++#define MV64340_PCI_1_P2P_MEM0_BASE_ADDR_REMAP_HIGH                 0xde0
++#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xd64
++#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_LOW                  0xde4
++#define MV64340_PCI_0_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xd68
++#define MV64340_PCI_1_P2P_MEM1_BASE_ADDR_REMAP_HIGH                 0xde8
++#define MV64340_PCI_0_P2P_I_O_BASE_ADDR_REMAP                       0xd6c
++#define MV64340_PCI_1_P2P_I_O_BASE_ADDR_REMAP                       0xdec 
++#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_LOW                       0xd70
++#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_LOW                       0xdf0
++#define MV64340_PCI_0_CPU_BASE_ADDR_REMAP_HIGH                      0xd74
++#define MV64340_PCI_1_CPU_BASE_ADDR_REMAP_HIGH                      0xdf4
++#define MV64340_PCI_0_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf00
++#define MV64340_PCI_1_INTEGRATED_SRAM_BASE_ADDR_REMAP               0xf80
++#define MV64340_PCI_0_EXPANSION_ROM_BASE_ADDR_REMAP                 0xf38
++#define MV64340_PCI_1_EXPANSION_ROM_BASE_ADDR_REMAP                 0xfb8
++#define MV64340_PCI_0_ADDR_DECODE_CONTROL                           0xd3c
++#define MV64340_PCI_1_ADDR_DECODE_CONTROL                           0xdbc
++#define MV64340_PCI_0_HEADERS_RETARGET_CONTROL                      0xF40
++#define MV64340_PCI_1_HEADERS_RETARGET_CONTROL                      0xFc0
++#define MV64340_PCI_0_HEADERS_RETARGET_BASE                         0xF44
++#define MV64340_PCI_1_HEADERS_RETARGET_BASE                         0xFc4
++#define MV64340_PCI_0_HEADERS_RETARGET_HIGH                         0xF48
++#define MV64340_PCI_1_HEADERS_RETARGET_HIGH                         0xFc8
++
++/***********************************/
++/*   PCI Control Register Map      */
++/***********************************/
++
++#define MV64340_PCI_0_DLL_STATUS_AND_COMMAND                        0x1d20
++#define MV64340_PCI_1_DLL_STATUS_AND_COMMAND                        0x1da0
++#define MV64340_PCI_0_MPP_PADS_DRIVE_CONTROL                        0x1d1C
++#define MV64340_PCI_1_MPP_PADS_DRIVE_CONTROL                        0x1d9C
++#define MV64340_PCI_0_COMMAND			         	    0xc00
++#define MV64340_PCI_1_COMMAND					    0xc80
++#define MV64340_PCI_0_MODE                                          0xd00
++#define MV64340_PCI_1_MODE                                          0xd80
++#define MV64340_PCI_0_RETRY	        	 		    0xc04
++#define MV64340_PCI_1_RETRY				            0xc84
++#define MV64340_PCI_0_READ_BUFFER_DISCARD_TIMER                     0xd04
++#define MV64340_PCI_1_READ_BUFFER_DISCARD_TIMER                     0xd84
++#define MV64340_PCI_0_MSI_TRIGGER_TIMER                             0xc38
++#define MV64340_PCI_1_MSI_TRIGGER_TIMER                             0xcb8
++#define MV64340_PCI_0_ARBITER_CONTROL                               0x1d00
++#define MV64340_PCI_1_ARBITER_CONTROL                               0x1d80
++#define MV64340_PCI_0_CROSS_BAR_CONTROL_LOW                         0x1d08
++#define MV64340_PCI_1_CROSS_BAR_CONTROL_LOW                         0x1d88
++#define MV64340_PCI_0_CROSS_BAR_CONTROL_HIGH                        0x1d0c
++#define MV64340_PCI_1_CROSS_BAR_CONTROL_HIGH                        0x1d8c
++#define MV64340_PCI_0_CROSS_BAR_TIMEOUT                             0x1d04
++#define MV64340_PCI_1_CROSS_BAR_TIMEOUT                             0x1d84
++#define MV64340_PCI_0_SYNC_BARRIER_TRIGGER_REG                      0x1D18
++#define MV64340_PCI_1_SYNC_BARRIER_TRIGGER_REG                      0x1D98
++#define MV64340_PCI_0_SYNC_BARRIER_VIRTUAL_REG                      0x1d10
++#define MV64340_PCI_1_SYNC_BARRIER_VIRTUAL_REG                      0x1d90
++#define MV64340_PCI_0_P2P_CONFIG                                    0x1d14
++#define MV64340_PCI_1_P2P_CONFIG                                    0x1d94
++
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_LOW                     0x1e00
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_0_HIGH                    0x1e04
++#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_0                         0x1e08
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_LOW                     0x1e10
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_1_HIGH                    0x1e14
++#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_1                         0x1e18
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_LOW                     0x1e20
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_2_HIGH                    0x1e24
++#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_2                         0x1e28
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_LOW                     0x1e30
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_3_HIGH                    0x1e34
++#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_3                         0x1e38
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_LOW                     0x1e40
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_4_HIGH                    0x1e44
++#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_4                         0x1e48
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_LOW                     0x1e50
++#define MV64340_PCI_0_ACCESS_CONTROL_BASE_5_HIGH                    0x1e54
++#define MV64340_PCI_0_ACCESS_CONTROL_SIZE_5                         0x1e58
++
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_LOW                     0x1e80
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_0_HIGH                    0x1e84
++#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_0                         0x1e88
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_LOW                     0x1e90
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_1_HIGH                    0x1e94
++#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_1                         0x1e98
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_LOW                     0x1ea0
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_2_HIGH                    0x1ea4
++#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_2                         0x1ea8
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_LOW                     0x1eb0
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_3_HIGH                    0x1eb4
++#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_3                         0x1eb8
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_LOW                     0x1ec0
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_4_HIGH                    0x1ec4
++#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_4                         0x1ec8
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_LOW                     0x1ed0
++#define MV64340_PCI_1_ACCESS_CONTROL_BASE_5_HIGH                    0x1ed4
++#define MV64340_PCI_1_ACCESS_CONTROL_SIZE_5                         0x1ed8
++
++/****************************************/
++/*   PCI Configuration Access Registers */
++/****************************************/
++
++#define MV64340_PCI_0_CONFIG_ADDR 				    0xcf8
++#define MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG                       0xcfc
++#define MV64340_PCI_1_CONFIG_ADDR 				    0xc78
++#define MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG                       0xc7c
++#define MV64340_PCI_0_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG	            0xc34
++#define MV64340_PCI_1_INTERRUPT_ACKNOWLEDGE_VIRTUAL_REG	            0xcb4
++
++/****************************************/
++/*   PCI Error Report Registers         */
++/****************************************/
++
++#define MV64340_PCI_0_SERR_MASK					    0xc28
++#define MV64340_PCI_1_SERR_MASK					    0xca8
++#define MV64340_PCI_0_ERROR_ADDR_LOW                                0x1d40
++#define MV64340_PCI_1_ERROR_ADDR_LOW                                0x1dc0
++#define MV64340_PCI_0_ERROR_ADDR_HIGH                               0x1d44
++#define MV64340_PCI_1_ERROR_ADDR_HIGH                               0x1dc4
++#define MV64340_PCI_0_ERROR_ATTRIBUTE                               0x1d48
++#define MV64340_PCI_1_ERROR_ATTRIBUTE                               0x1dc8
++#define MV64340_PCI_0_ERROR_COMMAND                                 0x1d50
++#define MV64340_PCI_1_ERROR_COMMAND                                 0x1dd0
++#define MV64340_PCI_0_ERROR_CAUSE                                   0x1d58
++#define MV64340_PCI_1_ERROR_CAUSE                                   0x1dd8
++#define MV64340_PCI_0_ERROR_MASK                                    0x1d5c
++#define MV64340_PCI_1_ERROR_MASK                                    0x1ddc
++
++/****************************************/
++/*   PCI Debug Registers                */
++/****************************************/
++
++#define MV64340_PCI_0_MMASK                                         0X1D24
++#define MV64340_PCI_1_MMASK                                         0X1DA4
++
++/*********************************************/
++/* PCI Configuration, Function 0, Registers  */
++/*********************************************/
++
++#define MV64340_PCI_DEVICE_AND_VENDOR_ID 			    0x000
++#define MV64340_PCI_STATUS_AND_COMMAND				    0x004
++#define MV64340_PCI_CLASS_CODE_AND_REVISION_ID			    0x008
++#define MV64340_PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 	    0x00C
++
++#define MV64340_PCI_SCS_0_BASE_ADDR_LOW   	      		    0x010
++#define MV64340_PCI_SCS_0_BASE_ADDR_HIGH   		            0x014
++#define MV64340_PCI_SCS_1_BASE_ADDR_LOW  	     	            0x018
++#define MV64340_PCI_SCS_1_BASE_ADDR_HIGH 		            0x01C
++#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_LOW      	    0x020
++#define MV64340_PCI_INTERNAL_REG_MEM_MAPPED_BASE_ADDR_HIGH     	    0x024
++#define MV64340_PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID	    0x02c
++#define MV64340_PCI_EXPANSION_ROM_BASE_ADDR_REG	                    0x030
++#define MV64340_PCI_CAPABILTY_LIST_POINTER                          0x034
++#define MV64340_PCI_INTERRUPT_PIN_AND_LINE 			    0x03C
++       /* capability list */
++#define MV64340_PCI_POWER_MANAGEMENT_CAPABILITY                     0x040
++#define MV64340_PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL             0x044
++#define MV64340_PCI_VPD_ADDR                                        0x048
++#define MV64340_PCI_VPD_DATA                                        0x04c
++#define MV64340_PCI_MSI_MESSAGE_CONTROL                             0x050
++#define MV64340_PCI_MSI_MESSAGE_ADDR                                0x054
++#define MV64340_PCI_MSI_MESSAGE_UPPER_ADDR                          0x058
++#define MV64340_PCI_MSI_MESSAGE_DATA                                0x05c
++#define MV64340_PCI_X_COMMAND                                       0x060
++#define MV64340_PCI_X_STATUS                                        0x064
++#define MV64340_PCI_COMPACT_PCI_HOT_SWAP                            0x068
++
++/***********************************************/
++/*   PCI Configuration, Function 1, Registers  */
++/***********************************************/
++
++#define MV64340_PCI_SCS_2_BASE_ADDR_LOW   			    0x110
++#define MV64340_PCI_SCS_2_BASE_ADDR_HIGH			    0x114
++#define MV64340_PCI_SCS_3_BASE_ADDR_LOW 			    0x118
++#define MV64340_PCI_SCS_3_BASE_ADDR_HIGH			    0x11c
++#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_LOW          	    0x120
++#define MV64340_PCI_INTERNAL_SRAM_BASE_ADDR_HIGH         	    0x124
++
++/***********************************************/
++/*  PCI Configuration, Function 2, Registers   */
++/***********************************************/
++
++#define MV64340_PCI_DEVCS_0_BASE_ADDR_LOW	    		    0x210
++#define MV64340_PCI_DEVCS_0_BASE_ADDR_HIGH 			    0x214
++#define MV64340_PCI_DEVCS_1_BASE_ADDR_LOW 			    0x218
++#define MV64340_PCI_DEVCS_1_BASE_ADDR_HIGH      		    0x21c
++#define MV64340_PCI_DEVCS_2_BASE_ADDR_LOW 			    0x220
++#define MV64340_PCI_DEVCS_2_BASE_ADDR_HIGH      		    0x224
++
++/***********************************************/
++/*  PCI Configuration, Function 3, Registers   */
++/***********************************************/
++
++#define MV64340_PCI_DEVCS_3_BASE_ADDR_LOW	    		    0x310
++#define MV64340_PCI_DEVCS_3_BASE_ADDR_HIGH 			    0x314
++#define MV64340_PCI_BOOT_CS_BASE_ADDR_LOW			    0x318
++#define MV64340_PCI_BOOT_CS_BASE_ADDR_HIGH      		    0x31c
++#define MV64340_PCI_CPU_BASE_ADDR_LOW 				    0x220
++#define MV64340_PCI_CPU_BASE_ADDR_HIGH      			    0x224
++
++/***********************************************/
++/*  PCI Configuration, Function 4, Registers   */
++/***********************************************/
++
++#define MV64340_PCI_P2P_MEM0_BASE_ADDR_LOW  			    0x410
++#define MV64340_PCI_P2P_MEM0_BASE_ADDR_HIGH 			    0x414
++#define MV64340_PCI_P2P_MEM1_BASE_ADDR_LOW   			    0x418
++#define MV64340_PCI_P2P_MEM1_BASE_ADDR_HIGH 			    0x41c
++#define MV64340_PCI_P2P_I_O_BASE_ADDR                 	            0x420
++#define MV64340_PCI_INTERNAL_REGS_I_O_MAPPED_BASE_ADDR              0x424
++
++/****************************************/
++/* Messaging Unit Registers (I20)   	*/
++/****************************************/
++
++#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_0_SIDE		    0x010
++#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_0_SIDE  		    0x014
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_0_SIDE 		    0x018
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_0_SIDE  		    0x01C
++#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_0_SIDE  		    0x020
++#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE          0x024
++#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE	    0x028
++#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_0_SIDE 		    0x02C
++#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_0_SIDE         0x030
++#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_0_SIDE          0x034
++#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE       0x040
++#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_0_SIDE      0x044
++#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_0_SIDE 		    0x050
++#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_0_SIDE 		    0x054
++#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE        0x060
++#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE        0x064
++#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE        0x068
++#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE        0x06C
++#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_0_SIDE       0x070
++#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_0_SIDE       0x074
++#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_0_SIDE       0x0F8
++#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_0_SIDE       0x0FC
++
++#define MV64340_I2O_INBOUND_MESSAGE_REG0_PCI_1_SIDE		    0x090
++#define MV64340_I2O_INBOUND_MESSAGE_REG1_PCI_1_SIDE  		    0x094
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_PCI_1_SIDE 		    0x098
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_PCI_1_SIDE  		    0x09C
++#define MV64340_I2O_INBOUND_DOORBELL_REG_PCI_1_SIDE  		    0x0A0
++#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE          0x0A4
++#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE	    0x0A8
++#define MV64340_I2O_OUTBOUND_DOORBELL_REG_PCI_1_SIDE 		    0x0AC
++#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_PCI_1_SIDE         0x0B0
++#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_PCI_1_SIDE          0x0B4
++#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE       0x0C0
++#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_PCI_1_SIDE      0x0C4
++#define MV64340_I2O_QUEUE_CONTROL_REG_PCI_1_SIDE 		    0x0D0
++#define MV64340_I2O_QUEUE_BASE_ADDR_REG_PCI_1_SIDE 		    0x0D4
++#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE        0x0E0
++#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE        0x0E4
++#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE        0x0E8
++#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE        0x0EC
++#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_PCI_1_SIDE       0x0F0
++#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_PCI_1_SIDE       0x0F4
++#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_PCI_1_SIDE       0x078
++#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_PCI_1_SIDE       0x07C
++
++#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU0_SIDE		    0x1C10
++#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU0_SIDE  		    0x1C14
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU0_SIDE 		    0x1C18
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU0_SIDE  		    0x1C1C
++#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU0_SIDE  		    0x1C20
++#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE  	    0x1C24
++#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU0_SIDE	    0x1C28
++#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU0_SIDE 		    0x1C2C
++#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU0_SIDE          0x1C30
++#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU0_SIDE           0x1C34
++#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE        0x1C40
++#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU0_SIDE       0x1C44
++#define MV64340_I2O_QUEUE_CONTROL_REG_CPU0_SIDE 		    0x1C50
++#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU0_SIDE 		    0x1C54
++#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE         0x1C60
++#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE         0x1C64
++#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE         0x1C68
++#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE         0x1C6C
++#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU0_SIDE        0x1C70
++#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU0_SIDE        0x1C74
++#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU0_SIDE        0x1CF8
++#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU0_SIDE        0x1CFC
++#define MV64340_I2O_INBOUND_MESSAGE_REG0_CPU1_SIDE		    0x1C90
++#define MV64340_I2O_INBOUND_MESSAGE_REG1_CPU1_SIDE  		    0x1C94
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG0_CPU1_SIDE 		    0x1C98
++#define MV64340_I2O_OUTBOUND_MESSAGE_REG1_CPU1_SIDE  		    0x1C9C
++#define MV64340_I2O_INBOUND_DOORBELL_REG_CPU1_SIDE  		    0x1CA0
++#define MV64340_I2O_INBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE  	    0x1CA4
++#define MV64340_I2O_INBOUND_INTERRUPT_MASK_REG_CPU1_SIDE	    0x1CA8
++#define MV64340_I2O_OUTBOUND_DOORBELL_REG_CPU1_SIDE 		    0x1CAC
++#define MV64340_I2O_OUTBOUND_INTERRUPT_CAUSE_REG_CPU1_SIDE          0x1CB0
++#define MV64340_I2O_OUTBOUND_INTERRUPT_MASK_REG_CPU1_SIDE           0x1CB4
++#define MV64340_I2O_INBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE        0x1CC0
++#define MV64340_I2O_OUTBOUND_QUEUE_PORT_VIRTUAL_REG_CPU1_SIDE       0x1CC4
++#define MV64340_I2O_QUEUE_CONTROL_REG_CPU1_SIDE 		    0x1CD0
++#define MV64340_I2O_QUEUE_BASE_ADDR_REG_CPU1_SIDE 		    0x1CD4
++#define MV64340_I2O_INBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE         0x1CE0
++#define MV64340_I2O_INBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE         0x1CE4
++#define MV64340_I2O_INBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE         0x1CE8
++#define MV64340_I2O_INBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE         0x1CEC
++#define MV64340_I2O_OUTBOUND_FREE_HEAD_POINTER_REG_CPU1_SIDE        0x1CF0
++#define MV64340_I2O_OUTBOUND_FREE_TAIL_POINTER_REG_CPU1_SIDE        0x1CF4
++#define MV64340_I2O_OUTBOUND_POST_HEAD_POINTER_REG_CPU1_SIDE        0x1C78
++#define MV64340_I2O_OUTBOUND_POST_TAIL_POINTER_REG_CPU1_SIDE        0x1C7C
++
++/****************************************/
++/*        Ethernet Unit Registers  		*/
++/****************************************/
++
++#define MV64340_ETH_PHY_ADDR_REG                                    0x2000
++#define MV64340_ETH_SMI_REG                                         0x2004
++#define MV64340_ETH_UNIT_DEFAULT_ADDR_REG                           0x2008
++#define MV64340_ETH_UNIT_DEFAULTID_REG                              0x200c
++#define MV64340_ETH_UNIT_INTERRUPT_CAUSE_REG                        0x2080
++#define MV64340_ETH_UNIT_INTERRUPT_MASK_REG                         0x2084
++#define MV64340_ETH_UNIT_INTERNAL_USE_REG                           0x24fc
++#define MV64340_ETH_UNIT_ERROR_ADDR_REG                             0x2094
++#define MV64340_ETH_BAR_0                                           0x2200
++#define MV64340_ETH_BAR_1                                           0x2208
++#define MV64340_ETH_BAR_2                                           0x2210
++#define MV64340_ETH_BAR_3                                           0x2218
++#define MV64340_ETH_BAR_4                                           0x2220
++#define MV64340_ETH_BAR_5                                           0x2228
++#define MV64340_ETH_SIZE_REG_0                                      0x2204
++#define MV64340_ETH_SIZE_REG_1                                      0x220c
++#define MV64340_ETH_SIZE_REG_2                                      0x2214
++#define MV64340_ETH_SIZE_REG_3                                      0x221c
++#define MV64340_ETH_SIZE_REG_4                                      0x2224
++#define MV64340_ETH_SIZE_REG_5                                      0x222c
++#define MV64340_ETH_HEADERS_RETARGET_BASE_REG                       0x2230
++#define MV64340_ETH_HEADERS_RETARGET_CONTROL_REG                    0x2234
++#define MV64340_ETH_HIGH_ADDR_REMAP_REG_0                           0x2280
++#define MV64340_ETH_HIGH_ADDR_REMAP_REG_1                           0x2284
++#define MV64340_ETH_HIGH_ADDR_REMAP_REG_2                           0x2288
++#define MV64340_ETH_HIGH_ADDR_REMAP_REG_3                           0x228c
++#define MV64340_ETH_BASE_ADDR_ENABLE_REG                            0x2290
++#define MV64340_ETH_ACCESS_PROTECTION_REG(port)                    (0x2294 + (port<<2))
++#define MV64340_ETH_MIB_COUNTERS_BASE(port)                        (0x3000 + (port<<7))
++#define MV64340_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
++#define MV64340_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2404 + (port<<10))
++#define MV64340_ETH_MII_SERIAL_PARAMETRS_REG(port)                 (0x2408 + (port<<10))
++#define MV64340_ETH_GMII_SERIAL_PARAMETRS_REG(port)                (0x240c + (port<<10))
++#define MV64340_ETH_VLAN_ETHERTYPE_REG(port)                       (0x2410 + (port<<10))
++#define MV64340_ETH_MAC_ADDR_LOW(port)                             (0x2414 + (port<<10))
++#define MV64340_ETH_MAC_ADDR_HIGH(port)                            (0x2418 + (port<<10))
++#define MV64340_ETH_SDMA_CONFIG_REG(port)                          (0x241c + (port<<10))
++#define MV64340_ETH_DSCP_0(port)                                   (0x2420 + (port<<10))
++#define MV64340_ETH_DSCP_1(port)                                   (0x2424 + (port<<10))
++#define MV64340_ETH_DSCP_2(port)                                   (0x2428 + (port<<10))
++#define MV64340_ETH_DSCP_3(port)                                   (0x242c + (port<<10))
++#define MV64340_ETH_DSCP_4(port)                                   (0x2430 + (port<<10))
++#define MV64340_ETH_DSCP_5(port)                                   (0x2434 + (port<<10))
++#define MV64340_ETH_DSCP_6(port)                                   (0x2438 + (port<<10))
++#define MV64340_ETH_PORT_SERIAL_CONTROL_REG(port)                  (0x243c + (port<<10))
++#define MV64340_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)            (0x2440 + (port<<10))
++#define MV64340_ETH_PORT_STATUS_REG(port)                          (0x2444 + (port<<10))
++#define MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port)               (0x2448 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_FIXED_PRIORITY(port)                  (0x244c + (port<<10))
++#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port)         (0x2450 + (port<<10))
++#define MV64340_ETH_MAXIMUM_TRANSMIT_UNIT(port)                    (0x2458 + (port<<10))
++#define MV64340_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port)           (0x245c + (port<<10))
++#define MV64340_ETH_INTERRUPT_CAUSE_REG(port)                      (0x2460 + (port<<10))
++#define MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port)               (0x2464 + (port<<10))
++#define MV64340_ETH_INTERRUPT_MASK_REG(port)                       (0x2468 + (port<<10))
++#define MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port)                (0x246c + (port<<10))
++#define MV64340_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2470 + (port<<10))
++#define MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2474 + (port<<10))
++#define MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)                (0x247c + (port<<10))
++#define MV64340_ETH_RX_DISCARDED_FRAMES_COUNTER(port)              (0x2484 + (port<<10)
++#define MV64340_ETH_PORT_DEBUG_0_REG(port)                         (0x248c + (port<<10))
++#define MV64340_ETH_PORT_DEBUG_1_REG(port)                         (0x2490 + (port<<10))
++#define MV64340_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port)             (0x2494 + (port<<10))
++#define MV64340_ETH_INTERNAL_USE_REG(port)                         (0x24fc + (port<<10))
++#define MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port)                (0x2680 + (port<<10))
++#define MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(port)               (0x2684 + (port<<10))      
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x260c + (port<<10))     
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x261c + (port<<10))     
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x262c + (port<<10))     
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x263c + (port<<10))     
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x264c + (port<<10))     
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x265c + (port<<10))     
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x266c + (port<<10))     
++#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x267c + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x26c0 + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x26c4 + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x26c8 + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x26cc + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x26d0 + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x26d4 + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x26d8 + (port<<10))     
++#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x26dc + (port<<10))     
++#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port)            (0x2700 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port)            (0x2710 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port)            (0x2720 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port)            (0x2730 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port)            (0x2740 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port)            (0x2750 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port)            (0x2760 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port)            (0x2770 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port)           (0x2704 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port)           (0x2714 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port)           (0x2724 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port)           (0x2734 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port)           (0x2744 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port)           (0x2754 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port)           (0x2764 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port)           (0x2774 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_0_ARBITER_CONFIG(port)                (0x2708 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_1_ARBITER_CONFIG(port)                (0x2718 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_2_ARBITER_CONFIG(port)                (0x2728 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_3_ARBITER_CONFIG(port)                (0x2738 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_4_ARBITER_CONFIG(port)                (0x2748 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_5_ARBITER_CONFIG(port)                (0x2758 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_6_ARBITER_CONFIG(port)                (0x2768 + (port<<10))
++#define MV64340_ETH_TX_QUEUE_7_ARBITER_CONFIG(port)                (0x2778 + (port<<10))
++#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port)               (0x2780 + (port<<10))
++#define MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)   (0x3400 + (port<<10))
++#define MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)     (0x3500 + (port<<10))
++#define MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)             (0x3600 + (port<<10))
++
++/*******************************************/
++/*          CUNIT  Registers               */
++/*******************************************/
++
++         /* Address Decoding Register Map */
++           
++#define MV64340_CUNIT_BASE_ADDR_REG0                                0xf200
++#define MV64340_CUNIT_BASE_ADDR_REG1                                0xf208
++#define MV64340_CUNIT_BASE_ADDR_REG2                                0xf210
++#define MV64340_CUNIT_BASE_ADDR_REG3                                0xf218
++#define MV64340_CUNIT_SIZE0                                         0xf204
++#define MV64340_CUNIT_SIZE1                                         0xf20c
++#define MV64340_CUNIT_SIZE2                                         0xf214
++#define MV64340_CUNIT_SIZE3                                         0xf21c
++#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG0                          0xf240
++#define MV64340_CUNIT_HIGH_ADDR_REMAP_REG1                          0xf244
++#define MV64340_CUNIT_BASE_ADDR_ENABLE_REG                          0xf250
++#define MV64340_MPSC0_ACCESS_PROTECTION_REG                         0xf254
++#define MV64340_MPSC1_ACCESS_PROTECTION_REG                         0xf258
++#define MV64340_CUNIT_INTERNAL_SPACE_BASE_ADDR_REG                  0xf25C
++
++        /*  Error Report Registers  */
++
++#define MV64340_CUNIT_INTERRUPT_CAUSE_REG                           0xf310
++#define MV64340_CUNIT_INTERRUPT_MASK_REG                            0xf314
++#define MV64340_CUNIT_ERROR_ADDR                                    0xf318
++
++        /*  Cunit Control Registers */
++
++#define MV64340_CUNIT_ARBITER_CONTROL_REG                           0xf300
++#define MV64340_CUNIT_CONFIG_REG                                    0xb40c
++#define MV64340_CUNIT_CRROSBAR_TIMEOUT_REG                          0xf304
++
++        /*  Cunit Debug Registers   */
++
++#define MV64340_CUNIT_DEBUG_LOW                                     0xf340
++#define MV64340_CUNIT_DEBUG_HIGH                                    0xf344
++#define MV64340_CUNIT_MMASK                                         0xf380
++
++        /*  MPSCs Clocks Routing Registers  */
++
++#define MV64340_MPSC_ROUTING_REG                                    0xb400
++#define MV64340_MPSC_RX_CLOCK_ROUTING_REG                           0xb404
++#define MV64340_MPSC_TX_CLOCK_ROUTING_REG                           0xb408
++
++        /*  MPSCs Interrupts Registers    */
++
++#define MV64340_MPSC_CAUSE_REG(port)                               (0xb804 + (port<<3))
++#define MV64340_MPSC_MASK_REG(port)                                (0xb884 + (port<<3))
++ 
++#define MV64340_MPSC_MAIN_CONFIG_LOW(port)                         (0x8000 + (port<<12))
++#define MV64340_MPSC_MAIN_CONFIG_HIGH(port)                        (0x8004 + (port<<12))    
++#define MV64340_MPSC_PROTOCOL_CONFIG(port)                         (0x8008 + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG1(port)                            (0x800c + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG2(port)                            (0x8010 + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG3(port)                            (0x8014 + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG4(port)                            (0x8018 + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG5(port)                            (0x801c + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG6(port)                            (0x8020 + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG7(port)                            (0x8024 + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG8(port)                            (0x8028 + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG9(port)                            (0x802c + (port<<12))    
++#define MV64340_MPSC_CHANNEL_REG10(port)                           (0x8030 + (port<<12))    
++        
++        /*  MPSC0 Registers      */
++
++
++/***************************************/
++/*          SDMA Registers             */
++/***************************************/
++
++#define MV64340_SDMA_CONFIG_REG(channel)                        (0x4000 + (channel<<13))        
++#define MV64340_SDMA_COMMAND_REG(channel)                       (0x4008 + (channel<<13))        
++#define MV64340_SDMA_CURRENT_RX_DESCRIPTOR_POINTER(channel)     (0x4810 + (channel<<13))        
++#define MV64340_SDMA_CURRENT_TX_DESCRIPTOR_POINTER(channel)     (0x4c10 + (channel<<13))        
++#define MV64340_SDMA_FIRST_TX_DESCRIPTOR_POINTER(channel)       (0x4c14 + (channel<<13)) 
++
++#define MV64340_SDMA_CAUSE_REG                                      0xb800
++#define MV64340_SDMA_MASK_REG                                       0xb880
++         
++/* BRG Interrupts */
++
++#define MV64340_BRG_CONFIG_REG(brg)                              (0xb200 + (brg<<3))
++#define MV64340_BRG_BAUDE_TUNING_REG(brg)                        (0xb208 + (brg<<3))
++#define MV64340_BRG_CAUSE_REG                                       0xb834
++#define MV64340_BRG_MASK_REG                                        0xb8b4
++
++/****************************************/
++/* DMA Channel Control			*/
++/****************************************/
++
++#define MV64340_DMA_CHANNEL0_CONTROL 				    0x840
++#define MV64340_DMA_CHANNEL0_CONTROL_HIGH			    0x880
++#define MV64340_DMA_CHANNEL1_CONTROL 				    0x844
++#define MV64340_DMA_CHANNEL1_CONTROL_HIGH			    0x884
++#define MV64340_DMA_CHANNEL2_CONTROL 				    0x848
++#define MV64340_DMA_CHANNEL2_CONTROL_HIGH			    0x888
++#define MV64340_DMA_CHANNEL3_CONTROL 				    0x84C
++#define MV64340_DMA_CHANNEL3_CONTROL_HIGH			    0x88C
++
++
++/****************************************/
++/*           IDMA Registers             */
++/****************************************/
++
++#define MV64340_DMA_CHANNEL0_BYTE_COUNT                             0x800
++#define MV64340_DMA_CHANNEL1_BYTE_COUNT                             0x804
++#define MV64340_DMA_CHANNEL2_BYTE_COUNT                             0x808
++#define MV64340_DMA_CHANNEL3_BYTE_COUNT                             0x80C
++#define MV64340_DMA_CHANNEL0_SOURCE_ADDR                            0x810
++#define MV64340_DMA_CHANNEL1_SOURCE_ADDR                            0x814
++#define MV64340_DMA_CHANNEL2_SOURCE_ADDR                            0x818
++#define MV64340_DMA_CHANNEL3_SOURCE_ADDR                            0x81c
++#define MV64340_DMA_CHANNEL0_DESTINATION_ADDR                       0x820
++#define MV64340_DMA_CHANNEL1_DESTINATION_ADDR                       0x824
++#define MV64340_DMA_CHANNEL2_DESTINATION_ADDR                       0x828
++#define MV64340_DMA_CHANNEL3_DESTINATION_ADDR                       0x82C
++#define MV64340_DMA_CHANNEL0_NEXT_DESCRIPTOR_POINTER                0x830
++#define MV64340_DMA_CHANNEL1_NEXT_DESCRIPTOR_POINTER                0x834
++#define MV64340_DMA_CHANNEL2_NEXT_DESCRIPTOR_POINTER                0x838
++#define MV64340_DMA_CHANNEL3_NEXT_DESCRIPTOR_POINTER                0x83C
++#define MV64340_DMA_CHANNEL0_CURRENT_DESCRIPTOR_POINTER             0x870
++#define MV64340_DMA_CHANNEL1_CURRENT_DESCRIPTOR_POINTER             0x874
++#define MV64340_DMA_CHANNEL2_CURRENT_DESCRIPTOR_POINTER             0x878
++#define MV64340_DMA_CHANNEL3_CURRENT_DESCRIPTOR_POINTER             0x87C
++
++ /*  IDMA Address Decoding Base Address Registers  */
++ 
++#define MV64340_DMA_BASE_ADDR_REG0                                  0xa00
++#define MV64340_DMA_BASE_ADDR_REG1                                  0xa08
++#define MV64340_DMA_BASE_ADDR_REG2                                  0xa10
++#define MV64340_DMA_BASE_ADDR_REG3                                  0xa18
++#define MV64340_DMA_BASE_ADDR_REG4                                  0xa20
++#define MV64340_DMA_BASE_ADDR_REG5                                  0xa28
++#define MV64340_DMA_BASE_ADDR_REG6                                  0xa30
++#define MV64340_DMA_BASE_ADDR_REG7                                  0xa38
++ 
++ /*  IDMA Address Decoding Size Address Register   */
++ 
++#define MV64340_DMA_SIZE_REG0                                       0xa04
++#define MV64340_DMA_SIZE_REG1                                       0xa0c
++#define MV64340_DMA_SIZE_REG2                                       0xa14
++#define MV64340_DMA_SIZE_REG3                                       0xa1c
++#define MV64340_DMA_SIZE_REG4                                       0xa24
++#define MV64340_DMA_SIZE_REG5                                       0xa2c
++#define MV64340_DMA_SIZE_REG6                                       0xa34
++#define MV64340_DMA_SIZE_REG7                                       0xa3C
++
++ /* IDMA Address Decoding High Address Remap and Access 
++                  Protection Registers                    */
++                  
++#define MV64340_DMA_HIGH_ADDR_REMAP_REG0                            0xa60
++#define MV64340_DMA_HIGH_ADDR_REMAP_REG1                            0xa64
++#define MV64340_DMA_HIGH_ADDR_REMAP_REG2                            0xa68
++#define MV64340_DMA_HIGH_ADDR_REMAP_REG3                            0xa6C
++#define MV64340_DMA_BASE_ADDR_ENABLE_REG                            0xa80
++#define MV64340_DMA_CHANNEL0_ACCESS_PROTECTION_REG                  0xa70
++#define MV64340_DMA_CHANNEL1_ACCESS_PROTECTION_REG                  0xa74
++#define MV64340_DMA_CHANNEL2_ACCESS_PROTECTION_REG                  0xa78
++#define MV64340_DMA_CHANNEL3_ACCESS_PROTECTION_REG                  0xa7c
++#define MV64340_DMA_ARBITER_CONTROL                                 0x860
++#define MV64340_DMA_CROSS_BAR_TIMEOUT                               0x8d0
++
++ /*  IDMA Headers Retarget Registers   */
++
++#define MV64340_DMA_HEADERS_RETARGET_CONTROL                        0xa84
++#define MV64340_DMA_HEADERS_RETARGET_BASE                           0xa88
++
++ /*  IDMA Interrupt Register  */
++
++#define MV64340_DMA_INTERRUPT_CAUSE_REG                             0x8c0
++#define MV64340_DMA_INTERRUPT_CAUSE_MASK                            0x8c4
++#define MV64340_DMA_ERROR_ADDR                                      0x8c8
++#define MV64340_DMA_ERROR_SELECT                                    0x8cc
++
++ /*  IDMA Debug Register ( for internal use )    */
++
++#define MV64340_DMA_DEBUG_LOW                                       0x8e0
++#define MV64340_DMA_DEBUG_HIGH                                      0x8e4
++#define MV64340_DMA_SPARE                                           0xA8C
++
++/****************************************/
++/* Timer_Counter 			*/
++/****************************************/
++
++#define MV64340_TIMER_COUNTER0					    0x850
++#define MV64340_TIMER_COUNTER1					    0x854
++#define MV64340_TIMER_COUNTER2					    0x858
++#define MV64340_TIMER_COUNTER3					    0x85C
++#define MV64340_TIMER_COUNTER_0_3_CONTROL			    0x864
++#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_CAUSE		    0x868
++#define MV64340_TIMER_COUNTER_0_3_INTERRUPT_MASK      		    0x86c
++
++/****************************************/
++/*         Watchdog registers  	        */
++/****************************************/
++
++#define MV64340_WATCHDOG_CONFIG_REG                                 0xb410
++#define MV64340_WATCHDOG_VALUE_REG                                  0xb414
++
++/****************************************/
++/* I2C Registers                        */
++/****************************************/
++
++#define MV64340_I2C_SLAVE_ADDR                                      0xc000
++#define MV64340_I2C_EXTENDED_SLAVE_ADDR                             0xc010
++#define MV64340_I2C_DATA                                            0xc004
++#define MV64340_I2C_CONTROL                                         0xc008
++#define MV64340_I2C_STATUS_BAUDE_RATE                               0xc00C
++#define MV64340_I2C_SOFT_RESET                                      0xc01c
++
++/****************************************/
++/* GPP Interface Registers              */
++/****************************************/
++
++#define MV64340_GPP_IO_CONTROL                                      0xf100
++#define MV64340_GPP_LEVEL_CONTROL                                   0xf110
++#define MV64340_GPP_VALUE                                           0xf104
++#define MV64340_GPP_INTERRUPT_CAUSE                                 0xf108
++#define MV64340_GPP_INTERRUPT_MASK0                                 0xf10c
++#define MV64340_GPP_INTERRUPT_MASK1                                 0xf114
++#define MV64340_GPP_VALUE_SET                                       0xf118
++#define MV64340_GPP_VALUE_CLEAR                                     0xf11c
++
++/****************************************/
++/* Interrupt Controller Registers       */
++/****************************************/
++
++/****************************************/
++/* Interrupts	  			*/
++/****************************************/
++
++#define MV64340_MAIN_INTERRUPT_CAUSE_LOW                            0x004
++#define MV64340_MAIN_INTERRUPT_CAUSE_HIGH                           0x00c
++#define MV64340_CPU_INTERRUPT0_MASK_LOW                             0x014
++#define MV64340_CPU_INTERRUPT0_MASK_HIGH                            0x01c
++#define MV64340_CPU_INTERRUPT0_SELECT_CAUSE                         0x024
++#define MV64340_CPU_INTERRUPT1_MASK_LOW                             0x034
++#define MV64340_CPU_INTERRUPT1_MASK_HIGH                            0x03c
++#define MV64340_CPU_INTERRUPT1_SELECT_CAUSE                         0x044
++#define MV64340_INTERRUPT0_MASK_0_LOW                               0x054
++#define MV64340_INTERRUPT0_MASK_0_HIGH                              0x05c
++#define MV64340_INTERRUPT0_SELECT_CAUSE                             0x064
++#define MV64340_INTERRUPT1_MASK_0_LOW                               0x074
++#define MV64340_INTERRUPT1_MASK_0_HIGH                              0x07c
++#define MV64340_INTERRUPT1_SELECT_CAUSE                             0x084
++
++/****************************************/
++/*      MPP Interface Registers         */
++/****************************************/
++
++#define MV64340_MPP_CONTROL0                                        0xf000
++#define MV64340_MPP_CONTROL1                                        0xf004
++#define MV64340_MPP_CONTROL2                                        0xf008
++#define MV64340_MPP_CONTROL3                                        0xf00c
++
++/****************************************/
++/*    Serial Initialization registers   */
++/****************************************/
++
++#define MV64340_SERIAL_INIT_LAST_DATA                               0xf324
++#define MV64340_SERIAL_INIT_CONTROL                                 0xf328
++#define MV64340_SERIAL_INIT_STATUS                                  0xf32c
++
++extern unsigned long mv64340_base;
++
++#define MV64340_BASE       (mv64340_base)
++
++/*
++ * Because of an error/peculiarity in the Galileo chip, we need to swap the
++ * bytes when running bigendian.
++ */
++
++#define MV_WRITE(ofs, data)		\
++        *(volatile u32 *)(MV64340_BASE + (ofs)) = cpu_to_le32((u32)data)
++#define MV_READ(ofs)			\
++        (le32_to_cpu(*(volatile u32 *)(MV64340_BASE + (ofs))))
++
++#define MV_WRITE_16(ofs, data)		\
++        *(volatile u16 *)(MV64340_BASE + (ofs)) = cpu_to_le16((u16)data)
++#define MV_READ_16(ofs)			\
++        le16_to_cpu(*(volatile u16 *)(MV64340_BASE + (ofs)))
++
++#define MV_WRITE_8(ofs, data)		\
++        *(volatile u8 *)(MV64340_BASE + (ofs)) = ((u16)data)
++#define MV_READ_8(ofs)			\
++        (*(volatile u8 *)(MV64340_BASE + (ofs)))
++
++#define MV_SET_REG_BITS(ofs, bits)	\
++	(*((volatile u32 *)(MV64340_BASE + (ofs)))) |= ((u32)cpu_to_le32(bits))
++#define MV_RESET_REG_BITS(ofs, bits)	\
++	(*((volatile u32 *)(MV64340_BASE + (ofs)))) &= ~((u32)cpu_to_le32(bits))
++
++extern void mv64340_irq_init(unsigned int base);
++
++extern struct pci_ops mv64340_bus0_pci_ops;
++extern struct pci_ops mv64340_bus1_pci_ops;
++
++#endif /* __ASM_MV64340_H */
+diff -urN linux-2.6.9.orig/include/linux/mv643xx.h linux-2.6.9/include/linux/mv643xx.h
+--- linux-2.6.9.orig/include/linux/mv643xx.h	2004-10-18 23:54:55.000000000 +0200
++++ linux-2.6.9/include/linux/mv643xx.h	2004-10-27 10:31:59.863442504 +0200
+@@ -13,7 +13,14 @@
+ #ifndef __ASM_MV64340_H
+ #define __ASM_MV64340_H
+ 
++#ifndef __PPC__
++/*
++ * PowerPC architecture (Pegasos II) does not requiere addrspace
++ * and it even doesn't exist in asm-ppc
++*/
+ #include <asm/addrspace.h>
++#endif
++
+ #include <asm/marvell.h>
+ 
+ /****************************************/

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-shmem-nomount-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-shmem-nomount-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-shmem-nomount-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,52 @@
+
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: don't allow tmpfs to be mounted if the driver is not present
+## DP: Patch author: Hugh Dickins
+## DP: Upstream status: upstream
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# origin: hugh (BitKeeper)
+# cset: 1.2458.1.34 (2.6) key=418eea77m1zMOQDODJYuKeuO0vXmdQ
+# inclusion: upstream
+# descrition: [PATCH] tmpfs: CONFIG_TMPFS=n mount fix
+# revision date: Tue, 09 Nov 2004 16:28:23 +0900
+#
+# rset: ChangeSet|1.2458.1.33..1.2458.1.34
+# rset: mm/shmem.c|1.172..1.173
+#
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/07 19:39:35-08:00 hugh at veritas.com 
+#   [PATCH] tmpfs: CONFIG_TMPFS=n mount fix
+#   
+#   My tmpfs superblock changes in 2.6.9 messed up mount -t tmpfs when
+#   CONFIG_TMPFS is not enabled: it wrongly claimed to succeed, and left the
+#   directory unusable, giving "Not a directory" errors thereafter.
+#   
+#   Signed-off-by: Hugh Dickins <hugh at veritas.com>
+#   Signed-off-by: Andrew Morton <akpm at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# mm/shmem.c
+#   2004/11/07 18:08:04-08:00 hugh at veritas.com +2 -0
+#   tmpfs: CONFIG_TMPFS=n mount fix
+# Updated for Debian kenrel-source-2.6.8 by Horms
+# 
+diff -Nru a/mm/shmem.c b/mm/shmem.c
+--- a/mm/shmem.c.dist	2004-11-09 17:32:32.000000000 +0900
++++ b/mm/shmem.c	2004-11-09 17:36:50.000000000 +0900
+@@ -1904,6 +1904,8 @@
+ 		sbinfo->max_inodes = inodes;
+ 		sbinfo->free_inodes = inodes;
+ 	}
++#else
++	sb->s_flags |= MS_NOUSER;
+ #endif
+ 
+ 	sb->s_maxbytes = SHMEM_MAX_BYTES;

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-vmscan.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-vmscan.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/mm-vmscan.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,68 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: vmscan: pages_scanned fix
+## DP: Patch author: Nick Piggin
+## DP: Upstream status: included
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# origin: nickpiggin (BitKeeper)
+# cset: 1.2263 (2.6) key=41810eeex2e2qwU7OTgBPwce7-mkrg
+# inclusion: upstream
+# descrition: [PATCH] vmscan: pages_scanned fix
+# revision date: Mon, 08 Nov 2004 12:04:32 +0900
+#
+# rset: ChangeSet|1.2262..1.2263
+# rset: mm/vmscan.c|1.231..1.232
+#
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/10/28 08:23:26-07:00 nickpiggin at yahoo.com.au 
+#   [PATCH] vmscan: pages_scanned fix
+#   
+#   kswapd is still sometimes going into loops.  The problem seemed to be
+#   happening on systems with zero inactive pages in ZONE_DMA, so pages_scanned
+#   could never be increased, all_unreclaimable would never be set, and kswapd
+#   would never break.
+#   
+#   So change pages_scanned to be a count of the number of _active_ list pages
+#   scanned rather than inactive.  This has been reported to solve the problems.
+#   
+#   This is not subject to the reverse problem where one might have zero active
+#   list pages, because inactive pages are either be reclaimed, or put onto the
+#   active list.
+#   
+#   I think it is reasonable to have all_unreclaimed trigger based on the amount
+#   of active list scanning rather than inactive.
+#   
+#   
+#   Signed-off-by: Andrew Morton <akpm at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# mm/vmscan.c
+#   2004/10/28 00:39:52-07:00 nickpiggin at yahoo.com.au +1 -1
+#   vmscan: pages_scanned fix
+# 
+diff -Nru a/mm/vmscan.c b/mm/vmscan.c
+--- a/mm/vmscan.c	2004-11-08 12:04:32 +09:00
++++ b/mm/vmscan.c	2004-11-08 12:04:32 +09:00
+@@ -574,7 +574,6 @@
+ 			nr_taken++;
+ 		}
+ 		zone->nr_inactive -= nr_taken;
+-		zone->pages_scanned += nr_taken;
+ 		spin_unlock_irq(&zone->lru_lock);
+ 
+ 		if (nr_taken == 0)
+@@ -675,6 +674,7 @@
+ 		}
+ 		pgscanned++;
+ 	}
++	zone->pages_scanned += pgscanned;
+ 	zone->nr_active -= pgmoved;
+ 	spin_unlock_irq(&zone->lru_lock);
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide-pnp.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide-pnp.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide-pnp.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,77 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Allow modular built of ide-pnp
+## DP: Patch author: Herbert Xu, Christoph Hellwig
+## DP: Upstream status: submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- 1.49/drivers/ide/Kconfig	2004-06-18 08:43:53 +02:00
++++ edited/drivers/ide/Kconfig	2004-06-19 12:25:46 +02:00
+@@ -305,7 +305,7 @@
+ 	  Otherwise say N.
+ 
+ config BLK_DEV_IDEPNP
+-	bool "PNP EIDE support"
++	tristate "PNP EIDE support"
+ 	depends on PNP
+ 	help
+ 	  If you have a PnP (Plug and Play) compatible EIDE card and
+--- 1.21/drivers/ide/Makefile	2004-06-18 08:43:53 +02:00
++++ edited/drivers/ide/Makefile	2004-06-19 12:42:49 +02:00
+@@ -23,7 +23,6 @@
+ ide-core-$(CONFIG_BLK_DEV_IDEDMA)	+= ide-dma.o
+ ide-core-$(CONFIG_BLK_DEV_IDE_TCQ)	+= ide-tcq.o
+ ide-core-$(CONFIG_PROC_FS)		+= ide-proc.o
+-ide-core-$(CONFIG_BLK_DEV_IDEPNP)	+= ide-pnp.o
+ 
+ # built-in only drivers from arm/
+ ide-core-$(CONFIG_IDE_ARM)		+= arm/ide_arm.o
+@@ -44,6 +43,7 @@
+ 
+ obj-$(CONFIG_BLK_DEV_IDE)		+= ide-core.o
+ obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
++obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
+ 
+ obj-$(CONFIG_BLK_DEV_IDEDISK)		+= ide-disk.o
+ obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd.o
+--- 1.9/drivers/ide/ide-pnp.c	2004-06-15 18:31:45 +02:00
++++ edited/drivers/ide/ide-pnp.c	2004-06-19 12:34:27 +02:00
+@@ -69,7 +69,21 @@
+ 	.remove		= idepnp_remove,
+ };
+ 
+-void __init pnpide_init(void)
++int __init pnpide_init(void)
+ {
+-	pnp_register_driver(&idepnp_driver);
++	return pnp_register_driver(&idepnp_driver);
+ }
++
++#ifdef MODULE
++static void __exit pnpide_exit(void)
++{
++       pnp_unregister_driver(&idepnp_driver);
++}
++
++module_init(pnpide_init);
++module_exit(pnpide_exit);
++#endif
++
++MODULE_AUTHOR("Andrey Panin");
++MODULE_DESCRIPTION("Enabler for ISAPNP IDE devices");
++MODULE_LICENSE("GPL");
+--- 1.150/drivers/ide/ide.c	2004-06-15 18:31:12 +02:00
++++ edited/drivers/ide/ide.c	2004-06-19 12:29:44 +02:00
+@@ -2003,7 +2003,7 @@
+ 	return 1;
+ }
+ 
+-extern void pnpide_init(void);
++extern int pnpide_init(void);
+ extern void h8300_ide_init(void);
+ 
+ /*

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-ide.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,1421 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: fix IDE modularisation
+## DP: Patch author: Herbert Xu
+## DP: Upstream status: partially rejected
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- 1.3/drivers/ide/ide-generic.c	2004-02-22 18:36:17 +01:00
++++ edited/drivers/ide/ide-generic.c	2004-06-16 15:44:16 +02:00
+@@ -11,9 +11,14 @@
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/ide.h>
++#include <linux/config.h>
+ 
+ static int __init ide_generic_init(void)
+ {
++#ifdef CONFIG_BLK_DEV_IDEPCI
++	ide_scan_pcibus();
++#endif
++
+ 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
+ 		ide_get_lock(NULL, NULL); /* for atari only */
+ 
+@@ -27,6 +32,11 @@
+ 	return 0;
+ }
+ 
++static void __exit ide_generic_exit(void)
++{
++}
++
+ module_init(ide_generic_init);
++module_exit(ide_generic_exit);
+ 
+ MODULE_LICENSE("GPL");
+--- 1.150/drivers/ide/ide.c	2004-06-15 18:31:12 +02:00
++++ edited/drivers/ide/ide.c	2004-06-16 15:44:16 +02:00
+@@ -175,10 +175,11 @@
+ static int initializing;	/* set while initializing built-in drivers */
+ 
+ DECLARE_MUTEX(ide_cfg_sem);
++EXPORT_SYMBOL(ide_cfg_sem);
+ spinlock_t ide_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+ 
+ #ifdef CONFIG_BLK_DEV_IDEPCI
+-static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
++int ide_scan_direction;		/* THIS was formerly 2.2.x pci=reverse */
+ #endif
+ 
+ #ifdef CONFIG_IDEDMA_AUTO
+@@ -1364,6 +1365,8 @@
+ 
+ EXPORT_SYMBOL(system_bus_clock);
+ 
++EXPORT_SYMBOL(ide_add_generic_settings);
++
+ /*
+  *	Locking is badly broken here - since way back.  That sucker is
+  * root-only, but that's not an excuse...  The real question is what
+@@ -2011,9 +2014,9 @@
+  */
+ static void __init probe_for_hwifs (void)
+ {
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-	ide_scan_pcibus(ide_scan_direction);
+-#endif /* CONFIG_BLK_DEV_IDEPCI */
++#if defined(CONFIG_BLK_DEV_IDEPCI) && !defined(MODULE)
++	ide_scan_pcibus();
++#endif /* CONFIG_BLK_DEV_IDEPCI && !MODULE */
+ 
+ #ifdef CONFIG_ETRAX_IDE
+ 	{
+--- 1.25/drivers/ide/setup-pci.c	2004-06-01 21:04:38 +02:00
++++ edited/drivers/ide/setup-pci.c	2004-06-16 15:44:18 +02:00
+@@ -821,7 +821,7 @@
+  *	boot up the pci layer takes over the job.
+  */
+  
+-static int __init ide_scan_pcidev(struct pci_dev *dev)
++static int ide_scan_pcidev(struct pci_dev *dev)
+ {
+ 	struct list_head *l;
+ 	struct pci_driver *d;
+@@ -847,21 +847,23 @@
+ 
+ /**
+  *	ide_scan_pcibus		-	perform the initial IDE driver scan
+- *	@scan_direction: set for reverse order scanning
+  *
+  *	Perform the initial bus rather than driver ordered scan of the
+  *	PCI drivers. After this all IDE pci handling becomes standard
+  *	module ordering not traditionally ordered.
+  */
+  	
+-void __init ide_scan_pcibus (int scan_direction)
++void ide_scan_pcibus(void)
+ {
+ 	struct pci_dev *dev = NULL;
+ 	struct pci_driver *d;
+ 	struct list_head *l, *n;
+ 
++	if (!pre_init)
++		return;
++
+ 	pre_init = 0;
+-	if (!scan_direction) {
++	if (!ide_scan_direction) {
+ 		while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ 			ide_scan_pcidev(dev);
+ 		}
+@@ -883,3 +885,5 @@
+ 		pci_register_driver(d);
+ 	}
+ }
++
++EXPORT_SYMBOL_GPL(ide_scan_pcibus);
+--- 1.16/drivers/ide/arm/icside.c	2004-02-28 12:38:08 +01:00
++++ edited/drivers/ide/arm/icside.c	2004-06-16 15:44:16 +02:00
+@@ -861,10 +861,19 @@
+ 		break;
+ 	}
+ 
+-	if (ret == 0)
++	if (ret == 0) {
+ 		ecard_set_drvdata(ec, state);
+-	else
++
++		/*
++		 * this locks the driver in-core - remove this
++		 * comment and the line below when we can
++		 * safely remove interfaces.
++		 */
++		if (!try_module_get(THIS_MODULE))
++			ret = -ENODEV;
++	} else {
+ 		kfree(state);
++	}
+  out:
+ 	return ret;
+ }
+@@ -947,8 +956,14 @@
+ 	return ecard_register_driver(&icside_driver);
+ }
+ 
++static void __exit icside_exit(void)
++{
++	ecard_remove_driver(&icside_driver);
++}
++
+ MODULE_AUTHOR("Russell King <rmk at arm.linux.org.uk>");
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("ICS IDE driver");
+ 
+ module_init(icside_init);
++module_exit(icside_exit);
+--- 1.6/drivers/ide/arm/rapide.c	2004-02-07 20:44:16 +01:00
++++ edited/drivers/ide/arm/rapide.c	2004-06-16 15:44:16 +02:00
+@@ -33,6 +33,14 @@
+ 
+ 	if (ret)
+ 		ecard_release(ec);
++	/*
++	 * this locks the driver in-core - remove this
++	 * comment and the two lines below when we can
++	 * safely remove interfaces.
++	 */
++	else if (!try_module_get(THIS_MODULE))
++		ret = -ENODEV;
++
+ 	return ret;
+ }
+ 
+@@ -60,7 +68,13 @@
+ 	return ecard_register_driver(&rapide_driver);
+ }
+ 
++static void __exit rapide_exit(void)
++{
++	ecard_remove_driver(&rapide_driver);
++}
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Yellowstone RAPIDE driver");
+ 
+ module_init(rapide_init);
++module_exit(rapide_exit);
+--- 1.4/drivers/ide/pci/adma100.c	2003-02-18 19:06:19 +01:00
++++ edited/drivers/ide/pci/adma100.c	2004-06-16 15:44:16 +02:00
+@@ -16,7 +16,7 @@
+ #include <linux/pci.h>
+ #include <asm/io.h>
+ 
+-void __init ide_init_adma100 (ide_hwif_t *hwif)
++void __devinit ide_init_adma100 (ide_hwif_t *hwif)
+ {
+ 	unsigned long  phy_admctl = pci_resource_start(hwif->pci_dev, 4) + 0x80 + (hwif->channel * 0x20);
+ 	void *v_admctl;
+--- 1.22/drivers/ide/pci/aec62xx.c	2004-06-16 05:17:44 +02:00
++++ edited/drivers/ide/pci/aec62xx.c	2004-06-16 15:44:16 +02:00
+@@ -525,6 +525,8 @@
+ {
+ 	ide_pci_device_t *d = &aec62xx_chipsets[id->driver_data];
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	d->init_setup(dev, d);
+ 	return 0;
+ }
+@@ -550,7 +552,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit aec62xx_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(aec62xx_ide_init);
++module_exit(aec62xx_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for ARTOP AEC62xx IDE");
+--- 1.25/drivers/ide/pci/alim15x3.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/alim15x3.c	2004-06-16 15:45:33 +02:00
+@@ -581,7 +581,7 @@
+  *	appropriate also sets up the 1533 southbridge.
+  */
+   
+-static unsigned int __init init_chipset_ali15x3 (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const char *name)
+ {
+ 	unsigned long flags;
+ 	u8 tmpbyte;
+@@ -675,7 +675,7 @@
+  *	FIXME: frobs bits that are not defined on newer ALi devicea
+  */
+ 
+-static unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif)
++static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev	= hwif->pci_dev;
+ 	unsigned int ata66	= 0;
+@@ -746,7 +746,7 @@
+  *	Initialize the IDE structure side of the ALi 15x3 driver.
+  */
+  
+-static void __init init_hwif_common_ali15x3 (ide_hwif_t *hwif)
++static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
+ {
+ 	hwif->autodma = 0;
+ 	hwif->tuneproc = &ali15x3_tune_drive;
+@@ -792,7 +792,7 @@
+  *	Sparc systems
+  */
+ 
+-static void __init init_hwif_ali15x3 (ide_hwif_t *hwif)
++static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
+ {
+ 	u8 ideic, inmir;
+ 	s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
+@@ -844,7 +844,7 @@
+  *	the actual work.
+  */
+ 
+-static void __init init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
++static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
+ {
+ 	if (m5229_revision < 0x20)
+ 		return;
+@@ -875,6 +875,9 @@
+ {
+ 	ide_pci_device_t *d = &ali15x3_chipset;
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
++
+ 	if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, NULL))
+ 		printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not yet fully tested.\n");
+ 
+@@ -903,7 +906,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit ali15x3_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(ali15x3_ide_init);
++module_exit(ali15x3_ide_exit);
+ 
+ MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
+ MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
+--- 1.31/drivers/ide/pci/amd74xx.c	2004-06-01 19:55:04 +02:00
++++ edited/drivers/ide/pci/amd74xx.c	2004-06-16 15:44:16 +02:00
+@@ -312,7 +312,7 @@
+  * and initialize its drive independent registers.
+  */
+ 
+-static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const char *name)
+ {
+ 	unsigned char t;
+ 	unsigned int u;
+@@ -416,7 +416,7 @@
+ 	return dev->irq;
+ }
+ 
+-static void __init init_hwif_amd74xx(ide_hwif_t *hwif)
++static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+ {
+ 	int i;
+ 
+@@ -496,6 +496,8 @@
+ 
+ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	amd_chipset = amd74xx_chipsets + id->driver_data;
+ 	amd_config = amd_ide_chips + id->driver_data;
+ 	if (dev->device != amd_config->id) BUG();
+@@ -538,7 +540,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit amd74xx_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(amd74xx_ide_init);
++module_exit(amd74xx_ide_exit);
+ 
+ MODULE_AUTHOR("Vojtech Pavlik");
+ MODULE_DESCRIPTION("AMD PCI IDE driver");
+--- 1.3/drivers/ide/pci/atiixp.c	2004-06-01 21:04:38 +02:00
++++ edited/drivers/ide/pci/atiixp.c	2004-06-16 15:46:09 +02:00
+@@ -479,6 +479,8 @@
+ 
+ static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++ 	if (!try_module_get(THIS_MODULE))
++ 		return -ENODEV;
+ 	ide_setup_pci_device(dev, &atiixp_pci_info[id->driver_data]);
+ 	return 0;
+ }
+@@ -500,7 +502,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit atiixp_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(atiixp_ide_init);
++module_exit(atiixp_ide_exit);
+ 
+ MODULE_AUTHOR("HUI YU");
+ MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
+--- 1.9/drivers/ide/pci/cmd640.c	2004-02-01 19:06:55 +01:00
++++ edited/drivers/ide/pci/cmd640.c	2004-06-16 15:44:17 +02:00
+@@ -276,7 +276,7 @@
+ 	spin_unlock_irqrestore(&ide_lock, flags);
+ }
+ 
+-static int __init match_pci_cmd640_device (void)
++static int __devinit match_pci_cmd640_device (void)
+ {
+ 	const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
+ 	unsigned int i;
+@@ -296,7 +296,7 @@
+ /*
+  * Probe for CMD640x -- pci method 1
+  */
+-static int __init probe_for_cmd640_pci1 (void)
++static int __devinit probe_for_cmd640_pci1 (void)
+ {
+ 	__get_cmd640_reg = get_cmd640_reg_pci1;
+ 	__put_cmd640_reg = put_cmd640_reg_pci1;
+@@ -312,7 +312,7 @@
+ /*
+  * Probe for CMD640x -- pci method 2
+  */
+-static int __init probe_for_cmd640_pci2 (void)
++static int __devinit probe_for_cmd640_pci2 (void)
+ {
+ 	__get_cmd640_reg = get_cmd640_reg_pci2;
+ 	__put_cmd640_reg = put_cmd640_reg_pci2;
+@@ -326,7 +326,7 @@
+ /*
+  * Probe for CMD640x -- vlb
+  */
+-static int __init probe_for_cmd640_vlb (void)
++static int __devinit probe_for_cmd640_vlb (void)
+ {
+ 	u8 b;
+ 
+@@ -347,7 +347,7 @@
+  *  Returns 1 if an IDE interface/drive exists at 0x170,
+  *  Returns 0 otherwise.
+  */
+-static int __init secondary_port_responding (void)
++static int __devinit secondary_port_responding (void)
+ {
+ 	unsigned long flags;
+ 
+@@ -390,7 +390,7 @@
+  * Check whether prefetch is on for a drive,
+  * and initialize the unmask flags for safe operation.
+  */
+-static void __init check_prefetch (unsigned int index)
++static void __devinit check_prefetch (unsigned int index)
+ {
+ 	ide_drive_t *drive = cmd_drives[index];
+ 	u8 b = get_cmd640_reg(prefetch_regs[index]);
+@@ -411,7 +411,7 @@
+ /*
+  * Figure out which devices we control
+  */
+-static void __init setup_device_ptrs (void)
++static void __devinit setup_device_ptrs (void)
+ {
+ 	unsigned int i;
+ 
+@@ -493,7 +493,7 @@
+ /*
+  * This routine retrieves the initial drive timings from the chipset.
+  */
+-static void __init retrieve_drive_counts (unsigned int index)
++static void __devinit retrieve_drive_counts (unsigned int index)
+ {
+ 	u8 b;
+ 
+@@ -714,7 +714,7 @@
+ /*
+  * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
+  */
+-int __init ide_probe_for_cmd640x (void)
++int __devinit ide_probe_for_cmd640x (void)
+ {
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ 	int second_port_toggled = 0;
+--- 1.23/drivers/ide/pci/cmd64x.c	2004-06-16 05:17:44 +02:00
++++ edited/drivers/ide/pci/cmd64x.c	2004-06-16 15:49:12 +02:00
+@@ -746,6 +746,8 @@
+ 
+ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &cmd64x_chipsets[id->driver_data]);
+ 	return 0;
+ }
+@@ -770,7 +772,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit cmd64x_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(cmd64x_ide_init);
++module_exit(cmd64x_ide_exit);
+ 
+ MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
+--- 1.11/drivers/ide/pci/cs5520.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/cs5520.c	2004-06-16 15:44:17 +02:00
+@@ -289,6 +289,10 @@
+ 		printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
+ 		return 1;
+ 	}
++
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
++
+ 	pci_set_master(dev);
+ 	pci_set_dma_mask(dev, 0xFFFFFFFF);
+ 	init_chipset_cs5520(dev, d->name);
+@@ -329,7 +333,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit cs5520_ide_exit(void)
++{
++	return ide_pci_unregister_driver(&driver);
++}
++
+ module_init(cs5520_ide_init);
++module_exit(cs5520_ide_exit);
+ 
+ MODULE_AUTHOR("Alan Cox");
+ MODULE_DESCRIPTION("PCI driver module for Cyrix 5510/5520 IDE");
+--- 1.22/drivers/ide/pci/cs5530.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/cs5530.c	2004-06-16 15:49:00 +02:00
+@@ -267,7 +267,7 @@
+  *	Initialize the cs5530 bridge for reliable IDE DMA operation.
+  */
+ 
+-static unsigned int __init init_chipset_cs5530 (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const char *name)
+ {
+ 	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
+ 	unsigned long flags;
+@@ -366,7 +366,7 @@
+  *	performs channel-specific pre-initialization before drive probing.
+  */
+ 
+-static void __init init_hwif_cs5530 (ide_hwif_t *hwif)
++static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
+ {
+ 	unsigned long basereg;
+ 	u32 d0_timings;
+@@ -416,6 +416,8 @@
+ 
+ static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &cs5530_chipset);
+ 	return 0;
+ }
+@@ -437,7 +439,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit cs5530_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(cs5530_ide_init);
++module_exit(cs5530_ide_exit);
+ 
+ MODULE_AUTHOR("Mark Lord");
+ MODULE_DESCRIPTION("PCI driver module for Cyrix/NS 5530 IDE");
+--- 1.17/drivers/ide/pci/cy82c693.c	2004-03-18 15:20:56 +01:00
++++ edited/drivers/ide/pci/cy82c693.c	2004-06-16 15:44:17 +02:00
+@@ -334,7 +334,7 @@
+ /*
+  * this function is called during init and is used to setup the cy82c693 chip
+  */
+-static unsigned int __init init_chipset_cy82c693(struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const char *name)
+ {
+ 	if (PCI_FUNC(dev->devfn) != 1)
+ 		return 0;
+@@ -386,7 +386,7 @@
+ /*
+  * the init function - called for each ide channel once
+  */
+-static void __init init_hwif_cy82c693(ide_hwif_t *hwif)
++static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif)
+ {
+ 	hwif->autodma = 0;
+ 
+@@ -410,9 +410,9 @@
+ 	hwif->drives[1].autodma = hwif->autodma;
+ }
+ 
+-static __initdata ide_hwif_t *primary;
++static __devinitdata ide_hwif_t *primary;
+ 
+-void __init init_iops_cy82c693(ide_hwif_t *hwif)
++void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
+ {
+ 	if (PCI_FUNC(hwif->pci_dev->devfn) == 1)
+ 		primary = hwif;
+@@ -427,6 +427,9 @@
+ 	ide_pci_device_t *d = &cy82c693_chipsets[id->driver_data];
+ 	struct pci_dev *dev2;
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
++
+ 	/* CY82C693 is more than only a IDE controller.
+ 	   Function 1 is primary IDE channel, function 2 - secondary. */
+         if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE &&
+@@ -454,7 +457,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit cy82c693_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(cy82c693_ide_init);
++module_exit(cy82c693_ide_exit);
+ 
+ MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
+--- 1.16/drivers/ide/pci/generic.c	2004-06-01 21:04:38 +02:00
++++ edited/drivers/ide/pci/generic.c	2004-06-16 15:44:17 +02:00
+@@ -41,12 +41,12 @@
+ 
+ #include "generic.h"
+ 
+-static unsigned int __init init_chipset_generic (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_generic (struct pci_dev *dev, const char *name)
+ {
+ 	return 0;
+ }
+ 
+-static void __init init_hwif_generic (ide_hwif_t *hwif)
++static void __devinit init_hwif_generic (ide_hwif_t *hwif)
+ {
+ 	switch(hwif->pci_dev->device) {
+ 		case PCI_DEVICE_ID_UMC_UM8673F:
+@@ -113,6 +113,8 @@
+ 		printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
+ 		return 1; 
+ 	}
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, d);
+ 	return 0;
+ }
+@@ -146,7 +148,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit generic_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(generic_ide_init);
++module_exit(generic_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for generic PCI IDE");
+--- 1.23/drivers/ide/pci/hpt34x.c	2004-06-16 05:17:44 +02:00
++++ edited/drivers/ide/pci/hpt34x.c	2004-06-16 15:44:17 +02:00
+@@ -323,6 +323,9 @@
+ 	static char *chipset_names[] = {"HPT343", "HPT345"};
+ 	u16 pcicmd = 0;
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
++
+ 	pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+ 
+ 	d->name = chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0];
+@@ -349,7 +352,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit hpt34x_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(hpt34x_ide_init);
++module_exit(hpt34x_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for Highpoint 34x IDE");
+--- 1.34/drivers/ide/pci/hpt366.c	2004-06-16 05:17:44 +02:00
++++ edited/drivers/ide/pci/hpt366.c	2004-06-16 15:44:17 +02:00
+@@ -1241,6 +1241,8 @@
+ {
+ 	ide_pci_device_t *d = &hpt366_chipsets[id->driver_data];
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	d->init_setup(dev, d);
+ 	return 0;
+ }
+@@ -1266,7 +1268,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit hpt366_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(hpt366_ide_init);
++module_exit(hpt366_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
+--- 1.18/drivers/ide/pci/it8172.c	2004-06-01 21:04:38 +02:00
++++ edited/drivers/ide/pci/it8172.c	2004-06-16 15:48:50 +02:00
+@@ -238,7 +238,7 @@
+ 	return 0;
+ }
+ 
+-static unsigned int __init init_chipset_it8172 (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_it8172 (struct pci_dev *dev, const char *name)
+ {
+ 	unsigned char progif;
+     
+@@ -252,7 +252,7 @@
+ }
+ 
+ 
+-static void __init init_hwif_it8172 (ide_hwif_t *hwif)
++static void __devinit init_hwif_it8172 (ide_hwif_t *hwif)
+ {
+ 	struct pci_dev* dev = hwif->pci_dev;
+ 	unsigned long cmdBase, ctrlBase;
+@@ -291,6 +291,8 @@
+         if ((!(PCI_FUNC(dev->devfn) & 1) ||
+             (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))))
+                 return 1; /* IT8172 is more than only a IDE controller */
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &it8172_chipsets[id->driver_data]);
+ 	return 0;
+ }
+@@ -312,7 +314,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit it8172_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(it8172_ide_init);
++module_exit(it8172_ide_exit);
+ 
+ MODULE_AUTHOR("SteveL at mvista.com");
+ MODULE_DESCRIPTION("PCI driver module for ITE 8172 IDE");
+--- 1.19/drivers/ide/pci/ns87415.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/ns87415.c	2004-06-16 15:48:42 +02:00
+@@ -130,7 +130,7 @@
+ 	return __ide_dma_check(drive);
+ }
+ 
+-static void __init init_hwif_ns87415 (ide_hwif_t *hwif)
++static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = hwif->pci_dev;
+ 	unsigned int ctrl, using_inta;
+@@ -225,6 +225,8 @@
+ 
+ static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &ns87415_chipset);
+ 	return 0;
+ }
+@@ -246,7 +248,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit ns87415_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(ns87415_ide_init);
++module_exit(ns87415_ide_exit);
+ 
+ MODULE_AUTHOR("Mark Lord, Eddie Dost, Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for NS87415 IDE");
+--- 1.18/drivers/ide/pci/opti621.c	2004-06-01 21:04:38 +02:00
++++ edited/drivers/ide/pci/opti621.c	2004-06-16 15:48:02 +02:00
+@@ -328,7 +328,7 @@
+ /*
+  * init_hwif_opti621() is called once for each hwif found at boot.
+  */
+-static void __init init_hwif_opti621 (ide_hwif_t *hwif)
++static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
+ {
+ 	hwif->autodma = 0;
+ 	hwif->drives[0].drive_data = PIO_DONT_KNOW;
+@@ -348,13 +348,15 @@
+ 	hwif->drives[1].autodma = hwif->autodma;
+ }
+ 
+-static void __init init_setup_opti621 (struct pci_dev *dev, ide_pci_device_t *d)
++static void __devinit init_setup_opti621 (struct pci_dev *dev, ide_pci_device_t *d)
+ {
+ 	ide_setup_pci_device(dev, d);
+ }
+ 
+ static int __devinit opti621_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &opti621_chipsets[id->driver_data]);
+ 	return 0;
+ }
+@@ -377,7 +379,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit opti621_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(opti621_ide_init);
++module_exit(opti621_ide_exit);
+ 
+ MODULE_AUTHOR("Jaromir Koutek, Jan Harkes, Mark Lord");
+ MODULE_DESCRIPTION("PCI driver module for Opti621 IDE");
+--- 1.30/drivers/ide/pci/pdc202xx_new.c	2004-06-16 05:17:44 +02:00
++++ edited/drivers/ide/pci/pdc202xx_new.c	2004-06-16 15:44:17 +02:00
+@@ -514,6 +514,8 @@
+ {
+ 	ide_pci_device_t *d = &pdcnew_chipsets[id->driver_data];
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	d->init_setup(dev, d);
+ 	return 0;
+ }
+@@ -541,7 +543,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit pdc202new_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(pdc202new_ide_init);
++module_exit(pdc202new_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
+ MODULE_DESCRIPTION("PCI driver module for Promise PDC20268 and higher");
+--- 1.32/drivers/ide/pci/pdc202xx_old.c	2004-06-16 05:17:44 +02:00
++++ edited/drivers/ide/pci/pdc202xx_old.c	2004-06-16 15:44:17 +02:00
+@@ -884,6 +884,8 @@
+ {
+ 	ide_pci_device_t *d = &pdc202xx_chipsets[id->driver_data];
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	d->init_setup(dev, d);
+ 	return 0;
+ }
+@@ -909,7 +911,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit pdc202xx_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(pdc202xx_ide_init);
++module_exit(pdc202xx_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
+ MODULE_DESCRIPTION("PCI driver module for older Promise IDE");
+--- 1.32/drivers/ide/pci/piix.c	2004-06-15 18:29:18 +02:00
++++ edited/drivers/ide/pci/piix.c	2004-06-16 15:44:17 +02:00
+@@ -739,6 +739,8 @@
+ {
+ 	ide_pci_device_t *d = &piix_pci_info[id->driver_data];
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	d->init_setup(dev, d);
+ 	return 0;
+ }
+@@ -814,7 +816,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit piix_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(piix_ide_init);
++module_exit(piix_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz");
+ MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE");
+--- 1.15/drivers/ide/pci/rz1000.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/rz1000.c	2004-06-16 15:47:44 +02:00
+@@ -33,7 +33,7 @@
+ 
+ #include <asm/io.h>
+ 
+-static void __init init_hwif_rz1000 (ide_hwif_t *hwif)
++static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
+ {
+ 	u16 reg;
+ 	struct pci_dev *dev = hwif->pci_dev;
+@@ -62,6 +62,8 @@
+ 
+ static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &rz1000_chipset);
+ 	return 0;
+ }
+@@ -84,7 +86,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit rz1000_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(rz1000_ide_init);
++module_exit(rz1000_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for RZ1000 IDE");
+--- 1.19/drivers/ide/pci/sc1200.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/sc1200.c	2004-06-16 15:47:38 +02:00
+@@ -507,7 +507,7 @@
+ /*
+  * Initialize the sc1200 bridge for reliable IDE DMA operation.
+  */
+-static unsigned int __init init_chipset_sc1200 (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_sc1200 (struct pci_dev *dev, const char *name)
+ {
+ #if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
+ 	if (!bmide_dev) {
+@@ -523,7 +523,7 @@
+  * This gets invoked by the IDE driver once for each channel,
+  * and performs channel-specific pre-initialization before drive probing.
+  */
+-static void __init init_hwif_sc1200 (ide_hwif_t *hwif)
++static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
+ {
+ 	if (hwif->mate)
+ 		hwif->serialized = hwif->mate->serialized = 1;
+@@ -554,6 +554,8 @@
+ 
+ static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &sc1200_chipset);
+ 	return 0;
+ }
+@@ -577,7 +579,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit sc1200_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(sc1200_ide_init);
++module_exit(sc1200_ide_exit);
+ 
+ MODULE_AUTHOR("Mark Lord");
+ MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE");
+--- 1.29/drivers/ide/pci/serverworks.c	2004-06-01 21:04:38 +02:00
++++ edited/drivers/ide/pci/serverworks.c	2004-06-16 15:44:17 +02:00
+@@ -510,7 +510,7 @@
+ 	return __ide_dma_end(drive);
+ }
+ 
+-static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const char *name)
+ {
+ 	unsigned int reg;
+ 	u8 btr;
+@@ -630,7 +630,7 @@
+ 	return (dev->irq) ? dev->irq : 0;
+ }
+ 
+-static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif)
++static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
+ {
+ 	return 1;
+ }
+@@ -642,7 +642,7 @@
+  * Bit 14 clear = primary IDE channel does not have 80-pin cable.
+  * Bit 14 set   = primary IDE channel has 80-pin cable.
+  */
+-static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif)
++static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = hwif->pci_dev;
+ 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+@@ -660,7 +660,7 @@
+  *
+  * WARNING: this only works on Alpine hardware!
+  */
+-static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif)
++static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = hwif->pci_dev;
+ 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
+@@ -671,7 +671,7 @@
+ 	return 0;
+ }
+ 
+-static unsigned int __init ata66_svwks (ide_hwif_t *hwif)
++static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = hwif->pci_dev;
+ 
+@@ -696,7 +696,7 @@
+ }
+ 
+ #undef CAN_SW_DMA
+-static void __init init_hwif_svwks (ide_hwif_t *hwif)
++static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
+ {
+ 	u8 dma_stat = 0;
+ 
+@@ -744,7 +744,7 @@
+ /*
+  * We allow the BM-DMA driver to only work on enabled interfaces.
+  */
+-static void __init init_dma_svwks (ide_hwif_t *hwif, unsigned long dmabase)
++static void __devinit init_dma_svwks (ide_hwif_t *hwif, unsigned long dmabase)
+ {
+ 	struct pci_dev *dev = hwif->pci_dev;
+ 
+@@ -756,12 +756,12 @@
+ 	ide_setup_dma(hwif, dmabase, 8);
+ }
+ 
+-static void __init init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
++static void __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d)
+ {
+ 	ide_setup_pci_device(dev, d);
+ }
+ 
+-static void __init init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d)
++static void __devinit init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d)
+ {
+ 	if (!(PCI_FUNC(dev->devfn) & 1)) {
+ 		d->bootable = NEVER_BOARD;
+@@ -798,6 +798,8 @@
+ {
+ 	ide_pci_device_t *d = &serverworks_chipsets[id->driver_data];
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	d->init_setup(dev, d);
+ 	return 0;
+ }
+@@ -826,7 +828,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit svwks_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(svwks_ide_init);
++module_exit(svwks_ide_exit);
+ 
+ MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE");
+--- 1.9/drivers/ide/pci/sgiioc4.c	2004-06-01 21:04:38 +02:00
++++ edited/drivers/ide/pci/sgiioc4.c	2004-06-16 15:49:46 +02:00
+@@ -382,7 +382,7 @@
+ }
+ 
+ /* Creates a dma map for the scatter-gather list entries */
+-static void __init
++static void __devinit
+ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ {
+ 	int num_ports = sizeof (ioc4_dma_regs_t);
+@@ -608,7 +608,7 @@
+ 	return 0;
+ }
+ 
+-static void __init
++static void __devinit
+ ide_init_sgiioc4(ide_hwif_t * hwif)
+ {
+ 	hwif->mmio = 2;
+@@ -646,7 +646,7 @@
+ 	hwif->INB = &sgiioc4_INB;
+ }
+ 
+-static int __init
++static int __devinit
+ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
+ {
+ 	unsigned long base, ctl, dma_base, irqport;
+@@ -716,7 +716,7 @@
+ 				     *pci_dev, pciio_endian_t device_end,
+ 				     pciio_endian_t desired_end);
+ 
+-static unsigned int __init
++static unsigned int __devinit
+ pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d)
+ {
+ 	unsigned int class_rev;
+@@ -751,6 +751,9 @@
+ 		return -ENODEV;
+ 	}
+ 
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
++
+ 	return sgiioc4_ide_setup_pci_device(dev, d);
+ }
+ 
+@@ -793,7 +796,14 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void
++sgiioc4_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(sgiioc4_ide_init);
++module_exit(sgiioc4_ide_exit);
+ 
+ MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
+ MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+--- 1.30/drivers/ide/pci/siimage.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/siimage.c	2004-06-16 15:47:24 +02:00
+@@ -1121,6 +1121,8 @@
+  
+ static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]);
+ 	return 0;
+ }
+@@ -1144,7 +1146,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit siimage_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(siimage_ide_init);
++module_exit(siimage_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick, Alan Cox");
+ MODULE_DESCRIPTION("PCI driver module for SiI IDE");
+--- 1.27/drivers/ide/pci/sis5513.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/sis5513.c	2004-06-16 15:47:18 +02:00
+@@ -746,7 +746,7 @@
+ */
+ 
+ /* Chip detection and general config */
+-static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const char *name)
+ {
+ 	struct pci_dev *host;
+ 	int i = 0;
+@@ -890,7 +890,7 @@
+ 	return 0;
+ }
+ 
+-static unsigned int __init ata66_sis5513 (ide_hwif_t *hwif)
++static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
+ {
+ 	u8 ata66 = 0;
+ 
+@@ -908,7 +908,7 @@
+         return ata66;
+ }
+ 
+-static void __init init_hwif_sis5513 (ide_hwif_t *hwif)
++static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
+ {
+ 	hwif->autodma = 0;
+ 
+@@ -957,6 +957,8 @@
+ 
+ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &sis5513_chipset);
+ 	return 0;
+ }
+@@ -978,7 +980,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit sis5513_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(sis5513_ide_init);
++module_exit(sis5513_ide_exit);
+ 
+ MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik");
+ MODULE_DESCRIPTION("PCI driver module for SIS IDE");
+--- 1.20/drivers/ide/pci/sl82c105.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/sl82c105.c	2004-06-16 15:47:12 +02:00
+@@ -388,7 +388,7 @@
+  * channel 0 here at least, but channel 1 has to be enabled by
+  * firmware or arch code. We still set both to 16 bits mode.
+  */
+-static unsigned int __init init_chipset_sl82c105(struct pci_dev *dev, const char *msg)
++static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const char *msg)
+ {
+ 	u32 val;
+ 
+@@ -401,7 +401,7 @@
+ 	return dev->irq;
+ }
+ 
+-static void __init init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
++static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
+ {
+ 	unsigned int rev;
+ 	u8 dma_state;
+@@ -433,7 +433,7 @@
+  * Initialise the chip
+  */
+ 
+-static void __init init_hwif_sl82c105(ide_hwif_t *hwif)
++static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
+ {
+ 	struct pci_dev *dev = hwif->pci_dev;
+ 	u32 val;
+@@ -492,6 +492,8 @@
+ 
+ static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &sl82c105_chipset);
+ 	return 0;
+ }
+@@ -513,7 +515,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit sl82c105_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(sl82c105_ide_init);
++module_exit(sl82c105_ide_exit);
+ 
+ MODULE_DESCRIPTION("PCI driver module for W82C105 IDE");
+ MODULE_LICENSE("GPL");
+--- 1.22/drivers/ide/pci/slc90e66.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/slc90e66.c	2004-06-16 15:47:02 +02:00
+@@ -313,7 +313,7 @@
+ }
+ #endif /* CONFIG_BLK_DEV_IDEDMA */
+ 
+-static unsigned int __init init_chipset_slc90e66 (struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_slc90e66 (struct pci_dev *dev, const char *name)
+ {
+ #if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
+ 	if (!slc90e66_proc) {
+@@ -325,7 +325,7 @@
+ 	return 0;
+ }
+ 
+-static void __init init_hwif_slc90e66 (ide_hwif_t *hwif)
++static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
+ {
+ 	u8 reg47 = 0;
+ 	u8 mask = hwif->channel ? 0x01 : 0x02;  /* bit0:Primary */
+@@ -376,6 +376,8 @@
+ 
+ static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &slc90e66_chipset);
+ 	return 0;
+ }
+@@ -397,7 +399,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit slc90e66_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(slc90e66_ide_init);
++module_exit(slc90e66_ide_exit);
+ 
+ MODULE_AUTHOR("Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for SLC90E66 IDE");
+--- 1.9/drivers/ide/pci/triflex.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/triflex.c	2004-06-16 15:46:54 +02:00
+@@ -190,7 +190,7 @@
+ 	return hwif->ide_dma_on(drive);
+ }
+ 
+-static void __init init_hwif_triflex(ide_hwif_t *hwif)
++static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
+ {
+ 	hwif->tuneproc = &triflex_tune_drive;
+ 	hwif->speedproc = &triflex_tune_chipset;
+@@ -228,6 +228,8 @@
+ static int __devinit triflex_init_one(struct pci_dev *dev, 
+ 		const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &triflex_device);
+ 	triflex_dev = dev;
+ 
+@@ -252,7 +254,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit triflex_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(triflex_ide_init);
++module_exit(triflex_ide_exit);
+ 
+ MODULE_AUTHOR("Torben Mathiasen");
+ MODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE");
+--- 1.21/drivers/ide/pci/trm290.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/trm290.c	2004-06-16 15:46:45 +02:00
+@@ -403,6 +403,8 @@
+ 
+ static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	ide_setup_pci_device(dev, &trm290_chipset);
+ 	return 0;
+ }
+@@ -424,7 +426,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit trm290_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(trm290_ide_init);
++module_exit(trm290_ide_exit);
+ 
+ MODULE_AUTHOR("Mark Lord");
+ MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE");
+--- 1.23/drivers/ide/pci/via82cxxx.c	2004-06-15 18:29:40 +02:00
++++ edited/drivers/ide/pci/via82cxxx.c	2004-06-16 15:46:29 +02:00
+@@ -414,7 +414,7 @@
+  *	and initialize its drive independent registers.
+  */
+ 
+-static unsigned int __init init_chipset_via82cxxx(struct pci_dev *dev, const char *name)
++static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name)
+ {
+ 	struct pci_dev *isa = NULL;
+ 	u8 t, v;
+@@ -575,7 +575,7 @@
+ 	return 0;
+ }
+ 
+-static void __init init_hwif_via82cxxx(ide_hwif_t *hwif)
++static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
+ {
+ 	int i;
+ 
+@@ -621,6 +621,8 @@
+ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+ {
+ 	ide_setup_pci_device(dev, &via82cxxx_chipset);
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
+ 	return 0;
+ }
+ 
+@@ -642,7 +644,13 @@
+ 	return ide_pci_register_driver(&driver);
+ }
+ 
++static void __exit via_ide_exit(void)
++{
++	ide_pci_unregister_driver(&driver);
++}
++
+ module_init(via_ide_init);
++module_exit(via_ide_exit);
+ 
+ MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick");
+ MODULE_DESCRIPTION("PCI driver module for VIA IDE");
+--- 1.124/include/linux/ide.h	2004-06-05 21:58:33 +02:00
++++ edited/include/linux/ide.h	2004-06-16 15:44:18 +02:00
+@@ -1224,6 +1224,7 @@
+ extern	ide_hwif_t	ide_hwifs[];		/* master data repository */
+ #endif
+ extern int noautodma;
++extern int ide_scan_direction;
+ 
+ extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
+ 
+@@ -1524,7 +1525,7 @@
+ 
+ extern int ideprobe_init(void);
+ 
+-extern void ide_scan_pcibus(int scan_direction) __init;
++extern void ide_scan_pcibus(void);
+ extern int ide_pci_register_driver(struct pci_driver *driver);
+ extern void ide_pci_unregister_driver(struct pci_driver *driver);
+ extern void ide_pci_setup_ports(struct pci_dev *dev, struct ide_pci_device_s *d, int autodma, int pciirq, ata_index_t *index);

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-vesafb.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-vesafb.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-vesafb.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,112 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: modularised VESA FB
+## DP: Patch author: unknown
+## DP: Upstream status: not submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- kernel-source-2.6.6/drivers/video/Kconfig	2004-05-10 19:48:01.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/video/Kconfig	2004-05-10 22:21:43.000000000 +1000
+@@ -283,7 +283,7 @@
+ 	  cards. Say Y if you have one of those.
+ 
+ config FB_VESA
+-	bool "VESA VGA graphics support"
++	tristate "VESA VGA graphics support"
+ 	depends on FB && (X86 || X86_64)
+ 	help
+ 	  This is the frame buffer device driver for generic VESA 2.0
+
+--- a/drivers/video/vesafb.c	2004-10-18 17:53:11.000000000 -0400
++++ b/drivers/video/vesafb.c	2004-10-23 01:58:33.000000000 -0400
+@@ -19,6 +19,7 @@
+ #include <linux/fb.h>
+ #include <linux/ioport.h>
+ #include <linux/init.h>
++#include <linux/moduleparam.h>
+ #ifdef __i386__
+ #include <video/edid.h>
+ #endif
+@@ -49,6 +50,7 @@
+ 
+ static int             inverse   = 0;
+ static int             mtrr      = 1;
++static int             mtrr_hdl;
+ static int	       vram __initdata = 0; /* Set amount of memory to be used */
+ static int             pmi_setpal = 0;	/* pmi for palette changes ??? */
+ static int             ypan       = 0;  /* 0..nothing, 1..ypan, 2..ywrap */
+@@ -56,6 +58,9 @@
+ static void            (*pmi_start)(void);
+ static void            (*pmi_pal)(void);
+ 
++static char	       *options;
++module_param(options, charp, 0);
++
+ /* --------------------------------------------------------------------- */
+ 
+ static int vesafb_pan_display(struct fb_var_screeninfo *var,
+@@ -221,6 +226,8 @@
+ 	struct fb_info *info;
+ 	int i, err;
+ 
++	vesafb_setup(options);
++
+ 	if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
+ 		return -ENXIO;
+ 
+@@ -368,7 +375,7 @@
+                 	temp_size &= (temp_size - 1);
+                         
+                 /* Try and find a power of two to add */
+-		while (temp_size && mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
++		while (temp_size && (mtrr_hdl = mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)) == -EINVAL) {
+ 			temp_size >>= 1;
+ 		}
+ 	}
+@@ -390,6 +397,7 @@
+ 	}
+ 	printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ 	       info->node, info->fix.id);
++	dev_set_drvdata(device, info);
+ 	return 0;
+ err:
+ 	framebuffer_release(info);
+@@ -397,6 +405,17 @@
+ 	return err;
+ }
+ 
++static void __exit vesafb_remove(struct device *device)
++{
++	struct fb_info *info = dev_get_drvdata(device);
++
++	unregister_framebuffer(info);
++	if (mtrr && mtrr_hdl >= 0)
++		mtrr_del(mtrr_hdl, 0, 0);
++	iounmap(info->screen_base);
++	release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
++}
++
+ static struct device_driver vesafb_driver = {
+ 	.name	= "vesafb",
+ 	.bus	= &platform_bus_type,
+@@ -424,7 +443,16 @@
+ 	}
+ 	return ret;
+ }
++
++#ifdef MODULE
++static void __exit vesafb_exit(void)
++{
++	platform_device_unregister(&vesafb_device);
++	driver_unregister(&vesafb_driver);
++}
+ module_init(vesafb_init);
++module_exit(vesafb_exit);
++#endif
+ 
+ /*
+  * Overrides for Emacs so that we follow Linus's tabbing style.

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-xfrm_tunnel-export-symbol.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-xfrm_tunnel-export-symbol.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/modular-xfrm_tunnel-export-symbol.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,12 @@
+# author: Joshua Kwan
+# upstream status: not submitted
+# Export some symbols to fully fix modular xfrm4_tunnel.
+
+--- kernel-source-2.6.8-2.6.8/net/ipv4/xfrm4_input.c~	2004-08-27 11:17:30.000000000 -0700
++++ kernel-source-2.6.8-2.6.8/net/ipv4/xfrm4_input.c	2004-08-27 11:18:04.000000000 -0700
+@@ -154,3 +154,5 @@
+ 	kfree_skb(skb);
+ 	return 0;
+ }
++
++EXPORT_SYMBOL(xfrm4_rcv_encap);

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/parport_pc-via8231.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/parport_pc-via8231.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/parport_pc-via8231.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,447 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: VIA8231 support for parallel port driver
+## DP: Patch author: Pavel Fedin <sonic_amiga at rambler.ru>
+## DP: Upstream status: sumbitted, approved by Jeff Garzik <jgarzik at pobox.com>
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- a/drivers/parport/parport_pc.c.orig	2004-10-27 15:43:58.000000000 +0400
++++ b/drivers/parport/parport_pc.c	2004-10-27 15:31:11.000000000 +0400
+@@ -62,6 +62,7 @@
+ 
+ #include <linux/parport.h>
+ #include <linux/parport_pc.h>
++#include <linux/via.h>
+ #include <asm/parport.h>
+ 
+ #define PARPORT_PC_MAX_PORTS PARPORT_MAX
+@@ -2363,7 +2364,7 @@
+ 
+ /* ITE support maintained by Rich Liu <richliu at poorman.org> */
+ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
+-					 int autodma)
++					 int autodma, struct parport_pc_via_data *via)
+ {
+ 	short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
+ 	struct resource *base_res;
+@@ -2466,71 +2467,161 @@
+ 	return 0;
+ }
+ 
+-/* Via support maintained by Jeff Garzik <jgarzik at pobox.com> */
+-static int __devinit sio_via_686a_probe (struct pci_dev *pdev, int autoirq,
+-					 int autodma)
++/* VIA 8231 support by Pavel Fedin <sonic_amiga at rambler.ru>
++   based on VIA 686a support code by Jeff Garzik <jgarzik at pobox.com> */
++static int __initdata parport_init_mode = 0;
++
++/* Data for two known VIA chips */
++static struct parport_pc_via_data via_686a_data __devinitdata = {
++	0x51,
++	0x50,
++	0x85,
++	0x02,
++	0xE2,
++	0xF0,
++	0xE6
++};
++static struct parport_pc_via_data via_8231_data __devinitdata = {
++	0x45,
++	0x44,
++	0x50,
++	0x04,
++	0xF2,
++	0xFA,
++	0xF6
++};
++
++static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq,
++					 int autodma, struct parport_pc_via_data *via)
+ {
+-	u8 tmp;
++	u8 tmp, tmp2, siofunc, ppcontrol;
+ 	int dma, irq;
+-	unsigned port1, port2, have_eppecp;
++	unsigned port1, port2;
++	unsigned have_epp = 0;
++
++	printk(KERN_DEBUG "parport_pc: VIA 686A/8231 detected\n");
+ 
++	switch(parport_init_mode)
++	{
++	case 1:
++	    printk(KERN_DEBUG "parport_pc: setting SPP mode\n");
++	    siofunc = VIA_FUNCTION_PARPORT_SPP;
++	    ppcontrol = 0;
++	    break;
++	case 2:
++	    printk(KERN_DEBUG "parport_pc: setting PS/2 mode\n");
++	    siofunc = VIA_FUNCTION_PARPORT_SPP;
++	    ppcontrol = VIA_PARPORT_BIDIR;
++	    break;
++	case 3:
++	    printk(KERN_DEBUG "parport_pc: setting EPP mode\n");
++	    siofunc = VIA_FUNCTION_PARPORT_EPP;
++	    ppcontrol = VIA_PARPORT_BIDIR;
++	    have_epp = 1;
++	    break;
++	case 4:
++	    printk(KERN_DEBUG "parport_pc: setting ECP mode\n");
++	    siofunc = VIA_FUNCTION_PARPORT_ECP;
++	    ppcontrol = VIA_PARPORT_BIDIR;
++	    break;
++	case 5:
++	    printk(KERN_DEBUG "parport_pc: setting EPP+ECP mode\n");
++	    siofunc = VIA_FUNCTION_PARPORT_ECP;
++	    ppcontrol = VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP;
++	    have_epp = 1;
++	    break;
++	 default:
++	    printk(KERN_DEBUG "parport_pc: probing current configuration\n");
++	    siofunc = VIA_FUNCTION_PROBE;
++	    break;
++	}   
+ 	/*
+-	 * unlock super i/o configuration, set 0x85_1
+-	 */
+-	pci_read_config_byte (pdev, 0x85, &tmp);
+-	tmp |= (1 << 1);
+-	pci_write_config_byte (pdev, 0x85, tmp);
+-	
+-	/* 
+-	 * Super I/O configuration, index port == 3f0h, data port == 3f1h
++	 * unlock super i/o configuration
+ 	 */
++	pci_read_config_byte(pdev, via->via_pci_superio_config_reg, &tmp);
++	tmp |= via->via_pci_superio_config_data;
++	pci_write_config_byte(pdev, via->via_pci_superio_config_reg, tmp);
++
++	/* Bits 1-0: Parallel Port Mode / Enable */
++	outb(via->viacfg_function, VIA_CONFIG_INDEX);
++	tmp = inb (VIA_CONFIG_DATA);
++	/* Bit 5: EPP+ECP enable; bit 7: PS/2 bidirectional port enable */
++	outb(via->viacfg_parport_control, VIA_CONFIG_INDEX);
++	tmp2 = inb (VIA_CONFIG_DATA);
++	if (siofunc == VIA_FUNCTION_PROBE)
++	{
++	    siofunc = tmp & VIA_FUNCTION_PARPORT_DISABLE;
++	    ppcontrol = tmp2;
++	}
++	else
++	{   
++	    tmp &= ~VIA_FUNCTION_PARPORT_DISABLE;
++	    tmp |= siofunc;
++	    outb(via->viacfg_function, VIA_CONFIG_INDEX);
++	    outb(tmp, VIA_CONFIG_DATA);
++	    tmp2 &= ~(VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP);
++	    tmp2 |= ppcontrol;
++	    outb(via->viacfg_parport_control, VIA_CONFIG_INDEX);
++	    outb(tmp2, VIA_CONFIG_DATA);
++	}
+ 	
+-	/* 0xE2_1-0: Parallel Port Mode / Enable */
+-	outb (0xE2, 0x3F0);
+-	tmp = inb (0x3F1);
++	/* Parallel Port I/O Base Address, bits 9-2 */
++	outb(via->viacfg_parport_base, VIA_CONFIG_INDEX);
++	port1 = inb(VIA_CONFIG_DATA) << 2;
+ 	
+-	if ((tmp & 0x03) == 0x03) {
+-		printk (KERN_INFO "parport_pc: Via 686A parallel port disabled in BIOS\n");
+-		return 0;
++	printk (KERN_DEBUG "parport_pc: Current parallel port base: 0x%X\n",port1);
++	if ((port1 == 0x3BC) && have_epp)
++	{
++	    outb(via->viacfg_parport_base, VIA_CONFIG_INDEX);
++	    outb((0x378 >> 2), VIA_CONFIG_DATA);
++	    printk(KERN_DEBUG "parport_pc: Parallel port base changed to 0x378\n");
++	    port1 = 0x378;
+ 	}
++
++	/*
++	 * lock super i/o configuration
++	 */
++	pci_read_config_byte(pdev, via->via_pci_superio_config_reg, &tmp);
++	tmp &= ~via->via_pci_superio_config_data;
++	pci_write_config_byte(pdev, via->via_pci_superio_config_reg, tmp);
++
++	if (siofunc == VIA_FUNCTION_PARPORT_DISABLE) {
++		printk(KERN_INFO "parport_pc: VIA parallel port disabled in BIOS\n");
++		return 0;
++	}	
+ 	
+-	/* 0xE6: Parallel Port I/O Base Address, bits 9-2 */
+-	outb (0xE6, 0x3F0);
+-	port1 = inb (0x3F1) << 2;
+-	
++	/* Bits 7-4: PnP Routing for Parallel Port IRQ */
++	pci_read_config_byte(pdev, via->via_pci_parport_irq_reg, &tmp);
++	irq = ((tmp & VIA_IRQCONTROL_PARALLEL) >> 4);
++
++	if (siofunc == VIA_FUNCTION_PARPORT_ECP)
++	{
++	    /* Bits 3-2: PnP Routing for Parallel Port DMA */
++	    pci_read_config_byte(pdev, via->via_pci_parport_dma_reg, &tmp);
++	    dma = ((tmp & VIA_DMACONTROL_PARALLEL) >> 2);
++	}
++	else
++	    /* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */
++	    dma = PARPORT_DMA_NONE;
++
++	/* Let the user (or defaults) steer us away from interrupts and DMA */
++	if (autoirq == PARPORT_IRQ_NONE) {
++	    irq = PARPORT_IRQ_NONE;
++	    dma = PARPORT_DMA_NONE;
++	}
++	if (autodma == PARPORT_DMA_NONE)
++	    dma = PARPORT_DMA_NONE;
++
+ 	switch (port1) {
+ 	case 0x3bc: port2 = 0x7bc; break;
+ 	case 0x378: port2 = 0x778; break;
+ 	case 0x278: port2 = 0x678; break;
+ 	default:
+-		printk (KERN_INFO "parport_pc: Weird Via 686A parport base 0x%X, ignoring\n",
++		printk(KERN_INFO "parport_pc: Weird VIA parport base 0x%X, ignoring\n",
+ 			port1);
+ 		return 0;
+ 	}
+ 
+-	/* 0xF0_5: EPP+ECP enable */
+-	outb (0xF0, 0x3F0);
+-	have_eppecp = (inb (0x3F1) & (1 << 5));
+-	
+-	/*
+-	 * lock super i/o configuration, clear 0x85_1
+-	 */
+-	pci_read_config_byte (pdev, 0x85, &tmp);
+-	tmp &= ~(1 << 1);
+-	pci_write_config_byte (pdev, 0x85, tmp);
+-
+-	/*
+-	 * Get DMA and IRQ from PCI->ISA bridge PCI config registers
+-	 */
+-
+-	/* 0x50_3-2: PnP Routing for Parallel Port DRQ */
+-	pci_read_config_byte (pdev, 0x50, &tmp);
+-	dma = ((tmp >> 2) & 0x03);
+-	
+-	/* 0x51_7-4: PnP Routing for Parallel Port IRQ */
+-	pci_read_config_byte (pdev, 0x51, &tmp);
+-	irq = ((tmp >> 4) & 0x0F);
+-
+ 	/* filter bogus IRQs */
+ 	switch (irq) {
+ 	case 0:
+@@ -2544,22 +2635,10 @@
+ 		break;
+ 	}
+ 
+-	/* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */
+-	if (!have_eppecp)
+-		dma = PARPORT_DMA_NONE;
+-
+-	/* Let the user (or defaults) steer us away from interrupts and DMA */
+-	if (autoirq != PARPORT_IRQ_AUTO) {
+-		irq = PARPORT_IRQ_NONE;
+-		dma = PARPORT_DMA_NONE;
+-	}
+-	if (autodma != PARPORT_DMA_AUTO)
+-		dma = PARPORT_DMA_NONE;
+-
+ 	/* finally, do the probe with values obtained */
+ 	if (parport_pc_probe_port (port1, port2, irq, dma, NULL)) {
+ 		printk (KERN_INFO
+-			"parport_pc: Via 686A parallel port: io=0x%X", port1);
++			"parport_pc: VIA parallel port: io=0x%X", port1);
+ 		if (irq != PARPORT_IRQ_NONE)
+ 			printk (", irq=%d", irq);
+ 		if (dma != PARPORT_DMA_NONE)
+@@ -2568,7 +2647,7 @@
+ 		return 1;
+ 	}
+ 	
+-	printk (KERN_WARNING "parport_pc: Strange, can't probe Via 686A parallel port: io=0x%X, irq=%d, dma=%d\n",
++	printk(KERN_WARNING "parport_pc: Strange, can't probe VIA parallel port: io=0x%X, irq=%d, dma=%d\n",
+ 		port1, irq, dma);
+ 	return 0;
+ }
+@@ -2576,19 +2655,21 @@
+ 
+ enum parport_pc_sio_types {
+ 	sio_via_686a = 0,	/* Via VT82C686A motherboard Super I/O */
++	sio_via_8231,		/* Via VT8231 south bridge integrated Super IO */
+ 	sio_ite_8872,
+ 	last_sio
+ };
+ 
+ /* each element directly indexed from enum list, above */
+ static struct parport_pc_superio {
+-	int (*probe) (struct pci_dev *pdev, int autoirq, int autodma);
++	int (*probe) (struct pci_dev *pdev, int autoirq, int autodma, struct parport_pc_via_data *via);
++	struct parport_pc_via_data *via;
+ } parport_pc_superio_info[] __devinitdata = {
+-	{ sio_via_686a_probe, },
+-	{ sio_ite_8872_probe, },
++	{ sio_via_probe, &via_686a_data, },
++	{ sio_via_probe, &via_8231_data, },
++	{ sio_ite_8872_probe, NULL, },
+ };
+ 
+-
+ enum parport_pc_pci_cards {
+ 	siig_1p_10x = last_sio,
+ 	siig_2p_10x,
+@@ -2714,6 +2795,7 @@
+ static struct pci_device_id parport_pc_pci_tbl[] = {
+ 	/* Super-IO onboard chips */
+ 	{ 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },
++	{ 0x1106, 0x8231, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_8231 },
+ 	{ PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872,
+ 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_ite_8872 },
+ 
+@@ -2855,7 +2937,7 @@
+ 			continue;
+ 
+ 		if (parport_pc_superio_info[id->driver_data].probe
+-			(pdev, autoirq, autodma)) {
++			(pdev, autoirq, autodma,parport_pc_superio_info[id->driver_data].via)) {
+ 			ret++;
+ 		}
+ 	}
+@@ -3041,9 +3123,27 @@
+ 				     PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO);
+ }
+ 
++static int __init parport_init_mode_setup(const char *str) {
++
++	printk(KERN_DEBUG "parport_pc.c: Specified parameter parport_init_mode=%s\n", str);
++
++	if (!strcmp (str, "spp"))
++	    parport_init_mode=1;
++	if (!strcmp (str, "ps2"))
++	    parport_init_mode=2;
++	if (!strcmp (str, "epp"))
++	    parport_init_mode=3;
++	if (!strcmp (str, "ecp"))
++	    parport_init_mode=4;
++	if (!strcmp (str, "ecpepp"))
++	    parport_init_mode=5;
++	return 1;
++}
++
+ #ifdef MODULE
+ static const char *irq[PARPORT_PC_MAX_PORTS];
+ static const char *dma[PARPORT_PC_MAX_PORTS];
++static const char *init_mode;
+ 
+ MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
+ MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+@@ -3058,12 +3158,17 @@
+ MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
+ MODULE_PARM(verbose_probing, "i");
+ #endif
++MODULE_PARM_DESC(init_mode, "Initialise mode for VIA VT8231 port (spp, ps2, epp, ecp or ecpepp)");
++MODULE_PARM(init_mode, "s");
+ 
+ static int __init parse_parport_params(void)
+ {
+ 	unsigned int i;
+ 	int val;
+ 
++	if (init_mode)
++		parport_init_mode_setup(init_mode);
++
+ 	for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) {
+ 		if (parport_parse_irq(irq[i], &val))
+ 			return 1;
+@@ -3171,6 +3276,15 @@
+ }
+ 
+ __setup ("parport=", parport_setup);
++
++/*
++ * Acceptable parameters:
++ *
++ * parport_init_mode=[spp|ps2|epp|ecp|ecpepp]
++ */
++
++__setup("parport_init_mode=",parport_init_mode_setup);
++
+ #endif
+ 
+ /* "Parser" ends here */
+--- a/include/linux/parport_pc.h.orig	2004-10-27 15:45:37.000000000 +0400
++++ b/include/linux/parport_pc.h	2004-10-27 15:33:50.000000000 +0400
+@@ -43,6 +43,23 @@
+ 	struct parport *port;
+ };
+ 
++struct parport_pc_via_data
++{
++	/* ISA PnP IRQ routing register 1 */
++	u8 via_pci_parport_irq_reg;
++	/* ISA PnP DMA request routing register */
++	u8 via_pci_parport_dma_reg;
++	/* Register and value to enable SuperIO configuration access */
++	u8 via_pci_superio_config_reg;
++	u8 via_pci_superio_config_data;
++	/* SuperIO function register number */
++	u8 viacfg_function;
++	/* parallel port control register number */
++	u8 viacfg_parport_control;
++	/* Parallel port base address register */
++	u8 viacfg_parport_base;
++};
++
+ static __inline__ void parport_pc_write_data(struct parport *p, unsigned char d)
+ {
+ #ifdef DEBUG_PARPORT
+--- a/include/linux/via.h.orig	1970-01-01 03:00:00.000000000 +0300
++++ b/include/linux/via.h	2004-10-27 15:15:27.000000000 +0400
+@@ -0,0 +1,22 @@
++/* Miscellaneous definitions for VIA chipsets
++   Currently used only by drivers/parport/parport_pc.c */
++
++/* Values for SuperIO function select configuration register */
++#define VIA_FUNCTION_PARPORT_SPP     0x00
++#define VIA_FUNCTION_PARPORT_ECP     0x01
++#define VIA_FUNCTION_PARPORT_EPP     0x02
++#define VIA_FUNCTION_PARPORT_DISABLE 0x03
++#define VIA_FUNCTION_PROBE           0xFF /* Special magic value to be used in code, not to be written into chip */
++
++/* Bits for parallel port mode configuration register */
++#define VIA_PARPORT_ECPEPP 0X20
++#define VIA_PARPORT_BIDIR  0x80
++
++/* VIA configuration registers */
++#define VIA_CONFIG_INDEX 0x3F0
++#define VIA_CONFIG_DATA  0x3F1
++
++/* Mask for parallel port IRQ bits (in ISA PnP IRQ routing register 1) */
++#define VIA_IRQCONTROL_PARALLEL 0xF0
++/* Mask for parallel port DMA bits (in ISA PnP DMA routing register) */
++#define VIA_DMACONTROL_PARALLEL 0x0C
+--- a/Documentation/kernel-parameters.txt.orig	2004-10-27 15:46:17.000000000 +0400
++++ b/Documentation/kernel-parameters.txt	2004-10-27 15:55:09.000000000 +0400
+@@ -795,6 +795,16 @@
+ 					Parallel ports are assigned in the
+ 					order they are specified on the command
+ 					line, starting with parport0.
++	
++	parport_init_mode=
++			[HW,PPT]	Configure VIA parallel port to
++					operate in specific mode. This is
++					necessary on Pegasos computer where
++					firmware has no options for setting up
++					parallel port mode and sets it to
++					spp. Currently this function knows
++					686a and 8231 chips.
++			Format: [spp|ps2|epp|ecp|ecpepp]
+ 
+ 	pas2=		[HW,OSS]
+ 			Format: <io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-g4-l2-flush-errata.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-g4-l2-flush-errata.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-g4-l2-flush-errata.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,239 @@
+#! /bin/sh -e 
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Fixes g4 l2 cache flush and MSR erratas.
+## DP: Patch author: Sven Luther <luther at debian.org>
+## DP: Upstream status: under review by benh.
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN -X dontdiff linux-2.6.7-pegasos-orig/arch/ppc/kernel/cputable.c linux-2.6.7/arch/ppc/kernel/cputable.c
+--- linux-2.6.7-pegasos-orig/arch/ppc/kernel/cputable.c	2004-08-11 23:19:46.000000000 -0600
++++ linux-2.6.7/arch/ppc/kernel/cputable.c	2004-08-12 20:08:49.000000000 -0600
+@@ -263,7 +263,8 @@
+ 	CPU_FTR_COMMON |
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+-	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NEED_COHERENT,
++	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NEED_COHERENT |
++	CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -274,7 +275,8 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT,
++	CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT | 
++	CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -285,7 +287,7 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_NEED_COHERENT,
++	CPU_FTR_NEED_COHERENT | CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -296,7 +298,7 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS |
+-	CPU_FTR_NEED_COHERENT,
++	CPU_FTR_NEED_COHERENT | CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -307,7 +309,8 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS,
++	CPU_FTR_L3_DISABLE_NAP | CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS |
++	CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -318,7 +321,7 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
++	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -329,7 +332,8 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
++	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC |
++	CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -340,7 +344,8 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC,
++	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | 
++	CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -351,7 +356,7 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
++	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+@@ -362,7 +367,7 @@
+     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+ 	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP |
+ 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR |
+-	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT,
++	CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT | CPU_FTR_HWFLUSH_L2_CACHE,
+ 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
+ 	32, 32,
+ 	__setup_cpu_745x
+diff -urN -X dontdiff linux-2.6.7-pegasos-orig/arch/ppc/kernel/l2cr.S linux-2.6.7/arch/ppc/kernel/l2cr.S
+--- linux-2.6.7-pegasos-orig/arch/ppc/kernel/l2cr.S	2004-08-12 02:31:16.000000000 -0600
++++ linux-2.6.7/arch/ppc/kernel/l2cr.S	2004-08-12 20:52:04.716349536 -0600
+@@ -36,7 +36,9 @@
+ 		several months.  The L2CR is similar, but I'm going
+ 		to assume the user of this functions knows what they
+ 		are doing.
+-
++	June 17, 2004.
++	- JPAN: Fixed 745X L3 cache enablement routine, also use HW flush assist.
++	
+ 	Author:	Terry Greeniaus (tgree at phys.ualberta.ca)
+ 	Please e-mail updates to this file to me, thanks!
+ */
+@@ -154,9 +156,7 @@
+ 	       Don't do this unless you accomodate all processor variations.
+ 	       The bit moved on the 7450.....
+ 	  ****/
+-
+-	/* TODO: use HW flush assist when available */
+-
++BEGIN_FTR_SECTION
+ 	lis	r4,0x0002
+ 	mtctr	r4
+ 	li	r4,0
+@@ -175,7 +175,23 @@
+ 	dcbf	0,r4
+ 	addi	r4,r4,32		/* Go to start of next cache line */
+ 	bdnz	1b
++END_FTR_SECTION_IFCLR(CPU_FTR_HWFLUSH_L2_CACHE)
+ 
++BEGIN_FTR_SECTION
++	/* Use HW flush assist, MPC7447A errata #3 */
++	oris	r4,r4,0x0010	/* Set L2CR[IONLY/11] = 1 */
++	oris	r4,r4,0x0001	/* Set L2CR[DONLY/15] = 1 */
++	mtspr   L2CR,r4		/* Lock the L2	*/
++	sync
++	ori	r4,r4,0x0800	/* Set L2CR[L2HWF/20] = 1 */
++	mtspr   L2CR,r4		/* Flush the L2 */
++1:	
++	mfspr	r4,L2CR
++	andi.	r4,r4,0x0800	/* L2HWF still set? */
++	bne	1b
++	sync	/* sync to clear the store queues before L3 flush (UM step 5)*/
++END_FTR_SECTION_IFSET(CPU_FTR_HWFLUSH_L2_CACHE)
++	
+ 2:
+ 	/* Set up the L2CR configuration bits (and switch L2 off) */
+ 	/* CPU errata: Make sure the mtspr below is already in the
+@@ -292,17 +308,18 @@
+ 
+ 	/* Flush the cache.
+ 	 */
+-
+-	/* TODO: use HW flush assist */
+-
+-	lis	r4,0x0008
+-	mtctr	r4
+-	li	r4,0
+-1:
+-	lwzx	r0,r0,r4
+-	dcbf	0,r4
+-	addi	r4,r4,32		/* Go to start of next cache line */
+-	bdnz	1b
++	/* use HW flush assist. (UM 3.6.3.1.5) */
++	mfspr	r4, SPRN_L3CR
++	oris	r4,r4,0x0040	/* Set L3CR[L3IO/9] = 1. */
++	ori	r4,r4,0x0040	/* Set L3CR[L3DO/29] = 1.*/
++	mtspr	1018,r4		/* Lock the L3 by making IONLY and DONLY */
++	ori	r4,r4,0x0800	/* Set L3CR[L3HWF/20] for hardware flush */
++	mtspr	SPRN_L3CR,r4
++flush_745x_L3_poll:
++	mfspr	r4,SPRN_L3CR
++	rlwinm.	r4,r4,0,20,20
++	bne	flush_745x_L3_poll
++	sync	/* Clear the store queues per procedure (UM step 8) */
+ 
+ 2:
+ 	/* Set up the L3CR configuration bits (and switch L3 off) */
+@@ -348,8 +365,8 @@
+ 	cmplwi	r5,0
+ 	beq	4f
+ 
+-	/* Enable the cache */
+-	oris	r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h
++	/* enable L3 clock */
++	oris	r3,r3,(L3CR_L3CLKEN)@h
+ 	mtspr	SPRN_L3CR,r3
+ 	sync
+ 
+@@ -357,6 +374,15 @@
+ 	li	r0,256
+ 	mtctr	r0
+ 1:	bdnz	1b
++	
++	/* Clear MSSSR0 which may cause parity error */
++	xor	r5,r5,r5
++	mtspr	1015, r5
++	
++	/* Enable L3 cache */
++	oris	r3,r3,(L3CR_L3E)@h
++	mtspr	SPRN_L3CR,r3
++	sync
+ 
+ 	/* Restore MSR (restores EE and DR bits to original state) */
+ 4:	SYNC
+diff -urN -X dontdiff linux-2.6.7-pegasos-orig/arch/ppc/kernel/traps.c linux-2.6.7/arch/ppc/kernel/traps.c
+--- linux-2.6.7-pegasos-orig/arch/ppc/kernel/traps.c	2004-08-12 02:31:30.000000000 -0600
++++ linux-2.6.7/arch/ppc/kernel/traps.c	2004-08-12 02:10:05.000000000 -0600
+@@ -263,7 +263,9 @@
+ 	case 0x80000:
+ 		printk("Machine check signal\n");
+ 		break;
+-	case 0:		/* for 601 */
++	case 0:		/* for 601 and 744x */
++		printk("Transfer error ack signal if 601, or MCP if 744x \n");
++		break;
+ 	case 0x40000:
+ 	case 0x140000:	/* 7450 MSS error and TEA */
+ 		printk("Transfer error ack signal\n");
+diff -urN -X dontdiff linux-2.6.7-pegasos-orig/include/asm-ppc/cputable.h linux-2.6.7/include/asm-ppc/cputable.h
+--- linux-2.6.7-pegasos-orig/include/asm-ppc/cputable.h	2004-08-11 23:19:46.000000000 -0600
++++ linux-2.6.7/include/asm-ppc/cputable.h	2004-08-12 19:51:45.000000000 -0600
+@@ -77,6 +77,7 @@
+ #define CPU_FTR_HAS_HIGH_BATS		0x00010000
+ #define CPU_FTR_NEED_COHERENT           0x00020000
+ #define CPU_FTR_NO_BTIC			0x00040000
++#define CPU_FTR_HWFLUSH_L2_CACHE	0x00080000
+ 
+ #ifdef __ASSEMBLY__
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-pegasos.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-pegasos.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/powerpc-pegasos.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,266 @@
+#! /bin/sh -e 
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Add Pegasos 1 and 2 support.
+## DP: Patch author: Sven Luther <luther at debian.org>
+## DP: Upstream status: submitted and approved.
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -ur kernel-source-2.6.7.orig/arch/ppc/platforms/chrp_pci.c kernel-source-2.6.7.peg2/arch/ppc/platforms/chrp_pci.c
+--- kernel-source-2.6.7.orig/arch/ppc/platforms/chrp_pci.c	2004-06-16 07:20:26.000000000 +0200
++++ kernel-source-2.6.7.peg2/arch/ppc/platforms/chrp_pci.c	2004-06-29 18:10:43.000000000 +0200
+@@ -97,8 +97,9 @@
+ rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ 		 int len, u32 *val)
+ {
++	struct pci_controller *hose = bus->sysdata;
+ 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+-		| ((bus->number & 0xff) << 16);
++		| (((bus->number - hose->first_busno) & 0xff) << 16) | (pci_domain_nr(bus) << 24);
+         unsigned long ret = ~0UL;
+ 	int rval;
+ 
+@@ -111,8 +112,9 @@
+ rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ 		  int len, u32 val)
+ {
++	struct pci_controller *hose = bus->sysdata;
+ 	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+-		| ((bus->number & 0xff) << 16);
++		| (((bus->number - hose->first_busno) & 0xff) << 16) | (pci_domain_nr(bus) << 24);
+ 	int rval;
+ 
+ 	rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
+@@ -186,6 +188,26 @@
+ 	iounmap(reg);
+ }
+ 
++/* Marvell Discovery II based Pegasos 2 */
++//#define PEGASOS_USE_PCI_DOMAINS
++
++static void __init
++setup_peg2(struct pci_controller *hose, struct device_node *dev)
++{
++	struct device_node *root = find_path_device("/");
++	struct device_node *rtas;
++
++	rtas = of_find_node_by_name (root, "rtas");
++	if (rtas) {
++		hose->ops = &rtas_pci_ops;
++	} else {
++		printk ("RTAS supporting Pegasos OF not found, please upgrade your firmware\n");
++	}
++#ifndef PEGASOS_USE_PCI_DOMAINS
++	pci_assign_all_busses = 1;
++#endif
++}
++
+ void __init
+ chrp_find_bridges(void)
+ {
+@@ -195,7 +217,7 @@
+ 	struct pci_controller *hose;
+ 	unsigned int *dma;
+ 	char *model, *machine;
+-	int is_longtrail = 0, is_mot = 0;
++	int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
+ 	struct device_node *root = find_path_device("/");
+ 
+ 	/*
+@@ -207,6 +229,8 @@
+ 	if (machine != NULL) {
+ 		is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
+ 		is_mot = strncmp(machine, "MOT", 3) == 0;
++		if (strncmp(machine, "Pegasos2", 8) == 0) is_pegasos = 2;
++		else if (strncmp(machine, "Pegasos", 7) == 0) is_pegasos = 1;
+ 	}
+ 	for (dev = root->child; dev != NULL; dev = dev->sibling) {
+ 		if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
+@@ -257,6 +281,10 @@
+ 			hose->cfg_data = (unsigned char *)
+ 				ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
+ 			gg2_pci_config_base = (unsigned long) hose->cfg_data;
++		} else if (is_pegasos == 1) {
++			setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc);
++		} else if (is_pegasos == 2) {
++			setup_peg2(hose, dev);
+ 		} else {
+ 			printk("No methods for %s (model %s), using RTAS\n",
+ 			       dev->full_name, model);
+@@ -274,6 +302,9 @@
+ 			printk("pci_dram_offset = %lx\n", pci_dram_offset);
+ 		}
+ 	}
+-
+-	ppc_md.pcibios_fixup = chrp_pcibios_fixup;
++	
++	if (is_pegasos)
++		ppc_md.pcibios_fixup = NULL;
++	else
++		ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+ }
+diff -ur kernel-source-2.6.7.orig/arch/ppc/platforms/chrp_setup.c kernel-source-2.6.7.peg2/arch/ppc/platforms/chrp_setup.c
+--- kernel-source-2.6.7.orig/arch/ppc/platforms/chrp_setup.c	2004-06-16 07:19:52.000000000 +0200
++++ kernel-source-2.6.7.peg2/arch/ppc/platforms/chrp_setup.c	2004-06-29 18:10:44.000000000 +0200
+@@ -214,6 +214,37 @@
+ 	}
+ }
+ 
++void pegasos_set_l2cr(void)
++{
++	struct device_node *root = find_path_device("/");
++	char *machine;
++	struct device_node *np;
++	int l2cr_value;
++
++	/* On Pegasos, enable the l2 cache if needed, as the OF forgets it */
++	if (root == NULL)
++		return;
++	machine = get_property(root, "model", NULL);
++	if (machine == NULL)
++		return;
++	if (strncmp(machine, "Pegasos", 7) == 0) {
++		/* Enable L2 cache if needed */
++		np = find_type_devices("cpu");
++		if (np != NULL) {
++			unsigned int *l2cr = (unsigned int *)
++				get_property (np, "l2cr", NULL);
++			if (l2cr == NULL) {
++				printk ("Pegasos l2cr : no cpu l2cr property found\n");
++				return;
++			}
++			if (!((*l2cr) & 0x80000000)) {
++				printk ("Pegasos l2cr : L2 cache was not active, activating\n");
++				_set_L2CR(0);
++				_set_L2CR((*l2cr) | 0x80000000);
++			}
++		}
++	}
++}
+ 
+ void __init
+ chrp_setup_arch(void)
+@@ -236,6 +267,9 @@
+ 	/* Lookup PCI host bridges */
+ 	chrp_find_bridges();
+ 
++	/* On pegasos, enable the L2 cache if not already done by OF */
++	pegasos_set_l2cr();
++
+ #ifndef CONFIG_PPC64BRIDGE
+ 	/*
+ 	 *  Temporary fixes for PCI devices.
+@@ -387,6 +421,8 @@
+ #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
+ 	struct device_node *kbd;
+ #endif
++	struct device_node *root = find_path_device ("/");
++	char *machine;
+ 
+ 	for (np = find_devices("pci"); np != NULL; np = np->next) {
+ 		unsigned int *addrp = (unsigned int *)
+@@ -400,16 +436,20 @@
+ 	if (np == NULL)
+ 		printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n");
+ 
+-	chrp_find_openpic();
+-
+-	prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
+-	OpenPIC_InitSenses = init_senses;
+-	OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
+-
+-	openpic_init(NUM_8259_INTERRUPTS);
+-	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+-	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
++	/* Pegasos doesn't have openpic */
++	machine = get_property(root, "model", NULL);
++	if (strncmp(machine, "Pegasos", 7) != 0) {
++		chrp_find_openpic();
++
++		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
++		OpenPIC_InitSenses = init_senses;
++		OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
++
++		openpic_init(NUM_8259_INTERRUPTS);
++		/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
++		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+ 			       i8259_irq);
++	}
+ 
+ 	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+ 		irq_desc[i].handler = &i8259_pic;
+@@ -450,6 +490,8 @@
+ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ 	  unsigned long r6, unsigned long r7)
+ {
++	struct device_node *root = find_path_device ("/");
++	char *machine;
+ #ifdef CONFIG_BLK_DEV_INITRD
+ 	/* take care of initrd if we have one */
+ 	if ( r6 )
+@@ -469,7 +511,11 @@
+ 	ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
+ 	ppc_md.irq_canonicalize = chrp_irq_canonicalize;
+ 	ppc_md.init_IRQ       = chrp_init_IRQ;
+-	ppc_md.get_irq        = openpic_get_irq;
++	machine = get_property(root, "model", NULL);
++	if (strncmp(machine, "Pegasos", 7) == 0)
++		ppc_md.get_irq        = i8259_irq;
++	else
++		ppc_md.get_irq        = openpic_get_irq;
+ 
+ 	ppc_md.init           = chrp_init2;
+ 
+diff -ur kernel-source-2.6.7.orig/arch/ppc/platforms/chrp_time.c kernel-source-2.6.7.peg2/arch/ppc/platforms/chrp_time.c
+--- kernel-source-2.6.7.orig/arch/ppc/platforms/chrp_time.c	2004-06-16 07:18:57.000000000 +0200
++++ kernel-source-2.6.7.peg2/arch/ppc/platforms/chrp_time.c	2004-06-29 18:10:44.000000000 +0200
+@@ -41,6 +41,8 @@
+ 	int base;
+ 
+ 	rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
++	if (rtcs == NULL)
++		rtcs = find_compatible_devices("rtc", "ds1385-rtc");
+ 	if (rtcs == NULL || rtcs->addrs == NULL)
+ 		return 0;
+ 	base = rtcs->addrs[0].address;
+diff -ur kernel-source-2.6.7.orig/arch/ppc/syslib/prom_init.c kernel-source-2.6.7.peg2/arch/ppc/syslib/prom_init.c
+--- kernel-source-2.6.7.orig/arch/ppc/syslib/prom_init.c	2004-06-16 07:20:24.000000000 +0200
++++ kernel-source-2.6.7.peg2/arch/ppc/syslib/prom_init.c	2004-06-30 07:51:49.975232432 +0200
+@@ -794,6 +794,9 @@
+ 	char *p, *d;
+  	unsigned long phys;
+ 	void *result[3];
++	char model[32];
++	phandle node;
++	int rc;
+ 
+  	/* Default */
+  	phys = (unsigned long) &_stext;
+@@ -850,11 +853,20 @@
+ 
+ 	klimit = (char *) (mem - offset);
+ 
+-	/* If we are already running at 0xc0000000, we assume we were
+-	 * loaded by an OF bootloader which did set a BAT for us.
+-	 * This breaks OF translate so we force phys to be 0.
+-	 */
+-	if (offset == 0) {
++	node = call_prom("finddevice", 1, 1, "/");
++	rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
++	if (rc > 0 && !strncmp (model, "Pegasos", 7)
++		&& strncmp (model, "Pegasos2", 8)) {
++		/* Pegasos 1 has a broken translate method in the OF,
++		 * and furthermore the BATs are mapped 1:1 so the phys
++		 * address calculated above is correct, so let's use
++		 * it directly.
++		 */
++	} else if (offset == 0) {
++		/* If we are already running at 0xc0000000, we assume we were
++	 	* loaded by an OF bootloader which did set a BAT for us.
++	 	* This breaks OF translate so we force phys to be 0.
++	 	*/
+ 		prom_print("(already at 0xc0000000) phys=0\n");
+ 		phys = 0;
+ 	} else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu",

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ppc64-iSeries-build-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ppc64-iSeries-build-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/ppc64-iSeries-build-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,60 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: build fix for iSeries
+## DP: Patch author: Benjamin Herrenschmidt <benh at kernel.crashing.org>
+## DP: Upstream status: backport 2.6.9-bk5
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
+--- a/arch/ppc64/kernel/iSeries_pci.c	2004-10-21 06:22:45 -07:00
++++ b/arch/ppc64/kernel/iSeries_pci.c	2004-10-21 06:22:45 -07:00
+@@ -55,6 +55,7 @@
+ extern unsigned long iSeries_Base_Io_Memory;    
+ 
+ extern struct iommu_table *tceTables[256];
++extern unsigned long io_page_mask;
+ 
+ extern void iSeries_MmIoTest(void);
+ 
+@@ -196,6 +197,7 @@
+ 	PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); 
+ 	iSeries_IoMmTable_Initialize();
+ 	find_and_init_phbs();
++	io_page_mask = -1;
+ 	/* pci_assign_all_busses = 0;		SFRXXX*/
+ 	PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); 
+ }
+diff -Nru a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
+--- a/include/asm-ppc64/eeh.h	2004-10-21 06:22:45 -07:00
++++ b/include/asm-ppc64/eeh.h	2004-10-21 06:22:45 -07:00
+@@ -256,10 +256,6 @@
+ 
+ #undef EEH_CHECK_ALIGN
+ 
+-#define MAX_ISA_PORT 0x10000
+-extern unsigned long io_page_mask;
+-#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) & io_page_mask)
+-
+ static inline u8 eeh_inb(unsigned long port) {
+ 	u8 val;
+ 	if (!_IO_IS_VALID(port))
+diff -Nru a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
+--- a/include/asm-ppc64/io.h	2004-10-21 06:22:45 -07:00
++++ b/include/asm-ppc64/io.h	2004-10-21 06:22:45 -07:00
+@@ -33,6 +33,12 @@
+ 
+ extern unsigned long isa_io_base;
+ extern unsigned long pci_io_base;
++extern unsigned long io_page_mask;
++
++#define MAX_ISA_PORT 0x10000
++
++#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \
++			    & io_page_mask)
+ 
+ #ifdef CONFIG_PPC_ISERIES
+ /* __raw_* accessors aren't supported on iSeries */

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/remove-references-to-removed-drivers.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/remove-references-to-removed-drivers.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/remove-references-to-removed-drivers.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,672 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: remove non-free bits
+## DP: Patch author: unknown
+## DP: Upstream status: not submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN kernel-source-2.6.6/arch/alpha/defconfig kernel-source-2.6.6-1/arch/alpha/defconfig
+--- kernel-source-2.6.6/arch/alpha/defconfig	2004-04-05 19:49:22.000000000 +1000
++++ kernel-source-2.6.6-1/arch/alpha/defconfig	2004-04-05 20:54:15.000000000 +1000
+@@ -492,7 +492,6 @@
+ # CONFIG_B44 is not set
+ # CONFIG_FORCEDETH is not set
+ # CONFIG_CS89x0 is not set
+-# CONFIG_DGRS is not set
+ # CONFIG_EEPRO100 is not set
+ # CONFIG_E100 is not set
+ # CONFIG_LNE390 is not set
+diff -urN kernel-source-2.6.6/arch/arm/defconfig kernel-source-2.6.6-1/arch/arm/defconfig
+--- kernel-source-2.6.6/arch/arm/defconfig	2004-03-11 13:55:24.000000000 +1100
++++ kernel-source-2.6.6-1/arch/arm/defconfig	2003-09-21 08:41:56.000000000 +1000
+@@ -239,7 +239,6 @@
+ # CONFIG_CS89x0 is not set
+ CONFIG_TULIP=y
+ # CONFIG_DE4X5 is not set
+-# CONFIG_DGRS is not set
+ # CONFIG_DM9102 is not set
+ CONFIG_EEPRO100=y
+ CONFIG_EEPRO100_PM=y
+@@ -262,7 +261,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-# CONFIG_ACENIC is not set
+ # CONFIG_HAMACHI is not set
+ # CONFIG_YELLOWFIN is not set
+ # CONFIG_SK98LIN is not set
+diff -urN kernel-source-2.6.6/arch/i386/defconfig kernel-source-2.6.6-1/arch/i386/defconfig
+--- kernel-source-2.6.6/arch/i386/defconfig	2004-04-05 19:49:22.000000000 +1000
++++ kernel-source-2.6.6-1/arch/i386/defconfig	2004-04-05 20:54:17.000000000 +1000
+@@ -624,7 +624,6 @@
+ # CONFIG_B44 is not set
+ # CONFIG_FORCEDETH is not set
+ # CONFIG_CS89x0 is not set
+-# CONFIG_DGRS is not set
+ # CONFIG_EEPRO100 is not set
+ # CONFIG_E100 is not set
+ # CONFIG_FEALNX is not set
+@@ -646,7 +645,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-# CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ # CONFIG_E1000 is not set
+ # CONFIG_NS83820 is not set
+@@ -1027,7 +1025,6 @@
+ #
+ # USB Multimedia devices
+ #
+-# CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Video4Linux support is needed for USB Multimedia device support
+diff -urN kernel-source-2.6.6/arch/ia64/defconfig kernel-source-2.6.6-1/arch/ia64/defconfig
+--- kernel-source-2.6.6/arch/ia64/defconfig	2004-05-10 19:47:46.000000000 +1000
++++ kernel-source-2.6.6-1/arch/ia64/defconfig	2004-05-10 22:21:10.000000000 +1000
+@@ -439,7 +439,6 @@
+ # CONFIG_ADAPTEC_STARFIRE is not set
+ # CONFIG_B44 is not set
+ # CONFIG_FORCEDETH is not set
+-# CONFIG_DGRS is not set
+ CONFIG_EEPRO100=y
+ # CONFIG_EEPRO100_PIO is not set
+ # CONFIG_E100 is not set
+@@ -456,7 +455,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-# CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ CONFIG_E1000=y
+ # CONFIG_E1000_NAPI is not set
+@@ -865,7 +863,6 @@
+ #
+ # USB Multimedia devices
+ #
+-# CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Video4Linux support is needed for USB Multimedia device support
+diff -urN kernel-source-2.6.6/arch/parisc/defconfig kernel-source-2.6.6-1/arch/parisc/defconfig
+--- kernel-source-2.6.6/arch/parisc/defconfig	2004-05-10 19:47:49.000000000 +1000
++++ kernel-source-2.6.6-1/arch/parisc/defconfig	2004-05-10 22:21:17.000000000 +1000
+@@ -366,7 +366,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-# CONFIG_ACENIC is not set
+ CONFIG_DL2K=y
+ # CONFIG_E1000 is not set
+ # CONFIG_NS83820 is not set
+@@ -703,7 +702,6 @@
+ #
+ # USB Multimedia devices
+ #
+-# CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Video4Linux support is needed for USB Multimedia device support
+diff -urN kernel-source-2.6.6/arch/ppc/defconfig kernel-source-2.6.6-1/arch/ppc/defconfig
+--- kernel-source-2.6.6/arch/ppc/defconfig	2004-05-10 19:47:49.000000000 +1000
++++ kernel-source-2.6.6-1/arch/ppc/defconfig	2004-05-10 22:21:17.000000000 +1000
+@@ -559,7 +558,6 @@
+ # CONFIG_B44 is not set
+ # CONFIG_FORCEDETH is not set
+ # CONFIG_CS89x0 is not set
+-# CONFIG_DGRS is not set
+ # CONFIG_EEPRO100 is not set
+ # CONFIG_E100 is not set
+ # CONFIG_FEALNX is not set
+@@ -577,7 +576,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-# CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ # CONFIG_E1000 is not set
+ # CONFIG_NS83820 is not set
+@@ -1080,7 +1078,6 @@
+ #
+ # USB Multimedia devices
+ #
+-# CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Video4Linux support is needed for USB Multimedia device support
+diff -urN kernel-source-2.6.6/arch/ppc64/defconfig kernel-source-2.6.6-1/arch/ppc64/defconfig
+--- kernel-source-2.6.6/arch/ppc64/defconfig	2004-05-10 19:47:49.000000000 +1000
++++ kernel-source-2.6.6-1/arch/ppc64/defconfig	2004-05-10 22:21:18.000000000 +1000
+@@ -459,7 +459,6 @@
+ # CONFIG_ADAPTEC_STARFIRE is not set
+ # CONFIG_B44 is not set
+ # CONFIG_FORCEDETH is not set
+-# CONFIG_DGRS is not set
+ # CONFIG_EEPRO100 is not set
+ CONFIG_E100=y
+ # CONFIG_E100_NAPI is not set
+@@ -476,8 +475,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-CONFIG_ACENIC=y
+-CONFIG_ACENIC_OMIT_TIGON_I=y
+ # CONFIG_DL2K is not set
+ CONFIG_E1000=y
+ # CONFIG_E1000_NAPI is not set
+diff -urN kernel-source-2.6.6/arch/sparc64/defconfig kernel-source-2.6.6-1/arch/sparc64/defconfig
+--- kernel-source-2.6.6/arch/sparc64/defconfig	2004-05-10 19:47:50.000000000 +1000
++++ kernel-source-2.6.6-1/arch/sparc64/defconfig	2004-05-10 22:21:21.000000000 +1000
+@@ -840,7 +840,6 @@
+ CONFIG_ADAPTEC_STARFIRE_NAPI=y
+ CONFIG_B44=m
+ CONFIG_FORCEDETH=m
+-CONFIG_DGRS=m
+ CONFIG_EEPRO100=m
+ # CONFIG_EEPRO100_PIO is not set
+ CONFIG_E100=m
+@@ -864,8 +863,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-CONFIG_ACENIC=m
+-# CONFIG_ACENIC_OMIT_TIGON_I is not set
+ CONFIG_DL2K=m
+ CONFIG_E1000=m
+ CONFIG_E1000_NAPI=y
+@@ -1579,7 +1576,6 @@
+ #
+ # USB Multimedia devices
+ #
+-# CONFIG_USB_DABUSB is not set
+ # CONFIG_USB_VICAM is not set
+ # CONFIG_USB_DSBR is not set
+ # CONFIG_USB_IBMCAM is not set
+diff -urN kernel-source-2.6.6/arch/x86_64/defconfig kernel-source-2.6.6-1/arch/x86_64/defconfig
+--- kernel-source-2.6.6/arch/x86_64/defconfig	2004-05-10 19:47:50.000000000 +1000
++++ kernel-source-2.6.6-1/arch/x86_64/defconfig	2004-05-10 22:21:22.000000000 +1000
+@@ -437,7 +436,6 @@
+ # CONFIG_ADAPTEC_STARFIRE is not set
+ # CONFIG_B44 is not set
+ CONFIG_FORCEDETH=y
+-# CONFIG_DGRS is not set
+ # CONFIG_EEPRO100 is not set
+ # CONFIG_E100 is not set
+ # CONFIG_FEALNX is not set
+@@ -457,7 +456,6 @@
+ #
+ # Ethernet (1000 Mbit)
+ #
+-# CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ CONFIG_E1000=y
+ # CONFIG_E1000_NAPI is not set
+diff -urN kernel-source-2.6.6/drivers/net/tokenring/Kconfig kernel-source-2.6.6-1/drivers/net/tokenring/Kconfig
+--- kernel-source-2.6.6/drivers/net/tokenring/Kconfig	2004-03-11 13:55:24.000000000 +1100
++++ kernel-source-2.6.6-1/drivers/net/tokenring/Kconfig	2004-01-14 20:00:15.000000000 +1100
+@@ -165,21 +165,5 @@
+ 	  To compile this driver as a module, choose M here: the module will be
+ 	  called madgemc.
+ 
+-config SMCTR
+-	tristate "SMC ISA/MCA adapter support"
+-	depends on TR && (ISA || MCA_LEGACY) && (BROKEN || !64BIT)
+-	---help---
+-	  This is support for the ISA and MCA SMC Token Ring cards,
+-	  specifically SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A
+-	  (8115T/A) adapters.
+-
+-	  If you have such an adapter and would like to use it, say Y or M and
+-	  read the Token-Ring mini-HOWTO, available from
+-	  <http://www.tldp.org/docs.html#howto> and the file
+-	  <file:Documentation/networking/smctr.txt>.
+-
+-	  To compile this driver as a module, choose M here: the module will be
+-	  called smctr.
+-
+ endmenu
+ 
+diff -urN kernel-source-2.6.6/drivers/scsi/Kconfig kernel-source-2.6.6-1/drivers/scsi/Kconfig
+--- kernel-source-2.6.6/drivers/scsi/Kconfig	2004-05-10 19:47:58.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/scsi/Kconfig	2004-05-10 22:21:38.000000000 +1000
+@@ -1259,8 +1277,6 @@
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called qlogicpti.
+ 
+-source "drivers/scsi/qla2xxx/Kconfig"
+-
+ config SCSI_SEAGATE
+ 	tristate "Seagate ST-02 and Future Domain TMC-8xx SCSI support"
+ 	depends on X86 && ISA && SCSI && BROKEN
+diff -urN kernel-source-2.6.6/drivers/scsi/Makefile kernel-source-2.6.6-1/drivers/scsi/Makefile
+--- kernel-source-2.6.6/drivers/scsi/Makefile	2004-05-10 19:47:58.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/scsi/Makefile	2004-05-10 22:21:38.000000000 +1000
+@@ -80,7 +80,6 @@
+ obj-$(CONFIG_SCSI_QLOGIC_ISP)	+= qlogicisp.o 
+ obj-$(CONFIG_SCSI_QLOGIC_FC)	+= qlogicfc.o 
+ obj-$(CONFIG_SCSI_QLOGIC_1280)	+= qla1280.o 
+-obj-$(CONFIG_SCSI_QLA2XXX)	+= qla2xxx/
+ obj-$(CONFIG_SCSI_PAS16)	+= pas16.o
+ obj-$(CONFIG_SCSI_SEAGATE)	+= seagate.o
+ obj-$(CONFIG_SCSI_FD_8xx)	+= seagate.o
+diff -urN kernel-source-2.6.6/drivers/usb/media/Kconfig kernel-source-2.6.6-1/drivers/usb/media/Kconfig
+--- kernel-source-2.6.6/drivers/usb/media/Kconfig	2004-05-10 19:48:01.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/usb/media/Kconfig	2004-05-10 22:21:43.000000000 +1000
+@@ -4,20 +4,6 @@
+ comment "USB Multimedia devices"
+ 	depends on USB
+ 
+-config USB_DABUSB
+-	tristate "DABUSB driver"
+-	depends on USB
+-	---help---
+-	  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+-	  brought to you by the DAB-Team
+-	  <http://wwwbode.cs.tum.edu/Par/arch/dab/>.  This driver can be taken
+-	  as an example for URB-based bulk, control, and isochronous
+-	  transactions. URB's are explained in
+-	  <file:Documentation/usb/URB.txt>.
+-
+-	  To compile this driver as a module, choose M here: the
+-	  module will be called dabusb.
+-
+ comment "Video4Linux support is needed for USB Multimedia device support"
+ 	depends on USB && VIDEO_DEV=n
+ 
+diff -urN kernel-source-2.6.6/drivers/usb/serial/Kconfig kernel-source-2.6.6-1/drivers/usb/serial/Kconfig
+--- kernel-source-2.6.6/drivers/usb/serial/Kconfig	2004-03-11 13:55:37.000000000 +1100
++++ kernel-source-2.6.6-1/drivers/usb/serial/Kconfig	2003-11-24 20:51:58.000000000 +1100
+@@ -219,84 +219,6 @@
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called keyspan.
+ 
+-config USB_SERIAL_KEYSPAN_MPR
+-	bool "USB Keyspan MPR Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the Keyspan MPR converter.
+-
+-config USB_SERIAL_KEYSPAN_USA28
+-	bool "USB Keyspan USA-28 Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-28 converter.
+-
+-config USB_SERIAL_KEYSPAN_USA28X
+-	bool "USB Keyspan USA-28X Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-28X converter.
+-	  Be sure you have a USA-28X, there are also 28XA and 28XB
+-	  models, the label underneath has the actual part number.
+-
+-config USB_SERIAL_KEYSPAN_USA28XA
+-	bool "USB Keyspan USA-28XA Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-28XA converter.
+-	  Be sure you have a USA-28XA, there are also 28X and 28XB
+-	  models, the label underneath has the actual part number.
+-
+-config USB_SERIAL_KEYSPAN_USA28XB
+-	bool "USB Keyspan USA-28XB Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-28XB converter.
+-	  Be sure you have a USA-28XB, there are also 28X and 28XA
+-	  models, the label underneath has the actual part number.
+-
+-config USB_SERIAL_KEYSPAN_USA19
+-	bool "USB Keyspan USA-19 Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-19 converter.
+-
+-config USB_SERIAL_KEYSPAN_USA18X
+-	bool "USB Keyspan USA-18X Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-18X converter.
+-
+-config USB_SERIAL_KEYSPAN_USA19W
+-	bool "USB Keyspan USA-19W Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-19W converter.
+-
+-config USB_SERIAL_KEYSPAN_USA19QW
+-	bool "USB Keyspan USA-19QW Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-19QW converter.
+-
+-config USB_SERIAL_KEYSPAN_USA19QI
+-	bool "USB Keyspan USA-19QI Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-19QI converter.
+-
+-config USB_SERIAL_KEYSPAN_USA49W
+-	bool "USB Keyspan USA-49W Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-49W converter.
+-
+-config USB_SERIAL_KEYSPAN_USA49WLC
+-	bool "USB Keyspan USA-49WLC Firmware"
+-	depends on USB_SERIAL_KEYSPAN
+-	help
+-	  Say Y here to include firmware for the USA-49WLC converter.
+-
+ config USB_SERIAL_KLSI
+ 	tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
+ 	depends on USB_SERIAL && EXPERIMENTAL
+--- kernel-source-2.6.6/drivers/net/Kconfig	2004-05-10 19:47:54.000000000 +1000
++++ kernel-source-2.6.6-1/drivers/net/Kconfig	2004-05-11 22:25:31.000000000 +1000
+@@ -1383,21 +1383,6 @@
+ 	tristate "TOSHIBA TC35815 Ethernet support"
+ 	depends on NET_PCI && PCI && TOSHIBA_JMR3927
+ 
+-config DGRS
+-	tristate "Digi Intl. RightSwitch SE-X support"
+-	depends on NET_PCI && (PCI || EISA)
+-	---help---
+-	  This is support for the Digi International RightSwitch series of
+-	  PCI/EISA Ethernet switch cards. These include the SE-4 and the SE-6
+-	  models.  If you have a network card of this type, say Y and read the
+-	  Ethernet-HOWTO, available from
+-	  <http://www.tldp.org/docs.html#howto>.  More specific
+-	  information is contained in <file:Documentation/networking/dgrs.txt>.
+-
+-	  To compile this driver as a module, choose M here and read
+-	  <file:Documentation/networking/net-modules.txt>.  The module
+-	  will be called dgrs.
+-
+ config EEPRO100
+ 	tristate "EtherExpressPro/100 support (eepro100, original Becker driver)"
+ 	depends on NET_PCI && PCI
+@@ -1877,33 +1862,6 @@
+ menu "Ethernet (1000 Mbit)"
+ 	depends on NETDEVICES
+ 
+-config ACENIC
+-	tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
+-	depends on PCI
+-	---help---
+-	  Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
+-	  GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
+-	  adapter. The driver allows for using the Jumbo Frame option (9000
+-	  bytes/frame) however it requires that your switches can handle this
+-	  as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
+-	  line.
+-
+-	  To compile this driver as a module, choose M here: the
+-	  module will be called acenic.
+-
+-config ACENIC_OMIT_TIGON_I
+-	bool "Omit support for old Tigon I based AceNICs"
+-	depends on ACENIC
+-	help
+-	  Say Y here if you only have Tigon II based AceNICs and want to leave
+-	  out support for the older Tigon I based cards which are no longer
+-	  being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
+-	  version)).  This will reduce the size of the driver object by
+-	  app. 100KB.  If you are not sure whether your card is a Tigon I or a
+-	  Tigon II, say N here.
+-
+-	  The safe and default value for this is N.
+-
+ config DL2K
+ 	tristate "D-Link DL2000-based Gigabit Ethernet support"
+ 	depends on PCI
+--- kernel-source-2.6.7-2.6.7/arch/i386/defconfig	2004-06-21 14:41:04.955084080 +0200
++++ kernel-source-2.6.7-2.6.7/arch/i386/defconfig.pruned	2004-06-21 14:47:18.767076968 +0200
+@@ -1055,8 +1055,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/sparc64/defconfig	2004-06-21 14:41:04.992082099 +0200
++++ kernel-source-2.6.7-2.6.7/arch/sparc64/defconfig.pruned	2004-06-21 14:47:21.073953542 +0200
+@@ -1668,8 +1668,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-CONFIG_USB_EMI62=m
+-CONFIG_USB_EMI26=m
+ # CONFIG_USB_TIGL is not set
+ CONFIG_USB_AUERSWALD=m
+ CONFIG_USB_RIO500=m
+--- kernel-source-2.6.7-2.6.7/arch/ppc/configs/common_defconfig	2004-06-16 07:19:03.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc/configs/common_defconfig.pruned	2004-06-21 14:47:22.053901111 +0200
+@@ -1138,8 +1138,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ppc/configs/sandpoint_defconfig	2004-06-16 07:19:22.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc/configs/sandpoint_defconfig.pruned	2004-06-21 14:47:22.672867994 +0200
+@@ -601,8 +601,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ppc/configs/lopec_defconfig	2004-06-16 07:19:37.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc/configs/lopec_defconfig.pruned	2004-06-21 14:47:23.263836374 +0200
+@@ -682,8 +682,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ppc/configs/pmac_defconfig	2004-06-16 07:20:03.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc/configs/pmac_defconfig.pruned	2004-06-21 14:47:23.837805665 +0200
+@@ -1170,8 +1170,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ppc/defconfig	2004-06-21 14:41:04.976082956 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc/defconfig.pruned	2004-06-21 14:47:24.352778112 +0200
+@@ -1141,8 +1141,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/mips/configs/rm200_defconfig	2004-06-16 07:19:03.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/mips/configs/rm200_defconfig.pruned	2004-06-21 14:47:24.842751896 +0200
+@@ -1007,8 +1007,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ CONFIG_USB_TIGL=m
+ CONFIG_USB_AUERSWALD=m
+ CONFIG_USB_RIO500=m
+--- kernel-source-2.6.7-2.6.7/arch/ia64/configs/zx1_defconfig	2004-06-16 07:19:37.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ia64/configs/zx1_defconfig.pruned	2004-06-21 14:47:25.322726216 +0200
+@@ -1022,8 +1022,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ia64/defconfig	2004-06-21 14:41:04.966083491 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ia64/defconfig.pruned	2004-06-21 14:47:25.802700535 +0200
+@@ -892,8 +892,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ppc64/configs/g5_defconfig	2004-06-16 07:18:56.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc64/configs/g5_defconfig.pruned	2004-06-21 14:47:26.301673838 +0200
+@@ -951,8 +951,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ppc64/configs/pSeries_defconfig	2004-06-16 07:20:03.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc64/configs/pSeries_defconfig.pruned	2004-06-21 14:47:26.805646874 +0200
+@@ -874,8 +874,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/ppc64/defconfig	2004-06-21 14:41:04.983082581 +0200
++++ kernel-source-2.6.7-2.6.7/arch/ppc64/defconfig.pruned	2004-06-21 14:47:27.271621943 +0200
+@@ -874,8 +874,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/arm/configs/lpd7a404_defconfig	2004-06-16 07:18:57.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/arm/configs/lpd7a404_defconfig.pruned	2004-06-21 14:47:27.781594657 +0200
+@@ -817,8 +817,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/parisc/configs/c3000_defconfig	2004-06-16 07:19:36.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/arch/parisc/configs/c3000_defconfig.pruned	2004-06-21 14:47:28.271568442 +0200
+@@ -874,8 +874,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/parisc/defconfig	2004-06-21 14:41:04.968083384 +0200
++++ kernel-source-2.6.7-2.6.7/arch/parisc/defconfig.pruned	2004-06-21 14:47:28.753542654 +0200
+@@ -731,8 +731,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/arch/x86_64/defconfig	2004-06-21 14:41:04.993082046 +0200
++++ kernel-source-2.6.7-2.6.7/arch/x86_64/defconfig.pruned	2004-06-21 14:47:29.261515476 +0200
+@@ -769,8 +769,6 @@
+ #
+ # USB Miscellaneous drivers
+ #
+-# CONFIG_USB_EMI62 is not set
+-# CONFIG_USB_EMI26 is not set
+ # CONFIG_USB_TIGL is not set
+ # CONFIG_USB_AUERSWALD is not set
+ # CONFIG_USB_RIO500 is not set
+--- kernel-source-2.6.7-2.6.7/drivers/usb/misc/Kconfig~	2004-06-16 07:20:04.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/drivers/usb/misc/Kconfig	2004-06-21 14:42:39.229036608 +0200
+@@ -4,34 +4,6 @@
+ comment "USB Miscellaneous drivers"
+ 	depends on USB
+ 
+-config USB_EMI62
+-	tristate "EMI 6|2m USB Audio interface support"
+-	depends on USB
+-	---help---
+-	  This driver loads firmware to Emagic EMI 6|2m low latency USB
+-	  Audio and Midi interface.
+-
+-	  After firmware load the device is handled with standard linux
+-	  USB Audio driver.
+-
+-	  This code is also available as a module ( = code which can be
+-	  inserted in and removed from the running kernel whenever you want).
+-	  The module will be called audio. If you want to compile it as a
+-	  module, say M here and read <file:Documentation/kbuild/modules.txt>.
+-
+-config USB_EMI26
+-	tristate "EMI 2|6 USB Audio interface support"
+-	depends on USB
+-	---help---
+-	  This driver loads firmware to Emagic EMI 2|6 low latency USB
+-	  Audio interface.
+-
+-	  After firmware load the device is handled with standard linux
+-	  USB Audio driver.
+-
+-	  To compile this driver as a module, choose M here: the
+-	  module will be called emi26.
+-
+ config USB_TIGL
+ 	tristate "Texas Instruments Graph Link USB (aka SilverLink) cable support"
+ 	depends on USB
+--- kernel-source-2.6.7-2.6.7/drivers/usb/misc/Makefile	2004-06-16 07:19:35.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/drivers/usb/misc/Makefile.pruned	2004-06-21 14:47:29.790487173 +0200
+@@ -5,8 +5,6 @@
+ 
+ obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
+ obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
+-obj-$(CONFIG_USB_EMI26)		+= emi26.o
+-obj-$(CONFIG_USB_EMI62)		+= emi62.o
+ obj-$(CONFIG_USB_LCD)		+= usblcd.o
+ obj-$(CONFIG_USB_LED)		+= usbled.o
+ obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
+--- kernel-source-2.6.7-2.6.7/drivers/usb/Makefile	2004-06-16 07:20:04.000000000 +0200
++++ kernel-source-2.6.7-2.6.7/drivers/usb/Makefile.pruned	2004-06-21 14:47:30.625442500 +0200
+@@ -56,8 +56,6 @@
+ 
+ obj-$(CONFIG_USB_AUERSWALD)	+= misc/
+ obj-$(CONFIG_USB_CYTHERM)	+= misc/
+-obj-$(CONFIG_USB_EMI26)		+= misc/
+-obj-$(CONFIG_USB_EMI62)		+= misc/
+ obj-$(CONFIG_USB_LCD)		+= misc/
+ obj-$(CONFIG_USB_LED)		+= misc/
+ obj-$(CONFIG_USB_LEGOTOWER)	+= misc/

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/s390-sacf-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/s390-sacf-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/s390-sacf-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,63 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: s390: sacf local root exploit (CAN-2004-0887)
+## DP: Patch author: Martin Schwidefsky <schwidefsky at de.ibm.com>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/10/25 18:09:17-07:00 schwidefsky at de.ibm.com 
+#   [PATCH] s390: sacf local root exploit (CAN-2004-0887)
+#   
+#   s390 core changes:
+#    - Force user process back to home space mode in space switch event
+#      exception handler.
+#   
+#   Signed-off-by: Martin Schwidefsky <schwidefsky at de.ibm.com>
+#   Signed-off-by: Andrew Morton <akpm at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# arch/s390/kernel/traps.c
+#   2004/10/25 13:18:42-07:00 schwidefsky at de.ibm.com +16 -1
+#   s390: sacf local root exploit (CAN-2004-0887)
+# 
+diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
+--- a/arch/s390/kernel/traps.c	2004-11-24 21:33:06 -08:00
++++ b/arch/s390/kernel/traps.c	2004-11-24 21:33:06 -08:00
+@@ -630,6 +630,21 @@
+ 	}
+ }
+ 
++asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code)
++{
++        siginfo_t info;
++
++	/* Set user psw back to home space mode. */
++	if (regs->psw.mask & PSW_MASK_PSTATE)
++		regs->psw.mask |= PSW_ASC_HOME;
++	/* Send SIGILL. */
++        info.si_signo = SIGILL;
++        info.si_errno = 0;
++        info.si_code = ILL_PRVOPC;
++        info.si_addr = get_check_address(regs);
++        do_trap(int_code, SIGILL, "space switch event", regs, &info);
++}
++
+ asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
+ {
+ 	die("Kernel stack overflow", regs, 0);
+@@ -673,7 +688,7 @@
+         pgm_check_table[0x3B] = &do_dat_exception;
+ #endif /* CONFIG_ARCH_S390X */
+         pgm_check_table[0x15] = &operand_exception;
+-        pgm_check_table[0x1C] = &privileged_op;
++        pgm_check_table[0x1C] = &space_switch_exception;
+         pgm_check_table[0x1D] = &hfp_sqrt_exception;
+ 	pgm_check_table[0x40] = &do_monitor_call;
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/scsi-blacklist.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/scsi-blacklist.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/scsi-blacklist.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,88 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: update scsi blacklist for USB multi card readers
+## DP: Patch author: unknown (from Fedora)
+## DP: Upstream status: submitted
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urNp linux-1100/drivers/scsi/scsi_devinfo.c linux-10000/drivers/scsi/scsi_devinfo.c
+--- linux-1100/drivers/scsi/scsi_devinfo.c
++++ linux-10000/drivers/scsi/scsi_devinfo.c
+@@ -118,10 +118,7 @@ static struct {
+ 	 */
+ 	{"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN},
+ 	{"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN},
+-	{"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
+-	{"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_FORCELUN},
+ 	{"CANON", "IPUBJD", NULL, BLIST_SPARSELUN},
+-	{"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN},
+ 	{"CMD", "CRA-7280", NULL, BLIST_SPARSELUN},	/* CMD RAID Controller */
+ 	{"CNSI", "G7324", NULL, BLIST_SPARSELUN},	/* Chaparral G7324 RAID */
+ 	{"CNSi", "G8324", NULL, BLIST_SPARSELUN},	/* Chaparral G8324 RAID */
+@@ -142,9 +139,6 @@ static struct {
+ 	{"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
+ 	{"EMULEX", "MD21/S2     ESDI", NULL, BLIST_SINGLELUN},
+ 	{"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+-	{"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN},
+-	{"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN},
+-	{"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN},
+ 	{"HITACHI", "DF400", "*", BLIST_SPARSELUN},
+ 	{"HITACHI", "DF500", "*", BLIST_SPARSELUN},
+ 	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
+@@ -164,7 +158,6 @@ static struct {
+ 	{"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+ 	{"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+-	{"Medion", "Flash XL  MMC/SD", "2.6D", BLIST_FORCELUN},
+ 	{"MegaRAID", "LD", NULL, BLIST_FORCELUN},
+ 	{"MICROP", "4110", NULL, BLIST_NOTQ},
+ 	{"MYLEX", "DACARMRB", "*", BLIST_REPORTLUN2},
+@@ -178,11 +171,9 @@ static struct {
+ 	{"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ 	{"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
+-	{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
+ 	{"SGI", "RAID3", "*", BLIST_SPARSELUN},
+ 	{"SGI", "RAID5", "*", BLIST_SPARSELUN},
+ 	{"SGI", "TP9100", "*", BLIST_REPORTLUN2},
+-	{"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN},
+ 	{"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
+ 	{"SONY", "TSL", NULL, BLIST_FORCELUN},		/* DDS3 & DDS4 autoloaders */
+ 	{"SUN", "T300", "*", BLIST_SPARSELUN},
+@@ -190,11 +181,31 @@ static struct {
+ 	{"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},
+ 	{"TOSHIBA", "CDROM", NULL, BLIST_ISROM},
+ 	{"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM},
+-	{"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN},
+ 	{"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+ 	{"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN},
+ 	{"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN},
+ 	{ NULL, NULL, NULL, 0 },
++
++	/*
++	 * USB multi card readers. Only these should use BLIST_FORCELUN.
++	 */
++	{"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
++	{"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_FORCELUN},
++	{"CBOX3", "USB Storage-SMC", "300A", BLIST_FORCELUN},
++	{"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN},
++	{"Generic", "USB Storage-SMC", "0090", BLIST_FORCELUN},
++	{"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN},
++	{"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN},
++	{"ICSI", "SD Card", "2.7C", BLIST_FORCELUN},
++	{"IOI", "Media Bay", "*", BLIST_FORCELUN},
++	{"Lexar", "Media Inc. SM/xD", "009E", BLIST_FORCELUN},
++	{"Medion", "Flash XL  MMC/SD", "2.6D", BLIST_FORCELUN},
++	{"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
++	{"SMSC", "223 U HS-CF", "1.95", BLIST_FORCELUN},
++	{"SMSC", "USB 2 HS-CF", NULL, BLIST_FORCELUN},
++	{"TwinMOS", "7-in-1 Card RWCF", "0100", BLIST_FORCELUN},
++	{"USB2.0", "SMARTMEDIA/XD", NULL, BLIST_FORCELUN},
++	{"Y-E DATA", "CF Card Reader", "1.03", BLIST_FORCELUN},
+ };
+ 
+ /*

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-1
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-1	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-1	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,56 @@
++ doc-post_halloween.dpatch
++ drivers-ide-dma-blacklist-toshiba.dpatch
++ drivers-input-psaux-hacks.dpatch
++ drivers-net-8139too-locking.dpatch
+X drivers/net/acenic_firmware.h
+X drivers/net/dgrs_firmware.c
+X drivers/net/tg3.c
+X drivers/net/tokenring/smctr_firmware.h
+X drivers/scsi/qla2xxx/ql2100_fw.c
+X drivers/scsi/qla2xxx/ql2200_fw.c
+X drivers/scsi/qla2xxx/ql2300_fw.c
+X drivers/scsi/qla2xxx/ql2322_fw.c
+X drivers/scsi/qla2xxx/ql6312_fw.c
+X drivers/scsi/qla2xxx/ql6322_fw.c
+X drivers/usb/media/dabfirmware.h
+X drivers/usb/misc/emi62_fw_m.h
+X drivers/usb/misc/emi62_fw_s.h
+X drivers/usb/serial/keyspan_mpr_fw.h
+X drivers/usb/serial/keyspan_usa18x_fw.h
+X drivers/usb/serial/keyspan_usa19_fw.h
+X drivers/usb/serial/keyspan_usa19qi_fw.h
+X drivers/usb/serial/keyspan_usa19qw_fw.h
+X drivers/usb/serial/keyspan_usa19w_fw.h
+X drivers/usb/serial/keyspan_usa28_fw.h
+X drivers/usb/serial/keyspan_usa28x_fw.h
+X drivers/usb/serial/keyspan_usa28xa_fw.h
+X drivers/usb/serial/keyspan_usa28xb_fw.h
+X drivers/usb/serial/keyspan_usa49w_fw.h
+X drivers/usb/serial/keyspan_usa49wlc_fw.h
++ drivers-net-tg3-readd.dpatch
++ drivers-scsi_changer.dpatch
++ drivers-scsi-generic_proc_info.dpatch
++ fs-asfs.dpatch
++ ipsec-missing_wakeup.dpatch
++ modular-ide.dpatch
++ modular-ide-pnp.dpatch
++ modular-vesafb.dpatch
++ remove-references-to-removed-drivers.dpatch
++ x86-i486_emu.dpatch
++ powerpc-pegasos.dpatch
++ ia64-generic-no-smp.dpatch
++ marvell-pegasos.dpatch
++ powerpc-g4-l2-flush-errata.dpatch
++ ia64-generic-no-smp-1-to-2.dpatch
++ ia64_cyclone_nosmp.dpatch
++ scsi-blacklist.dpatch
++ aic79xx-nohw.dpatch
++ ata_piix-combinde-mode-fix.dpatch
++ tg3-update.dpatch
++ alsa-module-load-fix.dpatch
++ sparc64-hme-lockup.dpatch
++ ia64-mem-max_addr-cmdline-fix.dpatch
++ ppc64-iSeries-build-fix.dpatch
++ drivers-video-fm2fb-build-fix.dpatch
++ fs-ext3-directio-leak-fix.dpatch
++ smbfs-overrun.dpatch

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-2
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-2	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-2	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,14 @@
++ drivers-pci-quirks-via8233a.dpatch
++ parport_pc-via8231.dpatch
++ ia64-hp-sba_iommu-fix.dpatch
++ drivers-serial-sn_console-up-buildfix.dpatch
++ SG_IO-safe-commands-1.dpatch
++ alpha-writeq-fix.dpatch
++ mm-vmscan.dpatch
++ drivers-usb-storage-transport-1.dpatch
++ drivers-usb-storage-transport-2.dpatch
++ ia64-sn-move-irq-noop.dpatch
++ mm-shmem-nomount-fix.dpatch
++ elf-loader-fixes.dpatch
++ sparc-cg14-init.dpatch
++ sparc-sunzilog-timeout.dpatch

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-3
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-3	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/series/2.6.9-3	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,15 @@
++ dm_io-ENOMEM-goof.dpatch
++ elf-loader-fixes-the-return.dpatch
++ aout-loader-fixes.dpatch
++ s390-sacf-fix.dpatch
+- smbfs-overrun.dpatch
++ smbfs-overflow-fixes.dpatch
++ tty-locking-fixes9.dpatch
++ drivers-serial-8250-ioremap-fix.dpatch
+- ata_piix-combinde-mode-fix.dpatch
++ ata_piix-combinde-mode-fix-2.dpatch
++ vlan-update-1.dpatch
++ drivers-ide-dma-ricoh.dpatch
++ fs-tmpfs-free_inode-leak.dpatch
++ sparc32-initrd-memcpy.dpatch
++ sparc64-sunsab-break-fix.dpatch

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overflow-fixes.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overflow-fixes.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overflow-fixes.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,104 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: SMBfs overflow fixes
+## DP: Patch author: unknown, stolen from -ac tree (probably Stefan Esser,  Juan Quintela, and Urban Widmark)
+## DP: Upstream status: unknown
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.9/fs/smbfs/proc.c linux-2.6.9/fs/smbfs/proc.c
+--- linux.vanilla-2.6.9/fs/smbfs/proc.c	2004-10-20 23:17:20.000000000 +0100
++++ linux-2.6.9/fs/smbfs/proc.c	2004-11-17 19:41:41.000000000 +0000
+@@ -1427,9 +1427,9 @@
+ 	 * So we must first calculate the amount of padding used by the server.
+ 	 */
+ 	data_off -= hdrlen;
+-	if (data_off > SMB_READX_MAX_PAD) {
+-		PARANOIA("offset is larger than max pad!\n");
+-		PARANOIA("%d > %d\n", data_off, SMB_READX_MAX_PAD);
++	if (data_off > SMB_READX_MAX_PAD || data_off < 0) {
++		PARANOIA("offset is larger than SMB_READX_MAX_PAD or negative!\n");
++		PARANOIA("%d > %d || %d < 0\n", data_off, SMB_READX_MAX_PAD, data_off);
+ 		req->rq_rlen = req->rq_bufsize + 1;
+ 		return;
+ 	}
+diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.9/fs/smbfs/request.c linux-2.6.9/fs/smbfs/request.c
+--- linux.vanilla-2.6.9/fs/smbfs/request.c	2004-10-20 22:33:50.000000000 +0100
++++ linux-2.6.9/fs/smbfs/request.c	2004-11-17 19:41:41.000000000 +0000
+@@ -588,6 +588,10 @@
+ 	data_count  = WVAL(inbuf, smb_drcnt);
+ 
+ 	/* Modify offset for the split header/buffer we use */
++	if (data_offset < hdrlen)
++		goto out_bad_data;
++	if (parm_offset < hdrlen)
++		goto out_bad_parm;
+ 	data_offset -= hdrlen;
+ 	parm_offset -= hdrlen;
+ 
+@@ -607,6 +611,10 @@
+ 		req->rq_lparm = parm_count;
+ 		req->rq_data = req->rq_buffer + data_offset;
+ 		req->rq_parm = req->rq_buffer + parm_offset;
++		if (parm_offset + parm_count > req->rq_rlen)
++			goto out_bad_parm;
++		if (data_offset + data_count > req->rq_rlen)
++			goto out_bad_data;
+ 		return 0;
+ 	}
+ 
+@@ -634,6 +642,7 @@
+ 		req->rq_trans2buffer = smb_kmalloc(buf_len, GFP_NOFS);
+ 		if (!req->rq_trans2buffer)
+ 			goto out_no_mem;
++		memset(req->rq_trans2buffer, 0, buf_len);
+ 
+ 		req->rq_parm = req->rq_trans2buffer;
+ 		req->rq_data = req->rq_trans2buffer + parm_tot;
+@@ -643,8 +652,12 @@
+ 
+ 	if (parm_disp + parm_count > req->rq_total_parm)
+ 		goto out_bad_parm;
++	if (parm_offset + parm_count > req->rq_rlen)
++		goto out_bad_parm;
+ 	if (data_disp + data_count > req->rq_total_data)
+ 		goto out_bad_data;
++	if (data_offset + data_count > req->rq_rlen)
++		goto out_bad_data;
+ 
+ 	inbuf = req->rq_buffer;
+ 	memcpy(req->rq_parm + parm_disp, inbuf + parm_offset, parm_count);
+@@ -657,8 +670,11 @@
+ 	 * Check whether we've received all of the data. Note that
+ 	 * we use the packet totals -- total lengths might shrink!
+ 	 */
+-	if (req->rq_ldata >= data_tot && req->rq_lparm >= parm_tot)
++	if (req->rq_ldata >= data_tot && req->rq_lparm >= parm_tot) {
++		req->rq_ldata = data_tot;
++		req->rq_lparm = parm_tot;
+ 		return 0;
++	}
+ 	return 1;
+ 
+ out_too_long:
+@@ -676,13 +692,13 @@
+ 	req->rq_errno = -EIO;
+ 	goto out;
+ out_bad_parm:
+-	printk(KERN_ERR "smb_trans2: invalid parms, disp=%d, cnt=%d, tot=%d\n",
+-	       parm_disp, parm_count, parm_tot);
++	printk(KERN_ERR "smb_trans2: invalid parms, disp=%d, cnt=%d, tot=%d, ofs=%d\n",
++	       parm_disp, parm_count, parm_tot, parm_offset);
+ 	req->rq_errno = -EIO;
+ 	goto out;
+ out_bad_data:
+-	printk(KERN_ERR "smb_trans2: invalid data, disp=%d, cnt=%d, tot=%d\n",
+-	       data_disp, data_count, data_tot);
++	printk(KERN_ERR "smb_trans2: invalid data, disp=%d, cnt=%d, tot=%d, ofs=%d\n",
++	       data_disp, data_count, data_tot, data_offset);
+ 	req->rq_errno = -EIO;
+ out:
+ 	return req->rq_errno;

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overrun.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overrun.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/smbfs-overrun.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,62 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: fix smbfs overrun/leak
+## DP: Patch author: Urban.Widmark at enlight.net
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/10/21 10:58:29-07:00 s.esser at e-matters.de 
+#   [PATCH] smbfs protocol fixes
+#   
+#   From: <Urban.Widmark at enlight.net>
+#   
+#   The memset is because it was previously possible to send always the same CIFS
+#   fragment and use this to increase the data counters.  When the data counter
+#   "exceeds" the amount of bytes expected this will return the buffer only
+#   partially initialised...  With findfirst etc requests this should allow
+#   leaking kernel memory content.
+#   
+#   The other thing is that the data is only returned when data_tot and parm_tot
+#   both "exceed" the expected values.  Previously it was possible to create a
+#   sequence of CIFS fragments that allowed exceeding the counters.  The calling
+#   functions then would believe they received a number of bytes that does not fit
+#   into the allocated buffer.
+#   
+#   Signed-off-by: Andrew Morton <akpm at osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds at osdl.org>
+# 
+# fs/smbfs/request.c
+#   2004/10/21 01:39:27-07:00 s.esser at e-matters.de +5 -1
+#   smbfs protocol fixes
+# 
+diff -Nru a/fs/smbfs/request.c b/fs/smbfs/request.c
+--- a/fs/smbfs/request.c	2004-10-27 21:08:34 -07:00
++++ b/fs/smbfs/request.c	2004-10-27 21:08:34 -07:00
+@@ -634,6 +634,7 @@
+ 		req->rq_trans2buffer = smb_kmalloc(buf_len, GFP_NOFS);
+ 		if (!req->rq_trans2buffer)
+ 			goto out_no_mem;
++		memset(req->rq_trans2buffer, 0, buf_len);
+ 
+ 		req->rq_parm = req->rq_trans2buffer;
+ 		req->rq_data = req->rq_trans2buffer + parm_tot;
+@@ -657,8 +658,11 @@
+ 	 * Check whether we've received all of the data. Note that
+ 	 * we use the packet totals -- total lengths might shrink!
+ 	 */
+-	if (req->rq_ldata >= data_tot && req->rq_lparm >= parm_tot)
++	if (req->rq_ldata >= data_tot && req->rq_lparm >= parm_tot) {
++		req->rq_ldata = data_tot;
++		req->rq_lparm = parm_tot;
+ 		return 0;
++	}
+ 	return 1;
+ 
+ out_too_long:

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-cg14-init.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-cg14-init.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-cg14-init.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,104 @@
+# origin: Debian (joshk) -> LKML (bbreuer)
+# cset: n/a
+# inclusion: davem knows about it
+# revision date: 2004-11-14 
+
+NOTE: had to be adapted from the diff sent to linux-sparc, which was broken 
+in ways previously unknown to man
+
+--- kernel-source-2.6.8-2.6.8/drivers/video/cg14.c~	2004-11-14 18:39:29.000000000 -0800
++++ kernel-source-2.6.8-2.6.8/drivers/video/cg14.c	2004-11-14 18:45:32.000000000 -0800
+@@ -255,6 +255,10 @@
+ 	if (regno >= 256)
+ 		return 1;
+ 
++	red >>= 8;
++	green >>= 8;
++	blue >>= 8;
++
+ 	val = (red | (green << 8) | (blue << 16));
+ 
+ 	spin_lock_irqsave(&par->lock, flags);
+@@ -322,7 +326,7 @@
+ 			break;
+ 
+ 		case MDI_16_PIX:
+-			cur_mode |= 0x20;
++			cur_mode |= (CG14_MCR_PIXMODE_16 << CG14_MCR_PIXMODE_SHIFT);;
+ 			break;
+ 
+ 		case MDI_8_PIX:
+@@ -331,7 +335,7 @@
+ 		default:
+ 			ret = -ENOSYS;
+ 			break;
+-		};
++		}
+ 		if (!ret) {
+ 			sbus_writeb(cur_mode, &regs->mcr);
+ 			par->mode = mode;
+@@ -341,9 +345,9 @@
+ 
+ 	default:
+ 		ret = sbusfb_ioctl_helper(cmd, arg, info,
+-					  FBTYPE_MDICOLOR, 24, par->fbsize);
++					  FBTYPE_MDICOLOR, 8, par->fbsize);
+ 		break;
+-	};
++	}
+ 
+ 	return ret;
+ }
+@@ -355,11 +359,17 @@
+ static void cg14_init_fix(struct fb_info *info, int linebytes)
+ {
+ 	struct cg14_par *par = (struct cg14_par *)info->par;
+-
+-	strlcpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id));
++	const char *name;
++	
++	name = "cgfourteen";
++
++	if (par->sdev)
++		name = par->sdev->prom_name;
++	
++	strlcpy(info->fix.id, name, sizeof(info->fix.id));
+ 
+ 	info->fix.type = FB_TYPE_PACKED_PIXELS;
+-	info->fix.visual = FB_VISUAL_TRUECOLOR;
++	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ 
+ 	info->fix.line_length = linebytes;
+ 
+@@ -484,8 +494,11 @@
+ 	spin_lock_init(&all->par.lock);
+ 
+ 	sbusfb_fill_var(&all->info.var, node, 8);
++	all->info.var.red.length = 8;
++	all->info.var.green.length = 8;
++	all->info.var.blue.length = 8;
+ 
+-	linebytes = prom_getintdefault(sdev->prom_node, "linebytes",
++	linebytes = prom_getintdefault(node, "linebytes",
+ 				       all->info.var.xres);
+ 	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+ 
+@@ -562,6 +575,7 @@
+ 		kfree(all);
+ 		return;
+ 	}
++	fb_set_cmap(&all->info.cmap, &all->info);
+ 
+ 	cg14_init_fix(&all->info, linebytes);
+ 
+@@ -574,8 +588,8 @@
+ 
+ 	list_add(&all->list, &cg14_list);
+ 
+-	printk("cg14: cgfourteen at %lx:%lx\n",
+-	       all->par.physbase, all->par.iospace);
++	printk("cg14: cgfourteen at %lx:%lx, %dMB\n",
++	       all->par.iospace, all->par.physbase, all->par.ramsize >> 20);
+ 
+ }
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-sunzilog-timeout.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-sunzilog-timeout.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc-sunzilog-timeout.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,23 @@
+# origin: benh
+# cset: n/a
+# inclusion: pushed to davem
+# revision date: 2004-11-11
+
+I found recently a bug in pmac_zilog, which originates from sunzilog who so might
+have the same problem. The "timeout" member of the port structure was never
+initialized, causing very long pauses to happen on port close, that is pretty much
+all the time when hitting userland.
+
+Quick untested patch (I don't have a sparc)
+
+===== drivers/serial/sunzilog.c 1.46 vs edited =====
+--- 1.46/drivers/serial/sunzilog.c	2004-09-21 06:46:03 +10:00
++++ edited/drivers/serial/sunzilog.c	2004-11-07 10:05:37 +11:00
+@@ -974,6 +974,8 @@
+
+ 	sunzilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+
++	uart_update_timeout(port, termios->c_cflag, baud);
++
+ 	spin_unlock_irqrestore(&up->port.lock, flags);
+ }

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc32-initrd-memcpy.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc32-initrd-memcpy.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc32-initrd-memcpy.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,27 @@
+# origin: Debian (jurij)
+# cset: n/a
+# inclusion: approved by davem (projected: 2.4.28)
+# revision date: 2004-11-15
+
+--- build-sparc32.orig/include/asm-sparc/string.h	2004-08-14 01:36:11.000000000 -0400
++++ build-sparc32/include/asm-sparc/string.h	2004-11-14 22:09:49.000000000 -0500
+@@ -40,6 +40,9 @@
+ 
+ 	if(n <= 32) {
+ 		__builtin_memcpy(to, from, n);
++	} else if (((unsigned int) to & 7) != 0) {
++		/* Destination is not aligned on the double-word boundary */
++		__memcpy(to, from, n);
+ 	} else {
+ 		switch(n) {
+ 		case PAGE_SIZE:
+--- build-sparc32.orig/arch/sparc/mm/iommu.c	2004-08-14 01:38:08.000000000 -0400
++++ build-sparc32/arch/sparc/mm/iommu.c	2004-11-14 22:10:09.000000000 -0500
+@@ -173,6 +173,7 @@
+ 	}
+ 
+ 	iommu_viking_flush_iotlb(iopte0, npages);
++	flush_cache_all();
+ 
+ 	return busa0;
+ }

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-hme-lockup.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-hme-lockup.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-hme-lockup.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,20 @@
+# origin: Debian (bcollins)
+# cset: n/a
+# inclusion: not suitable for upstream
+# revision date: 2004-10-08
+
+Seemingly only on the onboard hme's on the Ultra 1E (enterprise) models
+(as the non-E models have an onboard le)... it's a strange lockup problem
+that requires a reboot to fix.  This one-liner is a band-aid that seems
+to take care of it... a possible weirdo timing bug. --Uzi
+
+--- linux/drivers/net/sunhme.c.orig	Mon Jul 15 02:38:27 2002
++++ linux/drivers/net/sunhme.c	Mon Jul 15 03:09:03 2002
+@@ -1983,6 +1983,7 @@
+ 	}
+ 	hp->tx_old = elem;
+ 	TXD((">"));
++	udelay(1);
+ 
+ 	if (netif_queue_stopped(dev) &&
+ 	    TX_BUFFS_AVAIL(hp) > (MAX_SKB_FRAGS + 1))

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-sunsab-break-fix.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-sunsab-break-fix.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/sparc64-sunsab-break-fix.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,52 @@
+# origin: Debian (jurij)
+# cset: n/a
+# inclusion: submitted
+# revision date: 2004-11-21
+
+--- build-sparc64.orig/drivers/serial/sunsab.c	2004-11-21 12:03:51.282281488 -0500
++++ build-sparc64/drivers/serial/sunsab.c	2004-11-21 11:49:04.000000000 -0500
+@@ -143,6 +143,11 @@
+ 		writeb(SAB82532_CMDR_RMC, &up->regs->w.cmdr);
+ 	}
+ 
++	/* Count may be zero for BRK, so we check for it here */
++	if((stat->sreg.isr1 & SAB82532_ISR1_BRK) &&
++	   (up->port.line == up->port.cons->index))
++		saw_console_brk = 1;
++
+ 	for (i = 0; i < count; i++) {
+ 		unsigned char ch = buf[i];
+ 
+@@ -172,8 +177,6 @@
+ 				stat->sreg.isr0 &= ~(SAB82532_ISR0_PERR |
+ 						     SAB82532_ISR0_FERR);
+ 				up->port.icount.brk++;
+-				if (up->port.line == up->port.cons->index)
+-					saw_console_brk = 1;
+ 				/*
+ 				 * We do the SysRQ and SAK checking
+ 				 * here because otherwise the break
+@@ -325,8 +328,9 @@
+ 
+ 	tty = NULL;
+ 	if (status.stat) {
+-		if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
+-					SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
++		if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
++					SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) ||
++		    (status.sreg.isr1 & SAB82532_ISR1_BRK))
+ 			tty = receive_chars(up, &status, regs);
+ 		if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
+ 		    (status.sreg.isr1 & SAB82532_ISR1_CSC))
+@@ -352,8 +356,9 @@
+ 
+ 	tty = NULL;
+ 	if (status.stat) {
+-		if (status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
+-					SAB82532_ISR0_RFO | SAB82532_ISR0_RPF))
++		if ((status.sreg.isr0 & (SAB82532_ISR0_TCD | SAB82532_ISR0_TIME |
++					SAB82532_ISR0_RFO | SAB82532_ISR0_RPF)) ||
++		    (status.sreg.isr1 & SAB82532_ISR1_BRK))
+ 			tty = receive_chars(up, &status, regs);
+ 		if ((status.sreg.isr0 & SAB82532_ISR0_CDSC) ||
+ 		    (status.sreg.isr1 & (SAB82532_ISR1_BRK | SAB82532_ISR1_CSC)))

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tg3-update.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tg3-update.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tg3-update.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,1467 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Update tg3 driver to upstream BK as of 2004/09/21 (modulo firmware)
+## DP: Patch author: David Miller <davem at redhat.com> (+ addition contributors)
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+--- kernel-source-2.6.8/drivers/net/tg3.c	2004-09-13 05:28:07.000000000 +0200
++++ linux-2.5/drivers/net/tg3.c	2004-09-18 13:46:34.949986280 +0200
+@@ -60,8 +60,8 @@
+ 
+ #define DRV_MODULE_NAME		"tg3"
+ #define PFX DRV_MODULE_NAME	": "
+-#define DRV_MODULE_VERSION	"3.8"
+-#define DRV_MODULE_RELDATE	"July 14, 2004"
++#define DRV_MODULE_VERSION	"3.10"
++#define DRV_MODULE_RELDATE	"September 14, 2004"
+ 
+ #define TG3_DEF_MAC_MODE	0
+ #define TG3_DEF_RX_MODE		0
+@@ -445,9 +445,14 @@
+ 		       0x1f);
+ 	tp->pci_clock_ctrl = clock_ctrl;
+ 
+-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
+-	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
++	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
++	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
++		if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
++			tw32_f(TG3PCI_CLOCK_CTRL,
++			       clock_ctrl | CLOCK_CTRL_625_CORE);
++			udelay(40);
++		}
++	} else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
+ 		tw32_f(TG3PCI_CLOCK_CTRL,
+ 		     clock_ctrl |
+ 		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
+@@ -983,7 +988,7 @@
+ 		tp->link_config.orig_autoneg = tp->link_config.autoneg;
+ 	}
+ 
+-	if (tp->phy_id != PHY_ID_SERDES) {
++	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ 		tp->link_config.speed = SPEED_10;
+ 		tp->link_config.duplex = DUPLEX_HALF;
+ 		tp->link_config.autoneg = AUTONEG_ENABLE;
+@@ -995,7 +1000,7 @@
+ 	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
+ 		u32 mac_mode;
+ 
+-		if (tp->phy_id != PHY_ID_SERDES) {
++		if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ 			tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
+ 			udelay(40);
+ 
+@@ -1117,29 +1122,33 @@
+ 	u32 old_rx_mode = tp->rx_mode;
+ 	u32 old_tx_mode = tp->tx_mode;
+ 
+-	if (local_adv & ADVERTISE_PAUSE_CAP) {
+-		if (local_adv & ADVERTISE_PAUSE_ASYM) {
+-			if (remote_adv & LPA_PAUSE_CAP)
+-				new_tg3_flags |=
+-					(TG3_FLAG_RX_PAUSE |
+-					 TG3_FLAG_TX_PAUSE);
+-			else if (remote_adv & LPA_PAUSE_ASYM)
+-				new_tg3_flags |=
+-					(TG3_FLAG_RX_PAUSE);
+-		} else {
+-			if (remote_adv & LPA_PAUSE_CAP)
+-				new_tg3_flags |=
+-					(TG3_FLAG_RX_PAUSE |
+-					 TG3_FLAG_TX_PAUSE);
++	if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
++		if (local_adv & ADVERTISE_PAUSE_CAP) {
++			if (local_adv & ADVERTISE_PAUSE_ASYM) {
++				if (remote_adv & LPA_PAUSE_CAP)
++					new_tg3_flags |=
++						(TG3_FLAG_RX_PAUSE |
++					 	TG3_FLAG_TX_PAUSE);
++				else if (remote_adv & LPA_PAUSE_ASYM)
++					new_tg3_flags |=
++						(TG3_FLAG_RX_PAUSE);
++			} else {
++				if (remote_adv & LPA_PAUSE_CAP)
++					new_tg3_flags |=
++						(TG3_FLAG_RX_PAUSE |
++					 	TG3_FLAG_TX_PAUSE);
++			}
++		} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
++			if ((remote_adv & LPA_PAUSE_CAP) &&
++		    	(remote_adv & LPA_PAUSE_ASYM))
++				new_tg3_flags |= TG3_FLAG_TX_PAUSE;
+ 		}
+-	} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
+-		if ((remote_adv & LPA_PAUSE_CAP) &&
+-		    (remote_adv & LPA_PAUSE_ASYM))
+-			new_tg3_flags |= TG3_FLAG_TX_PAUSE;
+-	}
+ 
+-	tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
+-	tp->tg3_flags |= new_tg3_flags;
++		tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
++		tp->tg3_flags |= new_tg3_flags;
++	} else {
++		new_tg3_flags = tp->tg3_flags;
++	}
+ 
+ 	if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
+ 		tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
+@@ -1490,6 +1499,18 @@
+ 	current_speed = SPEED_INVALID;
+ 	current_duplex = DUPLEX_INVALID;
+ 
++	if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) {
++		u32 val;
++
++		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007);
++		tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
++		if (!(val & (1 << 10))) {
++			val |= (1 << 10);
++			tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
++			goto relink;
++		}
++	}
++
+ 	bmsr = 0;
+ 	for (i = 0; i < 100; i++) {
+ 		tg3_readphy(tp, MII_BMSR, &bmsr);
+@@ -1569,7 +1590,7 @@
+ 			tg3_setup_flow_control(tp, local_adv, remote_adv);
+ 		}
+ 	}
+-
++relink:
+ 	if (current_link_up == 0) {
+ 		u32 tmp;
+ 
+@@ -1619,7 +1640,7 @@
+ 	tw32_f(MAC_MODE, tp->mac_mode);
+ 	udelay(40);
+ 
+-	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
++	if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
+ 		/* Polled via timer. */
+ 		tw32_f(MAC_EVENT, 0);
+ 	} else {
+@@ -1968,62 +1989,264 @@
+ static int fiber_autoneg(struct tg3 *tp, u32 *flags)
+ {
+ 	int res = 0;
++	struct tg3_fiber_aneginfo aninfo;
++	int status = ANEG_FAILED;
++	unsigned int tick;
++	u32 tmp;
+ 
+-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
+-		u32 dig_status;
++	tw32_f(MAC_TX_AUTO_NEG, 0);
+ 
+-		dig_status = tr32(SG_DIG_STATUS);
+-		*flags = 0;
+-		if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
+-			*flags |= MR_LP_ADV_ASYM_PAUSE;
+-		if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
+-			*flags |= MR_LP_ADV_SYM_PAUSE;
+-
+-		if ((dig_status & SG_DIG_AUTONEG_COMPLETE) &&
+-		    !(dig_status & (SG_DIG_AUTONEG_ERROR |
+-				    SG_DIG_PARTNER_FAULT_MASK)))
+-			res = 1;
+-	} else {
+-		struct tg3_fiber_aneginfo aninfo;
+-		int status = ANEG_FAILED;
+-		unsigned int tick;
+-		u32 tmp;
++	tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
++	tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
++	udelay(40);
+ 
+-		tw32_f(MAC_TX_AUTO_NEG, 0);
++	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
++	udelay(40);
+ 
+-		tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+-		tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
+-		udelay(40);
++	memset(&aninfo, 0, sizeof(aninfo));
++	aninfo.flags |= MR_AN_ENABLE;
++	aninfo.state = ANEG_STATE_UNKNOWN;
++	aninfo.cur_time = 0;
++	tick = 0;
++	while (++tick < 195000) {
++		status = tg3_fiber_aneg_smachine(tp, &aninfo);
++		if (status == ANEG_DONE || status == ANEG_FAILED)
++			break;
+ 
+-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
+-		udelay(40);
++		udelay(1);
++	}
+ 
+-		memset(&aninfo, 0, sizeof(aninfo));
+-		aninfo.flags |= MR_AN_ENABLE;
+-		aninfo.state = ANEG_STATE_UNKNOWN;
+-		aninfo.cur_time = 0;
+-		tick = 0;
+-		while (++tick < 195000) {
+-			status = tg3_fiber_aneg_smachine(tp, &aninfo);
+-			if (status == ANEG_DONE || status == ANEG_FAILED)
+-				break;
++	tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
++	tw32_f(MAC_MODE, tp->mac_mode);
++	udelay(40);
+ 
+-			udelay(1);
++	*flags = aninfo.flags;
++
++	if (status == ANEG_DONE &&
++	    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
++			     MR_LP_ADV_FULL_DUPLEX)))
++		res = 1;
++
++	return res;
++}
++
++static void tg3_init_bcm8002(struct tg3 *tp)
++{
++	u32 mac_status = tr32(MAC_STATUS);
++	int i;
++
++	/* Reset when initting first time or we have a link. */
++	if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) &&
++	    !(mac_status & MAC_STATUS_PCS_SYNCED))
++		return;
++
++	/* Set PLL lock range. */
++	tg3_writephy(tp, 0x16, 0x8007);
++
++	/* SW reset */
++	tg3_writephy(tp, MII_BMCR, BMCR_RESET);
++
++	/* Wait for reset to complete. */
++	/* XXX schedule_timeout() ... */
++	for (i = 0; i < 500; i++)
++		udelay(10);
++
++	/* Config mode; select PMA/Ch 1 regs. */
++	tg3_writephy(tp, 0x10, 0x8411);
++
++	/* Enable auto-lock and comdet, select txclk for tx. */
++	tg3_writephy(tp, 0x11, 0x0a10);
++
++	tg3_writephy(tp, 0x18, 0x00a0);
++	tg3_writephy(tp, 0x16, 0x41ff);
++
++	/* Assert and deassert POR. */
++	tg3_writephy(tp, 0x13, 0x0400);
++	udelay(40);
++	tg3_writephy(tp, 0x13, 0x0000);
++
++	tg3_writephy(tp, 0x11, 0x0a50);
++	udelay(40);
++	tg3_writephy(tp, 0x11, 0x0a10);
++
++	/* Wait for signal to stabilize */
++	/* XXX schedule_timeout() ... */
++	for (i = 0; i < 15000; i++)
++		udelay(10);
++
++	/* Deselect the channel register so we can read the PHYID
++	 * later.
++	 */
++	tg3_writephy(tp, 0x10, 0x8011);
++}
++
++static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
++{
++	u32 sg_dig_ctrl, sg_dig_status;
++	u32 serdes_cfg, expected_sg_dig_ctrl;
++	int workaround, port_a;
++	int current_link_up;
++
++	serdes_cfg = 0;
++	expected_sg_dig_ctrl = 0;
++	workaround = 0;
++	port_a = 1;
++	current_link_up = 0;
++
++	if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
++	    tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
++		workaround = 1;
++		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
++			port_a = 0;
++
++		serdes_cfg = tr32(MAC_SERDES_CFG) &
++			((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20));
++	}
++
++	sg_dig_ctrl = tr32(SG_DIG_CTRL);
++
++	if (tp->link_config.autoneg != AUTONEG_ENABLE) {
++		if (sg_dig_ctrl & (1 << 31)) {
++			if (workaround) {
++				u32 val = serdes_cfg;
++
++				if (port_a)
++					val |= 0xc010880;
++				else
++					val |= 0x4010880;
++				tw32_f(MAC_SERDES_CFG, val);
++			}
++			tw32_f(SG_DIG_CTRL, 0x01388400);
++		}
++		if (mac_status & MAC_STATUS_PCS_SYNCED) {
++			tg3_setup_flow_control(tp, 0, 0);
++			current_link_up = 1;
+ 		}
++		goto out;
++	}
+ 
+-		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
+-		tw32_f(MAC_MODE, tp->mac_mode);
+-		udelay(40);
++	/* Want auto-negotiation.  */
++	expected_sg_dig_ctrl = 0x81388400;
++
++	/* Pause capability */
++	expected_sg_dig_ctrl |= (1 << 11);
++
++	/* Asymettric pause */
++	expected_sg_dig_ctrl |= (1 << 12);
++
++	if (sg_dig_ctrl != expected_sg_dig_ctrl) {
++		if (workaround)
++			tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880);
++		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
++		udelay(5);
++		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
++
++		tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
++	} else if (mac_status & (MAC_STATUS_PCS_SYNCED |
++				 MAC_STATUS_SIGNAL_DET)) {
++		sg_dig_status = tr32(SG_DIG_STATUS);
++
++		if ((sg_dig_status & (1 << 1)) &&
++		    (mac_status & MAC_STATUS_PCS_SYNCED)) {
++			u32 local_adv, remote_adv;
++
++			local_adv = ADVERTISE_PAUSE_CAP;
++			remote_adv = 0;
++			if (sg_dig_status & (1 << 19))
++				remote_adv |= LPA_PAUSE_CAP;
++			if (sg_dig_status & (1 << 20))
++				remote_adv |= LPA_PAUSE_ASYM;
++
++			tg3_setup_flow_control(tp, local_adv, remote_adv);
++			current_link_up = 1;
++			tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
++		} else if (!(sg_dig_status & (1 << 1))) {
++			if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED)
++				tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
++			else {
++				if (workaround) {
++					u32 val = serdes_cfg;
++
++					if (port_a)
++						val |= 0xc010880;
++					else
++						val |= 0x4010880;
++
++					tw32_f(MAC_SERDES_CFG, val);
++				}
+ 
+-		*flags = aninfo.flags;
++				tw32_f(SG_DIG_CTRL, 0x01388400);
++				udelay(40);
+ 
+-		if (status == ANEG_DONE &&
+-		    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
+-				     MR_LP_ADV_FULL_DUPLEX)))
+-			res = 1;
++				mac_status = tr32(MAC_STATUS);
++				if (mac_status & MAC_STATUS_PCS_SYNCED) {
++					tg3_setup_flow_control(tp, 0, 0);
++					current_link_up = 1;
++				}
++			}
++		}
+ 	}
+ 
+-	return res;
++out:
++	return current_link_up;
++}
++
++static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
++{
++	int current_link_up = 0;
++
++ 	if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
++		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
++		goto out;
++	}
++
++	if (tp->link_config.autoneg == AUTONEG_ENABLE) {
++		u32 flags;
++		int i;
++  
++		if (fiber_autoneg(tp, &flags)) {
++			u32 local_adv, remote_adv;
++
++			local_adv = ADVERTISE_PAUSE_CAP;
++			remote_adv = 0;
++			if (flags & MR_LP_ADV_SYM_PAUSE)
++				remote_adv |= LPA_PAUSE_CAP;
++			if (flags & MR_LP_ADV_ASYM_PAUSE)
++				remote_adv |= LPA_PAUSE_ASYM;
++
++			tg3_setup_flow_control(tp, local_adv, remote_adv);
++
++			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
++			current_link_up = 1;
++		}
++		for (i = 0; i < 30; i++) {
++			udelay(20);
++			tw32_f(MAC_STATUS,
++			       (MAC_STATUS_SYNC_CHANGED |
++				MAC_STATUS_CFG_CHANGED));
++			udelay(40);
++			if ((tr32(MAC_STATUS) &
++			     (MAC_STATUS_SYNC_CHANGED |
++			      MAC_STATUS_CFG_CHANGED)) == 0)
++				break;
++		}
++
++		mac_status = tr32(MAC_STATUS);
++		if (current_link_up == 0 &&
++		    (mac_status & MAC_STATUS_PCS_SYNCED) &&
++		    !(mac_status & MAC_STATUS_RCVD_CFG))
++			current_link_up = 1;
++	} else {
++		/* Forcing 1000FD link up. */
++		current_link_up = 1;
++		tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
++
++		tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
++		udelay(40);
++	}
++
++out:
++	return current_link_up;
+ }
+ 
+ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
+@@ -2031,6 +2254,7 @@
+ 	u32 orig_pause_cfg;
+ 	u16 orig_active_speed;
+ 	u8 orig_active_duplex;
++	u32 mac_status;
+ 	int current_link_up;
+ 	int i;
+ 
+@@ -2040,118 +2264,43 @@
+ 	orig_active_speed = tp->link_config.active_speed;
+ 	orig_active_duplex = tp->link_config.active_duplex;
+ 
+-	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+-	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+-	tw32_f(MAC_MODE, tp->mac_mode);
+-	udelay(40);
+-
+-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
+-		/* Allow time for the hardware to auto-negotiate (195ms) */
+-		unsigned int tick = 0;
+-
+-		while (++tick < 195000) { 
+-			if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
+-				break;
+-			udelay(1);
++	if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) &&
++	    netif_carrier_ok(tp->dev) &&
++	    (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) {
++		mac_status = tr32(MAC_STATUS);
++		mac_status &= (MAC_STATUS_PCS_SYNCED |
++			       MAC_STATUS_SIGNAL_DET |
++			       MAC_STATUS_CFG_CHANGED |
++			       MAC_STATUS_RCVD_CFG);
++		if (mac_status == (MAC_STATUS_PCS_SYNCED |
++				   MAC_STATUS_SIGNAL_DET)) {
++			tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
++					    MAC_STATUS_CFG_CHANGED));
++			return 0;
+ 		}
+-		if (tick >= 195000)
+-			printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
+-			    tp->dev->name);
+ 	}
+ 
+-	/* Reset when initting first time or we have a link. */
+-	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
+-	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
+-		/* Set PLL lock range. */
+-		tg3_writephy(tp, 0x16, 0x8007);
+-
+-		/* SW reset */
+-		tg3_writephy(tp, MII_BMCR, BMCR_RESET);
+-
+-		/* Wait for reset to complete. */
+-		/* XXX schedule_timeout() ... */
+-		for (i = 0; i < 500; i++)
+-			udelay(10);
+-
+-		/* Config mode; select PMA/Ch 1 regs. */
+-		tg3_writephy(tp, 0x10, 0x8411);
+-
+-		/* Enable auto-lock and comdet, select txclk for tx. */
+-		tg3_writephy(tp, 0x11, 0x0a10);
+-
+-		tg3_writephy(tp, 0x18, 0x00a0);
+-		tg3_writephy(tp, 0x16, 0x41ff);
++	tw32_f(MAC_TX_AUTO_NEG, 0);
+ 
+-		/* Assert and deassert POR. */
+-		tg3_writephy(tp, 0x13, 0x0400);
+-		udelay(40);
+-		tg3_writephy(tp, 0x13, 0x0000);
+-
+-		tg3_writephy(tp, 0x11, 0x0a50);
+-		udelay(40);
+-		tg3_writephy(tp, 0x11, 0x0a10);
++	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
++	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
++	tw32_f(MAC_MODE, tp->mac_mode);
++	udelay(40);
+ 
+-		/* Wait for signal to stabilize */
+-		/* XXX schedule_timeout() ... */
+-		for (i = 0; i < 15000; i++)
+-			udelay(10);
++	if (tp->phy_id == PHY_ID_BCM8002)
++		tg3_init_bcm8002(tp);
+ 
+-		/* Deselect the channel register so we can read the PHYID
+-		 * later.
+-		 */
+-		tg3_writephy(tp, 0x10, 0x8011);
+-	}
+-
+-	/* Enable link change interrupt unless serdes polling.  */
+-	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
+-		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+-	else
+-		tw32_f(MAC_EVENT, 0);
++	/* Enable link change event even when serdes polling.  */
++	tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+ 	udelay(40);
+ 
+ 	current_link_up = 0;
+- 	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
+-		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+-			u32 flags;
+-  
+-			if (fiber_autoneg(tp, &flags)) {
+-				u32 local_adv, remote_adv;
+-
+-				local_adv = ADVERTISE_PAUSE_CAP;
+-				remote_adv = 0;
+-				if (flags & MR_LP_ADV_SYM_PAUSE)
+-  					remote_adv |= LPA_PAUSE_CAP;
+-				if (flags & MR_LP_ADV_ASYM_PAUSE)
+-					remote_adv |= LPA_PAUSE_ASYM;
++	mac_status = tr32(MAC_STATUS);
+ 
+-				tg3_setup_flow_control(tp, local_adv, remote_adv);
+-
+-				tp->tg3_flags |=
+-					TG3_FLAG_GOT_SERDES_FLOWCTL;
+-				current_link_up = 1;
+-			}
+-			for (i = 0; i < 60; i++) {
+-				udelay(20);
+-				tw32_f(MAC_STATUS,
+-				     (MAC_STATUS_SYNC_CHANGED |
+-				      MAC_STATUS_CFG_CHANGED));
+-				udelay(40);
+-				if ((tr32(MAC_STATUS) &
+-				     (MAC_STATUS_SYNC_CHANGED |
+-				      MAC_STATUS_CFG_CHANGED)) == 0)
+-					break;
+-			}
+-			if (current_link_up == 0 &&
+-			    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
+-				current_link_up = 1;
+-			}
+-		} else {
+-			/* Forcing 1000FD link up. */
+-			current_link_up = 1;
+-			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
+-		}
+-	} else
+-		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
++	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG)
++		current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
++	else
++		current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
+ 
+ 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ 	tw32_f(MAC_MODE, tp->mac_mode);
+@@ -2162,19 +2311,24 @@
+ 		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
+ 
+ 	for (i = 0; i < 100; i++) {
+-		udelay(20);
+-		tw32_f(MAC_STATUS,
+-		     (MAC_STATUS_SYNC_CHANGED |
+-		      MAC_STATUS_CFG_CHANGED));
+-		udelay(40);
+-		if ((tr32(MAC_STATUS) &
+-		     (MAC_STATUS_SYNC_CHANGED |
+-		      MAC_STATUS_CFG_CHANGED)) == 0)
++		tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
++				    MAC_STATUS_CFG_CHANGED));
++		udelay(5);
++		if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
++					 MAC_STATUS_CFG_CHANGED)) == 0)
+ 			break;
+ 	}
+ 
+-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
++	mac_status = tr32(MAC_STATUS);
++	if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
+ 		current_link_up = 0;
++		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
++			tw32_f(MAC_MODE, (tp->mac_mode |
++					  MAC_MODE_SEND_CONFIGS));
++			udelay(1);
++			tw32_f(MAC_MODE, tp->mac_mode);
++		}
++	}
+ 
+ 	if (current_link_up == 1) {
+ 		tp->link_config.active_speed = SPEED_1000;
+@@ -2206,15 +2360,6 @@
+ 			tg3_link_report(tp);
+ 	}
+ 
+-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
+-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
+-		udelay(40);
+-		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
+-			tw32_f(MAC_MODE, tp->mac_mode);
+-			udelay(40);
+-		}
+-	}
+-
+ 	return 0;
+ }
+ 
+@@ -2222,7 +2367,7 @@
+ {
+ 	int err;
+ 
+-	if (tp->phy_id == PHY_ID_SERDES) {
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ 		err = tg3_setup_fiber_phy(tp, force_reset);
+ 	} else {
+ 		err = tg3_setup_copper_phy(tp, force_reset);
+@@ -2741,11 +2886,11 @@
+ 	tg3_halt(tp);
+ 	tg3_init_hw(tp);
+ 
++	tg3_netif_start(tp);
++
+ 	spin_unlock(&tp->tx_lock);
+ 	spin_unlock_irq(&tp->lock);
+ 
+-	tg3_netif_start(tp);
+-
+ 	if (restart_timer)
+ 		mod_timer(&tp->timer, jiffies + 1);
+ }
+@@ -2815,6 +2960,7 @@
+ 			dma_addr_t mapping, int len, u32 flags,
+ 			u32 mss_and_is_end)
+ {
++	struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
+ 	int is_end = (mss_and_is_end & 0x1);
+ 	u32 mss = (mss_and_is_end >> 1);
+ 	u32 vlan_tag = 0;
+@@ -2826,35 +2972,11 @@
+ 		flags &= 0xffff;
+ 	}
+ 	vlan_tag |= (mss << TXD_MSS_SHIFT);
+-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
+-		struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
+ 
+-		txd->addr_hi = ((u64) mapping >> 32);
+-		txd->addr_lo = ((u64) mapping & 0xffffffff);
+-		txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+-		txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
+-	} else {
+-		struct tx_ring_info *txr = &tp->tx_buffers[entry];
+-		unsigned long txd;
+-
+-		txd = (tp->regs +
+-		       NIC_SRAM_WIN_BASE +
+-		       NIC_SRAM_TX_BUFFER_DESC);
+-		txd += (entry * TXD_SIZE);
+-
+-		/* Save some PIOs */
+-		if (sizeof(dma_addr_t) != sizeof(u32))
+-			writel(((u64) mapping >> 32),
+-			       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
+-
+-		writel(((u64) mapping & 0xffffffff),
+-		       txd + TXD_ADDR + TG3_64BIT_REG_LOW);
+-		writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS);
+-		if (txr->prev_vlan_tag != vlan_tag) {
+-			writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG);
+-			txr->prev_vlan_tag = vlan_tag;
+-		}
+-	}
++	txd->addr_hi = ((u64) mapping >> 32);
++	txd->addr_lo = ((u64) mapping & 0xffffffff);
++	txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
++	txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
+ }
+ 
+ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
+@@ -3043,19 +3169,7 @@
+ 	}
+ 
+ 	/* Packets are ready, update Tx producer idx local and on card. */
+-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
+-		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
+-			      TG3_64BIT_REG_LOW), entry);
+-	} else {
+-		/* First, make sure tg3 sees last descriptor fully
+-		 * in SRAM.
+-		 */
+-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
+-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+-
+-		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
+-			      TG3_64BIT_REG_LOW), entry);
+-	}
++	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
+ 
+ 	tp->tx_prod = entry;
+ 	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
+@@ -3105,9 +3219,10 @@
+ 
+ 	tg3_init_hw(tp);
+ 
++	tg3_netif_start(tp);
++
+ 	spin_unlock(&tp->tx_lock);
+ 	spin_unlock_irq(&tp->lock);
+-	tg3_netif_start(tp);
+ 
+ 	return 0;
+ }
+@@ -3193,7 +3308,6 @@
+  */
+ static void tg3_init_rings(struct tg3 *tp)
+ {
+-	unsigned long start, end;
+ 	u32 i;
+ 
+ 	/* Free up all the SKBs. */
+@@ -3203,21 +3317,7 @@
+ 	memset(tp->rx_std, 0, TG3_RX_RING_BYTES);
+ 	memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES);
+ 	memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+-
+-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
+-		memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
+-	} else {
+-		start = (tp->regs +
+-			 NIC_SRAM_WIN_BASE +
+-			 NIC_SRAM_TX_BUFFER_DESC);
+-		end = start + TG3_TX_RING_BYTES;
+-		while (start < end) {
+-			writel(0, start);
+-			start += 4;
+-		}
+-		for (i = 0; i < TG3_TX_RING_SIZE; i++)
+-			tp->tx_buffers[i].prev_vlan_tag = 0;
+-	}
++	memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
+ 
+ 	/* Initialize invariants of the rings, we only set this
+ 	 * stuff once.  This works because the card does not
+@@ -3348,15 +3448,10 @@
+ 	if (!tp->rx_rcb)
+ 		goto err_out;
+ 
+-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
+-		tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
+-						   &tp->tx_desc_mapping);
+-		if (!tp->tx_ring)
+-			goto err_out;
+-	} else {
+-		tp->tx_ring = NULL;
+-		tp->tx_desc_mapping = 0;
+-	}
++	tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
++					   &tp->tx_desc_mapping);
++	if (!tp->tx_ring)
++		goto err_out;
+ 
+ 	tp->hw_status = pci_alloc_consistent(tp->pdev,
+ 					     TG3_HW_STATUS_SIZE,
+@@ -3598,6 +3693,8 @@
+ 	}
+ }
+ 
++static void tg3_stop_fw(struct tg3 *);
++
+ /* tp->lock is held. */
+ static int tg3_chip_reset(struct tg3 *tp)
+ {
+@@ -3605,7 +3702,7 @@
+ 	u32 flags_save;
+ 	int i;
+ 
+-	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704))
++	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+ 		tg3_nvram_lock(tp);
+ 
+ 	/*
+@@ -3700,6 +3797,11 @@
+ 
+ 	tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
+ 
++	if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
++		tg3_stop_fw(tp);
++		tw32(0x5000, 0x400);
++	}
++
+ 	tw32(GRC_MODE, tp->grc_mode);
+ 
+ 	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
+@@ -3716,7 +3818,7 @@
+ 		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+ 	}
+ 
+-	if (tp->phy_id == PHY_ID_SERDES) {
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ 		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
+ 		tw32_f(MAC_MODE, tp->mac_mode);
+ 	} else
+@@ -3731,7 +3833,7 @@
+ 		udelay(10);
+ 	}
+ 	if (i >= 100000 &&
+-	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
++	    !(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
+ 		printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
+ 		       "firmware will not restart magic=%08x\n",
+ 		       tp->dev->name, val);
+@@ -4314,10 +4915,7 @@
+ 			  GRC_MODE_4X_NIC_SEND_RINGS |
+ 			  GRC_MODE_NO_TX_PHDR_CSUM |
+ 			  GRC_MODE_NO_RX_PHDR_CSUM);
+-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS)
+-		tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
+-	else
+-		tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS;
++	tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
+ 	if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
+ 		tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
+ 	if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
+@@ -4470,18 +5068,11 @@
+ 	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
+ 	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
+ 
+-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
+-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
+-			       tp->tx_desc_mapping,
+-			       (TG3_TX_RING_SIZE <<
+-				BDINFO_FLAGS_MAXLEN_SHIFT),
+-			       NIC_SRAM_TX_BUFFER_DESC);
+-	} else {
+-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
+-			       0,
+-			       BDINFO_FLAGS_DISABLED,
+-			       NIC_SRAM_TX_BUFFER_DESC);
+-	}
++	tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
++		       tp->tx_desc_mapping,
++		       (TG3_TX_RING_SIZE <<
++			BDINFO_FLAGS_MAXLEN_SHIFT),
++		       NIC_SRAM_TX_BUFFER_DESC);
+ 
+ 	/* There is only one receive return ring on 5705/5750, no need
+ 	 * to explicitly disable the others.
+@@ -4747,14 +5338,14 @@
+ 	tw32(MAC_LED_CTRL, tp->led_ctrl);
+ 
+ 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+-	if (tp->phy_id == PHY_ID_SERDES) {
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ 		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+ 		udelay(10);
+ 	}
+ 	tw32_f(MAC_RX_MODE, tp->rx_mode);
+ 	udelay(10);
+ 
+-	if (tp->phy_id == PHY_ID_SERDES) {
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ 			/* Set drive transmission level to 1.2V  */
+ 			val = tr32(MAC_SERDES_CFG);
+@@ -4772,22 +5363,8 @@
+ 	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
+ 
+ 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+-	    tp->phy_id == PHY_ID_SERDES) {
+-		/* Enable hardware link auto-negotiation */
+-		u32 digctrl, txctrl;
+-
+-		digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
+-		    SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
+-		    (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
+-		    SG_DIG_GBIC_ENABLE;
+-
+-		txctrl = tr32(MAC_SERDES_CFG);
+-		tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
+-		tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
+-		tr32(SG_DIG_CTRL);
+-		udelay(5);
+-		tw32_f(SG_DIG_CTRL, digctrl);
+-
++	    (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
++		/* Use hardware link auto-negotiation */
+ 		tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
+ 	}
+ 
+@@ -4795,7 +5372,7 @@
+ 	if (err)
+ 		return err;
+ 
+-	if (tp->phy_id != PHY_ID_SERDES) {
++	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ 		u32 tmp;
+ 
+ 		/* Clear CRC stats. */
+@@ -4987,7 +5564,8 @@
+ 				need_setup = 1;
+ 			}
+ 			if (! netif_carrier_ok(tp->dev) &&
+-			    (mac_stat & MAC_STATUS_PCS_SYNCED)) {
++			    (mac_stat & (MAC_STATUS_PCS_SYNCED |
++					 MAC_STATUS_SIGNAL_DET))) {
+ 				need_setup = 1;
+ 			}
+ 			if (need_setup) {
+@@ -5040,8 +5618,8 @@
+ 	spin_unlock(&tp->tx_lock);
+ 	spin_unlock_irq(&tp->lock);
+ 
+-	/* If you move this call, make sure TG3_FLAG_HOST_TXDS in
+-	 * tp->tg3_flags is accurate at that new place.
++	/* The placement of this call is tied
++	 * to the setup and use of Host TX descriptors.
+ 	 */
+ 	err = tg3_alloc_consistent(tp);
+ 	if (err)
+@@ -5383,7 +5961,7 @@
+ {
+ 	struct tg3_hw_stats *hw_stats = tp->hw_stats;
+ 
+-	if (tp->phy_id != PHY_ID_SERDES &&
++	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+ 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+ 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
+ 		unsigned long flags;
+@@ -5814,7 +6394,7 @@
+ 		cmd->supported |= (SUPPORTED_1000baseT_Half |
+ 				   SUPPORTED_1000baseT_Full);
+ 
+-	if (tp->phy_id != PHY_ID_SERDES)
++	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
+ 		cmd->supported |= (SUPPORTED_100baseT_Half |
+ 				  SUPPORTED_100baseT_Full |
+ 				  SUPPORTED_10baseT_Half |
+@@ -5843,7 +6423,7 @@
+ 	    tp->link_config.phy_is_low_power)
+ 		return -EAGAIN;
+ 
+-	if (tp->phy_id == PHY_ID_SERDES) {
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ 		/* These are the only valid advertisement bits allowed.  */
+ 		if (cmd->autoneg == AUTONEG_ENABLE &&
+ 		    (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
+@@ -5901,7 +6481,7 @@
+ 	if (wol->wolopts & ~WAKE_MAGIC)
+ 		return -EINVAL;
+ 	if ((wol->wolopts & WAKE_MAGIC) &&
+-	    tp->phy_id == PHY_ID_SERDES &&
++	    tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
+ 	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
+ 		return -EINVAL;
+   
+@@ -5997,10 +6577,9 @@
+ 
+ 	tg3_halt(tp);
+ 	tg3_init_hw(tp);
+-	netif_wake_queue(tp->dev);
++	tg3_netif_start(tp);
+ 	spin_unlock(&tp->tx_lock);
+ 	spin_unlock_irq(&tp->lock);
+-	tg3_netif_start(tp);
+   
+ 	return 0;
+ }
+@@ -6010,8 +6589,8 @@
+ 	struct tg3 *tp = netdev_priv(dev);
+   
+ 	epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
+-	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0;
+-	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0;
++	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0;
++	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0;
+ }
+   
+ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
+@@ -6026,18 +6605,18 @@
+ 	else
+ 		tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
+ 	if (epause->rx_pause)
+-		tp->tg3_flags |= TG3_FLAG_PAUSE_RX;
++		tp->tg3_flags |= TG3_FLAG_RX_PAUSE;
+ 	else
+-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX;
++		tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE;
+ 	if (epause->tx_pause)
+-		tp->tg3_flags |= TG3_FLAG_PAUSE_TX;
++		tp->tg3_flags |= TG3_FLAG_TX_PAUSE;
+ 	else
+-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
++		tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
+ 	tg3_halt(tp);
+ 	tg3_init_hw(tp);
++	tg3_netif_start(tp);
+ 	spin_unlock(&tp->tx_lock);
+ 	spin_unlock_irq(&tp->lock);
+-	tg3_netif_start(tp);
+   
+ 	return 0;
+ }
+@@ -6124,7 +6703,7 @@
+ 	case SIOCGMIIREG: {
+ 		u32 mii_regval;
+ 
+-		if (tp->phy_id == PHY_ID_SERDES)
++		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ 			break;			/* We have no PHY */
+ 
+ 		spin_lock_irq(&tp->lock);
+@@ -6137,7 +6716,7 @@
+ 	}
+ 
+ 	case SIOCSMIIREG:
+-		if (tp->phy_id == PHY_ID_SERDES)
++		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ 			break;			/* We have no PHY */
+ 
+ 		if (!capable(CAP_NET_ADMIN))
+@@ -6224,7 +6803,7 @@
+ {
+ 	int j;
+ 
+-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
++	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
+ 		return;
+ 
+ 	tw32_f(GRC_EEPROM_ADDR,
+@@ -6311,8 +6890,8 @@
+ {
+ 	int i;
+ 
+-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
+-		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n");
++	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
++		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -6374,10 +6953,10 @@
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES  }, /* BCM95700A9 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0003, 0 },		    /* BCM95700A9 */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
+-	{ PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
++	{ PCI_VENDOR_ID_BROADCOM, 0x0007, 0 },		    /* BCM95701A7 */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
+ 	{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
+@@ -6386,7 +6965,7 @@
+ 	/* 3com boards. */
+ 	{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
+ 	{ PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
+-	{ PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES  }, /* 3C996SX */
++	{ PCI_VENDOR_ID_3COM, 0x1004, 0 },		/* 3C996SX */
+ 	{ PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
+ 	{ PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
+ 
+@@ -6399,37 +6978,43 @@
+ 	/* Compaq boards. */
+ 	{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
+ 	{ PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
+-	{ PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES  }, /* CHANGELING */
++	{ PCI_VENDOR_ID_COMPAQ, 0x007d, 0 },		  /* CHANGELING */
+ 	{ PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
+ 	{ PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */
+ 
+ 	/* IBM boards. */
+-	{ PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */
++	{ PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */
+ };
+ 
+-static int __devinit tg3_phy_probe(struct tg3 *tp)
++static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
+ {
+-	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
+-	u32 hw_phy_id, hw_phy_id_masked;
+-	u32 val;
+-	int i, eeprom_signature_found, err;
++	int i;
+ 
+-	tp->phy_id = PHY_ID_INVALID;
+ 	for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) {
+ 		if ((subsys_id_to_phy_id[i].subsys_vendor ==
+ 		     tp->pdev->subsystem_vendor) &&
+ 		    (subsys_id_to_phy_id[i].subsys_devid ==
+-		     tp->pdev->subsystem_device)) {
+-			tp->phy_id = subsys_id_to_phy_id[i].phy_id;
+-			break;
+-		}
++		     tp->pdev->subsystem_device))
++			return &subsys_id_to_phy_id[i];
+ 	}
++	return NULL;
++}
+ 
++static int __devinit tg3_phy_probe(struct tg3 *tp)
++{
++	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
++	u32 hw_phy_id, hw_phy_id_masked;
++	u32 val;
++	int eeprom_signature_found, eeprom_phy_serdes, err;
++
++	tp->phy_id = PHY_ID_INVALID;
+ 	eeprom_phy_id = PHY_ID_INVALID;
++	eeprom_phy_serdes = 0;
+ 	eeprom_signature_found = 0;
+ 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
+ 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
+ 		u32 nic_cfg, led_cfg;
++		u32 nic_phy_id, cfg2;
+ 
+ 		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
+ 		tp->nic_sram_data_cfg = nic_cfg;
+@@ -6437,21 +7022,19 @@
+ 		eeprom_signature_found = 1;
+ 
+ 		if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
+-		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
+-			eeprom_phy_id = PHY_ID_SERDES;
+-		} else {
+-			u32 nic_phy_id;
++		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
++			eeprom_phy_serdes = 1;
+ 
+-			tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
+-			if (nic_phy_id != 0) {
+-				u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
+-				u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
+-
+-				eeprom_phy_id  = (id1 >> 16) << 10;
+-				eeprom_phy_id |= (id2 & 0xfc00) << 16;
+-				eeprom_phy_id |= (id2 & 0x03ff) <<  0;
+-			}
+-		}
++		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
++		if (nic_phy_id != 0) {
++			u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
++			u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
++
++			eeprom_phy_id  = (id1 >> 16) << 10;
++			eeprom_phy_id |= (id2 & 0xfc00) << 16;
++			eeprom_phy_id |= (id2 & 0x03ff) <<  0;
++		} else
++			eeprom_phy_id = 0;
+ 
+ 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ 			tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
+@@ -6513,6 +7096,10 @@
+ 		}
+ 		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
+ 			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
++
++		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2);
++		if (cfg2 & (1 << 17))
++			tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
+ 	}
+ 
+ 	/* Reading the PHY ID register can conflict with ASF
+@@ -6539,20 +7126,31 @@
+ 
+ 	if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
+ 		tp->phy_id = hw_phy_id;
++		if (hw_phy_id_masked == PHY_ID_BCM8002)
++			tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+ 	} else {
+-		/* phy_id currently holds the value found in the
+-		 * subsys_id_to_phy_id[] table or PHY_ID_INVALID
+-		 * if a match was not found there.
+-		 */
+-		if (tp->phy_id == PHY_ID_INVALID) {
+-			if (!eeprom_signature_found ||
+-			    !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
+-				return -ENODEV;
++		if (eeprom_signature_found) {
+ 			tp->phy_id = eeprom_phy_id;
++			if (eeprom_phy_serdes)
++				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
++		} else {
++			struct subsys_tbl_ent *p;
++
++			/* No eeprom signature?  Try the hardcoded
++			 * subsys device table.
++			 */
++			p = lookup_by_subsys(tp);
++			if (!p)
++				return -ENODEV;
++
++			tp->phy_id = p->phy_id;
++			if (!tp->phy_id ||
++			    tp->phy_id == PHY_ID_BCM8002)
++				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+ 		}
+ 	}
+ 
+-	if (tp->phy_id != PHY_ID_SERDES &&
++	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+ 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
+ 		u32 bmsr, adv_reg, tg3_ctrl;
+ 
+@@ -6609,7 +7207,7 @@
+ 	if (!eeprom_signature_found)
+ 		tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+ 
+-	if (tp->phy_id == PHY_ID_SERDES)
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ 		tp->link_config.advertising =
+ 			(ADVERTISED_1000baseT_Half |
+ 			 ADVERTISED_1000baseT_Full |
+@@ -6628,11 +7226,11 @@
+ 	unsigned char vpd_data[256];
+ 	int i;
+ 
+-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
++	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+ 		/* Sun decided not to put the necessary bits in the
+ 		 * NVRAM of their onboard tg3 parts :(
+ 		 */
+-		strcpy(tp->board_part_number, "Sun 5704");
++		strcpy(tp->board_part_number, "Sun 570X");
+ 		return;
+ 	}
+ 
+@@ -6693,27 +7291,21 @@
+ }
+ 
+ #ifdef CONFIG_SPARC64
+-static int __devinit tg3_is_sun_5704(struct tg3 *tp)
++static int __devinit tg3_is_sun_570X(struct tg3 *tp)
+ {
+ 	struct pci_dev *pdev = tp->pdev;
+ 	struct pcidev_cookie *pcp = pdev->sysdata;
+ 
+ 	if (pcp != NULL) {
+ 		int node = pcp->prom_node;
+-		u32 venid, devid;
++		u32 venid;
+ 		int err;
+ 
+ 		err = prom_getproperty(node, "subsystem-vendor-id",
+ 				       (char *) &venid, sizeof(venid));
+ 		if (err == 0 || err == -1)
+ 			return 0;
+-		err = prom_getproperty(node, "subsystem-id",
+-				       (char *) &devid, sizeof(devid));
+-		if (err == 0 || err == -1)
+-			return 0;
+-
+-		if (venid == PCI_VENDOR_ID_SUN &&
+-		    devid == PCI_DEVICE_ID_TIGON3_5704)
++		if (venid == PCI_VENDOR_ID_SUN)
+ 			return 1;
+ 	}
+ 	return 0;
+@@ -6730,8 +7322,8 @@
+ 	int err;
+ 
+ #ifdef CONFIG_SPARC64
+-	if (tg3_is_sun_5704(tp))
+-		tp->tg3_flags2 |= TG3_FLG2_SUN_5704;
++	if (tg3_is_sun_570X(tp))
++		tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
+ #endif
+ 
+ 	/* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write
+@@ -6976,32 +7568,17 @@
+ 	udelay(50);
+ 	tg3_nvram_init(tp);
+ 
+-	/* Always use host TXDs, it performs better in particular
+-	 * with multi-frag packets.  The tests below are kept here
+-	 * as documentation should we change this decision again
+-	 * in the future.
+-	 */
+-	tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
+-
+-#if 0
+-	/* Determine if TX descriptors will reside in
+-	 * main memory or in the chip SRAM.
+-	 */
+-	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 ||
+-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+-		tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
+-#endif
+-
+ 	grc_misc_cfg = tr32(GRC_MISC_CFG);
+ 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
+ 
++	/* Broadcom's driver says that CIOBE multisplit has a bug */
++#if 0
+ 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+ 	    grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
+ 		tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
+ 		tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
+ 	}
+-
++#endif
+ 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+ 	    (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
+ 	     grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
+@@ -7028,7 +7605,7 @@
+ 
+ 	tg3_read_partno(tp);
+ 
+-	if (tp->phy_id == PHY_ID_SERDES) {
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+ 		tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
+ 	} else {
+ 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+@@ -7051,13 +7628,13 @@
+ 	 * upon subsystem IDs.
+ 	 */
+ 	if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+-	    tp->phy_id != PHY_ID_SERDES) {
++	    !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+ 		tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
+ 				  TG3_FLAG_USE_LINKCHG_REG);
+ 	}
+ 
+ 	/* For all SERDES we poll the MAC status register. */
+-	if (tp->phy_id == PHY_ID_SERDES)
++	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ 		tp->tg3_flags |= TG3_FLAG_POLL_SERDES;
+ 	else
+ 		tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
+@@ -7128,7 +7705,7 @@
+ 
+ 	mac_offset = 0x7c;
+ 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+-	    !(tp->tg3_flags & TG3_FLG2_SUN_5704)) {
++	    !(tp->tg3_flags & TG3_FLG2_SUN_570X)) {
+ 		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+ 			mac_offset = 0xcc;
+ 		if (tg3_nvram_lock(tp))
+@@ -7150,7 +7727,7 @@
+ 		dev->dev_addr[5] = (lo >>  0) & 0xff;
+ 	}
+ 	/* Next, try NVRAM. */
+-	else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) &&
++	else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
+ 		 !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
+ 		 !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
+ 		dev->dev_addr[0] = ((hi >> 16) & 0xff);
+@@ -7492,8 +8069,8 @@
+ 	case PHY_ID_BCM5704:	return "5704";
+ 	case PHY_ID_BCM5705:	return "5705";
+ 	case PHY_ID_BCM5750:	return "5750";
+-	case PHY_ID_BCM8002:	return "8002";
+-	case PHY_ID_SERDES:	return "serdes";
++	case PHY_ID_BCM8002:	return "8002/serdes";
++	case 0:			return "serdes";
+ 	default:		return "unknown";
+ 	};
+ }
+@@ -7785,6 +8339,9 @@
+ 	if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
+ 		dev->features &= ~NETIF_F_HIGHDMA;
+ 
++	/* flow control autonegotiation is default behavior */
++	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
++
+ 	err = register_netdev(dev);
+ 	if (err) {
+ 		printk(KERN_ERR PFX "Cannot register net device, "
+@@ -7816,11 +8373,10 @@
+ 		printk("%2.2x%c", dev->dev_addr[i],
+ 		       i == 5 ? '\n' : ':');
+ 
+-	printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] "
++	printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
+ 	       "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
+ 	       "TSOcap[%d] \n",
+ 	       dev->name,
+-	       (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0,
+ 	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
+ 	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
+ 	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
+@@ -7899,11 +8455,11 @@
+ 		tp->timer.expires = jiffies + tp->timer_offset;
+ 		add_timer(&tp->timer);
+ 
+-		spin_unlock(&tp->tx_lock);
+-		spin_unlock_irq(&tp->lock);
+-
+ 		netif_device_attach(dev);
+ 		tg3_netif_start(tp);
++
++		spin_unlock(&tp->tx_lock);
++		spin_unlock_irq(&tp->lock);
+ 	}
+ 
+ 	return err;
+@@ -7936,11 +8492,11 @@
+ 
+ 	tg3_enable_ints(tp);
+ 
++	tg3_netif_start(tp);
++
+ 	spin_unlock(&tp->tx_lock);
+ 	spin_unlock_irq(&tp->lock);
+ 
+-	tg3_netif_start(tp);
+-
+ 	return 0;
+ }
+ 

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tty-locking-fixes9.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tty-locking-fixes9.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/tty-locking-fixes9.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,12 @@
+--- kernel-source-2.6.8-2.6.8/drivers/serial/serial_core.c~	2004-11-24 11:56:39.000000000 -0800
++++ kernel-source-2.6.8-2.6.8/drivers/serial/serial_core.c	2004-11-24 11:56:50.000000000 -0800
+@@ -107,7 +107,8 @@
+ static void uart_tasklet_action(unsigned long data)
+ {
+ 	struct uart_state *state = (struct uart_state *)data;
+-	tty_wakeup(state->info->tty);
++	if (state->info->tty)
++		tty_wakeup(state->info->tty);
+ }
+ 
+ static inline void

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/vlan-update-1.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/vlan-update-1.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/vlan-update-1.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,282 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Sync code and feature set with 2.4.x
+## DP: Patch author: David Miller, Ben Greear
+## DP: Upstream status: upstream
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+# origin: greearb (BitKeeper)
+# cset: 1.2026.32.3 (2.6) key=4180303dxO_jU4ssNg8I1rEuY11kRA
+# inclusion: upstream
+# descrition: [VLAN]: Sync code and feature set with 2.4.x
+# revision date: Fri, 12 Nov 2004 16:24:20 +0900
+#
+# rset: ChangeSet|1.2026.32.2..1.2026.32.3
+# rset: include/linux/if_vlan.h|1.10..1.11
+# rset: net/8021q/vlan.h|1.10..1.11
+# rset: net/8021q/vlan.c|1.30..1.31
+# rset: net/8021q/vlan_dev.c|1.21..1.22
+#
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/10/27 16:33:17-07:00 greearb at candelatech.com 
+#   [VLAN]: Sync code and feature set with 2.4.x
+#   
+#   Signed-off-by: David S. Miller <davem at davemloft.net>
+# 
+# net/8021q/vlan_dev.c
+#   2004/10/27 16:32:46-07:00 greearb at candelatech.com +57 -6
+#   [VLAN]: Sync code and feature set with 2.4.x
+# 
+# net/8021q/vlan.h
+#   2004/10/27 16:32:46-07:00 greearb at candelatech.com +2 -0
+#   [VLAN]: Sync code and feature set with 2.4.x
+# 
+# net/8021q/vlan.c
+#   2004/10/27 16:32:46-07:00 greearb at candelatech.com +50 -17
+#   [VLAN]: Sync code and feature set with 2.4.x
+# 
+# include/linux/if_vlan.h
+#   2004/10/27 16:32:46-07:00 greearb at candelatech.com +3 -1
+#   [VLAN]: Sync code and feature set with 2.4.x
+# 
+diff -Nru a/include/linux/if_vlan.h b/include/linux/if_vlan.h
+--- a/include/linux/if_vlan.h	2004-11-12 16:24:20 +09:00
++++ b/include/linux/if_vlan.h	2004-11-12 16:24:20 +09:00
+@@ -366,7 +366,9 @@
+ 	GET_VLAN_INGRESS_PRIORITY_CMD,
+ 	GET_VLAN_EGRESS_PRIORITY_CMD,
+ 	SET_VLAN_NAME_TYPE_CMD,
+-	SET_VLAN_FLAG_CMD
++	SET_VLAN_FLAG_CMD,
++	GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
++	GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
+ };
+ 
+ enum vlan_name_types {
+diff -Nru a/net/8021q/vlan.c b/net/8021q/vlan.c
+--- a/net/8021q/vlan.c	2004-11-12 16:24:20 +09:00
++++ b/net/8021q/vlan.c	2004-11-12 16:24:20 +09:00
+@@ -647,15 +647,9 @@
+ static int vlan_ioctl_handler(void __user *arg)
+ {
+ 	int err = 0;
++	unsigned short vid = 0;
+ 	struct vlan_ioctl_args args;
+ 
+-	/* everything here needs root permissions, except aguably the
+-	 * hack ioctls for sending packets.  However, I know _I_ don't
+-	 * want users running that on my network! --BLG
+-	 */
+-	if (!capable(CAP_NET_ADMIN))
+-		return -EPERM;
+-
+ 	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
+ 		return -EFAULT;
+ 
+@@ -669,24 +663,32 @@
+ 
+ 	switch (args.cmd) {
+ 	case SET_VLAN_INGRESS_PRIORITY_CMD:
++		if (!capable(CAP_NET_ADMIN))
++			return -EPERM;
+ 		err = vlan_dev_set_ingress_priority(args.device1,
+ 						    args.u.skb_priority,
+ 						    args.vlan_qos);
+ 		break;
+ 
+ 	case SET_VLAN_EGRESS_PRIORITY_CMD:
++		if (!capable(CAP_NET_ADMIN))
++			return -EPERM;
+ 		err = vlan_dev_set_egress_priority(args.device1,
+ 						   args.u.skb_priority,
+ 						   args.vlan_qos);
+ 		break;
+ 
+ 	case SET_VLAN_FLAG_CMD:
++		if (!capable(CAP_NET_ADMIN))
++			return -EPERM;
+ 		err = vlan_dev_set_vlan_flag(args.device1,
+ 					     args.u.flag,
+ 					     args.vlan_qos);
+ 		break;
+ 
+ 	case SET_VLAN_NAME_TYPE_CMD:
++		if (!capable(CAP_NET_ADMIN))
++			return -EPERM;
+ 		if ((args.u.name_type >= 0) &&
+ 		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
+ 			vlan_name_type = args.u.name_type;
+@@ -696,17 +698,9 @@
+ 		}
+ 		break;
+ 
+-		/* TODO:  Figure out how to pass info back...
+-		   case GET_VLAN_INGRESS_PRIORITY_IOCTL:
+-		   err = vlan_dev_get_ingress_priority(args);
+-		   break;
+-
+-		   case GET_VLAN_EGRESS_PRIORITY_IOCTL:
+-		   err = vlan_dev_get_egress_priority(args);
+-		   break;
+-		*/
+-
+ 	case ADD_VLAN_CMD:
++		if (!capable(CAP_NET_ADMIN))
++			return -EPERM;
+ 		/* we have been given the name of the Ethernet Device we want to
+ 		 * talk to:  args.dev1	 We also have the
+ 		 * VLAN ID:  args.u.VID
+@@ -719,10 +713,49 @@
+ 		break;
+ 
+ 	case DEL_VLAN_CMD:
++		if (!capable(CAP_NET_ADMIN))
++			return -EPERM;
+ 		/* Here, the args.dev1 is the actual VLAN we want
+ 		 * to get rid of.
+ 		 */
+ 		err = unregister_vlan_device(args.device1);
++		break;
++
++	case GET_VLAN_INGRESS_PRIORITY_CMD:
++		/* TODO:  Implement
++		   err = vlan_dev_get_ingress_priority(args);
++		   if (copy_to_user((void*)arg, &args,
++		        sizeof(struct vlan_ioctl_args))) {
++		        err = -EFAULT;
++		   }
++		*/
++		err = -EINVAL;
++		break;
++	case GET_VLAN_EGRESS_PRIORITY_CMD:
++		/* TODO:  Implement
++		   err = vlan_dev_get_egress_priority(args.device1, &(args.args);
++		   if (copy_to_user((void*)arg, &args,
++		        sizeof(struct vlan_ioctl_args))) {
++		        err = -EFAULT;
++		   }
++		*/
++		err = -EINVAL;
++		break;
++	case GET_VLAN_REALDEV_NAME_CMD:
++		err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
++		if (copy_to_user((void*)arg, &args,
++				 sizeof(struct vlan_ioctl_args))) {
++			err = -EFAULT;
++		}
++		break;
++
++	case GET_VLAN_VID_CMD:
++		err = vlan_dev_get_vid(args.device1, &vid);
++		args.u.VID = vid;
++		if (copy_to_user((void*)arg, &args,
++				 sizeof(struct vlan_ioctl_args))) {
++                      err = -EFAULT;
++		}
+ 		break;
+ 
+ 	default:
+diff -Nru a/net/8021q/vlan.h b/net/8021q/vlan.h
+--- a/net/8021q/vlan.h	2004-11-12 16:24:20 +09:00
++++ b/net/8021q/vlan.h	2004-11-12 16:24:20 +09:00
+@@ -66,6 +66,8 @@
+ int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
+ int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
+ int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
++int vlan_dev_get_realdev_name(const char* dev_name, char* result);
++int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
+ void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
+ 
+ #endif /* !(__BEN_VLAN_802_1Q_INC__) */
+diff -Nru a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+--- a/net/8021q/vlan_dev.c	2004-11-12 16:24:20 +09:00
++++ b/net/8021q/vlan_dev.c	2004-11-12 16:24:20 +09:00
+@@ -1,4 +1,4 @@
+-/*
++/* -*- linux-c -*-
+  * INET		802.1Q VLAN
+  *		Ethernet-type device handling.
+  *
+@@ -484,13 +484,26 @@
+ 	       veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto);
+ #endif
+ 
+-	stats->tx_packets++; /* for statics only */
+-	stats->tx_bytes += skb->len;
+-
+ 	skb->dev = VLAN_DEV_INFO(dev)->real_dev;
+-	dev_queue_xmit(skb);
+ 
+-	return 0;
++	{
++		/* Please note, dev_queue_xmit consumes the pkt regardless of the
++		 * error value.  So, will copy the skb first and free if successful.
++		 */
++		struct sk_buff* skb2 = skb_get(skb);
++		int rv = dev_queue_xmit(skb2);
++		if (rv == 0) {
++			/* Was success, need to free the skb reference since we bumped up the
++			 * user count above.
++			 */
++
++			stats->tx_packets++; /* for statics only */
++			stats->tx_bytes += skb->len;
++
++			kfree_skb(skb);
++		}
++		return rv;
++	}
+ }
+ 
+ int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+@@ -621,6 +634,44 @@
+ 
+ 	return -EINVAL;
+ }
++
++
++int vlan_dev_get_realdev_name(const char *dev_name, char* result)
++{
++	struct net_device *dev = dev_get_by_name(dev_name);
++	int rv = 0;
++	if (dev) {
++		if (dev->priv_flags & IFF_802_1Q_VLAN) {
++			strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
++			rv = 0;
++		} else {
++			rv = -EINVAL;
++		}
++		dev_put(dev);
++	} else {
++		rv = -ENODEV;
++	}
++	return rv;
++}
++
++int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
++{
++	struct net_device *dev = dev_get_by_name(dev_name);
++	int rv = 0;
++	if (dev) {
++		if (dev->priv_flags & IFF_802_1Q_VLAN) {
++			*result = VLAN_DEV_INFO(dev)->vlan_id;
++			rv = 0;
++		} else {
++			rv = -EINVAL;
++		}
++		dev_put(dev);
++	} else {
++		rv = -ENODEV;
++	}
++	return rv;
++}
++
+ 
+ int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
+ {

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/x86-i486_emu.dpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/x86-i486_emu.dpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/patches/x86-i486_emu.dpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,528 @@
+#! /bin/sh -e 
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR at EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: 486 emulation
+## DP: Patch author: Willy Tarreau
+## DP: Upstream status: submitted, needs more work
+
+. $(dirname $0)/DPATCH
+
+ at DPATCH@
+diff -urN kernel-source-2.6.6/arch/i386/Kconfig kernel-source-2.6.6-1/arch/i386/Kconfig
+--- kernel-source-2.6.6/arch/i386/Kconfig	2004-05-10 19:47:45.000000000 +1000
++++ kernel-source-2.6.6-1/arch/i386/Kconfig	2004-05-10 22:21:08.000000000 +1000
+@@ -330,6 +330,41 @@
+ 	  This is really intended for distributors who need more
+ 	  generic optimizations.
+ 
++config X86_EMU486
++       bool "486 emulation"
++       help
++          When used on a 386, Linux can emulate 3 instructions from the 486
++          set.  This allows user space programs compiled for 486 to run on a
++          386 without crashing with a SIGILL. As any emulation, performance
++          will be very low, but since these instruction are not often used,
++          this might not hurt.  The emulated instructions are:
++             - bswap (does the same as htonl())
++             - cmpxchg (used in multi-threading, mutex locking)
++             - xadd (rarely used)
++
++          Note that this can also allow Step-A 486's to correctly run
++          multi-thread applications since cmpxchg has a wrong opcode on this
++          early CPU.
++
++          Don't use this to enable multi-threading on an SMP machine, the lock
++          atomicity can't be guaranted!
++
++          Although it's highly preferable that you only execute programs
++          targetted for your CPU, it may happen that, consecutively to a
++          hardware replacement, or during rescue of a damaged system, you have
++          to execute such programs on an inadapted processor.  In this case,
++          this option will help you get your programs working, even if they
++          will be slower.
++
++          It is recommended that you say N here in any case, except for the
++          kernels that you will use on your rescue disks.
++ 
++          This option should not be left on by default, because it means that
++          you execute a program not targetted for your CPU.  You should
++          recompile your applications whenever possible.
++
++          If you are not sure, say N.
++
+ endif
+ 
+ #
+@@ -438,6 +473,7 @@
+ 
+ config SMP
+ 	bool "Symmetric multi-processing support"
++	depends on !X86_EMU486
+ 	---help---
+ 	  This enables support for systems with more than one CPU. If you have
+ 	  a system with only one CPU, like most personal computers, say N. If
+diff -urN kernel-source-2.6.6/arch/i386/kernel/Makefile kernel-source-2.6.6-1/arch/i386/kernel/Makefile
+--- kernel-source-2.6.6/arch/i386/kernel/Makefile	2004-05-10 19:47:45.000000000 +1000
++++ kernel-source-2.6.6-1/arch/i386/kernel/Makefile	2004-05-10 22:21:08.000000000 +1000
+@@ -28,6 +28,7 @@
+ obj-$(CONFIG_MODULES)		+= module.o
+ obj-y				+= sysenter.o vsyscall.o
+ obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
++obj-$(CONFIG_X86_EMU486)	+= emu.o
+ obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
+ obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
+ obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+diff -urN kernel-source-2.6.6/arch/i386/kernel/emu.c kernel-source-2.6.6-1/arch/i386/kernel/emu.c
+--- kernel-source-2.6.6/arch/i386/kernel/emu.c	1970-01-01 10:00:00.000000000 +1000
++++ kernel-source-2.6.6-1/arch/i386/kernel/emu.c	2003-08-01 20:21:31.000000000 +1000
+@@ -0,0 +1,434 @@
++/*
++ *  linux/arch/i386/emu.c
++ *
++ *  Copyright (C) 2002  Willy Tarreau
++ */
++
++#include <linux/config.h>
++#include <linux/sched.h>
++#include <linux/linkage.h>
++#include <linux/preempt.h>
++#include <linux/ptrace.h>
++#include <linux/types.h>
++
++#include <asm/uaccess.h>
++#include <asm/segment.h>
++
++asmlinkage void do_general_protection(struct pt_regs *regs, long error_code);
++asmlinkage void do_invalid_op(struct pt_regs *regs, long error_code);
++
++/* gives the address of any register member in a struct pt_regs */
++static const int reg_ofs[8] = {
++	(int)&((struct pt_regs *)0)->eax,
++	(int)&((struct pt_regs *)0)->ecx,
++	(int)&((struct pt_regs *)0)->edx,
++	(int)&((struct pt_regs *)0)->ebx,
++	(int)&((struct pt_regs *)0)->esp,
++	(int)&((struct pt_regs *)0)->ebp,
++	(int)&((struct pt_regs *)0)->esi,
++	(int)&((struct pt_regs *)0)->edi
++};
++
++#define REG_PTR(regs, reg) ((unsigned long *)(((void *)(regs)) + reg_ofs[reg]))
++
++/* This code can be used to allow old 386's to hopefully correctly execute some
++ * code which was originally compiled for a 486, and to allow CMOV-disabled
++ * processors to emulate CMOV instructions. In user space, only 3 instructions
++ * have been added between the 386 the 486 :
++ *    - BSWAP reg		performs exactly htonl())
++ *    - CMPXCHG reg/mem, reg	used for mutex locking
++ *    - XADD reg/mem, reg	not encountered yet.
++ *
++ * Warning: this will NEVER allow a kernel compiled for a 486 to boot on a 386,
++ * neither will it allow a CMOV-optimized kernel to run on a processor without
++ * CMOV ! It will only help to port programs, or save you on a rescue disk, but
++ * for performance's sake, it's far better to recompile.
++ *
++ * Tests patterns have been submitted to this code on a 386, and it now seems
++ * OK. If you think you've found a bug, please report it to
++ * Willy Tarreau <willy at meta-x.org>.
++ */
++
++/* [modrm_address] returns a pointer to a user-space location by decoding the
++ * mod/rm byte and the bytes at <from>, which point to the mod/reg/rm byte.
++ * This must only be called if modrm indicates memory and not register. The
++ * <from> parameter is updated when bytes are read.
++ * NOTE: this code has some ugly lines, which produce a better assembler output
++ * than the "cleaner" version.
++ */
++static void *modrm_address(struct pt_regs *regs, u8 **from,
++                           int bit32, int modrm)
++{
++	u32 offset = 0;
++	u8 sib, mod, rm;
++
++	/* better optimization to compute them here, even
++	 * if rm is not always used
++	 */
++	rm = modrm & 7;
++	mod = modrm & 0xC0;
++
++	if (bit32) {  /* 32-bits addressing mode (default) */
++		if (mod == 0 && rm == 5) /* 32 bits offset and nothing more */
++			return (void *)*((u32*)*from)++;
++		
++		if (rm == 4) {
++			/* SIB byte is present and must be used */
++			sib = *(*from)++; /* SS(7-6) IDX(5-3) BASE(2-0) */
++
++			/* index * scale */
++			if (((sib >> 3) & 7) != 4)
++				offset += *REG_PTR(regs, (sib >> 3) & 7) << (sib >> 6);
++
++			rm = (sib & 7); /* base replaces rm from now */
++			if (mod == 0 && rm == 5) /* base off32 + scaled index */
++				return (void *)offset + *((u32*)*from)++;
++		}
++
++		/* base register */
++		offset += *REG_PTR(regs, rm);
++	
++		if (mod) {
++			if (mod & 0x80) /* 32 bits unsigned offset */
++				offset += *((u32*)*from)++;
++			else  /* 0x40: 8 bits signed offset */
++				offset += *((s8*)*from)++;
++		}
++
++		return (void *)offset;
++
++	} else { /* 16-bits addressing mode */
++		/* handle special case now */
++		if (mod == 0 && rm == 6) /* 16 bits offset */
++			return (void *)(u32)*((u16*)*from)++;
++
++		if ((rm & 4) == 0)
++			offset += (rm & 2) ? regs->ebp : regs->ebx;
++		if (rm < 6)
++			offset += (rm & 1) ? regs->edi : regs->esi;
++		else if (rm == 6)  /* bp */
++			offset += regs->ebp;
++		else if (rm == 7)  /* bx */
++			offset += regs->ebx;
++
++		/* now, let's include 8/16 bits offset */
++		if (mod) {
++			if (mod & 0x80) /* 16 bits unsigned offset */
++				offset += *((u16*)*from)++;
++			else  /* 0x40: 8 bits signed offset */
++				offset += *((s8*)*from)++;
++		}
++		return (void *)(offset & 0xFFFF);
++	}
++}
++
++
++/*
++ * skip_modrm() computes the EIP value of next instruction from the
++ * pointer <from> which points to the first byte after the mod/rm byte.
++ * Its purpose is to implement a fast alternative to modrm_address()
++ * when offset value is not needed.
++ */
++static inline void *skip_modrm(u8 *from, int bit32, int modrm)
++{
++    	u8 mod,rm;
++
++	/* better optimization to compute them here, even
++	 * if rm is not always used
++	 */
++	rm = modrm & 7;
++	mod = modrm & 0xC0;
++
++	/* most common case first : registers */
++	if (mod == 0xC0)
++		return from;
++
++	if (bit32) { /* 32 bits addressing mode (default) */
++		if (rm == 4)	/* SIB byte : rm becomes base */
++			rm = (*from++ & 7);
++		if (mod == 0x00) {
++			if (rm == 5)  /* 32 bits offset and nothing more */
++				return from + 4;
++			else
++				return from;
++		}
++	}
++	else { /* 16 bits mode */
++		if (mod == 0x00) {
++			if (rm == 6)  /* 16 bits offset and nothing more */
++				return from + 2;
++			else
++				return from;
++		}
++	}
++
++	if (mod & 0x80)
++		return from + (2 * (bit32 + 1)); /* + 2 or 4 bytes */
++	else
++		return from + 1;
++}
++
++
++/* [reg_address] returns a pointer to a register in the regs struct, depending
++ * on <w> (byte/word) and reg. Since the caller knows about <w>, it's
++ * responsible for understanding the result as a byte, word or dword pointer.
++ * Only the 3 lower bits of <reg> are meaningful, higher ones are ignored.
++ */
++static inline void *reg_address(struct pt_regs *regs, char w, u8 reg)
++{
++	if (w)
++		/* 16/32 bits mode */
++		return REG_PTR(regs, reg & 7);
++	else
++		/* 8 bits mode : al,cl,dl,bl,ah,ch,dh,bh */
++		return ((reg & 4) >> 2) + (u8*)REG_PTR(regs, reg & 3);
++
++	/* this is set just to prevent the compiler from complaining */
++	return NULL;
++}
++
++/* [do_emu] is called by exception 6 after an invalid opcode has been
++ * encountered. It will decode the prefixes and the instruction code, to try
++ * to emulate it, and will send a SIGILL or SIGSEGV to the process if not
++ * possible.
++ * REP/REPN prefixes are not supported anymore because it didn't make sense
++ * to emulate instructions prefixed with such opcodes since no arch-specific
++ * instruction start by one of them. At most, they will be the start of newer
++ * arch-specific instructions (SSE ?).
++ */
++asmlinkage void do_emu(struct pt_regs *regs, long error_code)
++{
++	enum {
++		PREFIX_ES   = 1,
++		PREFIX_CS   = 2,
++		PREFIX_SS   = 4,
++		PREFIX_DS   = 8,
++		PREFIX_FS   = 16,
++		PREFIX_GS   = 32,
++		PREFIX_SEG  = 63,  /* any seg */
++		PREFIX_D32  = 64,
++		PREFIX_A32  = 128,
++		PREFIX_LOCK = 256,
++	} prefixes = 0;
++
++	u32 *src, *dst;
++	u8 *eip;
++
++	preempt_disable();
++	eip = (u8*)regs->eip;
++
++#ifdef BENCH_CPU_EXCEPTION_BUT_NOT_THE_CODE
++	regs->eip += 3;
++	goto out;
++#endif
++	/* we'll first read all known opcode prefixes, and discard obviously
++	   invalid combinations.*/
++	while (1) {
++		/* prefix for CMOV, BSWAP, CMPXCHG, XADD */
++		if (*eip == 0x0F) {
++			eip++;
++
++			/* we'll verify if this is a BSWAP opcode, main source of SIGILL on 386's */
++			if ((*eip & 0xF8) == 0xC8) {  /* BSWAP */
++				u8 reg;
++
++				reg = *eip++ & 0x07;
++				src = reg_address(regs, 1, reg);
++				
++				__asm__ __volatile__ (
++						      "xchgb %%al, %%ah\n\t"
++						      "roll $16, %%eax\n\t"
++						      "xchgb %%al, %%ah\n\t"
++						      : "=a" (*(u32*)src)
++						      : "a" (*(u32*)src));
++				regs->eip = (u32)eip;
++				goto out;
++			}
++
++
++			/* we'll also try to emulate the CMPXCHG instruction (used in mutex locks).
++			   This instruction is often locked, but it's not possible to put a lock
++			   here. Anyway, I don't believe that there are lots of multiprocessors
++			   386 out there ...
++			*/
++			if ((*eip & 0xFE) == 0xB0) {  /* CMPXCHG */
++				u8 w, reg, modrm;
++
++				w = *eip & 1;
++				modrm = *(eip + 1);
++				eip += 2; /* skips all the opcodes */
++
++				reg = (modrm >> 3) & 7;
++				
++				dst = reg_address(regs, w, reg);
++				if ((modrm & 0xC0) == 0xC0) /* register to register */
++					src = reg_address(regs, w, modrm);
++				else {
++					src = modrm_address(regs, &eip, !(prefixes & PREFIX_A32), modrm);
++					/* we must verify that src is valid for this task */
++					if ((prefixes & (PREFIX_FS | PREFIX_GS)) ||
++					    verify_area(VERIFY_WRITE, (void *)src, (w?((prefixes & PREFIX_D32)?2:4):1))) {
++						do_general_protection(regs, error_code);
++					    goto out;
++					}
++				}
++				
++				if (!w) { /* 8 bits operands */
++					if ((u8)regs->eax == *(u8*)src) {
++						*(u8*)src = *(u8*)dst;
++						regs->eflags |= X86_EFLAGS_ZF;  /* set Zero Flag */
++					}
++					else {
++						*(u8*)&(regs->eax) = *(u8*)src;
++						regs->eflags &= ~X86_EFLAGS_ZF;  /* clear Zero Flag */
++					}
++				}
++				else if (!(prefixes & PREFIX_D32)) { /* 32 bits operands */
++					if ((u32)regs->eax == *(u32*)src) {
++						*(u32*)src = *(u32*)dst;
++						regs->eflags |= X86_EFLAGS_ZF;  /* set Zero Flag */
++					}
++					else {
++						regs->eax = *(u32*)src;
++						regs->eflags &= ~X86_EFLAGS_ZF;  /* clear Zero Flag */
++					}
++				}
++				else { /* 16 bits operands */
++					if ((u16)regs->eax == *(u16*)src) {
++						*(u16*)src = *(u16*)dst;
++						regs->eflags |= X86_EFLAGS_ZF;  /* set Zero Flag */
++					}
++					else {
++						*(u16*)&regs->eax = *(u16*)src;
++						regs->eflags &= ~X86_EFLAGS_ZF;  /* clear Zero Flag */
++					}
++				}
++				regs->eip = (u32)eip;
++				goto out;
++			}
++
++			/* we'll also try to emulate the XADD instruction (not very common) */
++			if ((*eip & 0xFE) == 0xC0) {  /* XADD */
++				u8 w, reg, modrm;
++				u32 op1, op2;
++
++				w = *eip & 1;
++				modrm = *(eip + 1);
++				eip += 2; /* skips all the opcodes */
++
++				reg = (modrm >> 3) & 7;
++				
++				dst = reg_address(regs, w, reg);
++				if ((modrm & 0xC0) == 0xC0) /* register to register */
++					src = reg_address(regs, w, modrm);
++				else {
++					src = modrm_address(regs, &eip, !(prefixes & PREFIX_A32), modrm);
++					/* we must verify that src is valid for this task */
++					if ((prefixes & (PREFIX_FS | PREFIX_GS)) ||
++					    verify_area(VERIFY_WRITE, (void *)src, (w?((prefixes & PREFIX_D32)?2:4):1))) {
++						do_general_protection(regs, error_code);
++						goto out;
++					}
++				}
++				
++				if (!w) { /* 8 bits operands */
++					op1 = *(u8*)src;
++					op2 = *(u8*)dst;
++					*(u8*)src = op1 + op2;
++					*(u8*)dst = op1;
++				}
++				else if (!(prefixes & PREFIX_D32)) { /* 32 bits operands */
++					op1 = *(u32*)src;
++					op2 = *(u32*)dst;
++					*(u32*)src = op1 + op2;
++					*(u32*)dst = op1;
++				}
++				else { /* 16 bits operands */
++					op1 = *(u16*)src;
++					op2 = *(u16*)dst;
++					*(u16*)src = op1 + op2;
++					*(u16*)dst = op1;
++				}
++				regs->eip = (u32)eip;
++				goto out;
++			}
++		} /* if (*eip == 0x0F) */
++		else if ((*eip & 0xfc) == 0x64) {
++			switch (*eip) {
++			case 0x66: /* Operand switches 16/32 bits */
++				if (prefixes & PREFIX_D32)
++					goto invalid_opcode;
++				prefixes |= PREFIX_D32;
++				eip++;
++				continue;
++			case 0x67: /* Address switches 16/32 bits */
++				if (prefixes & PREFIX_A32)
++					goto invalid_opcode;
++				prefixes |= PREFIX_A32;
++				eip++;
++				continue;
++			case 0x64: /* FS: */
++				if (prefixes & PREFIX_SEG)
++					goto invalid_opcode;
++				prefixes |= PREFIX_FS;
++				eip++;
++				continue;
++			case 0x65: /* GS: */
++				if (prefixes & PREFIX_SEG)
++					goto invalid_opcode;
++				prefixes |= PREFIX_GS;
++				eip++;
++				continue;
++			}
++		}
++		else if (*eip == 0xf0) { /* lock */
++			if (prefixes & PREFIX_LOCK)
++				goto invalid_opcode;
++			prefixes |= PREFIX_LOCK;
++				eip++;
++				continue;
++		}
++		else if ((*eip & 0xe7) == 0x26) {
++			switch (*eip) {
++			case 0x26: /* ES: */
++				if (prefixes & PREFIX_SEG)
++					goto invalid_opcode;
++				prefixes |= PREFIX_ES;
++				eip++;
++				continue;
++			case 0x2E: /* CS: */
++				if (prefixes & PREFIX_SEG)
++					goto invalid_opcode;
++				prefixes |= PREFIX_CS;
++				eip++;
++				continue;
++			case 0x36: /* SS: */
++				if (prefixes & PREFIX_SEG)
++					goto invalid_opcode;
++				prefixes |= PREFIX_SS;
++				eip++;
++				continue;
++			case 0x3E: /* DS: */
++				if (prefixes & PREFIX_SEG)
++					goto invalid_opcode;
++				prefixes |= PREFIX_DS;
++				eip++;
++				continue;
++			}
++		}
++		/* if this opcode has not been processed, it's not a prefix. */
++		break;
++	}
++
++	/* it's a case we can't handle. Unknown opcode or too many prefixes. */
++invalid_opcode:
++	preempt_enable();
++#ifdef CONFIG_CPU_EMU486_DEBUG
++	printk(KERN_DEBUG "do_emu() : invalid opcode detected @%p : %02x %02x ...\n", eip, eip[0], eip[1]);
++#endif
++	do_invalid_op(regs, error_code);
++	return;
++
++out:
++	preempt_enable();
++}
+diff -urN kernel-source-2.6.6/arch/i386/kernel/entry.S kernel-source-2.6.6-1/arch/i386/kernel/entry.S
+--- kernel-source-2.6.6/arch/i386/kernel/entry.S	2004-05-10 19:47:45.000000000 +1000
++++ kernel-source-2.6.6-1/arch/i386/kernel/entry.S	2004-05-10 22:21:09.000000000 +1000
+@@ -562,7 +562,11 @@
+ 
+ ENTRY(invalid_op)
+ 	pushl $0
++#ifdef CONFIG_X86_EMU486
++	pushl $do_emu
++#else
+ 	pushl $do_invalid_op
++#endif
+ 	jmp error_code
+ 
+ ENTRY(coprocessor_segment_overrun)

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/prune-non-free
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/prune-non-free	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/prune-non-free	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Scrubs known non-DFSG-compliant stuff out of the source tree so that a
+# DFSG-free .orig.tar.gz for the source package can be created.
+
+PROGNAME=${0##*/}
+
+if [ ! -d kernel ]; then
+    echo "$PROGNAME: no unpacked source tree in current working directory" >&2
+    exit 1
+fi
+
+grep -h '^X' debian/patches/series/2.6.* | while read x file; do
+    rm -f $file
+done
+
+# Upstream deletes our debian directory.  Bastards.
+sed -i 's#^.*/debian/$##' scripts/package/Makefile
+

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/rules
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/rules	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/rules	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,126 @@
+#!/usr/bin/make -f
+#
+# debian/rules for kernel-source.
+#
+# GNU copyright 1997 to 1999 by Joey Hess.
+# Copyright (c) 1999-2002 Herbert Xu <herbert at debian.org>
+# Copyright (c) 2004 Jens Schmalzing <jensen at debian.org>
+#
+
+release := $(shell dpkg-parsechangelog | awk '/^Version: / { print $$2 }')
+upstream := $(shell echo "$(release)" | sed 's/:\?\([0-9\.]\+\)-[0-9]*/\1/')
+patch_home := debian/kernel-patch-debian-$(upstream)/usr/src/kernel-patches/all/$(upstream)
+
+# Little things that help you...
+patch:
+	override_version=$(release) home=debian/patches sh debian/apply
+
+unpatch:
+	override_version=$(release) home=debian/patches sh debian/apply $(upstream)
+
+
+#####################
+# Below comes Herbert's stuff with minimal additions
+
+build:
+# Ye olde no-op.
+
+clean:
+	dh_testdir
+	dh_testroot
+
+# Hack in case we killed it in the middle of something
+ifneq (,$(wildcard version.Debian))
+ifneq ($(shell cat version.Debian),$(upstream))
+	override_version=$(release) home=debian/patches sh debian/apply $(upstream)
+endif
+endif
+
+	make-kpkg clean
+	rm -f stamp-* .config* version.Debian 
+
+	dh_clean
+
+install:
+	dh_testdir
+	dh_testroot
+	dh_clean -k
+	dh_installdirs
+
+debian/kernel-tree-$(upstream).substvars: debian/patches debian/make-substvars
+	sh debian/make-substvars $(upstream) > $@
+
+binary-kernel-patch:
+	mkdir -p $(patch_home) $(patch_home)/apply $(patch_home)/debian $(patch_home)/unpatch
+	cp debian/patches/*.dpatch $(patch_home)/debian
+	chmod -x $(patch_home)/debian/*.dpatch
+	mkdir -p $(patch_home)/debian/series
+	cp debian/patches/series/* $(patch_home)/debian/series/
+
+	sed 's/@version@/$(release)/' debian/apply > $(patch_home)/apply/debian
+	sed 's/@upstream@/$(upstream)/' debian/unpatch > $(patch_home)/unpatch/debian
+	chmod a+x $(patch_home)/apply/debian $(patch_home)/unpatch/debian
+	bzip2 -9 $(patch_home)/debian/*.dpatch
+
+	dh_installdocs -pkernel-patch-debian-$(upstream)
+	dh_installchangelogs -pkernel-patch-debian-$(upstream)
+	dh_compress -pkernel-patch-debian-$(upstream)
+	dh_installdeb -pkernel-patch-debian-$(upstream)
+	dh_gencontrol -pkernel-patch-debian-$(upstream)
+	dh_builddeb -pkernel-patch-debian-$(upstream)
+	
+# Build architecture-independent files here.
+binary-indep: install binary-kernel-patch debian/kernel-tree-$(upstream).substvars
+	dh_testdir
+	dh_testroot
+
+# Patch kernel with the Debian patch!
+	home=$(patch_home)/debian sh $(patch_home)/apply/debian
+	make-kpkg kernel-source
+
+# kernel-doc takes a LONG time, so build kernel-tree first for immediate use
+	dh_installdocs -pkernel-tree-$(upstream)
+	dh_installchangelogs -pkernel-tree-$(upstream)
+	dh_compress -pkernel-tree-$(upstream)
+	dh_installdeb -pkernel-tree-$(upstream)
+	dh_gencontrol -pkernel-tree-$(upstream)
+	dh_builddeb -pkernel-tree-$(upstream)
+	
+	make-kpkg kernel-doc
+# Clean up after yourself
+	home=$(patch_home)/debian sh $(patch_home)/apply/debian $(upstream)	
+
+# Build architecture-dependent files here.
+binary-arch:
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
+
+#####################
+# The following targets set the stage for building the Debian packages.
+# 
+# They unpack the vanilla kernel, remove the tainted bits, and package
+# everything again.  This produces both a free .orig.tar.gz in the
+# parent directory and an unpacked version plus the debian
+# subdirectory in the current directory.  In order to use these
+# targets, download the vanilla kernel as a gzipped tarball, put it
+# into the parent directory as linux-<release>.tar.gz, and run
+# 'debian/rules prune'.
+
+# phony target for easy reference
+.PHONY:	prune
+prune:	../kernel-source-$(upstream)_$(upstream).orig.tar.gz
+
+# prune the tainted bits from the vanilla kernel and package the result
+../kernel-source-$(upstream)_$(upstream).orig.tar.gz: debian/official
+	chmod u+x debian/prune-non-free
+	debian/prune-non-free
+	test $(notdir $(CURDIR)) = kernel-source-$(upstream)-$(upstream)
+	tar czCf .. $@ --exclude debian kernel-source-$(upstream)-$(upstream)
+
+# unpack the vanilla kernel from a tarball, move stuff over, and create a stamp file
+debian/official: ../linux-$(upstream).tar.bz2
+	tar xjCf .. $<
+	mv ../linux-$(upstream)/* .
+	rmdir ../linux-$(upstream)
+	echo This is the Debian version of Linux $(upstream). > $@


Property changes on: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/rules
___________________________________________________________________
Name: svn:executable
   + *

Added: tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/unpatch
===================================================================
--- tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/unpatch	2005-05-19 09:01:34 UTC (rev 3180)
+++ tags/kernel/i386/kernel-image-2.6.9-i386-2.6.9/2.6.9-3/debian/unpatch	2005-05-19 09:05:54 UTC (rev 3181)
@@ -0,0 +1,8 @@
+#!/bin/sh
+# $Id: unpatch,v 1.3 2003/06/30 12:49:09 herbert Exp $
+
+set -e
+
+upstream=${override_upstream:- at upstream@}
+
+/usr/src/kernel-patches/all/$upstream/apply/debian $upstream




More information about the Kernel-svn-changes mailing list