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, ®32);
++ 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, ®32);
++ 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,
++ ¤t_speed,
++ ¤t_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, ðtool_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, ¶ms, 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 = ðernet_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(ðernet_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(ðernet_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, ®s->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*)®s->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