diff -u --recursive --new-file v2.3.42/linux/CREDITS linux/CREDITS
--- v2.3.42/linux/CREDITS	Tue Feb  1 01:35:43 2000
+++ linux/CREDITS	Thu Feb 10 12:28:01 2000
@@ -24,6 +24,12 @@
 S: Iasi 6600
 S: Romania
 
+N: Monalisa Agrawal
+E: magrawal@nortelnetworks.com
+D: Basic Interphase 5575 driver with UBR and ABR support.
+S: 75 Donald St, Apt 42
+S: Weymouth, MA 02188
+
 N: Dave Airlie
 E: airlied@linux.ie
 W: http://www.csn.ul.ie/~airlied
@@ -38,11 +44,11 @@
 S: United Kingdom
 
 N: Werner Almesberger
-E: werner.almesberger@lrc.di.epfl.ch
-D: dosfs, LILO, some fd features, various other hacks here and there
+E: werner.almesberger@epfl.ch
+D: dosfs, LILO, some fd features, ATM, various other hacks here and there
 S: Ecole Polytechnique Federale de Lausanne
-S: DI-LRC
-S: INR (Ecublens)
+S: DSC ICA
+S: INN (Ecublens)
 S: CH-1015 Lausanne
 S: Switzerland
 
@@ -155,6 +161,14 @@
 S: Notre Dame, Indiana
 S: USA
 
+N: Greg Banks
+E: gnb@linuxfan.com
+D: IDT77105 ATM network driver
+S: NEC Australia
+S: 649-655 Springvale Rd
+S: Mulgrave, Victoria 3170
+S: Australia
+
 N: James Banks
 E: james@sovereign.org
 D: TLAN network driver
@@ -461,6 +475,13 @@
 S: NN1 3QT
 S: United Kingdom
 
+N: Uwe Dannowski
+E: Uwe.Dannowski@ira.uka.de
+W: http://i30www.ira.uka.de/~dannowsk/
+D: FORE PCA-200E driver
+S: University of Karlsruhe
+S: Germany
+
 N: Ray Dassen
 E: jdassen@wi.LeidenUniv.nl
 W: http://www.wi.leidenuniv.nl/~jdassen/
@@ -521,11 +542,11 @@
 S: Belgium
 
 N: Cort Dougan
-E: cort@ppc.kernel.org
+E: cort@fsmlabs.com
 W: http://www.ppc.kernel.org/~cort/
 D: PowerPC
-S: Computer Science Department
-S: New Mexico Tech
+S: Finite State Machine Labs
+S: P.O. 1829
 S: Socorro, New Mexico 87801
 S: USA
 
@@ -538,6 +559,20 @@
 S: Crimea
 S: UKRAINE, 334320
 
+N: Walt Drummond
+E: drummond@valinux.com
+D: Linux/IA-64
+S: 1382 Bordeaux Drive
+S: Sunnyvale, CA 94087
+S: USA
+
+N: Don Dugger
+E: n0ano@valinux.com
+D: Linux/IA-64
+S: 1209 Pearl Street, #12
+S: Boulder, CO 80302
+S: USA
+
 N: Thomas Dunbar
 E: tdunbar@vtaix.cc.vt.edu
 D: TeX & METAFONT hacking/maintenance
@@ -602,6 +637,13 @@
 S: S-114 53 Stockholm
 S: Sweden
 
+N: Stephane Eranian
+E: eranian@hpl.hp.com
+D: Linux/ia64
+S: 1501 Page Mill Rd, MS 1U17
+S: Palo Alto, CA 94304
+S: USA
+
 N: Paal-Kristian Engstad
 E: engstad@intermetrics.com
 D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
@@ -609,6 +651,13 @@
 S: Huntington Beach, California 92649
 S: USA
 
+N: Johannes Erdfelt
+E: jerdfelt@valinux.com
+D: Linux/IA-64 bootloader and kernel goop, USB
+S: 6350 Stoneridge Mall Road
+S: Pleasanton, CA 94588
+S: USA
+
 N: Doug Evans
 E: dje@cygnus.com
 D: Wrote Xenix FS (part of standard kernel since 0.99.15)
@@ -883,6 +932,7 @@
 E: benh@mipsys.com
 D: PowerMac booter (BootX)
 D: Additional PowerBook support
+D: Apple "Core99" machines support (ibook,g4,...)
 S: 22, rue des Marguettes
 S: 75012 Paris
 S: France
@@ -1123,6 +1173,13 @@
 S: TW9 1AE
 S: United Kingdom
 
+N: Marko Kiiskila
+E: marko@iprg.nokia.com
+D: Author of ATM Lan Emulation
+S: 660 Harvard Ave. #7
+S: Santa Clara, CA 95051
+S: USA
+
 N: Russell King
 E: rmk@arm.uk.linux.org
 D: Linux/arm integrator, maintainer & hacker
@@ -1321,6 +1378,15 @@
 S: (ask for current address)
 S: Germany
 
+N: Christophe Lizzi
+E: lizzi@cnam.fr
+W: http://cedric.cnam.fr/personne/lizzi
+D: FORE Systems 200E-series ATM network driver, sparc64 port of ATM
+S: CNAM, Laboratoire CEDRIC
+S: 292, rue St-Martin
+S: 75141 Paris Cedex 03
+S: France
+
 N: Siegfried "Frieder" Loeffler (dg1sek)
 E: floeff@tunix.mathematik.uni-stuttgart.de, fl@LF.net
 W: http://www.mathematik.uni-stuttgart.de/~floeff
@@ -1418,6 +1484,13 @@
 E: Kai.Makisara@metla.fi
 D: SCSI Tape Driver
 
+N: Asit Mallick
+E: asit.k.mallick@intel.com
+D: Linux/IA-64
+S: 2200 Mission College Blvd
+S: Santa Clara, CA 95052
+S: USA
+
 N: Martin Mares
 E: mj@atrey.karlin.mff.cuni.cz
 W: http://atrey.karlin.mff.cuni.cz/~mj/
@@ -1759,6 +1832,11 @@
 S: 13349 Berlin
 S: Germany
 
+N: Nicolas Pitre
+E: nico@cam.org
+D: StrongARM SA1100 support integrator & hacker
+S: Montreal, Quebec, Canada
+
 N: Emanuel Pirker
 E: epirker@edu.uni-klu.ac.at
 D: AIC5800 IEEE 1394, RAW I/O on 1394
@@ -1773,6 +1851,10 @@
 E: Frederic.Potter@masi.ibp.fr 
 D: Some PCI kernel support
 
+N: Rui Prior
+E: rprior@inescn.pt
+D: ATM device driver for NICStAR based cards
+
 N: Stefan Probst
 E: sp@caldera.de
 D: The Linux Support Team Erlangen, 1993-97
@@ -1799,6 +1881,13 @@
 S: 89020-350 Blumenau - Santa Catarina
 S: Brazil
 
+N: Goutham Rao
+E: goutham.rao@intel.com
+D: Linux/IA-64
+S: 2200 Mission College Blvd
+S: Santa Clara, CA 95052
+S: USA
+
 N: Eric S. Raymond
 E: esr@thyrsus.com
 W: http://www.tuxedo.org/~esr/
@@ -1893,11 +1982,10 @@
 D: the gpm mouse server and kernel support for it
 
 N: Philipp Rumpf
-E: prumpf@jcsbs.lanobis.de
-D: ipi_count for x86
+E: prumpf@tux.org
 D: random bugfixes
-S: Rueting 4
-S: 23743 Groemitz
+S: Drausnickstrasse 29
+S: 91052 Erlangen
 S: Germany
 
 N: Paul `Rusty' Russell
@@ -2053,6 +2141,15 @@
 S: Cliffwood, New Jersey 07721
 S: USA
 
+N: Manfred Spraul
+E: manfreds@colorfullife.com
+W: http://colorfullife.com/~manfreds
+D: major SysV IPC changes
+D: various bug fixes (mostly SMP code)
+S: Warburgring 67
+S: 66424 Homburg 
+S: Germany
+
 N: Henrik Storner
 E: storner@image.dk
 W: http://www.image.dk/~storner/
@@ -2348,6 +2445,13 @@
 S: Berkeley, CA 94720-1776
 S: USA
 
+N: Mike Westall
+D: IBM Turboways 25 ATM Device Driver
+E: westall@cs.clemson.edu
+S: Department of Computer Science
+S: Clemson University
+S: Clemson SC 29634 USA
+
 N: Greg Wettstein
 E: greg@wind.rmcc.com
 D: Filesystem valid flag for MINIX filesystem.
@@ -2509,6 +2613,20 @@
 S: 3078 Sulphur Spring Court
 S: San Jose, California 95148
 S: USA
+
+N: Alessandro Zummo
+E: azummo@ita.flashnet.it
+W: http://freepage.logicom.it/azummo/
+D: CMI8330 support is sb_card.c
+D: ISAPnP fixes in sb_card.c
+S: Italy
+
+N: Alessandro Zummo
+E: azummo@ita.flashnet.it
+W: http://freepage.logicom.it/azummo/
+D: CMI8330 support is sb_card.c
+D: ISAPnP fixes in sb_card.c
+S: Italy
 
 N: Marc Zyngier
 E: maz@wild-wind.fr.eu.org
diff -u --recursive --new-file v2.3.42/linux/Documentation/00-INDEX linux/Documentation/00-INDEX
--- v2.3.42/linux/Documentation/00-INDEX	Tue Dec  7 09:32:38 1999
+++ linux/Documentation/00-INDEX	Tue Feb  8 11:28:31 2000
@@ -23,8 +23,6 @@
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
 VGA-softcursor.txt
 	- how to change your VGA cursor from a blinking underscore.
-acpi.txt
-	- info on ACPI Driver Interface
 arm/
 	- directory with info about Linux on the ARM architecture.
 atm.txt
@@ -125,6 +123,8 @@
 	- info on the PCI subsystem for device driver authors
 pcwd-watchdog.txt
 	- info and sample code for using with the PC Watchdog reset card.
+pm.txt
+	- info on Linux power management support
 powerpc/
 	- directory with info on using Linux with the PowerPC.
 proc_usb_info.txt
diff -u --recursive --new-file v2.3.42/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.42/linux/Documentation/Configure.help	Tue Feb  1 01:35:43 2000
+++ linux/Documentation/Configure.help	Thu Feb 10 12:28:01 2000
@@ -557,6 +557,13 @@
 
   People with SCSI-only systems should say N here. If unsure, say Y.
 
+Cyrix CS5530 MediaGX chipset support
+CONFIG_BLK_DEV_CS5530
+  Include support for UDMA on the Cyrix MediaGX 5530 chipset. This
+  will automatically be detected and configured if found.
+
+  It is safe to say Y to this question.
+
 Generic PCI IDE chipset support
 CONFIG_BLK_DEV_IDEPCI
   Say Y here for PCI systems which use IDE drive(s).
@@ -583,7 +590,7 @@
   It is safe to say Y to this question.
 
 Good-Bad DMA Model-Firmware (EXPERIMENTAL)
-IDEDMA_NEW_DRIVE_LISTINGS
+CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
   If you say Y here, the model and firmware revision of your drive
   will be compared against a blacklist of buggy drives that claim to
   be (U)DMA capable but aren't. This is a blanket on/off test with no
@@ -711,12 +718,12 @@
   Please read the comments at the top of drivers/block/hpt366.c
 
 HPT366 Fast Interrupt support (EXPERIMENTAL) (WIP)
-HPT366_FAST_IRQ_PREDICTION
+CONFIG_HPT366_FAST_IRQ_PREDICTION
 
   If unsure, say N.
 
 HPT366 mode three unsupported (EXPERIMENTAL) (WIP)
-HPT366_MODE3
+CONFIG_HPT366_MODE3
   This is an undocumented mode that the HA366 can default to in many cases.
   If unsure, say N.
 
@@ -785,7 +792,7 @@
   If unsure, say N.
 
 Special UDMA Feature
-PDC202XX_FORCE_BURST_BIT
+CONFIG_PDC202XX_FORCE_BURST_BIT
   For PDC20246 and PDC20262 Ultra DMA chipsets. Designed originally
   for PDC20246/Ultra33 that has BIOS setup failures when using 3 or
   more cards.
@@ -795,7 +802,7 @@
   If unsure, say N.
 
 Special Mode Feature (EXPERIMENTAL)
-PDC202XX_FORCE_MASTER_MODE
+CONFIG_PDC202XX_FORCE_MASTER_MODE
   For PDC20246 and PDC20262 Ultra DMA chipsets. This is reserved for
   possible Hardware RAID 0,1 for the FastTrak Series.
 
@@ -2171,7 +2178,8 @@
 Acorn VIDC support
 CONFIG_FB_ACORN
   This is the frame buffer device driver for the Acorn VIDC graphics
-  chipset.
+  hardware found in Acorn RISC PCs and other ARM-based machines.  If
+  unsure, say N.
 
 Apollo frame buffer device
 CONFIG_FB_APOLLO
@@ -2212,6 +2220,13 @@
   kernel. Please note that this driver DOES NOT support the
   Cybervision 64 3D card, as they use incompatible video chips.
 
+CyberPro 20x0 support
+CONFIG_FB_CYBER2000
+  This enables support for the Integraphics CyberPro 20x0 and 5000
+  VGA chips used in the Rebel.com Netwinder and other machines.
+  Say Y if you have a NetWinder or a graphics card containing this
+  device, otherwise say N.
+
 Amiga CyberVision3D support (EXPERIMENTAL)
 CONFIG_FB_VIRGE
   This enables support for the Cybervision 64/3D graphics card from
@@ -2332,6 +2347,14 @@
   You will get a boot time penguin logo at no additional cost. Please
   read Documentation/fb/vesafb.txt. If unsure, say Y.
 
+VGA 16-color planar support
+CONFIG_FBCON_VGA_PLANES
+  This low level frame buffer console driver enable the kernel to use
+  the 16-color planar modes of the old VGA cards where the bits of each
+  pixel are separated into 4 plans.
+  Only answer Y here if you have an (very old) VGA card that isn't
+  VESA 2 compatible.
+
 VGA 16-color graphics console
 CONFIG_FB_VGA16
   This is the frame buffer device driver for VGA 16 color graphic
@@ -2342,6 +2365,25 @@
   running kernel whenever you want), say M here and read
   Documentation/modules.txt. The module will be called vga16fb.o.
 
+VGA 8x16 font
+CONFIG_FONT_8x16
+  This is the "high resolution" font for the VGA frame buffer (the one
+  provided by the text console 80x25 mode.
+
+Support only 8 pixels wide fonts
+CONFIG_FBCON_FONTWIDTH8_ONLY
+  Answer Y here will make the kernel provide only the 8x8 fonts (these
+  are the less readable).
+
+VGA 8x8 font
+CONFIG_FONT_8x8
+  This is the "high resolution" font for the VGA frame buffer (the one
+  provided by the text console 80x50 (and higher) modes.
+  Note this is a poor quality font. The VGA 8x16 font is quite a lot
+  more readable.
+  Given the resolution provided by the frame buffer device, anwser N
+  here is safe.
+
 Backward compatibility mode for Xpmac
 CONFIG_FB_COMPAT_XPMAC
   If you use the Xpmac X server (common with mklinux), you'll need to
@@ -2635,6 +2677,12 @@
   Ultra/AX machines. This code is also available as a module (say M),
   called parport_ax.o. If in doubt, saying N is the safe plan.
 
+Support IEEE1284 status readback
+CONFIG_PRINTER_READBACK
+  If you have a device on your parrallel port that support this protocol,
+  this option'll enable it to report its status.
+  It is safe to say Y.
+
 IEEE1284 transfer modes
 CONFIG_PARPORT_1284
   If you have a printer that supports status readback or device ID, or
@@ -3839,7 +3887,8 @@
   of your ATM card below.
 
   Note that you need a set of user-space programs to actually make use
-  of ATM. See the file Documentation/atm.txt for further details.
+  of ATM. See the file Documentation/networking/atm.txt for further
+  details.
 
 Classical IP over ATM
 CONFIG_ATM_CLIP
@@ -3981,12 +4030,30 @@
   overhead for timer synchronization and also per-packet overhead for
   time conversion.
 
-IDT 77201 (NICStAR)
+IDT 77201/11 (NICStAR) (ForeRunnerLE)
 CONFIG_ATM_NICSTAR
   The NICStAR chipset family is used in a large number of ATM NICs for
   25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE
   series.
 
+ForeRunner LE155 PHYsical layer
+CONFIG_ATM_NICSTAR_USE_SUNI
+  Support for the S-UNI and compatible PHYsical layer chips. These are
+  found in most 155Mbps NICStAR based ATM cards, namely in the
+  ForeRunner LE155 cards. This driver provides detection of cable
+  removal and reinsertion and provides some statistics. This driver
+  doesn't have removal capability when compiled as a module, so if you
+  need that capability don't include S-UNI support (it's not needed to
+  make the card work).
+
+ForeRunner LE25 PHYsical layer
+CONFIG_ATM_NICSTAR_USE_IDT77105
+  Support for the PHYsical layer chip in ForeRunner LE25 cards. In
+  addition to cable removal/reinsertion detection, this driver allows
+  you to control the loopback mode of the chip via a dedicated IOCTL.
+  This driver is required for proper handling of temporary carrier
+  loss, so if you have a 25Mbps NICStAR based ATM card you must say Y.
+
 Madge Ambassador (Collage PCI 155 Server)
 CONFIG_ATM_AMBASSADOR
   This is a driver for ATMizer based ATM card produced by Madge
@@ -4025,6 +4092,33 @@
   speed of the driver, and the size of your syslog files! When
   inactive, they will have only a modest impact on performance.
 
+Interphase ATM PCI x575/x525/x531 
+CONFIG_ATM_IA
+  This is a driver for the Interphase (i)ChipSAR adapter cards
+  which include a variety of variants in term of the size of the 
+  control memory (128K-1KVC, 512K-4KVC), the size of the packet 
+  memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3, 
+  UTP155, UTP25, DS3 and E3). Go to:
+  	www.iphase.com/products/ClassSheet.cfm?ClassID=ATM
+  for more info about the cards. Say Y (or M to compile as a module 
+  named iphase.o) here if you have one of these cards.
+
+  See the file Documentation/networking/iphase.txt for further
+  details.
+
+Enable debugging messages
+CONFIG_ATM_IA_DEBUG
+  Somewhat useful debugging messages are available. The choice of
+  messages is controlled by a bitmap. This may be specified as a
+  module argument (kernel command line argument as well?), changed
+  dynamically using an ioctl (Get the debug utility, iadbg, from 
+  ftp.iphase.com/pub/atm/pci). See the file drivers/atm/iphase.h 
+  for the meanings of the bits in the mask.
+
+  When active, these messages can have a significant impact on the
+  speed of the driver, and the size of your syslog files! When
+  inactive, they will have only a modest impact on performance.
+
 SCSI support?
 CONFIG_SCSI
   If you want to use a SCSI hard disk, SCSI tape drive, SCSI CDROM or
@@ -4067,6 +4161,18 @@
   on a SCSI disk. In this case, do not compile the driver for your
   SCSI host adapter (below) as a module either.
 
+Extra SCSI Disks
+CONFIG_SD_EXTRA_DEVS
+  This controls the amount of additional space allocated in tables for
+  drivers that are loaded as modules after the kernel is booted.  In
+  the event that the SCSI core itself was loaded as a module, this this
+  value is the number of additional disks that can be loaded after the
+  first host driver is loaded.
+
+  Admittedly this isn't pretty, but there are tons of race conditions
+  involved with resizing the internal arrays on the fly.  Someday this
+  flag will go away, and everything will work automatically.
+
 SCSI tape support
 CONFIG_CHR_DEV_ST
   If you want to use a SCSI tape drive under Linux, say Y and read the
@@ -4081,6 +4187,18 @@
   module, say M here and read Documentation/modules.txt and
   Documentation/scsi.txt .
 
+Extra SCSI Tapes
+CONFIG_ST_EXTRA_DEVS
+  This controls the amount of additional space allocated in tables for
+  drivers that are loaded as modules after the kernel is booted.  In the
+  event that the SCSI core itself was loaded as a module, this this value
+  is the number of additional tape devices that can be loaded after the
+  first host driver is loaded.
+
+  Admittedly this isn't pretty, but there are tons of race conditions
+  involved with resizing the internal arrays on the fly.  Someday this
+  flag will go away, and everything will work automatically.
+
 SCSI CDROM support
 CONFIG_BLK_DEV_SR
   If you want to use a SCSI CDROM under Linux, say Y and read the
@@ -4094,6 +4212,18 @@
   module, say M here and read Documentation/modules.txt and
   Documentation/scsi.txt .
 
+Extra SCSI CDROMs
+CONFIG_SR_EXTRA_DEVS
+  This controls the amount of additional space allocated in tables for
+  drivers that are loaded as modules after the kernel is booted.  In the
+  event that the SCSI core itself was loaded as a module, this this value
+  is the number of additional CDROMs that can be loaded after the first
+  host driver is loaded.
+
+  Admittedly this isn't pretty, but there are tons of race conditions
+  involved with resizing the internal arrays on the fly.  Someday this
+  flag will go away, and everything will work automatically.
+
 Enable vendor-specific extensions (for SCSI CDROM)
 CONFIG_BLK_DEV_SR_VENDOR
   This enables the usage of vendor specific SCSI commands. This is
@@ -7265,7 +7395,7 @@
   Documentation/networking/net-modules.txt.
 
 DECchip Tulip (dc21x4x) PCI support
-CONFIG_DEC_ELCP
+CONFIG_TULIP
   This driver is developed for the SMC EtherPower series Ethernet
   cards and also works with cards based on the DECchip
   21040/21041/21140 (Tulip series) chips. Some LinkSys PCI cards are
@@ -9398,9 +9528,9 @@
   from the Microsoft fat filesystem family or from JOLIET CDROMs
   correctly on the screen, you need to include the appropriate
   input/output character sets. Say Y here for the Latin 8 character
-  set, which adds the last accented vowels for Welsh (and Manx Gaelic)
-  that were missing in Latin 1. http://linux.speech.cymru.org/
-  has further information.
+  set, which adds the last accented vowels for Welsh (aka Cymraeg)
+  (and Manx Gaelic) hat were missing in Latin 1.
+  http://linux.speech.cymru.org/ has further information.
 
 nls iso8859-15
 CONFIG_NLS_ISO8859_15
@@ -10357,6 +10487,11 @@
 
   If unsure, say N.
 
+Enter S1 for sleep (EXPERIMENTAL)
+CONFIG_ACPI_S1_SLEEP
+  This enable ACPI compliant devices to enter level 1 of ACPI saving
+  power levels. Basically, this will let them entering in sleep mode.
+
 Advanced Power Management
 CONFIG_APM
   APM is a BIOS specification for saving power using several different
@@ -12958,7 +13093,84 @@
 
   If you do not have any Quicknet telephony cards, you can safely
   ignore this option.
- 
+
+/dev/agpgart (AGP Support) (EXPERIMENTAL)
+CONFIG_AGP
+  The agpgart kernel module is necessary to use the AGP features
+  of your 3D rendering video card.  It acts as a sort of "AGP
+  driver" for the motherboard's chipset.
+  Loading this module into the kernel will allow the glx module to
+  program the GART (graphics aperture relocation table) registers
+  with appropriate values to transfer commands to the card. 
+
+  If you need more texture memory than you can get with the AGP GART
+  (theoretically up to 256 megs, but in practice usually 64 or 128
+  megs due to kernel allocation issues), you could use PCI accesses
+  and have up to a couple gigs of texture space.
+
+  Note that this is the only meas to have get XFree4/GLX use
+  write-combining with MTRR support on AGP bus. Without, OpenGL
+  direct rendering will be a lot slower but still faster than PIO.
+
+  For the moment, most people should say no, unless you want to
+  test the GLX component which can be downloaded from
+       http://glx.on.openprojects.net/
+
+  or need to use the 810 Xserver in XFree 3.3.6
+
+Intel 440LX/BX/GX support
+CONFIG_AGP_INTEL
+  This option give you AGP support for the GLX component of the
+  "soon to be released" XFree86-4 on Intel 440LX/BX/GX chipsets.
+
+  For the moment, most people should say no, unless you want to
+  test the GLX component which can be downloaded from
+       http://glx.on.openprojects.net/
+
+Intel I810/I810 DC100/I810e support
+CONFIG_AGP_I810
+  This option give you AGP support for the Xserver for the intel
+  810 chipset boards. This is required to do any useful video
+  modes.
+
+VIA VP3/MVP3/Apollo Pro support
+CONFIG_AGP_VIA
+  This option give you AGP support for the GLX component of the
+  "soon to be released" XFree86-4 on VIA MPV3/Apollo Pro chipsets.
+
+  For the moment, most people should say no, unless you want to
+  test the GLX component which can be downloaded from
+       http://glx.on.openprojects.net/
+
+AMD Irongate support
+CONFIG_AGP_AMD
+  This option give you AGP support for the GLX component of the
+  "soon to be released" XFree86-4 on Intel AMD Irongate chipset.
+
+  For the moment, most people should say no, unless you want to
+  test the GLX component which can be downloaded from
+       http://glx.on.openprojects.net/
+
+Generic SiS support
+CONFIG_AGP_SIS
+  This option give you AGP support for the GLX component of the
+  "soon to be released" XFree86-4 on Silicon Integrated Systems [SiS]
+  chipsets.
+
+  Note than 5591/5592 AGP chipsets are NOT supported.
+
+  For the moment, most people should say no, unless you want to
+  test the GLX component which can be downloaded from
+       http://glx.on.openprojects.net/
+
+ALI M1541 support
+CONFIG_AGP_ALI
+  This option give you AGP support for the GLX component of the
+  "soon to be released" XFree86-4 on ALI M1541 chipset.
+
+  For the moment, most people should say no, unless you want to
+  test the GLX component which can be downloaded from
+       http://glx.on.openprojects.net/
 
 #
 # ARM options
@@ -13487,7 +13699,6 @@
   The kHTTPd is experimental. Be careful when using it on a production
   machine. Also note that kHTTPd doesn't support virtual servers yet.
 
-#
 I2C support
 CONFIG_I2C
   I2C (pronounce: I-square-C) is a slow bus protocol developed by
@@ -13540,6 +13751,7 @@
   files, usually found in the /dev directory on your system. They
   make it possible to have user-space programs use the I2C bus.
 
+#
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, 
 #               Intel, IRQ, Linux, MSDOS, NetWare, NetWinder, NFS, 
@@ -13801,4 +14013,4 @@
 # LocalWords:  adbmouse DRI DRM dlabs GMX PLCs Applicom fieldbus applicom int
 # LocalWords:  VWSND eg ESSSOLO CFU CFNR scribed eiconctrl eicon hylafax KFPU
 # LocalWords:  EXTRAPREC fpu mainboards KHTTPD kHTTPd khttpd Xcelerator
-# LocalWords:  LOGIBUSMOUSE OV511 ov511
+# LocalWords:  LOGIBUSMOUSE OV511 ov511 Integraphics
diff -u --recursive --new-file v2.3.42/linux/Documentation/acpi.txt linux/Documentation/acpi.txt
--- v2.3.42/linux/Documentation/acpi.txt	Thu Nov 11 20:11:30 1999
+++ linux/Documentation/acpi.txt	Wed Dec 31 16:00:00 1969
@@ -1,125 +0,0 @@
-ACPI Driver Interface
----------------------
-
-Overview:
-1) Register each instance of a device with "acpi_register"
-2) Call "acpi_access" before accessing the hardware.
-   (this will ensure that the hardware is awake and ready)
-3) "acpi_transition" callback is called before entering D1-D3
-   or after entering D0
-4) Call "acpi_dev_idle" when the device is not being used
-   (not required by will improve idle detection)
-5) When unloaded, unregister the device with "acpi_unregister"
-
-/*
- * Description: Register a device with the ACPI subsystem
- *
- * Parameters:
- *   info - static device information
- *     type - device type
- *     hid - PnP identifier (or 0 if unknown)
- *     trans - device state transition callback
- *   adr - bus number and address or unique id
- *
- * Returns: Registered ACPI device or NULL on error
- *
- * Details: The device type, bus number, and bus address should be
- *          enough information to reconstruct the device tree and
- *          identify device dependencies
- *
- * Examples:
- *   struct acpi_dev_info info = {ACPI_SYS_DEV, ACPI_VGA_HID, vga_trans};
- *   dev = acpi_register(&info, 0);
- *
- *   struct pci_dev *pci_dev = pci_find_dev(...);
- *   struct acpi_dev_info info = {ACPI_PCI_DEV, 0, trans};
- *   dev = acpi_register(&info, ACPI_PCI_ADR(pci_dev));
- */
-struct acpi_dev *acpi_register(struct acpi_dev_info *info, unsigned long adr);
-
-/*
- * Description: Unregister a device with ACPI
- *
- * Parameters:
- *   dev - ACPI device previously returned from acpi_register
- */
-void acpi_unregister(struct acpi_dev *dev);
-
-/*
- * Device idle/use detection
- *
- * In general, drivers for all devices should call "acpi_access"
- * before accessing the hardware (ie. before reading or modifying
- * a hardware register).  Request or packet-driven drivers should
- * additionally call "acpi_idle" when a device is not being used.
- *
- * Examples:
- * 1) A keyboard driver would call acpi_access whenever a key is pressed
- * 2) A network driver would call acpi_access before submitting
- *    a packet for transmit or receive and acpi_idle when its
- *    transfer and receive queues are empty.
- * 3) A VGA driver would call acpi_access before it accesses any
- *    of the video controller registers
- *
- * Ultimately, the ACPI policy manager uses the access and idle
- * information to decide when to transition devices between
- * device states.
- */
-
-/*
- * Description: Update device access time and wake up device, if necessary
- *
- * Parameters:
- *   dev - ACPI device previously returned from acpi_register
- *
- * Details: If called from an interrupt handler acpi_access updates
- *          access time but should never need to wake up the device
- *          (if device is generating interrupts, it should be awake
- *          already)  This is important as we can not wake up
- *          devices (run AML, etc.) from an interrupt handler.
- */
-void acpi_access(struct acpi_dev *dev);
-
-/*
- * Description: Identify device as currently being idle
- *
- * Parameters:
- *   dev - ACPI device previously returned from acpi_register
- *
- * Details: A call to acpi_idle might signal to the policy manager
- *          to put a device to sleep.  If a new device request arrives
- *          between the call to acpi_idle and the acpi_transition
- *          callback, the driver should fail the acpi_transition request.
- */
-void acpi_dev_idle(struct acpi_dev *dev);
-
-/*
- * Transition function
- *
- * Parameters:
- *   dev - ACPI device previously returned from acpi_register
- *   state - the device state being entered
- *
- * Returns: 0 if the state transition is possible and context saved
- *          EINVAL if the requested device state is not supported
- *          EBUSY if the device is now busy and can not transition
- *          ENOMEM if the device was unable to save context (out of memory)
- *          
- * Details: The device state transition function will be called
- *          before the device is transitioned into the D1-D3 states
- *          or after the device is transitioned into the D0 state.
- *          The device driver should save (D1-D3) or restore (D0)
- *          device context when the transition function is called.
- *
- *          For system devices, the ACPI subsystem will perform
- *          the actual hardware state transition itself.  For bus
- *          devices, after the driver's acpi_transition function
- *          is called, the bus driver's acpi_transition function
- *          is called to perform the actual hardware state transition.
- *
- *          Once a driver returns 0 (success) from a transition
- *          to D1-3 request, it should not process any further
- *          requests or access the device hardware until a
- *          call to "acpi_access" is made.
- */
-typedef int (*acpi_transition)(struct acpi_dev *dev, acpi_dstate_t state);
diff -u --recursive --new-file v2.3.42/linux/Documentation/arm/SA1100/Brutus linux/Documentation/arm/SA1100/Brutus
--- v2.3.42/linux/Documentation/arm/SA1100/Brutus	Fri Oct 22 13:21:43 1999
+++ linux/Documentation/arm/SA1100/Brutus	Sun Feb  6 17:45:25 2000
@@ -16,7 +16,8 @@
 0xc0008000 as well.
 
 But prior to execute the kernel, a ramdisk image must also be loaded in
-memory.  Use memory address 0x00800000 for this.
+memory.  Use memory address 0xd8000000 for this.  Note that the file 
+containing the (compressed) ramdisk image must not exceed 4 MB.
 
 Currently supported:
 	- RS232 serial ports
@@ -24,6 +25,10 @@
 	- LCD screen
 	- keyboard (needs to be cleaned up badly... any volunteer?)
 	
+The actual Brutus support may not be complete without extra patches. 
+If such patches exist, they should be found from 
+ftp.netwinder.org/users/n/nico.
+
 A full PCMCIA support is still missing, although it's possible to hack
 some drivers in order to drive already inserted cards at boot time with
 little modifications.
diff -u --recursive --new-file v2.3.42/linux/Documentation/arm/nwfpe/README linux/Documentation/arm/nwfpe/README
--- v2.3.42/linux/Documentation/arm/nwfpe/README	Fri Oct 22 13:21:43 1999
+++ linux/Documentation/arm/nwfpe/README	Sun Feb  6 17:45:25 2000
@@ -35,7 +35,7 @@
 remains to be done, and other ideas for the emulator.
 
 Bug reports, comments, suggestions should be directed to me at
-<scottb@netwinder.com>.  General reports of "this program doesn't
+<scottb@netwinder.org>.  General reports of "this program doesn't
 work correctly when your emulator is installed" are useful for
 determining that bugs still exist; but are virtually useless when
 attempting to isolate the problem.  Please report them, but don't
diff -u --recursive --new-file v2.3.42/linux/Documentation/atm.txt linux/Documentation/atm.txt
--- v2.3.42/linux/Documentation/atm.txt	Fri Sep 10 23:57:27 1999
+++ linux/Documentation/atm.txt	Wed Dec 31 16:00:00 1969
@@ -1,8 +0,0 @@
-In order to use anything but the most primitive functions of ATM,
-several user-mode programs are required to assist the kernel. These
-programs and related material can be found via the ATM on Linux Web
-page at http://icawww1.epfl.ch/linux-atm/
-
-If you encounter problems with ATM, please report them on the ATM
-on Linux mailing list. Subscription information, archives, etc.,
-can be found on http://icawww1.epfl.ch/linux-atm/
diff -u --recursive --new-file v2.3.42/linux/Documentation/filesystems/bfs.txt linux/Documentation/filesystems/bfs.txt
--- v2.3.42/linux/Documentation/filesystems/bfs.txt	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/filesystems/bfs.txt	Sun Feb  6 18:43:21 2000
@@ -1,13 +1,9 @@
-The BFS filesystem is used on SCO UnixWare machines for /stand slice.
-By default, if you attempt to mount it read-write it will be automatically
-mounted read-only. If you want to enable (limited) write support, you need
-to select "BFS write support" when configuring the kernel. The write support
-at this stage is limited to the blocks preallocated for a given inode.
-This means that writes beyond the value of inode->iu_eblock will fail with EIO.
-In particular, this means you can create empty files but not write data to them
-or you can write data to the existing files and increase their size but not the
-number of blocks allocated to them. I am currently working on removing this
-limitation, i.e. ability to migrate inodes within BFS filesystem.
+BFS FILESYSTEM FOR LINUX
+========================
+
+The BFS filesystem is used by SCO UnixWare OS for the /stand slice, which
+usually contains the kernel image and a few other files required for the
+boot process.
 
 In order to access /stand partition under Linux you obviously need to
 know the partition number and the kernel must support UnixWare disk slices
@@ -29,7 +25,9 @@
 # mount -t bfs -o loop stand.img /mnt/stand
 
 this will allocate the first available loopback device (and load loop.o 
-kernel module if necessary) automatically. Beware that umount will not
+kernel module if necessary) automatically. If the loopback driver is not
+loaded automatically, make sure that your kernel is compiled with kmod 
+support (CONFIG_KMOD) enabled. Beware that umount will not
 deallocate /dev/loopN device if /etc/mtab file on your system is a
 symbolic link to /proc/mounts. You will need to do it manually using
 "-d" switch of losetup(8). Read losetup(8) manpage for more info.
@@ -51,9 +49,9 @@
 
 # od -Ad -tx4 stand.img | more
 
-The first 4 bytes should be 0x1BADFACE.
+The first 4 bytes should be 0x1badface.
 
-If you have any questions or suggestions regarding this BFS implementation
-please contact me:
+If you have any patches, questions or suggestions regarding this BFS
+implementation please contact the author:
 
 Tigran A. Aivazian <tigran@ocston.org>.
diff -u --recursive --new-file v2.3.42/linux/Documentation/i2c/i2c-protocol linux/Documentation/i2c/i2c-protocol
--- v2.3.42/linux/Documentation/i2c/i2c-protocol	Mon Dec 20 18:48:21 1999
+++ linux/Documentation/i2c/i2c-protocol	Wed Feb  9 18:48:03 2000
@@ -44,3 +44,25 @@
 a byte read, followed by a byte write:
 
   S Addr Rd [A] [Data] NA S Addr Wr [A] Data [A] P
+
+
+Modified transactions
+=====================
+
+We have found some I2C devices that needs the following modifications:
+
+  Flag I2C_M_NOSTART: 
+    In a combined transaction, no 'S Addr' is generated at some point.
+    For example, setting I2C_M_NOSTART on the second partial message
+    generateds something like:
+      S Addr Rd [A] [Data] NA Wr [A] Data [A] P
+    If you set the I2C_M_NOSTART variable for the first partial message,
+    we do not generate Addr, but we do generate the startbit S. This will
+    probably confuse all other clients on your bus, so don't try this.
+
+  Flags I2C_M_REV_DIR_ADDR
+    This toggles the Rd/Wr flag. That is, if you want to do a write, but
+    need to emit an Rd instead of a Wr, or vice versa, you set this
+    flag. For example:
+      S Addr Rd [A] Data [A] Data [A] ... [A] Data [A] P
+                      
diff -u --recursive --new-file v2.3.42/linux/Documentation/ia64/README linux/Documentation/ia64/README
--- v2.3.42/linux/Documentation/ia64/README	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/ia64/README	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,76 @@
+        Linux kernel release 2.3.xx for the IA-64 Platform
+
+   These are the release notes for Linux version 2.3 for IA-64
+   platform.  This document provides information specific to IA-64
+   ONLY, to get additional information about the Linux kernel also
+   read the original Linux README provided with the kernel.
+ 
+INSTALLING the kernel:
+
+ - IA-64 kernel installation is the same as the other platforms, see
+   original README for details.
+   
+ 
+SOFTWARE REQUIREMENTS
+
+   Compiling and running this kernel requires an IA-64 compliant GCC
+   compiler.  And various software packages also compiled with an
+   IA-64 compliant GCC compiler.
+ 
+
+CONFIGURING the kernel:
+
+   Configuration is the same, see original README for details.
+  
+   
+COMPILING the kernel:
+
+ - Compiling this kernel doesn't differ from other platform so read
+   the original README for details BUT make sure you have an IA-64
+   compliant GCC compiler.
+ 
+IA-64 SPECIFICS
+
+ - Security related issues:
+ 
+    o mmap needs to check whether mapping would overlap with the
+      address-space hole in a region or whether the mapping would be
+      across regions.  In both cases, mmap should fail.
+ 
+    o ptrace is a huge security hole right now as it does not reject
+      writing to security sensitive bits (such as the PSR!).
+ 
+ - General issues:
+ 
+    o Kernel modules aren't supported yet.
+ 
+    o For non-RT signals, siginfo isn't passed through from the kernel
+      to the point where the signal is actually delivered.  Also, we
+      should make sure the siginfo data is compliant with the UNIX
+      ABI.
+ 
+    o Hardly any performance tuning has been done. Obvious targets
+      include the library routines (memcpy, IP checksum, etc.). Less
+      obvious targets include making sure we don't flush the TLB
+      needlessly, etc. Also, the TLB handlers should probably try to
+      do a speculative load from the virtually mapped linear page
+      table and only if that fails fall back on walking the page table
+      tree.
+	  
+    o Discontigous large memory support; memory above 4GB will be
+      discontigous since the 4GB-64MB is reserved for firmware and I/O
+      space.
+ 
+    o Correct mapping for PAL runtime code; PAL code needs to be
+      mapped by a TR.
+
+    o Make current IRQ/IOSAPIC handling closer to IA32 such as,
+      disable/enable interrupts, use of INPROGRESS flag etc.
+ 
+    o clone system call implementation; needs to setup proper backing
+      store
+ 
+    o SMP locks cleanup/optimization
+	
+    o IA32 support.  Currently experimental.  It mostly works but
+      there are problems with some dynamically loaded programs.
diff -u --recursive --new-file v2.3.42/linux/Documentation/networking/atm.txt linux/Documentation/networking/atm.txt
--- v2.3.42/linux/Documentation/networking/atm.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/atm.txt	Tue Feb  8 18:23:13 2000
@@ -0,0 +1,8 @@
+In order to use anything but the most primitive functions of ATM,
+several user-mode programs are required to assist the kernel. These
+programs and related material can be found via the ATM on Linux Web
+page at http://icawww1.epfl.ch/linux-atm/
+
+If you encounter problems with ATM, please report them on the ATM
+on Linux mailing list. Subscription information, archives, etc.,
+can be found on http://icawww1.epfl.ch/linux-atm/
diff -u --recursive --new-file v2.3.42/linux/Documentation/networking/decnet.txt linux/Documentation/networking/decnet.txt
--- v2.3.42/linux/Documentation/networking/decnet.txt	Tue Jan 11 22:31:36 2000
+++ linux/Documentation/networking/decnet.txt	Tue Feb  8 18:23:13 2000
@@ -27,8 +27,8 @@
     CONFIG_PROCFS (to see what's going on)
     CONFIG_SYSCTL (for easy configuration)
 
-if you want to try out router support (not properly debugged and not
-complete yet), you'll need the following options as well...
+if you want to try out router support (not properly debugged yet)
+you'll need the following options as well...
 
     CONFIG_DECNET_RAW (to receive routing packets)
     CONFIG_DECNET_ROUTER (to be able to add/delete routes)
@@ -39,26 +39,26 @@
 
 The kernel command line takes options looking like the following:
 
-    decnet=1,2,1
+    decnet=1,2
 
-the first two numbers are the node address 1,2 = 1.2 For 2.2.xx kernels
+the two numbers are the node address 1,2 = 1.2 For 2.2.xx kernels
 and early 2.3.xx kernels, you must use a comma when specifying the
 DECnet address like this. For more recent 2.3.xx kernels, you may
 use almost charecter except space, although a `.` would be the most
 obvious choice :-)
 
-The third number is the level number for routers and is optional. In fact
-this option may go away shortly in favour if settings for each interface
-seperately. It is probably a good idea to set the DECnet address and type
-on boot like this rather than trying to do it later.
+There used to be a third number specifying the node type. This option
+has gone away in favour of a per interface node type. This is now set
+using /proc/sys/net/decnet/conf/<dev>/forwarding. This file can be
+set with a single digit, 0=EndNode, 1=L1 Router and  2=L2 Router.
 
-There are also equivalent options for modules. The node address and type can
+There are also equivalent options for modules. The node address can
 also be set through the /proc/sys/net/decnet/ files, as can other system
 parameters.
 
-Currently the only supported device is ethernet. You'll have to set the
-ethernet address of your ethernet card according to the DECnet address
-of the node in order for it to be recognised (and thus appear in
+Currently the only supported devices are ethernet and ip_gre. The
+ethernet address of your ethernet card has to be set according to the DECnet
+address of the node in order for it to be recognised (and thus appear in
 /proc/net/decnet_dev). There is a utility available at the above
 FTP sites called dn2ethaddr which can compute the correct ethernet
 address to use. The address can be set by ifconfig either before at
@@ -101,7 +101,8 @@
 kernel subsystem is working.
 
    - Is the node address set (see /proc/sys/net/decnet/node_address)
-   - Is the node of the correct type (see /proc/sys/net/decnet/node_type)
+   - Is the node of the correct type 
+                             (see /proc/sys/net/decnet/conf/<dev>/forwarding)
    - Is the Ethernet MAC address of each Ethernet card set to match
      the DECnet address. If in doubt use the dn2ethaddr utility available
      at the ftp archive.
diff -u --recursive --new-file v2.3.42/linux/Documentation/networking/iphase.txt linux/Documentation/networking/iphase.txt
--- v2.3.42/linux/Documentation/networking/iphase.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/iphase.txt	Tue Feb  8 18:23:13 2000
@@ -0,0 +1,158 @@
+
+                              READ ME FISRT
+		  ATM (i)Chip IA Linux Driver Source
+--------------------------------------------------------------------------------
+                     Read This Before You Begin!
+--------------------------------------------------------------------------------
+
+Description
+-----------
+
+This is the README file for the Interphase PCI ATM (i)Chip IA Linux driver 
+source release.
+
+The features and limitations of this driver are as follows:
+    - A single VPI (VPI value of 0) is supported.
+    - Supports 4K VCs for the server board (with 512K control memory) and 1K 
+      VCs for the client board (with 128K control memory).
+    - UBR, ABR and CBR service categories are supported.
+    - Only AAL5 is supported. 
+    - Supports setting of PCR on the VCs. 
+    - Multiple adapters in a system are supported.
+    - All variants of Interphase ATM PCI (i)Chip adapter cards are supported, 
+      including x575 (OC3, control memory 128K , 512K and packet memory 128K, 
+      512K and 1M), x525 (UTP25) and x531 (DS3 and E3). See 
+           http://www.iphase.com/products/ClassSheet.cfm?ClassID=ATM 
+      for details.
+    - Only x86 platforms are supported.
+    - SMP is supported.
+
+
+Before You Start
+---------------- 
+
+
+Installation
+------------
+
+1. Installing the adapters in the system
+   To install the ATM adapters in the system, follow the steps below.
+       a. Login as root.
+       b. Shut down the system and power off the system.
+       c. Install one or more ATM adapters in the system.
+       d. Connect each adapter to a port on an ATM switch. The green 'Link' 
+          LED on the front panel of the adapter will be on if the adapter is 
+          connected to the switch properly when the system is powered up.
+       e. Power on and boot the system.
+
+2. [ Removed ]
+
+3. Rebuild kernel with ABR support
+   [ a. and b. removed ]
+    c. Reconfigure the kernel, choose the Interphase ia driver through "make 
+       menuconfig" or "make xconfig".
+    d. Rebuild the kernel, loadable modules and the atm tools. 
+    e. Install the new built kernel and modules and reboot.
+
+4. Load the adapter hardware driver (ia driver) if it is built as a module
+       a. Login as root.
+       b. Change directory to /lib/modules/<kernel-version>/atm.
+       c. Run "insmod suni.o;insmod iphase.o"
+	  The yellow 'status' LED on the front panel of the adapter will blink 
+          while the driver is loaded in the system.
+       d. To verify that the 'ia' driver is loaded successfully, run the 
+          following command:
+
+              cat /proc/atm/devices
+
+          If the driver is loaded successfully, the output of the command will 
+          be similar to the following lines:
+
+              Itf Type    ESI/"MAC"addr AAL(TX,err,RX,err,drop) ...
+              0   ia      xxxxxxxxx  0 ( 0 0 0 0 0 )  5 ( 0 0 0 0 0 )
+
+          You can also check the system log file /var/log/messages for messages
+          related to the ATM driver.
+
+5. Ia Driver Configuration 
+
+5.1 Configuration of adapter buffers
+    The (i)Chip boards have 3 different packet RAM size variants: 128K, 512K and
+    1M. The RAM size decides the number of buffers and buffer size. The default 
+    size and number of buffers are set as following: 
+
+          Totol    Rx RAM   Tx RAM   Rx Buf   Tx Buf   Rx buf   Tx buf
+         RAM size   size     size     size     size      cnt      cnt
+         --------  ------   ------   ------   ------   ------   ------
+           128K      64K      64K      10K      10K       6        6
+           512K     256K     256K      10K      10K      25       25
+             1M     512K     512K      10K      10K      51       51
+
+       These setting should work well in most environments, but can be
+       changed by typing the following command: 
+ 
+           insmod <IA_DIR>/ia.o IA_RX_BUF=<RX_CNT> IA_RX_BUF_SZ=<RX_SIZE> \
+                   IA_TX_BUF=<TX_CNT> IA_TX_BUF_SZ=<TX_SIZE> 
+       Where:
+            RX_CNT = number of receive buffers in the range (1-128)
+            RX_SIZE = size of receive buffers in the range (48-64K)
+            TX_CNT = number of transmit buffers in the range (1-128)
+            TX_SIZE = size of transmit buffers in the range (48-64K)
+
+            1. Transmit and receive buffer size must be a multiple of 4.
+            2. Care should be taken so that the memory required for the
+               transmit and receive buffers is less than or equal to the
+               total adapter packet memory.   
+
+5.2 Turn on ia debug trace
+
+    When the ia driver is built with the CONFIG_ATM_IA_DEBUG flag, the driver 
+    can provide more debug trace if needed. There is a bit mask variable, 
+    IADebugFlag, which controls the output of the traces. You can find the bit 
+    map of the IADebugFlag in iphase.h. 
+    The debug trace can be turn on through the insmod command line option, for 
+    example, "insmod iphase.o IADebugFlag=0xffffffff" can turn on all the debug 
+    traces together with loading the driver.
+
+6. Ia Driver Test Using ttcp_atm and PVC
+
+   For the PVC setup, the test machines can either be connected back-to-back or 
+   through a switch. If connected through the switch, the switch must be 
+   configured for the PVC(s).
+
+   a. For UBR test:
+      At the test machine intended to receive data, type:
+         ttcp_atm -r -a -s 0.100 
+      At the other test machine, type:
+         ttcp_atm -t -a -s 0.100 -n 10000
+      Run "ttcp_atm -h" to display more options of the ttcp_atm tool.
+   b. For ABR test:
+      It is the same as the UBR testing, but with an extra command option:
+         -Pabr:max_pcr=<xxx>
+         where:
+             xxx = the maximum peak cell rate, from 170 - 353207.
+         This option must be set on both the machines.
+   c. For CBR test:
+      It is the same as the UBR testing, but with an extra command option:
+         -Pcbr:max_pcr=<xxx>
+         where:
+             xxx = the maximum peak cell rate, from 170 - 353207.
+         This option may only be set on the trasmit machine.
+
+
+OUTSTANDING ISSUES
+------------------
+
+
+
+Contact Information
+-------------------
+
+     Customer Support:
+         United States:	Telephone:	(214) 654-5555
+     			Fax:		(214) 654-5500
+			E-Mail:		intouch@iphase.com
+	 Europe:	Telephone:	33 (0)1 41 15 44 00
+			Fax:		33 (0)1 41 15 12 13
+     World Wide Web:	http://www.iphase.com
+     Anonymous FTP:	ftp.iphase.com
diff -u --recursive --new-file v2.3.42/linux/Documentation/networking/tlan.txt linux/Documentation/networking/tlan.txt
--- v2.3.42/linux/Documentation/networking/tlan.txt	Tue Dec  7 09:32:38 1999
+++ linux/Documentation/networking/tlan.txt	Mon Feb  7 09:53:20 2000
@@ -1,25 +1,8 @@
+(C) 1997-1998 Caldera, Inc.
+(C) 1998 James Banks
+(C) 1999-2000 Torben Mathiasen <torben.mathiasen@compaq.com>
 
-
-I haven't had any time to do anything for a long time, and this isn't
-likely to change.  So there's a driver here for anyone looking to
-carry forward a project :)
-
-For those who are looking for help, I can't.  I haven't looked at
-a kernel since the early 2.0 series, so I won't know what's going on.
-Your best chance at help would be joining the TLAN mailing list and
-posting your question there.
-
-You can join by sending "subscribe tlan" in the body of an email to
-majordomo@vuser.vu.union.edu.
-
-Thanks to those who have (and who will ;) put work in to keep the TLAN
-driver working as the kernel moves on.
-
-James
-james@sovereign.org
-
-
-TLAN driver for Linux, version 1.0
+TLAN driver for Linux, version 1.3
 README
 
 
@@ -57,43 +40,7 @@
     but I do not expect any problems.
     
 
-II.  Building the Driver.
-
-    The TLAN driver may be compiled into the kernel, or it may be compiled
-    as a module separately, or in the kernel.  A patch is included for
-    2.0.29 (which also works for 2.0.30, 2.0.31, and 2.0.32).
-
-    To compile it as part of the kernel:
-        1. Download and untar the TLAN driver package.
-	2. If your kernel is 2.1.45 or later, you do not need to patch the
-           kernel sources.  Copy the tlan.c and tlan.h to drivers/net in
-           the kernel source tree.
-        3. Otherwise, apply the appropriate patch for your kernel.  For
-	   example:
-
-	       cd /usr/src/linux
-               patch -p1 < kernel.2.0.29
-
-        4. Copy the files tlan.c and tlan.h from the TLAN package to the
-           directory drivers/net in the Linux kernel source tree.
-        5. Configure your kernel for the TLAN driver.  Answer 'Y' when
-           prompted to ask about experimental code (the first question).
-           Then answer 'Y' when prompted if to include TI ThunderLAN
-           support.  If you want the driver compiled as a module, answer 'M'
-           instead of 'Y'.
-        6. Make the kernel and, if necessary, the modules.
-    
-    To compile the TLAN driver independently:
-        1. Download and untar the TLAN driver package.
-        2. Change to the tlan directory.
-        3. If you are NOT using a versioned kernel (ie, want an non-
-           versioned module), edit the Makefile, and comment out the
-           line:
-                 MODVERSIONS = -DMODVERSIONS
-        4. Run 'make'.
-
-
-III.  Driver Options
+II.   Driver Options
 	1. You can append debug=x to the end of the insmod line to get
            debug messages, where x is a bit field where the bits mean
 	   the following:
@@ -110,18 +57,20 @@
 	   device that does not have an AUI/BNC connector will probably
 	   cause it to not function correctly.)
 
-	4. You can set duplex=1 to force half duplex, and duplex=2 to
+	3. You can set duplex=1 to force half duplex, and duplex=2 to
 	   force full duplex.
 
-	5. You can set speed=10 to force 10Mbs operation, and speed=100Mbs
+	4. You can set speed=10 to force 10Mbs operation, and speed=100
 	   to force 100Mbs operation. (I'm not sure what will happen
 	   if a card which only supports 10Mbs is forced into 100Mbs
 	   mode.)
 
-	3. If the driver is built into the kernel, you can use the 3rd
+	5. If the driver is built into the kernel, you can use the 3rd
 	   and 4th parameters to set aui and debug respectively.  For
 	   example:
 
+/* kernel-parameters are currently not supported. I will fix this asap. */
+
 	   ether=0,0,0x1,0x7,eth0
 
 	   This sets aui to 0x1 and debug to 0x7, assuming eth0 is a
@@ -130,19 +79,17 @@
 	   The bits in the third byte are assigned as follows:
 
 		0x01 = aui
-		0x02 = use SA_INTERRUPT flag when reserving the irq.
 		0x04 = use half duplex
 		0x08 = use full duplex
 		0x10 = use 10BaseT
 		0x20 = use 100BaseTx
 
 
-IV.  Things to try if you have problems.
+III.  Things to try if you have problems.
 	1. Make sure your card's PCI id is among those listed in
 	   section I, above.
-	1. Make sure routing is correct.
-	2. If you are using a 2.1.x kernel, try to duplicate the
-	   problem on a 2.0.x (preferably 2.0.29 or 2.0.30) kernel.
+	2. Make sure routing is correct.
+	3. Try forcing different speed/duplex settings
 
 
 There is also a tlan mailing list which you can join by sending "subscribe tlan"
diff -u --recursive --new-file v2.3.42/linux/Documentation/pci.txt linux/Documentation/pci.txt
--- v2.3.42/linux/Documentation/pci.txt	Thu Jan  6 12:57:47 2000
+++ linux/Documentation/pci.txt	Mon Feb  7 12:13:07 2000
@@ -1,52 +1,130 @@
-		       Few Notes About The PCI Subsystem
+			 How To Write Linux PCI Drivers
 
-				       or
-
-		"What should you avoid when writing PCI drivers"
-
-		  by Martin Mares <mj@suse.cz> on 21-Nov-1999
+		  by Martin Mares <mj@suse.cz> on 07-Feb-2000
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The world of PCI is vast and it's full of (mostly unpleasant) surprises.
+Different PCI devices have different requirements and different bugs --
+because of this, the PCI support layer in Linux kernel is not as trivial
+as one would wish. This short pamphlet tries to help all potential driver
+authors to find their way through the deep forests of PCI handling.
+
 
 0. Structure of PCI drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   Aa typical PCI device driver needs to perform the following actions:
+There exist two kinds of PCI drivers: new-style ones (which leave most of
+probing for devices to the PCI layer and support online insertion and removal
+of devices [thus supporting PCI, hot-pluggable PCI and CardBus in single
+driver]) and old-style ones which just do all the probing themselves. Unless
+you have a very good reason to do so, please don't use the old way of probing
+in any new code. After the driver finds the devices it wishes to operate
+on (either the old or the new way), it needs to perform the following steps:
+
+	Enable the device
+	Access device configuration space
+	Discover resources (addresses and IRQ numbers) provided by the device
+	Allocate these resources
+	Communicate with the device
+
+Most of these topics are covered by the following sections, for the rest
+look at <linux/pci.h>, it's hopefully well commented.
+
+If the PCI subsystem is not configured (CONFIG_PCI is not set), most of
+the functions described below are defined as inline functions either completely
+empty or just returning an appropriate error codes to avoid lots of ifdefs
+in the drivers.
+
+
+1. New-style drivers
+~~~~~~~~~~~~~~~~~~~~
+The new-style drivers just call pci_register_driver during their initialization
+with a pointer to a structure describing the driver (struct pci_driver) which
+contains:
+
+	name		Name of the driver
+	id_table	Pointer to table of device ID's the driver is
+			interested in
+	probe		Pointer to a probing function which gets called (during
+			execution of pci_register_driver for already existing
+			devices or later if a new device gets inserted) for all
+			PCI devices which match the ID table and are not handled
+			by the other drivers yet. This function gets passed a pointer
+			to the pci_dev structure representing the device and also
+			which entry in the ID table did the device match. It returns
+			zero when the driver has accepted the device or an error
+			code (negative number) otherwise. This function always gets
+			called from process context, so it can sleep.
+	remove		Pointer to a function which gets called whenever a device
+			being handled by this driver is removed (either during
+			deregistration of the driver or when it's manually pulled
+			out of a hot-pluggable slot). This function can be called
+			from interrupt context.
+	suspend,	Power management hooks (currently used only for CardBus
+	resume		cards) -- called when the device goes to sleep or is
+			resumed.
+
+The ID table is an array of struct pci_device_id ending with a all-zero entry.
+Each entry consists of:
+
+	vendor, device	Vendor and device ID to match (or PCI_ANY_ID)
+	subvendor,	Subsystem vendor and device ID to match (or PCI_ANY_ID)
+	subdevice
+	class,		Device class to match. The class_mask tells which bits
+	class_mask	of the class are honored during the comparison.
+	driver_data	Data private to the driver.
+
+When the driver exits, it just calls pci_deregister_driver() and the PCI layer
+automatically calls the remove hook for all devices handled by the driver.
+
+Please mark the initialization and cleanup functions where appropriate
+(the corresponding macros are defined in <linux/init.h>):
+
+	__init		Initialization code. Thrown away after the driver
+			initializes.
+	__exit		Exit code. Ignored for non-modular drivers.
+	__devinit	Device initialization code. Identical to __init if
+			the kernel is not compiled with CONFIG_HOTPLUG, normal
+			function otherwise.
+	__devexit	The same for __exit.
+
+
+2. How to find PCI devices manually (the old style)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+PCI drivers not using the pci_register_driver() interface search
+for PCI devices manually using the following constructs:
+
+Searching by vendor and device ID:
+
+	struct pci_dev *dev = NULL;
+	while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev))
+		configure_device(dev);
+
+Searching by class ID (iterate in a similar way):
 
-	1. Find PCI devices it's able to handle
-	2. Enable them
-	3. Access their configuration space
-	4. Discover addresses and IRQ numbers
-
-1. How to find PCI devices
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-   In case your driver wants to search for all devices with given vendor/device
-ID, it should use:
-
-		struct pci_dev *dev = NULL;
-		while (dev = pci_find_device(VENDOR_ID, DEVICE_ID, dev))
-			configure_device(dev);
+	pci_find_class(CLASS_ID, dev)
 
-   For class-based search, use pci_find_class(CLASS_ID, dev).
+Searching by both vendor/device and subsystem vendor/device ID:
 
-   If you need to match by subsystem vendor/device ID, use
-pci_find_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
+	pci_find_subsys(VENDOR_ID, DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev).
 
    You can use the constant PCI_ANY_ID as a wildcard replacement for
 VENDOR_ID or DEVICE_ID.  This allows searching for any device from a
 specific vendor, for example.
 
-   In case you want to do some complex matching, you can walk the list of all
-known PCI devices:
+   In case you need to decide according to some more complex criteria,
+you can walk the list of all known PCI devices yourself:
 
-		struct pci_dev *dev;
-		pci_for_each_dev(dev) {
-			... do anything you want with dev ...
-		}
+	struct pci_dev *dev;
+	pci_for_each_dev(dev) {
+		... do anything you want with dev ...
+	}
 
-   The `struct pci_dev *' pointer serves as an identification of a PCI device
-and is passed to all other functions operating on PCI devices.
+For compatibility with device ordering in older kernels, you can also
+use pci_for_each_dev_reverse(dev) for walking the list in the opposite
+direction.
 
-2. Enabling devices
+
+3. Enabling devices
 ~~~~~~~~~~~~~~~~~~~
    Before you do anything with the device you've found, you need to enable
 it by calling pci_enable_device() which enables I/O and memory regions of
@@ -57,7 +135,8 @@
 which enables the bus master bit in PCI_COMMAND register and also fixes
 the latency timer value if it's set to something bogus by the BIOS.
 
-3. How to access PCI config space
+
+4. How to access PCI config space
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    You can use pci_(read|write)_config_(byte|word|dword) to access the config
 space of a device represented by struct pci_dev *. All these functions return 0
@@ -72,7 +151,8 @@
 pci_find_capability() for the particular capability and it will find the
 corresponding register block for you.
 
-4. Addresses and interrupts
+
+5. Addresses and interrupts
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Memory and port addresses and interrupt numbers should NOT be read from the
 config space. You should use the values in the pci_dev structure as they might
@@ -86,13 +166,33 @@
    All interrupt handlers should be registered with SA_SHIRQ and use the devid
 to map IRQs to devices (remember that all PCI interrupts are shared).
 
-5. Other interesting functions
+
+6. Other interesting functions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 pci_find_slot()			Find pci_dev corresponding to given bus and
 				slot numbers.
 pci_set_power_state()		Set PCI Power Management state (0=D0 ... 3=D3)
+pci_find_capability()		Find specified capability in device's capability
+				list.
+
+
+7. Miscellaneous hints
+~~~~~~~~~~~~~~~~~~~~~~
+When displaying PCI slot names to the user (for example when a driver wants
+to tell the user what card has it found), please use pci_dev->slot_name
+for this purpose.
+
+Always refer to the PCI devices by a pointer to the pci_dev structure.
+All PCI layer functions use this identification and it's the only
+reasonable one. Don't use bus/slot/function numbers except for very
+special purposes -- on systems with multiple primary buses their semantics
+can be pretty complex.
+
+If you're going to use PCI bus mastering DMA, take a look at
+Documentation/DMA-mapping.txt.
+
 
-6. Obsolete functions
+8. Obsolete functions
 ~~~~~~~~~~~~~~~~~~~~~
 There are several functions kept only for compatibility with old drivers
 not updated to the new PCI interface. Please don't use them in new code.
diff -u --recursive --new-file v2.3.42/linux/Documentation/pm.txt linux/Documentation/pm.txt
--- v2.3.42/linux/Documentation/pm.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/pm.txt	Tue Feb  8 11:28:31 2000
@@ -0,0 +1,166 @@
+               Linux Power Management Support
+
+This document briefly describes how to use power management with your
+Linux system and how to add power management support to Linux drivers.
+
+APM or ACPI?
+------------
+If you have a relatively recent x86 mobile, desktop, or server system,
+odds are it supports either Advanced Power Management (APM) or
+Advanced Configuration and Power Interface (ACPI).  ACPI is the newer
+of the two technologies and puts power management in the hands of the
+operating system, allowing for more intelligent power management than
+is possible with BIOS controlled APM.
+
+The best way to determine which, if either, your system supports is to
+build a kernel with both ACPI and APM enabled (as of 2.3.x ACPI is
+enabled by default).  If a working ACPI implementation is found, the
+ACPI driver will override and disable APM, otherwise the APM driver
+will be used.
+
+No sorry, you can not have both ACPI and APM enabled and running at
+once.  Some people with broken ACPI or broken APM implementations
+would like to use both to get a full set of working features, but you
+simply can not mix and match the two.  Only one power management
+interface can be in control of the machine at once.  Think about it..
+
+User-space Daemons
+------------------
+Both APM and ACPI rely on user-space daemons, apmd and acpid
+respectively, to be completely functional.  Obtain both of these
+daemons from your Linux distribution or from the Internet (see below)
+and be sure that they are started sometime in the system boot process.
+Go ahead and start both.  If ACPI or APM is not available on your
+system the associated daemon will exit gracefully.
+
+  apmd:   http://linuxcare.com.au/apm/
+  acpid:  http://phobos.fs.tum.de/acpi/
+
+Driver Interface
+----------------
+If you are writing a new driver or maintaining an old driver, it
+should include power management support.  Without power management
+support, a single driver may prevent a system with power management
+capabilities from ever being able to suspend (safely).
+
+Overview:
+1) Register each instance of a device with "pm_register"
+2) Call "pm_access" before accessing the hardware.
+   (this will ensure that the hardware is awake and ready)
+3) Your "pm_callback" is called before going into a
+   suspend state (ACPI D1-D3) or after resuming (ACPI D0)
+   from a suspend.
+4) Call "pm_dev_idle" when the device is not being used
+   (optional but will improve device idle detection)
+5) When unloaded, unregister the device with "pm_unregister"
+
+/*
+ * Description: Register a device with the power-management subsystem
+ *
+ * Parameters:
+ *   type - device type (PCI device, system device, ...)
+ *   id - instance number or unique identifier
+ *   cback - request handler callback (suspend, resume, ...)
+ *
+ * Returns: Registered PM device or NULL on error
+ *
+ * Examples:
+ *   dev = pm_register(PM_SYS_DEV, PM_SYS_VGA, vga_callback);
+ *
+ *   struct pci_dev *pci_dev = pci_find_dev(...);
+ *   dev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), callback);
+ */
+struct pm_dev *pm_register(pm_dev_t type, unsigned long id, pm_callback cback);
+
+/*
+ * Description: Unregister a device with the power management subsystem
+ *
+ * Parameters:
+ *   dev - PM device previously returned from pm_register
+ */
+void pm_unregister(struct pm_dev *dev);
+
+/*
+ * Description: Unregister all devices with a matching callback function
+ *
+ * Parameters:
+ *   cback - previously registered request callback
+ *
+ * Notes: Provided for easier porting from old APM interface
+ */
+void pm_unregister_all(pm_callback cback);
+
+/*
+ * Device idle/use detection
+ *
+ * In general, drivers for all devices should call "pm_access"
+ * before accessing the hardware (ie. before reading or modifying
+ * a hardware register).  Request or packet-driven drivers should
+ * additionally call "pm_dev_idle" when a device is not being used.
+ *
+ * Examples:
+ * 1) A keyboard driver would call pm_access whenever a key is pressed
+ * 2) A network driver would call pm_access before submitting
+ *    a packet for transmit or receive and pm_dev_idle when its
+ *    transfer and receive queues are empty.
+ * 3) A VGA driver would call pm_access before it accesses any
+ *    of the video controller registers
+ *
+ * Ultimately, the PM policy manager uses the access and idle
+ * information to decide when to suspend individual devices
+ * or when to suspend the entire system
+ */
+
+/*
+ * Description: Update device access time and wake up device, if necessary
+ *
+ * Parameters:
+ *   dev - PM device previously returned from pm_register
+ *
+ * Details: If called from an interrupt handler pm_access updates
+ *          access time but should never need to wake up the device
+ *          (if device is generating interrupts, it should be awake
+ *          already)  This is important as we can not wake up
+ *          devices from an interrupt handler.
+ */
+void pm_access(struct pm_dev *dev);
+
+/*
+ * Description: Identify device as currently being idle
+ *
+ * Parameters:
+ *   dev - PM device previously returned from pm_register
+ *
+ * Details: A call to pm_dev_idle might signal to the policy manager
+ *          to put a device to sleep.  If a new device request arrives
+ *          between the call to pm_dev_idle and the pm_callback
+ *          callback, the driver should fail the pm_callback request.
+ */
+void pm_dev_idle(struct pm_dev *dev);
+
+/*
+ * Power management request callback
+ *
+ * Parameters:
+ *   dev - PM device previously returned from pm_register
+ *   rqst - request type
+ *   data - data, if any, associated with the request
+ *
+ * Returns: 0 if the request is successful
+ *          EINVAL if the request is not supported
+ *          EBUSY if the device is now busy and can not handle the request
+ *          ENOMEM if the device was unable to handle the request due to memory
+ *          
+ * Details: The device request callback will be called before the
+ *          device/system enters a suspend state (ACPI D1-D3) or
+ *          or after the device/system resumes from suspend (ACPI D0).
+ *          For PM_SUSPEND, the ACPI D-state being entered is passed
+ *          as the "data" argument to the callback.  The device
+ *          driver should save (PM_SUSPEND) or restore (PM_RESUME)
+ *          device context when the request callback is called.
+ *
+ *          Once a driver returns 0 (success) from a suspend
+ *          request, it should not process any further requests or
+ *          access the device hardware until a call to "pm_access" is made.
+ */
+typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);
diff -u --recursive --new-file v2.3.42/linux/Documentation/sound/CMI8330 linux/Documentation/sound/CMI8330
--- v2.3.42/linux/Documentation/sound/CMI8330	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/sound/CMI8330	Wed Feb  9 18:48:03 2000
@@ -1,3 +1,83 @@
+Documentation for CMI 8330 (SoundPRO) 
+-------------------------------------
+Alessandro Zummo <azummo@ita.flashnet.it>
+
+This adapter is now directly supported by the sb driver.
+
+ The only thing you have to do is to compile the kernel sound
+support as a module and to enable kernel ISAPnP support,
+as shown below.
+
+
+CONFIG_SOUND=m
+CONFIG_SOUND_SB=m
+
+CONFIG_PNP=y
+CONFIG_ISAPNP=y
+
+
+and optionally:
+
+
+CONFIG_SOUND_MPU401=m
+
+ for MPU401 support.
+
+
+CONFIG_SOUND_YM3812=m
+
+ for OPL3 support. Please note that there are better ways to play midi files, like
+ timidity or the softoss2 module.
+
+
+CONFIG_JOYSTICK=y
+
+ to activate the joystick port.
+
+
+(I suggest you to use "make menuconfig" or "make xconfig" 
+ for a more comfortable configuration editing)
+
+
+
+Then you can do
+
+ modprobe sb
+
+and everything will be (hopefully) configured.
+
+You should get something similar in syslog:
+
+sb: CMI8330 detected.
+sb: CMI8330 sb base located at 0x220
+sb: CMI8330 mpu base located at 0x330
+sb: CMI8330 gameport base located at 0x200
+sb: CMI8330 opl3 base located at 0x388
+sb: CMI8330 mail reports to Alessandro Zummo <azummo@ita.flashnet.it>
+sb: ISAPnP reports CMI 8330 SoundPRO at i/o 0x220, irq 7, dma 1,5
+
+
+
+
+To activate the OPL3 support, you need these lines in /etc/modules.conf
+or in a file in /etc/modutils
+
+alias synth0 opl3
+options opl3 io=0x388
+
+and then you can do:
+
+ modprobe opl3
+
+
+
+
+
+
+The old documentation file follows for reference
+purposes.
+
+
 How to enable CMI 8330 (SOUNDPRO) soundchip on Linux
 ------------------------------------------
 Stefan Laudat <Stefan.Laudat@asit.ro>
diff -u --recursive --new-file v2.3.42/linux/Documentation/usb/ibmcam.txt linux/Documentation/usb/ibmcam.txt
--- v2.3.42/linux/Documentation/usb/ibmcam.txt	Fri Jan 28 15:09:06 2000
+++ linux/Documentation/usb/ibmcam.txt	Mon Feb  7 19:15:56 2000
@@ -23,11 +23,30 @@
 
 IBM "C-It" camera, also known as "Xirlink PC Camera"
 The device uses proprietary ASIC (and compression method);
-it is manufactured by Xirlink. See http://www.xirlink.com
+it is manufactured by Xirlink. See http://www.xirlink.com/
+or http://www.c-itnow.com/ for details and pictures.
+
+The Linux driver was developed with camera with following
+model number (or FCC ID): KSX-XVP510. This camera has three
+interfaces, each with one endpoint (control, iso, iso).
+
+It appears that Xirlink made some changes in their cameras recently.
+In particular, following models [FCC ID] are suspect; one with
+with FCC ID KSX-X9903 is known to be one of them:
+
+XVP300 [KSX-X9903]
+XVP600 [KSX-X9902]
+XVP610 [KSX-X9902]
+
+(see http://www.xirlink.com/ibmpccamera/ for updates, they refer
+to these new cameras by Windows driver dated 12-27-99, v3005 BETA)
+These cameras have two interfaces, one endpoint in each (iso, bulk).
+Attempts to remotely debug one of these cameras weren't successful.
+I'd need to have a camera to figure out how to use it.
 
 WHAT YOU NEED:
 
-- An IBM C-it camera
+- A supported IBM PC (C-it) camera (see above)
 
 - A Linux box with USB support (2.3/2.4 or 2.2 w/backport)
 
@@ -73,6 +92,7 @@
 debug           Integer         0-9 [0]         debug=1
 flags           Integer         0-0xFF [0]      flags=0x0d
 framerate       Integer         0-6 [2]         framerate=1
+hue_correction  Integer         0-255 [128]     hue_correction=115
 init_brightness Integer         0-255 [128]     init_brightness=100
 init_contrast   Integer         0-255 [192]     init_contrast=200
 init_color      Integer         0-255 [128]     init_color=130
@@ -108,6 +128,16 @@
                 Beware - fast settings are very demanding and may not
                 work well with all video sizes. Be conservative.
 
+hue_correction  This highly optional setting allows to adjust the
+                hue of the image in a way slightly different from
+                what usual "hue" control does. Both controls affect
+                YUV colorspace: regular "hue" control adjusts only
+                U component, and this "hue_correction" option similarly
+                adjusts only V component. However usually it is enough
+                to tweak only U or V to compensate for colored light or
+                color temperature; this option simply allows more
+                complicated correction when and if it is necessary.
+
 init_brightness These settings specify _initial_ values which will be
 init_contrast   used to set up the camera. If your V4L application has
 init_color      its own controls to adjust the picture then these
@@ -143,8 +173,8 @@
 
 WHAT NEEDS TO BE DONE:
 
-- The box freezes if working camera (with xawtv) is unplugged (OHCI).
-  Workaround: don't do that :) End the V4L application first.
+- The box freezes if camera is unplugged after being used (OHCI).
+  Workaround: don't do that :)
 - Some USB frames are lost on high frame rates, though they shouldn't
 - ViCE compression (Xirlink proprietary) may improve frame rate
 - On occasion camera does not start properly; xawtv reports errors.
diff -u --recursive --new-file v2.3.42/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt
--- v2.3.42/linux/Documentation/usb/ov511.txt	Fri Jan 28 15:09:06 2000
+++ linux/Documentation/usb/ov511.txt	Wed Feb  9 11:51:13 2000
@@ -15,12 +15,13 @@
 ________________________________________________________
 Manufacturer     | Model          | Custom ID | Status
 -----------------+----------------+-----------+---------
-MediaForte       | MV300          | 0         | Untested
+MediaForte       | MV300          | 0         | Working
 D-Link           | DSB-C300       | 3         | Working
+Puretek          | PT-6007        | 5         | Untested
 Creative Labs    | WebCam 3       | 21        | Working
 Lifeview         | RoboCam        | 100       | Untested
 AverMedia        | InterCam Elite | 102       | Working
-MediaForte       | MV300          | 112       | Untested
+MediaForte       | MV300          | 112       | Working
 --------------------------------------------------------
 
 Any camera using the OV511 and the OV7610 CCD should work with this driver. The
@@ -78,7 +79,9 @@
 	make
 	make install
 
-Now you should be able to run xawtv. Right click for the options dialog.
+Now you should be able to run xawtv. Right click for the options dialog. If
+you get a scrambled image it is likely that you made a mistake in Xawtv.ad.
+Try setting the size to 320x240 if all else fails.
 
 WORKING FEATURES:
  o Color streaming/capture at 640x480 and 320x240
diff -u --recursive --new-file v2.3.42/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.42/linux/MAINTAINERS	Tue Feb  1 01:35:43 2000
+++ linux/MAINTAINERS	Wed Feb  9 19:43:47 2000
@@ -561,7 +561,7 @@
 
 LINUX FOR POWERPC
 P:	Cort Dougan
-M:	cort@ppc.kernel.org
+M:	cort@fsmlabs.com
 W:	http://www.ppc.kernel.org/
 S:	Maintained
 
@@ -826,6 +826,12 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
+SA1100 SUPPORT
+P:	Nicolas Pitre
+M:	nico@cam.org
+L:	sa1100-linux@pa.dec.com
+S:	Maintained
+
 SBPCD CDROM DRIVER
 P:	Eberhard Moenkeberg
 M:	emoenke@gwdg.de
@@ -880,6 +886,11 @@
 P:	Linus Torvalds
 M:	torvalds@transmeta.com
 L:	linux-smp@vger.rutgers.edu
+S:	Maintained
+
+SOFTWARE RAID (Multiple Disks) SUPPORT
+P:	Ingo Molnar
+M:	mingo@redhat.com
 S:	Maintained
 
 SONIC NETWORK DRIVER
diff -u --recursive --new-file v2.3.42/linux/Makefile linux/Makefile
--- v2.3.42/linux/Makefile	Tue Feb  1 01:35:43 2000
+++ linux/Makefile	Tue Feb  8 22:26:49 2000
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 42
+SUBLEVEL = 43
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.3.42/linux/arch/alpha/config.in	Fri Jan 21 18:19:15 2000
+++ linux/arch/alpha/config.in	Tue Feb  8 18:37:43 2000
@@ -55,11 +55,15 @@
 
 # clear all implied options (don't want default values for those):
 unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
-unset CONFIG_PCI CONFIG_ALPHA_EISA
+unset CONFIG_PCI CONFIG_ISA CONFIG_ALPHA_EISA
 unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
 unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS
 unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
 unset CONFIG_ALPHA_IRONGATE
+
+# Most of these machines have ISA slots; not exactly sure which don't,
+# and this doesn't activate hordes of code, so do it always.
+define_bool CONFIG_ISA y
 
 if [ "$CONFIG_ALPHA_GENERIC" = "y" ]
 then
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v2.3.42/linux/arch/alpha/kernel/Makefile	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/Makefile	Mon Feb  7 20:09:05 2000
@@ -26,11 +26,11 @@
 	    sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o \
 	    sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
 	    sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_rx164.o \
-	    es1888.o smc37c669.o smc37c93x.o ns87312.o pci.o
+	    es1888.o smc37c669.o smc37c93x.o ns87312.o pci.o pci_iommu.o
 else
 
 ifdef CONFIG_PCI
-O_OBJS   += pci.o
+O_OBJS   += pci.o pci_iommu.o
 endif
 
 # Core logic support
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.3.42/linux/arch/alpha/kernel/alpha_ksyms.c	Wed Dec 15 10:43:16 1999
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Wed Feb  9 20:08:09 2000
@@ -149,6 +149,9 @@
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL_NOVERS(__down_read_failed);
+EXPORT_SYMBOL_NOVERS(__down_write_failed);
+EXPORT_SYMBOL_NOVERS(__rwsem_wake);
 
 /* 
  * SMP-specific symbols.
@@ -161,10 +164,7 @@
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_range);
 EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(cpu_number_map);
-EXPORT_SYMBOL(global_bh_lock);
-EXPORT_SYMBOL(global_bh_count);
-EXPORT_SYMBOL(synchronize_bh);
+EXPORT_SYMBOL(__cpu_number_map);
 EXPORT_SYMBOL(global_irq_holder);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_apecs.c linux/arch/alpha/kernel/core_apecs.c
--- v2.3.42/linux/arch/alpha/kernel/core_apecs.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/alpha/kernel/core_apecs.c	Mon Feb  7 20:09:05 2000
@@ -356,22 +356,49 @@
 	write_dword:	apecs_write_config_dword
 };
 
+void
+apecs_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+	wmb();
+	*(vip)APECS_IOC_TBIA = 0;
+	mb();
+}
+
 void __init
 apecs_init_arch(void)
 {
 	struct pci_controler *hose;
 
 	/*
-	 * Set up the PCI->physical memory translation windows.
-	 * For now, window 2 is disabled.  In the future, we may
-	 * want to use it to do scatter/gather DMA.  Window 1
-	 * goes at 1 GB and is 1 GB large.
+	 * Create our single hose.
+	 */
+
+	pci_isa_hose = hose = alloc_pci_controler();
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = APECS_CONF;
+	hose->index = 0;
+
+	/*
+	 * Set up the PCI to main memory translation windows.
+	 *
+	 * Window 1 is direct access 1GB at 1GB
+	 * Window 2 is scatter-gather 8MB at 8MB (for isa)
 	 */
-	*(vuip)APECS_IOC_PB1R = 1UL << 19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
-	*(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
+	hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, PAGE_SIZE);
+	hose->sg_pci = NULL;
+	__direct_map_base = 0x40000000;
+	__direct_map_size = 0x40000000;
+
+	*(vuip)APECS_IOC_PB1R = __direct_map_base | 0x00080000;
+	*(vuip)APECS_IOC_PM1R = (__direct_map_size - 1) & 0xfff00000U;
 	*(vuip)APECS_IOC_TB1R = 0;
 
-	*(vuip)APECS_IOC_PB2R = 0U;	/* disable window 2 */
+	*(vuip)APECS_IOC_PB2R = hose->sg_isa->dma_base | 0x000c0000;
+	*(vuip)APECS_IOC_PM2R = (hose->sg_isa->size - 1) & 0xfff00000;
+	*(vuip)APECS_IOC_TB2R = virt_to_phys(hose->sg_isa->ptes) >> 1;
+
+	apecs_pci_tbi(hose, 0, -1);
 
 	/*
 	 * Finally, clear the HAXR2 register, which gets used
@@ -381,16 +408,6 @@
 	 */
 	*(vuip)APECS_IOC_HAXR2 = 0;
 	mb();
-
-	/*
-	 * Create our single hose.
-	 */
-
-	hose = alloc_pci_controler();
-	hose->io_space = &ioport_resource;
-	hose->mem_space = &iomem_resource;
-	hose->config_space = APECS_CONF;
-	hose->index = 0;
 }
 
 void
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c
--- v2.3.42/linux/arch/alpha/kernel/core_cia.c	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/core_cia.c	Mon Feb  7 20:09:33 2000
@@ -314,12 +314,20 @@
 	write_dword:	cia_write_config_dword
 };
 
+void
+cia_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+	wmb();
+	*(vip)CIA_IOC_PCI_TBIA = 3;	/* Flush all locked and unlocked.  */
+	mb();
+}
+
 void __init
 cia_init_arch(void)
 {
 	struct pci_controler *hose;
 	struct resource *hae_mem;
-        unsigned int temp;
+	unsigned int temp;
 
 #if DEBUG_DUMP_REGS
 	temp = *(vuip)CIA_IOC_CIA_REV; mb();
@@ -368,63 +376,11 @@
 	printk("cia_init: W3_BASE was 0x%x\n", temp);
 #endif /* DEBUG_DUMP_REGS */
 
-        /* 
-	 * Set up error reporting.
-	 */
-	temp = *(vuip)CIA_IOC_CIA_ERR;
-	temp |= 0x180;   /* master, target abort */
-	*(vuip)CIA_IOC_CIA_ERR = temp;
-	mb();
-
-	temp = *(vuip)CIA_IOC_CIA_CTRL;
-	temp |= 0x400;	/* turn on FILL_ERR to get mchecks */
-	*(vuip)CIA_IOC_CIA_CTRL = temp;
-	mb();
-
-	/*
-	 * Set up the PCI->physical memory translation windows.
-	 * For now, windows 2 and 3 are disabled.  In the future,
-	 * we may want to use them to do scatter/gather DMA. 
-	 *
-	 * Window 0 goes at 1 GB and is 1 GB large.
-	 * Window 1 goes at 2 GB and is 1 GB large.
-	 */
-
-	*(vuip)CIA_IOC_PCI_W0_BASE = CIA_DMA_WIN0_BASE_DEFAULT | 1U;
-	*(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN0_SIZE_DEFAULT - 1) &
-				     0xfff00000U;
-	*(vuip)CIA_IOC_PCI_T0_BASE = CIA_DMA_WIN0_TRAN_DEFAULT >> 2;
-		
-	*(vuip)CIA_IOC_PCI_W1_BASE = CIA_DMA_WIN1_BASE_DEFAULT | 1U;
-	*(vuip)CIA_IOC_PCI_W1_MASK = (CIA_DMA_WIN1_SIZE_DEFAULT - 1) &
-				     0xfff00000U;
-	*(vuip)CIA_IOC_PCI_T1_BASE = CIA_DMA_WIN1_TRAN_DEFAULT >> 2;
-
-	*(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
-	*(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
-	mb();
-
-        /*
-         * Next, clear the CIA_CFG register, which gets used
-         * for PCI Config Space accesses. That is the way
-         * we want to use it, and we do not want to depend on
-         * what ARC or SRM might have left behind...
-         */
-	*((vuip)CIA_IOC_CFG) = 0; mb();
- 
-	/*
-	 * Zero the HAEs. 
-	 */
-	*((vuip)CIA_IOC_HAE_MEM) = 0; mb();
-	*((vuip)CIA_IOC_HAE_MEM); /* read it back. */
-	*((vuip)CIA_IOC_HAE_IO) = 0; mb();
-	*((vuip)CIA_IOC_HAE_IO);  /* read it back. */
-
 	/*
 	 * Create our single hose.
 	 */
 
-	hose = alloc_pci_controler();
+	pci_isa_hose = hose = alloc_pci_controler();
 	hae_mem = alloc_resource();
 
 	hose->io_space = &ioport_resource;
@@ -439,6 +395,64 @@
 
 	if (request_resource(&iomem_resource, hae_mem) < 0)
 		printk(KERN_ERR "Failed to request HAE_MEM\n");
+
+	/*
+	 * Set up the PCI to main memory translation windows.
+	 *
+	 * Window 0 is scatter-gather 8MB at 8MB (for isa)
+	 * Window 1 is scatter-gather 128MB at 1GB
+	 * Window 2 is direct access 2GB at 2GB
+	 * ??? We ought to scale window 1 with memory.
+	 */
+
+	/* NetBSD hints that page tables must be aligned to 32K due
+	   to a hardware bug.  No description of what models affected.  */
+	hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, 32768);
+	hose->sg_pci = iommu_arena_new(0x40000000, 0x08000000, 32768);
+	__direct_map_base = 0x80000000;
+	__direct_map_size = 0x80000000;
+
+	*(vuip)CIA_IOC_PCI_W0_BASE = hose->sg_isa->dma_base | 3;
+	*(vuip)CIA_IOC_PCI_W0_MASK = (hose->sg_isa->size - 1) & 0xfff00000;
+	*(vuip)CIA_IOC_PCI_T0_BASE = virt_to_phys(hose->sg_isa->ptes) >> 2;
+
+	*(vuip)CIA_IOC_PCI_W1_BASE = hose->sg_pci->dma_base | 3;
+	*(vuip)CIA_IOC_PCI_W1_MASK = (hose->sg_pci->size - 1) & 0xfff00000;
+	*(vuip)CIA_IOC_PCI_T1_BASE = virt_to_phys(hose->sg_pci->ptes) >> 2;
+
+	*(vuip)CIA_IOC_PCI_W2_BASE = __direct_map_base | 1;
+	*(vuip)CIA_IOC_PCI_W2_MASK = (__direct_map_size - 1) & 0xfff00000;
+	*(vuip)CIA_IOC_PCI_T2_BASE = 0;
+
+	*(vuip)CIA_IOC_PCI_W3_BASE = 0;
+
+	cia_pci_tbi(hose, 0, -1);
+
+	/* 
+	 * Set up error reporting.
+	 */
+	temp = *(vuip)CIA_IOC_CIA_ERR;
+	temp |= 0x180;   /* master, target abort */
+	*(vuip)CIA_IOC_CIA_ERR = temp;
+
+	temp = *(vuip)CIA_IOC_CIA_CTRL;
+	temp |= 0x400;	/* turn on FILL_ERR to get mchecks */
+	*(vuip)CIA_IOC_CIA_CTRL = temp;
+
+	/*
+	 * Next, clear the CIA_CFG register, which gets used
+	 * for PCI Config Space accesses. That is the way
+	 * we want to use it, and we do not want to depend on
+	 * what ARC or SRM might have left behind...
+	 */
+	*(vuip)CIA_IOC_CFG = 0;
+ 
+	/*
+	 * Zero the HAEs. 
+	 */
+	*(vuip)CIA_IOC_HAE_MEM = 0;
+	*(vuip)CIA_IOC_HAE_IO = 0;
+	mb();
 }
 
 static inline void
@@ -456,6 +470,8 @@
 cia_machine_check(unsigned long vector, unsigned long la_ptr,
 		  struct pt_regs * regs)
 {
+	int expected;
+
 	/* Clear the error before any reporting.  */
 	mb();
 	mb();  /* magic */
@@ -464,5 +480,23 @@
 	wrmces(rdmces());	/* reset machine check pending flag.  */
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "CIA", mcheck_expected(0));
+	expected = mcheck_expected(0);
+	if (!expected && vector == 0x660) {
+		struct el_common *com;
+		struct el_common_EV5_uncorrectable_mcheck *ev5;
+		struct el_CIA_sysdata_mcheck *cia;
+
+		com = (void *)la_ptr;
+		ev5 = (void *)(la_ptr + com->proc_offset);
+		cia = (void *)(la_ptr + com->sys_offset);
+
+		if (com->code == 0x202) {
+			printk(KERN_CRIT "CIA PCI machine check: err0=%08x "
+			       "err1=%08x err2=%08x\n",
+			       (int) cia->pci_err0, (int) cia->pci_err1,
+			       (int) cia->pci_err2);
+			expected = 1;
+		}
+	}
+	process_mcheck_info(vector, la_ptr, regs, "CIA", expected);
 }
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_irongate.c linux/arch/alpha/kernel/core_irongate.c
--- v2.3.42/linux/arch/alpha/kernel/core_irongate.c	Wed Dec 15 10:43:16 1999
+++ linux/arch/alpha/kernel/core_irongate.c	Mon Feb  7 20:09:05 2000
@@ -351,4 +351,8 @@
 	hose->mem_space = &iomem_resource;
 	hose->config_space = IRONGATE_CONF;
 	hose->index = 0;
+
+	hose->sg_isa = hose->sg_pci = NULL;
+	__direct_map_base = 0;
+	__direct_map_size = 0xffffffff;
 }
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_lca.c linux/arch/alpha/kernel/core_lca.c
--- v2.3.42/linux/arch/alpha/kernel/core_lca.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/alpha/kernel/core_lca.c	Mon Feb  7 20:09:05 2000
@@ -278,23 +278,51 @@
 	write_dword:	lca_write_config_dword
 };
 
+void
+lca_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+	wmb();
+	*(vip)LCA_IOC_TBIA = 0;
+	mb();
+}
+
 void __init
 lca_init_arch(void)
 {
 	struct pci_controler *hose;
 
 	/*
-	 * Set up the PCI->physical memory translation windows.
-	 * For now, window 1 is disabled.  In the future, we may
-	 * want to use it to do scatter/gather DMA. 
+	 * Create our single hose.
+	 */
+
+	pci_isa_hose = hose = alloc_pci_controler();
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = LCA_CONF;
+	hose->index = 0;
+
+	/*
+	 * Set up the PCI to main memory translation windows.
 	 *
-	 * Window 0 goes at 1 GB and is 1 GB large.
+	 * Window 0 is direct access 1GB at 1GB
+	 * Window 1 is scatter-gather 8MB at 8MB (for isa)
 	 */
-	*(vulp)LCA_IOC_W_BASE0 = 1UL << 33 | LCA_DMA_WIN_BASE;
-	*(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
+	hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, PAGE_SIZE);
+	hose->sg_pci = NULL;
+	__direct_map_base = 0x40000000;
+	__direct_map_size = 0x40000000;
+
+	*(vulp)LCA_IOC_W_BASE0 = __direct_map_base | (2UL << 32);
+	*(vulp)LCA_IOC_W_MASK0 = (__direct_map_size - 1) & 0xfff00000;
 	*(vulp)LCA_IOC_T_BASE0 = 0;
 
-	*(vulp)LCA_IOC_W_BASE1 = 0UL;
+	*(vulp)LCA_IOC_W_BASE1 = hose->sg_isa->dma_base | (3UL << 32);
+	*(vulp)LCA_IOC_W_MASK1 = (hose->sg_isa->size - 1) & 0xfff00000;
+	*(vulp)LCA_IOC_T_BASE1 = virt_to_phys(hose->sg_isa->ptes);
+
+	*(vulp)LCA_IOC_TB_ENA = 0x80;
+
+	lca_pci_tbi(hose, 0, -1);
 
 	/*
 	 * Disable PCI parity for now.  The NCR53c810 chip has
@@ -302,16 +330,6 @@
 	 * data parity errors.
 	 */
 	*(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
-
-	/*
-	 * Create our single hose.
-	 */
-
-	hose = alloc_pci_controler();
-	hose->io_space = &ioport_resource;
-	hose->mem_space = &iomem_resource;
-	hose->config_space = LCA_CONF;
-	hose->index = 0;
 }
 
 /*
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_mcpcia.c linux/arch/alpha/kernel/core_mcpcia.c
--- v2.3.42/linux/arch/alpha/kernel/core_mcpcia.c	Fri Jan 21 18:19:15 2000
+++ linux/arch/alpha/kernel/core_mcpcia.c	Mon Feb  7 20:09:05 2000
@@ -293,6 +293,14 @@
 	write_dword:	mcpcia_write_config_dword
 };
 
+void
+mcpcia_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+	wmb();
+	BUG();
+	mb();
+}
+
 static int __init
 mcpcia_probe_hose(int h)
 {
@@ -395,31 +403,36 @@
 
 	/*
 	 * Set up the PCI->physical memory translation windows.
-	 * For now, windows 1,2 and 3 are disabled.  In the
-	 * future, we may want to use them to do scatter/
-	 * gather DMA.
 	 *
-	 * Window 0 goes at 2 GB and is 2 GB large.
+	 * Window 0 is scatter-gather 8MB at 8MB (for isa)
+	 * Window 1 is scatter-gather 128MB at 1GB
+	 * Window 2 is direct access 2GB at 2GB
+	 * ??? We ought to scale window 1 with memory.
 	 */
 
-	*(vuip)MCPCIA_W0_BASE(mid) = 1U | (MCPCIA_DMA_WIN_BASE & 0xfff00000U);
-	*(vuip)MCPCIA_W0_MASK(mid) = (MCPCIA_DMA_WIN_SIZE - 1) & 0xfff00000U;
-	*(vuip)MCPCIA_T0_BASE(mid) = 0;
+	hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, PAGE_SIZE);
+	hose->sg_pci = iommu_arena_new(0x40000000, 0x08000000, PAGE_SIZE);
+	__direct_map_base = 0x80000000;
+	__direct_map_size = 0x80000000;
+
+	*(vuip)MCPCIA_W0_BASE(mid) = hose->sg_isa->dma_base | 3;
+	*(vuip)MCPCIA_W0_MASK(mid) = (hose->sg_isa->size - 1) & 0xfff00000;
+	*(vuip)MCPCIA_T0_BASE(mid) = virt_to_phys(hose->sg_isa->ptes) >> 2;
+
+	*(vuip)MCPCIA_W1_BASE(mid) = hose->sg_pci->dma_base | 3;
+	*(vuip)MCPCIA_W1_MASK(mid) = (hose->sg_pci->size - 1) & 0xfff00000;
+	*(vuip)MCPCIA_T1_BASE(mid) = virt_to_phys(hose->sg_pci->ptes) >> 2;
+
+	*(vuip)MCPCIA_W2_BASE(mid) = __direct_map_base | 1;
+	*(vuip)MCPCIA_W2_MASK(mid) = (__direct_map_size - 1) & 0xfff00000;
+	*(vuip)MCPCIA_T2_BASE(mid) = 0;
 
-	*(vuip)MCPCIA_W1_BASE(mid) = 0x0;
-	*(vuip)MCPCIA_W2_BASE(mid) = 0x0;
 	*(vuip)MCPCIA_W3_BASE(mid) = 0x0;
 
-	*(vuip)MCPCIA_HBASE(mid) = 0x0;
-	mb();
+	mcpcia_pci_tbi(hose, 0, -1);
 
-#if 0
-	tmp = *(vuip)MCPCIA_INT_CTL(mid);
-	printk("mcpcia_startup_hose: INT_CTL was 0x%x\n", tmp);
-	*(vuip)MCPCIA_INT_CTL(mid) = 1U;
+	*(vuip)MCPCIA_HBASE(mid) = 0x0;
 	mb();
-	tmp = *(vuip)MCPCIA_INT_CTL(mid);
-#endif
 
 	*(vuip)MCPCIA_HAE_MEM(mid) = 0U;
 	mb();
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_polaris.c linux/arch/alpha/kernel/core_polaris.c
--- v2.3.42/linux/arch/alpha/kernel/core_polaris.c	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/core_polaris.c	Mon Feb  7 20:09:05 2000
@@ -197,6 +197,12 @@
 	hose->mem_space = &iomem_resource;
 	hose->config_space = POLARIS_DENSE_CONFIG_BASE;
 	hose->index = 0;
+
+	hose->sg_isa = hose->sg_pci = NULL;
+
+	/* The I/O window is fixed at 2G @ 2G.  */
+	__direct_map_base = 0x80000000;
+	__direct_map_size = 0x80000000;
 }
 
 static inline void
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_pyxis.c linux/arch/alpha/kernel/core_pyxis.c
--- v2.3.42/linux/arch/alpha/kernel/core_pyxis.c	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/core_pyxis.c	Mon Feb  7 20:09:33 2000
@@ -6,20 +6,22 @@
  * Code common to all PYXIS core logic chips.
  */
 
-#include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/kernel.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_pyxis.h>
+#undef __EXTERN_INLINE
+
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
 
-#define __EXTERN_INLINE inline
-#include <asm/io.h>
-#include <asm/core_pyxis.h>
-#undef __EXTERN_INLINE
-
 #include "proto.h"
 #include "pci_impl.h"
 
@@ -284,6 +286,84 @@
 	write_dword:	pyxis_write_config_dword
 };
 
+void
+pyxis_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+	wmb();
+	*(vip)PYXIS_TBIA = 3;	/* Flush all locked and unlocked.  */
+	mb();
+}
+
+/*
+ * Pass 1 and 2 have a broken scatter-gather tlb -- it cannot be invalidated.
+ * To work around this problem, we allocate mappings, and put the chip into
+ * DMA loopback mode to read a garbage page.  This works by causing TLB
+ * misses, causing old entries to be purged to make room for the new entries
+ * coming in for the garbage page.
+ * 
+ * Thanks to NetBSD sources for pointing out this bug.  What a pain.
+ */
+
+static unsigned long broken_tbi_addr;
+
+#define BROKEN_TBI_READS 12
+
+static void
+pyxis_broken_pci_tbi(struct pci_controler *hose,
+		     dma_addr_t start, dma_addr_t end)
+{
+	unsigned long flags;
+	unsigned long bus_addr;
+	unsigned int ctrl;
+	long i;
+
+	__save_and_cli(flags);
+
+	/* Put the chip into PCI loopback mode.  */
+	mb();
+	ctrl = *(vuip)PYXIS_CTRL;
+	*(vuip)PYXIS_CTRL = ctrl | 4;
+	mb();
+
+	/* Read from PCI dense memory space at TBI_ADDR, skipping 64k
+	   on each read.  This forces SG TLB misses.  It appears that
+	   the TLB entries are "not quite LRU", meaning that we need
+	   to read more times than there are actual tags.  */
+
+	bus_addr = broken_tbi_addr;
+	for (i = 0; i < BROKEN_TBI_READS; ++i, bus_addr += 64*1024)
+		pyxis_readl(bus_addr);
+
+	/* Restore normal PCI operation.  */
+	mb();
+	*(vuip)PYXIS_CTRL = ctrl;
+	mb();
+
+	__restore_flags(flags);
+}
+
+static void
+pyxis_enable_broken_tbi(struct pci_iommu_arena *arena)
+{
+	void *page;
+	unsigned long *ppte, ofs, pte;
+	long i, npages;
+
+	page = alloc_bootmem_pages(PAGE_SIZE);
+	pte = (virt_to_phys(page) >> (PAGE_SHIFT - 1)) | 1;
+	npages = (BROKEN_TBI_READS + 1) * 64*1024 / PAGE_SIZE;
+
+	ofs = iommu_arena_alloc(arena, npages);
+	ppte = arena->ptes + ofs;
+	for (i = 0; i < npages; ++i)
+		ppte[i] = pte;
+
+	broken_tbi_addr = pyxis_ioremap(arena->dma_base + ofs*PAGE_SIZE);
+	alpha_mv.mv_pci_tbi = pyxis_broken_pci_tbi;
+
+	printk("PYXIS: Enabling broken tbia workaround.\n");
+}
+
 void __init
 pyxis_init_arch(void)
 {
@@ -306,84 +386,100 @@
 	 */
 	temp = *(vuip)PYXIS_ERR_MASK;
 	temp &= ~4;   
-	*(vuip)PYXIS_ERR_MASK = temp; mb();
-	temp = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
+	*(vuip)PYXIS_ERR_MASK = temp;
+	mb();
+	*(vuip)PYXIS_ERR_MASK;	/* re-read to force write */
+
+	temp = *(vuip)PYXIS_ERR;
+	temp |= 0x180;		/* master/target abort */
+	*(vuip)PYXIS_ERR = temp;
+	mb();
+	*(vuip)PYXIS_ERR;	/* re-read to force write */
 
-	temp = *(vuip)PYXIS_ERR ;
-	temp |= 0x180;   /* master/target abort */
-	*(vuip)PYXIS_ERR = temp; mb();
-	temp = *(vuip)PYXIS_ERR; /* re-read to force write */
+ 	/*
+	 * Create our single hose.
+	 */
+
+	hose = alloc_pci_controler();
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = PYXIS_CONF;
+	hose->index = 0;
 
 	/*
-	 * Set up the PCI->physical memory translation windows.
-	 * For now, windows 2 and 3 are disabled.  In the future, we may
-	 * want to use them to do scatter/gather DMA. 
+	 * Set up the PCI to main memory translation windows.
+	 *
+	 * Window 0 is scatter-gather 8MB at 8MB (for isa)
+	 * Window 1 is scatter-gather 128MB at 3GB
+	 * Window 2 is direct access 1GB at 1GB
+	 * Window 3 is direct access 1GB at 2GB
+	 * ??? We ought to scale window 1 with memory.
 	 *
-	 * Window 0 goes at 2 GB and is 1 GB large.
-	 * Window 1 goes at 3 GB and is 1 GB large.
+	 * We must actually use 2 windows to direct-map the 2GB space,
+	 * because of an idiot-syncrasy of the CYPRESS chip.  It may
+	 * respond to a PCI bus address in the last 1MB of the 4GB
+	 * address range.
 	 */
 
-	*(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN0_BASE_DEFAULT | 1U;
-	*(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN0_SIZE_DEFAULT - 1) & 0xfff00000U;
-	*(vuip)PYXIS_T0_BASE = PYXIS_DMA_WIN0_TRAN_DEFAULT >> 2;
-
-	*(vuip)PYXIS_W1_BASE = PYXIS_DMA_WIN1_BASE_DEFAULT | 1U;
-	*(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN1_SIZE_DEFAULT - 1) & 0xfff00000U;
-	*(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN1_TRAN_DEFAULT >> 2;
+	/* NetBSD hints that page tables must be aligned to 32K due
+	   to a hardware bug.  No description of what models affected.  */
+	hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, 32768);
+	hose->sg_pci = iommu_arena_new(0xc0000000, 0x08000000, 32768);
+	__direct_map_base = 0x40000000;
+	__direct_map_size = 0x80000000;
+
+	*(vuip)PYXIS_W0_BASE = hose->sg_isa->dma_base | 3;
+	*(vuip)PYXIS_W0_MASK = (hose->sg_isa->size - 1) & 0xfff00000;
+	*(vuip)PYXIS_T0_BASE = virt_to_phys(hose->sg_isa->ptes) >> 2;
+
+	*(vuip)PYXIS_W1_BASE = hose->sg_pci->dma_base | 3;
+	*(vuip)PYXIS_W1_MASK = (hose->sg_pci->size - 1) & 0xfff00000;
+	*(vuip)PYXIS_T1_BASE = virt_to_phys(hose->sg_pci->ptes) >> 2;
+
+	*(vuip)PYXIS_W2_BASE = 0x40000000 | 1;
+	*(vuip)PYXIS_W2_MASK = (0x40000000 - 1) & 0xfff00000;
+	*(vuip)PYXIS_T2_BASE = 0;
+
+	*(vuip)PYXIS_W3_BASE = 0x80000000 | 1;
+	*(vuip)PYXIS_W3_MASK = (0x40000000 - 1) & 0xfff00000;
+	*(vuip)PYXIS_T3_BASE = 0;
+
+	/* Pass 1 and 2 (ie revision <= 1) have a broken TBIA.  See the
+	   complete description next to pyxis_broken_pci_tbi for details.  */
+	if ((*(vuip)PYXIS_REV & 0xff) <= 1)
+		pyxis_enable_broken_tbi(hose->sg_pci);
 
-	*(vuip)PYXIS_W2_BASE = 0x0;
-	*(vuip)PYXIS_W3_BASE = 0x0;
-	mb();
+	alpha_mv.mv_pci_tbi(hose, 0, -1);
 
 	/*
-         * Next, clear the PYXIS_CFG register, which gets used
+	 * Next, clear the PYXIS_CFG register, which gets used
 	 *  for PCI Config Space accesses. That is the way
 	 *  we want to use it, and we do not want to depend on
 	 *  what ARC or SRM might have left behind...
 	 */
-	{
-		unsigned int pyxis_cfg, temp;
-		pyxis_cfg = *(vuip)PYXIS_CFG; mb();
-		if (pyxis_cfg != 0) {
-#if 1
-			printk("PYXIS_init: CFG was 0x%x\n", pyxis_cfg);
-#endif
-			*(vuip)PYXIS_CFG = 0; mb();
-			temp = *(vuip)PYXIS_CFG;  /* re-read to force write */
-		}
+	temp = *(vuip)PYXIS_CFG;
+	if (temp != 0) {
+		*(vuip)PYXIS_CFG = 0;
+		mb();
+		*(vuip)PYXIS_CFG; /* re-read to force write */
 	}
  
 	/* Zero the HAE.  */
 	*(vuip)PYXIS_HAE_MEM = 0U; mb();
-	*(vuip)PYXIS_HAE_MEM; /* re-read to force write */
+	*(vuip)PYXIS_HAE_MEM;	/* re-read to force write */
 	*(vuip)PYXIS_HAE_IO = 0; mb();
-	*(vuip)PYXIS_HAE_IO;  /* re-read to force write */
+	*(vuip)PYXIS_HAE_IO;	/* re-read to force write */
 
 	/*
 	 * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
 	 * enabling byte/word PCI bus space(s) access.
 	 */
-	{
-		unsigned int ctrl1;
-		ctrl1 = *(vuip) PYXIS_CTRL1;
-		if (!(ctrl1 & 1)) {
-#if 1
-			printk("PYXIS_init: enabling byte/word PCI space\n");
-#endif
-			*(vuip) PYXIS_CTRL1 = ctrl1 | 1; mb();
-			ctrl1 = *(vuip)PYXIS_CTRL1;  /* re-read */
-		}
+	temp = *(vuip) PYXIS_CTRL1;
+	if (!(temp & 1)) {
+		*(vuip)PYXIS_CTRL1 = temp | 1;
+		mb();
+		*(vuip)PYXIS_CTRL1; /* re-read */
 	}
-
-	/*
-	 * Create our single hose.
-	 */
-
-	hose = alloc_pci_controler();
-	hose->io_space = &ioport_resource;
-	hose->mem_space = &iomem_resource;
-	hose->config_space = PYXIS_CONF;
-	hose->index = 0;
 }
 
 static inline void
@@ -401,6 +497,8 @@
 pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
 		    struct pt_regs * regs)
 {
+	int expected;
+
 	/* Clear the error before reporting anything.  */
 	mb();
 	mb();  /* magic */
@@ -409,5 +507,23 @@
 	wrmces(0x7);
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "PYXIS", mcheck_expected(0));
+	expected = mcheck_expected(0);
+	if (!expected && vector == 0x660) {
+		struct el_common *com;
+		struct el_common_EV5_uncorrectable_mcheck *ev5;
+		struct el_PYXIS_sysdata_mcheck *pyxis;
+
+		com = (void *)la_ptr;
+		ev5 = (void *)(la_ptr + com->proc_offset);
+		pyxis = (void *)(la_ptr + com->sys_offset);
+
+		if (com->code == 0x202) {
+			printk(KERN_CRIT "PYXIS PCI machine check: err0=%08x "
+			       "err1=%08x err2=%08x\n",
+			       (int) pyxis->pci_err0, (int) pyxis->pci_err1,
+			       (int) pyxis->pci_err2);
+			expected = 1;
+		}
+	}
+	process_mcheck_info(vector, la_ptr, regs, "PYXIS", expected);
 }
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_t2.c linux/arch/alpha/kernel/core_t2.c
--- v2.3.42/linux/arch/alpha/kernel/core_t2.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/alpha/kernel/core_t2.c	Mon Feb  7 20:09:05 2000
@@ -389,6 +389,10 @@
 	hose->mem_space = &iomem_resource;
 	hose->config_space = T2_CONF;
 	hose->index = 0;
+
+	hose->sg_isa = hose->sg_pci = NULL;
+	__direct_map_base = 0x40000000;
+	__direct_map_size = 0x40000000;
 }
 
 #define SIC_SEIC (1UL << 33)    /* System Event Clear */
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c
--- v2.3.42/linux/arch/alpha/kernel/core_tsunami.c	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/core_tsunami.c	Mon Feb  7 20:09:05 2000
@@ -100,11 +100,11 @@
 		 "pci_addr=0x%p, type1=0x%p)\n",
 		 bus, device_fn, where, pci_addr, type1));
 
-        if (hose->first_busno == dev->bus->number)
+	if (hose->first_busno == dev->bus->number)
 		bus = 0;
-        *type1 = (bus != 0);
+	*type1 = (bus != 0);
 
-        addr = (bus << 16) | (device_fn << 8) | where;
+	addr = (bus << 16) | (device_fn << 8) | where;
 	addr |= hose->config_space;
 		
 	*pci_addr = addr;
@@ -206,6 +206,23 @@
 	write_dword:	tsunami_write_config_dword
 };
 
+void
+tsunami_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
+{
+	tsunami_pchip *pchip = hose->index ? TSUNAMI_pchip1 : TSUNAMI_pchip0;
+
+	wmb();
+
+	/* We can invalidate up to 8 tlb entries in a go.  The flush
+	   matches against <31:16> in the pci address.  */
+	if (((start ^ end) & 0xffff0000) == 0)
+		pchip->tlbiv.csr = (start & 0xffff0000) >> 12;
+	else
+		pchip->tlbia.csr = 0;
+
+	mb();
+}
+
 #ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
 static long
 tsunami_probe_read(volatile unsigned long *vaddr)
@@ -264,6 +281,8 @@
 		return;
 
 	hose = alloc_pci_controler();
+	if (index == 0)
+		pci_isa_hose = hose;
 	hose->io_space = alloc_resource();
 	hose->mem_space = alloc_resource();
 
@@ -307,27 +326,41 @@
 	saved_pchip[index].tba[3] = pchip->tba[3].csr;
 
 	/*
-	 * Set up the PCI->physical memory translation windows.
-	 * For now, windows 1,2 and 3 are disabled.  In the future,
-	 * we may want to use them to do scatter/gather DMA. 
+	 * Set up the PCI to main memory translation windows.
+	 *
+	 * Window 0 is scatter-gather 8MB at 8MB (for isa)
+	 * Window 1 is scatter-gather 128MB at 3GB
+	 * Window 2 is direct access 1GB at 1GB
+	 * Window 3 is direct access 1GB at 2GB
+	 * ??? We ought to scale window 1 memory.
 	 *
-	 * Window 0 goes at 1 GB and is 1 GB large, mapping to 0.
-	 * Window 1 goes at 2 GB and is 1 GB large, mapping to 1GB.
+	 * We must actually use 2 windows to direct-map the 2GB space,
+	 * because of an idiot-syncrasy of the CYPRESS chip.  It may
+	 * respond to a PCI bus address in the last 1MB of the 4GB
+	 * address range.
 	 */
+	hose->sg_isa = iommu_arena_new(0x00800000, 0x00800000, PAGE_SIZE);
+	hose->sg_pci = iommu_arena_new(0xc0000000, 0x08000000, PAGE_SIZE);
+	__direct_map_base = 0x40000000;
+	__direct_map_size = 0x80000000;
+
+	pchip->wsba[0].csr = hose->sg_isa->dma_base | 3;
+	pchip->wsm[0].csr  = (hose->sg_isa->size - 1) & 0xfff00000;
+	pchip->tba[0].csr  = virt_to_phys(hose->sg_isa->ptes);
+
+	pchip->wsba[1].csr = hose->sg_pci->dma_base | 3;
+	pchip->wsm[1].csr  = (hose->sg_pci->size - 1) & 0xfff00000;
+	pchip->tba[1].csr  = virt_to_phys(hose->sg_pci->ptes);
+
+	pchip->wsba[2].csr = 0x40000000 | 1;
+	pchip->wsm[2].csr  = (0x40000000 - 1) & 0xfff00000;
+	pchip->tba[2].csr  = 0;
+
+	pchip->wsba[3].csr = 0x80000000 | 1;
+	pchip->wsm[3].csr  = (0x40000000 - 1) & 0xfff00000;
+	pchip->tba[3].csr  = 0;
 
-	pchip->wsba[0].csr = TSUNAMI_DMA_WIN0_BASE_DEFAULT | 1UL;
-	pchip->wsm[0].csr  = (TSUNAMI_DMA_WIN0_SIZE_DEFAULT - 1) &
-			     0xfff00000UL;
-	pchip->tba[0].csr  = TSUNAMI_DMA_WIN0_TRAN_DEFAULT;
-
-	pchip->wsba[1].csr = TSUNAMI_DMA_WIN1_BASE_DEFAULT | 1UL;
-	pchip->wsm[1].csr  = (TSUNAMI_DMA_WIN1_SIZE_DEFAULT - 1) &
-			     0xfff00000UL;
-	pchip->tba[1].csr  = TSUNAMI_DMA_WIN1_TRAN_DEFAULT;
-
-	pchip->wsba[2].csr = 0;
-	pchip->wsba[3].csr = 0;
-	mb();
+	tsunami_pci_tbi(hose, 0, -1);
 }
 
 void __init
@@ -335,7 +368,7 @@
 {
 #ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
 	extern asmlinkage void entInt(void);
-        unsigned long tmp;
+	unsigned long tmp;
 	
 	/* Ho hum.. init_arch is called before init_IRQ, but we need to be
 	   able to handle machine checks.  So install the handler now.  */
@@ -426,7 +459,7 @@
 
 	/* TSUNAMI and TYPHOON can have 2, but might only have 1 (DS10) */
 	if (TSUNAMI_cchip->csc.csr & 1L<<14)
-	    tsunami_pci_clr_err_1(TSUNAMI_pchip1);
+		tsunami_pci_clr_err_1(TSUNAMI_pchip1);
 }
 
 void
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.3.42/linux/arch/alpha/kernel/entry.S	Tue Jan 11 22:31:36 2000
+++ linux/arch/alpha/kernel/entry.S	Wed Feb  9 20:08:09 2000
@@ -32,6 +32,7 @@
 #define TASK_ADDR_LIMIT		24	
 #define TASK_EXEC_DOMAIN	32
 #define TASK_NEED_RESCHED	40
+#define TASK_PROCESSOR		100
 
 /*
  * task flags (must match include/linux/sched.h):
@@ -572,12 +573,15 @@
 .align 3
 ret_from_sys_call:
 	cmovne	$26,0,$19		/* $19 = 0 => non-restartable */
-	/* check bottom half interrupts */
-	ldq	$3,bh_active
-	ldq	$4,bh_mask
-	and	$3,$4,$2
-	bne	$2,handle_bottom_half
-ret_from_handle_bh:
+	ldq	$3,TASK_PROCESSOR($8)
+	lda	$4,softirq_state
+	sll	$3,5,$3
+	addq	$3,$4,$4
+	ldq	$4,0($4)
+	sll	$4,32,$3
+	and	$4,$3,$4
+	bne	$4,handle_softirq
+ret_from_softirq:
 	ldq	$0,SP_OFF($30)
 	and	$0,8,$0
 	beq	$0,restore_all
@@ -656,16 +660,16 @@
 	br	ret_from_sys_call
 
 	.align 3
-handle_bottom_half:
+handle_softirq:
 	subq	$30,16,$30
 	stq	$19,0($30)	/* save syscall nr */
 	stq	$20,8($30)	/* and error indication (a3) */
-	jsr	$26,do_bottom_half
+	jsr	$26,do_softirq
 	ldq	$19,0($30)
 	ldq	$20,8($30)
 	addq	$30,16,$30
-	br	ret_from_handle_bh
-
+	br	ret_from_softirq
+	
 	.align 3
 syscall_error:
 	/*
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.3.42/linux/arch/alpha/kernel/irq.c	Wed Dec  8 14:11:24 1999
+++ linux/arch/alpha/kernel/irq.c	Wed Feb  9 20:08:09 2000
@@ -377,10 +377,6 @@
 /* Global IRQ locking depth. */
 atomic_t global_irq_count = ATOMIC_INIT(0);
 
-/* This protects BH software state (masks, things like that). */
-atomic_t global_bh_lock = ATOMIC_INIT(0);
-atomic_t global_bh_count = ATOMIC_INIT(0);
-
 static void *previous_irqholder = NULL;
 
 #define MAXCOUNT 100000000
@@ -401,7 +397,7 @@
 		 */
 		if (!atomic_read(&global_irq_count)) {
 			if (local_bh_count(cpu)
-			    || !atomic_read(&global_bh_count))
+			    || !spin_is_locked(&global_bh_lock))
 				break;
 		}
 
@@ -422,7 +418,7 @@
 			if (spin_is_locked(&global_irq_lock))
 				continue;
 			if (!local_bh_count(cpu)
-			    && atomic_read(&global_bh_count))
+			    && spin_is_locked(&global_bh_lock))
 				continue;
 			if (spin_trylock(&global_irq_lock))
 				break;
@@ -552,7 +548,7 @@
 	       cpu_data[1].irq_count);
 
         printk("bh:   %d [%d %d]\n",
-	       atomic_read(&global_bh_count),
+	       spin_is_locked(&global_bh_lock) ? 1 : 0,
 	       cpu_data[0].bh_count,
 	       cpu_data[1].bh_count);
 #if 0
@@ -567,35 +563,6 @@
 #endif
 }
         
-static inline void
-wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-        do {
-		if (!--count) {
-			show("wait_on_bh", 0);
-                        count = ~0;
-                }
-                /* nothing .. wait for the other bh's to go away */
-		barrier();
-        } while (atomic_read(&global_bh_count) != 0);
-}
-
-/*
- * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler.
- */
-void
-synchronize_bh(void)
-{
-	if (atomic_read(&global_bh_count) && !in_interrupt())
-		wait_on_bh();
-}
-
 /*
  * From its use, I infer that synchronize_irq() stalls a thread until
  * the effects of a command to an external device are known to have
@@ -897,6 +864,7 @@
 	case 0x98: reason = "processor detected hard error"; break;
 	
 	/* System specific (these are for Alcor, at least): */
+	case 0x202: reason = "system detected hard error"; break;
 	case 0x203: reason = "system detected uncorrectable ECC error"; break;
 	case 0x204: reason = "SIO SERR occurred on PCI bus"; break;
 	case 0x205: reason = "parity error detected by CIA"; break;
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/machvec_impl.h linux/arch/alpha/kernel/machvec_impl.h
--- v2.3.42/linux/arch/alpha/kernel/machvec_impl.h	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/machvec_impl.h	Mon Feb  7 20:09:05 2000
@@ -101,8 +101,7 @@
 #define DO_TSUNAMI_IO	IO(TSUNAMI,tsunami)
 
 #define BUS(which)					\
-	mv_virt_to_bus:	CAT(which,_virt_to_bus),	\
-	mv_bus_to_virt:	CAT(which,_bus_to_virt)
+	mv_pci_tbi:	CAT(which,_pci_tbi)
 
 #define DO_APECS_BUS	BUS(apecs)
 #define DO_CIA_BUS	BUS(cia)
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c
--- v2.3.42/linux/arch/alpha/kernel/pci.c	Fri Jan 21 18:19:15 2000
+++ linux/arch/alpha/kernel/pci.c	Mon Feb  7 20:09:05 2000
@@ -40,6 +40,7 @@
  */
 
 struct pci_controler *hose_head, **hose_tail = &hose_head;
+struct pci_controler *pci_isa_hose;
 
 /*
  * Quirks.
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/pci_impl.h linux/arch/alpha/kernel/pci_impl.h
--- v2.3.42/linux/arch/alpha/kernel/pci_impl.h	Tue Nov 23 22:42:20 1999
+++ linux/arch/alpha/kernel/pci_impl.h	Mon Feb  7 20:09:05 2000
@@ -7,7 +7,7 @@
 
 struct pci_dev;
 struct pci_controler;
-
+struct pci_iommu_arena;
 
 /*
  * We can't just blindly use 64K for machines with EISA busses; they
@@ -125,11 +125,16 @@
 
 /* The hose list.  */
 extern struct pci_controler *hose_head, **hose_tail;
+extern struct pci_controler *pci_isa_hose;
 
 extern void common_init_pci(void);
 extern u8 common_swizzle(struct pci_dev *, u8 *);
 extern struct pci_controler *alloc_pci_controler(void);
 extern struct resource *alloc_resource(void);
+
+extern struct pci_iommu_arena *iommu_arena_new(dma_addr_t, unsigned long,
+					   unsigned long);
+extern long iommu_arena_alloc(struct pci_iommu_arena *arena, long n);
 
 extern const char *const pci_io_names[];
 extern const char *const pci_mem_names[];
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/pci_iommu.c linux/arch/alpha/kernel/pci_iommu.c
--- v2.3.42/linux/arch/alpha/kernel/pci_iommu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/pci_iommu.c	Mon Feb  7 20:09:33 2000
@@ -0,0 +1,531 @@
+/*
+ *	linux/arch/alpha/kernel/pci_iommu.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/hwrpb.h>
+
+#include "proto.h"
+#include "pci_impl.h"
+
+
+#define DEBUG_ALLOC 0
+
+#if DEBUG_ALLOC > 0
+# define DBGA(args...)		printk(KERN_DEBUG ##args)
+#else
+# define DBGA(args...)
+#endif
+#if DEBUG_ALLOC > 1
+# define DBGA2(args...)		printk(KERN_DEBUG ##args)
+#else
+# define DBGA2(args...)
+#endif
+
+
+static inline unsigned long
+mk_iommu_pte(unsigned long paddr)
+{
+	return (paddr >> (PAGE_SHIFT-1)) | 1;
+}
+
+static inline long
+calc_npages(long bytes)
+{
+	return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
+}
+
+struct pci_iommu_arena *
+iommu_arena_new(dma_addr_t base, unsigned long window_size,
+		unsigned long align)
+{
+	unsigned long entries, mem_size, mem_pages;
+	struct pci_iommu_arena *arena;
+
+	entries = window_size >> PAGE_SHIFT;
+	mem_size = entries * sizeof(unsigned long);
+	mem_pages = calc_npages(mem_size);
+
+	arena = alloc_bootmem(sizeof(*arena));
+	arena->ptes = __alloc_bootmem(mem_pages * PAGE_SIZE, align, 0);
+
+	spin_lock_init(&arena->lock);
+	arena->dma_base = base;
+	arena->size = window_size;
+	arena->alloc_hint = 0;
+
+	return arena;
+}
+
+long
+iommu_arena_alloc(struct pci_iommu_arena *arena, long n)
+{
+	unsigned long flags;
+	unsigned long *beg, *p, *end;
+	long i;
+
+	spin_lock_irqsave(&arena->lock, flags);
+
+	/* Search forward for the first sequence of N empty ptes.  */
+	beg = arena->ptes;
+	end = beg + (arena->size >> PAGE_SHIFT);
+	p = beg + arena->alloc_hint;
+	i = 0;
+	while (i < n && p < end)
+		i = (*p++ == 0 ? i + 1 : 0);
+
+	if (p >= end) {
+		/* Failure.  Assume the hint was wrong and go back to
+		   search from the beginning.  */
+		p = beg;
+		i = 0;
+		while (i < n && p < end)
+			i = (*p++ == 0 ? i + 1 : 0);
+
+		if (p >= end) {
+			spin_unlock_irqrestore(&arena->lock, flags);
+			return -1;
+		}
+	}
+
+	/* Success.  Mark them all in use, ie not zero.  Typically
+	   bit zero is the valid bit, so write ~1 into everything.
+	   The chip specific bits will fill this in with something
+	   kosher when we return.  */
+	for (p = p - n, i = 0; i < n; ++i)
+		p[i] = ~1UL;
+
+	arena->alloc_hint = p - beg + n;
+	spin_unlock_irqrestore(&arena->lock, flags);
+
+	return p - beg;
+}
+
+static void
+iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
+{
+	unsigned long *p;
+	long i;
+
+	p = arena->ptes + ofs;
+	for (i = 0; i < n; ++i)
+		p[i] = 0;
+	arena->alloc_hint = ofs;
+}
+
+/* Map a single buffer of the indicate size for PCI DMA in streaming
+   mode.  The 32-bit PCI bus mastering address to use is returned.
+   Once the device is given the dma address, the device owns this memory
+   until either pci_unmap_single or pci_sync_single is performed.  */
+
+dma_addr_t
+pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size)
+{
+	struct pci_controler *hose = pdev ? pdev->sysdata : pci_isa_hose;
+	dma_addr_t max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+	struct pci_iommu_arena *arena;
+	long npages, dma_ofs, i;
+	unsigned long paddr;
+	dma_addr_t ret;
+
+	paddr = virt_to_phys(cpu_addr);
+
+	/* First check to see if we can use the direct map window.  */
+	if (paddr + size + __direct_map_base - 1 <= max_dma
+	    && paddr + size <= __direct_map_size) {
+		ret = paddr + __direct_map_base;
+
+		DBGA2("pci_map_single: [%p,%lx] -> direct %x from %p\n",
+		      cpu_addr, size, ret, __builtin_return_address(0));
+
+		return ret;
+	}
+
+	/* If the machine doesn't define a pci_tbi routine, we have to
+	   assume it doesn't support sg mapping.  */
+	if (! alpha_mv.mv_pci_tbi) {
+		printk(KERN_INFO "pci_map_single failed: no hw sg\n");
+		return 0;
+	}
+		
+	arena = hose->sg_pci;
+	if (!arena || arena->dma_base + arena->size > max_dma)
+		arena = hose->sg_isa;
+
+	npages = calc_npages((paddr & ~PAGE_MASK) + size);
+	dma_ofs = iommu_arena_alloc(arena, npages);
+	if (dma_ofs < 0) {
+		printk(KERN_INFO "pci_map_single failed: "
+		       "could not allocate dma page tables\n");
+		return 0;
+	}
+
+	paddr &= PAGE_MASK;
+	for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
+		arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);
+
+	ret = arena->dma_base + dma_ofs * PAGE_SIZE;
+	ret += (unsigned long)cpu_addr & ~PAGE_MASK;
+
+	/* ??? This shouldn't have been needed, since the entries
+	   we've just modified were not in the iommu tlb.  */
+	alpha_mv.mv_pci_tbi(hose, ret, ret + size - 1);
+
+	DBGA("pci_map_single: [%p,%lx] np %ld -> sg %x from %p\n",
+	     cpu_addr, size, npages, ret, __builtin_return_address(0));
+
+	return ret;
+}
+
+
+/* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
+   SIZE must match what was provided for in a previous pci_map_single
+   call.  All other usages are undefined.  After this call, reads by
+   the cpu to the buffer are guarenteed to see whatever the device
+   wrote there.  */
+
+void
+pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size)
+{
+	struct pci_controler *hose = pdev ? pdev->sysdata : pci_isa_hose;
+	struct pci_iommu_arena *arena;
+	long dma_ofs, npages;
+
+
+	if (dma_addr >= __direct_map_base
+	    && dma_addr < __direct_map_base + __direct_map_size) {
+		/* Nothing to do.  */
+
+		DBGA2("pci_unmap_single: direct [%x,%lx] from %p\n",
+		      dma_addr, size, __builtin_return_address(0));
+
+		return;
+	}
+
+	arena = hose->sg_pci;
+	if (!arena || dma_addr < arena->dma_base)
+		arena = hose->sg_isa;
+
+	dma_ofs = (dma_addr - arena->dma_base) >> PAGE_SHIFT;
+	if (dma_ofs * PAGE_SIZE >= arena->size) {
+		printk(KERN_ERR "Bogus pci_unmap_single: dma_addr %x "
+		       " base %x size %x\n", dma_addr, arena->dma_base,
+		       arena->size);
+		return;
+		BUG();
+	}
+
+	npages = calc_npages((dma_addr & ~PAGE_MASK) + size);
+	iommu_arena_free(arena, dma_ofs, npages);
+	alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);
+
+	DBGA2("pci_unmap_single: sg [%x,%lx] np %ld from %p\n",
+	      dma_addr, size, npages, __builtin_return_address(0));
+}
+
+
+/* Allocate and map kernel buffer using consistent mode DMA for PCI
+   device.  Returns non-NULL cpu-view pointer to the buffer if
+   successful and sets *DMA_ADDRP to the pci side dma address as well,
+   else DMA_ADDRP is undefined.  */
+
+void *
+pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
+{
+	void *cpu_addr;
+
+	cpu_addr = kmalloc(size, GFP_ATOMIC);
+	if (! cpu_addr) {
+		printk(KERN_INFO "dma_alloc_consistent: "
+		       "kmalloc failed from %p\n",
+			__builtin_return_address(0));
+		/* ??? Really atomic allocation?  Otherwise we could play
+		   with vmalloc and sg if we can't find contiguous memory.  */
+		return NULL;
+	}
+	memset(cpu_addr, 0, size);
+
+	*dma_addrp = pci_map_single(pdev, cpu_addr, size);
+	if (*dma_addrp == 0) {
+		kfree_s(cpu_addr, size);
+		return NULL;
+	}
+		
+	DBGA2("dma_alloc_consistent: %lx -> [%p,%x] from %p\n",
+	      size, cpu_addr, *dma_addrp, __builtin_return_address(0));
+
+	return cpu_addr;
+}
+
+
+/* Free and unmap a consistent DMA buffer.  CPU_ADDR and DMA_ADDR must
+   be values that were returned from pci_alloc_consistent.  SIZE must
+   be the same as what as passed into pci_alloc_consistent.
+   References to the memory and mappings assosciated with CPU_ADDR or
+   DMA_ADDR past this call are illegal.  */
+
+void
+pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr,
+		    dma_addr_t dma_addr)
+{
+	pci_unmap_single(pdev, dma_addr, size);
+	kfree_s(cpu_addr, size);
+
+	DBGA2("dma_free_consistent: [%x,%lx] from %p\n",
+	      dma_addr, size, __builtin_return_address(0));
+}
+
+
+/* Classify the elements of the scatterlist.  Write dma_address
+   of each element with:
+	0   : Not mergable.
+	1   : Followers all physically adjacent.
+	[23]: Followers all virtually adjacent.
+	-1  : Not leader.
+   Write dma_length of each leader with the combined lengths of
+   the mergable followers.  */
+
+static inline void
+sg_classify(struct scatterlist *sg, struct scatterlist *end)
+{
+	unsigned long next_vaddr;
+	struct scatterlist *leader;
+
+	leader = sg;
+	leader->dma_address = 0;
+	leader->dma_length = leader->length;
+	next_vaddr = (unsigned long)leader->address + leader->length;
+
+	for (++sg; sg < end; ++sg) {
+		unsigned long addr, len;
+		addr = (unsigned long) sg->address;
+		len = sg->length;
+
+		if (next_vaddr == addr) {
+			sg->dma_address = -1;
+			leader->dma_address |= 1;
+			leader->dma_length += len;
+		} else if (((next_vaddr | addr) & ~PAGE_MASK) == 0) {
+			sg->dma_address = -1;
+			leader->dma_address |= 2;
+			leader->dma_length += len;
+		} else {
+			leader = sg;
+			leader->dma_address = 0;
+			leader->dma_length = len;
+		}
+
+		next_vaddr = addr + len;
+	}
+}
+
+/* Given a scatterlist leader, choose an allocation method and fill
+   in the blanks.  */
+
+static inline int
+sg_fill(struct scatterlist *leader, struct scatterlist *end,
+	struct scatterlist *out, struct pci_iommu_arena *arena,
+	dma_addr_t max_dma)
+{
+	unsigned long paddr = virt_to_phys(leader->address);
+	unsigned long size = leader->dma_length;
+	struct scatterlist *sg;
+	unsigned long *ptes;
+	long npages, dma_ofs, i;
+
+	/* If everything is physically contiguous, and the addresses
+	   fall into the direct-map window, use it.  */
+	if (leader->dma_address < 2
+	    && paddr + size + __direct_map_base - 1 <= max_dma
+	    && paddr + size <= __direct_map_size) {
+		out->dma_address = paddr + __direct_map_base;
+		out->dma_length = size;
+
+		DBGA2("sg_fill: [%p,%lx] -> direct %x\n",
+		      leader->address, size, out->dma_address);
+
+		return 0;
+	}
+
+	/* Otherwise, we'll use the iommu to make the pages virtually
+	   contiguous.  */
+
+	paddr &= ~PAGE_MASK;
+	npages = calc_npages(paddr + size);
+	dma_ofs = iommu_arena_alloc(arena, npages);
+	if (dma_ofs < 0)
+		return -1;
+
+	out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
+	out->dma_length = size;
+
+	DBGA("sg_fill: [%p,%lx] -> sg %x\n",
+	     leader->address, size, out->dma_address);
+
+	ptes = &arena->ptes[dma_ofs];
+	sg = leader;
+	do {
+		paddr = virt_to_phys(sg->address);
+		npages = calc_npages((paddr & ~PAGE_MASK) + sg->length);
+
+		DBGA("        (%ld) [%p,%x]\n",
+		      sg - leader, sg->address, sg->length);
+
+		paddr &= PAGE_MASK;
+		for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
+			*ptes++ = mk_iommu_pte(paddr);
+
+		++sg;
+	} while (sg < end && sg->dma_address == -1);
+
+	return 1;
+}
+
+/* TODO: Only use the iommu when it helps.  Non-mergable scatterlist
+   entries might as well use direct mappings.  */
+
+int
+pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
+{
+	struct scatterlist *start, *end, *out;
+	struct pci_controler *hose;
+	struct pci_iommu_arena *arena;
+	dma_addr_t max_dma, fstart, fend;
+
+	/* If pci_tbi is not available, we must not be able to control
+	   an iommu.  Direct map everything, no merging.  */
+	if (! alpha_mv.mv_pci_tbi) {
+		for (end = sg + nents; sg < end; ++sg) {
+			sg->dma_address = virt_to_bus(sg->address);
+			sg->dma_length = sg->length;
+		}
+		return nents;
+	}
+
+	/* Fast path single entry scatterlists.  */
+	if (nents == 1) {
+		sg->dma_length = sg->length;
+		sg->dma_address
+		  = pci_map_single(pdev, sg->address, sg->length);
+		return sg->dma_address != 0;
+	}
+
+	hose = pdev ? pdev->sysdata : pci_isa_hose;
+	max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+	arena = hose->sg_pci;
+	if (!arena || arena->dma_base + arena->size > max_dma)
+		arena = hose->sg_isa;
+	start = sg;
+	end = sg + nents;
+	fstart = -1;
+	fend = 0;
+	
+	/* First, prepare information about the entries.  */
+	sg_classify(sg, end);
+
+	/* Second, iterate over the scatterlist leaders and allocate
+	   dma space as needed.  */
+	for (out = sg; sg < end; ++sg) {
+		int ret;
+
+		if (sg->dma_address == -1)
+			continue;
+
+		ret = sg_fill(sg, end, out, arena, max_dma);
+		if (ret < 0)
+			goto error;
+		else if (ret > 0) {
+			dma_addr_t ts, te;
+
+			ts = out->dma_address;
+			te = ts + out->dma_length - 1;
+			if (fstart > ts)
+				fstart = ts;
+			if (fend < te)
+				fend = te;
+		}
+		out++;
+	}
+
+	/* ??? This shouldn't have been needed, since the entries
+	   we've just modified were not in the iommu tlb.  */
+	if (fend)
+		alpha_mv.mv_pci_tbi(hose, fstart, fend);
+
+	if (out - start == 0)
+		printk(KERN_INFO "pci_map_sg failed: no entries?\n");
+
+	return out - start;
+
+error:
+	printk(KERN_INFO "pci_map_sg failed: "
+	       "could not allocate dma page tables\n");
+
+	/* Some allocation failed while mapping the scatterlist
+	   entries.  Unmap them now.  */
+	if (out > start)
+		pci_unmap_sg(pdev, start, out - start);
+	return 0;
+}
+
+
+/* Unmap a set of streaming mode DMA translations.  Again, cpu read
+   rules concerning calls here are the same as for pci_unmap_single()
+   above.  */
+
+void
+pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
+{
+	struct pci_controler *hose;
+	struct pci_iommu_arena *arena;
+	struct scatterlist *end;
+	dma_addr_t max_dma;
+	dma_addr_t fstart, fend;
+
+	if (! alpha_mv.mv_pci_tbi)
+		return;
+
+	hose = pdev ? pdev->sysdata : pci_isa_hose;
+	max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+	arena = hose->sg_pci;
+	if (!arena || arena->dma_base + arena->size > max_dma)
+		arena = hose->sg_isa;
+	fstart = -1;
+	fend = 0;
+
+	for (end = sg + nents; sg < end; ++sg) {
+		unsigned long addr, size;
+
+		addr = sg->dma_address;
+		size = sg->dma_length;
+
+		if (addr >= __direct_map_base
+		    && addr < __direct_map_base + __direct_map_size) {
+			/* Nothing to do.  */
+			DBGA2("pci_unmap_sg: direct [%lx,%lx]\n", addr, size);
+		} else {
+			long npages, ofs;
+			dma_addr_t tend;
+
+			npages = calc_npages((addr & ~PAGE_MASK) + size);
+			ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
+			iommu_arena_free(arena, ofs, npages);
+
+			tend = addr + size - 1;
+			if (fstart > addr)
+				fstart = addr;
+			if (fend < tend)
+				fend = tend;
+
+			DBGA2("pci_unmap_sg: sg [%lx,%lx]\n", addr, size);
+		}
+	}
+	if (fend)
+		alpha_mv.mv_pci_tbi(hose, fstart, fend);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- v2.3.42/linux/arch/alpha/kernel/proto.h	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/proto.h	Mon Feb  7 20:09:05 2000
@@ -9,55 +9,65 @@
 struct pt_regs;
 struct task_struct;
 struct pci_dev;
+struct pci_controler;
 
 /* core_apecs.c */
 extern struct pci_ops apecs_pci_ops;
 extern void apecs_init_arch(void);
 extern void apecs_pci_clr_err(void);
 extern void apecs_machine_check(u64, u64, struct pt_regs *);
+extern void apecs_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
 
 /* core_cia.c */
 extern struct pci_ops cia_pci_ops;
 extern void cia_init_arch(void);
 extern void cia_machine_check(u64, u64, struct pt_regs *);
+extern void cia_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
 
 /* core_irongate.c */
 extern struct pci_ops irongate_pci_ops;
 extern int irongate_pci_clr_err(void);
 extern void irongate_init_arch(void);
 extern void irongate_machine_check(u64, u64, struct pt_regs *);
+#define irongate_pci_tbi ((void *)0)
 
 /* core_lca.c */
 extern struct pci_ops lca_pci_ops;
 extern void lca_init_arch(void);
 extern void lca_machine_check(u64, u64, struct pt_regs *);
+extern void lca_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
 
 /* core_mcpcia.c */
 extern struct pci_ops mcpcia_pci_ops;
 extern void mcpcia_init_arch(void);
 extern void mcpcia_init_hoses(void);
 extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
+extern void mcpcia_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
 
 /* core_polaris.c */
 extern struct pci_ops polaris_pci_ops;
 extern void polaris_init_arch(void);
 extern void polaris_machine_check(u64, u64, struct pt_regs *);
+#define polaris_pci_tbi ((void *)0)
 
 /* core_pyxis.c */
 extern struct pci_ops pyxis_pci_ops;
 extern void pyxis_init_arch(void);
 extern void pyxis_machine_check(u64, u64, struct pt_regs *);
+extern void pyxis_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
 
 /* core_t2.c */
 extern struct pci_ops t2_pci_ops;
 extern void t2_init_arch(void);
 extern void t2_machine_check(u64, u64, struct pt_regs *);
+#define t2_pci_tbi ((void *)0)
 
 /* core_tsunami.c */
 extern struct pci_ops tsunami_pci_ops;
 extern void tsunami_init_arch(void);
 extern void tsunami_kill_arch(int);
 extern void tsunami_machine_check(u64, u64, struct pt_regs *);
+extern void tsunami_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
 
 /* setup.c */
 extern unsigned long srm_hae;
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/semaphore.c linux/arch/alpha/kernel/semaphore.c
--- v2.3.42/linux/arch/alpha/kernel/semaphore.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/alpha/kernel/semaphore.c	Mon Feb  7 20:09:05 2000
@@ -36,7 +36,9 @@
  * critical part is the inline stuff in <asm/semaphore.h>
  * where we want to avoid any extra jumps and calls.
  */
-void __up(struct semaphore *sem)
+
+void
+__up(struct semaphore *sem)
 {
 	wake_one_more(sem);
 	wake_up(&sem->wait);
@@ -63,7 +65,7 @@
 #define DOWN_VAR				\
 	struct task_struct *tsk = current;	\
 	wait_queue_t wait;			\
-	init_waitqueue_entry(&wait, tsk);
+	init_waitqueue_entry(&wait, tsk)
 
 #define DOWN_HEAD(task_state)						\
 									\
@@ -92,23 +94,27 @@
 		tsk->state = (task_state);	\
 	}					\
 	tsk->state = TASK_RUNNING;		\
-	remove_wait_queue(&sem->wait, &wait);
+	remove_wait_queue(&sem->wait, &wait)
 
-void __down(struct semaphore * sem)
+void
+__down(struct semaphore * sem)
 {
-	DOWN_VAR
-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+	DOWN_VAR;
+	DOWN_HEAD(TASK_UNINTERRUPTIBLE);
+
 	if (waking_non_zero(sem))
 		break;
 	schedule();
-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+
+	DOWN_TAIL(TASK_UNINTERRUPTIBLE);
 }
 
-int __down_interruptible(struct semaphore * sem)
+int
+__down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-	DOWN_VAR
-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+	DOWN_VAR;
+	DOWN_HEAD(TASK_INTERRUPTIBLE);
 
 	ret = waking_non_zero_interruptible(sem, tsk);
 	if (ret)
@@ -119,11 +125,149 @@
 		break;
 	}
 	schedule();
-	DOWN_TAIL(TASK_INTERRUPTIBLE)
+
+	DOWN_TAIL(TASK_INTERRUPTIBLE);
 	return ret;
 }
 
-int __down_trylock(struct semaphore * sem)
+int
+__down_trylock(struct semaphore * sem)
 {
 	return waking_non_zero_trylock(sem);
+}
+
+
+/*
+ * RW Semaphores
+ */
+
+void
+__down_read(struct rw_semaphore *sem, int count)
+{
+	long tmp;
+	DOWN_VAR;
+
+ retry_down:
+	if (count < 0) {
+		/* Wait for the lock to become unbiased.  Readers
+		   are non-exclusive.  */
+		
+		/* This takes care of granting the lock.  */
+		up_read(sem);
+
+		add_wait_queue(&sem->wait, &wait);
+		while (sem->count < 0) {
+			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			if (sem->count >= 0)
+				break;
+			schedule();
+		}
+
+		remove_wait_queue(&sem->wait, &wait);
+		tsk->state = TASK_RUNNING;
+
+		__asm __volatile (
+			"	mb\n"
+			"1:	ldl_l	%0,%1\n"
+			"	subl	%0,1,%2\n"
+			"	subl	%0,1,%0\n"
+			"	stl_c	%2,%1\n"
+			"	bne	%2,2f\n"
+			".section .text2,\"ax\"\n"
+			"2:	br	1b\n"
+			".previous"
+			: "=r"(count), "=m"(sem->count), "=r"(tmp)
+			: : "memory");
+		if (count <= 0)
+			goto retry_down;
+	} else {
+		add_wait_queue(&sem->wait, &wait);
+
+		while (1) {
+			if (test_and_clear_bit(0, &sem->granted))
+				break;
+			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			if ((sem->granted & 1) == 0)
+				schedule();
+		}
+
+		remove_wait_queue(&sem->wait, &wait);
+		tsk->state = TASK_RUNNING;
+	}
+}
+
+void
+__down_write(struct rw_semaphore *sem, int count)
+{
+	long tmp;
+	DOWN_VAR;
+
+ retry_down:
+	if (count + RW_LOCK_BIAS < 0) {
+		up_write(sem);
+
+		add_wait_queue_exclusive(&sem->wait, &wait);
+	
+		while (sem->count < 0) {
+			set_task_state(tsk, (TASK_UNINTERRUPTIBLE
+					     | TASK_EXCLUSIVE));
+			if (sem->count >= RW_LOCK_BIAS)
+				break;
+			schedule();
+		}
+
+		remove_wait_queue(&sem->wait, &wait);
+		tsk->state = TASK_RUNNING;
+
+		__asm __volatile (
+			"	mb\n"
+			"1:	ldl_l	%0,%1\n"
+			"	ldah	%2,%3(%0)\n"
+			"	ldah	%0,%3(%0)\n"
+			"	stl_c	%2,%1\n"
+			"	bne	%2,2f\n"
+			".section .text2,\"ax\"\n"
+			"2:	br	1b\n"
+			".previous"
+			: "=r"(count), "=m"(sem->count), "=r"(tmp)
+			: "i"(-(RW_LOCK_BIAS >> 16))
+			: "memory");
+		if (count != 0)
+			goto retry_down;
+	} else {
+		/* Put ourselves at the end of the list.  */
+		add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
+
+		while (1) {
+			if (test_and_clear_bit(1, &sem->granted))
+				break;
+			set_task_state(tsk, (TASK_UNINTERRUPTIBLE
+					     | TASK_EXCLUSIVE));
+			if ((sem->granted & 2) == 0)
+				schedule();
+		}
+
+		remove_wait_queue(&sem->write_bias_wait, &wait);
+		tsk->state = TASK_RUNNING;
+
+		/* If the lock is currently unbiased, awaken the sleepers.
+		   FIXME: This wakes up the readers early in a bit of a
+		   stampede -> bad!  */
+		if (sem->count >= 0)
+			wake_up(&sem->wait);
+	}
+}
+
+void
+__do_rwsem_wake(struct rw_semaphore *sem, int readers)
+{
+	if (readers) {
+		if (test_and_set_bit(0, &sem->granted))
+			BUG();
+		wake_up(&sem->wait);
+	} else {
+		if (test_and_set_bit(1, &sem->granted))
+			BUG();
+		wake_up(&sem->write_bias_wait);
+	}
 }
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.3.42/linux/arch/alpha/kernel/setup.c	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/setup.c	Mon Feb  7 20:09:33 2000
@@ -96,6 +96,13 @@
 	orig_video_points: 16
 };
 
+/*
+ * The direct map I/O window, if any.  This should be the same
+ * for all busses, since it's used by virt_to_bus.
+ */
+
+unsigned long __direct_map_base;
+unsigned long __direct_map_size;
 
 /*
  * Declare all of the machine vectors.
@@ -225,15 +232,8 @@
 			max_low_pfn = end;
 	}
 
-	/* Enforce maximum of 2GB even if there is more.  Blah.  */
-	if (max_low_pfn > PFN_MAX)
-		max_low_pfn = PFN_MAX;
-	printk("max_low_pfn %ld\n", max_low_pfn);
-
 	/* Find the end of the kernel memory.  */
 	start_pfn = PFN_UP(virt_to_phys(_end));
-	printk("_end %p, start_pfn %ld\n", _end, start_pfn);
-
 	bootmap_start = -1;
 
  try_again:
@@ -243,7 +243,6 @@
 	/* We need to know how many physically contigous pages
 	   we'll need for the bootmap.  */
 	bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
-	printk("bootmap size: %ld pages\n", bootmap_pages);
 
 	/* Now find a good region where to allocate the bootmap.  */
 	for_each_mem_cluster(memdesc, cluster, i) {
@@ -261,8 +260,6 @@
 		if (end > max_low_pfn)
 			end = max_low_pfn;
 		if (end - start >= bootmap_pages) {
-			printk("allocating bootmap in area %ld:%ld\n",
-			       start, start+bootmap_pages);
 			bootmap_start = start;
 			break;
 		}
@@ -270,8 +267,6 @@
 
 	if (bootmap_start == -1) {
 		max_low_pfn >>= 1;
-		printk("bootmap area not found now trying with %ld pages\n",
-		       max_low_pfn);
 		goto try_again;
 	}
 
@@ -304,8 +299,6 @@
 
 	/* Reserve the bootmap memory.  */
 	reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size);
-	printk("reserving bootmap %ld:%ld\n", bootmap_start,
-	       bootmap_start + PFN_UP(bootmap_size));
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	initrd_start = INITRD_START;
@@ -328,27 +321,26 @@
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
-int __init page_is_ram(unsigned long pfn)
+int __init
+page_is_ram(unsigned long pfn)
 {
 	struct memclust_struct * cluster;
 	struct memdesc_struct * memdesc;
 	int i;
 
-	memdesc = (struct memdesc_struct *) (hwrpb->mddt_offset + (unsigned long) hwrpb);
+	memdesc = (struct memdesc_struct *)
+		(hwrpb->mddt_offset + (unsigned long) hwrpb);
 	for_each_mem_cluster(memdesc, cluster, i)
 	{
 		if (pfn >= cluster->start_pfn  &&
-		    pfn < cluster->start_pfn + cluster->numpages)
-		{
-			if (cluster->usage & 3)
-				return 0;
-			else
-				return 1;
+		    pfn < cluster->start_pfn + cluster->numpages) {
+			return (cluster->usage & 3) ? 0 : 1;
 		}
 	}
 
 	return 0;
 }
+
 #undef PFN_UP
 #undef PFN_DOWN
 #undef PFN_PHYS
@@ -369,8 +361,7 @@
 
 	/* Hack for Jensen... since we're restricted to 8 or 16 chars for
 	   boot flags depending on the boot mode, we need some shorthand.
-	   This should do for installation.  Later we'll add other
-	   abbreviations as well... */
+	   This should do for installation.  */
 	if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
 		strcpy(command_line, "root=/dev/fd0 load_ramdisk=1");
 	} else {
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.3.42/linux/arch/alpha/kernel/smp.c	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/smp.c	Wed Feb  9 19:33:13 2000
@@ -51,9 +51,9 @@
 } ipi_data[NR_CPUS] __cacheline_aligned;
 
 enum ipi_message_type {
-        IPI_RESCHEDULE,
-        IPI_CALL_FUNC,
-        IPI_CPU_STOP,
+	IPI_RESCHEDULE,
+	IPI_CALL_FUNC,
+	IPI_CPU_STOP,
 };
 
 spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
@@ -70,7 +70,7 @@
 int smp_threads_ready;		/* True once the per process idle is forked. */
 cycles_t cacheflush_time;
 
-int cpu_number_map[NR_CPUS];
+int __cpu_number_map[NR_CPUS];
 int __cpu_logical_map[NR_CPUS];
 
 extern void calibrate_delay(void);
@@ -426,13 +426,13 @@
 	if (fork_by_hand() < 0)
 		panic("failed fork for CPU %d", cpuid);
 
-        idle = init_task.prev_task;
-        if (!idle)
-                panic("No idle process for CPU %d", cpuid);
+	idle = init_task.prev_task;
+	if (!idle)
+		panic("No idle process for CPU %d", cpuid);
 
 	idle->processor = cpuid;
 	__cpu_logical_map[cpunum] = cpuid;
-	cpu_number_map[cpuid] = cpunum;
+	__cpu_number_map[cpuid] = cpunum;
 	idle->has_cpu = 1; /* we schedule the first task manually */
  
 	del_from_runqueue(idle);
@@ -461,7 +461,7 @@
 
 	/* we must invalidate our stuff as we failed to boot the CPU */
 	__cpu_logical_map[cpunum] = -1;
-	cpu_number_map[cpuid] = -1;
+	__cpu_number_map[cpuid] = -1;
 
 	/* the idle task is local to us so free it as we don't use it */
 	free_task_struct(idle);
@@ -534,11 +534,11 @@
 	unsigned long bogosum;
 
 	/* Take care of some initial bookkeeping.  */
-	memset(cpu_number_map, -1, sizeof(cpu_number_map));
+	memset(__cpu_number_map, -1, sizeof(__cpu_number_map));
 	memset(__cpu_logical_map, -1, sizeof(__cpu_logical_map));
 	memset(ipi_data, 0, sizeof(ipi_data));
 
-	cpu_number_map[smp_boot_cpuid] = 0;
+	__cpu_number_map[smp_boot_cpuid] = 0;
 	__cpu_logical_map[0] = smp_boot_cpuid;
 	current->processor = smp_boot_cpuid;
 
@@ -554,7 +554,7 @@
 
 	/* Nothing to do on a UP box, or when told not to.  */
 	if (smp_num_probed == 1 || max_cpus == 0) {
-	        printk(KERN_INFO "SMP mode deactivated.\n");
+		printk(KERN_INFO "SMP mode deactivated.\n");
 		return;
 	}
 
@@ -565,7 +565,7 @@
 		if (i == smp_boot_cpuid)
 			continue;
 
-	        if (((cpu_present_mask >> i) & 1) == 0)
+		if (((cpu_present_mask >> i) & 1) == 0)
 			continue;
 
 		if (smp_boot_one_cpu(i, cpu_count))
@@ -580,10 +580,10 @@
 	}
 
 	bogosum = 0;
-        for (i = 0; i < NR_CPUS; i++) {
+	for (i = 0; i < NR_CPUS; i++) {
 		if (cpu_present_mask & (1L << i))
 			bogosum += cpu_data[i].loops_per_sec;
-        }
+	}
 	printk(KERN_INFO "SMP: Total of %d processors activated "
 	       "(%lu.%02lu BogoMIPS).\n",
 	       cpu_count, (bogosum + 2500) / 500000,
@@ -605,7 +605,7 @@
 
 
 extern void update_one_process(struct task_struct *p, unsigned long ticks,
-	                       unsigned long user, unsigned long system,
+			       unsigned long user, unsigned long system,
 			       int cpu);
 
 void
@@ -626,13 +626,13 @@
 		irq_enter(cpu, TIMER_IRQ);
 
 		update_one_process(current, 1, user, !user, cpu);
-	        if (current->pid) {
-	                if (--current->counter <= 0) {
+		if (current->pid) {
+			if (--current->counter <= 0) {
 				current->counter = 0;
-	                        current->need_resched = 1;
-	                }
+				current->need_resched = 1;
+			}
 
-	                if (user) {
+			if (user) {
 				if (current->priority < DEF_PRIORITY) {
 					kstat.cpu_nice++;
 					kstat.per_cpu_nice[cpu]++;
@@ -640,11 +640,11 @@
 					kstat.cpu_user++;
 					kstat.per_cpu_user[cpu]++;
 				}
-	                } else {
+			} else {
 				kstat.cpu_system++;
 				kstat.per_cpu_system[cpu]++;
-	                }
-	        }
+			}
+		}
 
 		data->prof_counter = data->prof_multiplier;
 		irq_exit(cpu, TIMER_IRQ);
@@ -722,7 +722,7 @@
 		return -EBUSY;
 
 	while (*(void **)lock)
-		schedule();
+		barrier();
 	goto again;
 }
 
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/sys_jensen.c linux/arch/alpha/kernel/sys_jensen.c
--- v2.3.42/linux/arch/alpha/kernel/sys_jensen.c	Tue Dec  7 09:32:39 1999
+++ linux/arch/alpha/kernel/sys_jensen.c	Mon Feb  7 20:09:05 2000
@@ -111,11 +111,20 @@
 }
 
 static void
+jensen_init_arch(void)
+{
+	__direct_map_base = 0;
+	__direct_map_size = 0xffffffff;
+}
+
+static void
 jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
 {
 	printk(KERN_CRIT "Machine check\n");
 }
 
+#define jensen_pci_tbi	((void*)0)
+
 
 /*
  * The System Vector
@@ -136,7 +145,7 @@
 	ack_irq:		common_ack_irq,
 	device_interrupt:	jensen_device_interrupt,
 
-	init_arch:		NULL,
+	init_arch:		jensen_init_arch,
 	init_irq:		jensen_init_irq,
 	init_pit:		common_init_pit,
 	init_pci:		NULL,
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c
--- v2.3.42/linux/arch/alpha/kernel/sys_sio.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/alpha/kernel/sys_sio.c	Mon Feb  7 20:09:05 2000
@@ -55,52 +55,6 @@
 }
 
 static inline void __init
-xl_init_arch(void)
-{
-	struct pci_controler *hose;
-
-	/*
-	 * Set up the PCI->physical memory translation windows.  For
-	 * the XL we *must* use both windows, in order to maximize the
-	 * amount of physical memory that can be used to DMA from the
-	 * ISA bus, and still allow PCI bus devices access to all of
-	 * host memory.
-	 *
-	 * See <asm/apecs.h> for window bases and sizes.
-	 *
-	 * This restriction due to the true XL motherboards' 82379AB SIO
-	 * PCI<->ISA bridge chip which passes only 27 bits of address...
-	 */
-
-	*(vuip)APECS_IOC_PB1R = 1<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U);
-	*(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U;
-	*(vuip)APECS_IOC_TB1R = 0;
-
-	*(vuip)APECS_IOC_PB2R = 1<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U);
-	*(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U;
-	*(vuip)APECS_IOC_TB2R = 0;
-
-	/*
-	 * Finally, clear the HAXR2 register, which gets used for PCI
-	 * Config Space accesses. That is the way we want to use it,
-	 * and we do not want to depend on what ARC or SRM might have
-	 * left behind...
-	 */
-
-	*(vuip)APECS_IOC_HAXR2 = 0; mb();
-
-	/*
-	 * Create our single hose.
-	 */
-
-	hose = alloc_pci_controler();
-	hose->io_space = &ioport_resource;
-	hose->mem_space = &iomem_resource;
-	hose->config_space = LCA_CONF;
-	hose->index = 0;
-}
-
-static inline void __init
 alphabook1_init_arch(void)
 {
 	/* The AlphaBook1 has LCD video fixed at 800x600,
@@ -448,7 +402,7 @@
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	BUS(apecs_xl),
+	BUS(apecs),
 	machine_check:		apecs_machine_check,
 	max_dma_address:	ALPHA_XL_MAX_DMA_ADDRESS,
 	min_io_address:		DEFAULT_IO_BASE,
@@ -460,7 +414,7 @@
 	ack_irq:		common_ack_irq,
 	device_interrupt:	isa_device_interrupt,
 
-	init_arch:		xl_init_arch,
+	init_arch:		lca_init_arch,
 	init_irq:		sio_init_irq,
 	init_pit:		common_init_pit,
 	init_pci:		noname_init_pci,
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/lib/semaphore.S linux/arch/alpha/lib/semaphore.S
--- v2.3.42/linux/arch/alpha/lib/semaphore.S	Wed Jan 27 10:18:03 1999
+++ linux/arch/alpha/lib/semaphore.S	Mon Feb  7 20:09:05 2000
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/alpha/lib/semaphore.S
  *
- *  Copyright (C) 1999  Richard Henderson
+ *  Copyright (C) 1999, 2000  Richard Henderson
  */
 
 /*
@@ -181,3 +181,168 @@
 	lda	$30, 20*8($30)
 	ret	$31, ($28), 0
 	.end	__up_wakeup
+
+/* __down_read_failed takes the semaphore in $24, count in $25;
+   clobbers $24, $25 and $28.  */
+
+	.globl	__down_read_failed
+	.ent	__down_read_failed
+__down_read_failed:
+	ldgp	$29,0($27)
+	lda	$30, -18*8($30)
+	stq	$28, 0*8($30)
+	stq	$0, 1*8($30)
+	stq	$1, 2*8($30)
+	stq	$2, 3*8($30)
+	stq	$3, 4*8($30)
+	stq	$4, 5*8($30)
+	stq	$5, 6*8($30)
+	stq	$6, 7*8($30)
+	stq	$7, 8*8($30)
+	stq	$16, 9*8($30)
+	stq	$17, 10*8($30)
+	stq	$18, 11*8($30)
+	stq	$19, 12*8($30)
+	stq	$20, 13*8($30)
+	stq	$21, 14*8($30)
+	stq	$22, 15*8($30)
+	stq	$23, 16*8($30)
+	stq	$26, 17*8($30)
+	.frame $30, 18*8, $28
+	.prologue 1
+	
+	mov	$24, $16
+	mov	$25, $17
+	jsr	__down_read
+	
+	ldq	$28, 0*8($30)
+	ldq	$0, 1*8($30)
+	ldq	$1, 2*8($30)
+	ldq	$2, 3*8($30)
+	ldq	$3, 4*8($30)
+	ldq	$4, 5*8($30)
+	ldq	$5, 6*8($30)
+	ldq	$6, 7*8($30)
+	ldq	$7, 8*8($30)
+	ldq	$16, 9*8($30)
+	ldq	$17, 10*8($30)
+	ldq	$18, 11*8($30)
+	ldq	$19, 12*8($30)
+	ldq	$20, 13*8($30)
+	ldq	$21, 14*8($30)
+	ldq	$22, 15*8($30)
+	ldq	$23, 16*8($30)
+	ldq	$26, 17*8($30)
+	lda	$30, 18*8($30)
+	ret	$31, ($28), 0
+	.end	__down_read_failed
+
+/* __down_write_failed takes the semaphore in $24, count in $25;
+   clobbers $24, $25 and $28.  */
+
+	.globl	__down_write_failed
+	.ent	__down_write_failed
+__down_write_failed:
+	ldgp	$29,0($27)
+	lda	$30, -20*8($30)
+	stq	$28, 0*8($30)
+	stq	$0, 1*8($30)
+	stq	$1, 2*8($30)
+	stq	$2, 3*8($30)
+	stq	$3, 4*8($30)
+	stq	$4, 5*8($30)
+	stq	$5, 6*8($30)
+	stq	$6, 7*8($30)
+	stq	$7, 8*8($30)
+	stq	$16, 9*8($30)
+	stq	$17, 10*8($30)
+	stq	$18, 11*8($30)
+	stq	$19, 12*8($30)
+	stq	$20, 13*8($30)
+	stq	$21, 14*8($30)
+	stq	$22, 15*8($30)
+	stq	$23, 16*8($30)
+	stq	$26, 17*8($30)
+	.frame $30, 18*8, $28
+	.prologue 1
+	
+	mov	$24, $16
+	mov	$25, $17
+	jsr	__down_write
+	
+	ldq	$28, 0*8($30)
+	ldq	$0, 1*8($30)
+	ldq	$1, 2*8($30)
+	ldq	$2, 3*8($30)
+	ldq	$3, 4*8($30)
+	ldq	$4, 5*8($30)
+	ldq	$5, 6*8($30)
+	ldq	$6, 7*8($30)
+	ldq	$7, 8*8($30)
+	ldq	$16, 9*8($30)
+	ldq	$17, 10*8($30)
+	ldq	$18, 11*8($30)
+	ldq	$19, 12*8($30)
+	ldq	$20, 13*8($30)
+	ldq	$21, 14*8($30)
+	ldq	$22, 15*8($30)
+	ldq	$23, 16*8($30)
+	ldq	$26, 17*8($30)
+	lda	$30, 18*8($30)
+	ret	$31, ($28), 0
+	.end	__down_write_failed
+
+/* __rwsem_wake takes the semaphore in $24, readers in $25;
+   clobbers $24, $25, and $28.  */
+
+	.globl	__rwsem_wake
+	.ent	__rwsem_wake
+__rwsem_wake:
+	ldgp	$29,0($27)
+	lda	$30, -18*8($30)
+	stq	$28, 0*8($30)
+	stq	$0, 1*8($30)
+	stq	$1, 2*8($30)
+	stq	$2, 3*8($30)
+	stq	$3, 4*8($30)
+	stq	$4, 5*8($30)
+	stq	$5, 6*8($30)
+	stq	$6, 7*8($30)
+	stq	$7, 8*8($30)
+	stq	$16, 9*8($30)
+	stq	$17, 10*8($30)
+	stq	$18, 11*8($30)
+	stq	$19, 12*8($30)
+	stq	$20, 13*8($30)
+	stq	$21, 14*8($30)
+	stq	$22, 15*8($30)
+	stq	$23, 16*8($30)
+	stq	$26, 17*8($30)
+	.frame $30, 18*8, $28
+	.prologue 1
+	
+	mov	$24, $16
+	mov	$25, $17
+	jsr	__do_rwsem_wake
+	
+	ldq	$28, 0*8($30)
+	ldq	$0, 1*8($30)
+	ldq	$1, 2*8($30)
+	ldq	$2, 3*8($30)
+	ldq	$3, 4*8($30)
+	ldq	$4, 5*8($30)
+	ldq	$5, 6*8($30)
+	ldq	$6, 7*8($30)
+	ldq	$7, 8*8($30)
+	ldq	$16, 9*8($30)
+	ldq	$17, 10*8($30)
+	ldq	$18, 11*8($30)
+	ldq	$19, 12*8($30)
+	ldq	$20, 13*8($30)
+	ldq	$21, 14*8($30)
+	ldq	$22, 15*8($30)
+	ldq	$23, 16*8($30)
+	ldq	$26, 17*8($30)
+	lda	$30, 18*8($30)
+	ret	$31, ($28), 0
+	.end	__rwsem_wake
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v2.3.42/linux/arch/alpha/mm/init.c	Fri Jan 21 18:19:15 2000
+++ linux/arch/alpha/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -34,7 +34,6 @@
 static unsigned long totalram_pages;
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
-extern void show_net_buffers(void);
 
 struct thread_struct original_pcb;
 
@@ -173,9 +172,6 @@
 	printk("%ld pages swap cached\n",cached);
 	printk("%ld pages in page table cache\n",pgtable_cache_size);
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 }
 
 static inline unsigned long
@@ -195,7 +191,7 @@
 {
 	unsigned long newptbr;
 	unsigned long original_pcb_ptr;
-	unsigned int zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
 	unsigned long dma_pfn, high_pfn;
 
 	dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
diff -u --recursive --new-file v2.3.42/linux/arch/alpha/vmlinux.lds linux/arch/alpha/vmlinux.lds
--- v2.3.42/linux/arch/alpha/vmlinux.lds	Tue Aug 31 17:29:12 1999
+++ linux/arch/alpha/vmlinux.lds	Mon Feb  7 20:09:05 2000
@@ -82,4 +82,6 @@
   .debug_funcnames 0 : { *(.debug_funcnames) }
   .debug_typenames 0 : { *(.debug_typenames) }
   .debug_varnames  0 : { *(.debug_varnames) }
+
+  /DISCARD/ : { *(.text.exit) *(.data.exit) }
 }
diff -u --recursive --new-file v2.3.42/linux/arch/arm/def-configs/a5k linux/arch/arm/def-configs/a5k
--- v2.3.42/linux/arch/arm/def-configs/a5k	Fri Jan 21 18:19:15 2000
+++ linux/arch/arm/def-configs/a5k	Sun Feb  6 17:45:25 2000
@@ -167,6 +167,11 @@
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
 # CONFIG_DRM_TDFX is not set
+
+#
+# PCMCIA character device support
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
 # CONFIG_AGP is not set
 
 #
@@ -322,6 +327,11 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
 
 #
 # SCSI support
diff -u --recursive --new-file v2.3.42/linux/arch/arm/def-configs/footbridge linux/arch/arm/def-configs/footbridge
--- v2.3.42/linux/arch/arm/def-configs/footbridge	Fri Jan 21 18:19:15 2000
+++ linux/arch/arm/def-configs/footbridge	Sun Feb  6 17:45:25 2000
@@ -54,6 +54,7 @@
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_PCMCIA is not set
 # CONFIG_PARPORT_ARC is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
@@ -264,6 +265,12 @@
 # CONFIG_DRM_TDFX is not set
 
 #
+# PCMCIA character device support
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_AGP is not set
+
+#
 # Support for USB
 #
 CONFIG_USB=m
@@ -495,6 +502,11 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
 
 #
 # SCSI support
diff -u --recursive --new-file v2.3.42/linux/arch/arm/def-configs/rpc linux/arch/arm/def-configs/rpc
--- v2.3.42/linux/arch/arm/def-configs/rpc	Fri Jan 21 18:19:15 2000
+++ linux/arch/arm/def-configs/rpc	Sun Feb  6 17:45:25 2000
@@ -50,6 +50,7 @@
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 # CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
 # CONFIG_PARPORT_ARC is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
@@ -176,6 +177,11 @@
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
 # CONFIG_DRM_TDFX is not set
+
+#
+# PCMCIA character device support
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
 # CONFIG_AGP is not set
 CONFIG_RPCMOUSE=y
 
@@ -347,6 +353,11 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
 
 #
 # SCSI support
diff -u --recursive --new-file v2.3.42/linux/arch/arm/defconfig linux/arch/arm/defconfig
--- v2.3.42/linux/arch/arm/defconfig	Fri Jan 21 18:19:15 2000
+++ linux/arch/arm/defconfig	Sun Feb  6 17:45:25 2000
@@ -54,6 +54,7 @@
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_PCMCIA is not set
 # CONFIG_PARPORT_ARC is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
@@ -262,6 +263,11 @@
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
 # CONFIG_DRM_TDFX is not set
+
+#
+# PCMCIA character device support
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
 # CONFIG_AGP is not set
 
 #
@@ -496,6 +502,11 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
 
 #
 # SCSI support
diff -u --recursive --new-file v2.3.42/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- v2.3.42/linux/arch/arm/kernel/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/arm/kernel/Makefile	Sun Feb  6 17:45:25 2000
@@ -16,9 +16,9 @@
   ISA_DMA_OBJS += dma-isa.o
 endif
 
-O_OBJS_arc        = dma-arc.o iic.o fiq.o oldlatches.o
-O_OBJS_a5k        = dma-a5k.o iic.o fiq.o
-O_OBJS_rpc        = dma-rpc.o iic.o fiq.o
+O_OBJS_arc        = dma-arc.o iic.o fiq.o time-acorn.o oldlatches.o
+O_OBJS_a5k        = dma-a5k.o iic.o fiq.o time-acorn.o
+O_OBJS_rpc        = dma-rpc.o iic.o fiq.o time-acorn.o
 O_OBJS_ebsa110    = dma-dummy.o
 O_OBJS_footbridge = dma-footbridge.o $(ISA_DMA_OBJS) isa.o
 O_OBJS_nexuspci   = dma-dummy.o
diff -u --recursive --new-file v2.3.42/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c
--- v2.3.42/linux/arch/arm/kernel/bios32.c	Fri Jan 21 18:19:15 2000
+++ linux/arch/arm/kernel/bios32.c	Sun Feb  6 17:45:25 2000
@@ -381,7 +381,7 @@
 	 * Assign any unassigned resources.  Note that we really ought to
 	 * have min/max stuff here - max mem address is 0x0fffffff
 	 */
-	pci_assign_unassigned_resources(hw_pci->io_start, hw_pci->mem_start);
+	pci_assign_unassigned_resources();
 	pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq);
 	pci_set_bus_ranges();
 
@@ -404,17 +404,34 @@
 	return str;
 }
 
-/*
- * Assign new address to PCI resource.  We hope our resource information
- * is complete.
- *
- * Expects start=0, end=size-1, flags=resource type.
- */
-int pci_assign_resource(struct pci_dev *dev, int i)
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
 {
-	return 0;
 }
 
-void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+int pcibios_enable_device(struct pci_dev *dev)
 {
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		r = dev->resource + idx;
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because"
+			       " of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: enabling device %s (%04x -> %04x)\n",
+		       dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
 }
diff -u --recursive --new-file v2.3.42/linux/arch/arm/kernel/time-acorn.c linux/arch/arm/kernel/time-acorn.c
--- v2.3.42/linux/arch/arm/kernel/time-acorn.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/time-acorn.c	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,71 @@
+/*
+ * linux/arch/arm/kernel/time-acorn.c
+ *
+ * Copyright (c) 1996-2000 Russell King.
+ *
+ * Changelog:
+ *  24-Sep-1996	RMK	Created
+ *  10-Oct-1996	RMK	Brought up to date with arch-sa110eval
+ *  04-Dec-1997	RMK	Updated for new arch/arm/time.c
+ */
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/ioc.h>
+#include <asm/irq.h>
+
+extern unsigned long (*gettimeoffset)(void);
+
+static unsigned long ioctime_gettimeoffset(void)
+{
+	unsigned int count1, count2, status1, status2;
+	unsigned long offset = 0;
+
+	status1 = inb(IOC_IRQREQA);
+	barrier ();
+	outb (0, IOC_T0LATCH);
+	barrier ();
+	count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
+	barrier ();
+	status2 = inb(IOC_IRQREQA);
+	barrier ();
+	outb (0, IOC_T0LATCH);
+	barrier ();
+	count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
+
+	if (count2 < count1) {
+		/*
+		 * This means that we haven't just had an interrupt
+		 * while reading into status2.
+		 */
+		if (status2 & (1 << 5))
+			offset = tick;
+		count1 = count2;
+	} else if (count2 > count1) {
+		/*
+		 * We have just had another interrupt while reading
+		 * status2.
+		 */
+		offset += tick;
+		count1 = count2;
+	}
+
+	count1 = LATCH - count1;
+	/*
+	 * count1 = number of clock ticks since last interrupt
+	 */
+	offset += count1 * tick / LATCH;
+	return offset;
+}
+
+void __init ioctime_init(void)
+{
+	outb(LATCH & 255, IOC_T0LTCHL);
+	outb(LATCH >> 8, IOC_T0LTCHH);
+	outb(0, IOC_T0GO);
+
+	gettimeoffset = ioctime_gettimeoffset;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- v2.3.42/linux/arch/arm/kernel/time.c	Fri Jan 21 18:19:15 2000
+++ linux/arch/arm/kernel/time.c	Tue Feb  8 12:01:59 2000
@@ -12,15 +12,12 @@
  * 1998-12-20  Updated NTP code according to technical memorandum Jan '96
  *             "A Kernel Model for Precision Timekeeping" by Dave Mills
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/time.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/smp.h>
 
@@ -32,6 +29,7 @@
 #include <asm/hardware.h>
 
 extern int setup_arm_irq(int, struct irqaction *);
+extern void setup_timer(void);
 extern volatile unsigned long lost_ticks;
 
 /* change this if you have some constant time drift */
@@ -45,6 +43,26 @@
 #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
 #endif
 
+static int dummy_set_rtc(void)
+{
+	return 0;
+}
+
+/*
+ * hook for setting the RTC's idea of the current time.
+ */
+int (*set_rtc)(void) = dummy_set_rtc;
+
+static unsigned long dummy_gettimeoffset(void)
+{
+	return 0;
+}
+
+/*
+ * hook for getting the time offset
+ */
+unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
+
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
@@ -60,9 +78,9 @@
  * machines were long is 32-bit! (However, as time_t is signed, we
  * will already get problems at other places on 2038-01-19 03:14:08)
  */
-unsigned long mktime(unsigned int year, unsigned int mon,
-	unsigned int day, unsigned int hour,
-	unsigned int min, unsigned int sec)
+unsigned long
+mktime(unsigned int year, unsigned int mon, unsigned int day,
+       unsigned int hour, unsigned int min, unsigned int sec)
 {
 	if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
 		mon += 12;	/* Puts Feb last since it has leap day */
@@ -77,11 +95,14 @@
 }
 
 /*
- * Handle profile stuff...
+ * Handle kernel profile stuff...
  */
-static void do_profile(unsigned long pc)
+static inline void do_profile(struct pt_regs *regs)
 {
-	if (prof_buffer && current->pid) {
+	if (!user_mode(regs) &&
+	    prof_buffer &&
+	    current->pid) {
+		unsigned long pc = instruction_pointer(regs);
 		extern int _stext;
 
 		pc -= (unsigned long)&_stext;
@@ -95,12 +116,61 @@
 	}
 }
 
-#include <asm/arch/time.h>
+static long next_rtc_update;
+
+/*
+ * If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes.  set_rtc() has to be
+ * called as close as possible to 500 ms before the new second
+ * starts.
+ */
+static inline void do_set_rtc(void)
+{
+	if (time_status & STA_UNSYNC || set_rtc == NULL)
+		return;
+
+	if (next_rtc_update &&
+	    time_before(xtime.tv_sec, next_rtc_update))
+		return;
+
+	if (xtime.tv_usec < 50000 - (tick >> 1) &&
+	    xtime.tv_usec >= 50000 + (tick >> 1))
+		return;
+
+	if (set_rtc())
+		/*
+		 * rtc update failed.  Try again in 60s
+		 */
+		next_rtc_update = xtime.tv_sec + 60;
+	else
+		next_rtc_update = xtime.tv_sec + 660;
+}
+
+#ifdef CONFIG_LEDS
 
-static unsigned long do_gettimeoffset(void)
+#include <asm/leds.h>
+
+static void do_leds(void)
 {
-	return gettimeoffset ();
+	static unsigned int count = 50;
+	static int last_pid;
+
+	if (current->pid != last_pid) {
+		last_pid = current->pid;
+		if (last_pid)
+			leds_event(led_idle_end);
+		else
+			leds_event(led_idle_start);
+	}
+		
+	if (--count == 0) {
+		count = 50;
+		leds_event(led_timer);
+	}
 }
+#else
+#define do_leds()
+#endif
 
 void do_gettimeofday(struct timeval *tv)
 {
@@ -108,7 +178,7 @@
 
 	save_flags_cli (flags);
 	*tv = xtime;
-	tv->tv_usec += do_gettimeoffset();
+	tv->tv_usec += gettimeoffset();
 
 	/*
 	 * xtime is atomically updated in timer_bh. lost_ticks is
@@ -134,7 +204,7 @@
 	 * Discover what correction gettimeofday
 	 * would have done, and then undo it!
 	 */
-	tv->tv_usec -= do_gettimeoffset();
+	tv->tv_usec -= gettimeoffset();
 
 	if (tv->tv_usec < 0) {
 		tv->tv_usec += 1000000;
@@ -149,9 +219,25 @@
 	sti();
 }
 
+static struct irqaction timer_irq = {
+	NULL, 0, 0, "timer", NULL, NULL
+};
+
+/*
+ * Include architecture specific code
+ */
+#include <asm/arch/time.h>
+
+/*
+ * This must cause the timer to start ticking.
+ * It doesn't have to set the current time though
+ * from an RTC - it can be done later once we have
+ * some buses initialised.
+ */
 void __init time_init(void)
 {
 	xtime.tv_usec = 0;
+	xtime.tv_sec  = 0;
 
 	setup_timer();
 }
diff -u --recursive --new-file v2.3.42/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.3.42/linux/arch/arm/kernel/traps.c	Fri Jan 21 18:19:15 2000
+++ linux/arch/arm/kernel/traps.c	Sun Feb  6 17:45:25 2000
@@ -370,7 +370,7 @@
 asmlinkage void
 baddataabort(int code, unsigned long instr, struct pt_regs *regs)
 {
-	unsigned long phys, addr = instruction_pointer(regs);
+	unsigned long addr = instruction_pointer(regs);
 
 #ifdef CONFIG_DEBUG_ERRORS
 	dump_instr(addr, 1);
@@ -383,11 +383,8 @@
 			pmd_t *pmd;
 			pmd = pmd_offset (pgd, addr);
 			printk (", *pmd = %08lx", pmd_val (*pmd));
-			if (!pmd_none (*pmd)) {
-				unsigned long ptr = pte_page(*pte_offset(pmd, addr));
-				printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr)));
-				phys = ptr + (addr & 0x7fff);
-			}
+			if (!pmd_none (*pmd))
+				printk (", *pte = %08lx", pte_val(*pte_offset (pmd, addr)));
 		}
 		printk ("\n");
 	}
diff -u --recursive --new-file v2.3.42/linux/arch/arm/lib/io.c linux/arch/arm/lib/io.c
--- v2.3.42/linux/arch/arm/lib/io.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/lib/io.c	Sun Feb  6 17:45:25 2000
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+#include <linux/types.h>
 
 #include <asm/io.h>
 
@@ -6,7 +7,7 @@
  * Copy data from IO memory space to "real" memory space.
  * This needs to be optimized.
  */
-void _memcpy_fromio(void * to, unsigned long from, unsigned long count)
+void _memcpy_fromio(void * to, unsigned long from, size_t count)
 {
 	while (count) {
 		count--;
@@ -20,7 +21,7 @@
  * Copy data from "real" memory space to IO memory space.
  * This needs to be optimized.
  */
-void _memcpy_toio(unsigned long to, const void * from, unsigned long count)
+void _memcpy_toio(unsigned long to, const void * from, size_t count)
 {
 	while (count) {
 		count--;
@@ -34,7 +35,7 @@
  * "memset" on IO memory space.
  * This needs to be optimized.
  */
-void _memset_io(unsigned long dst, int c, unsigned long count)
+void _memset_io(unsigned long dst, int c, size_t count)
 {
 	while (count) {
 		count--;
diff -u --recursive --new-file v2.3.42/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.3.42/linux/arch/arm/mm/init.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/arm/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -35,8 +35,6 @@
 static unsigned long totalram_pages;
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-extern void show_net_buffers(void);
-
 /*
  * empty_bad_page is the page that is used for page faults when
  * linux is out-of-memory. Older versions of linux just did a
@@ -157,9 +155,6 @@
 	printk("%ld page tables cached\n", pgtable_cache_size);
 #endif
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 }
 
 /*
diff -u --recursive --new-file v2.3.42/linux/arch/arm/mm/ioremap.c linux/arch/arm/mm/ioremap.c
--- v2.3.42/linux/arch/arm/mm/ioremap.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/arm/mm/ioremap.c	Sun Feb  6 17:45:25 2000
@@ -115,7 +115,7 @@
  * 'flags' are the extra L_PTE_ flags that you want to specify for this
  * mapping.  See include/asm-arm/proc-armv/pgtable.h for more information.
  */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void * __ioremap(unsigned long phys_addr, size_t size, unsigned long flags)
 {
 	void * addr;
 	struct vm_struct * area;
diff -u --recursive --new-file v2.3.42/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.3.42/linux/arch/arm/mm/mm-armv.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/arm/mm/mm-armv.c	Sun Feb  6 17:45:25 2000
@@ -34,6 +34,7 @@
 {
 	cr_alignment &= ~4;
 	cr_no_alignment &= ~4;
+	flush_cache_all();
 	set_cr(cr_alignment);
 	return 1;
 }
@@ -42,6 +43,7 @@
 {
 	cr_alignment &= ~(8|4);
 	cr_no_alignment &= ~(8|4);
+	flush_cache_all();
 	set_cr(cr_alignment);
 	return 1;
 }
@@ -284,7 +286,7 @@
 
 void __init pagetable_init(void)
 {
-	struct map_desc *init_maps, *p;
+	struct map_desc *init_maps, *p, *q;
 	unsigned long address = 0;
 	int i;
 
@@ -358,17 +360,18 @@
 	 * pgdir entries that are not in the description.
 	 */
 	i = 0;
+	q = init_maps;
 	do {
-		if (address < init_maps->virtual || init_maps == p) {
+		if (address < q->virtual || q == p) {
 			clear_mapping(address);
 			address += PGDIR_SIZE;
 		} else {
-			create_mapping(init_maps);
+			create_mapping(q);
 
-			address = init_maps->virtual + init_maps->length;
+			address = q->virtual + q->length;
 			address = (address + PGDIR_SIZE - 1) & PGDIR_MASK;
 
-			init_maps ++;
+			q ++;
 		}
 	} while (address != 0);
 
diff -u --recursive --new-file v2.3.42/linux/arch/i386/boot/compressed/head.S linux/arch/i386/boot/compressed/head.S
--- v2.3.42/linux/arch/i386/boot/compressed/head.S	Fri Jan  7 19:13:21 2000
+++ linux/arch/i386/boot/compressed/head.S	Mon Feb  7 19:59:39 2000
@@ -12,10 +12,6 @@
  * the page directory. [According to comments etc elsewhere on a compressed
  * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
  *
- * In SMP mode we keep this page safe. Really we ought to shuffle things and
- * put the trampoline here. - AC. An SMP trampoline enters with %cx holding
- * the stack base.
- *
  * Page 0 is deliberately kept safe, since System Management Mode code in 
  * laptops may need to access the BIOS data stored there.  This is also
  * useful for future device drivers that either access the BIOS via VM86 
@@ -41,24 +37,7 @@
 	movl %ax,%es
 	movl %ax,%fs
 	movl %ax,%gs
-#ifdef __SMP__
-	orw %bx,%bx			# What state are we in BX=1 for SMP
-					# 0 for boot
-	jz  2f				# Initial boot
 
-/*
- *	We are trampolining an SMP processor
- */
-	mov %ax,%ss
-	xorl %eax,%eax			# Back to 0
-	mov  %cx,%ax			# SP low 16 bits
-	movl %eax,%esp
-	pushl $0			# Clear NT
-	popfl
-	ljmp $(__KERNEL_CS), $0x100000	# Into C and sanity
-
-2:
-#endif
 	lss SYMBOL_NAME(stack_start),%esp
 	xorl %eax,%eax
 1:	incl %eax		# check that A20 really IS enabled
diff -u --recursive --new-file v2.3.42/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.42/linux/arch/i386/defconfig	Fri Jan 28 15:09:06 2000
+++ linux/arch/i386/defconfig	Thu Feb 10 12:44:22 2000
@@ -173,7 +173,9 @@
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_CHR_DEV_ST is not set
+CONFIG_ST_EXTRA_DEVS=2
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 
@@ -228,6 +230,7 @@
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
@@ -272,7 +275,7 @@
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
 # CONFIG_DE4X5 is not set
-# CONFIG_DEC_ELCP is not set
+# CONFIG_TULIP is not set
 # CONFIG_DGRS is not set
 CONFIG_EEXPRESS_PRO100=y
 # CONFIG_NE2K_PCI is not set
@@ -429,7 +432,6 @@
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_BFS_FS_WRITE is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.3.42/linux/arch/i386/kernel/Makefile	Fri Jan 28 15:09:06 2000
+++ linux/arch/i386/kernel/Makefile	Thu Feb 10 12:35:19 2000
@@ -40,23 +40,19 @@
   endif
 endif
 
-ifdef CONFIG_ACPI
-OX_OBJS += pm.o
-else
-ifdef CONFIG_APM
-OX_OBJS += pm.o
-endif
-endif
-
 ifeq ($(CONFIG_ACPI),y)
-  O_OBJS += acpi.o
+O_OBJS += acpi.o
+else
+  ifeq ($(CONFIG_ACPI),m)
+  M_OBJS += acpi.o
+  endif
 endif
 
 ifeq ($(CONFIG_APM),y)
-OX_OBJS += apm.o
+O_OBJS += apm.o
 else
   ifeq ($(CONFIG_APM),m)
-  MX_OBJS += apm.o
+  M_OBJS += apm.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c
--- v2.3.42/linux/arch/i386/kernel/acpi.c	Fri Jan 28 15:09:06 2000
+++ linux/arch/i386/kernel/acpi.c	Tue Feb  8 11:32:18 2000
@@ -105,7 +105,6 @@
 static int acpi_p_lvl3_tested = 0;
 
 static int acpi_disabled = 0;
-int acpi_active = 0;
 
 // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
 static unsigned long acpi_slp_typ[] = 
@@ -564,7 +563,7 @@
 /*
  * Init VIA ACPI device and create a fake FACP
  */
-static int __init acpi_init_via686a(struct pci_dev *dev)
+static int __init acpi_init_via(struct pci_dev *dev)
 {
 	u32 base;
 	u8 tmp, irq;
@@ -631,6 +630,7 @@
 {
 	CH_UNKNOWN = 0,
 	CH_INTEL_PIIX4,
+	CH_VIA_586,
 	CH_VIA_686A,
 } acpi_chip_t;
 
@@ -642,12 +642,13 @@
 {
 	{NULL,},
 	{acpi_init_piix4},
-	{acpi_init_via686a},
+	{acpi_init_via},
 };
 	
 const static struct pci_device_id acpi_pci_tbl[] =
 {
 	{0x8086, 0x7113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_INTEL_PIIX4},
+	{0x1106, 0x3040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_586},
 	{0x1106, 0x3057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_686A},
 	{0,}, /* terminate list */
 };
@@ -792,7 +793,7 @@
 /*
  * Idle loop (uniprocessor only)
  */
-static void acpi_idle_handler(void)
+static void acpi_idle(void)
 {
 	static int sleep_level = 1;
 	struct acpi_facp *facp = acpi_facp;
@@ -1009,56 +1010,63 @@
 /*
  * Enter soft-off (S5)
  */
-static void acpi_power_off_handler(void)
+static void acpi_power_off(void)
 {
 	acpi_enter_sx(ACPI_S5);
 }
 
 /*
+ * Claim I/O port if available
+ */
+static int acpi_claim(unsigned long start, unsigned long size)
+{
+	if (start && size) {
+		if (check_region(start, size))
+			return -EBUSY;
+		request_region(start, size, "acpi");
+	}
+	return 0;
+}
+
+/*
  * Claim ACPI I/O ports
  */
 static int acpi_claim_ioports(struct acpi_facp *facp)
 {
 	// we don't get a guarantee of contiguity for any of the ACPI registers
-	if (facp->pm1a_evt)
-		request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi");
-	if (facp->pm1b_evt)
-		request_region(facp->pm1b_evt, facp->pm1_evt_len, "acpi");
-	if (facp->pm1a_cnt)
-		request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi");
-	if (facp->pm1b_cnt)
-		request_region(facp->pm1b_cnt, facp->pm1_cnt_len, "acpi");
-	if (facp->pm_tmr)
-		request_region(facp->pm_tmr, facp->pm_tm_len, "acpi");
-	if (facp->gpe0)
-		request_region(facp->gpe0, facp->gpe0_len, "acpi");
-	if (facp->gpe1)
-		request_region(facp->gpe1, facp->gpe1_len, "acpi");
-
+	if (acpi_claim(facp->pm1a_evt, facp->pm1_evt_len)
+	    || acpi_claim(facp->pm1b_evt, facp->pm1_evt_len)
+	    || acpi_claim(facp->pm1a_cnt, facp->pm1_cnt_len)
+	    || acpi_claim(facp->pm1b_cnt, facp->pm1_cnt_len)
+	    || acpi_claim(facp->pm_tmr, facp->pm_tm_len)
+	    || acpi_claim(facp->gpe0, facp->gpe0_len)
+	    || acpi_claim(facp->gpe1, facp->gpe1_len))
+		return -EBUSY;
 	return 0;
 }
 
 /*
+ * Release I/O port if claimed
+ */
+static void acpi_release(unsigned long start, unsigned long size)
+{
+	if (start && size)
+		release_region(start, size);
+}
+
+/*
  * Free ACPI I/O ports
  */
 static int acpi_release_ioports(struct acpi_facp *facp)
 {
 	// we don't get a guarantee of contiguity for any of the ACPI registers
-	if (facp->pm1a_evt)
-		release_region(facp->pm1a_evt, facp->pm1_evt_len);
-	if (facp->pm1b_evt)
-		release_region(facp->pm1b_evt, facp->pm1_evt_len);
-	if (facp->pm1a_cnt)
-		release_region(facp->pm1a_cnt, facp->pm1_cnt_len);
-	if (facp->pm1b_cnt)
-		release_region(facp->pm1b_cnt, facp->pm1_cnt_len);
-	if (facp->pm_tmr)
-		release_region(facp->pm_tmr, facp->pm_tm_len);
-	if (facp->gpe0)
-		release_region(facp->gpe0, facp->gpe0_len);
-	if (facp->gpe1)
-		release_region(facp->gpe1, facp->gpe1_len);
-
+	acpi_release(facp->gpe1, facp->gpe1_len);
+	acpi_release(facp->gpe0, facp->gpe0_len);
+	acpi_release(facp->pm_tmr, facp->pm_tm_len);
+	acpi_release(facp->pm1b_cnt, facp->pm1_cnt_len);
+	acpi_release(facp->pm1a_cnt, facp->pm1_cnt_len);
+	acpi_release(facp->pm1b_evt, facp->pm1_evt_len);
+	acpi_release(facp->pm1a_evt, facp->pm1_evt_len);
 	return 0;
 }
 
@@ -1322,6 +1330,14 @@
 			= ACPI_uS_TO_TMR_TICKS(acpi_facp->p_lvl3_lat * 5);
 	}
 
+	if (acpi_claim_ioports(acpi_facp)) {
+		printk(KERN_ERR "ACPI: I/O port allocation failed\n");
+		if (pci_driver_registered)
+			pci_unregister_driver(&acpi_driver);
+		acpi_destroy_tables();
+		return -ENODEV;
+	}
+
 	if (acpi_facp->sci_int
 	    && request_irq(acpi_facp->sci_int,
 			   acpi_irq,
@@ -1338,16 +1354,15 @@
 		return -ENODEV;
 	}
 
-	acpi_claim_ioports(acpi_facp);
 	acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
 
 	pid = kernel_thread(acpi_control_thread,
 			    NULL,
 			    CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 
-	acpi_power_off = acpi_power_off_handler;
+	pm_power_off = acpi_power_off;
 
-	acpi_active = 1;
+	pm_active = 1;
 
 	/*
 	 * Set up the ACPI idle function. Note that we can't really
@@ -1360,7 +1375,7 @@
 #endif
 
 	if (acpi_facp->pm_tmr)
-		acpi_idle = acpi_idle_handler;
+		pm_idle = acpi_idle;
 
 	return 0;
 }
@@ -1370,8 +1385,8 @@
  */
 static void __exit acpi_exit(void)
 {
-	acpi_idle = NULL;
-	acpi_power_off = NULL;
+	pm_idle = NULL;
+	pm_power_off = NULL;
 
 	unregister_sysctl_table(acpi_sysctl);
 	acpi_disable(acpi_facp);
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.42/linux/arch/i386/kernel/apm.c	Fri Jan 28 15:09:06 2000
+++ linux/arch/i386/kernel/apm.c	Tue Feb  8 11:32:18 2000
@@ -150,13 +150,7 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 
-/*
- * Make APM look as much as just another ACPI module as possible..
- */
-#include <linux/acpi.h>
-
-EXPORT_SYMBOL(apm_register_callback);
-EXPORT_SYMBOL(apm_unregister_callback);
+#include <linux/pm.h>
 
 extern unsigned long get_cmos_time(void);
 extern void machine_real_restart(unsigned char *, int);
@@ -304,13 +298,6 @@
 #define NR_APM_EVENT_NAME	\
 		(sizeof(apm_event_name) / sizeof(apm_event_name[0]))
 
-typedef struct callback_list_t {
-	int (*				callback)(apm_event_t);
-	struct callback_list_t *	next;
-} callback_list_t;
-
-static callback_list_t *	callback_list = NULL;
-
 typedef struct lookup_t {
 	int	key;
 	char *	msg;
@@ -687,32 +674,6 @@
 }
 #endif
 
-int apm_register_callback(int (*callback)(apm_event_t))
-{
-	callback_list_t *	new;
-
-	new = kmalloc(sizeof(callback_list_t), GFP_KERNEL);
-	if (new == NULL)
-		return -ENOMEM;
-	new->callback = callback;
-	new->next = callback_list;
-	callback_list = new;
-	return 0;
-}
-
-void apm_unregister_callback(int (*callback)(apm_event_t))
-{
-	callback_list_t **	ptr;
-	callback_list_t *	old;
-
-	for (ptr = &callback_list; *ptr != NULL; ptr = &(*ptr)->next)
-		if ((*ptr)->callback == callback)
-			break;
-	old = *ptr;
-	*ptr = old->next;
-	kfree_s(old, sizeof(callback_list_t));
-}
-
 static int queue_empty(struct apm_bios_struct * as)
 {
 	return as->event_head == as->event_tail;
@@ -848,17 +809,26 @@
 static int send_event(apm_event_t event, apm_event_t undo,
 		       struct apm_bios_struct *sender)
 {
-	callback_list_t *	call;
-	callback_list_t *	fix;
-
-	for (call = callback_list; call != NULL; call = call->next) {
-		if (call->callback(event) && undo) {
-			for (fix = callback_list; fix != call; fix = fix->next)
-				fix->callback(undo);
+	switch (event) {
+	case APM_SYS_SUSPEND:
+	case APM_CRITICAL_SUSPEND:
+	case APM_USER_SUSPEND:
+		/* map all suspends to ACPI D3 */
+		if (pm_send_request(PM_SUSPEND, (void*) 3)) {
+			if (apm_bios_info.version > 0x100)
+				apm_set_power_state(APM_STATE_REJECT);
+			return 0;
+		}
+		break;
+	case APM_NORMAL_RESUME:
+	case APM_CRITICAL_RESUME:
+		/* map all resumes to ACPI D0 */
+		if (pm_send_request(PM_RESUME, 0)) {
 			if (apm_bios_info.version > 0x100)
 				apm_set_power_state(APM_STATE_REJECT);
 			return 0;
 		}
+		break;
 	}
 
 	queue_event(event, sender);
@@ -1373,7 +1343,7 @@
 
 	/* Install our power off handler.. */
 	if (power_off_enabled)
-		acpi_power_off = apm_power_off;
+		pm_power_off = apm_power_off;
 #ifdef CONFIG_MAGIC_SYSRQ
 	sysrq_power_off = apm_power_off;
 #endif
@@ -1381,6 +1351,8 @@
 	console_blank_hook = apm_console_blank;
 #endif
 
+	pm_active = 1;
+
 	apm_mainloop();
 	return 0;
 }
@@ -1484,12 +1456,10 @@
 		APM_INIT_ERROR_RETURN;
 	}
 
-#ifdef CONFIG_ACPI
-	if (acpi_active) {
+	if (PM_IS_ACTIVE()) {
 		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
 		APM_INIT_ERROR_RETURN;
 	}
-#endif
 
 	/*
 	 * Set up a segment that references the real mode segment 0x40
@@ -1551,4 +1521,4 @@
 	return 0;
 }
 
-module_init(apm_init)
+__initcall(apm_init);
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.3.42/linux/arch/i386/kernel/entry.S	Fri Jan 28 15:09:06 2000
+++ linux/arch/i386/kernel/entry.S	Wed Feb  9 20:08:09 2000
@@ -76,6 +76,7 @@
 addr_limit	= 12
 exec_domain	= 16
 need_resched	= 20
+processor	= 56
 
 ENOSYS = 38
 
@@ -203,9 +204,17 @@
 	.globl ret_from_sys_call
 	.globl ret_from_intr
 ret_from_sys_call:
-	movl SYMBOL_NAME(bh_mask),%eax
-	andl SYMBOL_NAME(bh_active),%eax
-	jne handle_bottom_half
+#ifdef __SMP__
+	movl processor(%ebx),%eax
+	shll $5,%eax
+	movl SYMBOL_NAME(softirq_state)(,%eax),%ecx
+	testl SYMBOL_NAME(softirq_state)+4(,%eax),%ecx
+#else
+	movl SYMBOL_NAME(softirq_state),%ecx
+	testl SYMBOL_NAME(softirq_state)+4,%ecx
+#endif
+	jne   handle_softirq
+	
 ret_with_reschedule:
 	cmpl $0,need_resched(%ebx)
 	jne reschedule
@@ -250,9 +259,18 @@
 
 	ALIGN
 ret_from_exception:
-	movl SYMBOL_NAME(bh_mask),%eax
-	andl SYMBOL_NAME(bh_active),%eax
-	jne handle_bottom_half
+#ifdef __SMP__
+	GET_CURRENT(%ebx)
+	movl processor(%ebx),%eax
+	shll $5,%eax
+	movl SYMBOL_NAME(softirq_state)(,%eax),%ecx
+	testl SYMBOL_NAME(softirq_state)+4(,%eax),%ecx
+#else
+	movl SYMBOL_NAME(softirq_state),%ecx
+	testl SYMBOL_NAME(softirq_state)+4,%ecx
+#endif
+	jne   handle_softirq
+
 	ALIGN
 ret_from_intr:
 	GET_CURRENT(%ebx)
@@ -263,10 +281,10 @@
 	jmp restore_all
 
 	ALIGN
-handle_bottom_half:
-	call SYMBOL_NAME(do_bottom_half)
+handle_softirq:
+	call SYMBOL_NAME(do_softirq)
 	jmp ret_from_intr
-
+	
 	ALIGN
 reschedule:
 	call SYMBOL_NAME(schedule)    # test
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.3.42/linux/arch/i386/kernel/head.S	Fri Jan  7 19:13:21 2000
+++ linux/arch/i386/kernel/head.S	Mon Feb  7 19:59:39 2000
@@ -212,17 +212,6 @@
 	orl $2,%eax		# set MP
 2:	movl %eax,%cr0
 	call check_x87
-#ifdef __SMP__
-	movb ready,%al		# First CPU if 0
-	orb %al,%al
-	jz 4f			# First CPU skip this stuff
-	movl %cr4,%eax		# Turn on 4Mb pages
-	orl $16,%eax
-	movl %eax,%cr4
-	movl %cr3,%eax		# Intel specification clarification says
-	movl %eax,%cr3		# to do this. Maybe it makes a difference.
-				# Who knows ?
-#endif
 4:
 #ifdef __SMP__
 	incb ready
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.3.42/linux/arch/i386/kernel/i386_ksyms.c	Fri Jan 28 15:09:06 2000
+++ linux/arch/i386/kernel/i386_ksyms.c	Wed Feb  9 20:08:09 2000
@@ -8,7 +8,7 @@
 #include <linux/in6.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
-#include <linux/acpi.h>
+#include <linux/pm.h>
 #include <linux/pci.h>
 
 #include <asm/semaphore.h>
@@ -44,14 +44,13 @@
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(__io_virt_debug);
-EXPORT_SYMBOL(local_bh_count);
-EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(disable_irq_nosync);
+EXPORT_SYMBOL(probe_irq_mask);
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(acpi_idle);
-EXPORT_SYMBOL(acpi_power_off);
+EXPORT_SYMBOL(pm_idle);
+EXPORT_SYMBOL(pm_power_off);
 
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
@@ -106,11 +105,7 @@
 
 /* Global SMP irq stuff */
 EXPORT_SYMBOL(synchronize_irq);
-EXPORT_SYMBOL(synchronize_bh);
-EXPORT_SYMBOL(global_bh_count);
-EXPORT_SYMBOL(global_bh_lock);
 EXPORT_SYMBOL(global_irq_holder);
-EXPORT_SYMBOL(i386_bh_lock);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
 EXPORT_SYMBOL(__global_save_flags);
@@ -141,3 +136,7 @@
 #endif
 
 EXPORT_SYMBOL(get_wchan);
+
+
+EXPORT_SYMBOL(local_bh_count); 
+EXPORT_SYMBOL(local_irq_count); 
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.3.42/linux/arch/i386/kernel/io_apic.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/i386/kernel/io_apic.c	Tue Feb  8 09:37:35 2000
@@ -223,7 +223,7 @@
 static int __init pin_2_irq(int idx, int apic, int pin);
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
 {
-	int apic, i;
+	int apic, i, best_guess = -1;
 
 	for (i = 0; i < mp_irq_entries; i++) {
 		int lbus = mp_irqs[i].mpc_srcbus;
@@ -236,10 +236,18 @@
 		    (mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
 		    !mp_irqs[i].mpc_irqtype &&
 		    (bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
-		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f)) &&
-		    (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)))
+		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
 
-			return pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
+			if (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3))
+				return irq;
+			/*
+			 * Use the first all-but-pin matching entry as a
+			 * best-guess fuzzy result for broken mptables.
+			 */
+			if (best_guess < 0)
+				best_guess = irq;
+		}
 	}
 	return -1;
 }
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.3.42/linux/arch/i386/kernel/irq.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/i386/kernel/irq.c	Wed Feb  9 20:08:09 2000
@@ -182,30 +182,12 @@
  * Global interrupt locks for SMP. Allow interrupts to come in on any
  * CPU, yet make cli/sti act globally to protect critical regions..
  */
-spinlock_t i386_bh_lock = SPIN_LOCK_UNLOCKED;
 
 #ifdef CONFIG_SMP
 unsigned char global_irq_holder = NO_PROC_ID;
 unsigned volatile int global_irq_lock;
 atomic_t global_irq_count;
 
-atomic_t global_bh_count;
-atomic_t global_bh_lock;
-
-/*
- * "global_cli()" is a special case, in that it can hold the
- * interrupts disabled for a longish time, and also because
- * we may be doing TLB invalidates when holding the global
- * IRQ lock for historical reasons. Thus we may need to check
- * SMP invalidate events specially by hand here (but not in
- * any normal spinlocks)
- */
-static inline void check_smp_invalidate(int cpu)
-{
-	if (test_bit(cpu, &smp_invalidate_needed))
-		do_flush_tlb_local();
-}
-
 static void show(char * str)
 {
 	int i;
@@ -216,7 +198,7 @@
 	printk("irq:  %d [%d %d]\n",
 		atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
 	printk("bh:   %d [%d %d]\n",
-		atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+		spin_is_locked(&global_bh_lock) ? 1 : 0, local_bh_count[0], local_bh_count[1]);
 	stack = (unsigned long *) &stack;
 	for (i = 40; i ; i--) {
 		unsigned long x = *++stack;
@@ -228,18 +210,6 @@
 	
 #define MAXCOUNT 100000000
 
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if (!--count) {
-			show("wait_on_bh");
-			count = ~0;
-		}
-		/* nothing .. wait for the other bh's to go away */
-	} while (atomic_read(&global_bh_count) != 0);
-}
-
 /*
  * I had a lockup scenario where a tight loop doing
  * spin_unlock()/spin_lock() on CPU#1 was racing with
@@ -279,7 +249,7 @@
 		 * already executing in one..
 		 */
 		if (!atomic_read(&global_irq_count)) {
-			if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
+			if (local_bh_count[cpu] || !spin_is_locked(&global_bh_lock))
 				break;
 		}
 
@@ -294,12 +264,11 @@
 			__sti();
 			SYNC_OTHER_CORES(cpu);
 			__cli();
-			check_smp_invalidate(cpu);
 			if (atomic_read(&global_irq_count))
 				continue;
 			if (global_irq_lock)
 				continue;
-			if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
+			if (!local_bh_count[cpu] && spin_is_locked(&global_bh_lock))
 				continue;
 			if (!test_and_set_bit(0,&global_irq_lock))
 				break;
@@ -309,20 +278,6 @@
 
 /*
  * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler. 
- */
-void synchronize_bh(void)
-{
-	if (atomic_read(&global_bh_count) && !in_interrupt())
-		wait_on_bh();
-}
-
-/*
- * This is called when we want to synchronize with
  * interrupts. We may for example tell a device to
  * stop sending interrupts: but to make sure there
  * are no interrupts that are executing on another
@@ -346,7 +301,6 @@
 		/* Uhhuh.. Somebody else got it. Wait.. */
 		do {
 			do {
-				check_smp_invalidate(cpu);
 			} while (test_bit(0,&global_irq_lock));
 		} while (test_and_set_bit(0,&global_irq_lock));		
 	}
@@ -621,16 +575,8 @@
 		desc->handler->end(irq);
 	spin_unlock(&irq_controller_lock);
 
-	/*
-	 * This should be conditional: we should really get
-	 * a return code from the irq handler to tell us
-	 * whether the handler wants us to do software bottom
-	 * half handling or not..
-	 */
-	if (1) {
-		if (bh_active & bh_mask)
-			do_bottom_half();
-	}
+	if (softirq_state[cpu].active&softirq_state[cpu].mask)
+		do_softirq();
 	return 1;
 }
 
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.3.42/linux/arch/i386/kernel/mtrr.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/i386/kernel/mtrr.c	Wed Feb  9 11:42:35 2000
@@ -1469,19 +1469,10 @@
 
 static struct file_operations mtrr_fops =
 {
-    NULL,        /*  Seek              */
-    mtrr_read,   /*  Read              */
-    mtrr_write,  /*  Write             */
-    NULL,        /*  Readdir           */
-    NULL,        /*  Poll              */
-    mtrr_ioctl,  /*  IOctl             */
-    NULL,        /*  MMAP              */
-    NULL,	 /*  Open              */
-    NULL,        /*  Flush             */
-    mtrr_close,  /*  Release           */
-    NULL,        /*  Fsync             */
-    NULL,        /*  Fasync            */
-    NULL,        /*  Lock              */
+	 read:		mtrr_read,
+	 write:		mtrr_write,
+	 ioctl:		mtrr_ioctl,
+	 release:	mtrr_close,
 };
 
 static struct inode_operations proc_mtrr_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.3.42/linux/arch/i386/kernel/pci-pc.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/i386/kernel/pci-pc.c	Thu Feb 10 12:30:30 2000
@@ -939,12 +939,26 @@
 	}
 }
 
+static void __init pci_fixup_ide_trash(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * There exist PCI IDE controllers which have utter garbage
+	 * in first four base registers. Ignore that.
+	 */
+	DBG("PCI: IDE base address trash cleared for %s\n", d->slot_name);
+	for(i=0; i<4; i++)
+		d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
+}
+
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_RCC,	PCI_DEVICE_ID_RCC_HE,		pci_fixup_rcc },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_RCC,	PCI_DEVICE_ID_RCC_LE,		pci_fixup_rcc },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_COMPAQ,	PCI_DEVICE_ID_COMPAQ_6010,	pci_fixup_compaq },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_UMC,	PCI_DEVICE_ID_UMC_UM8886BF,	pci_fixup_umc_ide },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5513,		pci_fixup_ide_trash },
 	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,		PCI_ANY_ID,			pci_fixup_ide_bases },
 	{ 0 }
 };
@@ -1132,6 +1146,10 @@
 			if (pin) {
 				pin--;		/* interrupt pins are numbered starting from 1 */
 				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+/*
+ * Will be removed completely if things work out well with fuzzy parsing
+ */
+#if 0
 				if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
 					struct pci_dev * bridge = dev->bus->self;
 
@@ -1142,6 +1160,7 @@
 						printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", 
 							bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
 				}
+#endif
 				if (irq >= 0) {
 					printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
 						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/pm.c linux/arch/i386/kernel/pm.c
--- v2.3.42/linux/arch/i386/kernel/pm.c	Fri Jan 28 15:09:06 2000
+++ linux/arch/i386/kernel/pm.c	Wed Dec 31 16:00:00 1969
@@ -1,104 +0,0 @@
-/*
- *  pm.c - Power management interface
- *
- *  Copyright (C) 2000 Andrew Henroid
- *
- *  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
- */
-
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/pm.h>
-
-static spinlock_t pm_devs_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(pm_devs);
-
-/*
- * Register a device with power management
- */
-struct pm_dev *pm_register(pm_dev_t type,
-			   unsigned long id,
-			   pm_callback callback)
-{
-	struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
-	if (dev) {
-		unsigned long flags;
-
-		memset(dev, 0, sizeof(*dev));
-		dev->type = type;
-		dev->id = id;
-		dev->callback = callback;
-
-		spin_lock_irqsave(&pm_devs_lock, flags);
-		list_add(&dev->entry, &pm_devs);
-		spin_unlock_irqrestore(&pm_devs_lock, flags);
-	}
-	return dev;
-}
-
-/*
- * Unregister a device with power management
- */
-void pm_unregister(struct pm_dev *dev)
-{
-	if (dev) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&pm_devs_lock, flags);
-		list_del(&dev->entry);
-		spin_unlock_irqrestore(&pm_devs_lock, flags);
-
-		kfree(dev);
-	}
-}
-
-/*
- * Send a request to all devices
- */
-int pm_send_request(pm_request_t rqst, void *data)
-{
-	struct list_head *entry = pm_devs.next;
-	while (entry != &pm_devs) {
-		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
-		if (dev->callback) {
-			int status = (*dev->callback)(dev, rqst, data);
-			if (status)
-				return status;
-		}
-		entry = entry->next;
-	}
-	return 0;
-}
-
-/*
- * Find a device
- */
-struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
-{
-	struct list_head *entry = from ? from->entry.next:pm_devs.next;
-	while (entry != &pm_devs) {
-		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
-		if (type == PM_UNKNOWN_DEV || dev->type == type)
-			return dev;
-		entry = entry->next;
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL(pm_register);
-EXPORT_SYMBOL(pm_unregister);
-EXPORT_SYMBOL(pm_send_request);
-EXPORT_SYMBOL(pm_find);
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.3.42/linux/arch/i386/kernel/process.c	Mon Dec 20 18:48:21 1999
+++ linux/arch/i386/kernel/process.c	Tue Feb  8 11:32:18 2000
@@ -61,12 +61,12 @@
 /*
  * Powermanagement idle function, if any..
  */
-void (*acpi_idle)(void) = NULL;
+void (*pm_idle)(void) = NULL;
 
 /*
  * Power off function, if any
  */
-void (*acpi_power_off)(void) = NULL;
+void (*pm_power_off)(void) = NULL;
 
 /*
  * We use this if we don't have any better
@@ -92,7 +92,7 @@
 	current->counter = -100;
 
 	while (1) {
-		void (*idle)(void) = acpi_idle;
+		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = default_idle;
 		while (!current->need_resched)
@@ -328,8 +328,8 @@
 
 void machine_power_off(void)
 {
-	if (acpi_power_off)
-		acpi_power_off();
+	if (pm_power_off)
+		pm_power_off();
 }
 
 
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.42/linux/arch/i386/kernel/setup.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/i386/kernel/setup.c	Mon Feb  7 20:01:14 2000
@@ -75,7 +75,7 @@
 #include <asm/e820.h>
 #include <asm/dma.h>
 #include <asm/mpspec.h>
-
+#include <asm/mmu_context.h>
 /*
  * Machine setup..
  */
@@ -1543,6 +1543,10 @@
 	 */
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
+	if(current->mm)
+		BUG();
+	enter_lazy_tlb(&init_mm, current, nr);
+
 	t->esp0 = current->thread.esp0;
 	set_tss_desc(nr,t);
 	gdt_table[__TSS(nr)].b &= 0xfffffdff;
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.3.42/linux/arch/i386/kernel/smp.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/i386/kernel/smp.c	Tue Feb  8 18:44:57 2000
@@ -103,8 +103,7 @@
 /* The 'big kernel lock' */
 spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
 
-volatile unsigned long smp_invalidate_needed; /* immediate flush required */
-unsigned int cpu_tlbbad[NR_CPUS]; /* flush before returning to user space */
+struct tlb_state cpu_tlbstate[NR_CPUS];
 
 /*
  * the following functions deal with sending IPIs between CPUs.
@@ -186,15 +185,15 @@
 	return cfg;
 }
 
-static inline int __prepare_ICR2 (unsigned int dest)
+static inline int __prepare_ICR2 (unsigned int mask)
 {
 	unsigned int cfg;
 
 	cfg = __get_ICR2();
 #if LOGICAL_DELIVERY
-	cfg |= SET_APIC_DEST_FIELD((1<<dest));
+	cfg |= SET_APIC_DEST_FIELD(mask);
 #else
-	cfg |= SET_APIC_DEST_FIELD(dest);
+	cfg |= SET_APIC_DEST_FIELD(mask);
 #endif
 
 	return cfg;
@@ -250,7 +249,7 @@
 	__send_IPI_shortcut(APIC_DEST_SELF, vector);
 }
 
-static inline void send_IPI_single(int dest, int vector)
+static inline void send_IPI_mask(int mask, int vector)
 {
 	unsigned long cfg;
 #if FORCE_READ_AROUND_WRITE
@@ -264,7 +263,7 @@
 	 * prepare target chip field
 	 */
 
-	cfg = __prepare_ICR2(dest);
+	cfg = __prepare_ICR2(mask);
 	apic_write(APIC_ICR2, cfg);
 
 	/*
@@ -282,112 +281,173 @@
 }
 
 /*
- * This is fraught with deadlocks. Probably the situation is not that
- * bad as in the early days of SMP, so we might ease some of the
- * paranoia here.
+ *	Smarter SMP flushing macros. 
+ *		c/o Linus Torvalds.
+ *
+ *	These mean you can really definitely utterly forget about
+ *	writing to user space from interrupts. (Its not allowed anyway).
+ *
+ *	Optimizations Manfred Spraul <manfreds@colorfullife.com>
  */
-static void flush_tlb_others(unsigned int cpumask)
+
+static volatile unsigned long flush_cpumask;
+static struct mm_struct * flush_mm;
+static unsigned long flush_va;
+static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
+#define FLUSH_ALL	0xffffffff
+
+static void inline leave_mm (unsigned long cpu)
 {
-	int cpu = smp_processor_id();
-	int stuck;
-	unsigned long flags;
+	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
+		BUG();
+	clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
+	cpu_tlbstate[cpu].state = TLBSTATE_OLD;
+}
+
+/*
+ *
+ * The flush IPI assumes that a thread switch happens in this order:
+ * 1) set_bit(cpu, &new_mm->cpu_vm_mask);
+ * 2) update cpu_tlbstate
+ * [now the cpu can accept tlb flush request for the new mm]
+ * 3) change cr3 (if required, or flush local tlb,...)
+ * 4) clear_bit(cpu, &old_mm->cpu_vm_mask);
+ * 5) switch %%esp, ie current
+ *
+ * The interrupt must handle 2 special cases:
+ * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
+ * - the cpu performs speculative tlb reads, i.e. even if the cpu only
+ *   runs in kernel space, the cpu could load tlb entries for user space
+ *   pages.
+ *
+ * The good news is that cpu_tlbstate is local to each cpu, no
+ * write/read ordering problems.
+ */
+
+/*
+ * TLB flush IPI:
+ *
+ * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
+ * 2) Leave the mm if we are in the lazy tlb mode.
+ * We cannot call mmdrop() because we are in interrupt context, 
+ * instead update cpu_tlbstate.
+ */
+
+asmlinkage void smp_invalidate_interrupt (void)
+{
+	unsigned long cpu = smp_processor_id();
+
+	if (!test_bit(cpu, &flush_cpumask))
+		BUG();
+	if (flush_mm == cpu_tlbstate[cpu].active_mm) {
+		if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
+			if (flush_va == FLUSH_ALL)
+				local_flush_tlb();
+			else
+				__flush_tlb_one(flush_va);
+		} else
+			leave_mm(cpu);
+	} else {
+		extern void show_stack (void *);
+		printk("hm #1: %p, %p.\n", flush_mm, cpu_tlbstate[cpu].active_mm);
+		show_stack(NULL);
+	}
+	__flush_tlb();
+	ack_APIC_irq();
+	clear_bit(cpu, &flush_cpumask);
+}
+
+static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm,
+						unsigned long va)
+{
+	/*
+	 * A couple of (to be removed) sanity checks:
+	 *
+	 * - we do not send IPIs to not-yet booted CPUs.
+	 * - current CPU must not be in mask
+	 * - mask must exist :)
+	 */
+	if (!cpumask)
+		BUG();
+	if ((cpumask & cpu_online_map) != cpumask)
+		BUG();
+	if (cpumask & (1 << smp_processor_id()))
+		BUG();
+	if (!mm)
+		BUG();
 
 	/*
-	 * it's important that we do not generate any APIC traffic
-	 * until the AP CPUs have booted up!
+	 * i'm not happy about this global shared spinlock in the
+	 * MM hot path, but we'll see how contended it is.
+	 * Temporarily this turns IRQs off, so that lockups are
+	 * detected by the NMI watchdog.
 	 */
-	cpumask &= cpu_online_map;
-	if (cpumask) {
-		atomic_set_mask(cpumask, &smp_invalidate_needed);
-
-		/*
-		 * Processors spinning on some lock with IRQs disabled
-		 * will see this IRQ late. The smp_invalidate_needed
-		 * map will ensure they don't do a spurious flush tlb
-		 * or miss one.
-		 */
+	spin_lock_irq(&tlbstate_lock);
 	
-		__save_flags(flags);
-		__cli();
+	flush_mm = mm;
+	flush_va = va;
+	atomic_set_mask(cpumask, &flush_cpumask);
+	/*
+	 * We have to send the IPI only to
+	 * CPUs affected.
+	 */
+	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
 
-		send_IPI_allbutself(INVALIDATE_TLB_VECTOR);
+	while (flush_cpumask)
+		/* nothing. lockup detection does not belong here */;
 
-		/*
-		 * Spin waiting for completion
-		 */
-
-		stuck = 50000000;
-		while (smp_invalidate_needed) {
-			/*
-			 * Take care of "crossing" invalidates
-			 */
-			if (test_bit(cpu, &smp_invalidate_needed))
-				do_flush_tlb_local();
-
-			--stuck;
-			if (!stuck) {
-				printk("stuck on TLB IPI wait (CPU#%d)\n",cpu);
-				break;
-			}
-		}
-		__restore_flags(flags);
-	}
+	flush_mm = NULL;
+	flush_va = 0;
+	spin_unlock_irq(&tlbstate_lock);
 }
-
-/*
- *	Smarter SMP flushing macros. 
- *		c/o Linus Torvalds.
- *
- *	These mean you can really definitely utterly forget about
- *	writing to user space from interrupts. (Its not allowed anyway).
- */	
+	
 void flush_tlb_current_task(void)
 {
-	unsigned long vm_mask = 1 << smp_processor_id();
 	struct mm_struct *mm = current->mm;
-	unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+	unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
 
-	mm->cpu_vm_mask = vm_mask;
-	flush_tlb_others(cpu_mask);
 	local_flush_tlb();
+	if (cpu_mask)
+		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
 }
 
-void flush_tlb_mm(struct mm_struct * mm)
+void flush_tlb_mm (struct mm_struct * mm)
 {
-	unsigned long vm_mask = 1 << smp_processor_id();
-	unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+	unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
 
-	mm->cpu_vm_mask = 0;
 	if (current->active_mm == mm) {
-		mm->cpu_vm_mask = vm_mask;
-		local_flush_tlb();
+		if (current->mm)
+			local_flush_tlb();
+		else
+			leave_mm(smp_processor_id());
 	}
-	flush_tlb_others(cpu_mask);
+	if (cpu_mask)
+		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
 }
 
 void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
 {
-	unsigned long vm_mask = 1 << smp_processor_id();
 	struct mm_struct *mm = vma->vm_mm;
-	unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+	unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
 
-	mm->cpu_vm_mask = 0;
 	if (current->active_mm == mm) {
-		__flush_tlb_one(va);
-		mm->cpu_vm_mask = vm_mask;
+		if(current->mm)
+			__flush_tlb_one(va);
+		 else
+		 	leave_mm(smp_processor_id());
 	}
-	flush_tlb_others(cpu_mask);
+
+	if (cpu_mask)
+		flush_tlb_others(cpu_mask, mm, va);
 }
 
 static inline void do_flush_tlb_all_local(void)
 {
-	__flush_tlb_all();
-	if (!current->mm && current->active_mm) {
-		unsigned long cpu = smp_processor_id();
+	unsigned long cpu = smp_processor_id();
 
-		clear_bit(cpu, &current->active_mm->cpu_vm_mask);
-		cpu_tlbbad[cpu] = 1;
-	}
+	__flush_tlb_all();
+	if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY)
+		leave_mm(cpu);
 }
 
 static void flush_tlb_all_ipi(void* info)
@@ -410,7 +470,7 @@
 
 void smp_send_reschedule(int cpu)
 {
-	send_IPI_single(cpu, RESCHEDULE_VECTOR);
+	send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR);
 }
 
 /*
@@ -512,23 +572,6 @@
 asmlinkage void smp_reschedule_interrupt(void)
 {
 	ack_APIC_irq();
-}
-
-/*
- * Invalidate call-back.
- *
- * Mark the CPU as a VM user if there is a active
- * thread holding on to an mm at this time. This
- * allows us to optimize CPU cross-calls even in the
- * presense of lazy TLB handling.
- */
-asmlinkage void smp_invalidate_interrupt(void)
-{
-	if (test_bit(smp_processor_id(), &smp_invalidate_needed))
-		do_flush_tlb_local();
-
-	ack_APIC_irq();
-
 }
 
 asmlinkage void smp_call_function_interrupt(void)
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/trampoline.S linux/arch/i386/kernel/trampoline.S
--- v2.3.42/linux/arch/i386/kernel/trampoline.S	Wed May  6 11:42:54 1998
+++ linux/arch/i386/kernel/trampoline.S	Mon Feb  7 19:59:39 2000
@@ -55,7 +55,7 @@
 	jmp	flush_instr
 flush_instr:
 	ljmpl	$__KERNEL_CS, $0x00100000
-				# jump to startup_32
+			# jump to startup_32 in arch/i386/kernel/head.S
 
 idt_48:
 	.word	0			# idt limit = 0
diff -u --recursive --new-file v2.3.42/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.3.42/linux/arch/i386/kernel/traps.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/i386/kernel/traps.c	Wed Feb  9 19:36:08 2000
@@ -124,19 +124,63 @@
 
 /*
  * These constants are for searching for possible module text
- * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
- * a guess of how much space is likely to be vmalloced.
+ * segments. MODULE_RANGE is a guess of how much space is likely
+ * to be vmalloced.
  */
-#define VMALLOC_OFFSET (8*1024*1024)
 #define MODULE_RANGE (8*1024*1024)
 
+void show_stack(unsigned long * esp)
+{
+	unsigned long *stack, addr, module_start, module_end;
+	int i;
+
+	// debugging aid: "show_stack(NULL);" prints the
+	// back trace for this cpu.
+
+	if(esp==NULL)
+		esp=(unsigned long*)&esp;
+
+	stack = esp;
+	for(i=0; i < kstack_depth_to_print; i++) {
+		if (((long) stack & (THREAD_SIZE-1)) == 0)
+			break;
+		if (i && ((i % 8) == 0))
+			printk("\n       ");
+		printk("%08lx ", *stack++);
+	}
+
+	printk("\nCall Trace: ");
+	stack = esp;
+	i = 1;
+	module_start = VMALLOC_START;
+	module_end = VMALLOC_END;
+	while (((long) stack & (THREAD_SIZE-1)) != 0) {
+		addr = *stack++;
+		/*
+		 * If the address is either in the text segment of the
+		 * kernel, or in the region which contains vmalloc'ed
+		 * memory, it *may* be the address of a calling
+		 * routine; if so, print it so that someone tracing
+		 * down the cause of the crash will be able to figure
+		 * out the call path that was taken.
+		 */
+		if (((addr >= (unsigned long) &_stext) &&
+		     (addr <= (unsigned long) &_etext)) ||
+		    ((addr >= module_start) && (addr <= module_end))) {
+			if (i && ((i % 8) == 0))
+				printk("\n       ");
+			printk("[<%08lx>] ", addr);
+			i++;
+		}
+	}
+}
+
 static void show_registers(struct pt_regs *regs)
 {
 	int i;
 	int in_kernel = 1;
 	unsigned long esp;
 	unsigned short ss;
-	unsigned long *stack, addr, module_start, module_end;
 
 	esp = (unsigned long) (&regs->esp);
 	ss = __KERNEL_DS;
@@ -160,43 +204,24 @@
 	 * time of the fault..
 	 */
 	if (in_kernel) {
+
 		printk("\nStack: ");
-		stack = (unsigned long *) esp;
-		for(i=0; i < kstack_depth_to_print; i++) {
-			if (((long) stack & 4095) == 0)
+		show_stack((unsigned long*)esp);
+
+		printk("\nCode: ");
+		if(regs->eip < PAGE_OFFSET)
+			goto bad;
+
+		for(i=0;i<20;i++)
+		{
+			unsigned char c;
+			if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
+bad:
+				printk(" Bad EIP value.");
 				break;
-			if (i && ((i % 8) == 0))
-				printk("\n       ");
-			printk("%08lx ", *stack++);
-		}
-		printk("\nCall Trace: ");
-		stack = (unsigned long *) esp;
-		i = 1;
-		module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
-		module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
-		module_end = module_start + MODULE_RANGE;
-		while (((long) stack & 4095) != 0) {
-			addr = *stack++;
-			/*
-			 * If the address is either in the text segment of the
-			 * kernel, or in the region which contains vmalloc'ed
-			 * memory, it *may* be the address of a calling
-			 * routine; if so, print it so that someone tracing
-			 * down the cause of the crash will be able to figure
-			 * out the call path that was taken.
-			 */
-			if (((addr >= (unsigned long) &_stext) &&
-			     (addr <= (unsigned long) &_etext)) ||
-			    ((addr >= module_start) && (addr <= module_end))) {
-				if (i && ((i % 8) == 0))
-					printk("\n       ");
-				printk("[<%08lx>] ", addr);
-				i++;
 			}
+			printk("%02x ", c);
 		}
-		printk("\nCode: ");
-		for(i=0;i<20;i++)
-			printk("%02x ", ((unsigned char *)regs->eip)[i]);
 	}
 	printk("\n");
 }	
diff -u --recursive --new-file v2.3.42/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.3.42/linux/arch/i386/mm/init.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/i386/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -40,8 +40,6 @@
 static unsigned long totalram_pages = 0;
 static unsigned long totalhigh_pages = 0;
 
-extern void show_net_buffers(void);
-
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -228,9 +226,6 @@
 	printk("%d pages swap cached\n",cached);
 	printk("%ld pages in page table cache\n",pgtable_cache_size);
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 }
 
 /* References to section boundaries */
@@ -448,7 +443,7 @@
 	kmap_init();
 #endif
 	{
-		unsigned int zones_size[MAX_NR_ZONES] = {0, 0, 0};
+		unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
 		unsigned int max_dma, high, low;
 
 		max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/Makefile linux/arch/ia64/Makefile
--- v2.3.42/linux/arch/ia64/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,125 @@
+#
+# ia64/Makefile
+#
+# 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) 1998, 1999 by David Mosberger-Tang <davidm@hpl.hp.com>
+#
+
+NM := $(CROSS_COMPILE)nm -B
+
+LINKFLAGS = -static -T arch/$(ARCH)/vmlinux.lds
+# next line is for HP compiler backend:
+#AFLAGS += -DGCC_RETVAL_POINTER_IN_R8
+# The next line is needed when compiling with the July snapshot of the Cygnus compiler:
+#EXTRA	= -ma0-bugs -D__GCC_DOESNT_KNOW_IN_REGS__
+# next two lines are for the September snapshot of the Cygnus compiler:
+AFLAGS += -D__GCC_MULTIREG_RETVALS__
+EXTRA	= -ma0-bugs -D__GCC_MULTIREG_RETVALS__
+
+CFLAGS := -g $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127
+
+ifdef CONFIG_IA64_GENERIC
+	CORE_FILES      :=      arch/$(ARCH)/hp/hp.a	\
+				arch/$(ARCH)/sn/sn.a	\
+				arch/$(ARCH)/dig/dig.a	\
+				$(CORE_FILES)
+	SUBDIRS		:=	arch/$(ARCH)/hp		\
+				arch/$(ARCH)/sn/sn1	\
+				arch/$(ARCH)/sn		\
+				arch/$(ARCH)/dig	\
+				$(SUBDIRS)
+
+else # !GENERIC
+
+ifeq ($(CONFIG_IA64_HP_SIM),y)
+        SUBDIRS         :=      arch/$(ARCH)/hp		\
+                                $(SUBDIRS)
+        CORE_FILES      :=      arch/$(ARCH)/hp/hp.a	\
+                                $(CORE_FILES)
+endif
+
+ifeq ($(CONFIG_IA64_SGI_SN1_SIM),y)
+        SUBDIRS         :=      arch/$(ARCH)/sn/sn1	\
+				arch/$(ARCH)/sn		\
+				$(SUBDIRS)
+        CORE_FILES      :=      arch/$(ARCH)/sn/sn.a	\
+				$(CORE_FILES)
+endif
+
+ifeq ($(CONFIG_IA64_SOFTSDV),y)
+        SUBDIRS         :=      arch/$(ARCH)/dig	\
+				$(SUBDIRS)
+        CORE_FILES      :=      arch/$(ARCH)/dig/dig.a	\
+				$(CORE_FILES)
+endif
+
+ifeq ($(CONFIG_IA64_DIG),y)
+        SUBDIRS         :=      arch/$(ARCH)/dig	\
+				$(SUBDIRS)
+        CORE_FILES      :=      arch/$(ARCH)/dig/dig.a	\
+				$(CORE_FILES)
+endif
+
+endif # !GENERIC
+
+ifeq ($(CONFIG_IA32_SUPPORT),y)
+	SUBDIRS		:=	arch/$(ARCH)/ia32 $(SUBDIRS)
+	CORE_FILES	:=	arch/$(ARCH)/ia32/ia32.o $(CORE_FILES)
+endif
+
+ifdef CONFIG_KDB
+	LIBS := $(LIBS) $(TOPDIR)/arch/$(ARCH)/kdb/kdb.a
+	SUBDIRS := $(SUBDIRS) arch/$(ARCH)/kdb
+endif
+
+HEAD := arch/$(ARCH)/kernel/head.o arch/ia64/kernel/init_task.o
+
+SUBDIRS := arch/$(ARCH)/tools arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/lib $(SUBDIRS)
+CORE_FILES := arch/$(ARCH)/kernel/kernel.o arch/$(ARCH)/mm/mm.o $(CORE_FILES)
+
+LIBS := $(TOPDIR)/arch/$(ARCH)/lib/lib.a $(LIBS) \
+	$(TOPDIR)/arch/$(ARCH)/lib/lib.a
+
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+vmlinux: arch/$(ARCH)/vmlinux.lds
+
+arch/$(ARCH)/vmlinux.lds: arch/$(ARCH)/vmlinux.lds.S FORCE
+	gcc -D__ASSEMBLY__ -E -C -P -I$(HPATH) -I$(HPATH)/asm-$(ARCH) \
+		arch/$(ARCH)/vmlinux.lds.S > $@
+
+FORCE: ;
+
+rawboot:
+	@$(MAKEBOOT) rawboot
+
+#
+# My boot writes directly to a specific disk partition, I doubt most
+# people will want to do that without changes..
+#
+msb my-special-boot:
+	@$(MAKEBOOT) msb
+
+bootimage:
+	@$(MAKEBOOT) bootimage
+
+srmboot:
+	@$(MAKEBOOT) srmboot
+
+archclean:
+	@$(MAKE) -C arch/$(ARCH)/kernel clean
+	@$(MAKE) -C arch/$(ARCH)/tools clean
+	@$(MAKEBOOT) clean
+
+archmrproper:
+	rm -f arch/$(ARCH)/vmlinux.lds
+	@$(MAKE) -C arch/$(ARCH)/tools mrproper
+
+archdep:
+	@$(MAKEBOOT) dep
+
+bootpfile:
+	@$(MAKEBOOT) bootpfile
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/boot/Makefile linux/arch/ia64/boot/Makefile
--- v2.3.42/linux/arch/ia64/boot/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/boot/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,33 @@
+#
+# ia64/boot/Makefile
+#
+# 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) 1998 by David Mosberger-Tang <davidm@hpl.hp.com>
+#
+
+LINKFLAGS = -static -T bootloader.lds
+
+.S.s:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.o $<
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $<
+
+OBJECTS	= bootloader.o
+TARGETS =
+
+ifdef CONFIG_IA64_HP_SIM
+ TARGETS += bootloader
+endif
+
+all:	$(TARGETS)
+
+bootloader: $(OBJECTS)
+	$(LD) $(LINKFLAGS) $(OBJECTS) $(LIBS) -o bootloader
+
+clean:
+	rm -f $(TARGETS)
+
+dep:
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/boot/bootloader.c linux/arch/ia64/boot/bootloader.c
--- v2.3.42/linux/arch/ia64/boot/bootloader.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/boot/bootloader.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,234 @@
+/*
+ * arch/ia64/boot/bootloader.c
+ *
+ * Loads an ELF kernel.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * 01/07/99 S.Eranian modified to pass command line arguments to kernel
+ */
+#include <linux/config.h>
+#include <linux/elf.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/elf.h>
+#include <asm/pal.h>
+#include <asm/pgtable.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+
+/* Simulator system calls: */
+
+#define SSC_CONSOLE_INIT		20
+#define SSC_GETCHAR			21
+#define SSC_PUTCHAR			31
+#define SSC_OPEN			50
+#define SSC_CLOSE			51
+#define SSC_READ			52
+#define SSC_WRITE			53
+#define SSC_GET_COMPLETION		54
+#define SSC_WAIT_COMPLETION		55
+#define SSC_CONNECT_INTERRUPT		58
+#define SSC_GENERATE_INTERRUPT		59
+#define SSC_SET_PERIODIC_INTERRUPT	60
+#define SSC_GET_RTC			65
+#define SSC_EXIT			66
+#define SSC_LOAD_SYMBOLS		69
+#define SSC_GET_TOD			74
+
+#define SSC_GET_ARGS			75
+
+struct disk_req {
+	unsigned long addr;
+	unsigned len;
+};
+
+struct disk_stat {
+	int fd;
+	unsigned count;
+};
+
+#include "../kernel/fw-emu.c"
+
+static void
+cons_write (const char *buf)
+{
+	unsigned long ch;
+
+	while ((ch = *buf++) != '\0') {
+		ssc(ch, 0, 0, 0, SSC_PUTCHAR);
+		if (ch == '\n')
+		  ssc('\r', 0, 0, 0, SSC_PUTCHAR);
+	}
+}
+
+void
+enter_virtual_mode (unsigned long new_psr)
+{
+	asm volatile ("mov cr.ipsr=%0" :: "r"(new_psr));
+	asm volatile ("mov cr.iip=%0" :: "r"(&&target));
+	asm volatile ("mov cr.ifs=r0");
+	asm volatile ("rfi;;");		/* must be last insn in an insn group */
+
+  target:
+}
+
+
+#define MAX_ARGS 32
+
+void
+_start (void)
+{
+	register long sp asm ("sp");
+	static char stack[16384] __attribute__ ((aligned (16)));
+	static char mem[4096];
+	static char buffer[1024];
+	unsigned long flags, off;
+	int fd, i;
+	struct disk_req req;
+	struct disk_stat stat;
+	struct elfhdr *elf;
+	struct elf_phdr *elf_phdr;	/* program header */
+	unsigned long e_entry, e_phoff, e_phnum;
+	char *kpath, *args;
+	long arglen = 0;
+
+	asm volatile ("movl gp=__gp" ::: "memory");
+	asm volatile ("mov sp=%0" :: "r"(stack) : "memory");
+	asm volatile ("bsw.1;;");
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+	asm volative ("nop 0;; nop 0;; nop 0;;");
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+	ssc(0, 0, 0, 0, SSC_CONSOLE_INIT);
+
+	/*
+	 * S.Eranian: extract the commandline argument from the 
+	 * simulator
+	 *
+	 * The expected format is as follows:
+         *
+	 *	kernelname args...
+	 *
+	 * Both are optional but you can't have the second one without the 
+	 * first.
+	 */
+	arglen = ssc((long) buffer, 0, 0, 0, SSC_GET_ARGS);
+
+	kpath = "vmlinux";
+	args = buffer;
+	if (arglen > 0) {
+		kpath = buffer;
+		while (*args != ' ' && *args != '\0')
+			++args, --arglen;
+		if (*args == ' ')
+			*args++ = '\0', --arglen;
+	}
+
+	if (arglen <= 0) {
+		args = "";
+		arglen = 1;
+	}
+
+	fd = ssc((long) kpath, 1, 0, 0, SSC_OPEN);
+
+	if (fd < 0) {
+		cons_write(kpath);
+		cons_write(": file not found, reboot now\n");
+		for(;;);
+	}
+	stat.fd = fd;
+	off = 0;
+
+	req.len = sizeof(mem);
+	req.addr = (long) mem;
+	ssc(fd, 1, (long) &req, off, SSC_READ);
+	ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
+
+	elf = (struct elfhdr *) mem;
+	if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) != 0) {
+		cons_write("not an ELF file\n");
+		return;
+	}
+	if (elf->e_type != ET_EXEC) {
+		cons_write("not an ELF executable\n");
+		return;
+	}
+	if (!elf_check_arch(elf->e_machine)) {
+		cons_write("kernel not for this processor\n");
+		return;
+	}
+
+	e_entry = elf->e_entry;
+	e_phnum = elf->e_phnum;
+	e_phoff = elf->e_phoff;
+
+	cons_write("loading ");
+	cons_write(kpath);
+	cons_write("...\n");
+
+	for (i = 0; i < e_phnum; ++i) {
+		req.len = sizeof(*elf_phdr);
+		req.addr = (long) mem;
+		ssc(fd, 1, (long) &req, e_phoff, SSC_READ);
+		ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
+		if (stat.count != sizeof(*elf_phdr)) {
+			cons_write("failed to read phdr\n");
+			return;
+		}
+		e_phoff += sizeof(*elf_phdr);
+
+		elf_phdr = (struct elf_phdr *) mem;
+		req.len = elf_phdr->p_filesz;
+		req.addr = __pa(elf_phdr->p_vaddr);
+		ssc(fd, 1, (long) &req, elf_phdr->p_offset, SSC_READ);
+		ssc((long) &stat, 0, 0, 0, SSC_WAIT_COMPLETION);
+		memset((char *)__pa(elf_phdr->p_vaddr) + elf_phdr->p_filesz, 0,
+		       elf_phdr->p_memsz - elf_phdr->p_filesz);
+	}
+	ssc(fd, 0, 0, 0, SSC_CLOSE);
+
+	cons_write("starting kernel...\n");
+
+	/* fake an I/O base address: */
+	asm volatile ("mov ar.k0=%0" :: "r"(0xffffc000000UL));
+
+	/*
+	 * Install a translation register that identity maps the
+	 * kernel's 256MB page.
+	 */
+	ia64_clear_ic(flags);
+	ia64_set_rr(          0, (0x1000 << 8) | (_PAGE_SIZE_1M << 2));
+	ia64_set_rr(PAGE_OFFSET, (ia64_rid(0, PAGE_OFFSET) << 8) | (_PAGE_SIZE_256M << 2));
+	ia64_srlz_d();
+	ia64_itr(0x3, 0, 1024*1024,
+		 pte_val(mk_pte_phys(1024*1024, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))),
+		 _PAGE_SIZE_1M);
+	ia64_itr(0x3, 1, PAGE_OFFSET,
+		 pte_val(mk_pte_phys(0, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))),
+		 _PAGE_SIZE_256M);
+	ia64_srlz_i();
+
+	enter_virtual_mode(flags | IA64_PSR_IT | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT
+			   | IA64_PSR_DFH | IA64_PSR_BN);
+
+	sys_fw_init(args, arglen);
+
+	ssc(0, (long) kpath, 0, 0, SSC_LOAD_SYMBOLS);
+
+	/*
+	 * Install the kernel's command line argument on ZERO_PAGE
+	 * just after the botoparam structure.
+	 * In case we don't have any argument just put \0
+	 */
+	memcpy(((struct ia64_boot_param *)ZERO_PAGE_ADDR) + 1, args, arglen);
+	sp = __pa(&stack);
+
+	asm volatile ("br.sptk.few %0" :: "b"(e_entry));
+
+	cons_write("kernel returned!\n");
+	ssc(-1, 0, 0, 0, SSC_EXIT);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/boot/bootloader.lds linux/arch/ia64/boot/bootloader.lds
--- v2.3.42/linux/arch/ia64/boot/bootloader.lds	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/boot/bootloader.lds	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,65 @@
+OUTPUT_FORMAT("elf64-ia64-little")
+OUTPUT_ARCH(ia64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x100000;
+
+  _text = .;
+  .text : { *(__ivt_section) *(.text) }
+  _etext = .;
+
+  /* Global data */
+  _data = .;
+  .rodata : { *(.rodata) }
+  .data    : { *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
+  __gp = ALIGN (8) + 0x200000;
+  .got           : { *(.got.plt) *(.got) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  _edata  =  .;
+
+  _bss = .;
+  .sbss      : { *(.sbss) *(.scommon) }
+  .bss       : { *(.bss) *(COMMON) }
+  . = ALIGN(64 / 8);
+  _end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* These must appear regardless of  .  */
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/config.in linux/arch/ia64/config.in
--- v2.3.42/linux/arch/ia64/config.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/config.in	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,172 @@
+mainmenu_name "Kernel configuration of Linux for IA-64 machines"
+
+mainmenu_option next_comment
+comment 'General setup'
+
+choice 'IA-64 system type'					\
+	"Generic		CONFIG_IA64_GENERIC		\
+	 HP-simulator		CONFIG_IA64_HP_SIM		\
+	 SN1-simulator		CONFIG_IA64_SGI_SN1_SIM		\
+	 DIG-compliant		CONFIG_IA64_DIG" Generic
+
+choice 'Kernel page size'						\
+	"4KB			CONFIG_IA64_PAGE_SIZE_4KB		\
+	 8KB			CONFIG_IA64_PAGE_SIZE_8KB		\
+	 16KB			CONFIG_IA64_PAGE_SIZE_16KB		\
+	 64KB			CONFIG_IA64_PAGE_SIZE_64KB" 16KB
+
+if [ "$CONFIG_IA64_DIG" = "y" ]; then
+	bool '  Enable Itanium A-step specific code' CONFIG_ITANIUM_ASTEP_SPECIFIC
+	bool '  Enable SoftSDV hacks' CONFIG_IA64_SOFTSDV_HACKS n
+	bool '  Enable BigSur hacks' CONFIG_IA64_BIGSUR_HACKS y
+	bool '  Enable Lion hacks' CONFIG_IA64_LION_HACKS n
+	bool '  Emulate PAL/SAL/EFI firmware' CONFIG_IA64_FW_EMU n
+	bool '  Get PCI IRQ routing from firmware/ACPI'	CONFIG_IA64_IRQ_ACPI y
+fi
+
+if [ "$CONFIG_IA64_GENERIC" = "y" ]; then
+	define_bool CONFIG_IA64_SOFTSDV_HACKS y
+fi
+
+if [ "$CONFIG_IA64_SGI_SN1_SIM" = "y" ]; then
+	define_bool CONFIG_NUMA y
+	define_bool CONFIG_IA64_SOFTSDV_HACKS y
+fi
+
+define_bool CONFIG_KCORE_ELF y	# On IA-64, we always want an ELF /dev/kcore.
+
+bool 'SMP support' CONFIG_SMP n
+bool 'Performance monitor support' CONFIG_PERFMON n
+
+bool 'Networking support' CONFIG_NET n
+bool 'System V IPC' CONFIG_SYSVIPC n
+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT n
+bool 'Sysctl support' CONFIG_SYSCTL n
+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+bool 'PCI support' CONFIG_PCI n
+source drivers/pci/Config.in
+
+source drivers/pcmcia/Config.in
+
+mainmenu_option next_comment
+ comment 'Code maturity level options'
+ bool 'Prompt for development and/or incomplete code/drivers' \
+	CONFIG_EXPERIMENTAL n
+endmenu
+
+mainmenu_option next_comment
+ comment 'Loadable module support'
+ bool 'Enable loadable module support' CONFIG_MODULES n
+ if [ "$CONFIG_MODULES" = "y" ]; then
+  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS n
+  bool 'Kernel module loader' CONFIG_KMOD n
+ fi
+endmenu
+
+source drivers/parport/Config.in
+
+endmenu
+
+source drivers/pnp/Config.in
+source drivers/block/Config.in
+source drivers/i2o/Config.in
+
+if [ "$CONFIG_NET" = "y" ]; then
+  source net/Config.in
+fi
+
+mainmenu_option next_comment
+comment 'SCSI support'
+
+tristate 'SCSI support' CONFIG_SCSI
+
+if [ "$CONFIG_SCSI" != "n" ]; then
+  source drivers/scsi/Config.in
+  bool 'Simulated SCSI disk' CONFIG_SCSI_SIM n
+fi
+endmenu
+
+if [ "$CONFIG_NET" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Network device support'
+
+  bool 'Network device support' CONFIG_NETDEVICES n
+  if [ "$CONFIG_NETDEVICES" = "y" ]; then
+    source drivers/net/Config.in
+  fi
+  endmenu
+fi
+
+source net/ax25/Config.in
+
+mainmenu_option next_comment
+comment 'ISDN subsystem'
+
+tristate 'ISDN support' CONFIG_ISDN
+if [ "$CONFIG_ISDN" != "n" ]; then
+  source drivers/isdn/Config.in
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+
+bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI n
+if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+  source drivers/cdrom/Config.in
+fi
+endmenu
+
+source drivers/char/Config.in
+source drivers/usb/Config.in
+source drivers/misc/Config.in
+
+source fs/Config.in
+
+source fs/nls/Config.in
+
+if [ "$CONFIG_VT" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Console drivers'
+  bool 'VGA text console' CONFIG_VGA_CONSOLE n
+  if [ "$CONFIG_FB" = "y" ]; then
+    define_bool CONFIG_PCI_CONSOLE y
+  fi
+  source drivers/video/Config.in
+  endmenu
+fi
+
+mainmenu_option next_comment
+comment 'Sound'
+
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+  source drivers/sound/Config.in
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'Kernel support for IA-32 emulation' CONFIG_IA32_SUPPORT
+  tristate 'Kernel FP software completion' CONFIG_MATHEMU
+else
+  define_bool CONFIG_MATHEMU y
+fi
+
+bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ n
+bool 'Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK n
+bool 'Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG n
+bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ n
+bool 'Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS n
+bool 'Built-in Kernel Debugger support' CONFIG_KDB
+if [ "$CONFIG_KDB" = "y" ]; then
+  bool 'Compile the kernel with frame pointers' CONFIG_KDB_FRAMEPTR
+  int  'KDB Kernel Symbol Table size?' CONFIG_KDB_STBSIZE 10000
+fi
+
+endmenu
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/defconfig linux/arch/ia64/defconfig
--- v2.3.42/linux/arch/ia64/defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/defconfig	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,146 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# General setup
+#
+CONFIG_IA64_SIM=y
+CONFIG_PCI=y
+# CONFIG_PCI_QUIRKS is not set
+CONFIG_PCI_OLD_PROC=y
+# CONFIG_NET is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_BINFMT_ELF is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_BINFMT_JAVA is not set
+# CONFIG_BINFMT_EM86 is not set
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_IDE is not set
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_ONLY is not set
+
+#
+# Additional Block Devices
+#
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_XD is not set
+CONFIG_PARIDE_PARPORT=y
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+CONFIG_EFI_RTC=y
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_NVRAM is not set
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_PROC_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_MATHEMU is not set
+# CONFIG_MAGIC_SYSRQ is not set
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/dig/Makefile linux/arch/ia64/dig/Makefile
--- v2.3.42/linux/arch/ia64/dig/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/dig/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,24 @@
+#
+# ia64/platform/dig/Makefile
+#
+# Copyright (C) 1999 Silicon Graphics, Inc.
+# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+#
+
+.S.s:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
+all: dig.a
+
+O_TARGET        = dig.a
+O_OBJS          = iosapic.o setup.o
+
+ifeq ($(CONFIG_IA64_GENERIC),y)
+O_OBJS		+= machvec.o
+endif
+
+clean::
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/dig/iosapic.c linux/arch/ia64/dig/iosapic.c
--- v2.3.42/linux/arch/ia64/dig/iosapic.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/dig/iosapic.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,553 @@
+/*
+ * Streamlined APIC support.
+ *
+ * Copyright (C) 1999 Intel Corp.
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999-2000 Hewlett-Packard Co.
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/iosapic.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/delay.h>
+#include <asm/processor.h>
+
+#undef DEBUG_IRQ_ROUTING
+
+/*
+ * IRQ vectors 0..15 are treated as the legacy interrupts of the PC-AT
+ * platform.  No new drivers should ever ask for specific irqs, but we
+ * provide compatibility here in case there is an old driver that does
+ * ask for specific irqs (serial, keyboard, stuff like that).  Since
+ * IA-64 doesn't allow irq 0..15 to be used for external interrupts
+ * anyhow, this in no way prevents us from doing the Right Thing
+ * with new drivers.
+ */
+struct iosapic_vector iosapic_vector[NR_IRQS] = {
+	[0 ... NR_IRQS-1] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
+};
+
+#ifndef CONFIG_IA64_IRQ_ACPI
+/*
+ * Defines the default interrupt routing information for the LION platform
+ * XXX - this information should be obtained from the ACPI and hardcoded since
+ * we do not have ACPI AML support.
+ */
+
+struct intr_routing_entry intr_routing[] = {
+      {0,0,0,2,0,0,0,0},
+      {0,0,1,1,0,0,0,0},
+      {0,0,2,0xff,0,0,0,0},
+      {0,0,3,3,0,0,0,0},
+      {0,0,4,4,0,0,0,0},
+      {0,0,5,5,0,0,0,0},
+      {0,0,6,6,0,0,0,0},
+      {0,0,7,7,0,0,0,0},
+      {0,0,8,8,0,0,0,0},
+      {0,0,9,9,0,0,0,0},
+      {0,0,10,10,0,0,0,0},
+      {0,0,11,11,0,0,0,0},
+      {0,0,12,12,0,0,0,0},
+      {0,0,13,13,0,0,0,0},
+      {0,0,14,14,0,0,0,0},
+      {0,0,15,15,0,0,0,0},
+#ifdef CONFIG_IA64_LION_HACKS
+      {1, 0, 0x04, 16, 0, 0, 1, 1},	/* bus 0, device id 1, INTA */
+      {1, 0, 0x05, 26, 0, 0, 1, 1},	/* bus 0, device id 1, INTB */
+      {1, 0, 0x06, 36, 0, 0, 1, 1},	/* bus 0, device id 1, INTC */
+      {1, 0, 0x07, 42, 0, 0, 1, 1},	/* bus 0, device id 1, INTD */
+
+      {1, 0, 0x08, 17, 0, 0, 1, 1},	/* bus 0, device id 2, INTA */
+      {1, 0, 0x09, 27, 0, 0, 1, 1},	/* bus 0, device id 2, INTB */
+      {1, 0, 0x0a, 37, 0, 0, 1, 1},	/* bus 0, device id 2, INTC */
+      {1, 0, 0x0b, 42, 0, 0, 1, 1},	/* bus 0, device id 2, INTD */
+
+      {1, 0, 0x0f, 50, 0, 0, 1, 1},	/* bus 0, device id 3, INTD */
+
+      {1, 0, 0x14, 51, 0, 0, 1, 1},	/* bus 0, device id 5, INTA */
+
+      {1, 0, 0x18, 49, 0, 0, 1, 1},	/* bus 0, device id 6, INTA */
+
+      {1, 1, 0x04, 18, 0, 0, 1, 1},	/* bus 1, device id 1, INTA */
+      {1, 1, 0x05, 28, 0, 0, 1, 1},	/* bus 1, device id 1, INTB */
+      {1, 1, 0x06, 38, 0, 0, 1, 1},	/* bus 1, device id 1, INTC */
+      {1, 1, 0x07, 43, 0, 0, 1, 1},	/* bus 1, device id 1, INTD */
+
+      {1, 1, 0x08, 48, 0, 0, 1, 1},	/* bus 1, device id 2, INTA */
+
+      {1, 1, 0x0c, 19, 0, 0, 1, 1},	/* bus 1, device id 3, INTA */
+      {1, 1, 0x0d, 29, 0, 0, 1, 1},	/* bus 1, device id 3, INTB */
+      {1, 1, 0x0e, 38, 0, 0, 1, 1},	/* bus 1, device id 3, INTC */
+      {1, 1, 0x0f, 44, 0, 0, 1, 1},	/* bus 1, device id 3, INTD */
+
+      {1, 1, 0x10, 20, 0, 0, 1, 1},	/* bus 1, device id 4, INTA */
+      {1, 1, 0x11, 30, 0, 0, 1, 1},	/* bus 1, device id 4, INTB */
+      {1, 1, 0x12, 39, 0, 0, 1, 1},	/* bus 1, device id 4, INTC */
+      {1, 1, 0x13, 45, 0, 0, 1, 1},	/* bus 1, device id 4, INTD */
+
+      {1, 2, 0x04, 21, 0, 0, 1, 1},	/* bus 2, device id 1, INTA */
+      {1, 2, 0x05, 31, 0, 0, 1, 1},	/* bus 2, device id 1, INTB */
+      {1, 2, 0x06, 39, 0, 0, 1, 1},	/* bus 2, device id 1, INTC */
+      {1, 2, 0x07, 45, 0, 0, 1, 1},	/* bus 2, device id 1, INTD */
+
+      {1, 2, 0x08, 22, 0, 0, 1, 1},	/* bus 2, device id 2, INTA */
+      {1, 2, 0x09, 32, 0, 0, 1, 1},	/* bus 2, device id 2, INTB */
+      {1, 2, 0x0a, 40, 0, 0, 1, 1},	/* bus 2, device id 2, INTC */
+      {1, 2, 0x0b, 46, 0, 0, 1, 1},	/* bus 2, device id 2, INTD */
+
+      {1, 2, 0x0c, 23, 0, 0, 1, 1},	/* bus 2, device id 3, INTA */
+      {1, 2, 0x0d, 33, 0, 0, 1, 1},	/* bus 2, device id 3, INTB */
+      {1, 2, 0x0e, 40, 0, 0, 1, 1},	/* bus 2, device id 3, INTC */
+      {1, 2, 0x0f, 46, 0, 0, 1, 1},	/* bus 2, device id 3, INTD */
+
+      {1, 3, 0x04, 24, 0, 0, 1, 1},	/* bus 3, device id 1, INTA */
+      {1, 3, 0x05, 34, 0, 0, 1, 1},	/* bus 3, device id 1, INTB */
+      {1, 3, 0x06, 41, 0, 0, 1, 1},	/* bus 3, device id 1, INTC */
+      {1, 3, 0x07, 47, 0, 0, 1, 1},	/* bus 3, device id 1, INTD */
+
+      {1, 3, 0x08, 25, 0, 0, 1, 1},	/* bus 3, device id 2, INTA */
+      {1, 3, 0x09, 35, 0, 0, 1, 1},	/* bus 3, device id 2, INTB */
+      {1, 3, 0x0a, 41, 0, 0, 1, 1},	/* bus 3, device id 2, INTC */
+      {1, 3, 0x0b, 47, 0, 0, 1, 1},	/* bus 3, device id 2, INTD */
+#else
+      /*
+       * BigSur platform, bus 0, device 1,2,4 and bus 1 device 0-3
+       */
+      {1,1,0x0,19,0,0,1,1},		/* bus 1, device id 0, INTA */
+      {1,1,0x1,18,0,0,1,1},		/* bus 1, device id 0, INTB */
+      {1,1,0x2,17,0,0,1,1},		/* bus 1, device id 0, INTC */
+      {1,1,0x3,16,0,0,1,1},		/* bus 1, device id 0, INTD */
+
+      {1,1,0x4,23,0,0,1,1},		/* bus 1, device id 1, INTA */
+      {1,1,0x5,22,0,0,1,1},		/* bus 1, device id 1, INTB */
+      {1,1,0x6,21,0,0,1,1},		/* bus 1, device id 1, INTC */
+      {1,1,0x7,20,0,0,1,1},		/* bus 1, device id 1, INTD */
+
+      {1,1,0x8,27,0,0,1,1},		/* bus 1, device id 2, INTA */
+      {1,1,0x9,26,0,0,1,1},		/* bus 1, device id 2, INTB */
+      {1,1,0xa,25,0,0,1,1},		/* bus 1, device id 2, INTC */
+      {1,1,0xb,24,0,0,1,1},		/* bus 1, device id 2, INTD */
+
+      {1,1,0xc,31,0,0,1,1},		/* bus 1, device id 3, INTA */
+      {1,1,0xd,30,0,0,1,1},		/* bus 1, device id 3, INTB */
+      {1,1,0xe,29,0,0,1,1},		/* bus 1, device id 3, INTC */
+      {1,1,0xf,28,0,0,1,1},		/* bus 1, device id 3, INTD */
+
+      {1,0,0x4,35,0,0,1,1},		/* bus 0, device id 1, INTA */
+      {1,0,0x5,34,0,0,1,1},		/* bus 0, device id 1, INTB */
+      {1,0,0x6,33,0,0,1,1},		/* bus 0, device id 1, INTC */
+      {1,0,0x7,32,0,0,1,1},		/* bus 0, device id 1, INTD */
+
+      {1,0,0x8,39,0,0,1,1},		/* bus 0, device id 2, INTA */
+      {1,0,0x9,38,0,0,1,1},		/* bus 0, device id 2, INTB */
+      {1,0,0xa,37,0,0,1,1},		/* bus 0, device id 2, INTC */
+      {1,0,0xb,36,0,0,1,1},		/* bus 0, device id 2, INTD */
+
+      {1,0,0x10,43,0,0,1,1},		/* bus 0, device id 4, INTA */
+      {1,0,0x11,42,0,0,1,1},		/* bus 0, device id 4, INTB */
+      {1,0,0x12,41,0,0,1,1},		/* bus 0, device id 4, INTC */
+      {1,0,0x13,40,0,0,1,1},		/* bus 0, device id 4, INTD */
+
+      {1,0,0x14,17,0,0,1,1},		/* bus 0, device id 5, INTA */
+      {1,0,0x18,18,0,0,1,1},		/* bus 0, device id 6, INTA */
+      {1,0,0x1c,19,0,0,1,1},		/* bus 0, device id 7, INTA */
+#endif
+      {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
+};
+
+int
+iosapic_get_PCI_irq_vector(int bus, int slot, int pci_pin)
+{
+	int     i = -1;
+
+	while (intr_routing[++i].srcbus != 0xff) {
+		if (intr_routing[i].srcbus == BUS_PCI) {
+			if ((intr_routing[i].srcbusirq == ((slot << 2) | pci_pin)) 
+			    && (intr_routing[i].srcbusno == bus)) {
+				return(intr_routing[i].iosapic_pin);
+			}
+		}
+	}
+	return -1;
+}
+
+#else /* CONFIG_IA64_IRQ_ACPI */
+
+/*
+ * find the IRQ in the IOSAPIC map for the PCI device on bus/slot/pin
+ */
+int
+iosapic_get_PCI_irq_vector(int bus, int slot, int pci_pin)
+{
+	int	i;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		if ((iosapic_bustype(i) == BUS_PCI) &&
+		    (iosapic_bus(i) == bus) &&
+		    (iosapic_busdata(i) == ((slot << 16) | pci_pin))) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+#endif /* !CONFIG_IA64_IRQ_ACPI */
+
+static void
+set_rte (unsigned long iosapic_addr, int entry, int pol, int trigger, int delivery,
+	 long dest, int vector)
+{
+	int low32;
+	int high32;
+
+	low32 = ((pol << IO_SAPIC_POLARITY_SHIFT) |
+		 (trigger << IO_SAPIC_TRIGGER_SHIFT) |
+		 (delivery << IO_SAPIC_DELIVERY_SHIFT) |
+		 vector);
+
+	/* dest contains both id and eid */
+	high32 = (dest << IO_SAPIC_DEST_SHIFT);	
+
+	/*
+	 * program the rte 
+	 */
+	writel(IO_SAPIC_RTE_HIGH(entry), iosapic_addr + IO_SAPIC_REG_SELECT);
+	writel(high32, iosapic_addr + IO_SAPIC_WINDOW);
+	writel(IO_SAPIC_RTE_LOW(entry), iosapic_addr + IO_SAPIC_REG_SELECT);
+	writel(low32, iosapic_addr + IO_SAPIC_WINDOW);
+}
+
+
+static void 
+enable_pin (unsigned int pin, unsigned long iosapic_addr)
+{
+        int low32;
+
+        writel(IO_SAPIC_RTE_LOW(pin), iosapic_addr + IO_SAPIC_REG_SELECT);
+        low32 = readl(iosapic_addr + IO_SAPIC_WINDOW);
+
+        low32 &= ~(1 << IO_SAPIC_MASK_SHIFT);    /* Zero only the mask bit */
+        writel(low32, iosapic_addr + IO_SAPIC_WINDOW);
+}
+
+
+static void 
+disable_pin (unsigned int pin, unsigned long iosapic_addr)
+{
+        int low32;
+
+        writel(IO_SAPIC_RTE_LOW(pin), iosapic_addr + IO_SAPIC_REG_SELECT);
+        low32 = readl(iosapic_addr + IO_SAPIC_WINDOW);
+
+        low32 |= (1 << IO_SAPIC_MASK_SHIFT);     /* Set only the mask bit */
+        writel(low32, iosapic_addr + IO_SAPIC_WINDOW);
+}
+
+#define iosapic_shutdown_irq	iosapic_disable_irq
+
+static void
+iosapic_enable_irq (unsigned int irq)
+{
+	int pin = iosapic_pin(irq);
+
+	if (pin < 0)
+		/* happens during irq auto probing... */
+		return;
+	enable_pin(pin, iosapic_addr(irq));
+}
+
+static void
+iosapic_disable_irq (unsigned int irq)
+{
+	int pin = iosapic_pin(irq);
+
+	if (pin < 0)
+		return;
+	disable_pin(pin, iosapic_addr(irq));
+}
+
+unsigned int
+iosapic_version(unsigned long base_addr) 
+{
+	/*
+	 * IOSAPIC Version Register return 32 bit structure like:
+	 * {
+	 *	unsigned int version   : 8;
+	 *	unsigned int reserved1 : 8;
+	 *	unsigned int pins      : 8;
+	 *	unsigned int reserved2 : 8;
+	 * }
+	 */
+	writel(IO_SAPIC_VERSION, base_addr + IO_SAPIC_REG_SELECT);
+	return readl(IO_SAPIC_WINDOW + base_addr);
+}
+
+static int
+iosapic_handle_irq (unsigned int irq, struct pt_regs *regs)
+{
+	struct irqaction *action = 0;
+	struct irq_desc *id = irq_desc + irq;
+	unsigned int status;
+	int retval;
+
+	spin_lock(&irq_controller_lock);
+	{
+		status = id->status;
+
+		/* do we need to do something IOSAPIC-specific to ACK the irq here??? */
+		/* Yes, but only level-triggered interrupts. We'll do that later */
+		if ((status & IRQ_INPROGRESS) == 0 && (status & IRQ_ENABLED) != 0) {
+			action = id->action;
+			status |= IRQ_INPROGRESS;
+		}
+		id->status = status & ~(IRQ_REPLAY | IRQ_WAITING);
+	}
+	spin_unlock(&irq_controller_lock);
+
+	if (!action) {
+		if (!(id->status & IRQ_AUTODETECT))
+			printk("iosapic_handle_irq: unexpected interrupt %u;"
+			       "disabling it (status=%x)\n", irq, id->status);
+		/*
+		 * If we don't have a handler, disable the pin so we
+		 * won't get any further interrupts (until
+		 * re-enabled).  --davidm 99/12/17
+		 */
+		iosapic_disable_irq(irq);
+		return 0;
+	}
+
+	retval = invoke_irq_handlers (irq, regs, action);
+
+	if (iosapic_trigger(irq) == IO_SAPIC_LEVEL)	/* ACK Level trigger interrupts */
+		writel(irq, iosapic_addr(irq) + IO_SAPIC_EOI);
+
+	spin_lock(&irq_controller_lock);
+	{
+		status = (id->status & ~IRQ_INPROGRESS);
+		id->status = status;
+	}
+	spin_unlock(&irq_controller_lock);
+
+	return retval;
+}
+
+void __init
+iosapic_init (unsigned long addr)
+{
+	int	i;
+#ifdef CONFIG_IA64_IRQ_ACPI
+	struct pci_vector_struct *vectors;
+	int     irq;
+#else 
+	int     vector;
+#endif
+
+	/*
+	 * Disable all local interrupts
+	 */
+
+	ia64_set_itv(0, 1);
+	ia64_set_lrr0(0, 1);	
+	ia64_set_lrr1(0, 1);	
+
+	/*
+	 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
+	 * enabled.
+	 */
+
+	outb(0xff, 0xA1);
+	outb(0xff, 0x21);
+
+#if defined(CONFIG_IA64_SOFTSDV_HACKS)
+	memset(iosapic_vector, 0x0, sizeof(iosapic_vector));
+	for (i = 0; i < NR_IRQS; i++) {
+		iosapic_pin(i) = 0xff;
+		iosapic_addr(i) = (unsigned long) ioremap(IO_SAPIC_DEFAULT_ADDR, 0);
+	}
+	/* XXX this should come from systab or some such: */
+	iosapic_pin(TIMER_IRQ) = 5;	/* System Clock Interrupt */
+	iosapic_pin(0x40) = 3;	/* Keyboard */
+	iosapic_pin(0x92) = 9;	/* COM1 Serial Port */
+	iosapic_pin(0x80) = 4;	/* Periodic Interrupt */
+	iosapic_pin(0xc0) = 2;	/* Mouse */
+	iosapic_pin(0xe0) = 1;	/* IDE Disk */
+	iosapic_pin(0xf0) = 6;	/* E-IDE CDROM */
+	iosapic_pin(0xa0) = 10;	/* Real PCI Interrupt */
+#elif !defined(CONFIG_IA64_IRQ_ACPI)
+	/*
+	 * For systems where the routing info in ACPI is
+	 * unavailable/wrong, use the intr_routing information to
+	 * initialize the iosapic array
+	 */
+	i = -1;
+	while (intr_routing[++i].srcbus != 0xff) {
+		if (intr_routing[i].srcbus == BUS_ISA) {
+			vector = map_legacy_irq(intr_routing[i].srcbusirq);
+		} else if (intr_routing[i].srcbus == BUS_PCI) {
+			vector = intr_routing[i].iosapic_pin;
+		} else {
+			printk("unknown bus type %d for intr_routing[%d]\n",
+                               intr_routing[i].srcbus, i);
+			continue;
+		}
+		iosapic_pin(vector) = intr_routing[i].iosapic_pin;
+		iosapic_dmode(vector) = intr_routing[i].mode;
+		iosapic_polarity(vector) = intr_routing[i].polarity;
+		iosapic_trigger(vector) = intr_routing[i].trigger;
+# ifdef DEBUG_IRQ_ROUTING
+		printk("irq[0x%x(0x%x)]:0x%x, %d, %d, %d\n", vector, intr_routing[i].srcbusirq,
+		       iosapic_pin(vector), iosapic_dmode(vector), iosapic_polarity(vector),
+		       iosapic_trigger(vector));
+# endif
+	}
+#else /* !defined(CONFIG_IA64_SOFTSDV_HACKS) && !defined(CONFIG_IA64_IRQ_ACPI) */
+	/* 
+	 * Map the legacy ISA devices into the IOAPIC data; We'll override these
+	 * later with data from the ACPI Interrupt Source Override table.
+	 *
+	 * Huh, the Lion w/ FPSWA firmware has entries for _all_ of the legacy IRQs, 
+	 * including those that are not different from PC/AT standard.  I don't know
+	 * if this is a bug in the other firmware or not.  I'm going to leave this code 
+	 * here, so that this works on BigSur but will go ask Intel. --wfd 2000-Jan-19
+	 *
+	 */
+	for (i =0 ; i < IA64_MIN_VECTORED_IRQ; i++) {
+		irq = map_legacy_irq(i);
+		iosapic_pin(irq) = i; 
+		iosapic_bus(irq) = BUS_ISA;
+		iosapic_busdata(irq) = 0;
+		iosapic_dmode(irq) = IO_SAPIC_LOWEST_PRIORITY;
+		iosapic_trigger(irq)  = IO_SAPIC_EDGE;
+		iosapic_polarity(irq) = IO_SAPIC_POL_HIGH;
+#ifdef DEBUG_IRQ_ROUTING
+		printk("ISA: IRQ %02x -> Vector %02x IOSAPIC Pin %d\n", i, irq, iosapic_pin(irq));
+#endif
+	}
+
+	/* 
+	 * Map the PCI Interrupt data into the ACPI IOSAPIC data using
+	 * the info that the bootstrap loader passed to us.
+	 */
+	ia64_boot_param.pci_vectors = (__u64) __va(ia64_boot_param.pci_vectors);
+	vectors = (struct pci_vector_struct *) ia64_boot_param.pci_vectors;
+	for (i = 0; i < ia64_boot_param.num_pci_vectors; i++) {
+		irq = map_legacy_irq(vectors[i].irq);
+
+		iosapic_bustype(irq) = BUS_PCI;
+		iosapic_pin(irq) = irq - iosapic_baseirq(irq);
+		iosapic_bus(irq) = vectors[i].bus;
+		/*
+		 * Map the PCI slot and pin data into iosapic_busdata()
+		 */
+		iosapic_busdata(irq) = (vectors[i].pci_id & 0xffff0000) | vectors[i].pin;
+
+		/* Default settings for PCI */
+		iosapic_dmode(irq) = IO_SAPIC_LOWEST_PRIORITY;
+		iosapic_trigger(irq)  = IO_SAPIC_LEVEL;
+		iosapic_polarity(irq) = IO_SAPIC_POL_LOW;
+
+#ifdef DEBUG_IRQ_ROUTING
+		printk("PCI: BUS %d Slot %x Pin %x IRQ %02x --> Vector %02x IOSAPIC Pin %d\n", 
+		       vectors[i].bus, vectors[i].pci_id>>16, vectors[i].pin, vectors[i].irq, 
+		       irq, iosapic_pin(irq));
+#endif
+	}
+#endif /* !CONFIG_IA64_IRQ_ACPI */
+}
+
+static void
+iosapic_startup_irq (unsigned int irq)
+{
+	int pin;
+
+	if (irq == TIMER_IRQ)
+		return;
+	pin = iosapic_pin(irq);
+	if (pin < 0)
+		/* happens during irq auto probing... */
+		return;
+	set_rte(iosapic_addr(irq), pin, iosapic_polarity(irq), iosapic_trigger(irq), 
+		iosapic_dmode(irq), (ia64_get_lid() >> 16) & 0xffff, irq);
+	enable_pin(pin, iosapic_addr(irq));
+}
+
+struct hw_interrupt_type irq_type_iosapic = {
+	"IOSAPIC",
+	iosapic_init,
+	iosapic_startup_irq,
+	iosapic_shutdown_irq,
+	iosapic_handle_irq,
+	iosapic_enable_irq,
+	iosapic_disable_irq
+};
+
+void
+dig_irq_init (struct irq_desc desc[NR_IRQS])
+{
+	int i;
+
+	/*
+	 * Claim all non-legacy irq vectors as ours unless they're
+	 * claimed by someone else already (e.g., timer or IPI are
+	 * handled internally).
+	 */
+	for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) {
+		if (irq_desc[i].handler == &irq_type_default)
+			irq_desc[i].handler = &irq_type_iosapic;
+	}
+}
+
+void
+dig_pci_fixup (void)
+{
+	struct	pci_dev	*dev;
+	int		irq;
+	unsigned char 	pin;
+
+	pci_for_each_dev(dev) {
+		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+		if (pin) {
+			pin--;          /* interrupt pins are numbered starting from 1 */
+			irq = iosapic_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn),
+							 pin);
+			if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+				struct pci_dev * bridge = dev->bus->self;
+
+				/* do the bridge swizzle... */
+				pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+				irq = iosapic_get_PCI_irq_vector(bridge->bus->number,
+								 PCI_SLOT(bridge->devfn), pin);
+				if (irq >= 0)
+					printk(KERN_WARNING
+					       "PCI: using PPB(B%d,I%d,P%d) to get irq %02x\n",
+					       bridge->bus->number, PCI_SLOT(bridge->devfn),
+					       pin, irq);
+			}
+			if (irq >= 0) {
+				printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %02x\n",
+				       dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+				dev->irq = irq;
+			}
+		}
+		/*
+		 * Nothing to fixup
+		 * Fix out-of-range IRQ numbers
+		 */
+		if (dev->irq >= NR_IRQS)
+			dev->irq = 15;	/* Spurious interrupts */
+	}
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/dig/machvec.c linux/arch/ia64/dig/machvec.c
--- v2.3.42/linux/arch/ia64/dig/machvec.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/dig/machvec.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,4 @@
+#include <asm/machvec_init.h>
+#include <asm/machvec_dig.h>
+
+MACHVEC_DEFINE(dig)
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/dig/setup.c linux/arch/ia64/dig/setup.c
--- v2.3.42/linux/arch/ia64/dig/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/dig/setup.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,93 @@
+/*
+ * Platform dependent support for Intel SoftSDV simulator.
+ *
+ * Copyright (C) 1999 Intel Corp.
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
+ */
+#include <linux/config.h>
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_IA64_FW_EMU
+# include "../../kernel/fw-emu.c"
+#endif
+
+/*
+ * This is here so we can use the CMOS detection in ide-probe.c to
+ * determine what drives are present.  In theory, we don't need this
+ * as the auto-detection could be done via ide-probe.c:do_probe() but
+ * in practice that would be much slower, which is painful when
+ * running in the simulator.  Note that passing zeroes in DRIVE_INFO
+ * is sufficient (the IDE driver will autodetect the drive geometry).
+ */
+char drive_info[4*16];
+
+unsigned char aux_device_present = 0xaa;	/* XXX remove this when legacy I/O is gone */
+
+void __init
+dig_setup (char **cmdline_p)
+{
+	unsigned int orig_x, orig_y, num_cols, num_rows, font_height;
+
+	/*
+	 * This assumes that the EFI partition is physical disk 1
+	 * partition 1 and the Linux root disk is physical disk 1
+	 * partition 2.
+	 */
+#ifdef CONFIG_IA64_LION_HACKS
+	/* default to /dev/sda2 on Lion... */
+	ROOT_DEV = to_kdev_t(0x0802);		/* default to second partition on first drive */
+#else
+	/* default to /dev/dha2 on BigSur... */
+	ROOT_DEV = to_kdev_t(0x0302);		/* default to second partition on first drive */
+#endif
+
+#ifdef CONFIG_SMP
+	init_smp_config();
+#endif
+
+	memset(&screen_info, 0, sizeof(screen_info));
+
+	if (!ia64_boot_param.console_info.num_rows
+	    || !ia64_boot_param.console_info.num_cols)
+	{
+		printk("dig_setup: warning: invalid screen-info, guessing 80x25\n");
+		orig_x = 0;
+		orig_y = 0;
+		num_cols = 80;
+		num_rows = 25;
+		font_height = 16;
+	} else {
+		orig_x = ia64_boot_param.console_info.orig_x;
+		orig_y = ia64_boot_param.console_info.orig_y;
+		num_cols = ia64_boot_param.console_info.num_cols;
+		num_rows = ia64_boot_param.console_info.num_rows;
+		font_height = 400 / num_rows;
+	}
+
+	screen_info.orig_x = orig_x;
+	screen_info.orig_y = orig_y;
+	screen_info.orig_video_cols  = num_cols;
+	screen_info.orig_video_lines = num_rows;
+	screen_info.orig_video_points = font_height;
+	screen_info.orig_video_mode = 3;	/* XXX fake */
+	screen_info.orig_video_isVGA = 1;	/* XXX fake */
+	screen_info.orig_video_ega_bx = 3;	/* XXX fake */
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/hp/Makefile linux/arch/ia64/hp/Makefile
--- v2.3.42/linux/arch/ia64/hp/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/hp/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,19 @@
+#
+# ia64/platform/hp/Makefile
+#
+# Copyright (C) 1999 Silicon Graphics, Inc.
+# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+#
+
+all: hp.a
+
+O_TARGET	= hp.a
+O_OBJS		= hpsim_console.o hpsim_irq.o hpsim_setup.o
+
+ifeq ($(CONFIG_IA64_GENERIC),y)
+O_OBJS		+= hpsim_machvec.o
+endif
+
+clean::
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/hp/hpsim_console.c linux/arch/ia64/hp/hpsim_console.c
--- v2.3.42/linux/arch/ia64/hp/hpsim_console.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/hp/hpsim_console.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,78 @@
+/*
+ * Platform dependent support for HP simulator.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/pal.h>
+#include <asm/machvec.h>
+#include <asm/pgtable.h>
+#include <asm/sal.h>
+
+#include "hpsim_ssc.h"
+
+static int simcons_init (struct console *, char *);
+static void simcons_write (struct console *, const char *, unsigned);
+static int simcons_wait_key (struct console *);
+static kdev_t simcons_console_device (struct console *);
+
+struct console hpsim_cons = {
+	"simcons",
+	simcons_write,		/* write */
+	NULL,			/* read */
+	simcons_console_device,	/* device */
+	simcons_wait_key,	/* wait_key */
+	NULL,			/* unblank */
+	simcons_init,		/* setup */
+	CON_PRINTBUFFER,	/* flags */
+	-1,			/* index */
+	0,			/* cflag */
+	NULL			/* next */
+};
+
+static int
+simcons_init (struct console *cons, char *options)
+{
+	return 0;
+}
+
+static void
+simcons_write (struct console *cons, const char *buf, unsigned count)
+{
+	unsigned long ch;
+
+	while (count-- > 0) {
+		ch = *buf++;
+		ia64_ssc(ch, 0, 0, 0, SSC_PUTCHAR);
+		if (ch == '\n')
+		  ia64_ssc('\r', 0, 0, 0, SSC_PUTCHAR);
+	}
+}
+
+static int
+simcons_wait_key (struct console *cons)
+{
+	char ch;
+
+	do {
+		ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR);
+	} while (ch == '\0');
+	return ch;
+}
+
+static kdev_t
+simcons_console_device (struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/hp/hpsim_irq.c linux/arch/ia64/hp/hpsim_irq.c
--- v2.3.42/linux/arch/ia64/hp/hpsim_irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/hp/hpsim_irq.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,83 @@
+/*
+ * Platform dependent support for HP simulator.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/pal.h>
+#include <asm/machvec.h>
+#include <asm/pgtable.h>
+#include <asm/sal.h>
+
+
+static int
+irq_hp_sim_handle_irq (unsigned int irq, struct pt_regs *regs)
+{
+	struct irqaction *action = 0;
+	struct irq_desc *id = irq_desc + irq;
+	unsigned int status;
+	int retval;
+
+	spin_lock(&irq_controller_lock);
+	{
+		status = id->status;
+		if ((status & IRQ_INPROGRESS) == 0 && (status & IRQ_ENABLED) != 0) {
+			action = id->action;
+			status |= IRQ_INPROGRESS;
+		}
+		id->status = status & ~(IRQ_REPLAY | IRQ_WAITING);
+	}
+	spin_unlock(&irq_controller_lock);
+
+	if (!action) {
+		if (!(id->status & IRQ_AUTODETECT))
+			printk("irq_hpsim_handle_irq: unexpected interrupt %u\n", irq);
+		return 0;
+	}
+
+	retval = invoke_irq_handlers(irq, regs, action);
+
+	spin_lock(&irq_controller_lock);
+	{
+		id->status &= ~IRQ_INPROGRESS;
+	}
+	spin_unlock(&irq_controller_lock);
+
+	return retval;
+}
+
+static void
+irq_hp_sim_noop (unsigned int irq)
+{
+}
+
+static struct hw_interrupt_type irq_type_hp_sim = {
+	"hp_sim",
+	(void (*)(unsigned long)) irq_hp_sim_noop,	/* init */
+	irq_hp_sim_noop,				/* startup */
+	irq_hp_sim_noop,				/* shutdown */
+	irq_hp_sim_handle_irq,				/* handle */
+	irq_hp_sim_noop,				/* enable */
+	irq_hp_sim_noop,				/* disable */
+};
+
+void
+hpsim_irq_init (struct irq_desc desc[NR_IRQS])
+{
+	int i;
+
+	for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) {
+		irq_desc[i].handler = &irq_type_hp_sim;
+	}
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/hp/hpsim_machvec.c linux/arch/ia64/hp/hpsim_machvec.c
--- v2.3.42/linux/arch/ia64/hp/hpsim_machvec.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/hp/hpsim_machvec.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,4 @@
+#include <asm/machvec_init.h>
+#include <asm/machvec_hpsim.h>
+
+MACHVEC_DEFINE(hpsim)
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/hp/hpsim_setup.c linux/arch/ia64/hp/hpsim_setup.c
--- v2.3.42/linux/arch/ia64/hp/hpsim_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/hp/hpsim_setup.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,71 @@
+/*
+ * Platform dependent support for HP simulator.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/pal.h>
+#include <asm/machvec.h>
+#include <asm/pgtable.h>
+#include <asm/sal.h>
+
+#include "hpsim_ssc.h"
+
+extern struct console hpsim_cons;
+
+/*
+ * Simulator system call.
+ */
+inline long
+ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr)
+{
+#ifdef __GCC_DOESNT_KNOW_IN_REGS__
+	register long in0 asm ("r32") = arg0;
+	register long in1 asm ("r33") = arg1;
+	register long in2 asm ("r34") = arg2;
+	register long in3 asm ("r35") = arg3;
+#else
+	register long in0 asm ("in0") = arg0;
+	register long in1 asm ("in1") = arg1;
+	register long in2 asm ("in2") = arg2;
+	register long in3 asm ("in3") = arg3;
+#endif
+	register long r8 asm ("r8");
+	register long r15 asm ("r15") = nr;
+
+	asm volatile ("break 0x80001"
+		      : "=r"(r8)
+		      : "r"(r15), "r"(in0), "r"(in1), "r"(in2), "r"(in3));
+	return r8;
+}
+
+void
+ia64_ssc_connect_irq (long intr, long irq)
+{
+	ia64_ssc(intr, irq, 0, 0, SSC_CONNECT_INTERRUPT);
+}
+
+void
+ia64_ctl_trace (long on)
+{
+	ia64_ssc(on, 0, 0, 0, SSC_CTL_TRACE);
+}
+
+void __init
+hpsim_setup (char **cmdline_p)
+{
+	ROOT_DEV = to_kdev_t(0x0801);		/* default to first SCSI drive */
+
+	register_console (&hpsim_cons);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/hp/hpsim_ssc.h linux/arch/ia64/hp/hpsim_ssc.h
--- v2.3.42/linux/arch/ia64/hp/hpsim_ssc.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/hp/hpsim_ssc.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,36 @@
+/*
+ * Platform dependent support for HP simulator.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
+ */
+#ifndef _IA64_PLATFORM_HPSIM_SSC_H
+#define _IA64_PLATFORM_HPSIM_SSC_H
+
+/* Simulator system calls: */
+
+#define SSC_CONSOLE_INIT		20
+#define SSC_GETCHAR			21
+#define SSC_PUTCHAR			31
+#define SSC_CONNECT_INTERRUPT		58
+#define SSC_GENERATE_INTERRUPT		59
+#define SSC_SET_PERIODIC_INTERRUPT	60
+#define SSC_GET_RTC			65
+#define SSC_EXIT			66
+#define SSC_LOAD_SYMBOLS		69
+#define SSC_GET_TOD			74
+#define SSC_CTL_TRACE			76
+
+#define SSC_NETDEV_PROBE		100
+#define SSC_NETDEV_SEND			101
+#define SSC_NETDEV_RECV			102
+#define SSC_NETDEV_ATTACH		103
+#define SSC_NETDEV_DETACH		104
+
+/*
+ * Simulator system call.
+ */
+extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr);
+
+#endif /* _IA64_PLATFORM_HPSIM_SSC_H */
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/ia32/Makefile linux/arch/ia64/ia32/Makefile
--- v2.3.42/linux/arch/ia64/ia32/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/ia32/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,17 @@
+#
+# Makefile for the ia32 kernel emulation subsystem.
+#
+
+.S.s:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
+all: ia32.o
+
+O_TARGET := ia32.o
+O_OBJS	 := ia32_entry.o ia32_signal.o sys_ia32.o ia32_support.o binfmt_elf32.o
+
+clean::
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/ia32/binfmt_elf32.c linux/arch/ia64/ia32/binfmt_elf32.c
--- v2.3.42/linux/arch/ia64/ia32/binfmt_elf32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/ia32/binfmt_elf32.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,180 @@
+/*
+ * IA-32 ELF support.
+ *
+ * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
+ */
+#include <linux/config.h>
+#include <linux/posix_types.h>
+
+#include <asm/signal.h>
+#include <asm/ia32.h>
+
+#define CONFIG_BINFMT_ELF32
+
+/* Override some function names */
+#undef start_thread
+#define start_thread			ia32_start_thread
+#define init_elf_binfmt			init_elf32_binfmt
+
+#undef CONFIG_BINFMT_ELF
+#ifdef CONFIG_BINFMT_ELF32
+# define CONFIG_BINFMT_ELF		CONFIG_BINFMT_ELF32
+#endif
+
+#undef CONFIG_BINFMT_ELF_MODULE
+#ifdef CONFIG_BINFMT_ELF32_MODULE
+# define CONFIG_BINFMT_ELF_MODULE	CONFIG_BINFMT_ELF32_MODULE
+#endif
+
+void ia64_elf32_init(struct pt_regs *regs);
+#define ELF_PLAT_INIT(_r)		ia64_elf32_init(_r)
+
+#define setup_arg_pages(bprm)		ia32_setup_arg_pages(bprm)
+
+/* Ugly but avoids duplication */
+#include "../../../fs/binfmt_elf.c"
+
+/* Global descriptor table */
+unsigned long *ia32_gdt_table, *ia32_tss;
+
+struct page *
+put_shared_page(struct task_struct * tsk, struct page *page, unsigned long address)
+{
+	pgd_t * pgd;
+	pmd_t * pmd;
+	pte_t * pte;
+
+	if (page_count(page) != 1)
+		printk("mem_map disagrees with %p at %08lx\n", page, address);
+	pgd = pgd_offset(tsk->mm, address);
+	pmd = pmd_alloc(pgd, address);
+	if (!pmd) {
+		__free_page(page);
+		oom(tsk);
+		return 0;
+	}
+	pte = pte_alloc(pmd, address);
+	if (!pte) {
+		__free_page(page);
+		oom(tsk);
+		return 0;
+	}
+	if (!pte_none(*pte)) {
+		pte_ERROR(*pte);
+		__free_page(page);
+		return 0;
+	}
+	flush_page_to_ram(page);
+	set_pte(pte, pte_mkwrite(mk_pte(page, PAGE_SHARED)));
+	/* no need for flush_tlb */
+	return page;
+}
+
+void ia64_elf32_init(struct pt_regs *regs)
+{
+	int nr;
+
+	put_shared_page(current, mem_map + MAP_NR(ia32_gdt_table), IA32_PAGE_OFFSET);
+	if (PAGE_SHIFT <= IA32_PAGE_SHIFT)
+		put_shared_page(current, mem_map + MAP_NR(ia32_tss), IA32_PAGE_OFFSET + PAGE_SIZE);
+
+	nr = smp_processor_id();
+	
+	/* Do all the IA-32 setup here */
+
+	/* CS descriptor */
+	__asm__("mov ar.csd = %0" : /* no outputs */
+		: "r" IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0xBL, 1L,
+					  3L, 1L, 1L, 1L));
+	/* SS descriptor */
+	__asm__("mov ar.ssd = %0" : /* no outputs */
+		: "r" IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L,
+					  3L, 1L, 1L, 1L));
+	/* EFLAGS */
+	__asm__("mov ar.eflag = %0" : /* no outputs */ : "r" (IA32_EFLAG));
+
+	/* Control registers */
+	__asm__("mov ar.cflg = %0"
+		: /* no outputs */
+		: "r" (((ulong) IA32_CR4 << 32) | IA32_CR0));
+	__asm__("mov ar.fsr = %0"
+		: /* no outputs */
+		: "r" ((ulong)IA32_FSR_DEFAULT));
+	__asm__("mov ar.fcr = %0"
+		: /* no outputs */
+		: "r" ((ulong)IA32_FCR_DEFAULT));
+	__asm__("mov ar.fir = r0");
+	__asm__("mov ar.fdr = r0");
+	/* TSS */
+	__asm__("mov ar.k1 = %0"
+		: /* no outputs */
+		: "r" IA64_SEG_DESCRIPTOR(IA32_PAGE_OFFSET + PAGE_SIZE,
+					  0x1FFFL, 0xBL, 1L,
+					  3L, 1L, 1L, 1L));
+
+	/* Get the segment selectors right */
+	regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
+	regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32)
+		    | (__USER_DS << 16) | __USER_CS;
+
+	/* Setup other segment descriptors - ESD, DSD, FSD, GSD */
+	regs->r24 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
+	regs->r27 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
+	regs->r28 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
+	regs->r29 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
+
+	/* Setup the LDT and GDT */
+	regs->r30 = ia32_gdt_table[_LDT(nr)];
+	regs->r31 = IA64_SEG_DESCRIPTOR(0xc0000000L, 0x400L, 0x3L, 1L, 3L,
+					1L, 1L, 1L);
+
+       	/* Clear psr.ac */
+	regs->cr_ipsr &= ~IA64_PSR_AC;
+
+	regs->loadrs = 0;
+}
+
+#undef STACK_TOP
+#define STACK_TOP ((IA32_PAGE_OFFSET/3) * 2)
+
+int ia32_setup_arg_pages(struct linux_binprm *bprm)
+{
+	unsigned long stack_base;
+	struct vm_area_struct *mpnt;
+	int i;
+
+	stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
+
+	bprm->p += stack_base;
+	if (bprm->loader)
+		bprm->loader += stack_base;
+	bprm->exec += stack_base;
+
+	mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	if (!mpnt) 
+		return -ENOMEM; 
+	
+	{
+		mpnt->vm_mm = current->mm;
+		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
+		mpnt->vm_end = STACK_TOP;
+		mpnt->vm_page_prot = PAGE_COPY;
+		mpnt->vm_flags = VM_STACK_FLAGS;
+		mpnt->vm_ops = NULL;
+		mpnt->vm_pgoff = 0;
+		mpnt->vm_file = NULL;
+		mpnt->vm_private_data = 0;
+		insert_vm_struct(current->mm, mpnt);
+		current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+	} 
+
+	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
+		if (bprm->page[i]) {
+			current->mm->rss++;
+			put_dirty_page(current,bprm->page[i],stack_base);
+		}
+		stack_base += PAGE_SIZE;
+	}
+	
+	return 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/ia32/ia32_entry.S linux/arch/ia64/ia32/ia32_entry.S
--- v2.3.42/linux/arch/ia64/ia32/ia32_entry.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/ia32/ia32_entry.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,255 @@
+#include <asm/offsets.h>
+#include <asm/signal.h>
+
+	.global ia32_ret_from_syscall
+	.proc ia64_ret_from_syscall
+ia32_ret_from_syscall:
+	cmp.ge p6,p7=r8,r0                      // syscall executed successfully?
+	adds r2=IA64_PT_REGS_R8_OFFSET+16,sp    // r2 = &pt_regs.r8
+	;; 
+	st8 [r2]=r8                             // store return value in slot for r8
+	br.cond.sptk.few ia64_leave_kernel
+
+	//
+	// Invoke a system call, but do some tracing before and after the call.
+	// We MUST preserve the current register frame throughout this routine
+	// because some system calls (such as ia64_execve) directly
+	// manipulate ar.pfs.
+	//
+	// Input:
+	//	r15 = syscall number
+	//	b6  = syscall entry point
+	//
+	.global ia32_trace_syscall
+	.proc ia32_trace_syscall
+ia32_trace_syscall:
+	br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
+.Lret4:	br.call.sptk.few rp=b6			// do the syscall
+.Lret5:	cmp.lt p6,p0=r8,r0			// syscall failed?
+	adds r2=IA64_PT_REGS_R8_OFFSET+16,sp	// r2 = &pt_regs.r8
+	;;
+	st8.spill [r2]=r8			// store return value in slot for r8
+	br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
+.Lret6:	br.cond.sptk.many ia64_leave_kernel	// rp MUST be != ia64_leave_kernel!
+
+	.endp ia32_trace_syscall
+
+	.align 16
+	.global sys32_fork
+	.proc sys32_fork
+sys32_fork:
+	alloc r16=ar.pfs,2,2,3,0;;
+	movl r28=1f
+	mov loc1=rp
+	br.cond.sptk.many save_switch_stack
+1:
+	mov loc0=r16				// save ar.pfs across do_fork
+	adds out2=IA64_SWITCH_STACK_SIZE+16,sp
+	adds r2=IA64_SWITCH_STACK_SIZE+IA64_PT_REGS_R12_OFFSET+16,sp
+	mov out0=SIGCHLD			// out0 = clone_flags
+	;;
+	ld8 out1=[r2]				// fetch usp from pt_regs.r12
+	br.call.sptk.few rp=do_fork
+.ret1:
+	mov ar.pfs=loc0
+	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
+	mov rp=loc1
+	;;
+	br.ret.sptk.many rp
+	.endp sys32_fork
+
+	.rodata
+	.align 8
+	.globl ia32_syscall_table
+ia32_syscall_table:	
+	data8 sys_ni_syscall	  /* 0	-  old "setup(" system call*/
+	data8 sys_exit
+	data8 sys32_fork
+	data8 sys_read
+	data8 sys_write
+	data8 sys_open		  /* 5 */
+	data8 sys_close
+	data8 sys32_waitpid
+	data8 sys_creat
+	data8 sys_link
+	data8 sys_unlink	  /* 10 */
+	data8 sys32_execve
+	data8 sys_chdir
+	data8 sys_ni_syscall /* sys_time is not supported on ia64 */
+	data8 sys_mknod
+	data8 sys_chmod		  /* 15 */
+	data8 sys_lchown
+	data8 sys_ni_syscall	  /* old break syscall holder */
+	data8 sys_ni_syscall
+	data8 sys_lseek
+	data8 sys_getpid	  /* 20 */
+	data8 sys_mount
+	data8 sys_oldumount
+	data8 sys_setuid
+	data8 sys_getuid
+	data8 sys_ni_syscall /* sys_stime is not supported on IA64 */  /* 25 */
+	data8 sys_ptrace
+	data8 sys32_alarm
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall	  /* 30 */
+	data8 sys_ni_syscall	  /* old stty syscall holder */
+	data8 sys_ni_syscall	  /* old gtty syscall holder */
+	data8 sys_access
+	data8 sys_nice
+	data8 sys_ni_syscall	  /* 35 */	  /* old ftime syscall holder */
+	data8 sys_sync
+	data8 sys_kill
+	data8 sys_rename
+	data8 sys_mkdir
+	data8 sys_rmdir		  /* 40 */
+	data8 sys_dup
+	data8 sys32_pipe
+	data8 sys_times
+	data8 sys_ni_syscall	  /* old prof syscall holder */
+	data8 sys_brk		  /* 45 */
+	data8 sys_setgid
+	data8 sys_getgid
+	data8 sys_ni_syscall
+	data8 sys_geteuid
+	data8 sys_getegid	  /* 50 */
+	data8 sys_acct
+	data8 sys_umount	  /* recycled never used phys( */
+	data8 sys_ni_syscall	  /* old lock syscall holder */
+	data8 sys_ioctl
+	data8 sys_fcntl		  /* 55 */
+	data8 sys_ni_syscall	  /* old mpx syscall holder */
+	data8 sys_setpgid
+	data8 sys_ni_syscall	  /* old ulimit syscall holder */
+	data8 sys_ni_syscall
+	data8 sys_umask		  /* 60 */
+	data8 sys_chroot
+	data8 sys_ustat
+	data8 sys_dup2
+	data8 sys_getppid
+	data8 sys_getpgrp	  /* 65 */
+	data8 sys_setsid
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_ni_syscall
+	data8 sys_setreuid	  /* 70 */
+	data8 sys_setregid
+	data8 sys_ni_syscall
+	data8 sys_sigpending
+	data8 sys_sethostname
+	data8 sys32_setrlimit	  /* 75 */
+	data8 sys32_getrlimit
+	data8 sys_getrusage
+	data8 sys32_gettimeofday
+	data8 sys32_settimeofday
+	data8 sys_getgroups	  /* 80 */
+	data8 sys_setgroups
+	data8 sys_ni_syscall
+	data8 sys_symlink
+	data8 sys_ni_syscall
+	data8 sys_readlink	  /* 85 */
+	data8 sys_uselib
+	data8 sys_swapon
+	data8 sys_reboot
+	data8 sys32_readdir
+	data8 sys32_mmap	  /* 90 */
+	data8 sys_munmap
+	data8 sys_truncate
+	data8 sys_ftruncate
+	data8 sys_fchmod
+	data8 sys_fchown	  /* 95 */
+	data8 sys_getpriority
+	data8 sys_setpriority
+	data8 sys_ni_syscall	  /* old profil syscall holder */
+	data8 sys32_statfs
+	data8 sys32_fstatfs	  /* 100 */
+	data8 sys_ioperm
+	data8 sys32_socketcall
+	data8 sys_syslog
+	data8 sys32_setitimer
+	data8 sys32_getitimer	  /* 105 */
+	data8 sys32_newstat
+	data8 sys32_newlstat
+	data8 sys32_newfstat
+	data8 sys_ni_syscall
+	data8 sys_iopl		  /* 110 */
+	data8 sys_vhangup
+	data8 sys_ni_syscall		// used to be sys_idle
+	data8 sys_ni_syscall
+	data8 sys32_wait4
+	data8 sys_swapoff	  /* 115 */
+	data8 sys_sysinfo
+	data8 sys32_ipc
+	data8 sys_fsync
+	data8 sys32_sigreturn
+	data8 sys_clone		  /* 120 */
+	data8 sys_setdomainname
+	data8 sys_newuname
+	data8 sys_modify_ldt
+	data8 sys_adjtimex
+	data8 sys32_mprotect	  /* 125 */
+	data8 sys_sigprocmask
+	data8 sys_create_module
+	data8 sys_init_module
+	data8 sys_delete_module
+	data8 sys_get_kernel_syms  /* 130 */
+	data8 sys_quotactl
+	data8 sys_getpgid
+	data8 sys_fchdir
+	data8 sys_bdflush
+	data8 sys_sysfs		  /* 135 */
+	data8 sys_personality
+	data8 sys_ni_syscall	  /* for afs_syscall */
+	data8 sys_setfsuid
+	data8 sys_setfsgid
+	data8 sys_llseek	  /* 140 */
+	data8 sys32_getdents
+	data8 sys32_select
+	data8 sys_flock
+	data8 sys_msync
+	data8 sys32_readv	  /* 145 */
+	data8 sys32_writev
+	data8 sys_getsid
+	data8 sys_fdatasync
+	data8 sys_sysctl
+	data8 sys_mlock		  /* 150 */
+	data8 sys_munlock
+	data8 sys_mlockall
+	data8 sys_munlockall
+	data8 sys_sched_setparam
+	data8 sys_sched_getparam  /* 155 */
+	data8 sys_sched_setscheduler
+	data8 sys_sched_getscheduler
+	data8 sys_sched_yield
+	data8 sys_sched_get_priority_max
+	data8 sys_sched_get_priority_min	 /* 160 */
+	data8 sys_sched_rr_get_interval
+	data8 sys32_nanosleep
+	data8 sys_mremap
+	data8 sys_setresuid
+	data8 sys_getresuid	  /* 165 */
+	data8 sys_vm86
+	data8 sys_query_module
+	data8 sys_poll
+	data8 sys_nfsservctl
+	data8 sys_setresgid	  /* 170 */
+	data8 sys_getresgid
+	data8 sys_prctl
+	data8 sys32_rt_sigreturn
+	data8 sys32_rt_sigaction
+	data8 sys32_rt_sigprocmask /* 175 */
+	data8 sys_rt_sigpending
+	data8 sys_rt_sigtimedwait
+	data8 sys_rt_sigqueueinfo
+	data8 sys_rt_sigsuspend
+	data8 sys_pread		  /* 180 */
+	data8 sys_pwrite
+	data8 sys_chown
+	data8 sys_getcwd
+	data8 sys_capget
+	data8 sys_capset	  /* 185 */
+	data8 sys_sigaltstack
+	data8 sys_sendfile
+	data8 sys_ni_syscall		  /* streams1 */
+	data8 sys_ni_syscall		  /* streams2 */
+	data8 sys32_vfork	  /* 190 */
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/ia32/ia32_signal.c linux/arch/ia64/ia32/ia32_signal.c
--- v2.3.42/linux/arch/ia64/ia32/ia32_signal.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/ia32/ia32_signal.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,412 @@
+/*
+ * IA32 Architecture-specific signal handling support.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
+ * Copyright (C) 2000 VA Linux Co
+ * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
+ *
+ * Derived from i386 and Alpha versions.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/wait.h>
+
+#include <asm/uaccess.h>
+#include <asm/rse.h>
+#include <asm/sigcontext.h>
+#include <asm/segment.h>
+#include <asm/ia32.h>
+
+#define DEBUG_SIG	0
+#define _BLOCKABLE	(~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+
+struct sigframe_ia32
+{
+       int pretcode;
+       int sig;
+       struct sigcontext_ia32 sc;
+       struct _fpstate_ia32 fpstate;
+       unsigned int extramask[_IA32_NSIG_WORDS-1];
+       char retcode[8];
+};
+
+struct rt_sigframe_ia32
+{
+       int pretcode;
+       int sig;
+       int pinfo;
+       int puc;
+       struct siginfo info;
+       struct ucontext_ia32 uc;
+       struct _fpstate_ia32 fpstate;
+       char retcode[8];
+};
+
+static int
+setup_sigcontext_ia32(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
+                struct pt_regs *regs, unsigned long mask)
+{
+       int  err = 0;
+
+       err |= __put_user((regs->r16 >> 32) & 0xffff , (unsigned int *)&sc->fs);
+       err |= __put_user((regs->r16 >> 48) & 0xffff , (unsigned int *)&sc->gs);
+
+       err |= __put_user((regs->r16 >> 56) & 0xffff, (unsigned int *)&sc->es);
+       err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
+       err |= __put_user(regs->r15, &sc->edi);
+       err |= __put_user(regs->r14, &sc->esi);
+       err |= __put_user(regs->r13, &sc->ebp);
+       err |= __put_user(regs->r12, &sc->esp);
+       err |= __put_user(regs->r11, &sc->ebx);
+       err |= __put_user(regs->r10, &sc->edx);
+       err |= __put_user(regs->r9, &sc->ecx);
+       err |= __put_user(regs->r8, &sc->eax);
+#if 0
+       err |= __put_user(current->tss.trap_no, &sc->trapno);
+       err |= __put_user(current->tss.error_code, &sc->err);
+#endif
+       err |= __put_user(regs->cr_iip, &sc->eip);
+       err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
+#if 0
+       err |= __put_user(regs->eflags, &sc->eflags);
+#endif
+       
+       err |= __put_user(regs->r12, &sc->esp_at_signal);
+       err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);
+
+#if 0
+       tmp = save_i387(fpstate);
+       if (tmp < 0)
+         err = 1;
+       else
+         err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
+
+       /* non-iBCS2 extensions.. */
+       err |= __put_user(mask, &sc->oldmask);
+       err |= __put_user(current->tss.cr2, &sc->cr2);
+#endif
+       
+       return err;
+}
+
+static int
+restore_sigcontext_ia32(struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
+{
+       unsigned int err = 0;
+
+#define COPY(ia64x, ia32x)             err |= __get_user(regs->ia64x, &sc->ia32x)
+
+#define copyseg_gs(tmp)        (regs->r16 |= (unsigned long) tmp << 48)
+#define copyseg_fs(tmp)        (regs->r16 |= (unsigned long) tmp << 32)
+#define copyseg_cs(tmp)        (regs->r17 |= tmp)
+#define copyseg_ss(tmp)        (regs->r17 |= (unsigned long) tmp << 16)
+#define copyseg_es(tmp)        (regs->r16 |= (unsigned long) tmp << 16)
+#define copyseg_ds(tmp)        (regs->r16 |= tmp)
+
+#define COPY_SEG(seg)                                          \
+       { unsigned short tmp;                                   \
+         err |= __get_user(tmp, &sc->seg);                             \
+         copyseg_##seg(tmp); }
+
+#define COPY_SEG_STRICT(seg)                                   \
+       { unsigned short tmp;                                   \
+         err |= __get_user(tmp, &sc->seg);                             \
+         copyseg_##seg(tmp|3); }
+
+       /* To make COPY_SEGs easier, we zero r16, r17 */
+       regs->r16 = 0;
+       regs->r17 = 0;
+
+       COPY_SEG(gs);
+       COPY_SEG(fs);
+       COPY_SEG(es);
+       COPY_SEG(ds);
+       COPY(r15, edi);
+       COPY(r14, esi);
+       COPY(r13, ebp);
+       COPY(r12, esp);
+       COPY(r11, ebx);
+       COPY(r10, edx);
+       COPY(r9, ecx);
+       COPY(cr_iip, eip);
+       COPY_SEG_STRICT(cs);
+       COPY_SEG_STRICT(ss);
+#if 0
+       {
+               unsigned int tmpflags;
+               err |= __get_user(tmpflags, &sc->eflags);
+               /* XXX: Change this to ar.eflags */
+               regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
+               regs->orig_eax = -1;            /* disable syscall checks */
+       }
+
+       {
+               struct _fpstate * buf;
+               err |= __get_user(buf, &sc->fpstate);
+               if (buf) {
+                       if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+                               goto badframe;
+                       err |= restore_i387(buf);
+               }
+       }
+#endif
+
+       err |= __get_user(*peax, &sc->eax);
+       return err;
+
+#if 0       
+badframe:
+       return 1;
+#endif
+
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+{
+       unsigned long esp;
+       unsigned int xss;
+
+       /* Default to using normal stack */
+       esp = regs->r12;
+       xss = regs->r16 >> 16;
+
+       /* This is the X/Open sanctioned signal stack switching.  */
+       if (ka->sa.sa_flags & SA_ONSTACK) {
+               if (! on_sig_stack(esp))
+                       esp = current->sas_ss_sp + current->sas_ss_size;
+       }
+       /* Legacy stack switching not supported */
+       
+       return (void *)((esp - frame_size) & -8ul);
+}
+
+static void
+setup_frame_ia32(int sig, struct k_sigaction *ka, sigset_t *set,
+           struct pt_regs * regs) 
+{      
+       struct sigframe_ia32 *frame;
+       int err = 0;
+
+       frame = get_sigframe(ka, regs, sizeof(*frame));
+
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               goto give_sigsegv;
+
+       err |= __put_user((current->exec_domain
+                          && current->exec_domain->signal_invmap
+                          && sig < 32
+                          ? (int)(current->exec_domain->signal_invmap[sig])
+                          : sig),
+                         &frame->sig);
+
+       err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+
+       if (_NSIG_WORDS > 1) {
+               err |= __copy_to_user(frame->extramask, &set->sig[1],
+                                     sizeof(frame->extramask));
+       }
+
+       /* Set up to return from userspace.  If provided, use a stub
+          already in userspace.  */
+       err |= __put_user(frame->retcode, &frame->pretcode);
+       /* This is popl %eax ; movl $,%eax ; int $0x80 */
+       err |= __put_user(0xb858, (short *)(frame->retcode+0));
+#define __IA32_NR_sigreturn            119
+       err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
+       err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
+       err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+
+       if (err)
+               goto give_sigsegv;
+
+       /* Set up registers for signal handler */
+       regs->r12 = (unsigned long) frame;
+       regs->cr_iip = (unsigned long) ka->sa.sa_handler;
+
+       set_fs(USER_DS);
+       regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
+       regs->r17 = (__USER_DS << 16) | __USER_CS;
+
+#if 0
+       regs->eflags &= ~TF_MASK;
+#endif
+
+#if 1
+       printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
+               current->comm, current->pid, frame, regs->cr_iip, frame->pretcode);
+#endif
+
+       return;
+
+give_sigsegv:
+       if (sig == SIGSEGV)
+               ka->sa.sa_handler = SIG_DFL;
+       force_sig(SIGSEGV, current);
+}
+
+static void
+setup_rt_frame_ia32(int sig, struct k_sigaction *ka, siginfo_t *info,
+              sigset_t *set, struct pt_regs * regs)
+{
+       struct rt_sigframe_ia32 *frame;
+       int err = 0;
+
+       frame = get_sigframe(ka, regs, sizeof(*frame));
+
+       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+               goto give_sigsegv;
+
+       err |= __put_user((current->exec_domain
+                          && current->exec_domain->signal_invmap
+                          && sig < 32
+                          ? current->exec_domain->signal_invmap[sig]
+                          : sig),
+                         &frame->sig);
+       err |= __put_user(&frame->info, &frame->pinfo);
+       err |= __put_user(&frame->uc, &frame->puc);
+       err |= __copy_to_user(&frame->info, info, sizeof(*info));
+
+       /* Create the ucontext.  */
+       err |= __put_user(0, &frame->uc.uc_flags);
+       err |= __put_user(0, &frame->uc.uc_link);
+       err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+       err |= __put_user(sas_ss_flags(regs->r12),
+                         &frame->uc.uc_stack.ss_flags);
+       err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+       err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate,
+                               regs, set->sig[0]);
+       err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+       
+       err |= __put_user(frame->retcode, &frame->pretcode);
+       /* This is movl $,%eax ; int $0x80 */
+       err |= __put_user(0xb8, (char *)(frame->retcode+0));
+#define __IA32_NR_rt_sigreturn         173
+       err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
+       err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+
+       if (err)
+               goto give_sigsegv;
+
+       /* Set up registers for signal handler */
+       regs->r12 = (unsigned long) frame;
+       regs->cr_iip = (unsigned long) ka->sa.sa_handler;
+
+       set_fs(USER_DS);
+
+       regs->r16 = (__USER_DS << 16) |  (__USER_DS); /* ES == DS, GS, FS are zero */
+       regs->r17 = (__USER_DS << 16) | __USER_CS;
+
+#if 0
+       regs->eflags &= ~TF_MASK;
+#endif
+
+#if 1
+       printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
+               current->comm, current->pid, frame, regs->cr_iip, frame->pretcode);
+#endif
+
+       return;
+
+give_sigsegv:
+       if (sig == SIGSEGV)
+               ka->sa.sa_handler = SIG_DFL;
+       force_sig(SIGSEGV, current);
+}
+
+long
+ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
+		   sigset_t *set, struct pt_regs *regs)
+{
+       /* Set up the stack frame */
+       if (ka->sa.sa_flags & SA_SIGINFO)
+               setup_rt_frame_ia32(sig, ka, info, set, regs);
+       else
+               setup_frame_ia32(sig, ka, set, regs);
+
+}
+
+asmlinkage int
+sys32_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack)
+{
+       struct pt_regs *regs = (struct pt_regs *) &stack;
+       struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(regs->r12- 8);
+       sigset_t set;
+       int eax;
+
+       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+               goto badframe;
+
+       if (__get_user(set.sig[0], &frame->sc.oldmask)
+           || (_IA32_NSIG_WORDS > 1
+               && __copy_from_user((((char *) &set.sig) + 4),
+                                   &frame->extramask,
+                                   sizeof(frame->extramask))))
+               goto badframe;
+
+       sigdelsetmask(&set, ~_BLOCKABLE);
+       spin_lock_irq(&current->sigmask_lock);
+       current->blocked = (sigset_t) set;
+       recalc_sigpending(current);
+       spin_unlock_irq(&current->sigmask_lock);
+       
+       if (restore_sigcontext_ia32(regs, &frame->sc, &eax))
+               goto badframe;
+       return eax;
+
+badframe:
+       force_sig(SIGSEGV, current);
+       return 0;
+}      
+
+asmlinkage int
+sys32_rt_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack)
+{
+       struct pt_regs *regs = (struct pt_regs *) &stack;
+       struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(regs->r12 - 4);
+       sigset_t set;
+       stack_t st;
+       int eax;
+
+       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+               goto badframe;
+       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+               goto badframe;
+
+       sigdelsetmask(&set, ~_BLOCKABLE);
+       spin_lock_irq(&current->sigmask_lock);
+       current->blocked =  set;
+       recalc_sigpending(current);
+       spin_unlock_irq(&current->sigmask_lock);
+       
+       if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
+               goto badframe;
+
+       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+               goto badframe;
+       /* It is more difficult to avoid calling this function than to
+          call it and ignore errors.  */
+       do_sigaltstack(&st, NULL, regs->r12);
+
+       return eax;
+
+badframe:
+       force_sig(SIGSEGV, current);
+       return 0;
+}      
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/ia32/ia32_support.c linux/arch/ia64/ia32/ia32_support.c
--- v2.3.42/linux/arch/ia64/ia32/ia32_support.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/ia32/ia32_support.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,61 @@
+/*
+ * IA32 helper functions
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/ia32.h>
+
+extern unsigned long *ia32_gdt_table, *ia32_tss;
+
+extern void die_if_kernel (char *str, struct pt_regs *regs, long err);
+
+/*
+ * Setup IA32 GDT and TSS 
+ */
+void
+ia32_gdt_init(void)
+{
+	unsigned long gdt_and_tss_page;
+
+	/* allocate two IA-32 pages of memory: */
+	gdt_and_tss_page = __get_free_pages(GFP_KERNEL,
+					    (IA32_PAGE_SHIFT < PAGE_SHIFT)
+					    ? 0 : (IA32_PAGE_SHIFT + 1) - PAGE_SHIFT);
+	ia32_gdt_table = (unsigned long *) gdt_and_tss_page;
+	ia32_tss = (unsigned long *) (gdt_and_tss_page + IA32_PAGE_SIZE);
+
+	/* Zero the gdt and tss */
+	memset((void *) gdt_and_tss_page, 0, 2*IA32_PAGE_SIZE);
+
+	/* CS descriptor in IA-32 format */
+	ia32_gdt_table[4] = IA32_SEG_DESCRIPTOR(0L, 0xBFFFFFFFL, 0xBL, 1L,
+						3L, 1L, 1L, 1L, 1L);
+
+	/* DS descriptor in IA-32 format */
+	ia32_gdt_table[5] = IA32_SEG_DESCRIPTOR(0L, 0xBFFFFFFFL, 0x3L, 1L,
+						3L, 1L, 1L, 1L, 1L);
+}
+
+/*
+ * Handle bad IA32 interrupt via syscall 
+ */
+void
+ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
+{
+	siginfo_t siginfo;
+
+	die_if_kernel("Bad IA-32 interrupt", regs, int_num);
+
+	siginfo.si_signo = SIGTRAP;
+	siginfo.si_errno = int_num;	/* XXX is it legal to abuse si_errno like this? */
+	siginfo.si_code = TRAP_BRKPT;
+	force_sig_info(SIGTRAP, &siginfo, current);
+}
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c
--- v2.3.42/linux/arch/ia64/ia32/sys_ia32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/ia32/sys_ia32.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,4309 @@
+/*
+ * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
+ *             sys_sparc32 
+ *
+ * Copyright (C) 2000		VA Linux Co
+ * Copyright (C) 2000		Don Dugger <n0ano@valinux.com>
+ * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com>
+ * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu)
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * environment.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h> 
+#include <linux/file.h> 
+#include <linux/signal.h>
+#include <linux/utime.h>
+#include <linux/resource.h>
+#include <linux/times.h>
+#include <linux/utsname.h>
+#include <linux/timex.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/malloc.h>
+#include <linux/uio.h>
+#include <linux/nfs_fs.h>
+#include <linux/smb_fs.h>
+#include <linux/smb_mount.h>
+#include <linux/ncp_fs.h>
+#include <linux/quota.h>
+#include <linux/module.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr.h>
+#include <linux/nfsd/syscall.h>
+#include <linux/poll.h>
+#include <linux/personality.h>
+#include <linux/stat.h>
+#include <linux/ipc.h>
+
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <asm/ipc.h>
+
+#include <net/scm.h>
+#include <net/sock.h>
+#include <asm/ia32.h>
+
+#define A(__x) ((unsigned long)(__x))
+#define AA(__x) ((unsigned long)(__x))
+
+/*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+asmlinkage int sys32_vfork(
+int dummy0,
+int dummy1,
+int dummy2,
+int dummy3,
+int dummy4,
+int dummy5,
+int dummy6,
+int dummy7,
+int stack)
+{
+	struct pt_regs *regs = (struct pt_regs *)&stack;
+
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r12, regs);
+}
+
+static int
+nargs(unsigned int arg, char **ap)
+{
+	char *ptr;
+	int n, err;
+
+	n = 0;
+	do {
+		if (err = get_user(ptr, (int *)arg))
+			return(err);
+		if (ap)
+			*ap++ = ptr;
+		arg += sizeof(unsigned int);
+		n++;
+	} while (ptr);
+	return(n - 1);
+}
+
+asmlinkage long
+sys32_execve(
+char *filename,
+unsigned int argv,
+unsigned int envp,
+int dummy3,
+int dummy4,
+int dummy5,
+int dummy6,
+int dummy7,
+int stack)
+{
+	struct pt_regs *regs = (struct pt_regs *)&stack;
+	char **av, **ae;
+	int na, ne, r, len;
+
+	na = nargs(argv, NULL);
+	ne = nargs(envp, NULL);
+	len = (na + ne + 2) * sizeof(*av);
+	/*
+	 *  kmalloc won't work because the `sys_exec' code will attempt
+	 *  to do a `get_user' on the arg list and `get_user' will fail
+	 *  on a kernel address (simplifies `get_user').  Instead we
+	 *  do an mmap to get a user address.  Note that since a successful
+	 *  `execve' frees all current memory we only have to do an
+	 *  `munmap' if the `execve' failes.
+	 */
+	down(&current->mm->mmap_sem);
+	lock_kernel();
+
+	av = do_mmap_pgoff(0, NULL, len,
+		PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0);
+
+	unlock_kernel();
+	up(&current->mm->mmap_sem);
+
+	if (IS_ERR(av))
+		return(av);
+	ae = av + na + 1;
+	av[na] = (char *)0;
+	ae[ne] = (char *)0;
+	(void)nargs(argv, av);
+	(void)nargs(envp, ae);
+	r = sys_execve(filename, av, ae, regs);
+	if (IS_ERR(r))
+		sys_munmap(av, len);
+	return(r);
+}
+
+static inline int
+putstat(struct stat32 *ubuf, struct stat *kbuf)
+{
+	int err;
+	
+	err = put_user (kbuf->st_dev, &ubuf->st_dev);
+	err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
+	err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
+	err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
+	err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
+	err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
+	err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
+	err |= __put_user (kbuf->st_size, &ubuf->st_size);
+	err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
+	err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
+	err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
+	err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
+	err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+	return err;
+}
+
+extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
+
+asmlinkage int
+sys32_newstat(char * filename, struct stat32 *statbuf)
+{
+	int ret;
+	struct stat s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newstat(filename, &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
+
+asmlinkage int
+sys32_newlstat(char * filename, struct stat32 *statbuf)
+{
+	int ret;
+	struct stat s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newlstat(filename, &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+asmlinkage int
+sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
+{
+	int ret;
+	struct stat s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newfstat(fd, &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+#define ALIGN4K(a)	(((a) + 0xfff) & ~0xfff)
+#define OFFSET4K(a)	((a) & 0xfff)
+
+unsigned long
+do_mmap_fake(struct file *file, unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags, unsigned long off)
+{
+	struct inode *inode;
+	void *front, *back;
+	unsigned long baddr;
+	int r;
+	char c;
+
+	if (OFFSET4K(addr) || OFFSET4K(off))
+		return -EINVAL;
+	if (prot & PROT_WRITE)
+		prot |= PROT_EXEC;
+	front = NULL;
+	back = NULL;
+	if ((baddr = (addr & PAGE_MASK)) != addr && get_user(c, (char *)baddr) == 0) {
+		front = kmalloc(addr - baddr, GFP_KERNEL);
+		memcpy(front, (void *)baddr, addr - baddr);
+	}
+	if ((addr + len) & ~PAGE_MASK && get_user(c, (char *)(addr + len)) == 0) {
+		back = kmalloc(PAGE_SIZE - ((addr + len) & ~PAGE_MASK), GFP_KERNEL);
+		memcpy(back, addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
+	}
+	if ((r = do_mmap(0, baddr, len + (addr - baddr), prot, flags | MAP_ANONYMOUS, 0)) < 0)
+		return(r);
+	if (back) {
+		memcpy(addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
+		kfree(back);
+	}
+	if (front) {
+		memcpy((void *)baddr, front, addr - baddr);
+		kfree(front);
+	}
+	if (flags & MAP_ANONYMOUS) {
+		memset(addr, 0, len);
+		return(addr);
+	}
+	if (!file)
+		return -EINVAL;
+	inode = file->f_dentry->d_inode;
+	if (!inode->i_op || !inode->i_op->default_file_ops)
+		return -EINVAL;
+	if (!file->f_op->read)
+		return -EINVAL;
+	if (file->f_op->llseek) {
+		if (file->f_op->llseek(file,off,0) != off)
+			return -EINVAL;
+	} else
+		file->f_pos = off;
+	r = file->f_op->read(file, (char *)addr, len, &file->f_pos);
+	return (r < 0) ? -EINVAL : addr;
+}
+
+/*
+ * Linux/i386 didn't use to be able to handle more than
+ * 4 system call parameters, so these system calls used a memory
+ * block for parameter passing..
+ */
+
+struct mmap_arg_struct {
+	unsigned int addr;
+	unsigned int len;
+	unsigned int prot;
+	unsigned int flags;
+	unsigned int fd;
+	unsigned int offset;
+};
+
+asmlinkage int
+sys32_mmap(struct mmap_arg_struct *arg)
+{
+	int error = -EFAULT;
+	struct file * file = NULL;
+	struct mmap_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+
+	down(&current->mm->mmap_sem);
+	lock_kernel();
+	if (!(a.flags & MAP_ANONYMOUS)) {
+		error = -EBADF;
+		file = fget(a.fd);
+		if (!file)
+			goto out;
+	}
+	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+	if ((a.flags & MAP_FIXED) && ((a.addr & ~PAGE_MASK) || (a.offset & ~PAGE_MASK))) {
+		unlock_kernel();
+		up(&current->mm->mmap_sem);
+		error = do_mmap_fake(file, a.addr, a.len, a.prot, a.flags, a.offset);
+		down(&current->mm->mmap_sem);
+		lock_kernel();
+	} else
+		error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
+	if (file)
+		fput(file);
+out:
+	unlock_kernel();
+	up(&current->mm->mmap_sem);
+	return error;
+}
+
+asmlinkage long
+sys32_pipe(int *fd)
+{
+	int retval;
+	int fds[2];
+
+	lock_kernel();
+	retval = do_pipe(fds);
+	if (retval)
+		goto out;
+	if (copy_to_user(fd, fds, sizeof(fds)))
+		retval = -EFAULT;
+  out:
+	unlock_kernel();
+	return retval;
+}
+
+asmlinkage long
+sys32_mprotect(unsigned long start, size_t len, unsigned long prot)
+{
+
+	if (prot == 0)
+		return(0);
+	len += start & ~PAGE_MASK;
+	if ((start & ~PAGE_MASK) && (prot & PROT_WRITE))
+		prot |= PROT_EXEC;
+	return(sys_mprotect(start & PAGE_MASK, len & PAGE_MASK, prot));
+}
+
+asmlinkage int
+sys32_rt_sigaction(int sig, struct sigaction32 *act,
+		   struct sigaction32 *oact,  unsigned int sigsetsize)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+	sigset32_t set32;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset32_t))
+		return -EINVAL;
+
+	if (act) {
+		ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret |= __copy_from_user(&set32, &act->sa_mask,
+					sizeof(sigset32_t));
+		switch (_NSIG_WORDS) {
+		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
+				| (((long)set32.sig[7]) << 32);
+		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
+				| (((long)set32.sig[5]) << 32);
+		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
+				| (((long)set32.sig[3]) << 32);
+		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
+				| (((long)set32.sig[1]) << 32);
+		}
+		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		
+		if (ret)
+			return -EFAULT;
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		switch (_NSIG_WORDS) {
+		case 4:
+			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
+			set32.sig[6] = old_ka.sa.sa_mask.sig[3];
+		case 3:
+			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
+			set32.sig[4] = old_ka.sa.sa_mask.sig[2];
+		case 2:
+			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
+			set32.sig[2] = old_ka.sa.sa_mask.sig[1];
+		case 1:
+			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
+			set32.sig[0] = old_ka.sa.sa_mask.sig[0];
+		}
+		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
+		ret |= __copy_to_user(&oact->sa_mask, &set32,
+				      sizeof(sigset32_t));
+		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+	}
+
+	return ret;
+}
+
+
+extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
+					 size_t sigsetsize);
+
+asmlinkage int
+sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
+		     unsigned int sigsetsize)
+{
+	sigset_t s;
+	sigset32_t s32;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	if (set) {
+		if (copy_from_user (&s32, set, sizeof(sigset32_t)))
+			return -EFAULT;
+		switch (_NSIG_WORDS) {
+		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
+		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
+		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
+		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
+		}
+	}
+	set_fs (KERNEL_DS);
+	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,
+				 sigsetsize); 
+	set_fs (old_fs);
+	if (ret) return ret;
+	if (oset) {
+		switch (_NSIG_WORDS) {
+		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
+		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
+		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
+		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
+		}
+		if (copy_to_user (oset, &s32, sizeof(sigset32_t)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static inline int
+put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
+{
+	int err;
+	
+	err = put_user (kbuf->f_type, &ubuf->f_type);
+	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
+	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
+	err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
+	err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
+	err |= __put_user (kbuf->f_files, &ubuf->f_files);
+	err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
+	err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
+	err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
+	err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
+	return err;
+}
+
+extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
+
+asmlinkage int
+sys32_statfs(const char * path, struct statfs32 *buf)
+{
+	int ret;
+	struct statfs s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_statfs((const char *)path, &s);
+	set_fs (old_fs);
+	if (put_statfs(buf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
+
+asmlinkage int
+sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
+{
+	int ret;
+	struct statfs s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_fstatfs(fd, &s);
+	set_fs (old_fs);
+	if (put_statfs(buf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+struct timeval32
+{
+    int tv_sec, tv_usec;
+};
+
+struct itimerval32
+{
+    struct timeval32 it_interval;
+    struct timeval32 it_value;
+};
+
+static inline long
+get_tv32(struct timeval *o, struct timeval32 *i)
+{
+	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
+		(__get_user(o->tv_sec, &i->tv_sec) |
+		 __get_user(o->tv_usec, &i->tv_usec)));
+	return ENOSYS;
+}
+
+static inline long
+put_tv32(struct timeval32 *o, struct timeval *i)
+{
+	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
+		(__put_user(i->tv_sec, &o->tv_sec) |
+		 __put_user(i->tv_usec, &o->tv_usec)));
+}
+
+static inline long
+get_it32(struct itimerval *o, struct itimerval32 *i)
+{
+	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
+		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
+		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
+		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
+		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
+	return ENOSYS;
+}
+
+static inline long
+put_it32(struct itimerval32 *o, struct itimerval *i)
+{
+	return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) ||
+		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
+		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
+		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
+		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
+	return ENOSYS;
+}
+
+extern int do_getitimer(int which, struct itimerval *value);
+
+asmlinkage int
+sys32_getitimer(int which, struct itimerval32 *it)
+{
+	struct itimerval kit;
+	int error;
+
+	error = do_getitimer(which, &kit);
+	if (!error && put_it32(it, &kit))
+		error = -EFAULT;
+
+	return error;
+}
+
+extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+
+asmlinkage int
+sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
+{
+	struct itimerval kin, kout;
+	int error;
+
+	if (in) {
+		if (get_it32(&kin, in))
+			return -EFAULT;
+	} else
+		memset(&kin, 0, sizeof(kin));
+
+	error = do_setitimer(which, &kin, out ? &kout : NULL);
+	if (error || !out)
+		return error;
+	if (put_it32(out, &kout))
+		return -EFAULT;
+
+	return 0;
+
+}
+asmlinkage unsigned long 
+sys32_alarm(unsigned int seconds)
+{
+	struct itimerval it_new, it_old;
+	unsigned int oldalarm;
+
+	it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
+	it_new.it_value.tv_sec = seconds;
+	it_new.it_value.tv_usec = 0;
+	do_setitimer(ITIMER_REAL, &it_new, &it_old);
+	oldalarm = it_old.it_value.tv_sec;
+	/* ehhh.. We can't return 0 if we have an alarm pending.. */
+	/* And we'd better return too much than too little anyway */
+	if (it_old.it_value.tv_usec)
+		oldalarm++;
+	return oldalarm;
+}
+
+/* Translations due to time_t size differences.  Which affects all
+   sorts of things, like timeval and itimerval.  */
+
+extern struct timezone sys_tz;
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+
+asmlinkage int
+sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	if (tv) {
+		struct timeval ktv;
+		do_gettimeofday(&ktv);
+		if (put_tv32(tv, &ktv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+asmlinkage int
+sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	struct timeval ktv;
+	struct timezone ktz;
+
+ 	if (tv) {
+		if (get_tv32(&ktv, tv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_from_user(&ktz, tz, sizeof(ktz)))
+			return -EFAULT;
+	}
+
+	return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
+}
+
+struct dirent32 {
+	unsigned int	d_ino;
+	unsigned int	d_off;
+	unsigned short	d_reclen;
+	char		d_name[NAME_MAX + 1];
+};
+
+static void
+xlate_dirent(void *dirent, long n)
+{
+	long off;
+	struct dirent *dirp;
+	struct dirent32 *dirp32;
+
+	off = 0;
+	while (off < n) {
+		dirp = (struct dirent *)(dirent + off);
+		off += dirp->d_reclen;
+		dirp32 = (struct dirent32 *)dirp;
+		dirp32->d_ino = dirp->d_ino;
+		dirp32->d_off = (unsigned int)dirp->d_off;
+		dirp32->d_reclen = dirp->d_reclen;
+		strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2));
+	}
+	return;
+}
+
+asmlinkage long
+sys32_getdents(unsigned int fd, void * dirent, unsigned int count)
+{
+	long n;
+
+	if ((n = sys_getdents(fd, dirent, count)) < 0)
+		return(n);
+	xlate_dirent(dirent, n);
+	return(n);
+}
+
+asmlinkage int
+sys32_readdir(unsigned int fd, void * dirent, unsigned int count)
+{
+	int n;
+	struct dirent *dirp;
+
+	if ((n = old_readdir(fd, dirent, count)) < 0)
+		return(n);
+	dirp = (struct dirent *)dirent;
+	xlate_dirent(dirent, dirp->d_reclen);
+	return(n);
+}
+
+/*
+ * We can actually return ERESTARTSYS instead of EINTR, but I'd
+ * like to be certain this leads to no problems. So I return
+ * EINTR just for safety.
+ *
+ * Update: ERESTARTSYS breaks at least the xview clock binary, so
+ * I'm trying ERESTARTNOHAND which restart only when you want to.
+ */
+#define MAX_SELECT_SECONDS \
+	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
+
+asmlinkage int
+sys32_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32)
+{
+	fd_set_bits fds;
+	char *bits;
+	long timeout;
+	int ret, size;
+
+	timeout = MAX_SCHEDULE_TIMEOUT;
+	if (tvp32) {
+		time_t sec, usec;
+
+		get_user(sec, &tvp32->tv_sec);
+		get_user(usec, &tvp32->tv_usec);
+
+		ret = -EINVAL;
+		if (sec < 0 || usec < 0)
+			goto out_nofds;
+
+		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
+			timeout = ROUND_UP(usec, 1000000/HZ);
+			timeout += sec * (unsigned long) HZ;
+		}
+	}
+
+	ret = -EINVAL;
+	if (n < 0)
+		goto out_nofds;
+
+	if (n > current->files->max_fdset)
+		n = current->files->max_fdset;
+
+	/*
+	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
+	 * since we used fdset we need to allocate memory in units of
+	 * long-words. 
+	 */
+	ret = -ENOMEM;
+	size = FDS_BYTES(n);
+	bits = kmalloc(6 * size, GFP_KERNEL);
+	if (!bits)
+		goto out_nofds;
+	fds.in      = (unsigned long *)  bits;
+	fds.out     = (unsigned long *) (bits +   size);
+	fds.ex      = (unsigned long *) (bits + 2*size);
+	fds.res_in  = (unsigned long *) (bits + 3*size);
+	fds.res_out = (unsigned long *) (bits + 4*size);
+	fds.res_ex  = (unsigned long *) (bits + 5*size);
+
+	if ((ret = get_fd_set(n, inp, fds.in)) ||
+	    (ret = get_fd_set(n, outp, fds.out)) ||
+	    (ret = get_fd_set(n, exp, fds.ex)))
+		goto out;
+	zero_fd_set(n, fds.res_in);
+	zero_fd_set(n, fds.res_out);
+	zero_fd_set(n, fds.res_ex);
+
+	ret = do_select(n, &fds, &timeout);
+
+	if (tvp32 && !(current->personality & STICKY_TIMEOUTS)) {
+		time_t sec = 0, usec = 0;
+		if (timeout) {
+			sec = timeout / HZ;
+			usec = timeout % HZ;
+			usec *= (1000000/HZ);
+		}
+		put_user(sec, (int *)&tvp32->tv_sec);
+		put_user(usec, (int *)&tvp32->tv_usec);
+	}
+
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		ret = -ERESTARTNOHAND;
+		if (signal_pending(current))
+			goto out;
+		ret = 0;
+	}
+
+	set_fd_set(n, inp, fds.res_in);
+	set_fd_set(n, outp, fds.res_out);
+	set_fd_set(n, exp, fds.res_ex);
+
+out:
+	kfree(bits);
+out_nofds:
+	return ret;
+}
+
+struct rusage32 {
+        struct timeval32 ru_utime;
+        struct timeval32 ru_stime;
+        int    ru_maxrss;
+        int    ru_ixrss;
+        int    ru_idrss;
+        int    ru_isrss;
+        int    ru_minflt;
+        int    ru_majflt;
+        int    ru_nswap;
+        int    ru_inblock;
+        int    ru_oublock;
+        int    ru_msgsnd; 
+        int    ru_msgrcv; 
+        int    ru_nsignals;
+        int    ru_nvcsw;
+        int    ru_nivcsw;
+};
+
+static int
+put_rusage (struct rusage32 *ru, struct rusage *r)
+{
+	int err;
+	
+	err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
+	err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
+	err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
+	err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
+	err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
+	err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
+	err |= __put_user (r->ru_idrss, &ru->ru_idrss);
+	err |= __put_user (r->ru_isrss, &ru->ru_isrss);
+	err |= __put_user (r->ru_minflt, &ru->ru_minflt);
+	err |= __put_user (r->ru_majflt, &ru->ru_majflt);
+	err |= __put_user (r->ru_nswap, &ru->ru_nswap);
+	err |= __put_user (r->ru_inblock, &ru->ru_inblock);
+	err |= __put_user (r->ru_oublock, &ru->ru_oublock);
+	err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
+	err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
+	err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
+	err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
+	err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
+	return err;
+}
+
+extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr,
+				int options, struct rusage * ru);
+
+asmlinkage int
+sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options,
+	    struct rusage32 *ru)
+{
+	if (!ru)
+		return sys_wait4(pid, stat_addr, options, NULL);
+	else {
+		struct rusage r;
+		int ret;
+		unsigned int status;
+		mm_segment_t old_fs = get_fs();
+		
+		set_fs (KERNEL_DS);
+		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
+		set_fs (old_fs);
+		if (put_rusage (ru, &r)) return -EFAULT;
+		if (stat_addr && put_user (status, stat_addr))
+			return -EFAULT;
+		return ret;
+	}
+}
+
+asmlinkage int
+sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options)
+{
+	return sys32_wait4(pid, stat_addr, options, NULL);
+}
+
+struct timespec32 {
+	int 	tv_sec;
+	int	tv_nsec;
+};
+
+extern asmlinkage int sys_nanosleep(struct timespec *rqtp,
+				    struct timespec *rmtp); 
+
+asmlinkage int
+sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	if (get_user (t.tv_sec, &rqtp->tv_sec) ||
+	    __get_user (t.tv_nsec, &rqtp->tv_nsec))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_nanosleep(&t, rmtp ? &t : NULL);
+	set_fs (old_fs);
+	if (rmtp && ret == -EINTR) {
+		if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
+	    	    __put_user (t.tv_nsec, &rmtp->tv_nsec))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+struct iovec32 { unsigned int iov_base; int iov_len; };
+
+typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
+
+static long
+do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
+		  u32 count)
+{
+	unsigned long tot_len;
+	struct iovec iovstack[UIO_FASTIOV];
+	struct iovec *iov=iovstack, *ivp;
+	struct inode *inode;
+	long retval, i;
+	IO_fn_t fn;
+
+	/* First get the "struct iovec" from user memory and
+	 * verify all the pointers
+	 */
+	if (!count)
+		return 0;
+	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+		return -EFAULT;
+	if (count > UIO_MAXIOV)
+		return -EINVAL;
+	if (count > UIO_FASTIOV) {
+		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
+		if (!iov)
+			return -ENOMEM;
+	}
+
+	tot_len = 0;
+	i = count;
+	ivp = iov;
+	while(i > 0) {
+		u32 len;
+		u32 buf;
+
+		__get_user(len, &vector->iov_len);
+		__get_user(buf, &vector->iov_base);
+		tot_len += len;
+		ivp->iov_base = (void *)A(buf);
+		ivp->iov_len = (__kernel_size_t) len;
+		vector++;
+		ivp++;
+		i--;
+	}
+
+	inode = file->f_dentry->d_inode;
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	retval = locks_verify_area((type == VERIFY_WRITE
+				    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
+				   inode, file, file->f_pos, tot_len);
+	if (retval) {
+		if (iov != iovstack)
+			kfree(iov);
+		return retval;
+	}
+
+	/* Then do the actual IO.  Note that sockets need to be handled
+	 * specially as they have atomicity guarantees and can handle
+	 * iovec's natively
+	 */
+	if (inode->i_sock) {
+		int err;
+		err = sock_readv_writev(type, inode, file, iov, count, tot_len);
+		if (iov != iovstack)
+			kfree(iov);
+		return err;
+	}
+
+	if (!file->f_op) {
+		if (iov != iovstack)
+			kfree(iov);
+		return -EINVAL;
+	}
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	fn = file->f_op->read;
+	if (type == VERIFY_READ)
+		fn = (IO_fn_t) file->f_op->write;		
+	ivp = iov;
+	while (count > 0) {
+		void * base;
+		int len, nr;
+
+		base = ivp->iov_base;
+		len = ivp->iov_len;
+		ivp++;
+		count--;
+		nr = fn(file, base, len, &file->f_pos);
+		if (nr < 0) {
+			if (retval)
+				break;
+			retval = nr;
+			break;
+		}
+		retval += nr;
+		if (nr != len)
+			break;
+	}
+	if (iov != iovstack)
+		kfree(iov);
+	return retval;
+}
+
+asmlinkage long
+sys32_readv(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	long ret = -EBADF;
+
+	lock_kernel();
+	file = fget(fd);
+	if(!file)
+		goto bad_file;
+
+	if(!(file->f_mode & 1))
+		goto out;
+
+	ret = do_readv_writev32(VERIFY_WRITE, file,
+				vector, count);
+out:
+	fput(file);
+bad_file:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage long
+sys32_writev(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	int ret = -EBADF;
+
+	lock_kernel();
+	file = fget(fd);
+	if(!file)
+		goto bad_file;
+
+	if(!(file->f_mode & 2))
+		goto out;
+
+	down(&file->f_dentry->d_inode->i_sem);
+	ret = do_readv_writev32(VERIFY_READ, file,
+				vector, count);
+	up(&file->f_dentry->d_inode->i_sem);
+out:
+	fput(file);
+bad_file:
+	unlock_kernel();
+	return ret;
+}
+
+#define RLIM_INFINITY32	0x7fffffff
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+
+struct rlimit32 {
+	int	rlim_cur;
+	int	rlim_max;
+};
+
+extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
+
+asmlinkage int
+sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit r;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_getrlimit(resource, &r);
+	set_fs (old_fs);
+	if (!ret) {
+		ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
+		ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
+	}
+	return ret;
+}
+
+extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
+
+asmlinkage int
+sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit r;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+
+	if (resource >= RLIM_NLIMITS) return -EINVAL;	
+	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+	    __get_user (r.rlim_max, &rlim->rlim_max))
+		return -EFAULT;
+	if (r.rlim_cur == RLIM_INFINITY32)
+		r.rlim_cur = RLIM_INFINITY;
+	if (r.rlim_max == RLIM_INFINITY32)
+		r.rlim_max = RLIM_INFINITY;
+	set_fs (KERNEL_DS);
+	ret = sys_setrlimit(resource, &r);
+	set_fs (old_fs);
+	return ret;
+}
+
+/* Argument list sizes for sys_socketcall */
+#define AL(x) ((x) * sizeof(u32))
+static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+#undef AL
+
+extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
+extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr,
+				  int addrlen);
+extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr,
+				 int *upeer_addrlen); 
+extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr,
+				      int *usockaddr_len);
+extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr,
+				      int *usockaddr_len);
+extern asmlinkage int sys_send(int fd, void *buff, size_t len, unsigned flags);
+extern asmlinkage int sys_sendto(int fd, u32 buff, __kernel_size_t32 len,
+				   unsigned flags, u32 addr, int addr_len);
+extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
+extern asmlinkage int sys_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
+				     unsigned flags, u32 addr, u32 addr_len);
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+				     char *optval, int optlen);
+extern asmlinkage int sys_getsockopt(int fd, int level, int optname,
+				       u32 optval, u32 optlen);
+
+extern asmlinkage int sys_socket(int family, int type, int protocol);
+extern asmlinkage int sys_socketpair(int family, int type, int protocol,
+				     int usockvec[2]);
+extern asmlinkage int sys_shutdown(int fd, int how);
+extern asmlinkage int sys_listen(int fd, int backlog);
+
+asmlinkage int sys32_socketcall(int call, u32 *args)
+{
+	int i, ret;
+	u32 a[6];
+	u32 a0,a1;
+				 
+	if (call<SYS_SOCKET||call>SYS_RECVMSG)
+		return -EINVAL;
+	if (copy_from_user(a, args, nas[call]))
+		return -EFAULT;
+	a0=a[0];
+	a1=a[1];
+	
+	switch(call) 
+	{
+		case SYS_SOCKET:
+			ret = sys_socket(a0, a1, a[2]);
+			break;
+		case SYS_BIND:
+			ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
+			break;
+		case SYS_CONNECT:
+			ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
+			break;
+		case SYS_LISTEN:
+			ret = sys_listen(a0, a1);
+			break;
+		case SYS_ACCEPT:
+			ret = sys_accept(a0, (struct sockaddr *)A(a1),
+					  (int *)A(a[2]));
+			break;
+		case SYS_GETSOCKNAME:
+			ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
+					       (int *)A(a[2]));
+			break;
+		case SYS_GETPEERNAME:
+			ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
+					       (int *)A(a[2]));
+			break;
+		case SYS_SOCKETPAIR:
+			ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+			break;
+		case SYS_SEND:
+			ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
+			break;
+		case SYS_SENDTO:
+			ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
+			break;
+		case SYS_RECV:
+			ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
+			break;
+		case SYS_RECVFROM:
+			ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
+			break;
+		case SYS_SHUTDOWN:
+			ret = sys_shutdown(a0,a1);
+			break;
+		case SYS_SETSOCKOPT:
+			ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
+					      a[4]);
+			break;
+		case SYS_GETSOCKOPT:
+			ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
+			break;
+		case SYS_SENDMSG:
+			ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1),
+					     a[2]);
+			break;
+		case SYS_RECVMSG:
+			ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1),
+					     a[2]);
+			break;
+		default:
+			ret = EINVAL;
+			break;
+	}
+	return ret;
+}
+
+/*
+ *  Declare the IA32 version of the msghdr
+ */
+ 
+struct msghdr32 {
+	unsigned int    msg_name;	/* Socket name			*/
+	int		msg_namelen;	/* Length of name		*/
+	unsigned int    msg_iov;	/* Data blocks			*/
+	unsigned int	msg_iovlen;	/* Number of blocks		*/
+	unsigned int    msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
+	unsigned int	msg_controllen;	/* Length of cmsg list */
+	unsigned	msg_flags;
+};
+
+static inline int
+shape_msg(struct msghdr *mp, struct msghdr32 *mp32)
+{
+	unsigned int i;
+
+	if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
+		return(-EFAULT);
+	__get_user(i, &mp32->msg_name);
+	mp->msg_name = (void *)i;
+	__get_user(mp->msg_namelen, &mp32->msg_namelen);
+	__get_user(i, &mp32->msg_iov);
+	mp->msg_iov = (struct iov *)i;
+	__get_user(mp->msg_iovlen, &mp32->msg_iovlen);
+	__get_user(i, &mp32->msg_control);
+	mp->msg_control = (void *)i;
+	__get_user(mp->msg_controllen, &mp32->msg_controllen);
+	__get_user(mp->msg_flags, &mp32->msg_flags);
+	return(0);
+}
+
+/*
+ *	Verify & re-shape IA32 iovec. The caller must ensure that the
+ *      iovec is big enough to hold the re-shaped message iovec.
+ *
+ *	Save time not doing verify_area. copy_*_user will make this work
+ *	in any case.
+ *
+ *	Don't need to check the total size for overflow (cf net/core/iovec.c),
+ *	32-bit sizes can't overflow a 64-bit count.
+ */
+
+static inline int
+verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode)
+{
+	int size, err, ct;
+	struct iovec32 *iov32;
+	
+	if(m->msg_namelen)
+	{
+		if(mode==VERIFY_READ)
+		{
+			err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
+			if(err<0)
+				goto out;
+		}
+		
+		m->msg_name = address;
+	} else
+		m->msg_name = NULL;
+
+	err = -EFAULT;
+	size = m->msg_iovlen * sizeof(struct iovec32);
+	if (copy_from_user(iov, m->msg_iov, size))
+		goto out;
+	m->msg_iov=iov;
+
+	err = 0;
+	iov32 = (struct iovec32 *)iov;
+	for (ct = m->msg_iovlen; ct-- > 0; ) {
+		iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
+		iov[ct].iov_base = (void *)iov32[ct].iov_base;
+		err += iov[ct].iov_len;
+	}
+out:
+	return err;
+}
+
+extern __inline__ void
+sockfd_put(struct socket *sock)
+{
+	fput(sock->file);
+}
+
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
+					   16 for IP, 16 for IPX,
+					   24 for IPv6,
+					   about 80 for AX.25 */
+
+extern struct socket *sockfd_lookup(int fd, int *err);
+
+/*
+ *	BSD sendmsg interface
+ */
+
+asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
+{
+	struct socket *sock;
+	char address[MAX_SOCK_ADDR];
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */
+	unsigned char *ctl_buf = ctl;
+	struct msghdr msg_sys;
+	int err, ctl_len, iov_size, total_len;
+	
+	err = -EFAULT;
+	if (shape_msg(&msg_sys, msg))
+		goto out; 
+
+	sock = sockfd_lookup(fd, &err);
+	if (!sock) 
+		goto out;
+
+	/* do not move before msg_sys is valid */
+	err = -EINVAL;
+	if (msg_sys.msg_iovlen > UIO_MAXIOV)
+		goto out_put;
+
+	/* Check whether to allocate the iovec area*/
+	err = -ENOMEM;
+	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
+	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+		if (!iov)
+			goto out_put;
+	}
+
+	/* This will also move the address data into kernel space */
+	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
+	if (err < 0) 
+		goto out_freeiov;
+	total_len = err;
+
+	err = -ENOBUFS;
+
+	if (msg_sys.msg_controllen > INT_MAX)
+		goto out_freeiov;
+	ctl_len = msg_sys.msg_controllen; 
+	if (ctl_len) 
+	{
+		if (ctl_len > sizeof(ctl))
+		{
+			err = -ENOBUFS;
+			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
+			if (ctl_buf == NULL) 
+				goto out_freeiov;
+		}
+		err = -EFAULT;
+		if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len))
+			goto out_freectl;
+		msg_sys.msg_control = ctl_buf;
+	}
+	msg_sys.msg_flags = flags;
+
+	if (sock->file->f_flags & O_NONBLOCK)
+		msg_sys.msg_flags |= MSG_DONTWAIT;
+	err = sock_sendmsg(sock, &msg_sys, total_len);
+
+out_freectl:
+	if (ctl_buf != ctl)    
+		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
+out_freeiov:
+	if (iov != iovstack)
+		sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+	sockfd_put(sock);
+out:       
+	return err;
+}
+
+/*
+ *	BSD recvmsg interface
+ */
+
+asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *msg, unsigned int flags)
+{
+	struct socket *sock;
+	struct iovec iovstack[UIO_FASTIOV];
+	struct iovec *iov=iovstack;
+	struct msghdr msg_sys;
+	unsigned long cmsg_ptr;
+	int err, iov_size, total_len, len;
+
+	/* kernel mode address */
+	char addr[MAX_SOCK_ADDR];
+
+	/* user mode address pointers */
+	struct sockaddr *uaddr;
+	int *uaddr_len;
+	
+	err=-EFAULT;
+	if (shape_msg(&msg_sys, msg))
+		goto out;
+
+	sock = sockfd_lookup(fd, &err);
+	if (!sock)
+		goto out;
+
+	err = -EINVAL;
+	if (msg_sys.msg_iovlen > UIO_MAXIOV)
+		goto out_put;
+	
+	/* Check whether to allocate the iovec area*/
+	err = -ENOMEM;
+	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
+	if (msg_sys.msg_iovlen > UIO_FASTIOV) {
+		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
+		if (!iov)
+			goto out_put;
+	}
+
+	/*
+	 *	Save the user-mode address (verify_iovec will change the
+	 *	kernel msghdr to use the kernel address space)
+	 */
+	 
+	uaddr = msg_sys.msg_name;
+	uaddr_len = &msg->msg_namelen;
+	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
+	if (err < 0)
+		goto out_freeiov;
+	total_len=err;
+
+	cmsg_ptr = (unsigned long)msg_sys.msg_control;
+	msg_sys.msg_flags = 0;
+	
+	if (sock->file->f_flags & O_NONBLOCK)
+		flags |= MSG_DONTWAIT;
+	err = sock_recvmsg(sock, &msg_sys, total_len, flags);
+	if (err < 0)
+		goto out_freeiov;
+	len = err;
+
+	if (uaddr != NULL) {
+		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
+		if (err < 0)
+			goto out_freeiov;
+	}
+	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
+	if (err)
+		goto out_freeiov;
+	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, 
+							 &msg->msg_controllen);
+	if (err)
+		goto out_freeiov;
+	err = len;
+
+out_freeiov:
+	if (iov != iovstack)
+		sock_kfree_s(sock->sk, iov, iov_size);
+out_put:
+	sockfd_put(sock);
+out:
+	return err;
+}
+
+/*
+ * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
+ *
+ * This is really horribly ugly.
+ */
+
+struct msgbuf32 { s32 mtype; char mtext[1]; };
+
+struct ipc_perm32
+{
+	key_t    	  key;
+        __kernel_uid_t32  uid;
+        __kernel_gid_t32  gid;
+        __kernel_uid_t32  cuid;
+        __kernel_gid_t32  cgid;
+        __kernel_mode_t32 mode;
+        unsigned short  seq;
+};
+
+struct semid_ds32 {
+        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
+        __kernel_time_t32 sem_otime;              /* last semop time */
+        __kernel_time_t32 sem_ctime;              /* last change time */
+        u32 sem_base;              /* ptr to first semaphore in array */
+        u32 sem_pending;          /* pending operations to be processed */
+        u32 sem_pending_last;    /* last pending operation */
+        u32 undo;                  /* undo requests on this array */
+        unsigned short  sem_nsems;              /* no. of semaphores in array */
+};
+
+struct msqid_ds32
+{
+        struct ipc_perm32 msg_perm;
+        u32 msg_first;
+        u32 msg_last;
+        __kernel_time_t32 msg_stime;
+        __kernel_time_t32 msg_rtime;
+        __kernel_time_t32 msg_ctime;
+        u32 wwait;
+        u32 rwait;
+        unsigned short msg_cbytes;
+        unsigned short msg_qnum;  
+        unsigned short msg_qbytes;
+        __kernel_ipc_pid_t32 msg_lspid;
+        __kernel_ipc_pid_t32 msg_lrpid;
+};
+
+struct shmid_ds32 {
+        struct ipc_perm32       shm_perm;
+        int                     shm_segsz;
+        __kernel_time_t32       shm_atime;
+        __kernel_time_t32       shm_dtime;
+        __kernel_time_t32       shm_ctime;
+        __kernel_ipc_pid_t32    shm_cpid; 
+        __kernel_ipc_pid_t32    shm_lpid; 
+        unsigned short          shm_nattch;
+};
+
+#define IPCOP_MASK(__x)	(1UL << (__x))
+
+static int
+do_sys32_semctl(int first, int second, int third, void *uptr)
+{
+	union semun fourth;
+	u32 pad;
+	int err = -EINVAL;
+
+	if (!uptr)
+		goto out;
+	err = -EFAULT;
+	if (get_user (pad, (u32 *)uptr))
+		goto out;
+	if(third == SETVAL)
+		fourth.val = (int)pad;
+	else
+		fourth.__pad = (void *)A(pad);
+	if (IPCOP_MASK (third) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) |
+	     IPCOP_MASK (GETVAL) | IPCOP_MASK (GETPID) |
+	     IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
+	     IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) |
+	     IPCOP_MASK (IPC_RMID))) {
+		err = sys_semctl (first, second, third, fourth);
+	} else {
+		struct semid_ds s;
+		struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
+		mm_segment_t old_fs;
+		int need_back_translation;
+
+		if (third == IPC_SET) {
+			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
+			err |= __get_user(s.sem_perm.gid, &usp->sem_perm.gid);
+			err |= __get_user(s.sem_perm.mode, &usp->sem_perm.mode);
+			if (err)
+				goto out;
+			fourth.__pad = &s;
+		}
+		need_back_translation =
+			(IPCOP_MASK (third) &
+			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
+		if (need_back_translation)
+			fourth.__pad = &s;
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_semctl (first, second, third, fourth);
+		set_fs (old_fs);
+		if (need_back_translation) {
+			int err2 = put_user(s.sem_perm.key, &usp->sem_perm.key);
+			err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid);
+			err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid);
+			err2 |= __put_user(s.sem_perm.cuid,
+					   &usp->sem_perm.cuid);
+			err2 |= __put_user (s.sem_perm.cgid,
+					    &usp->sem_perm.cgid);
+			err2 |= __put_user (s.sem_perm.mode,
+					    &usp->sem_perm.mode);
+			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
+			err2 |= __put_user (s.sem_otime, &usp->sem_otime);
+			err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
+			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
+			if (err2) err = -EFAULT;
+		}
+	}
+out:
+	return err;
+}
+
+static int
+do_sys32_msgsnd (int first, int second, int third, void *uptr)
+{
+	struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf)
+				    + 4, GFP_USER);
+	struct msgbuf32 *up = (struct msgbuf32 *)uptr;
+	mm_segment_t old_fs;
+	int err;
+
+	if (!p)
+		return -ENOMEM;
+	err = get_user (p->mtype, &up->mtype);
+	err |= __copy_from_user (p->mtext, &up->mtext, second);
+	if (err)
+		goto out;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_msgsnd (first, p, second, third);
+	set_fs (old_fs);
+out:
+	kfree (p);
+	return err;
+}
+
+static int
+do_sys32_msgrcv (int first, int second, int msgtyp, int third,
+		 int version, void *uptr)
+{
+	struct msgbuf32 *up;
+	struct msgbuf *p;
+	mm_segment_t old_fs;
+	int err;
+
+	if (!version) {
+		struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
+		struct ipc_kludge ipck;
+
+		err = -EINVAL;
+		if (!uptr)
+			goto out;
+		err = -EFAULT;
+		if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
+			goto out;
+		uptr = (void *)A(ipck.msgp);
+		msgtyp = ipck.msgtyp;
+	}
+	err = -ENOMEM;
+	p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+	if (!p)
+		goto out;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_msgrcv (first, p, second + 4, msgtyp, third);
+	set_fs (old_fs);
+	if (err < 0)
+		goto free_then_out;
+	up = (struct msgbuf32 *)uptr;
+	if (put_user (p->mtype, &up->mtype) ||
+	    __copy_to_user (&up->mtext, p->mtext, err))
+		err = -EFAULT;
+free_then_out:
+	kfree (p);
+out:
+	return err;
+}
+
+static int
+do_sys32_msgctl (int first, int second, void *uptr)
+{
+	int err;
+
+	if (IPCOP_MASK (second) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
+	     IPCOP_MASK (IPC_RMID))) {
+		err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
+	} else {
+		struct msqid_ds m;
+		struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == IPC_SET) {
+			err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
+			err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
+			err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_msgctl (first, second, &m);
+		set_fs (old_fs);
+		if (IPCOP_MASK (second) &
+		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
+			err2 |= __put_user(m.msg_perm.uid, &up->msg_perm.uid);
+			err2 |= __put_user(m.msg_perm.gid, &up->msg_perm.gid);
+			err2 |= __put_user(m.msg_perm.cuid, &up->msg_perm.cuid);
+			err2 |= __put_user(m.msg_perm.cgid, &up->msg_perm.cgid);
+			err2 |= __put_user(m.msg_perm.mode, &up->msg_perm.mode);
+			err2 |= __put_user(m.msg_perm.seq, &up->msg_perm.seq);
+			err2 |= __put_user(m.msg_stime, &up->msg_stime);
+			err2 |= __put_user(m.msg_rtime, &up->msg_rtime);
+			err2 |= __put_user(m.msg_ctime, &up->msg_ctime);
+			err2 |= __put_user(m.msg_cbytes, &up->msg_cbytes);
+			err2 |= __put_user(m.msg_qnum, &up->msg_qnum);
+			err2 |= __put_user(m.msg_qbytes, &up->msg_qbytes);
+			err2 |= __put_user(m.msg_lspid, &up->msg_lspid);
+			err2 |= __put_user(m.msg_lrpid, &up->msg_lrpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	}
+
+out:
+	return err;
+}
+
+static int
+do_sys32_shmat (int first, int second, int third, int version, void *uptr)
+{
+	unsigned long raddr;
+	u32 *uaddr = (u32 *)A((u32)third);
+	int err = -EINVAL;
+
+	if (version == 1)
+		goto out;
+	err = sys_shmat (first, uptr, second, &raddr);
+	if (err)
+		goto out;
+	err = put_user (raddr, uaddr);
+out:
+	return err;
+}
+
+static int
+do_sys32_shmctl (int first, int second, void *uptr)
+{
+	int err;
+
+	if (IPCOP_MASK (second) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK)
+	     | IPCOP_MASK (SHM_UNLOCK) | IPCOP_MASK (IPC_RMID))) {
+		err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
+	} else {
+		struct shmid_ds s;
+		struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == IPC_SET) {
+			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
+			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
+			err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_shmctl (first, second, &s);
+		set_fs (old_fs);
+		if (err < 0)
+			goto out;
+
+		/* Mask it even in this case so it becomes a CSE. */
+		if (second == SHM_INFO) {
+			struct shm_info32 {
+				int used_ids;
+				u32 shm_tot, shm_rss, shm_swp;
+				u32 swap_attempts, swap_successes;
+			} *uip = (struct shm_info32 *)uptr;
+			struct shm_info *kp = (struct shm_info *)&s;
+			int err2 = put_user (kp->used_ids, &uip->used_ids);
+			err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
+			err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
+			err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
+			err2 |= __put_user (kp->swap_attempts,
+					    &uip->swap_attempts);
+			err2 |= __put_user (kp->swap_successes,
+					    &uip->swap_successes);
+			if (err2)
+				err = -EFAULT;
+		} else if (IPCOP_MASK (second) &
+			   (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
+			err2 |= __put_user (s.shm_perm.uid, &up->shm_perm.uid);
+			err2 |= __put_user (s.shm_perm.gid, &up->shm_perm.gid);
+			err2 |= __put_user (s.shm_perm.cuid,
+					    &up->shm_perm.cuid);
+			err2 |= __put_user (s.shm_perm.cgid,
+					    &up->shm_perm.cgid);
+			err2 |= __put_user (s.shm_perm.mode,
+					    &up->shm_perm.mode);
+			err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
+			err2 |= __put_user (s.shm_atime, &up->shm_atime);
+			err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
+			err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
+			err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
+			err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
+			err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
+			err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	}
+out:
+	return err;
+}
+
+asmlinkage int
+sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+{
+	int version, err;
+
+	lock_kernel();
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	if (call <= SEMCTL)
+		switch (call) {
+		case SEMOP:
+			/* struct sembuf is the same on 32 and 64bit :)) */
+			err = sys_semop (first, (struct sembuf *)AA(ptr),
+					 second);
+			goto out;
+		case SEMGET:
+			err = sys_semget (first, second, third);
+			goto out;
+		case SEMCTL:
+			err = do_sys32_semctl (first, second, third,
+					       (void *)AA(ptr));
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		};
+	if (call <= MSGCTL) 
+		switch (call) {
+		case MSGSND:
+			err = do_sys32_msgsnd (first, second, third,
+					       (void *)AA(ptr));
+			goto out;
+		case MSGRCV:
+			err = do_sys32_msgrcv (first, second, fifth, third,
+					       version, (void *)AA(ptr));
+			goto out;
+		case MSGGET:
+			err = sys_msgget ((key_t) first, second);
+			goto out;
+		case MSGCTL:
+			err = do_sys32_msgctl (first, second, (void *)AA(ptr));
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		}
+	if (call <= SHMCTL) 
+		switch (call) {
+		case SHMAT:
+			err = do_sys32_shmat (first, second, third,
+					      version, (void *)AA(ptr));
+			goto out;
+		case SHMDT: 
+			err = sys_shmdt ((char *)AA(ptr));
+			goto out;
+		case SHMGET:
+			err = sys_shmget (first, second, third);
+			goto out;
+		case SHMCTL:
+			err = do_sys32_shmctl (first, second, (void *)AA(ptr));
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		}
+
+	err = -EINVAL;
+
+out:
+	unlock_kernel();
+	return err;
+}
+
+#ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
+
+/* In order to reduce some races, while at the same time doing additional
+ * checking and hopefully speeding things up, we copy filenames to the
+ * kernel data space before using them..
+ *
+ * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
+ */
+static inline int
+do_getname32(const char *filename, char *page)
+{
+	int retval;
+
+	/* 32bit pointer will be always far below TASK_SIZE :)) */
+	retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);
+	if (retval > 0) {
+		if (retval < PAGE_SIZE)
+			return 0;
+		return -ENAMETOOLONG;
+	} else if (!retval)
+		retval = -ENOENT;
+	return retval;
+}
+
+char *
+getname32(const char *filename)
+{
+	char *tmp, *result;
+
+	result = ERR_PTR(-ENOMEM);
+	tmp = (char *)__get_free_page(GFP_KERNEL);
+	if (tmp)  {
+		int retval = do_getname32(filename, tmp);
+
+		result = tmp;
+		if (retval < 0) {
+			putname(tmp);
+			result = ERR_PTR(retval);
+		}
+	}
+	return result;
+}
+
+/* 32-bit timeval and related flotsam.  */
+
+extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
+
+asmlinkage int
+sys32_ioperm(u32 from, u32 num, int on)
+{
+	return sys_ioperm((unsigned long)from, (unsigned long)num, on);
+}
+
+static inline int
+get_flock(struct flock *kfl, struct flock32 *ufl)
+{
+	int err;
+	
+	err = get_user(kfl->l_type, &ufl->l_type);
+	err |= __get_user(kfl->l_whence, &ufl->l_whence);
+	err |= __get_user(kfl->l_start, &ufl->l_start);
+	err |= __get_user(kfl->l_len, &ufl->l_len);
+	err |= __get_user(kfl->l_pid, &ufl->l_pid);
+	return err;
+}
+
+static inline int
+put_flock(struct flock *kfl, struct flock32 *ufl)
+{
+	int err;
+	
+	err = __put_user(kfl->l_type, &ufl->l_type);
+	err |= __put_user(kfl->l_whence, &ufl->l_whence);
+	err |= __put_user(kfl->l_start, &ufl->l_start);
+	err |= __put_user(kfl->l_len, &ufl->l_len);
+	err |= __put_user(kfl->l_pid, &ufl->l_pid);
+	return err;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd,
+				 unsigned long arg);
+
+asmlinkage long
+sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		{
+			struct flock f;
+			mm_segment_t old_fs;
+			long ret;
+			
+			if(get_flock(&f, (struct flock32 *)arg))
+				return -EFAULT;
+			old_fs = get_fs(); set_fs (KERNEL_DS);
+			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+			set_fs (old_fs);
+			if(put_flock(&f, (struct flock32 *)arg))
+				return -EFAULT;
+			return ret;
+		}
+	default:
+		return sys_fcntl(fd, cmd, (unsigned long)arg);
+	}
+}
+
+struct dqblk32 {
+    __u32 dqb_bhardlimit;
+    __u32 dqb_bsoftlimit;
+    __u32 dqb_curblocks;
+    __u32 dqb_ihardlimit;
+    __u32 dqb_isoftlimit;
+    __u32 dqb_curinodes;
+    __kernel_time_t32 dqb_btime;
+    __kernel_time_t32 dqb_itime;
+};
+                                
+extern asmlinkage int sys_quotactl(int cmd, const char *special, int id,
+				   caddr_t addr);
+
+asmlinkage int
+sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
+{
+	int cmds = cmd >> SUBCMDSHIFT;
+	int err;
+	struct dqblk d;
+	mm_segment_t old_fs;
+	char *spec;
+	
+	switch (cmds) {
+	case Q_GETQUOTA:
+		break;
+	case Q_SETQUOTA:
+	case Q_SETUSE:
+	case Q_SETQLIM:
+		if (copy_from_user (&d, (struct dqblk32 *)addr,
+				    sizeof (struct dqblk32)))
+			return -EFAULT;
+		d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
+		d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
+		break;
+	default:
+		return sys_quotactl(cmd, special,
+				    id, (caddr_t)addr);
+	}
+	spec = getname32 (special);
+	err = PTR_ERR(spec);
+	if (IS_ERR(spec)) return err;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
+	set_fs (old_fs);
+	putname (spec);
+	if (cmds == Q_GETQUOTA) {
+		__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
+		((struct dqblk32 *)&d)->dqb_itime = i;
+		((struct dqblk32 *)&d)->dqb_btime = b;
+		if (copy_to_user ((struct dqblk32 *)addr, &d,
+				  sizeof (struct dqblk32)))
+			return -EFAULT;
+	}
+	return err;
+}
+
+extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
+
+struct utimbuf32 {
+	__kernel_time_t32 actime, modtime;
+};
+
+asmlinkage int
+sys32_utime(char * filename, struct utimbuf32 *times)
+{
+	struct utimbuf t;
+	mm_segment_t old_fs;
+	int ret;
+	char *filenam;
+	
+	if (!times)
+		return sys_utime(filename, NULL);
+	if (get_user (t.actime, &times->actime) ||
+	    __get_user (t.modtime, &times->modtime))
+		return -EFAULT;
+	filenam = getname32 (filename);
+	ret = PTR_ERR(filenam);
+	if (!IS_ERR(filenam)) {
+		old_fs = get_fs();
+		set_fs (KERNEL_DS); 
+		ret = sys_utime(filenam, &t);
+		set_fs (old_fs);
+		putname (filenam);
+	}
+	return ret;
+}
+
+/*
+ * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+ */
+
+static inline int
+get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
+{
+	if (ufdset) {
+		unsigned long odd;
+
+		if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
+			return -EFAULT;
+
+		odd = n & 1UL;
+		n &= ~1UL;
+		while (n) {
+			unsigned long h, l;
+			__get_user(l, ufdset);
+			__get_user(h, ufdset+1);
+			ufdset += 2;
+			*fdset++ = h << 32 | l;
+			n -= 2;
+		}
+		if (odd)
+			__get_user(*fdset, ufdset);
+	} else {
+		/* Tricky, must clear full unsigned long in the
+		 * kernel fdset at the end, this makes sure that
+		 * actually happens.
+		 */
+		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
+	}
+	return 0;
+}
+
+static inline void
+set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+	unsigned long odd;
+
+	if (!ufdset)
+		return;
+
+	odd = n & 1UL;
+	n &= ~1UL;
+	while (n) {
+		unsigned long h, l;
+		l = *fdset++;
+		h = l >> 32;
+		__put_user(l, ufdset);
+		__put_user(h, ufdset+1);
+		ufdset += 2;
+		n -= 2;
+	}
+	if (odd)
+		__put_user(*fdset, ufdset);
+}
+
+extern asmlinkage int sys_sysfs(int option, unsigned long arg1,
+				unsigned long arg2);
+
+asmlinkage int
+sys32_sysfs(int option, u32 arg1, u32 arg2)
+{
+	return sys_sysfs(option, arg1, arg2);
+}
+
+struct ncp_mount_data32 {
+        int version;
+        unsigned int ncp_fd;
+        __kernel_uid_t32 mounted_uid;
+        __kernel_pid_t32 wdog_pid;
+        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
+        unsigned int time_out;
+        unsigned int retry_count;
+        unsigned int flags;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
+
+static void *
+do_ncp_super_data_conv(void *raw_data)
+{
+	struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
+	struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
+
+	n->dir_mode = n32->dir_mode;
+	n->file_mode = n32->file_mode;
+	n->gid = n32->gid;
+	n->uid = n32->uid;
+	memmove (n->mounted_vol, n32->mounted_vol,
+		 (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
+	n->wdog_pid = n32->wdog_pid;
+	n->mounted_uid = n32->mounted_uid;
+	return raw_data;
+}
+
+struct smb_mount_data32 {
+        int version;
+        __kernel_uid_t32 mounted_uid;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
+
+static void *
+do_smb_super_data_conv(void *raw_data)
+{
+	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
+	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+
+	s->version = s32->version;
+	s->mounted_uid = s32->mounted_uid;
+	s->uid = s32->uid;
+	s->gid = s32->gid;
+	s->file_mode = s32->file_mode;
+	s->dir_mode = s32->dir_mode;
+	return raw_data;
+}
+
+static int
+copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
+{
+	int i;
+	unsigned long page;
+	struct vm_area_struct *vma;
+
+	*kernel = 0;
+	if(!user)
+		return 0;
+	vma = find_vma(current->mm, (unsigned long)user);
+	if(!vma || (unsigned long)user < vma->vm_start)
+		return -EFAULT;
+	if(!(vma->vm_flags & VM_READ))
+		return -EFAULT;
+	i = vma->vm_end - (unsigned long) user;
+	if(PAGE_SIZE <= (unsigned long) i)
+		i = PAGE_SIZE - 1;
+	if(!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	if(copy_from_user((void *) page, user, i)) {
+		free_page(page);
+		return -EFAULT;
+	}
+	*kernel = page;
+	return 0;
+}
+
+extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
+				unsigned long new_flags, void *data);
+
+#define SMBFS_NAME	"smbfs"
+#define NCPFS_NAME	"ncpfs"
+
+asmlinkage int
+sys32_mount(char *dev_name, char *dir_name, char *type,
+	    unsigned long new_flags, u32 data)
+{
+	unsigned long type_page;
+	int err, is_smb, is_ncp;
+
+	if(!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	is_smb = is_ncp = 0;
+	err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
+	if(err)
+		return err;
+	if(type_page) {
+		is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+		is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+	}
+	if(!is_smb && !is_ncp) {
+		if(type_page)
+			free_page(type_page);
+		return sys_mount(dev_name, dir_name, type, new_flags,
+				 (void *)AA(data));
+	} else {
+		unsigned long dev_page, dir_page, data_page;
+		mm_segment_t old_fs;
+
+		err = copy_mount_stuff_to_kernel((const void *)dev_name,
+						 &dev_page);
+		if(err)
+			goto out;
+		err = copy_mount_stuff_to_kernel((const void *)dir_name,
+						 &dir_page);
+		if(err)
+			goto dev_out;
+		err = copy_mount_stuff_to_kernel((const void *)AA(data),
+						 &data_page);
+		if(err)
+			goto dir_out;
+		if(is_ncp)
+			do_ncp_super_data_conv((void *)data_page);
+		else if(is_smb)
+			do_smb_super_data_conv((void *)data_page);
+		else
+			panic("The problem is here...");
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_mount((char *)dev_page, (char *)dir_page,
+				(char *)type_page, new_flags,
+				(void *)data_page);
+		set_fs(old_fs);
+
+		if(data_page)
+			free_page(data_page);
+	dir_out:
+		if(dir_page)
+			free_page(dir_page);
+	dev_out:
+		if(dev_page)
+			free_page(dev_page);
+	out:
+		if(type_page)
+			free_page(type_page);
+		return err;
+	}
+}
+
+struct sysinfo32 {
+        s32 uptime;
+        u32 loads[3];
+        u32 totalram;
+        u32 freeram;
+        u32 sharedram;
+        u32 bufferram;
+        u32 totalswap;
+        u32 freeswap;
+        unsigned short procs;
+        char _f[22];
+};
+
+extern asmlinkage int sys_sysinfo(struct sysinfo *info);
+
+asmlinkage int
+sys32_sysinfo(struct sysinfo32 *info)
+{
+	struct sysinfo s;
+	int ret, err;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_sysinfo(&s);
+	set_fs (old_fs);
+	err = put_user (s.uptime, &info->uptime);
+	err |= __put_user (s.loads[0], &info->loads[0]);
+	err |= __put_user (s.loads[1], &info->loads[1]);
+	err |= __put_user (s.loads[2], &info->loads[2]);
+	err |= __put_user (s.totalram, &info->totalram);
+	err |= __put_user (s.freeram, &info->freeram);
+	err |= __put_user (s.sharedram, &info->sharedram);
+	err |= __put_user (s.bufferram, &info->bufferram);
+	err |= __put_user (s.totalswap, &info->totalswap);
+	err |= __put_user (s.freeswap, &info->freeswap);
+	err |= __put_user (s.procs, &info->procs);
+	if (err)
+		return -EFAULT;
+	return ret;
+}
+                
+extern asmlinkage int sys_sched_rr_get_interval(pid_t pid,
+						struct timespec *interval);
+
+asmlinkage int
+sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_sched_rr_get_interval(pid, &t);
+	set_fs (old_fs);
+	if (put_user (t.tv_sec, &interval->tv_sec) ||
+	    __put_user (t.tv_nsec, &interval->tv_nsec))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set,
+				      old_sigset_t *oset);
+
+asmlinkage int
+sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
+{
+	old_sigset_t s;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	if (set && get_user (s, set)) return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
+	set_fs (old_fs);
+	if (ret) return ret;
+	if (oset && put_user (s, oset)) return -EFAULT;
+	return 0;
+}
+
+extern asmlinkage int sys_sigpending(old_sigset_t *set);
+
+asmlinkage int
+sys32_sigpending(old_sigset_t32 *set)
+{
+	old_sigset_t s;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_sigpending(&s);
+	set_fs (old_fs);
+	if (put_user (s, set)) return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
+
+asmlinkage int
+sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
+{
+	sigset_t s;
+	sigset_t32 s32;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_rt_sigpending(&s, sigsetsize);
+	set_fs (old_fs);
+	if (!ret) {
+		switch (_NSIG_WORDS) {
+		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
+		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
+		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
+		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
+		}
+		if (copy_to_user (set, &s32, sizeof(sigset_t32)))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+siginfo_t32 *
+siginfo64to32(siginfo_t32 *d, siginfo_t *s)
+{
+	memset (&d, 0, sizeof(siginfo_t32));
+	d->si_signo = s->si_signo;
+	d->si_errno = s->si_errno;
+	d->si_code = s->si_code;
+	if (s->si_signo >= SIGRTMIN) {
+		d->si_pid = s->si_pid;
+		d->si_uid = s->si_uid;
+		/* XXX: Ouch, how to find this out??? */
+		d->si_int = s->si_int;
+	} else switch (s->si_signo) {
+	/* XXX: What about POSIX1.b timers */
+	case SIGCHLD:
+		d->si_pid = s->si_pid;
+		d->si_status = s->si_status;
+		d->si_utime = s->si_utime;
+		d->si_stime = s->si_stime;
+		break;
+	case SIGSEGV:
+	case SIGBUS:
+	case SIGFPE:
+	case SIGILL:
+		d->si_addr = (long)(s->si_addr);
+		/* XXX: Do we need to translate this from ia64 to ia32 traps? */
+		d->si_trapno = s->si_trapno;
+		break;
+	case SIGPOLL:
+		d->si_band = s->si_band;
+		d->si_fd = s->si_fd;
+		break;
+	default:
+		d->si_pid = s->si_pid;
+		d->si_uid = s->si_uid;
+		break;
+	}
+	return d;
+}
+
+siginfo_t *
+siginfo32to64(siginfo_t *d, siginfo_t32 *s)
+{
+	d->si_signo = s->si_signo;
+	d->si_errno = s->si_errno;
+	d->si_code = s->si_code;
+	if (s->si_signo >= SIGRTMIN) {
+		d->si_pid = s->si_pid;
+		d->si_uid = s->si_uid;
+		/* XXX: Ouch, how to find this out??? */
+		d->si_int = s->si_int;
+	} else switch (s->si_signo) {
+	/* XXX: What about POSIX1.b timers */
+	case SIGCHLD:
+		d->si_pid = s->si_pid;
+		d->si_status = s->si_status;
+		d->si_utime = s->si_utime;
+		d->si_stime = s->si_stime;
+		break;
+	case SIGSEGV:
+	case SIGBUS:
+	case SIGFPE:
+	case SIGILL:
+		d->si_addr = (void *)A(s->si_addr);
+		/* XXX: Do we need to translate this from ia32 to ia64 traps? */
+		d->si_trapno = s->si_trapno;
+		break;
+	case SIGPOLL:
+		d->si_band = s->si_band;
+		d->si_fd = s->si_fd;
+		break;
+	default:
+		d->si_pid = s->si_pid;
+		d->si_uid = s->si_uid;
+		break;
+	}
+	return d;
+}
+
+extern asmlinkage int
+sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
+		    const struct timespec *uts, size_t sigsetsize);
+
+asmlinkage int
+sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
+		      struct timespec32 *uts, __kernel_size_t32 sigsetsize)
+{
+	sigset_t s;
+	sigset_t32 s32;
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	siginfo_t info;
+	siginfo_t32 info32;
+		
+	if (copy_from_user (&s32, uthese, sizeof(sigset_t32)))
+		return -EFAULT;
+	switch (_NSIG_WORDS) {
+	case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
+	case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
+	case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
+	case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
+	}
+	if (uts) {
+		ret = get_user (t.tv_sec, &uts->tv_sec);
+		ret |= __get_user (t.tv_nsec, &uts->tv_nsec);
+		if (ret)
+			return -EFAULT;
+	}
+	set_fs (KERNEL_DS);
+	ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
+	set_fs (old_fs);
+	if (ret >= 0 && uinfo) {
+		if (copy_to_user (uinfo, siginfo64to32(&info32, &info),
+				  sizeof(siginfo_t32)))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+extern asmlinkage int
+sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
+
+asmlinkage int
+sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
+{
+	siginfo_t info;
+	siginfo_t32 info32;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
+		return -EFAULT;
+	/* XXX: Is this correct? */
+	siginfo32to64(&info, &info32);
+	set_fs (KERNEL_DS);
+	ret = sys_rt_sigqueueinfo(pid, sig, &info);
+	set_fs (old_fs);
+	return ret;
+}
+
+extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid);
+
+asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
+{
+	uid_t sruid, seuid;
+
+	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+	return sys_setreuid(sruid, seuid);
+}
+
+extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
+
+asmlinkage int
+sys32_setresuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid,
+		__kernel_uid_t32 suid)
+{
+	uid_t sruid, seuid, ssuid;
+
+	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
+	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
+	ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
+	return sys_setresuid(sruid, seuid, ssuid);
+}
+
+extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
+
+asmlinkage int
+sys32_getresuid(__kernel_uid_t32 *ruid, __kernel_uid_t32 *euid,
+		__kernel_uid_t32 *suid)
+{
+	uid_t a, b, c;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_getresuid(&a, &b, &c);
+	set_fs (old_fs);
+	if (put_user (a, ruid) || put_user (b, euid) || put_user (c, suid))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_setregid(gid_t rgid, gid_t egid);
+
+asmlinkage int
+sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid)
+{
+	gid_t srgid, segid;
+
+	srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
+	segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
+	return sys_setregid(srgid, segid);
+}
+
+extern asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
+
+asmlinkage int
+sys32_setresgid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid,
+		__kernel_gid_t32 sgid)
+{
+	gid_t srgid, segid, ssgid;
+
+	srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
+	segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
+	ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid);
+	return sys_setresgid(srgid, segid, ssgid);
+}
+
+extern asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
+
+asmlinkage int
+sys32_getresgid(__kernel_gid_t32 *rgid, __kernel_gid_t32 *egid,
+		__kernel_gid_t32 *sgid) 
+{
+	gid_t a, b, c;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_getresgid(&a, &b, &c);
+	set_fs (old_fs);
+	if (!ret) {
+		ret = put_user (a, rgid);
+		ret |= put_user (b, egid);
+		ret |= put_user (c, sgid);
+	}
+	return ret;
+}
+
+struct tms32 {
+	__kernel_clock_t32 tms_utime;
+	__kernel_clock_t32 tms_stime;
+	__kernel_clock_t32 tms_cutime;
+	__kernel_clock_t32 tms_cstime;
+};
+                                
+extern asmlinkage long sys_times(struct tms * tbuf);
+
+asmlinkage long
+sys32_times(struct tms32 *tbuf)
+{
+	struct tms t;
+	long ret;
+	mm_segment_t old_fs = get_fs ();
+	int err;
+	
+	set_fs (KERNEL_DS);
+	ret = sys_times(tbuf ? &t : NULL);
+	set_fs (old_fs);
+	if (tbuf) {
+		err = put_user (t.tms_utime, &tbuf->tms_utime);
+		err |= __put_user (t.tms_stime, &tbuf->tms_stime);
+		err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
+		err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
+		if (err)
+			ret = -EFAULT;
+	}
+	return ret;
+}
+
+extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
+
+asmlinkage int
+sys32_getgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
+{
+	gid_t gl[NGROUPS];
+	int ret, i;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_getgroups(gidsetsize, gl);
+	set_fs (old_fs);
+	if (gidsetsize && ret > 0 && ret <= NGROUPS)
+		for (i = 0; i < ret; i++, grouplist++)
+			if (__put_user (gl[i], grouplist))
+				return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
+
+asmlinkage int
+sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
+{
+	gid_t gl[NGROUPS];
+	int ret, i;
+	mm_segment_t old_fs = get_fs ();
+	
+	if ((unsigned) gidsetsize > NGROUPS)
+		return -EINVAL;
+	for (i = 0; i < gidsetsize; i++, grouplist++)
+		if (__get_user (gl[i], grouplist))
+			return -EFAULT;
+        set_fs (KERNEL_DS);
+	ret = sys_setgroups(gidsetsize, gl);
+	set_fs (old_fs);
+	return ret;
+}
+
+extern asmlinkage int
+sys_getrusage(int who, struct rusage *ru);
+
+asmlinkage int
+sys32_getrusage(int who, struct rusage32 *ru)
+{
+	struct rusage r;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_getrusage(who, &r);
+	set_fs (old_fs);
+	if (put_rusage (ru, &r)) return -EFAULT;
+	return ret;
+}
+
+
+/* XXX These as well... */
+extern __inline__ struct socket *
+socki_lookup(struct inode *inode)
+{
+	return &inode->u.socket_i;
+}
+
+extern __inline__ struct socket *
+sockfd_lookup(int fd, int *err)
+{
+	struct file *file;
+	struct inode *inode;
+
+	if (!(file = fget(fd)))
+	{
+		*err = -EBADF;
+		return NULL;
+	}
+
+	inode = file->f_dentry->d_inode;
+	if (!inode || !inode->i_sock || !socki_lookup(inode))
+	{
+		*err = -ENOTSOCK;
+		fput(file);
+		return NULL;
+	}
+
+	return socki_lookup(inode);
+}
+
+struct msghdr32 {
+        u32               msg_name;
+        int               msg_namelen;
+        u32               msg_iov;
+        __kernel_size_t32 msg_iovlen;
+        u32               msg_control;
+        __kernel_size_t32 msg_controllen;
+        unsigned          msg_flags;
+};
+
+struct cmsghdr32 {
+        __kernel_size_t32 cmsg_len;
+        int               cmsg_level;
+        int               cmsg_type;
+};
+
+/* Bleech... */
+#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) \
+        __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) \
+        cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
+
+#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+
+#define CMSG32_DATA(cmsg) \
+	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
+#define CMSG32_SPACE(len) \
+	(CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
+#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
+
+#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
+				    (struct cmsghdr32 *)(ctl) : \
+				    (struct cmsghdr32 *)NULL)
+#define CMSG32_FIRSTHDR(msg) \
+	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+__inline__ struct cmsghdr32 *
+__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
+		struct cmsghdr32 *__cmsg, int __cmsg_len) 
+{
+	struct cmsghdr32 * __ptr;
+
+	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
+				     CMSG32_ALIGN(__cmsg_len));
+	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+		return NULL;
+
+	return __ptr;
+}
+
+__inline__ struct cmsghdr32 *
+cmsg32_nxthdr (struct msghdr *__msg, struct cmsghdr32 *__cmsg, int __cmsg_len)
+{
+	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
+			       __cmsg, __cmsg_len);
+}
+
+static inline int
+iov_from_user32_to_kern(struct iovec *kiov, struct iovec32 *uiov32, int niov)
+{
+	int tot_len = 0;
+
+	while(niov > 0) {
+		u32 len, buf;
+
+		if(get_user(len, &uiov32->iov_len) ||
+		   get_user(buf, &uiov32->iov_base)) {
+			tot_len = -EFAULT;
+			break;
+		}
+		tot_len += len;
+		kiov->iov_base = (void *)A(buf);
+		kiov->iov_len = (__kernel_size_t) len;
+		uiov32++;
+		kiov++;
+		niov--;
+	}
+	return tot_len;
+}
+
+static inline int
+msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg)
+{
+	u32 tmp1, tmp2, tmp3;
+	int err;
+
+	err = get_user(tmp1, &umsg->msg_name);
+	err |= __get_user(tmp2, &umsg->msg_iov);
+	err |= __get_user(tmp3, &umsg->msg_control);
+	if (err)
+		return -EFAULT;
+
+	kmsg->msg_name = (void *)A(tmp1);
+	kmsg->msg_iov = (struct iovec *)A(tmp2);
+	kmsg->msg_control = (void *)A(tmp3);
+
+	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
+	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+	
+	return err;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+static int
+verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
+	       char *kern_address, int mode)
+{
+	int tot_len;
+
+	if(kern_msg->msg_namelen) {
+		if(mode==VERIFY_READ) {
+			int err = move_addr_to_kernel(kern_msg->msg_name,
+						      kern_msg->msg_namelen,
+						      kern_address);
+			if(err < 0)
+				return err;
+		}
+		kern_msg->msg_name = kern_address;
+	} else
+		kern_msg->msg_name = NULL;
+
+	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+				   GFP_KERNEL);
+		if(!kern_iov)
+			return -ENOMEM;
+	}
+
+	tot_len = iov_from_user32_to_kern(kern_iov,
+					  (struct iovec32 *)kern_msg->msg_iov,
+					  kern_msg->msg_iovlen);
+	if(tot_len >= 0)
+		kern_msg->msg_iov = kern_iov;
+	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+		kfree(kern_iov);
+
+	return tot_len;
+}
+
+/* There is a lot of hair here because the alignment rules (and
+ * thus placement) of cmsg headers and length are different for
+ * 32-bit apps.  -DaveM
+ */
+static int
+cmsghdr_from_user32_to_kern(struct msghdr *kmsg, unsigned char *stackbuf,
+			    int stackbuf_size) 
+{
+	struct cmsghdr32 *ucmsg;
+	struct cmsghdr *kcmsg, *kcmsg_base;
+	__kernel_size_t32 ucmlen;
+	__kernel_size_t kcmlen, tmp;
+
+	kcmlen = 0;
+	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+	ucmsg = CMSG32_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		if(get_user(ucmlen, &ucmsg->cmsg_len))
+			return -EFAULT;
+
+		/* Catch bogons. */
+		if(CMSG32_ALIGN(ucmlen) <
+		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
+			return -EINVAL;
+		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
+				   + ucmlen) > kmsg->msg_controllen)
+			return -EINVAL;
+
+		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmlen += tmp;
+		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+	if(kcmlen == 0)
+		return -EINVAL;
+
+	/* The kcmlen holds the 64-bit version of the control length.
+	 * It may not be modified as we do not stick it into the kmsg
+	 * until we have successfully copied over all of the data
+	 * from the user.
+	 */
+	if(kcmlen > stackbuf_size)
+		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
+	if(kcmsg == NULL)
+		return -ENOBUFS;
+
+	/* Now copy them over neatly. */
+	memset(kcmsg, 0, kcmlen);
+	ucmsg = CMSG32_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		__get_user(ucmlen, &ucmsg->cmsg_len);
+		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmsg->cmsg_len = tmp;
+		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+		/* Copy over the data. */
+		if(copy_from_user(CMSG_DATA(kcmsg),
+				  CMSG32_DATA(ucmsg),
+				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+			goto out_free_efault;
+
+		/* Advance. */
+		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+
+	/* Ok, looks like we made it.  Hook it up and return success. */
+	kmsg->msg_control = kcmsg_base;
+	kmsg->msg_controllen = kcmlen;
+	return 0;
+
+out_free_efault:
+	if(kcmsg_base != (struct cmsghdr *)stackbuf)
+		kfree(kcmsg_base);
+	return -EFAULT;
+}
+
+static void
+put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data)
+{
+	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+	struct cmsghdr32 cmhdr;
+	int cmlen = CMSG32_LEN(len);
+
+	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		return;
+	}
+
+	if(kmsg->msg_controllen < cmlen) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		cmlen = kmsg->msg_controllen;
+	}
+	cmhdr.cmsg_level = level;
+	cmhdr.cmsg_type = type;
+	cmhdr.cmsg_len = cmlen;
+
+	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+		return;
+	if(copy_to_user(CMSG32_DATA(cm), data,
+			cmlen - sizeof(struct cmsghdr32)))
+		return;
+	cmlen = CMSG32_SPACE(len);
+	kmsg->msg_control += cmlen;
+	kmsg->msg_controllen -= cmlen;
+}
+
+static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
+{
+	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32))
+		/ sizeof(int);
+	int fdnum = scm->fp->count;
+	struct file **fp = scm->fp->fp;
+	int *cmfptr;
+	int err = 0, i;
+
+	if (fdnum < fdmax)
+		fdmax = fdnum;
+
+	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm);
+	     i < fdmax;
+	     i++, cmfptr++) {
+		int new_fd;
+		err = get_unused_fd();
+		if (err < 0)
+			break;
+		new_fd = err;
+		err = put_user(new_fd, cmfptr);
+		if (err) {
+			put_unused_fd(new_fd);
+			break;
+		}
+		/* Bump the usage count and install the file. */
+		fp[i]->f_count++;
+		current->files->fd[new_fd] = fp[i];
+	}
+
+	if (i > 0) {
+		int cmlen = CMSG32_LEN(i * sizeof(int));
+		if (!err)
+			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		if (!err)
+			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+		if (!err)
+			err = put_user(cmlen, &cm->cmsg_len);
+		if (!err) {
+			cmlen = CMSG32_SPACE(i * sizeof(int));
+			kmsg->msg_control += cmlen;
+			kmsg->msg_controllen -= cmlen;
+		}
+	}
+	if (i < fdnum)
+		kmsg->msg_flags |= MSG_CTRUNC;
+
+	/*
+	 * All of the files that fit in the message have had their
+	 * usage counts incremented, so we just free the list.
+	 */
+	__scm_destroy(scm);
+}
+
+/* In these cases we (currently) can just copy to data over verbatim
+ * because all CMSGs created by the kernel have well defined types which
+ * have the same layout in both the 32-bit and 64-bit API.  One must add
+ * some special cased conversions here if we start sending control messages
+ * with incompatible types.
+ *
+ * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
+ * we do our work.  The remaining cases are:
+ *
+ * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
+ *		IP_TTL		int			32-bit clean
+ *		IP_TOS		__u8			32-bit clean
+ *		IP_RECVOPTS	variable length		32-bit clean
+ *		IP_RETOPTS	variable length		32-bit clean
+ *		(these last two are clean because the types are defined
+ *		 by the IPv4 protocol)
+ *		IP_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in	32-bit clean
+ * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in6	32-bit clean
+ *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
+ *		IPV6_HOPLIMIT	int			32-bit clean
+ *		IPV6_FLOWINFO	u32			32-bit clean
+ *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
+ *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
+ *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
+ *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
+ */
+static void
+cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+{
+	unsigned char *workbuf, *wp;
+	unsigned long bufsz, space_avail;
+	struct cmsghdr *ucmsg;
+
+	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
+	space_avail = kmsg->msg_controllen + bufsz;
+	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
+	if(workbuf == NULL)
+		goto fail;
+
+	/* To make this more sane we assume the kernel sends back properly
+	 * formatted control messages.  Because of how the kernel will truncate
+	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
+	 */
+	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
+	while(((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
+		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
+		int clen64, clen32;
+
+		/* UCMSG is the 64-bit format CMSG entry in user-space.
+		 * KCMSG32 is within the kernel space temporary buffer
+		 * we use to convert into a 32-bit style CMSG.
+		 */
+		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
+		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
+
+		clen64 = kcmsg32->cmsg_len;
+		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
+			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
+		kcmsg32->cmsg_len = clen32;
+
+		ucmsg = (struct cmsghdr *) (((char *)ucmsg) +
+					    CMSG_ALIGN(clen64)); 
+		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
+	}
+
+	/* Copy back fixed up data, and adjust pointers. */
+	bufsz = (wp - workbuf);
+	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
+
+	kmsg->msg_control = (struct cmsghdr *)
+		(((char *)orig_cmsg_uptr) + bufsz);
+	kmsg->msg_controllen = space_avail - bufsz;
+
+	kfree(workbuf);
+	return;
+
+fail:
+	/* If we leave the 64-bit format CMSG chunks in there,
+	 * the application could get confused and crash.  So to
+	 * ensure greater recovery, we report no CMSGs.
+	 */
+	kmsg->msg_controllen += bufsz;
+	kmsg->msg_control = (void *) orig_cmsg_uptr;
+}
+
+asmlinkage int
+sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
+{
+	struct socket *sock;
+	char address[MAX_SOCK_ADDR];
+	struct iovec iov[UIO_FASTIOV];
+	unsigned char ctl[sizeof(struct cmsghdr) + 20];
+	unsigned char *ctl_buf = ctl;
+	struct msghdr kern_msg;
+	int err, total_len;
+
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+		return -EFAULT;
+	if(kern_msg.msg_iovlen > UIO_MAXIOV)
+		return -EINVAL;
+	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+	if (err < 0)
+		goto out;
+	total_len = err;
+
+	if(kern_msg.msg_controllen) {
+		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
+		if(err)
+			goto out_freeiov;
+		ctl_buf = kern_msg.msg_control;
+	}
+	kern_msg.msg_flags = user_flags;
+
+	lock_kernel();
+	sock = sockfd_lookup(fd, &err);
+	if (sock != NULL) {
+		if (sock->file->f_flags & O_NONBLOCK)
+			kern_msg.msg_flags |= MSG_DONTWAIT;
+		err = sock_sendmsg(sock, &kern_msg, total_len);
+		sockfd_put(sock);
+	}
+	unlock_kernel();
+
+	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
+	if(ctl_buf != ctl)
+		kfree(ctl_buf);
+out_freeiov:
+	if(kern_msg.msg_iov != iov)
+		kfree(kern_msg.msg_iov);
+out:
+	return err;
+}
+
+asmlinkage int
+sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
+{
+	struct iovec iovstack[UIO_FASTIOV];
+	struct msghdr kern_msg;
+	char addr[MAX_SOCK_ADDR];
+	struct socket *sock;
+	struct iovec *iov = iovstack;
+	struct sockaddr *uaddr;
+	int *uaddr_len;
+	unsigned long cmsg_ptr;
+	int err, total_len, len = 0;
+
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+		return -EFAULT;
+	if(kern_msg.msg_iovlen > UIO_MAXIOV)
+		return -EINVAL;
+
+	uaddr = kern_msg.msg_name;
+	uaddr_len = &user_msg->msg_namelen;
+	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+	if (err < 0)
+		goto out;
+	total_len = err;
+
+	cmsg_ptr = (unsigned long) kern_msg.msg_control;
+	kern_msg.msg_flags = 0;
+
+	lock_kernel();
+	sock = sockfd_lookup(fd, &err);
+	if (sock != NULL) {
+		struct scm_cookie scm;
+
+		if (sock->file->f_flags & O_NONBLOCK)
+			user_flags |= MSG_DONTWAIT;
+		memset(&scm, 0, sizeof(scm));
+		err = sock->ops->recvmsg(sock, &kern_msg, total_len,
+					 user_flags, &scm);
+		if(err >= 0) {
+			len = err;
+			if(!kern_msg.msg_control) {
+				if(sock->passcred || scm.fp)
+					kern_msg.msg_flags |= MSG_CTRUNC;
+				if(scm.fp)
+					__scm_destroy(&scm);
+			} else {
+				/* If recvmsg processing itself placed some
+				 * control messages into user space, it's is
+				 * using 64-bit CMSG processing, so we need
+				 * to fix it up before we tack on more stuff.
+				 */
+				if((unsigned long) kern_msg.msg_control
+				   != cmsg_ptr)
+					cmsg32_recvmsg_fixup(&kern_msg,
+							     cmsg_ptr);
+
+				/* Wheee... */
+				if(sock->passcred)
+					put_cmsg32(&kern_msg,
+						   SOL_SOCKET, SCM_CREDENTIALS,
+						   sizeof(scm.creds),
+						   &scm.creds);
+				if(scm.fp != NULL)
+					scm_detach_fds32(&kern_msg, &scm);
+			}
+		}
+		sockfd_put(sock);
+	}
+	unlock_kernel();
+
+	if(uaddr != NULL && err >= 0)
+		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr,
+					uaddr_len);
+	if(cmsg_ptr != 0 && err >= 0) {
+		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
+		__kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr
+							       - cmsg_ptr);
+		err |= __put_user(uclen, &user_msg->msg_controllen);
+	}
+	if(err >= 0)
+		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
+	if(kern_msg.msg_iov != iov)
+		kfree(kern_msg.msg_iov);
+out:
+	if(err < 0)
+		return err;
+	return len;
+}
+
+extern void check_pending(int signum);
+
+asmlinkage int
+sys32_sigaction (int sig, struct old_sigaction32 *act,
+		 struct old_sigaction32 *oact)
+{
+        struct k_sigaction new_ka, old_ka;
+        int ret;
+
+	if(sig < 0) {
+		current->tss.new_signal = 1;
+		sig = -sig;
+	}
+
+        if (act) {
+		old_sigset_t32 mask;
+		
+		ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		ret |= __get_user(mask, &act->sa_mask);
+		if (ret)
+			return ret;
+		siginitset(&new_ka.sa.sa_mask, mask);
+        }
+
+        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
+		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+        }
+
+	return ret;
+}
+
+#ifdef CONFIG_MODULES
+
+extern asmlinkage unsigned long sys_create_module(const char *name_user,
+						  size_t size);
+
+asmlinkage unsigned long
+sys32_create_module(const char *name_user, __kernel_size_t32 size)
+{
+	return sys_create_module(name_user, (size_t)size);
+}
+
+extern asmlinkage int sys_init_module(const char *name_user,
+				      struct module *mod_user); 
+
+/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
+ * module structure, even if from 32bit modutils... Why to pollute kernel... :))
+ */
+asmlinkage int
+sys32_init_module(const char *name_user, struct module *mod_user)
+{
+	return sys_init_module(name_user, mod_user);
+}
+
+extern asmlinkage int sys_delete_module(const char *name_user);
+
+asmlinkage int
+sys32_delete_module(const char *name_user)
+{
+	return sys_delete_module(name_user);
+}
+
+struct module_info32 {
+	u32 addr;
+	u32 size;
+	u32 flags;
+	s32 usecount;
+};
+
+/* Query various bits about modules.  */
+
+static inline long
+get_mod_name(const char *user_name, char **buf)
+{
+	unsigned long page;
+	long retval;
+
+	if ((unsigned long)user_name >= TASK_SIZE
+	    && !segment_eq(get_fs (), KERNEL_DS))
+		return -EFAULT;
+
+	page = __get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
+	if (retval > 0) {
+		if (retval < PAGE_SIZE) {
+			*buf = (char *)page;
+			return retval;
+		}
+		retval = -ENAMETOOLONG;
+	} else if (!retval)
+		retval = -EINVAL;
+
+	free_page(page);
+	return retval;
+}
+
+static inline void
+put_mod_name(char *buf)
+{
+	free_page((unsigned long)buf);
+}
+
+static __inline__ struct module *
+find_module(const char *name)
+{
+	struct module *mod;
+
+	for (mod = module_list; mod ; mod = mod->next) {
+		if (mod->flags & MOD_DELETED)
+			continue;
+		if (!strcmp(mod->name, name))
+			break;
+	}
+
+	return mod;
+}
+
+static int
+qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	struct module *mod;
+	size_t nmod, space, len;
+
+	nmod = space = 0;
+
+	for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
+		len = strlen(mod->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, mod->name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(nmod, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((mod = mod->next)->next != NULL)
+		space += strlen(mod->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t i, space, len;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (i = 0; i < mod->ndeps; ++i) {
+		const char *dep_name = mod->deps[i].dep->name;
+
+		len = strlen(dep_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, dep_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while (++i < mod->ndeps)
+		space += strlen(mod->deps[i].dep->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t nrefs, space, len;
+	struct module_ref *ref;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
+		const char *ref_name = ref->ref->name;
+
+		len = strlen(ref_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, ref_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(nrefs, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((ref = ref->next_ref) != NULL)
+		space += strlen(ref->ref->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_symbols(struct module *mod, char *buf, size_t bufsize,
+	   __kernel_size_t32 *ret)
+{
+	size_t i, space, len;
+	struct module_symbol *s;
+	char *strings;
+	unsigned *vals;
+
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = mod->nsyms * 2*sizeof(u32);
+
+	i = len = 0;
+	s = mod->syms;
+
+	if (space > bufsize)
+		goto calc_space_needed;
+
+	if (!access_ok(VERIFY_WRITE, buf, space))
+		return -EFAULT;
+
+	bufsize -= space;
+	vals = (unsigned *)buf;
+	strings = buf+space;
+
+	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
+		len = strlen(s->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+
+		if (copy_to_user(strings, s->name, len)
+		    || __put_user(s->value, vals+0)
+		    || __put_user(space, vals+1))
+			return -EFAULT;
+
+		strings += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	for (; i < mod->nsyms; ++i, ++s)
+		space += strlen(s->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	int error = 0;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+
+	if (sizeof(struct module_info32) <= bufsize) {
+		struct module_info32 info;
+		info.addr = (unsigned long)mod;
+		info.size = mod->size;
+		info.flags = mod->flags;
+		info.usecount =
+			((mod_member_present(mod, can_unload)
+			  && mod->can_unload)
+			 ? -1 : atomic_read(&mod->uc.usecount));
+
+		if (copy_to_user(buf, &info, sizeof(struct module_info32)))
+			return -EFAULT;
+	} else
+		error = -ENOSPC;
+
+	if (put_user(sizeof(struct module_info32), ret))
+		return -EFAULT;
+
+	return error;
+}
+
+asmlinkage int
+sys32_query_module(char *name_user, int which, char *buf,
+		   __kernel_size_t32 bufsize, u32 ret) 
+{
+	struct module *mod;
+	int err;
+
+	lock_kernel();
+	if (name_user == 0) {
+		/* This finds "kernel_module" which is not exported. */
+		for(mod = module_list; mod->next != NULL; mod = mod->next)
+			;
+	} else {
+		long namelen;
+		char *name;
+
+		if ((namelen = get_mod_name(name_user, &name)) < 0) {
+			err = namelen;
+			goto out;
+		}
+		err = -ENOENT;
+		if (namelen == 0) {
+			/* This finds "kernel_module" which is not exported. */
+			for(mod = module_list;
+			    mod->next != NULL;
+			    mod = mod->next) ;
+		} else if ((mod = find_module(name)) == NULL) {
+			put_mod_name(name);
+			goto out;
+		}
+		put_mod_name(name);
+	}
+
+	switch (which)
+	{
+	case 0:
+		err = 0;
+		break;
+	case QM_MODULES:
+		err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_DEPS:
+		err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_REFS:
+		err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_SYMBOLS:
+		err = qm_symbols(mod, buf, bufsize,
+				 (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_INFO:
+		err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+out:
+	unlock_kernel();
+	return err;
+}
+
+struct kernel_sym32 {
+	u32 value;
+	char name[60];
+};
+		 
+extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
+
+asmlinkage int
+sys32_get_kernel_syms(struct kernel_sym32 *table)
+{
+	int len, i;
+	struct kernel_sym *tbl;
+	mm_segment_t old_fs;
+	
+	len = sys_get_kernel_syms(NULL);
+	if (!table) return len;
+	tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
+	if (!tbl) return -ENOMEM;
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	sys_get_kernel_syms(tbl);
+	set_fs (old_fs);
+	for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
+		if (put_user (tbl[i].value, &table->value) ||
+		    copy_to_user (table->name, tbl[i].name, 60))
+			break;
+	}
+	kfree (tbl);
+	return i;
+}
+
+#else /* CONFIG_MODULES */
+
+asmlinkage unsigned long
+sys32_create_module(const char *name_user, size_t size)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_init_module(const char *name_user, struct module *mod_user)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_delete_module(const char *name_user)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
+		 size_t *ret)
+{
+	/* Let the program know about the new interface.  Not that
+	   it'll do them much good.  */
+	if (which == 0)
+		return 0;
+
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_get_kernel_syms(struct kernel_sym *table)
+{
+	return -ENOSYS;
+}
+
+#endif  /* CONFIG_MODULES */
+
+/* Stuff for NFS server syscalls... */
+struct nfsctl_svc32 {
+	u16			svc32_port;
+	s32			svc32_nthreads;
+};
+
+struct nfsctl_client32 {
+	s8			cl32_ident[NFSCLNT_IDMAX+1];
+	s32			cl32_naddr;
+	struct in_addr		cl32_addrlist[NFSCLNT_ADDRMAX];
+	s32			cl32_fhkeytype;
+	s32			cl32_fhkeylen;
+	u8			cl32_fhkey[NFSCLNT_KEYMAX];
+};
+
+struct nfsctl_export32 {
+	s8			ex32_client[NFSCLNT_IDMAX+1];
+	s8			ex32_path[NFS_MAXPATHLEN+1];
+	__kernel_dev_t32	ex32_dev;
+	__kernel_ino_t32	ex32_ino;
+	s32			ex32_flags;
+	__kernel_uid_t32	ex32_anon_uid;
+	__kernel_gid_t32	ex32_anon_gid;
+};
+
+struct nfsctl_uidmap32 {
+	u32			ug32_ident;   /* char * */
+	__kernel_uid_t32	ug32_uidbase;
+	s32			ug32_uidlen;
+	u32			ug32_udimap;  /* uid_t * */
+	__kernel_uid_t32	ug32_gidbase;
+	s32			ug32_gidlen;
+	u32			ug32_gdimap;  /* gid_t * */
+};
+
+struct nfsctl_fhparm32 {
+	struct sockaddr		gf32_addr;
+	__kernel_dev_t32	gf32_dev;
+	__kernel_ino_t32	gf32_ino;
+	s32			gf32_version;
+};
+
+struct nfsctl_arg32 {
+	s32			ca32_version;	/* safeguard */
+	union {
+		struct nfsctl_svc32	u32_svc;
+		struct nfsctl_client32	u32_client;
+		struct nfsctl_export32	u32_export;
+		struct nfsctl_uidmap32	u32_umap;
+		struct nfsctl_fhparm32	u32_getfh;
+		u32			u32_debug;
+	} u;
+#define ca32_svc	u.u32_svc
+#define ca32_client	u.u32_client
+#define ca32_export	u.u32_export
+#define ca32_umap	u.u32_umap
+#define ca32_getfh	u.u32_getfh
+#define ca32_authd	u.u32_authd
+#define ca32_debug	u.u32_debug
+};
+
+union nfsctl_res32 {
+	struct knfs_fh		cr32_getfh;
+	u32			cr32_debug;
+};
+
+static int
+nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
+	err |= __get_user(karg->ca_svc.svc_nthreads,
+			  &arg32->ca32_svc.svc32_nthreads);
+	return err;
+}
+
+static int
+nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_client.cl_ident[0],
+			  &arg32->ca32_client.cl32_ident[0],
+			  NFSCLNT_IDMAX);
+	err |= __get_user(karg->ca_client.cl_naddr,
+			  &arg32->ca32_client.cl32_naddr);
+	err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
+			  &arg32->ca32_client.cl32_addrlist[0],
+			  (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
+	err |= __get_user(karg->ca_client.cl_fhkeytype,
+		      &arg32->ca32_client.cl32_fhkeytype);
+	err |= __get_user(karg->ca_client.cl_fhkeylen,
+		      &arg32->ca32_client.cl32_fhkeylen);
+	err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
+			  &arg32->ca32_client.cl32_fhkey[0],
+			  NFSCLNT_KEYMAX);
+	return err;
+}
+
+static int
+nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_export.ex_client[0],
+			  &arg32->ca32_export.ex32_client[0],
+			  NFSCLNT_IDMAX);
+	err |= copy_from_user(&karg->ca_export.ex_path[0],
+			  &arg32->ca32_export.ex32_path[0],
+			  NFS_MAXPATHLEN);
+	err |= __get_user(karg->ca_export.ex_dev,
+		      &arg32->ca32_export.ex32_dev);
+	err |= __get_user(karg->ca_export.ex_ino,
+		      &arg32->ca32_export.ex32_ino);
+	err |= __get_user(karg->ca_export.ex_flags,
+		      &arg32->ca32_export.ex32_flags);
+	err |= __get_user(karg->ca_export.ex_anon_uid,
+		      &arg32->ca32_export.ex32_anon_uid);
+	err |= __get_user(karg->ca_export.ex_anon_gid,
+		      &arg32->ca32_export.ex32_anon_gid);
+	return err;
+}
+
+static int
+nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	u32 uaddr;
+	int i;
+	int err;
+
+	memset(karg, 0, sizeof(*karg));
+	if(__get_user(karg->ca_version, &arg32->ca32_version))
+		return -EFAULT;
+	karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
+	if(!karg->ca_umap.ug_ident)
+		return -ENOMEM;
+	err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
+	if(strncpy_from_user(karg->ca_umap.ug_ident,
+			     (char *)A(uaddr), PAGE_SIZE) <= 0)
+		return -EFAULT;
+	err |= __get_user(karg->ca_umap.ug_uidbase,
+		      &arg32->ca32_umap.ug32_uidbase);
+	err |= __get_user(karg->ca_umap.ug_uidlen,
+		      &arg32->ca32_umap.ug32_uidlen);
+	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
+	if (err)
+		return -EFAULT;
+	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) *
+					   karg->ca_umap.ug_uidlen),
+					  GFP_USER);
+	if(!karg->ca_umap.ug_udimap)
+		return -ENOMEM;
+	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
+		err |= __get_user(karg->ca_umap.ug_udimap[i],
+			      &(((__kernel_uid_t32 *)A(uaddr))[i]));
+	err |= __get_user(karg->ca_umap.ug_gidbase,
+		      &arg32->ca32_umap.ug32_gidbase);
+	err |= __get_user(karg->ca_umap.ug_uidlen,
+		      &arg32->ca32_umap.ug32_gidlen);
+	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
+	if (err)
+		return -EFAULT;
+	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) *
+					   karg->ca_umap.ug_uidlen),
+					  GFP_USER);
+	if(!karg->ca_umap.ug_gdimap)
+		return -ENOMEM;
+	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
+		err |= __get_user(karg->ca_umap.ug_gdimap[i],
+			      &(((__kernel_gid_t32 *)A(uaddr))[i]));
+
+	return err;
+}
+
+static int
+nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_getfh.gf_addr,
+			  &arg32->ca32_getfh.gf32_addr,
+			  (sizeof(struct sockaddr)));
+	err |= __get_user(karg->ca_getfh.gf_dev,
+		      &arg32->ca32_getfh.gf32_dev);
+	err |= __get_user(karg->ca_getfh.gf_ino,
+		      &arg32->ca32_getfh.gf32_ino);
+	err |= __get_user(karg->ca_getfh.gf_version,
+		      &arg32->ca32_getfh.gf32_version);
+	return err;
+}
+
+static int
+nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
+{
+	int err;
+	
+	err = copy_to_user(&res32->cr32_getfh,
+			&kres->cr_getfh,
+			sizeof(res32->cr32_getfh));
+	err |= __put_user(kres->cr_debug, &res32->cr32_debug);
+	return err;
+}
+
+extern asmlinkage int sys_nfsservctl(int cmd, void *arg, void *resp);
+
+int asmlinkage
+sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
+{
+	struct nfsctl_arg *karg = NULL;
+	union nfsctl_res *kres = NULL;
+	mm_segment_t oldfs;
+	int err;
+
+	karg = kmalloc(sizeof(*karg), GFP_USER);
+	if(!karg)
+		return -ENOMEM;
+	if(res32) {
+		kres = kmalloc(sizeof(*kres), GFP_USER);
+		if(!kres) {
+			kfree(karg);
+			return -ENOMEM;
+		}
+	}
+	switch(cmd) {
+	case NFSCTL_SVC:
+		err = nfs_svc32_trans(karg, arg32);
+		break;
+	case NFSCTL_ADDCLIENT:
+		err = nfs_clnt32_trans(karg, arg32);
+		break;
+	case NFSCTL_DELCLIENT:
+		err = nfs_clnt32_trans(karg, arg32);
+		break;
+	case NFSCTL_EXPORT:
+		err = nfs_exp32_trans(karg, arg32);
+		break;
+	/* This one is unimplemented, be we're ready for it. */
+	case NFSCTL_UGIDUPDATE:
+		err = nfs_uud32_trans(karg, arg32);
+		break;
+	case NFSCTL_GETFH:
+		err = nfs_getfh32_trans(karg, arg32);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+	if(err)
+		goto done;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_nfsservctl(cmd, karg, kres);
+	set_fs(oldfs);
+
+	if(!err && cmd == NFSCTL_GETFH)
+		err = nfs_getfh32_res_trans(kres, res32);
+
+done:
+	if(karg) {
+		if(cmd == NFSCTL_UGIDUPDATE) {
+			if(karg->ca_umap.ug_ident)
+				kfree(karg->ca_umap.ug_ident);
+			if(karg->ca_umap.ug_udimap)
+				kfree(karg->ca_umap.ug_udimap);
+			if(karg->ca_umap.ug_gdimap)
+				kfree(karg->ca_umap.ug_gdimap);
+		}
+		kfree(karg);
+	}
+	if(kres)
+		kfree(kres);
+	return err;
+}
+
+asmlinkage int sys_utimes(char *, struct timeval *);
+
+asmlinkage int
+sys32_utimes(char *filename, struct timeval32 *tvs)
+{
+	char *kfilename;
+	struct timeval ktvs[2];
+	mm_segment_t old_fs;
+	int ret;
+
+	kfilename = getname32(filename);
+	ret = PTR_ERR(kfilename);
+	if (!IS_ERR(kfilename)) {
+		if (tvs) {
+			if (get_tv32(&ktvs[0], tvs) ||
+			    get_tv32(&ktvs[1], 1+tvs))
+				return -EFAULT;
+		}
+
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		ret = sys_utimes(kfilename, &ktvs[0]);
+		set_fs(old_fs);
+
+		putname(kfilename);
+	}
+	return ret;
+}
+
+/* These are here just in case some old ia32 binary calls it. */
+asmlinkage int
+sys32_pause(void)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	return -ERESTARTNOHAND;
+}
+
+/* PCI config space poking. */
+extern asmlinkage int sys_pciconfig_read(unsigned long bus,
+					 unsigned long dfn,
+					 unsigned long off,
+					 unsigned long len,
+					 unsigned char *buf);
+
+extern asmlinkage int sys_pciconfig_write(unsigned long bus,
+					  unsigned long dfn,
+					  unsigned long off,
+					  unsigned long len,
+					  unsigned char *buf);
+
+asmlinkage int
+sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
+{
+	return sys_pciconfig_read((unsigned long) bus,
+				  (unsigned long) dfn,
+				  (unsigned long) off,
+				  (unsigned long) len,
+				  (unsigned char *)AA(ubuf));
+}
+
+asmlinkage int
+sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
+{
+	return sys_pciconfig_write((unsigned long) bus,
+				   (unsigned long) dfn,
+				   (unsigned long) off,
+				   (unsigned long) len,
+				   (unsigned char *)AA(ubuf));
+}
+
+extern asmlinkage int sys_prctl(int option, unsigned long arg2,
+				unsigned long arg3, unsigned long arg4,
+				unsigned long arg5);
+
+asmlinkage int
+sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+{
+	return sys_prctl(option,
+			 (unsigned long) arg2,
+			 (unsigned long) arg3,
+			 (unsigned long) arg4,
+			 (unsigned long) arg5);
+}
+
+
+extern asmlinkage int sys_newuname(struct new_utsname * name);
+
+asmlinkage int
+sys32_newuname(struct new_utsname * name)
+{
+	int ret = sys_newuname(name);
+	
+	if (current->personality == PER_LINUX32 && !ret) {
+		ret = copy_to_user(name->machine, "sparc\0\0", 8);
+	}
+	return ret;
+}
+
+extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
+				    size_t count, loff_t pos);
+
+extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
+				     size_t count, loff_t pos);
+
+typedef __kernel_ssize_t32 ssize_t32;
+
+asmlinkage ssize_t32
+sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count,
+	    u32 poshi, u32 poslo)
+{
+	return sys_pread(fd, ubuf, count,
+			 ((loff_t)AA(poshi) << 32) | AA(poslo));
+}
+
+asmlinkage ssize_t32
+sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count,
+	     u32 poshi, u32 poslo)
+{
+	return sys_pwrite(fd, ubuf, count,
+			  ((loff_t)AA(poshi) << 32) | AA(poslo));
+}
+
+
+extern asmlinkage int sys_personality(unsigned long);
+
+asmlinkage int
+sys32_personality(unsigned long personality)
+{
+	int ret;
+	lock_kernel();
+	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+		personality = PER_LINUX32;
+	ret = sys_personality(personality);
+	unlock_kernel();
+	if (ret == PER_LINUX32)
+		ret = PER_LINUX;
+	return ret;
+}
+
+extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset,
+				       size_t count); 
+
+asmlinkage int
+sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
+{
+	mm_segment_t old_fs = get_fs();
+	int ret;
+	off_t of;
+	
+	if (offset && get_user(of, offset))
+		return -EFAULT;
+		
+	set_fs(KERNEL_DS);
+	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+	set_fs(old_fs);
+	
+	if (!ret && offset && put_user(of, offset))
+		return -EFAULT;
+		
+	return ret;
+}
+
+/* Handle adjtimex compatability. */
+
+struct timex32 {
+	u32 modes;
+	s32 offset, freq, maxerror, esterror;
+	s32 status, constant, precision, tolerance;
+	struct timeval32 time;
+	s32 tick;
+	s32 ppsfreq, jitter, shift, stabil;
+	s32 jitcnt, calcnt, errcnt, stbcnt;
+	s32  :32; s32  :32; s32  :32; s32  :32;
+	s32  :32; s32  :32; s32  :32; s32  :32;
+	s32  :32; s32  :32; s32  :32; s32  :32;
+};
+
+extern int do_adjtimex(struct timex *);
+
+asmlinkage int
+sys32_adjtimex(struct timex32 *utp)
+{
+	struct timex txc;
+	int ret;
+
+	memset(&txc, 0, sizeof(struct timex));
+
+	if(get_user(txc.modes, &utp->modes) ||
+	   __get_user(txc.offset, &utp->offset) ||
+	   __get_user(txc.freq, &utp->freq) ||
+	   __get_user(txc.maxerror, &utp->maxerror) ||
+	   __get_user(txc.esterror, &utp->esterror) ||
+	   __get_user(txc.status, &utp->status) ||
+	   __get_user(txc.constant, &utp->constant) ||
+	   __get_user(txc.precision, &utp->precision) ||
+	   __get_user(txc.tolerance, &utp->tolerance) ||
+	   __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+	   __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+	   __get_user(txc.tick, &utp->tick) ||
+	   __get_user(txc.ppsfreq, &utp->ppsfreq) ||
+	   __get_user(txc.jitter, &utp->jitter) ||
+	   __get_user(txc.shift, &utp->shift) ||
+	   __get_user(txc.stabil, &utp->stabil) ||
+	   __get_user(txc.jitcnt, &utp->jitcnt) ||
+	   __get_user(txc.calcnt, &utp->calcnt) ||
+	   __get_user(txc.errcnt, &utp->errcnt) ||
+	   __get_user(txc.stbcnt, &utp->stbcnt))
+		return -EFAULT;
+
+	ret = do_adjtimex(&txc);
+
+	if(put_user(txc.modes, &utp->modes) ||
+	   __put_user(txc.offset, &utp->offset) ||
+	   __put_user(txc.freq, &utp->freq) ||
+	   __put_user(txc.maxerror, &utp->maxerror) ||
+	   __put_user(txc.esterror, &utp->esterror) ||
+	   __put_user(txc.status, &utp->status) ||
+	   __put_user(txc.constant, &utp->constant) ||
+	   __put_user(txc.precision, &utp->precision) ||
+	   __put_user(txc.tolerance, &utp->tolerance) ||
+	   __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+	   __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+	   __put_user(txc.tick, &utp->tick) ||
+	   __put_user(txc.ppsfreq, &utp->ppsfreq) ||
+	   __put_user(txc.jitter, &utp->jitter) ||
+	   __put_user(txc.shift, &utp->shift) ||
+	   __put_user(txc.stabil, &utp->stabil) ||
+	   __put_user(txc.jitcnt, &utp->jitcnt) ||
+	   __put_user(txc.calcnt, &utp->calcnt) ||
+	   __put_user(txc.errcnt, &utp->errcnt) ||
+	   __put_user(txc.stbcnt, &utp->stbcnt))
+		ret = -EFAULT;
+
+	return ret;
+}
+#endif	// NOTYET
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kdb/Makefile linux/arch/ia64/kdb/Makefile
--- v2.3.42/linux/arch/ia64/kdb/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kdb/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,21 @@
+#
+# Makefile for ia64-specific kdb files..
+#
+#  Copyright 1999, Silicon Graphics Inc.
+#
+#  Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+#  Code for IA64 written by Goutham Rao <goutham.rao@intel.com> and
+#  Sreenivas Subramoney <sreenivas.subramoney@intel.com>
+#
+
+SUB_DIRS     :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+L_TARGET = kdb.a
+L_OBJS  = kdbsupport.o kdb_io.o kdb_bt.o kdb_traps.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kdb/kdb_bt.c linux/arch/ia64/kdb/kdb_bt.c
--- v2.3.42/linux/arch/ia64/kdb/kdb_bt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kdb/kdb_bt.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,104 @@
+/**
+ * Minimalist Kernel Debugger 
+ * Machine dependent stack traceback code for IA-64.
+ *
+ * Copyright (C) 1999 Goutham Rao <goutham.rao@intel.com>
+ * Copyright (C) 1999 Sreenivas Subramoney <sreenivas.subramoney@intel.com>
+ * Intel Corporation, August 1999.
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 99/12/03 D. Mosberger	Reimplemented based on <asm-ia64/unwind.h> API.
+ * 99/12/06 D. Mosberger	Added support for backtracing other processes.
+ */
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kdb.h>
+#include <asm/system.h>
+#include <asm/current.h>
+#include <asm/kdbsupport.h>
+
+/*
+ * Minimal stack back trace functionality.
+ */
+int
+kdb_bt (int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	struct task_struct *task = current;
+	struct ia64_frame_info info;
+	char *name;
+	int diag;
+
+	if (strcmp(argv[0], "btp") == 0) {
+		unsigned long pid;
+
+		diag = kdbgetularg(argv[1], &pid);
+		if (diag)
+			return diag;
+
+		task = find_task_by_pid(pid);
+		if (!task) {
+			kdb_printf("No process with pid == %d found\n", pid);
+			return 0;
+		}
+		regs = ia64_task_regs(task);
+	} else if (argc) {
+		kdb_printf("bt <address> is unsupported for IA-64\n");
+		return 0;
+	}
+
+	if (task == current) {
+		/*
+		 * Upon entering kdb, the stack frame looks like this:
+		 *
+		 *	+---------------------+
+		 *	|   struct pt_regs    |
+		 *	+---------------------+
+		 *	|		      |
+		 *	|   kernel stack      |
+		 *	|		      |
+		 *	+=====================+ <--- top of stack upon entering kdb
+		 *	|   struct pt_regs    |
+		 *	+---------------------+
+		 *	| struct switch_stack |
+		 *	+---------------------+
+		 */
+		if (user_mode(regs)) {
+			/* We are not implementing stack backtrace from user mode code */
+			kdb_printf ("Not in Kernel\n");
+			return 0;
+		}
+		ia64_unwind_init_from_current(&info, regs);
+	} else {
+		/*
+		 * For a blocked task, the stack frame looks like this:
+		 *
+		 *	+---------------------+
+		 *	|   struct pt_regs    |
+		 *	+---------------------+
+		 *	|		      |
+		 *	|   kernel stack      |
+		 *	|		      |
+		 *	+---------------------+
+		 *	| struct switch_stack |
+		 *	+=====================+ <--- task->thread.ksp
+		 */
+		ia64_unwind_init_from_blocked_task(&info, task);
+	}
+
+	kdb_printf("Ret Address           Reg Stack base       Name\n\n") ;
+	do {
+		unsigned long ip = ia64_unwind_get_ip(&info);
+
+		name = kdbnearsym(ip);
+		if (!name) {
+			kdb_printf("Interrupt\n");
+			return 0;
+		}
+		kdb_printf("0x%016lx: [0x%016lx] %s\n", ip, ia64_unwind_get_bsp(&info), name);
+	} while (ia64_unwind_to_previous_frame(&info) >= 0);
+	return 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kdb/kdb_io.c linux/arch/ia64/kdb/kdb_io.c
--- v2.3.42/linux/arch/ia64/kdb/kdb_io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kdb/kdb_io.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,350 @@
+/*
+ * Kernel Debugger Console I/O handler
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) Scott Lurndal (slurn@engr.sgi.com)
+ * Copyright (C) Scott Foehner (sfoehner@engr.sgi.com)
+ * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ *
+ * Modifications from:
+ *	Chuck Fleckenstein		1999/07/20
+ *		Move kdb_info struct declaration to this file
+ *		for cases where serial support is not compiled into
+ *		the kernel.
+ *
+ *	Masahiro Adegawa		1999/07/20
+ *		Handle some peculiarities of japanese 86/106
+ *		keyboards.
+ *
+ *	marc@mucom.co.il		1999/07/20
+ *		Catch buffer overflow for serial input.
+ *
+ *      Scott Foehner  
+ *              Port to ia64
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+
+#include "pc_keyb.h"
+
+int kdb_port = 0;
+
+/*
+ * This module contains code to read characters from the keyboard or a serial
+ * port.
+ * 
+ * It is used by the kernel debugger, and is polled, not interrupt driven.
+ *
+ */
+
+/*
+ * send:  Send a byte to the keyboard controller.  Used primarily to 
+ * 	  alter LED settings.
+ */
+
+static void
+kdb_kbdsend(unsigned char byte) 
+{
+	while (inb(KBD_STATUS_REG) & KBD_STAT_IBF)
+		;
+	outb(KBD_DATA_REG, byte);
+}
+
+static void
+kdb_kbdsetled(int leds)
+{
+	kdb_kbdsend(KBD_CMD_SET_LEDS);
+	kdb_kbdsend((unsigned char)leds);
+}
+
+static void
+console_read (char *buffer, size_t bufsize)
+{
+	struct console *in;
+	struct console *out;
+	char *cp, ch;
+
+	for (in = console_drivers; in; in = in->next) {
+		if ((in->flags & CON_ENABLED) && (in->read || in->wait_key))
+			break;
+	}
+	for (out = console_drivers; out; out = out->next) {
+		if ((out->flags & CON_ENABLED) && out->write)
+			break;
+	}
+
+	if ((!in->read && !in->wait_key) || !out->write) {
+		panic("kdb_io: can't do console i/o!");
+	}
+
+	if (in->read) {
+		/* this is untested... */
+		(*in->read)(in, buffer, bufsize);
+		return;
+	}
+
+	bufsize -= 2;			/* leave room for CR & NUL terminator */
+	cp = buffer;
+	while (1) {
+		ch = (*in->wait_key)(in);
+		switch (ch) {
+		      case '\b':
+			if (cp > buffer) {
+				--cp, ++bufsize;
+				(*out->write)(out, "\b \b", 3);
+			}
+			break;
+
+		      case '\025':
+			while (cp > buffer) {
+				--cp, ++bufsize;
+				(*out->write)(out, "\b \b", 3);
+			}
+			break;
+
+		      case '\r':
+		      case '\n':
+			(*out->write)(out, "\r\n", 2);
+			*cp++ = '\n';
+			*cp++ = '\0';
+			return;
+
+		      default:
+			if (bufsize > 0) {
+				(*out->write)(out, &ch, 1);
+				--bufsize;
+				*cp++ = ch;
+			}
+			break;
+		}
+	}
+}
+
+char *
+kdb_getscancode(char *buffer, size_t bufsize)
+{
+	/*
+	 * XXX Shouldn't kdb _always_ use console based I/O?  That's what the console
+	 * abstraction is for, after all... ---davidm
+	 */
+#ifdef CONFIG_IA64_HP_SIM
+	extern spinlock_t console_lock;
+	unsigned long flags;
+
+	spin_lock_irqsave(&console_lock, flags);
+	console_read(buffer, bufsize);
+	spin_unlock_irqrestore(&console_lock, flags);
+	return buffer;
+#else /* !CONFIG_IA64_HP_SIM */
+	char	*cp = buffer;
+	int	scancode, scanstatus;
+	static int shift_lock = 0;	/* CAPS LOCK state (0-off, 1-on) */
+	static int shift_key  = 0;	/* Shift next keypress */
+	static int ctrl_key   = 0;
+	static int leds       = 2;	/* Num lock */
+	u_short keychar;
+	extern u_short plain_map[], shift_map[], ctrl_map[];
+
+	bufsize -= 2;	/* Reserve space for newline and null byte */
+
+	/*
+	 * If we came in via a serial console, we allow that to
+	 * be the input window for kdb.
+	 */
+	if (kdb_port != 0) {
+		char ch;
+		int status;
+#define serial_inp(info, offset) inb((info) + (offset))
+#define serial_out(info, offset, v) outb((v), (info) + (offset))
+
+		while(1) {
+			while ((status = serial_inp(kdb_port, UART_LSR)) 
+							& UART_LSR_DR) {
+readchar:
+				ch = serial_inp(kdb_port, UART_RX);
+				if (ch == 8) {		/* BS */
+					if (cp > buffer) {
+						--cp, bufsize++;
+						printk("%c %c", 0x08, 0x08);
+					}
+					continue;
+				}
+				serial_out(kdb_port, UART_TX, ch);
+				if (ch == 13) {		/* CR */
+					*cp++ = '\n';
+					*cp++ = '\0';
+					serial_out(kdb_port, UART_TX, 10);
+					return(buffer);
+				}
+				/*
+				 * Discard excess characters
+				 */
+				if (bufsize > 0) {
+					*cp++ = ch;
+					bufsize--;
+				} 
+			}
+			while (((status = serial_inp(kdb_port, UART_LSR)) 
+					& UART_LSR_DR) == 0);
+		}
+	}
+
+	while (1) {
+
+		/*
+		 * Wait for a valid scancode
+		 */
+
+		while ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0)
+			;
+
+		/*
+		 * Fetch the scancode
+		 */
+		scancode = inb(KBD_DATA_REG);
+		scanstatus = inb(KBD_STATUS_REG);
+
+		/*
+		 * Ignore mouse events.
+		 */
+		if (scanstatus & KBD_STAT_MOUSE_OBF)
+			continue;
+
+		/*
+		 * Ignore release, trigger on make
+		 * (except for shift keys, where we want to 
+		 *  keep the shift state so long as the key is
+		 *  held down).
+		 */
+
+		if (((scancode&0x7f) == 0x2a) 
+		 || ((scancode&0x7f) == 0x36)) {
+			/*
+			 * Next key may use shift table
+			 */
+			if ((scancode & 0x80) == 0) {
+				shift_key=1;
+			} else {
+				shift_key=0;
+			}
+			continue;
+		}
+
+		if ((scancode&0x7f) == 0x1d) {
+			/*
+			 * Left ctrl key
+			 */
+			if ((scancode & 0x80) == 0) {
+				ctrl_key = 1;
+			} else {
+				ctrl_key = 0;
+			}
+			continue;
+		}
+
+		if ((scancode & 0x80) != 0) 
+			continue;
+
+		scancode &= 0x7f;
+
+		/*
+	 	 * Translate scancode
+		 */
+		
+		if (scancode == 0x3a) {
+			/*
+			 * Toggle caps lock
+			 */
+			shift_lock ^= 1;
+			leds ^= 0x4;	/* toggle caps lock led */
+			
+			kdb_kbdsetled(leds);
+			continue;
+		}
+			
+		if (scancode == 0x0e) {
+			/*
+			 * Backspace
+			 */
+			if (cp > buffer) {
+				--cp, bufsize++;
+
+				/*
+				 * XXX - erase character on screen
+				 */
+				printk("%c %c", 0x08, 0x08);
+			}
+			continue;
+		}
+	
+		if (scancode == 0xe0) {
+			continue;
+		}
+
+		/*
+		 * For Japanese 86/106 keyboards 
+		 * 	See comment in drivers/char/pc_keyb.c.
+		 * 	- Masahiro Adegawa
+		 */
+		if (scancode == 0x73) {
+			scancode = 0x59;
+		} else if (scancode == 0x7d) {
+			scancode = 0x7c;
+		}
+			
+		if (!shift_lock && !shift_key) {
+			keychar = plain_map[scancode];
+		} else if (shift_lock || shift_key) {
+			keychar = shift_map[scancode];
+		} else if (ctrl_key) {
+			keychar = ctrl_map[scancode];
+		} else {
+			keychar = 0x0020;
+			printk("Unknown state/scancode (%d)\n", scancode);
+		}
+		 
+		if ((scancode & 0x7f) == 0x1c) {
+			/*
+			 * enter key.  All done.
+			 */
+			printk("\n");
+			break;
+		}
+
+		/*
+		 * echo the character.
+		 */
+		printk("%c", keychar&0xff);
+
+		if (bufsize) {
+			--bufsize;
+			*cp++ = keychar&0xff;
+		} else {
+			printk("buffer overflow\n");
+			break;
+		}
+
+	}
+
+	*cp++ = '\n';		/* White space for parser */
+	*cp++ = '\0';		/* String termination */
+
+#if defined(NOTNOW)
+	cp = buffer;
+	while (*cp) {
+		printk("char 0x%x\n", *cp++);
+	}
+#endif
+
+	return buffer;
+#endif /* !CONFIG_IA64_HP_SIM */
+}
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kdb/kdb_traps.c linux/arch/ia64/kdb/kdb_traps.c
--- v2.3.42/linux/arch/ia64/kdb/kdb_traps.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kdb/kdb_traps.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,55 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kdb.h>
+
+static struct kdb_bp_support {
+	unsigned long	addr ;
+	int		slot ;
+} kdb_bp_info[NR_CPUS] ;
+
+
+extern void kdb_bp_install (void);
+
+/*
+ * This gets invoked right before a call to ia64_fault().
+ * Returns zero the normal fault handler should be invoked.
+ */
+long
+ia64_kdb_fault_handler (unsigned long vector, unsigned long isr, unsigned long ifa,
+			unsigned long iim, unsigned long itir, unsigned long arg5,
+			unsigned long arg6, unsigned long arg7, unsigned long stack)
+{
+	struct switch_stack *sw = (struct switch_stack *) &stack;
+	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+	int bundle_slot;
+
+	/*
+	 * TBD
+	 * If KDB is configured, enter KDB for any fault.
+	 */
+	if ((vector == 29) || (vector == 35) || (vector == 36)) {
+		if (!user_mode(regs)) {
+			bundle_slot = ia64_psr(regs)->ri;
+			if (vector == 29) {
+				if (bundle_slot == 0) {
+			 		kdb_bp_info[0].addr = regs->cr_iip;
+					kdb_bp_info[0].slot = bundle_slot;
+					kdb(KDB_REASON_FLTDBG, 0, regs);
+				} else {
+					if ((bundle_slot < 3) &&
+					    (kdb_bp_info[0].addr == regs->cr_iip))
+					{
+						ia64_psr(regs)->id = 1;
+						ia64_psr(regs)->db = 1;
+						kdb_bp_install() ;
+					} else /* some error ?? */
+						kdb(KDB_REASON_FLTDBG, 0, regs);
+				}
+			} else /* single step or taken branch */
+				kdb(KDB_REASON_DEBUG, 0, regs);
+			return 1;
+		}
+	}
+	return 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kdb/kdbsupport.c linux/arch/ia64/kdb/kdbsupport.c
--- v2.3.42/linux/arch/ia64/kdb/kdbsupport.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kdb/kdbsupport.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,1310 @@
+/*
+ * Minimalist Kernel Debugger
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) Scott Lurndal (slurn@engr.sgi.com)
+ * Copyright (C) Scott Foehner (sfoehner@engr.sgi.com)
+ * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+ * Copyright (C) David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ *
+ * Modifications from:
+ *      Richard Bass                    1999/07/20
+ *              Many bug fixes and enhancements.
+ *      Scott Foehner
+ *              Port to ia64
+ *      Srinivasa Thirumalachar
+ *              RSE support for ia64
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kdb.h>
+#include <linux/stddef.h> 
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/kdbsupport.h>
+#include <asm/rse.h>
+
+extern kdb_state_t kdb_state ;
+k_machreg_t dbregs[KDB_DBREGS];
+
+static int __init
+kdb_setup (char *str)
+{
+	kdb_flags |= KDB_FLAG_EARLYKDB;
+	return 1;
+}
+
+__setup("kdb", kdb_setup);
+
+static int
+kdb_ia64_sir (int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+	u64 lid, tpr, lrr0, lrr1, itv, pmv, cmcv;
+
+	asm ("mov %0=cr.lid" : "=r"(lid));
+	asm ("mov %0=cr.tpr" : "=r"(tpr));
+	asm ("mov %0=cr.lrr0" : "=r"(lrr0));
+	asm ("mov %0=cr.lrr1" : "=r"(lrr1));
+	printk ("lid=0x%lx, tpr=0x%lx, lrr0=0x%lx, llr1=0x%lx\n", lid, tpr, lrr0, lrr1);
+
+	asm ("mov %0=cr.itv" : "=r"(itv));
+	asm ("mov %0=cr.pmv" : "=r"(pmv));
+	asm ("mov %0=cr.cmcv" : "=r"(cmcv));
+	printk ("itv=0x%lx, pmv=0x%lx, cmcv=0x%lx\n", itv, pmv, cmcv);
+
+	printk ("irr=0x%016lx,0x%016lx,0x%016lx,0x%016lx\n",
+		ia64_get_irr0(), ia64_get_irr1(), ia64_get_irr2(), ia64_get_irr3());
+	return 0;
+}
+
+void __init
+kdb_init (void)
+{
+	extern void kdb_inittab(void);
+	unsigned long reg;
+
+	kdb_inittab();
+	kdb_initbptab();
+#if 0
+	kdb_disinit();
+#endif
+	kdb_printf("kdb version %d.%d by Scott Lurndal. "\
+		   "Copyright SGI, All Rights Reserved\n",
+		   KDB_MAJOR_VERSION, KDB_MINOR_VERSION);
+
+	/* Enable debug registers */
+        __asm__ ("mov %0=psr":"=r"(reg));
+        reg |= IA64_PSR_DB;
+        __asm__ ("mov psr.l=%0"::"r"(reg));
+        ia64_srlz_d();
+
+	/* Init kdb state */
+	kdb_state.bkpt_handling_state = BKPTSTATE_NOT_HANDLED ;
+
+	kdb_register("irr", kdb_ia64_sir, "", "Show interrupt registers", 0);
+}
+
+/*
+ * kdbprintf
+ * kdbgetword
+ * kdb_getstr
+ */
+
+char *
+kbd_getstr(char *buffer, size_t bufsize, char *prompt)
+{
+	extern char* kdb_getscancode(char *, size_t);
+
+#if defined(CONFIG_SMP)
+	kdb_printf(prompt, smp_processor_id());
+#else
+	kdb_printf("%s", prompt);
+#endif
+
+	return kdb_getscancode(buffer, bufsize);
+
+}
+
+int
+kdb_printf(const char *fmt, ...)
+{
+	char buffer[256];
+	va_list	ap;
+	int diag;
+	int linecount;
+
+	diag = kdbgetintenv("LINES", &linecount);
+	if (diag) 
+		linecount = 22;
+
+	va_start(ap, fmt);
+	vsprintf(buffer, fmt, ap);
+	va_end(ap);
+
+	printk("%s", buffer);
+#if 0
+	if (strchr(buffer, '\n') != NULL) {
+		kdb_nextline++;
+	}
+
+	if (kdb_nextline == linecount) {
+		char buf1[16];
+		char buf2[32];
+		extern char* kdb_getscancode(char *, size_t);
+		char *moreprompt;
+
+		/*
+		 * Pause until cr.
+		 */
+		moreprompt = kdbgetenv("MOREPROMPT");
+		if (moreprompt == NULL) {
+			moreprompt = "more> ";
+		}
+
+#if defined(CONFIG_SMP)
+		if (strchr(moreprompt, '%')) {
+			sprintf(buf2, moreprompt, smp_processor_id());
+			moreprompt = buf2;
+		}
+#endif
+
+		printk(moreprompt);
+		(void) kdb_getscancode(buf1, sizeof(buf1));
+
+		kdb_nextline = 1;
+
+		if ((buf1[0] == 'q') 
+		 || (buf1[0] == 'Q')) {
+			kdb_longjmp(&kdbjmpbuf, 1);
+		}
+	}
+#endif	
+	return 0;
+}
+
+unsigned long
+kdbgetword(unsigned long addr, int width)
+{
+	/*
+	 * This function checks the address for validity.  Any address
+	 * in the range PAGE_OFFSET to high_memory is legal, any address
+	 * which maps to a vmalloc region is legal, and any address which
+	 * is a user address, we use get_user() to verify validity.
+	 */
+
+	if (addr < PAGE_OFFSET) {
+		/*
+		 * Usermode address.
+		 */
+		unsigned long diag;
+		unsigned long ulval;
+
+		switch (width) {
+	        case 8:
+		{	unsigned long *lp;
+
+			lp = (unsigned long *) addr;
+			diag = get_user(ulval, lp);
+			break;
+		}
+		case 4:
+		{	unsigned int *ip;
+
+			ip = (unsigned int *) addr;
+			diag = get_user(ulval, ip);
+			break;
+		}
+		case 2:
+		{	unsigned short *sp;
+
+			sp = (unsigned short *) addr;
+			diag = get_user(ulval, sp);
+			break;
+		}
+		case 1:
+		{	unsigned char *cp;
+
+			cp = (unsigned char *) addr;
+			diag = get_user(ulval, cp);
+			break;
+		}
+		default:
+			printk("kdbgetword: Bad width\n");
+			return 0L;
+		}
+			
+		if (diag) {
+			if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) {
+				printk("kdb: Bad user address 0x%lx\n", addr);
+				kdb_flags |= KDB_FLAG_SUPRESS;
+			}
+			return 0L;
+		}
+		kdb_flags &= ~KDB_FLAG_SUPRESS;
+		return ulval;
+	}
+
+	if (addr > (unsigned long)high_memory) {
+		extern int kdb_vmlist_check(unsigned long, unsigned long);
+
+		if (!kdb_vmlist_check(addr, addr+width)) {
+			/*
+			 * Would appear to be an illegal kernel address; 
+			 * Print a message once, and don't print again until
+			 * a legal address is used.
+			 */
+			if ((kdb_flags & KDB_FLAG_SUPRESS) == 0) {
+				printk("kdb: Bad kernel address 0x%lx\n", addr);
+				kdb_flags |= KDB_FLAG_SUPRESS;
+			}
+			return 0L;
+		}
+	}
+
+	/*
+	 * A good address.  Reset error flag.
+	 */
+	kdb_flags &= ~KDB_FLAG_SUPRESS;
+
+	switch (width) {
+	case 8:
+	{	unsigned long *lp;
+
+		lp = (unsigned long *)(addr);
+		return *lp;
+	}
+	case 4:
+	{	unsigned int *ip;
+
+		ip = (unsigned int *)(addr);
+		return *ip;
+	}
+	case 2:
+	{	unsigned short *sp;
+
+		sp = (unsigned short *)(addr);
+		return *sp;
+	}
+	case 1:
+	{	unsigned char *cp;
+
+		cp = (unsigned char *)(addr);
+		return *cp;
+	}
+	}
+
+	printk("kdbgetword: Bad width\n");
+	return 0L;
+}
+
+/*
+ * Start of breakpoint management routines
+ */
+
+/*
+ * Arg: bp structure
+ */
+
+int
+kdb_allocdbreg(kdb_bp_t *bp)
+{
+	int i=0;
+
+	/* For inst bkpt, just return. No hw reg alloc to be done. */
+
+	if (bp->bp_mode == BKPTMODE_INST) {
+		return i;
+	} else if (bp->bp_mode == BKPTMODE_DATAW) {
+		for(i=0; i<KDB_DBREGS; i++) {
+			if (dbregs[i] == 0xffffffff) {
+				dbregs[i] = 0;
+				return i;
+			}
+		}
+	}
+
+	return -1;
+}
+
+void
+kdb_freedbreg(kdb_bp_t *bp)
+{
+	if (bp->bp_mode == BKPTMODE_DATAW)
+		dbregs[bp->bp_reg] = 0xffffffff;
+}
+
+void
+kdb_initdbregs(void)
+{
+	int i;
+
+	for(i=0; i<KDB_DBREGS; i++) {
+		dbregs[i] = 0xffffffff;
+	}
+}
+int
+kdbinstalltrap(int type, handler_t newh, handler_t *oldh)
+{
+	/*
+	 * Usurp INTn.  XXX - TBD.
+	 */
+
+	return 0;
+}
+
+int
+install_instbkpt(kdb_bp_t *bp)
+{
+	unsigned long	*addr = (unsigned long *)bp->bp_addr ;
+	bundle_t	*bundle = (bundle_t *)bp->bp_longinst;
+
+	/* save current bundle */
+	*bundle = *(bundle_t *)addr ;
+
+	/* Set the break point! */
+	((bundle_t *)addr)->lform.low8 = (
+		(((bundle_t *)addr)->lform.low8 & ~INST_SLOT0_MASK) |
+		BREAK_INSTR);
+
+	/* set flag */
+	bp->bp_instvalid = 1 ;
+
+	/* flush icache as it is stale now */
+	ia64_flush_icache_page((unsigned long)addr) ;
+
+#ifdef KDB_DEBUG
+	kdb_printf ("[0x%016lx]: install 0x%016lx with 0x%016lx\n",
+		    addr, bundle->lform.low8, addr[0]) ;
+#endif
+	return 0 ;
+}
+
+int
+install_databkpt(kdb_bp_t *bp)
+{
+	unsigned long dbreg_addr = bp->bp_reg * 2;
+	unsigned long dbreg_cond = dbreg_addr + 1;
+	unsigned long value = 0x8fffffffffffffff;
+	unsigned long addr = (unsigned long)bp->bp_addr;
+	__asm__ ("mov dbr[%0]=%1"::"r"(dbreg_cond),"r"(value));
+//	__asm__ ("movl %0,%%db0\n\t"::"r"(contents));
+	__asm__ ("mov dbr[%0]=%1"::"r"(dbreg_addr),"r"(addr));
+	ia64_insn_group_barrier();
+	ia64_srlz_i();
+	ia64_insn_group_barrier();
+
+#ifdef KDB_DEBUG
+	kdb_printf("installed dbkpt at 0x%016lx\n", addr) ;
+#endif
+	return 0;
+}
+
+int
+kdbinstalldbreg(kdb_bp_t *bp)
+{
+	if (bp->bp_mode == BKPTMODE_INST) {
+		return install_instbkpt(bp) ;
+	} else if (bp->bp_mode == BKPTMODE_DATAW) {
+		return install_databkpt(bp) ;
+	}
+	return 0;
+}
+
+void
+remove_instbkpt(kdb_bp_t *bp)
+{
+	unsigned long   *addr = (unsigned long *)bp->bp_addr ;
+	bundle_t        *bundle = (bundle_t *)bp->bp_longinst;
+
+	if (!bp->bp_instvalid)
+	/* Nothing to remove. If we just alloced the bkpt
+	 * but never resumed, the bp_inst will not be valid. */
+		return ;
+
+#ifdef KDB_DEBUG
+	kdb_printf ("[0x%016lx]: remove 0x%016lx with 0x%016lx\n", 
+		    addr, addr[0], bundle->lform.low8) ;
+#endif
+
+	/* restore current bundle */
+	*(bundle_t *)addr = *bundle ;
+	/* reset the flag */
+	bp->bp_instvalid = 0 ;
+	ia64_flush_icache_page((unsigned long)addr) ;
+}
+  
+void
+remove_databkpt(kdb_bp_t *bp)
+{
+	int		regnum = bp->bp_reg ;
+	unsigned long dbreg_addr = regnum * 2;
+	unsigned long dbreg_cond = dbreg_addr + 1;
+	unsigned long value = 0x0fffffffffffffff;
+	__asm__ ("mov dbr[%0]=%1"::"r"(dbreg_cond),"r"(value));
+//	__asm__ ("movl %0,%%db0\n\t"::"r"(contents));
+	ia64_insn_group_barrier();
+	ia64_srlz_i();
+	ia64_insn_group_barrier();
+
+#ifdef KDB_DEBUG
+	kdb_printf("removed dbkpt at 0x%016lx\n", bp->bp_addr) ;
+#endif
+}
+
+void
+kdbremovedbreg(kdb_bp_t *bp)
+{
+	if (bp->bp_mode == BKPTMODE_INST) {
+		remove_instbkpt(bp) ;
+	} else if (bp->bp_mode == BKPTMODE_DATAW) {
+		remove_databkpt(bp) ;
+	}
+}
+
+k_machreg_t
+kdb_getdr6(void)
+{
+	return kdb_getdr(6);
+}
+
+k_machreg_t
+kdb_getdr7(void)
+{
+	return kdb_getdr(7);
+}
+
+k_machreg_t
+kdb_getdr(int regnum)
+{
+	k_machreg_t contents = 0;
+	unsigned long reg = (unsigned long)regnum;
+
+	__asm__ ("mov %0=ibr[%1]"::"r"(contents),"r"(reg));
+//        __asm__ ("mov ibr[%0]=%1"::"r"(dbreg_cond),"r"(value));	
+
+	return contents;
+}
+
+
+k_machreg_t
+kdb_getcr(int regnum)
+{
+	k_machreg_t contents = 0;
+	return contents;
+}
+
+void
+kdb_putdr6(k_machreg_t contents)
+{
+	kdb_putdr(6, contents);
+}
+
+void
+kdb_putdr7(k_machreg_t contents)
+{
+	kdb_putdr(7, contents);
+}
+
+void
+kdb_putdr(int regnum, k_machreg_t contents)
+{
+}
+
+void
+get_fault_regs(fault_regs_t *fr)
+{
+	fr->ifa = 0 ;
+	fr->isr = 0 ;
+
+	__asm__ ("rsm psr.ic;;") ;
+        ia64_srlz_d();
+        __asm__ ("mov %0=cr.ifa" : "=r"(fr->ifa));
+        __asm__ ("mov %0=cr.isr" : "=r"(fr->isr));
+	__asm__ ("ssm psr.ic;;") ;
+        ia64_srlz_d();
+}
+
+/*
+ * kdb_db_trap
+ *
+ * 	Perform breakpoint processing upon entry to the
+ *	processor debugger fault.   Determine and print
+ *	the active breakpoint.
+ *
+ * Parameters:
+ *	ef	Exception frame containing machine register state
+ *	reason	Why did we enter kdb - fault or break
+ * Outputs:
+ *	None.
+ * Returns:
+ *	0	Standard instruction or data breakpoint encountered
+ *	1	Single Step fault ('ss' command)
+ *	2	Single Step fault, caller should continue ('ssb' command)
+ * Locking:
+ *	None.
+ * Remarks:
+ *	Yup, there be goto's here.
+ */
+
+int
+kdb_db_trap(struct pt_regs *ef, int reason)
+{
+	int i, rv=0;
+
+	/* Trying very hard to not change the interface to kdb.
+	 * So, eventhough we have these values in the fault function
+	 * it is not passed in but read again.
+	 */
+	fault_regs_t	faultregs ;
+
+	if (reason == KDB_REASON_FLTDBG)
+		get_fault_regs(&faultregs) ;
+
+	/* NOTE : XXX: This has to be done only for data bkpts */
+	/* Prevent it from continuously faulting */
+	ef->cr_ipsr |= 0x0000002000000000;
+
+	if (ef->cr_ipsr & 0x0000010000000000) {
+		/* single step */
+		ef->cr_ipsr &= 0xfffffeffffffffff;
+		if ((kdb_state.bkpt_handling_state == BKPTSTATE_HANDLED) 
+			&& (kdb_state.cmd_given == CMDGIVEN_GO)) 
+				; 
+		else
+			kdb_printf("SS trap at 0x%lx\n", ef->cr_iip + ia64_psr(ef)->ri);
+		rv = 1;
+		kdb_state.reason_for_entry = ENTRYREASON_SSTEP ;
+		goto handled;
+	} else
+		kdb_state.reason_for_entry = ENTRYREASON_GO ;
+
+        /*
+         * Determine which breakpoint was encountered.
+         */
+        for(i=0; i<KDB_MAXBPT; i++) {
+                if ((breakpoints[i].bp_enabled)
+                 && ((breakpoints[i].bp_addr == ef->cr_iip) ||
+			((faultregs.ifa) && 
+			 (breakpoints[i].bp_addr == faultregs.ifa)))) {
+                        /*
+                         * Hit this breakpoint.  Remove it while we are
+                         * handling hit to avoid recursion. XXX ??
+                         */
+			if (breakpoints[i].bp_addr == faultregs.ifa)
+                        	kdb_printf("Data breakpoint #%d for 0x%lx at 0x%lx\n",
+                                  i, breakpoints[i].bp_addr, ef->cr_iip + ia64_psr(ef)->ri);
+			else
+                        	kdb_printf("%s breakpoint #%d at 0x%lx\n",
+                                  	rwtypes[0],
+                                  	i, breakpoints[i].bp_addr);
+
+                        /*
+                         * For an instruction breakpoint, disassemble
+                         * the current instruction.
+                         */
+#if 0
+                        if (rw == 0) {
+                                kdb_id1(ef->eip);
+                        }
+#endif
+
+                        goto handled;
+                }
+        }
+
+#if 0
+unknown:
+#endif
+        kdb_printf("Unknown breakpoint.  Should forward. \n");
+	/* Need a flag for this. The skip should be done XXX
+	 * when a go or single step command is done for this session.
+	 * For now it is here.
+ 	 */
+	ia64_increment_ip(ef) ;
+	return rv ;
+
+handled:
+
+	/* We are here after handling a break inst/data bkpt */
+	if (kdb_state.bkpt_handling_state == BKPTSTATE_NOT_HANDLED) {
+		kdb_state.bkpt_handling_state = BKPTSTATE_HANDLED ;
+		if (kdb_state.reason_for_entry == ENTRYREASON_GO) {
+			kdb_setsinglestep(ef) ;
+			kdb_state.kdb_action = ACTION_NOBPINSTALL; 
+			/* We dont want bp install just this once */
+			kdb_state.cmd_given = CMDGIVEN_UNKNOWN ;
+		}
+	} else if (kdb_state.bkpt_handling_state == BKPTSTATE_HANDLED) {
+                kdb_state.bkpt_handling_state = BKPTSTATE_NOT_HANDLED ;
+                if (kdb_state.reason_for_entry == ENTRYREASON_SSTEP) {
+			if (kdb_state.cmd_given == CMDGIVEN_GO)
+				kdb_state.kdb_action = ACTION_NOPROMPT ;
+			kdb_state.cmd_given = CMDGIVEN_UNKNOWN ;
+		}
+	} else
+		kdb_printf("Unknown value of bkpt state\n") ;
+
+	return rv;
+
+}
+
+void
+kdb_setsinglestep(struct pt_regs *regs)
+{
+	regs->cr_ipsr |= 0x0000010000000000;
+#if 0
+	regs->eflags |= EF_TF;
+#endif
+}
+
+/*
+ * Symbol table functions.
+ */
+
+/*
+ * kdbgetsym
+ *
+ *	Return the symbol table entry for the given symbol
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ * Outputs:
+ * Returns:
+ *	NULL	Symbol doesn't exist
+ *	ksp	Pointer to symbol table entry
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+__ksymtab_t *
+kdbgetsym(const char *symname)
+{
+	__ksymtab_t *ksp = __kdbsymtab;
+	int i;
+
+	if (symname == NULL)
+		return NULL;
+
+	for (i=0; i<__kdbsymtabsize; i++, ksp++) {
+		if (ksp->name && (strcmp(ksp->name, symname)==0)) {
+			return ksp;
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * kdbgetsymval
+ *
+ *	Return the address of the given symbol.
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ * Outputs:
+ * Returns:
+ *	0	Symbol name is NULL
+ *	addr	Address corresponding to symname
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+unsigned long
+kdbgetsymval(const char *symname)
+{
+	__ksymtab_t *ksp = kdbgetsym(symname);
+
+	return (ksp?ksp->value:0);
+}
+
+/*
+ * kdbaddmodsym
+ *
+ *	Add a symbol to the kernel debugger symbol table.  Called when
+ *	a new module is loaded into the kernel.
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ *	value	Value of symbol
+ * Outputs:
+ * Returns:
+ *	0	Successfully added to table.
+ *	1	Duplicate symbol
+ *	2	Symbol table full
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdbaddmodsym(char *symname, unsigned long value) 
+{
+
+	/*
+	 * Check for duplicate symbols.
+	 */
+	if (kdbgetsym(symname)) {
+		printk("kdb: Attempt to register duplicate symbol '%s' @ 0x%lx\n",
+			symname, value);
+		return 1;
+	}
+
+	if (__kdbsymtabsize < __kdbmaxsymtabsize) {
+		__ksymtab_t *ksp = &__kdbsymtab[__kdbsymtabsize++];
+		
+		ksp->name = symname;
+		ksp->value = value;
+		return 0;
+	}
+
+	/*
+	 * No room left in kernel symbol table.
+	 */
+	{
+		static int __kdbwarn = 0;
+
+		if (__kdbwarn == 0) {
+			__kdbwarn++;
+			printk("kdb: Exceeded symbol table size.  Increase CONFIG_KDB_SYMTAB_SIZE in kernel configuration\n");
+		}
+	}
+
+	return 2;
+}
+
+/*
+ * kdbdelmodsym
+ *
+ *	Add a symbol to the kernel debugger symbol table.  Called when
+ *	a new module is loaded into the kernel.
+ *
+ * Parameters:
+ * 	symname	Character string containing symbol name
+ *	value	Value of symbol
+ * Outputs:
+ * Returns:
+ *	0	Successfully added to table.
+ *	1	Symbol not found
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+int
+kdbdelmodsym(const char *symname)
+{
+	__ksymtab_t *ksp, *endksp;
+
+	if (symname == NULL)
+		return 1;
+
+	/*
+	 * Search for the symbol.  If found, move 
+	 * all successive symbols down one position
+	 * in the symbol table to avoid leaving holes.
+	 */
+	endksp = &__kdbsymtab[__kdbsymtabsize];
+	for (ksp = __kdbsymtab; ksp < endksp; ksp++) {
+		if (ksp->name && (strcmp(ksp->name, symname) == 0)) {
+			endksp--;
+			for ( ; ksp < endksp; ksp++) {
+				*ksp = *(ksp + 1);
+			}
+			__kdbsymtabsize--;
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * kdbnearsym
+ *
+ *	Return the name of the symbol with the nearest address
+ *	less than 'addr'.
+ *
+ * Parameters:
+ * 	addr	Address to check for symbol near
+ * Outputs:
+ * Returns:
+ *	NULL	No symbol with address less than 'addr'
+ *	symbol	Returns the actual name of the symbol.
+ * Locking:
+ *	None.
+ * Remarks:
+ */
+
+char *
+kdbnearsym(unsigned long addr)
+{
+	__ksymtab_t *ksp = __kdbsymtab;
+	__ksymtab_t *kpp = NULL;
+	int i;
+
+	for(i=0; i<__kdbsymtabsize; i++, ksp++) {
+		if (!ksp->name) 
+			continue;
+
+		if (addr == ksp->value) {
+			kpp = ksp;
+			break;
+		}
+		if (addr > ksp->value) {
+			if ((kpp == NULL) 
+			 || (ksp->value > kpp->value)) {
+				kpp = ksp;
+			}
+		}
+	}
+
+	/*
+	 * If more than 128k away, don't bother.
+	 */
+	if ((kpp == NULL)
+	 || ((addr - kpp->value) > 0x20000)) {
+		return NULL;
+	}
+
+	return kpp->name;
+}
+
+/*
+ * kdbgetregcontents
+ *
+ *	Return the contents of the register specified by the 
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ *	The following pseudo register names are supported:
+ *	   &regs	 - Prints address of exception frame
+ *	   kesp		 - Prints kernel stack pointer at time of fault
+ * 	   sstk		 - Prints switch stack for ia64
+ *	   %<regname>	 - Uses the value of the registers at the 
+ *			   last time the user process entered kernel
+ *			   mode, instead of the registers at the time
+ *			   kdb was entered.
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ * Outputs:
+ *	*contents	Pointer to unsigned long to recieve register contents
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ *
+ * 	Note that this function is really machine independent.   The kdb
+ *	register list is not, however.
+ */
+
+static struct kdbregs {
+	char   *reg_name;
+	size_t	reg_offset;
+} kdbreglist[] = {
+        { " psr",	offsetof(struct pt_regs, cr_ipsr) },
+	{ " ifs",	offsetof(struct pt_regs, cr_ifs) }, 
+        { "  ip",	offsetof(struct pt_regs, cr_iip) },
+
+	{ "unat", 	offsetof(struct pt_regs, ar_unat) },
+	{ " pfs",	offsetof(struct pt_regs, ar_pfs) },
+	{ " rsc", 	offsetof(struct pt_regs, ar_rsc) },
+
+	{ "rnat",	offsetof(struct pt_regs, ar_rnat) },
+	{ "bsps",	offsetof(struct pt_regs, ar_bspstore) },
+	{ "  pr",	offsetof(struct pt_regs, pr) },
+
+	{ "ldrs",	offsetof(struct pt_regs, loadrs) },
+	{ " ccv",	offsetof(struct pt_regs, ar_ccv) },
+	{ "fpsr",	offsetof(struct pt_regs, ar_fpsr) },
+
+	{ "  b0",	offsetof(struct pt_regs, b0) },
+	{ "  b6",	offsetof(struct pt_regs, b6) },
+	{ "  b7",	offsetof(struct pt_regs, b7) },
+
+	{ "  r1",offsetof(struct pt_regs, r1) },
+        { "  r2",offsetof(struct pt_regs, r2) },
+        { "  r3",offsetof(struct pt_regs, r3) },
+
+        { "  r8",offsetof(struct pt_regs, r8) },
+        { "  r9",offsetof(struct pt_regs, r9) },
+        { " r10",offsetof(struct pt_regs, r10) },
+
+	{ " r11",offsetof(struct pt_regs, r11) },
+        { " r12",offsetof(struct pt_regs, r12) },
+        { " r13",offsetof(struct pt_regs, r13) },
+
+        { " r14",offsetof(struct pt_regs, r14) },
+        { " r15",offsetof(struct pt_regs, r15) },
+        { " r16",offsetof(struct pt_regs, r16) },
+
+        { " r17",offsetof(struct pt_regs, r17) },
+        { " r18",offsetof(struct pt_regs, r18) },
+        { " r19",offsetof(struct pt_regs, r19) },
+
+        { " r20",offsetof(struct pt_regs, r20) },
+        { " r21",offsetof(struct pt_regs, r21) },
+        { " r22",offsetof(struct pt_regs, r22) },
+
+        { " r23",offsetof(struct pt_regs, r23) },
+        { " r24",offsetof(struct pt_regs, r24) },
+        { " r25",offsetof(struct pt_regs, r25) },
+
+        { " r26",offsetof(struct pt_regs, r26) },
+        { " r27",offsetof(struct pt_regs, r27) },
+        { " r28",offsetof(struct pt_regs, r28) },
+
+        { " r29",offsetof(struct pt_regs, r29) },
+        { " r30",offsetof(struct pt_regs, r30) },
+        { " r31",offsetof(struct pt_regs, r31) },
+
+};
+
+static const int nkdbreglist = sizeof(kdbreglist) / sizeof(struct kdbregs);
+
+int
+kdbgetregcontents(const char *regname, 
+		  struct pt_regs *regs,
+		  unsigned long *contents)
+{
+	int i;
+
+	if (strcmp(regname, "&regs") == 0) {
+		*contents = (unsigned long)regs;
+		return 0;
+	}
+
+	if (strcmp(regname, "sstk") == 0) {
+		*contents = (unsigned long)getprsregs(regs) ;
+		return 0;
+	}
+
+	if (strcmp(regname, "isr") == 0) {
+		fault_regs_t fr ;
+		get_fault_regs(&fr) ;
+		*contents = fr.isr ;
+		return 0 ;
+	} 
+
+#if 0
+	/* XXX need to verify this */
+        if (strcmp(regname, "kesp") == 0) {
+                *contents = (unsigned long)regs + sizeof(struct pt_regs);
+                return 0;
+        }
+
+	if (regname[0] == '%') {
+		/* User registers:  %%e[a-c]x, etc */
+		regname++;
+		regs = (struct pt_regs *)
+			(current->thread.ksp - sizeof(struct pt_regs));
+	}
+#endif
+
+	for (i=0; i<nkdbreglist; i++) {
+		if (strstr(kdbreglist[i].reg_name, regname))
+			break;
+	}
+
+	if (i == nkdbreglist) {
+		/* Lets check the rse maybe */
+		if (regname[0] == 'r')
+			if (show_cur_stack_frame(regs, simple_strtoul(regname+1, 0, 0) - 31, 
+					contents))
+				return 0 ;
+		return KDB_BADREG;
+	}
+
+	*contents = *(unsigned long *)((unsigned long)regs +
+			kdbreglist[i].reg_offset);
+
+	return 0;
+}
+
+/*
+ * kdbsetregcontents
+ *
+ *	Set the contents of the register specified by the 
+ *	input string argument.   Return an error if the string
+ *	does not match a machine register.
+ *
+ *	Supports modification of user-mode registers via
+ *	%<register-name>
+ *
+ * Parameters:
+ *	regname		Pointer to string naming register
+ *	regs		Pointer to structure containing registers.
+ *	contents	Unsigned long containing new register contents
+ * Outputs:
+ * Returns:
+ *	0		Success
+ *	KDB_BADREG	Invalid register name
+ * Locking:
+ * 	None.
+ * Remarks:
+ */
+
+int
+kdbsetregcontents(const char *regname, 
+		  struct pt_regs *regs,
+		  unsigned long contents)
+{
+	int i;
+
+	if (regname[0] == '%') {
+		regname++;
+		regs = (struct pt_regs *)
+			(current->thread.ksp - sizeof(struct pt_regs));
+	}
+
+	for (i=0; i<nkdbreglist; i++) {
+		if (strnicmp(kdbreglist[i].reg_name, 
+			     regname, 
+			     strlen(regname)) == 0)
+			break;
+	}
+
+	if ((i == nkdbreglist) 
+	 || (strlen(kdbreglist[i].reg_name) != strlen(regname))) {
+		return KDB_BADREG;
+	}
+
+	*(unsigned long *)((unsigned long)regs + kdbreglist[i].reg_offset) = 
+		contents;
+
+	return 0;
+}
+
+/*
+ * kdbdumpregs
+ *
+ *	Dump the specified register set to the display.
+ *
+ * Parameters:
+ *	regs		Pointer to structure containing registers.
+ *	type		Character string identifying register set to dump
+ *	extra		string further identifying register (optional)
+ * Outputs:
+ * Returns:
+ *	0		Success
+ * Locking:
+ * 	None.
+ * Remarks:
+ *	This function will dump the general register set if the type
+ *	argument is NULL (struct pt_regs).   The alternate register 
+ *	set types supported by this function:
+ *
+ *	d 		Debug registers
+ *	c		Control registers
+ *	u		User registers at most recent entry to kernel
+ * Following not yet implemented:
+ *	m		Model Specific Registers (extra defines register #)
+ *	r		Memory Type Range Registers (extra defines register)
+ *
+ *	For now, all registers are covered as follows:
+ *
+ * 	rd 		- dumps all regs
+ *	rd	%isr	- current interrupt status reg, read freshly
+ *	rd	s	- valid stacked regs
+ * 	rd 	%sstk	- gets switch stack addr. dump memory and search
+ *	rd	d	- debug regs, may not be too useful
+ *
+ *	ARs		TB Done
+ *	Interrupt regs 	TB Done ??
+ *	OTHERS		TB Decided ??
+ *
+ *	Intel wish list
+ *	These will be implemented later - Srinivasa
+ *
+ *      type        action
+ *      ----        ------
+ *      g           dump all General static registers
+ *      s           dump all general Stacked registers
+ *      f           dump all Floating Point registers
+ *      p           dump all Predicate registers
+ *      b           dump all Branch registers
+ *      a           dump all Application registers
+ *      c           dump all Control registers
+ *
+ */
+
+int
+kdbdumpregs(struct pt_regs *regs,
+	    const char *type,
+	    const char *extra)
+
+{
+	int i;
+	int count = 0;
+
+	if (type 
+	 && (type[0] == 'u')) {
+		type = NULL;
+		regs = (struct pt_regs *)
+			(current->thread.ksp - sizeof(struct pt_regs));
+	}
+
+	if (type == NULL) {
+		for (i=0; i<nkdbreglist; i++) {
+			kdb_printf("%s: 0x%16.16lx  ", 
+				   kdbreglist[i].reg_name, 
+				   *(unsigned long *)((unsigned long)regs + 
+						  kdbreglist[i].reg_offset));
+
+			if ((++count % 3) == 0)
+				kdb_printf("\n");
+		}
+
+		kdb_printf("&regs = 0x%16.16lx\n", regs);
+
+		return 0;
+	}
+
+	switch (type[0]) {
+	case 'd':
+	{
+		for(i=0; i<8; i+=2) {
+			kdb_printf("idr%d: 0x%16.16lx  idr%d: 0x%16.16lx\n", i, 
+					kdb_getdr(i), i+1, kdb_getdr(i+1));
+					
+		}
+		return 0;
+	}
+#if 0
+	case 'c':
+	{
+		unsigned long cr[5];
+
+		for (i=0; i<5; i++) {
+			cr[i] = kdb_getcr(i);
+		}
+		kdb_printf("cr0 = 0x%8.8x  cr1 = 0x%8.8x  cr2 = 0x%8.8x  cr3 = 0x%8.8x\ncr4 = 0x%8.8x\n",
+			   cr[0], cr[1], cr[2], cr[3], cr[4]);
+		return 0;
+	}
+#endif
+	case 'm':
+		break;
+	case 'r':
+		break;
+
+	case 's':
+	{
+		show_cur_stack_frame(regs, 0, NULL) ;
+
+		return 0 ;
+	}
+
+	case '%':
+	{
+		unsigned long contents ;
+
+		if (!kdbgetregcontents(type+1, regs, &contents))
+                	kdb_printf("%s = 0x%16.16lx\n", type+1, contents) ;
+		else
+                        kdb_printf("diag: Invalid register %s\n", type+1) ;
+
+		return 0 ;
+	}
+
+	default:
+		return KDB_BADREG;
+	}
+
+	/* NOTREACHED */
+	return 0;
+}
+
+k_machreg_t
+kdb_getpc(struct pt_regs *regs)
+{
+	return regs->cr_iip + ia64_psr(regs)->ri;
+}
+
+int
+kdb_setpc(struct pt_regs *regs, k_machreg_t newpc)
+{
+	regs->cr_iip = newpc & ~0xf;
+	ia64_psr(regs)->ri = newpc & 0x3;
+	return 0;
+}
+
+void
+kdb_disableint(kdbintstate_t *state)
+{
+	int *fp = (int *)state;
+	int   flags;
+
+        __save_flags(flags);
+        __cli();
+
+	*fp = flags;
+}
+
+void
+kdb_restoreint(kdbintstate_t *state)
+{
+	int flags = *(int *)state;
+	__restore_flags(flags);
+}
+
+int
+kdb_putword(unsigned long addr, unsigned long contents)
+{
+	*(unsigned long *)addr = contents;
+	return 0;
+}	
+
+int
+kdb_getcurrentframe(struct pt_regs *regs)
+{
+#if 0
+	regs->xcs = 0;
+#if defined(CONFIG_KDB_FRAMEPTR)
+	asm volatile("movl %%ebp,%0":"=m" (*(int *)&regs->ebp));
+#endif
+	asm volatile("movl %%esp,%0":"=m" (*(int *)&regs->esp));
+#endif
+	return 0;
+}
+
+unsigned long
+show_cur_stack_frame(struct pt_regs *regs, int regno, unsigned long *contents)
+{
+        long sof = regs->cr_ifs & ((1<<7)-1) ;	/* size of frame */
+        unsigned long   i ;
+	int j;
+	struct switch_stack *prs_regs = getprsregs(regs) ;
+        unsigned long *sofptr = (prs_regs? ia64_rse_skip_regs(
+			(unsigned long *)prs_regs->ar_bspstore, -sof) : NULL) ;
+
+	if (!sofptr) {
+		printk("Unable to display Current Stack Frame\n") ;
+		return 0 ;
+	}
+
+	if (regno < 0) 
+		return 0 ;
+
+	for (i=sof, j=0;i;i--,j++) {
+		/* remember to skip the nat collection dword */
+		if ((((unsigned long)sofptr>>3) & (((1<<6)-1))) 
+				== ((1<<6)-1))
+			sofptr++ ;
+
+		/* return the value in the reg if regno is non zero */
+
+		if (regno) {
+			if ((j+1) == regno) {
+				if (contents)
+					*contents = *sofptr ;
+				return -1;
+			}
+			sofptr++ ;
+		} else {
+			printk(" r%d: %016lx ", 32+j, *sofptr++) ;
+			if (!((j+1)%3)) printk("\n") ;
+		}
+	}
+
+	if (regno) {
+		if (!i) /* bogus rse number */
+			return 0 ;
+	} else
+		printk("\n") ;
+
+	return 0 ;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kdb/pc_keyb.h linux/arch/ia64/kdb/pc_keyb.h
--- v2.3.42/linux/arch/ia64/kdb/pc_keyb.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kdb/pc_keyb.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,127 @@
+/*
+ *	linux/drivers/char/pc_keyb.h
+ *
+ *	PC Keyboard And Keyboard Controller
+ *
+ *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/*
+ *	Configuration Switches
+ */
+
+#undef KBD_REPORT_ERR			/* Report keyboard errors */
+#define KBD_REPORT_UNKN			/* Report unknown scan codes */
+#define KBD_REPORT_TIMEOUTS		/* Report keyboard timeouts */
+#undef KBD_IS_FOCUS_9000		/* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE			/* Define if your PS/2 mouse needs initialization. */
+
+
+
+#define KBD_INIT_TIMEOUT 1000		/* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250			/* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 1000		/* Timeout in ms for keyboard command acknowledge */
+
+/*
+ *	Internal variables of the driver
+ */
+
+extern unsigned char pckbd_read_mask;
+extern unsigned char aux_device_present;
+
+/*
+ *	Keyboard Controller Registers
+ */
+
+#define KBD_STATUS_REG		0x64	/* Status register (R) */
+#define KBD_CNTL_REG		0x64	/* Controller command register (W) */
+#define KBD_DATA_REG		0x60	/* Keyboard data register (R/W) */
+
+/*
+ *	Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE	0x20	/* Read mode bits */
+#define KBD_CCMD_WRITE_MODE	0x60	/* Write mode bits */
+#define KBD_CCMD_GET_VERSION	0xA1	/* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE	0xA8	/* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE	0xA9	/* Mouse interface test */
+#define KBD_CCMD_SELF_TEST	0xAA	/* Controller self test */
+#define KBD_CCMD_KBD_TEST	0xAB	/* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE	0xAD	/* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE	0xAE	/* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if
+					   initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE	0xD4	/* Write the following byte to the mouse */
+
+/*
+ *	Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
+#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
+#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
+#define KBD_CMD_DISABLE		0xF5	/* Disable scanning */
+#define KBD_CMD_RESET		0xFF	/* Reset */
+
+/*
+ *	Keyboard Replies
+ */
+
+#define KBD_REPLY_POR		0xAA	/* Power on reset */
+#define KBD_REPLY_ACK		0xFA	/* Command ACK */
+#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
+
+/*
+ *	Status Register Bits
+ */
+
+#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */
+#define KBD_STAT_IBF 		0x02	/* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST	0x04	/* Self test successful */
+#define KBD_STAT_CMD		0x08	/* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED	0x10	/* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */
+#define KBD_STAT_GTO 		0x40	/* General receive/xmit timeout */
+#define KBD_STAT_PERR 		0x80	/* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *	Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT	0x01	/* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT	0x02	/* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 		0x04	/* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK	0x08	/* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD	0x10	/* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */
+#define KBD_MODE_KCC 		0x40	/* Scan code conversion to PC format */
+#define KBD_MODE_RFU		0x80
+
+/*
+ *	Mouse Commands
+ */
+
+#define AUX_SET_RES		0xE8	/* Set resolution */
+#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
+#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
+#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
+#define AUX_SET_STREAM		0xEA	/* Set stream mode */
+#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
+#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
+#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
+#define AUX_RESET		0xFF	/* Reset aux device */
+
+#define AUX_BUF_SIZE		2048
+
+struct aux_queue {
+	unsigned long head;
+	unsigned long tail;
+	struct wait_queue *proc_list;
+	struct fasync_struct *fasync;
+	unsigned char buf[AUX_BUF_SIZE];
+};
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/Makefile linux/arch/ia64/kernel/Makefile
--- v2.3.42/linux/arch/ia64/kernel/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/Makefile	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,42 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
+all: kernel.o head.o init_task.o
+
+O_TARGET := kernel.o
+O_OBJS	 := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_default.o irq_internal.o ivt.o \
+	    pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o sal_stub.o semaphore.o setup.o signal.o \
+	    sys_ia64.o traps.o time.o unaligned.o unwind.o
+#O_OBJS   := fpreg.o
+#OX_OBJS  := ia64_ksyms.o
+
+ifeq ($(CONFIG_IA64_GENERIC),y)
+O_OBJS	+= machvec.o
+endif
+
+ifdef CONFIG_PCI
+O_OBJS	+= pci.o
+endif
+
+ifdef CONFIG_SMP
+O_OBJS	+= smp.o irq_lock.o
+endif
+
+ifeq ($(CONFIG_MCA),y)
+O_OBJS	+= mca.o mca_asm.o
+endif
+
+clean::
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/acpi.c linux/arch/ia64/kernel/acpi.c
--- v2.3.42/linux/arch/ia64/kernel/acpi.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/acpi.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,308 @@
+/*
+ * Advanced Configuration and Power Interface 
+ *
+ * Based on 'ACPI Specification 1.0b' February 2, 1999 and 
+ * 'IA-64 Extensions to ACPI Specification' Revision 0.6
+ * 
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
+ */
+
+#include <linux/config.h>
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/acpi-ext.h>
+#include <asm/page.h>
+#include <asm/efi.h>
+#include <asm/io.h>
+#include <asm/iosapic.h>
+#include <asm/irq.h>
+
+#undef ACPI_DEBUG		/* Guess what this does? */
+
+#ifdef CONFIG_SMP
+extern unsigned long ipi_base_addr;
+#endif
+
+/* These are ugly but will be reclaimed by the kernel */
+int __initdata acpi_cpus = 0;	
+int __initdata acpi_apic_map[32];
+int __initdata cpu_cnt = 0;
+
+void (*pm_idle) (void);
+
+/*
+ * Identify usable CPU's and remember them for SMP bringup later.
+ */
+static void __init
+acpi_lsapic(char *p) 
+{
+	int add = 1;
+
+	acpi_entry_lsapic_t *lsapic = (acpi_entry_lsapic_t *) p;
+
+	if ((lsapic->flags & LSAPIC_PRESENT) == 0) 
+		return;
+
+	printk("      CPU %d (%.04x:%.04x): ", cpu_cnt, lsapic->eid, lsapic->id);
+
+	if ((lsapic->flags & LSAPIC_ENABLED) == 0) {
+		printk("Disabled.\n");
+		add = 0;
+	} else if (lsapic->flags & LSAPIC_PERFORMANCE_RESTRICTED) {
+		printk("Performance Restricted; ignoring.\n");
+		add = 0;
+	}
+	
+	if (add) {
+		printk("Available.\n");
+		acpi_cpus++;
+		acpi_apic_map[cpu_cnt] = (lsapic->id << 8) | lsapic->eid;
+	}
+	
+	cpu_cnt++;
+}
+
+/*
+ * Find all IOSAPICs and tag the iosapic_vector structure with the appropriate 
+ * base addresses.
+ */
+static void __init
+acpi_iosapic(char *p) 
+{
+	/*
+	 * This is not good.  ACPI is not necessarily limited to CONFIG_IA64_SV, yet
+	 * ACPI does not necessarily imply IOSAPIC either.  Perhaps there should be
+	 * a means for platform_setup() to register ACPI handlers?
+	 */
+#ifdef CONFIG_IA64_DIG
+	acpi_entry_iosapic_t *iosapic = (acpi_entry_iosapic_t *) p;
+	unsigned int ver;
+	int l, v, pins;
+
+	ver = iosapic_version(iosapic->address);
+	pins = (ver >> 16) & 0xff;
+	
+	printk("IOSAPIC Version %x.%x: address 0x%lx IRQs 0x%x - 0x%x\n", 
+	       (ver & 0xf0) >> 4, (ver & 0x0f), iosapic->address, 
+	       iosapic->irq_base, iosapic->irq_base + pins);
+	
+	for (l = 0; l < pins; l++) {
+		v = map_legacy_irq(iosapic->irq_base + l);
+		if (v > IA64_MAX_VECTORED_IRQ) {
+			printk("    !!! IRQ %d > 255\n", v);
+			continue;
+		}
+		/* XXX Check for IOSAPIC collisions */
+		iosapic_addr(v) = (unsigned long) ioremap(iosapic->address, 0);
+		iosapic_baseirq(v) = iosapic->irq_base;
+	}
+	iosapic_init(iosapic->address);
+#endif
+}
+
+
+/*
+ * Configure legacy IRQ information in iosapic_vector
+ */
+static void __init
+acpi_legacy_irq(char *p)
+{
+	/*
+	 * This is not good.  ACPI is not necessarily limited to CONFIG_IA64_SV, yet
+	 * ACPI does not necessarily imply IOSAPIC either.  Perhaps there should be
+	 * a means for platform_setup() to register ACPI handlers?
+	 */
+#ifdef CONFIG_IA64_IRQ_ACPI
+	acpi_entry_int_override_t *legacy = (acpi_entry_int_override_t *) p;
+	unsigned char vector; 
+	int i;
+
+	vector = map_legacy_irq(legacy->isa_irq);
+
+	/*
+	 * Clobber any old pin mapping.  It may be that it gets replaced later on
+	 */
+	for (i = 0; i < IA64_MAX_VECTORED_IRQ; i++) {
+		if (i == vector) 
+			continue;
+		if (iosapic_pin(i) == iosapic_pin(vector))
+			iosapic_pin(i) = 0xff;
+        }
+
+	iosapic_pin(vector) = legacy->pin;
+	iosapic_bus(vector) = BUS_ISA;	/* This table only overrides the ISA devices */
+	iosapic_busdata(vector) = 0;
+	
+	/* 
+	 * External timer tick is special... 
+	 */
+	if (vector != TIMER_IRQ)
+		iosapic_dmode(vector) = IO_SAPIC_LOWEST_PRIORITY;
+	else 
+		iosapic_dmode(vector) = IO_SAPIC_FIXED;
+	
+	/* See MPS 1.4 section 4.3.4 */
+	switch (legacy->flags) {
+	case 0x5:
+		iosapic_polarity(vector) = IO_SAPIC_POL_HIGH;
+		iosapic_trigger(vector) = IO_SAPIC_EDGE;
+		break;
+	case 0x8:
+		iosapic_polarity(vector) = IO_SAPIC_POL_LOW;
+		iosapic_trigger(vector) = IO_SAPIC_EDGE;
+		break;
+	case 0xd:
+		iosapic_polarity(vector) = IO_SAPIC_POL_HIGH;
+		iosapic_trigger(vector) = IO_SAPIC_LEVEL;
+		break;
+	case 0xf:
+		iosapic_polarity(vector) = IO_SAPIC_POL_LOW;
+		iosapic_trigger(vector) = IO_SAPIC_LEVEL;
+		break;
+	default:
+		printk("    ACPI Legacy IRQ 0x%02x: Unknown flags 0x%x\n", legacy->isa_irq,
+		       legacy->flags);
+		break;
+	}
+
+#ifdef ACPI_DEBUG
+	printk("Legacy ISA IRQ %x -> IA64 Vector %x IOSAPIC Pin %x Active %s %s Trigger\n", 
+	       legacy->isa_irq, vector, iosapic_pin(vector), 
+	       ((iosapic_polarity(vector) == IO_SAPIC_POL_LOW) ? "Low" : "High"),
+	       ((iosapic_trigger(vector) == IO_SAPIC_LEVEL) ? "Level" : "Edge"));
+#endif /* ACPI_DEBUG */
+
+#endif /* CONFIG_IA64_IRQ_ACPI */
+}
+
+/*
+ * Info on platform interrupt sources: NMI. PMI, INIT, etc.
+ */
+static void __init
+acpi_platform(char *p)
+{
+	acpi_entry_platform_src_t *plat = (acpi_entry_platform_src_t *) p;
+
+	printk("PLATFORM: IOSAPIC %x -> Vector %lx on CPU %.04u:%.04u\n",
+	       plat->iosapic_vector, plat->global_vector, plat->eid, plat->id);
+}
+
+/*
+ * Parse the ACPI Multiple SAPIC Table
+ */
+static void __init
+acpi_parse_msapic(acpi_sapic_t *msapic)
+{
+	char *p, *end;
+
+	memset(&acpi_apic_map, -1, sizeof(acpi_apic_map));
+
+#ifdef CONFIG_SMP
+	/* Base address of IPI Message Block */
+	ipi_base_addr = ioremap(msapic->interrupt_block, 0);
+#endif
+	
+	p = (char *) (msapic + 1);
+	end = p + (msapic->header.length - sizeof(acpi_sapic_t));
+
+	while (p < end) {
+		
+		switch (*p) {
+		case ACPI_ENTRY_LOCAL_SAPIC:
+			acpi_lsapic(p);
+			break;
+	
+		case ACPI_ENTRY_IO_SAPIC:
+			acpi_iosapic(p);
+			break;
+
+		case ACPI_ENTRY_INT_SRC_OVERRIDE:
+			acpi_legacy_irq(p);
+			break;
+		
+		case ACPI_ENTRY_PLATFORM_INT_SOURCE:
+			acpi_platform(p);
+			break;
+		
+		default:
+			break;
+		}
+
+		/* Move to next table entry. */
+		p += *(p + 1);
+	}
+
+	/* Make bootup pretty */
+	printk("      %d CPUs available, %d CPUs total\n", acpi_cpus, cpu_cnt);
+}
+
+int __init 
+acpi_parse(acpi_rsdp_t *rsdp)
+{
+	acpi_rsdt_t *rsdt;
+	acpi_desc_table_hdr_t *hdrp;
+	long tables, i;
+
+	if (!rsdp) {
+		printk("Uh-oh, no ACPI Root System Description Pointer table!\n");
+		return 0;
+	}
+
+	if (strncmp(rsdp->signature, ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN)) {
+		printk("Uh-oh, ACPI RSDP signature incorrect!\n");
+		return 0;
+	}
+
+	rsdp->rsdt = __va(rsdp->rsdt);
+	rsdt = rsdp->rsdt;
+	if (strncmp(rsdt->header.signature, ACPI_RSDT_SIG, ACPI_RSDT_SIG_LEN)) {
+		printk("Uh-oh, ACPI RDST signature incorrect!\n");
+		return 0;
+	}
+
+	printk("ACPI: %.6s %.8s %d.%d\n", rsdt->header.oem_id, rsdt->header.oem_table_id, 
+	       rsdt->header.oem_revision >> 16, rsdt->header.oem_revision & 0xffff);
+	
+	tables = (rsdt->header.length - sizeof(acpi_desc_table_hdr_t)) / 8;
+	for (i = 0; i < tables; i++) {
+		hdrp = (acpi_desc_table_hdr_t *) __va(rsdt->entry_ptrs[i]);
+
+		/* Only interested int the MSAPIC table for now ... */
+		if (strncmp(hdrp->signature, ACPI_SAPIC_SIG, ACPI_SAPIC_SIG_LEN) != 0)
+			continue;
+
+		acpi_parse_msapic((acpi_sapic_t *) hdrp);
+	} /* while() */
+
+	if (acpi_cpus == 0) {
+		printk("ACPI: Found 0 CPUS; assuming 1\n");
+		acpi_cpus = 1; /* We've got at least one of these, no? */
+	}
+	return 1;
+}
+
+const char *
+acpi_get_sysname (void)
+{       
+	/* the following should go away once we have an ACPI parser: */
+#ifdef CONFIG_IA64_GENERIC
+	return "hpsim";
+#else
+# if defined (CONFIG_IA64_HP_SIM)
+	return "hpsim";
+# elif defined (CONFIG_IA64_SGI_SN1_SIM)
+	return "sn1";
+# elif defined (CONFIG_IA64_DIG)
+	return "dig";
+# else
+#	error Unknown platform.  Fix acpi.c.
+# endif
+#endif
+}        
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/efi.c linux/arch/ia64/kernel/efi.c
--- v2.3.42/linux/arch/ia64/kernel/efi.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/efi.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,365 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * All EFI Runtime Services are not implemented yet as EFI only
+ * supports physical mode addressing on SoftSDV. This is to be fixed
+ * in a future version.  --drummond 1999-07-20
+ *
+ * Implemented EFI runtime services and virtual mode calls.  --davidm
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+
+#include <asm/efi.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#define EFI_DEBUG
+
+extern efi_status_t efi_call_phys (void *, ...);
+
+struct efi efi;
+		    
+static efi_runtime_services_t *runtime;
+
+static efi_status_t
+phys_get_time (efi_time_t *tm, efi_time_cap_t *tc)
+{
+	return efi_call_phys(__va(runtime->get_time), __pa(tm), __pa(tc));
+}
+
+static efi_status_t
+phys_set_time (efi_time_t *tm)
+{
+	return efi_call_phys(__va(runtime->set_time), __pa(tm));
+}
+
+static efi_status_t
+phys_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm)
+{
+	return efi_call_phys(__va(runtime->get_wakeup_time), __pa(enabled), __pa(pending),
+			     __pa(tm));
+}
+
+static efi_status_t
+phys_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)
+{
+	return efi_call_phys(__va(runtime->set_wakeup_time), enabled, __pa(tm));
+}
+
+static efi_status_t
+phys_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
+		   unsigned long *data_size, void *data)
+{
+	return efi_call_phys(__va(runtime->get_variable), __pa(name), __pa(vendor), __pa(attr),
+			     __pa(data_size), __pa(data));
+}
+
+static efi_status_t
+phys_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor)
+{
+	return efi_call_phys(__va(runtime->get_next_variable), __pa(name_size), __pa(name),
+			     __pa(vendor));
+}
+
+static efi_status_t
+phys_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr,
+		   unsigned long data_size, void *data)
+{
+	return efi_call_phys(__va(runtime->set_variable), __pa(name), __pa(vendor), attr,
+			     data_size, __pa(data));
+}
+
+static efi_status_t
+phys_get_next_high_mono_count (u64 *count)
+{
+	return efi_call_phys(__va(runtime->get_next_high_mono_count), __pa(count));
+}
+
+static void
+phys_reset_system (int reset_type, efi_status_t status,
+		   unsigned long data_size, efi_char16_t *data)
+{
+	efi_call_phys(__va(runtime->reset_system), status, data_size, __pa(data));
+}
+
+/*
+ * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static inline unsigned long 
+mktime (unsigned int year, unsigned int mon, unsigned int day, unsigned int hour,
+	unsigned int min, unsigned int sec)
+{
+        if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
+                mon += 12;      /* Puts Feb last since it has leap day */
+                year -= 1;
+        }
+        return ((((unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day)
+		  + year*365 - 719499
+		)*24 + hour /* now have hours */
+		)*60 + min /* now have minutes */
+		)*60 + sec; /* finally seconds */
+}
+
+void
+efi_gettimeofday (struct timeval *tv)
+{
+	efi_time_t tm;
+
+	memset(tv, 0, sizeof(tv));
+	if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS)
+		return;
+
+	tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
+	tv->tv_usec = tm.nanosecond / 1000;
+}
+
+/*
+ * Walks the EFI memory map and calls CALLBACK once for each EFI
+ * memory descriptor that has memory that is available for OS use.
+ */
+void
+efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
+{
+	int prev_valid = 0;
+	struct range {
+		u64 start;
+		u64 end;
+	} prev, curr;
+	void *efi_map_start, *efi_map_end, *p;
+	efi_memory_desc_t *md;
+	u64 efi_desc_size, start, end;
+
+	efi_map_start = __va(ia64_boot_param.efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param.efi_memmap_size;
+	efi_desc_size = ia64_boot_param.efi_memdesc_size;
+
+	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+		md = p;
+		switch (md->type) {
+		      case EFI_LOADER_CODE:
+		      case EFI_LOADER_DATA:
+		      case EFI_BOOT_SERVICES_CODE:
+		      case EFI_BOOT_SERVICES_DATA:
+		      case EFI_CONVENTIONAL_MEMORY:
+#ifndef CONFIG_IA64_VIRTUAL_MEM_MAP
+			if (md->phys_addr > 1024*1024*1024UL) {
+				printk("Warning: ignoring %luMB of memory above 1GB!\n",
+				       md->num_pages >> 8);
+				md->type = EFI_UNUSABLE_MEMORY;
+				continue;
+			}
+#endif
+
+			curr.start = PAGE_OFFSET + md->phys_addr;
+			curr.end   = curr.start + (md->num_pages << 12);
+
+			if (!prev_valid) {
+				prev = curr;
+				prev_valid = 1;
+			} else {
+				if (curr.start < prev.start)
+					printk("Oops: EFI memory table not ordered!\n");
+
+				if (prev.end == curr.start) {
+					/* merge two consecutive memory ranges */
+					prev.end = curr.end;
+				} else {
+					start = PAGE_ALIGN(prev.start);
+					end = prev.end & PAGE_MASK;
+					if ((end > start) && (*callback)(start, end, arg) < 0)
+						return;
+					prev = curr;
+				}
+			}
+			break;
+
+		      default:
+			continue;
+		}
+	}
+	if (prev_valid) {
+		start = PAGE_ALIGN(prev.start);
+		end = prev.end & PAGE_MASK;
+		if (end > start)
+			(*callback)(start, end, arg);
+	}
+}
+
+void __init 
+efi_init (void)
+{
+	void *efi_map_start, *efi_map_end, *p;
+	efi_config_table_t *config_tables;
+	efi_memory_desc_t *md;
+	efi_char16_t *c16;
+	u64 efi_desc_size;
+	char vendor[100] = "unknown";
+	int i;
+
+	efi.systab = __va(ia64_boot_param.efi_systab);
+
+	/*
+	 * Verify the EFI Table
+ 	 */
+	if (efi.systab == NULL) 
+		panic("Woah! Can't find EFI system table.\n");
+	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) 
+		panic("Woah! EFI system table signature incorrect\n");
+	if (efi.systab->hdr.revision != EFI_SYSTEM_TABLE_REVISION)
+		printk("Warning: EFI system table version mismatch: "
+		       "got %d.%02d, expected %d.%02d\n",
+		       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff,
+		       EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff);
+
+	config_tables = __va(efi.systab->tables);
+
+	/* Show what we know for posterity */
+	c16 = __va(efi.systab->fw_vendor);
+	if (c16) {
+		for (i = 0;i < sizeof(vendor) && *c16; ++i)
+			vendor[i] = *c16++;
+		vendor[i] = '\0';
+	}
+
+	printk("EFI v%u.%.02u by %s:",
+	       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
+
+	for (i = 0; i < efi.systab->nr_tables; i++) {
+		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
+			efi.mps = __va(config_tables[i].table);
+			printk(" MPS=0x%lx", config_tables[i].table);
+		} else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
+			efi.acpi = __va(config_tables[i].table);
+			printk(" ACPI=0x%lx", config_tables[i].table);
+		} else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
+			efi.smbios = __va(config_tables[i].table);
+			printk(" SMBIOS=0x%lx", config_tables[i].table);
+		} else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
+			efi.sal_systab = __va(config_tables[i].table);
+			printk(" SALsystab=0x%lx", config_tables[i].table);
+		}
+	}
+	printk("\n");
+
+	runtime = __va(efi.systab->runtime);
+	efi.get_time = phys_get_time;
+	efi.set_time = phys_set_time;
+	efi.get_wakeup_time = phys_get_wakeup_time;
+	efi.set_wakeup_time = phys_set_wakeup_time;
+	efi.get_variable = phys_get_variable;
+	efi.get_next_variable = phys_get_next_variable;
+	efi.set_variable = phys_set_variable;
+	efi.get_next_high_mono_count = phys_get_next_high_mono_count;
+	efi.reset_system = phys_reset_system;
+
+	efi_map_start = __va(ia64_boot_param.efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param.efi_memmap_size;
+	efi_desc_size = ia64_boot_param.efi_memdesc_size;
+
+#ifdef EFI_DEBUG
+	/* print EFI memory map: */
+	for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
+		md = p;
+		printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
+		       i, md->type, md->attribute,
+		       md->phys_addr, md->phys_addr + (md->num_pages<<12) - 1, md->num_pages >> 8);
+	}
+#endif
+}
+
+void
+efi_enter_virtual_mode (void)
+{
+	void *efi_map_start, *efi_map_end, *p;
+	efi_memory_desc_t *md;
+	efi_status_t status;
+	u64 efi_desc_size;
+
+	efi_map_start = __va(ia64_boot_param.efi_memmap);
+	efi_map_end   = efi_map_start + ia64_boot_param.efi_memmap_size;
+	efi_desc_size = ia64_boot_param.efi_memdesc_size;
+
+	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+		md = p;
+		if (md->attribute & EFI_MEMORY_RUNTIME) {
+			/*
+			 * Some descriptors have multiple bits set, so the order of
+			 * the tests is relevant.
+			 */
+			if (md->attribute & EFI_MEMORY_WB) {
+				md->virt_addr = (u64) __va(md->phys_addr);
+			} else if (md->attribute & EFI_MEMORY_UC) {
+				md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+			} else if (md->attribute & EFI_MEMORY_WC) {
+#if 0
+				md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
+									   | _PAGE_D
+									   | _PAGE_MA_WC
+									   | _PAGE_PL_0
+									   | _PAGE_AR_RW));
+#else
+				printk("EFI_MEMORY_WC mapping\n");
+				md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+#endif
+			} else if (md->attribute & EFI_MEMORY_WT) {
+#if 0
+				md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
+									   | _PAGE_D | _PAGE_MA_WT
+									   | _PAGE_PL_0
+									   | _PAGE_AR_RW));
+#else
+				printk("EFI_MEMORY_WT mapping\n");
+				md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+#endif
+			}
+		}
+	}
+
+	status = efi_call_phys(__va(runtime->set_virtual_address_map),
+			       ia64_boot_param.efi_memmap_size,
+			       efi_desc_size, ia64_boot_param.efi_memdesc_version,
+			       ia64_boot_param.efi_memmap);
+	if (status != EFI_SUCCESS) {
+		printk("Warning: unable to switch EFI into virtual mode (status=%lu)\n", status);
+		return;
+	}
+
+	/*
+	 * Now that EFI is in virtual mode, we arrange for EFI functions to be
+	 * called directly:
+	 */
+	efi.get_time = __va(runtime->get_time);
+	efi.set_time = __va(runtime->set_time);
+	efi.get_wakeup_time = __va(runtime->get_wakeup_time);
+	efi.set_wakeup_time = __va(runtime->set_wakeup_time);
+	efi.get_variable = __va(runtime->get_variable);
+	efi.get_next_variable = __va(runtime->get_next_variable);
+	efi.set_variable = __va(runtime->set_variable);
+	efi.get_next_high_mono_count = __va(runtime->get_next_high_mono_count);
+	efi.reset_system = __va(runtime->reset_system);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/efi_stub.S linux/arch/ia64/kernel/efi_stub.S
--- v2.3.42/linux/arch/ia64/kernel/efi_stub.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/efi_stub.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,141 @@
+/*
+ * EFI call stub.
+ *
+ * Copyright (C) 1999 David Mosberger <davidm@hpl.hp.com>
+ *
+ * This stub allows us to make EFI calls in physical mode with interrupts
+ * turned off.  We need this because we can't call SetVirtualMap() until
+ * the kernel has booted far enough to allow allocation of struct vma_struct
+ * entries (which we would need to map stuff with memory attributes other
+ * than uncached or writeback...).  Since the GetTime() service gets called
+ * earlier than that, we need to be able to make physical mode EFI calls from
+ * the kernel.
+ */
+
+/*
+ * PSR settings as per SAL spec (Chapter 8 in the "IA-64 System
+ * Abstraction Layer Specification", revision 2.6e).  Note that
+ * psr.dfl and psr.dfh MUST be cleared, despite what this manual says.
+ * Otherwise, SAL dies whenever it's trying to do an IA-32 BIOS call
+ * (the br.ia instruction fails unless psr.dfl and psr.dfh are
+ * cleared).  Fortunately, SAL promises not to touch the floating
+ * point regs, so at least we don't have to save f2-f127.
+ */
+#define PSR_BITS_TO_CLEAR						\
+	(IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT |		\
+	 IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED |	\
+	 IA64_PSR_DFL | IA64_PSR_DFH)
+
+#define PSR_BITS_TO_SET							\
+	(IA64_PSR_BN)
+
+#include <asm/processor.h>
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.text
+
+/*
+ * Switch execution mode from virtual to physical or vice versa.
+ *
+ * Inputs:
+ *	r16 = new psr to establish
+ */
+	.proc switch_mode
+switch_mode:
+ {
+	alloc r2=ar.pfs,0,0,0,0
+	rsm psr.i | psr.ic		// disable interrupts and interrupt collection
+	mov r15=ip
+ }
+	;;
+ {
+	flushrs				// must be first insn in group
+	srlz.i
+	shr.u r19=r15,61		// r19 <- top 3 bits of current IP
+ }
+	;;
+	mov cr.ipsr=r16			// set new PSR
+	add r3=1f-switch_mode,r15
+	xor r15=0x7,r19			// flip the region bits
+
+	mov r17=ar.bsp
+	mov r14=rp			// get return address into a general register
+
+	// switch RSE backing store:
+	;;
+	dep r17=r15,r17,61,3		// make ar.bsp physical or virtual
+	mov r18=ar.rnat			// save ar.rnat
+	;;
+	mov ar.bspstore=r17		// this steps on ar.rnat
+	dep r3=r15,r3,61,3		// make rfi return address physical or virtual
+	;;
+	mov cr.iip=r3
+	mov cr.ifs=r0
+	dep sp=r15,sp,61,3		// make stack pointer physical or virtual
+	;;
+	mov ar.rnat=r18			// restore ar.rnat
+	dep r14=r15,r14,61,3		// make function return address physical or virtual
+	rfi				// must be last insn in group
+	;;
+1:	mov rp=r14
+	br.ret.sptk.few rp
+	.endp switch_mode
+
+/*
+ * Inputs:
+ *	in0 = address of function descriptor of EFI routine to call
+ *	in1..in7 = arguments to routine
+ *
+ * Outputs:
+ *	r8 = EFI_STATUS returned by called function
+ */
+
+	.global efi_call_phys
+	.proc efi_call_phys
+efi_call_phys:
+
+	alloc loc0=ar.pfs,8,5,7,0
+	ld8 r2=[in0],8			// load EFI function's entry point
+	mov loc1=rp
+	;;
+	mov loc2=gp			// save global pointer
+	mov loc4=ar.rsc			// save RSE configuration
+	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+	;;
+
+	ld8 gp=[in0]			// load EFI function's global pointer
+	mov out0=in1
+	mov out1=in2
+	movl r16=PSR_BITS_TO_CLEAR
+
+	mov loc3=psr			// save processor status word
+	movl r17=PSR_BITS_TO_SET
+	;;
+	mov out2=in3
+	or loc3=loc3,r17
+	mov b6=r2
+	;;
+	andcm r16=loc3,r16		// get psr with IT, DT, and RT bits cleared
+	mov out3=in4
+	br.call.sptk.few rp=switch_mode
+.ret0:
+	mov out4=in5
+	mov out5=in6
+	mov out6=in7
+	br.call.sptk.few rp=b6		// call the EFI function
+.ret1:
+	mov ar.rsc=r0			// put RSE in enforced lazy, LE mode
+	mov r16=loc3
+	br.call.sptk.few rp=switch_mode	// return to virtual mode
+.ret2:
+	mov ar.rsc=loc4			// restore RSE configuration
+	mov ar.pfs=loc0
+	mov rp=loc1
+	mov gp=loc2
+	br.ret.sptk.few rp
+	
+	.endp efi_call_phys
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/entry.S linux/arch/ia64/kernel/entry.S
--- v2.3.42/linux/arch/ia64/kernel/entry.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/entry.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,1261 @@
+/*
+ * ia64/kernel/entry.S
+ *
+ * Kernel entry points.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 Asit Mallick <Asit.K.Mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <Don.Dugger@intel.com>
+ */
+/*
+ * Global (preserved) predicate usage on syscall entry/exit path:
+ *
+ * 
+ *	pEOI:		See entry.h.
+ *	pKern:		See entry.h.
+ *	pSys:		See entry.h.
+ *	pNonSys:	!pSys
+ *	p2:		(Alias of pKern!) True if any signals are pending.
+ *	p16/p17:	Used by stubs calling ia64_do_signal to indicate if current task
+ *			has PF_PTRACED flag bit set.  p16 is true if so, p17 is the complement.
+ */
+
+#include <linux/config.h>
+
+#include <asm/errno.h>
+#include <asm/offsets.h>
+#include <asm/processor.h>
+#include <asm/unistd.h>
+
+#include "entry.h"
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	/*
+	 * execve() is special because in case of success, we need to
+	 * setup a null register window frame.
+	 */
+	.align 16
+	.proc ia64_execve
+ia64_execve:
+	alloc loc0=ar.pfs,3,2,4,0
+	mov loc1=rp
+	mov out0=in0			// filename
+	;;				// stop bit between alloc and call
+	mov out1=in1			// argv
+	mov out2=in2			// envp
+	add out3=16,sp			// regs
+	br.call.sptk.few rp=sys_execve
+.ret0:	cmp4.ge p6,p0=r8,r0
+	mov ar.pfs=loc0			// restore ar.pfs
+	;;
+(p6)	mov ar.pfs=r0			// clear ar.pfs in case of success
+	sxt4 r8=r8			// return 64-bit result
+	mov rp=loc1
+
+	br.ret.sptk.few rp
+	.endp ia64_execve
+
+	.align 16
+	.global sys_clone
+	.proc sys_clone
+sys_clone:
+	alloc r16=ar.pfs,2,2,3,0;;
+	movl r28=1f
+	mov loc1=rp
+	br.cond.sptk.many save_switch_stack
+1:
+	mov loc0=r16				// save ar.pfs across do_fork
+	adds out2=IA64_SWITCH_STACK_SIZE+16,sp
+	adds r2=IA64_SWITCH_STACK_SIZE+IA64_PT_REGS_R12_OFFSET+16,sp
+	cmp.eq p8,p9=in1,r0			// usp == 0?
+	mov out0=in0				// out0 = clone_flags
+	;;
+(p8)	ld8 out1=[r2]				// fetch usp from pt_regs.r12
+(p9)	mov out1=in1
+	br.call.sptk.few rp=do_fork
+.ret1:
+	mov ar.pfs=loc0
+	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
+	mov rp=loc1
+	;;
+	br.ret.sptk.many rp
+	.endp sys_clone
+
+/*
+ * prev_task <- switch_to(struct task_struct *next)
+ */
+	.align 16
+	.global ia64_switch_to
+	.proc ia64_switch_to
+ia64_switch_to:
+	alloc r16=ar.pfs,1,0,0,0
+	movl r28=1f
+	br.cond.sptk.many save_switch_stack
+1:
+	// disable interrupts to ensure atomicity for next few instructions:
+	mov r17=psr		// M-unit
+	;;
+	rsm psr.i		// M-unit
+	dep r18=-1,r0,0,61	// build mask 0x1fffffffffffffff
+	;;
+	srlz.d
+	;;
+	adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
+	adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
+	;;
+	st8 [r22]=sp		// save kernel stack pointer of old task
+	ld8 sp=[r21]		// load kernel stack pointer of new task
+	and r20=in0,r18		// physical address of "current"
+	;;
+	mov r8=r13		// return pointer to previously running task
+	mov r13=in0		// set "current" pointer
+	mov ar.k6=r20		// copy "current" into ar.k6
+	;;
+	// restore interrupts
+	mov psr.l=r17
+	;;
+	srlz.d
+
+	movl r28=1f
+	br.cond.sptk.many load_switch_stack
+1:
+	br.ret.sptk.few rp
+	.endp ia64_switch_to
+
+	/*
+	 * Like save_switch_stack, but also save the stack frame that is active
+	 * at the time this function is called.
+	 */
+	.align 16
+	.proc save_switch_stack_with_current_frame
+save_switch_stack_with_current_frame:
+1:	{
+	  alloc r16=ar.pfs,0,0,0,0		// pass ar.pfs to save_switch_stack
+	  mov r28=ip
+	}
+	;;
+	adds r28=1f-1b,r28
+	br.cond.sptk.many save_switch_stack
+1:	br.ret.sptk.few rp
+	.endp save_switch_stack_with_current_frame
+/*
+ * Note that interrupts are enabled during save_switch_stack and
+ * load_switch_stack.  This means that we may get an interrupt with
+ * "sp" pointing to the new kernel stack while ar.bspstore is still
+ * pointing to the old kernel backing store area.  Since ar.rsc,
+ * ar.rnat, ar.bsp, and ar.bspstore are all preserved by interrupts,
+ * this is not a problem.
+ */
+
+/*
+ * save_switch_stack:
+ *	- r16 holds ar.pfs
+ *	- r28 holds address to return to
+ *	- rp (b0) holds return address to save
+ */
+	.align 16
+	.global save_switch_stack
+	.proc save_switch_stack
+save_switch_stack:
+	flushrs			// flush dirty regs to backing store (must be first in insn group)
+	mov r17=ar.unat		// preserve caller's
+	adds r2=-IA64_SWITCH_STACK_SIZE+16,sp	// r2 = &sw->caller_unat
+	;;
+	mov r18=ar.fpsr		// preserve fpsr
+	mov ar.rsc=r0		// put RSE in mode: enforced lazy, little endian, pl 0
+	;;
+	mov r19=ar.rnat
+	adds r3=-IA64_SWITCH_STACK_SIZE+24,sp	// r3 = &sw->ar_fpsr
+
+	// Note: the instruction ordering is important here: we can't
+	// store anything to the switch stack before sp is updated
+	// as otherwise an interrupt might overwrite the memory!
+	adds sp=-IA64_SWITCH_STACK_SIZE,sp
+	;;
+	st8 [r2]=r17,16
+	st8 [r3]=r18,24
+	;;
+	stf.spill [r2]=f2,32
+	stf.spill [r3]=f3,32
+	mov r21=b0
+	;;
+	stf.spill [r2]=f4,32
+	stf.spill [r3]=f5,32
+	;;
+	stf.spill [r2]=f10,32
+	stf.spill [r3]=f11,32
+	mov r22=b1
+	;;
+	stf.spill [r2]=f12,32
+	stf.spill [r3]=f13,32
+	mov r23=b2
+	;;
+	stf.spill [r2]=f14,32
+	stf.spill [r3]=f15,32
+	mov r24=b3
+	;;
+	stf.spill [r2]=f16,32
+	stf.spill [r3]=f17,32
+	mov r25=b4
+	;;
+	stf.spill [r2]=f18,32
+	stf.spill [r3]=f19,32
+	mov r26=b5
+	;;
+	stf.spill [r2]=f20,32
+	stf.spill [r3]=f21,32
+	mov r17=ar.lc				// I-unit
+	;;
+	stf.spill [r2]=f22,32
+	stf.spill [r3]=f23,32
+	;;
+	stf.spill [r2]=f24,32
+	stf.spill [r3]=f25,32
+	;;
+	stf.spill [r2]=f26,32
+	stf.spill [r3]=f27,32
+	;;
+	stf.spill [r2]=f28,32
+	stf.spill [r3]=f29,32
+	;;
+	stf.spill [r2]=f30,32
+	stf.spill [r3]=f31,24
+	;;
+	st8.spill [r2]=r4,16
+	st8.spill [r3]=r5,16
+	;;
+	st8.spill [r2]=r6,16
+	st8.spill [r3]=r7,16
+	;;
+	st8 [r2]=r21,16		// save b0
+	st8 [r3]=r22,16		// save b1
+	/* since we're done with the spills, read and save ar.unat: */
+	mov r18=ar.unat		// M-unit
+	mov r20=ar.bspstore	// M-unit
+	;;
+	st8 [r2]=r23,16		// save b2
+	st8 [r3]=r24,16		// save b3
+	;;
+	st8 [r2]=r25,16		// save b4
+	st8 [r3]=r26,16		// save b5
+	;;
+	st8 [r2]=r16,16		// save ar.pfs
+	st8 [r3]=r17,16		// save ar.lc
+	mov r21=pr
+	;;
+	st8 [r2]=r18,16		// save ar.unat
+	st8 [r3]=r19,16		// save ar.rnat
+	mov b7=r28
+	;;
+	st8 [r2]=r20		// save ar.bspstore
+	st8 [r3]=r21		// save predicate registers
+	mov ar.rsc=3		// put RSE back into eager mode, pl 0
+	br.cond.sptk.few b7
+	.endp save_switch_stack
+
+/*
+ * load_switch_stack:
+ *	- r28 holds address to return to
+ */
+	.align 16
+	.proc load_switch_stack
+load_switch_stack:
+	invala			// invalidate ALAT
+	adds r2=IA64_SWITCH_STACK_B0_OFFSET+16,sp	// get pointer to switch_stack.b0
+	mov ar.rsc=r0		// put RSE into enforced lazy mode
+	adds r3=IA64_SWITCH_STACK_B0_OFFSET+24,sp	// get pointer to switch_stack.b1
+	;;
+	ld8 r21=[r2],16		// restore b0
+	ld8 r22=[r3],16		// restore b1
+	;;
+	ld8 r23=[r2],16		// restore b2
+	ld8 r24=[r3],16		// restore b3
+	;;
+	ld8 r25=[r2],16		// restore b4
+	ld8 r26=[r3],16		// restore b5
+	;;
+	ld8 r16=[r2],16		// restore ar.pfs
+	ld8 r17=[r3],16		// restore ar.lc
+	;;
+	ld8 r18=[r2],16		// restore ar.unat
+	ld8 r19=[r3],16		// restore ar.rnat
+	mov b0=r21
+	;;
+	ld8 r20=[r2]		// restore ar.bspstore
+	ld8 r21=[r3]		// restore predicate registers
+	mov ar.pfs=r16
+	;;
+	mov ar.bspstore=r20
+	;;
+	loadrs			// invalidate stacked regs outside current frame
+	adds r2=16-IA64_SWITCH_STACK_SIZE,r2	// get pointer to switch_stack.caller_unat
+	;;			// stop bit for rnat dependency
+	mov ar.rnat=r19
+	mov ar.unat=r18		// establish unat holding the NaT bits for r4-r7
+	adds r3=16-IA64_SWITCH_STACK_SIZE,r3	// get pointer to switch_stack.ar_fpsr
+	;;
+	ld8 r18=[r2],16		// restore caller's unat
+	ld8 r19=[r3],24		// restore fpsr
+	mov ar.lc=r17
+	;;
+	ldf.fill f2=[r2],32
+	ldf.fill f3=[r3],32
+	mov pr=r21,-1
+	;;
+	ldf.fill f4=[r2],32
+	ldf.fill f5=[r3],32
+	;;
+	ldf.fill f10=[r2],32
+	ldf.fill f11=[r3],32
+	mov b1=r22
+	;;
+	ldf.fill f12=[r2],32
+	ldf.fill f13=[r3],32
+	mov b2=r23
+	;;
+	ldf.fill f14=[r2],32
+	ldf.fill f15=[r3],32
+	mov b3=r24
+	;;
+	ldf.fill f16=[r2],32
+	ldf.fill f17=[r3],32
+	mov b4=r25
+	;;
+	ldf.fill f18=[r2],32
+	ldf.fill f19=[r3],32
+	mov b5=r26
+	;;
+	ldf.fill f20=[r2],32
+	ldf.fill f21=[r3],32
+	;;
+	ldf.fill f22=[r2],32
+	ldf.fill f23=[r3],32
+	;;
+	ldf.fill f24=[r2],32
+	ldf.fill f25=[r3],32
+	;;
+	ldf.fill f26=[r2],32
+	ldf.fill f27=[r3],32
+	;;
+	ldf.fill f28=[r2],32
+	ldf.fill f29=[r3],32
+	;;
+	ldf.fill f30=[r2],32
+	ldf.fill f31=[r3],24
+	;;
+	ld8.fill r4=[r2],16
+	ld8.fill r5=[r3],16
+	mov b7=r28
+	;;
+	ld8.fill r6=[r2],16
+	ld8.fill r7=[r3],16
+	mov ar.unat=r18				// restore caller's unat
+	mov ar.fpsr=r19				// restore fpsr
+	mov ar.rsc=3				// put RSE back into eager mode, pl 0
+	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop switch_stack
+	br.cond.sptk.few b7
+	.endp load_switch_stack
+
+	.align 16
+	.global __ia64_syscall
+	.proc __ia64_syscall
+__ia64_syscall:
+	.regstk 6,0,0,0
+	mov r15=in5				// put syscall number in place
+	break __BREAK_SYSCALL
+	movl r2=errno
+	cmp.eq p6,p7=-1,r10
+	;;
+(p6)	st4 [r2]=r8
+(p6)	mov r8=-1
+	br.ret.sptk.few rp
+	.endp __ia64_syscall
+
+	//
+	// We invoke syscall_trace through this intermediate function to
+	// ensure that the syscall input arguments are not clobbered.  We
+	// also use it to preserve b6, which contains the syscall entry point.
+	//
+	.align 16
+	.global invoke_syscall_trace
+	.proc invoke_syscall_trace
+invoke_syscall_trace:
+	alloc loc0=ar.pfs,8,3,0,0
+	;;			// WAW on CFM at the br.call
+	mov loc1=rp
+	br.call.sptk.many rp=save_switch_stack_with_current_frame	// must preserve b6!!
+.ret2:	mov loc2=b6
+	br.call.sptk.few rp=syscall_trace
+.ret3:	adds sp=IA64_SWITCH_STACK_SIZE,sp	// drop switch_stack frame
+	mov rp=loc1
+	mov ar.pfs=loc0
+	mov b6=loc2
+	;;
+	br.ret.sptk.few rp
+	.endp invoke_syscall_trace
+
+	//
+	// Invoke a system call, but do some tracing before and after the call.
+	// We MUST preserve the current register frame throughout this routine
+	// because some system calls (such as ia64_execve) directly
+	// manipulate ar.pfs.
+	//
+	// Input:
+	//	r15 = syscall number
+	//	b6  = syscall entry point
+	//
+	.global ia64_trace_syscall
+	.global ia64_strace_leave_kernel
+	.global ia64_strace_clear_r8
+
+	.proc ia64_strace_clear_r8
+ia64_strace_clear_r8:		// this is where we return after cloning when PF_TRACESYS is on
+# ifdef CONFIG_SMP
+	br.call.sptk.few rp=invoke_schedule_tail
+# endif
+	mov r8=0
+	br strace_check_retval
+	.endp ia64_strace_clear_r8
+
+	.proc ia64_trace_syscall
+ia64_trace_syscall:
+	br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
+.ret4:	br.call.sptk.few rp=b6			// do the syscall
+strace_check_retval:
+.ret5:	cmp.lt p6,p0=r8,r0			// syscall failed?
+	;;
+	adds r2=IA64_PT_REGS_R8_OFFSET+16,sp	// r2 = &pt_regs.r8
+	adds r3=IA64_PT_REGS_R8_OFFSET+32,sp	// r3 = &pt_regs.r10
+	mov r10=0
+(p6)	br.cond.sptk.few strace_error		// syscall failed ->
+	;;					// avoid RAW on r10
+strace_save_retval:
+	st8.spill [r2]=r8			// store return value in slot for r8
+	st8.spill [r3]=r10			// clear error indication in slot for r10
+ia64_strace_leave_kernel:
+	br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
+.ret6:	br.cond.sptk.many ia64_leave_kernel
+
+strace_error:
+	ld8 r3=[r2]				// load pt_regs.r8
+	sub r9=0,r8				// negate return value to get errno value
+	;;
+	cmp.ne p6,p0=r3,r0			// is pt_regs.r8!=0?
+	adds r3=16,r2				// r3=&pt_regs.r10
+	;;
+(p6)	mov r10=-1
+(p6)	mov r8=r9
+	br.cond.sptk.few strace_save_retval
+	.endp ia64_trace_syscall
+
+/*
+ * A couple of convenience macros to help implement/understand the state
+ * restoration that happens at the end of ia64_ret_from_syscall.
+ */
+#define rARPR		r31
+#define rCRIFS		r30
+#define rCRIPSR		r29
+#define rCRIIP		r28
+#define rARRSC		r27
+#define rARPFS		r26
+#define rARUNAT		r25
+#define rARRNAT		r24
+#define rARBSPSTORE	r23
+#define rKRBS		r22
+#define rB6		r21
+
+	.align 16
+	.global ia64_ret_from_syscall
+	.global ia64_ret_from_syscall_clear_r8
+	.global ia64_leave_kernel
+	.proc ia64_ret_from_syscall
+ia64_ret_from_syscall_clear_r8:
+#ifdef CONFIG_SMP
+	// In SMP mode, we need to call schedule_tail to complete the scheduling process.
+	// Called by ia64_switch_to after do_fork()->copy_thread().  r8 contains the
+	// address of the previously executing task.
+	br.call.sptk.few rp=invoke_schedule_tail
+.ret7:
+#endif                  
+	mov r8=0
+	;;					// added stop bits to prevent r8 dependency
+ia64_ret_from_syscall:
+	cmp.ge p6,p7=r8,r0			// syscall executed successfully?
+	adds r2=IA64_PT_REGS_R8_OFFSET+16,sp	// r2 = &pt_regs.r8
+	adds r3=IA64_PT_REGS_R8_OFFSET+32,sp	// r3 = &pt_regs.r10
+	;;
+(p6)	st8.spill [r2]=r8	// store return value in slot for r8 and set unat bit
+(p6)	st8.spill [r3]=r0	// clear error indication in slot for r10 and set unat bit
+(p7)	br.cond.spnt.few handle_syscall_error	// handle potential syscall failure
+
+ia64_leave_kernel:
+	// check & deliver software interrupts (bottom half handlers):
+
+	movl r2=bh_active		// sheesh, why aren't these two in
+	movl r3=bh_mask			// a struct??
+	;;
+	ld8 r2=[r2]
+	ld8 r3=[r3]
+	;;
+	and r2=r2,r3
+	;;
+	cmp.ne p6,p7=r2,r0		// any soft interrupts ready for delivery?
+(p6)	br.call.dpnt.few rp=invoke_do_bottom_half
+1:
+(pKern)	br.cond.dpnt.many restore_all	// yup -> skip check for rescheduling & signal delivery
+
+	// call schedule() until we find a task that doesn't have need_resched set:
+
+back_from_resched:
+	{ .mii
+	  adds r2=IA64_TASK_NEED_RESCHED_OFFSET,r13
+	  mov r3=ip
+	  adds r14=IA64_TASK_SIGPENDING_OFFSET,r13
+	}
+	;;
+	ld8 r2=[r2]
+	ld4 r14=[r14]
+	mov rp=r3			// arrange for schedule() to return to back_from_resched
+	;;
+	/*
+	 * If pEOI is set, we need to write the cr.eoi now and then
+	 * clear pEOI because both invoke_schedule() and
+	 * handle_signal_delivery() may call the scheduler.  Since
+	 * we're returning to user-level, we get at most one nested
+	 * interrupt of the same priority level, which doesn't tax the
+	 * kernel stack too much.
+	 */
+(pEOI)	mov cr.eoi=r0
+	cmp.ne p6,p0=r2,r0
+	cmp.ne p2,p0=r14,r0		// NOTE: pKern is an alias for p2!!
+(pEOI)	cmp.ne pEOI,p0=r0,r0		// clear pEOI before calling schedule()
+	srlz.d
+(p6)	br.call.spnt.many b6=invoke_schedule	// ignore return value
+2:
+	// check & deliver pending signals:
+(p2)	br.call.spnt.few rp=handle_signal_delivery
+restore_all:
+
+	// start restoring the state saved on the kernel stack (struct pt_regs):
+
+	adds r2=IA64_PT_REGS_R8_OFFSET+16,r12
+	adds r3=IA64_PT_REGS_R8_OFFSET+24,r12
+	;;
+	ld8.fill r8=[r2],16
+	ld8.fill r9=[r3],16
+	;;
+	ld8.fill r10=[r2],16
+	ld8.fill r11=[r3],16
+	;;
+	ld8.fill r16=[r2],16
+	ld8.fill r17=[r3],16
+	;;
+	ld8.fill r18=[r2],16
+	ld8.fill r19=[r3],16
+	;;
+	ld8.fill r20=[r2],16
+	ld8.fill r21=[r3],16
+	;;
+	ld8.fill r22=[r2],16
+	ld8.fill r23=[r3],16
+	;;
+	ld8.fill r24=[r2],16
+	ld8.fill r25=[r3],16
+	;;
+	ld8.fill r26=[r2],16
+	ld8.fill r27=[r3],16
+	;;
+	ld8.fill r28=[r2],16
+	ld8.fill r29=[r3],16
+	;;
+	ld8.fill r30=[r2],16
+	ld8.fill r31=[r3],16
+	;;
+	ld8 r1=[r2],16		// ar.ccv
+	ld8 r13=[r3],16		// ar.fpsr
+	;;
+	ld8 r14=[r2],16		// b0
+	ld8 r15=[r3],16+8	// b7
+	;;
+	ldf.fill f6=[r2],32
+	ldf.fill f7=[r3],32
+	;;
+	ldf.fill f8=[r2],32
+	ldf.fill f9=[r3],32
+	;;
+	mov ar.ccv=r1
+	mov ar.fpsr=r13
+	mov b0=r14
+	// turn off interrupts, interrupt collection, & data translation
+	rsm psr.i | psr.ic | psr.dt
+	;;
+	srlz.i			// EAS 2.5
+	mov b7=r15
+	;;
+	invala			// invalidate ALAT
+	dep r12=0,r12,61,3	// convert sp to physical address
+	bsw.0;;			// switch back to bank 0 (must be last in insn group)
+	;;
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+	nop.i 0x0
+	;;
+	nop.i 0x0
+	;;
+	nop.i 0x0
+	;;
+#endif
+	adds r16=16,r12
+	adds r17=24,r12
+	;;
+	ld8 rCRIPSR=[r16],16	// load cr.ipsr
+	ld8 rCRIIP=[r17],16	// load cr.iip
+	;;
+	ld8 rCRIFS=[r16],16	// load cr.ifs
+	ld8 rARUNAT=[r17],16	// load ar.unat
+	;;
+	ld8 rARPFS=[r16],16	// load ar.pfs
+	ld8 rARRSC=[r17],16	// load ar.rsc
+	;;
+	ld8 rARRNAT=[r16],16	// load ar.rnat (may be garbage)
+	ld8 rARBSPSTORE=[r17],16	// load ar.bspstore (may be garbage)
+	;;
+	ld8 rARPR=[r16],16	// load predicates
+	ld8 rB6=[r17],16	// load b6
+	;;
+	ld8 r18=[r16],16	// load ar.rsc value for "loadrs"
+	ld8.fill r1=[r17],16	// load r1
+	;;
+	ld8.fill r2=[r16],16
+	ld8.fill r3=[r17],16
+	;;
+	ld8.fill r12=[r16],16
+	ld8.fill r13=[r17],16
+	extr.u r19=rCRIPSR,32,2	// extract ps.cpl
+	;;
+	ld8.fill r14=[r16],16
+	ld8.fill r15=[r17],16
+	cmp.eq p6,p7=r0,r19	// are we returning to kernel mode? (psr.cpl==0)
+	;;
+	mov b6=rB6
+	mov ar.pfs=rARPFS
+(p6)	br.cond.dpnt.few skip_rbs_switch
+
+	/*
+	 * Restore user backing store.
+	 *
+	 * NOTE: alloc, loadrs, and cover can't be predicated.
+	 *
+	 * XXX This needs some scheduling/tuning once we believe it
+	 *     really does work as intended.
+	 */
+	mov r16=ar.bsp			// get existing backing store pointer
+(pNonSys) br.cond.dpnt.few dont_preserve_current_frame
+	cover				// add current frame into dirty partition
+	;;
+	mov rCRIFS=cr.ifs		// fetch the cr.ifs value that "cover" produced
+	mov r17=ar.bsp			// get new backing store pointer
+	;;
+	sub r16=r17,r16			// calculate number of bytes that were added to rbs
+	;;
+	shl r16=r16,16			// shift additional frame size into position for loadrs
+	;;
+	add r18=r16,r18			// adjust the loadrs value
+	;;
+#ifdef CONFIG_IA64_SOFTSDV_HACKS
+	// Reset ITM if we've missed a timer tick.  Workaround for SoftSDV bug
+	mov r16 = r2
+	mov r2 = ar.itc
+	mov r17 = cr.itm
+	;; 
+	cmp.gt p6,p7 = r2, r17
+(p6)	addl r17 = 100, r2
+	;;
+	mov cr.itm = r17
+	mov r2 = r16
+#endif
+dont_preserve_current_frame:
+	alloc r16=ar.pfs,0,0,0,0	// drop the current call frame (noop for syscalls)
+	;;
+	mov ar.rsc=r18			// load ar.rsc to be used for "loadrs"
+#ifdef CONFIG_IA32_SUPPORT
+	tbit.nz p6,p0=rCRIPSR,IA64_PSR_IS_BIT
+	;;
+(p6)	mov ar.rsc=r0                   // returning to IA32 mode
+#endif
+ 	;;
+	loadrs
+	;;
+	mov ar.bspstore=rARBSPSTORE
+	;;
+	mov ar.rnat=rARRNAT	// must happen with RSE in lazy mode
+
+skip_rbs_switch:
+	mov ar.rsc=rARRSC
+	mov ar.unat=rARUNAT
+	mov cr.ifs=rCRIFS	// restore cr.ifs only if not a (synchronous) syscall
+(pEOI)	mov cr.eoi=r0
+	mov pr=rARPR,-1
+	mov cr.iip=rCRIIP
+	mov cr.ipsr=rCRIPSR
+	;;
+	rfi;;			// must be last instruction in an insn group
+
+handle_syscall_error:
+	/*
+	 * Some system calls (e.g., ptrace, mmap) can return arbitrary
+	 * values which could lead us to mistake a negative return
+	 * value as a failed syscall.  Those syscall must deposit
+	 * a non-zero value in pt_regs.r8 to indicate an error.
+	 * If pt_regs.r8 is zero, we assume that the call completed
+	 * successfully.
+	 */
+	ld8 r3=[r2]		// load pt_regs.r8
+	sub r9=0,r8		// negate return value to get errno
+	;;
+	mov r10=-1		// return -1 in pt_regs.r10 to indicate error
+	cmp.eq p6,p7=r3,r0	// is pt_regs.r8==0?
+	adds r3=16,r2		// r3=&pt_regs.r10
+	;;
+(p6)	mov r9=r8
+(p6)	mov r10=0
+	;;
+	st8.spill [r2]=r9	// store errno in pt_regs.r8 and set unat bit
+	st8.spill [r3]=r10	// store error indication in pt_regs.r10 and set unat bit
+	br.cond.sptk.many ia64_leave_kernel
+	.endp __ret_from_syscall
+
+#ifdef CONFIG_SMP
+	/*
+	 * Invoke schedule_tail(task) while preserving in0-in7, which may be needed
+	 * in case a system call gets restarted.
+	 */
+	.proc invoke_schedule_tail
+invoke_schedule_tail:
+	alloc loc0=ar.pfs,8,2,1,0
+	mov loc1=rp
+	mov out0=r8				// Address of previous task
+	;;
+	br.call.sptk.few rp=schedule_tail
+.ret8:
+	mov ar.pfs=loc0
+	mov rp=loc1
+	br.ret.sptk.many rp
+	.endp invoke_schedule_tail
+#endif /* CONFIG_SMP */
+
+	/*
+	 * Invoke do_bottom_half() while preserving in0-in7, which may be needed
+	 * in case a system call gets restarted.
+	 */
+	.proc invoke_do_bottom_half
+invoke_do_bottom_half:
+	alloc loc0=ar.pfs,8,2,0,0
+	mov loc1=rp
+	;;
+	br.call.sptk.few rp=do_bottom_half
+.ret9:
+	mov ar.pfs=loc0
+	mov rp=loc1
+	br.ret.sptk.many rp
+	.endp invoke_do_bottom_half
+
+	/*
+	 * Invoke schedule() while preserving in0-in7, which may be needed
+	 * in case a system call gets restarted.
+	 */
+	.proc invoke_schedule
+invoke_schedule:
+	alloc loc0=ar.pfs,8,2,0,0
+	mov loc1=rp
+	;;
+	br.call.sptk.few rp=schedule
+.ret10:
+	mov ar.pfs=loc0
+	mov rp=loc1
+	br.ret.sptk.many rp
+	.endp invoke_schedule
+
+	//
+	// Setup stack and call ia64_do_signal.  Note that pSys and pNonSys need to
+	// be set up by the caller.  We declare 8 input registers so the system call
+	// args get preserved, in case we need to restart a system call.
+	//
+	.align 16
+	.proc handle_signal_delivery
+handle_signal_delivery:
+	alloc loc0=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
+	mov r9=ar.unat
+
+	// If the process is being ptraced, the signal may not actually be delivered to
+	// the process.  Instead, SIGCHLD will be sent to the parent.  We need to
+	// setup a switch_stack so ptrace can inspect the processes state if necessary.
+	adds r2=IA64_TASK_FLAGS_OFFSET,r13
+	;;
+	ld8 r2=[r2]
+	mov out0=0				// there is no "oldset"
+	adds out1=16,sp				// out1=&pt_regs
+	;;
+(pSys)	mov out2=1				// out2==1 => we're in a syscall
+	tbit.nz p16,p17=r2,PF_PTRACED_BIT
+(p16)	br.cond.spnt.many setup_switch_stack
+	;;
+back_from_setup_switch_stack:
+(pNonSys) mov out2=0				// out2==0 => not a syscall
+	adds r3=-IA64_SWITCH_STACK_SIZE+IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp
+(p17)	adds sp=-IA64_SWITCH_STACK_SIZE,sp	// make space for (dummy) switch_stack
+	;;
+(p17)	st8 [r3]=r9				// save ar.unat in sw->caller_unat
+	mov loc1=rp				// save return address
+	br.call.sptk.few rp=ia64_do_signal
+.ret11:
+	adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp
+	;;
+	ld8 r9=[r3]				// load new unat from sw->caller_unat
+	mov rp=loc1
+	;;
+(p17)	adds sp=IA64_SWITCH_STACK_SIZE,sp	// drop (dummy) switch_stack
+(p17)	mov ar.unat=r9
+(p17)	mov ar.pfs=loc0
+(p17)	br.ret.sptk.many rp
+
+	// restore the switch stack (ptrace may have modified it):
+	movl r28=1f
+	br.cond.sptk.many load_switch_stack
+1:	br.ret.sptk.many rp
+	// NOT REACHED
+
+setup_switch_stack:
+	movl r28=back_from_setup_switch_stack
+	mov r16=loc0
+	br.cond.sptk.many save_switch_stack
+	// NOT REACHED
+
+	.endp handle_signal_delivery
+
+	.align 16
+	.proc sys_rt_sigsuspend
+	.global sys_rt_sigsuspend
+sys_rt_sigsuspend:
+	alloc loc0=ar.pfs,2,2,3,0
+	mov r9=ar.unat
+
+	// If the process is being ptraced, the signal may not actually be delivered to
+	// the process.  Instead, SIGCHLD will be sent to the parent.  We need to
+	// setup a switch_stack so ptrace can inspect the processes state if necessary.
+	adds r2=IA64_TASK_FLAGS_OFFSET,r13
+	;;
+	ld8 r2=[r2]
+	mov out0=in0				// mask
+	mov out1=in1				// sigsetsize
+	;;
+	adds out2=16,sp				// out1=&pt_regs
+	tbit.nz p16,p17=r2,PF_PTRACED_BIT
+(p16)	br.cond.spnt.many sigsuspend_setup_switch_stack
+	;;
+back_from_sigsuspend_setup_switch_stack:
+	adds r3=-IA64_SWITCH_STACK_SIZE+IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp
+(p17)	adds sp=-IA64_SWITCH_STACK_SIZE,sp	// make space for (dummy) switch_stack
+	;;
+(p17)	st8 [r3]=r9				// save ar.unat in sw->caller_unat
+	mov loc1=rp				// save return address
+	br.call.sptk.many rp=ia64_rt_sigsuspend
+.ret12:
+	adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp
+	;;
+	ld8 r9=[r3]				// load new unat from sw->caller_unat
+	mov rp=loc1
+	;;
+(p17)	adds sp=IA64_SWITCH_STACK_SIZE,sp	// drop (dummy) switch_stack
+(p17)	mov ar.unat=r9
+(p17)	mov ar.pfs=loc0
+(p17)	br.ret.sptk.many rp
+
+	// restore the switch stack (ptrace may have modified it):
+	movl r28=1f
+	br.cond.sptk.many load_switch_stack
+1:	br.ret.sptk.many rp
+	// NOT REACHED
+
+sigsuspend_setup_switch_stack:
+	movl r28=back_from_sigsuspend_setup_switch_stack
+	mov r16=loc0
+	br.cond.sptk.many save_switch_stack
+	// NOT REACHED
+
+	.endp sys_rt_sigsuspend
+
+	.align 16
+	.proc sys_rt_sigreturn
+sys_rt_sigreturn:
+	alloc loc0=ar.pfs,8,1,1,0 // preserve all eight input regs in case of syscall restart!
+	adds out0=16,sp				// out0 = &pt_regs
+	;;
+	adds sp=-IA64_SWITCH_STACK_SIZE,sp	// make space for unat and padding
+	br.call.sptk.few rp=ia64_rt_sigreturn
+.ret13:
+	adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp
+	;;
+	ld8 r9=[r3]			// load new ar.unat
+	mov rp=r8
+	;;
+	adds sp=IA64_SWITCH_STACK_SIZE,sp	// drop (dummy) switch-stack frame
+	mov ar.unat=r9
+	mov ar.pfs=loc0
+	br.ret.sptk.many rp
+	.endp sys_rt_sigreturn
+
+	.align 16
+	.global ia64_prepare_handle_unaligned
+	.proc ia64_prepare_handle_unaligned
+ia64_prepare_handle_unaligned:
+	movl r28=1f
+	//
+	// r16 = fake ar.pfs, we simply need to make sure 
+	// privilege is still 0
+	//
+	mov r16=r0 				
+	br.cond.sptk.few save_switch_stack
+1: 	br.call.sptk.few rp=ia64_handle_unaligned // stack frame setup in ivt
+.ret14:
+	movl r28=2f
+	br.cond.sptk.many load_switch_stack
+2:	br.cond.sptk.many rp			  // goes to ia64_leave_kernel
+	.endp ia64_prepare_handle_unaligned
+
+#ifdef CONFIG_KDB
+	//
+	// This gets called from ivt.S with:
+	//	SAVE MIN with cover done
+	//	SAVE REST done
+	//	no parameters
+	//	r15 has return value = ia64_leave_kernel
+	//
+	.align 16
+	.global ia64_invoke_kdb
+	.proc ia64_invoke_kdb
+ia64_invoke_kdb:
+	alloc r16=ar.pfs,0,0,4,0
+	movl r28=1f				// save_switch_stack protocol
+	;;			// avoid WAW on CFM
+	br.cond.sptk.many save_switch_stack	// to flushrs
+1:	mov out0=4				// kdb entry reason
+	mov out1=0				// err number
+	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// pt_regs
+	add out3=16,sp				// switch_stack
+	br.call.sptk.few rp=kdb
+.ret15:
+	movl r28=1f				// load_switch_stack proto
+	br.cond.sptk.many load_switch_stack
+1:	br.ret.sptk.many rp
+	.endp ia64_invoke_kdb
+
+	//
+	// When KDB is compiled in, we intercept each fault and give
+	// kdb a chance to run before calling the normal fault handler.
+	//
+        .align 16
+        .global ia64_invoke_kdb_fault_handler
+        .proc ia64_invoke_kdb_fault_handler
+ia64_invoke_kdb_fault_handler:
+        alloc r16=ar.pfs,5,1,5,0
+        movl r28=1f
+	mov loc0=rp			// save this
+	br.cond.sptk.many save_switch_stack // to flushrs
+	;;			// avoid WAW on CFM
+1:	mov out0=in0			// vector number
+	mov out1=in1			// cr.isr
+	mov out2=in2			// cr.ifa
+	mov out3=in3			// cr.iim
+	mov out4=in4			// cr.itir
+	br.call.sptk.few rp=ia64_kdb_fault_handler
+.ret16:
+
+	movl r28=1f
+	br.cond.sptk.many load_switch_stack
+1:	cmp.ne p6,p0=r8,r0		// did ia64_kdb_fault_handler return 0?
+	mov rp=loc0
+(p6)	br.ret.spnt.many rp		// no, we're done
+	;;		// avoid WAW on rp
+	mov out0=in0			// vector number
+	mov out1=in1			// cr.isr
+	mov out2=in2			// cr.ifa
+	mov out3=in3			// cr.iim
+	mov out4=in4			// cr.itir
+	mov in0=ar.pfs			// preserve ar.pfs returned by load_switch_stack
+	br.call.sptk.few rp=ia64_fault	// yup -> we need to invoke normal fault handler now
+.ret17:
+	mov ar.pfs=in0
+	mov rp=loc0
+	br.ret.sptk.many rp
+
+	.endp ia64_invoke_kdb_fault_handler
+
+#endif /* CONFIG_KDB */
+
+	.rodata
+	.align 8
+	.globl sys_call_table
+sys_call_table:
+	data8 sys_ni_syscall		//  This must be sys_ni_syscall!  See ivt.S.
+	data8 sys_exit				// 1025
+	data8 sys_read
+	data8 sys_write
+	data8 sys_open
+	data8 sys_close
+	data8 sys_creat				// 1030
+	data8 sys_link
+	data8 sys_unlink
+	data8 ia64_execve
+	data8 sys_chdir
+	data8 sys_fchdir			// 1035
+	data8 sys_utimes
+	data8 sys_mknod
+	data8 sys_chmod
+	data8 sys_chown
+	data8 sys_lseek				// 1040
+	data8 sys_getpid
+	data8 sys_getppid
+	data8 sys_mount
+	data8 sys_umount
+	data8 sys_setuid			// 1045
+	data8 sys_getuid
+	data8 sys_geteuid
+	data8 sys_ptrace
+	data8 sys_access
+	data8 sys_sync				// 1050
+	data8 sys_fsync
+	data8 sys_fdatasync
+	data8 sys_kill
+	data8 sys_rename
+	data8 sys_mkdir				// 1055
+	data8 sys_rmdir
+	data8 sys_dup
+	data8 sys_pipe
+	data8 sys_times
+	data8 ia64_brk				// 1060
+	data8 sys_setgid
+	data8 sys_getgid
+	data8 sys_getegid
+	data8 sys_acct
+	data8 sys_ioctl				// 1065
+	data8 sys_fcntl
+	data8 sys_umask
+	data8 sys_chroot
+	data8 sys_ustat
+	data8 sys_dup2				// 1070
+	data8 sys_setreuid
+	data8 sys_setregid
+	data8 sys_getresuid
+	data8 sys_setresuid
+	data8 sys_getresgid			// 1075
+	data8 sys_setresgid
+	data8 sys_getgroups
+	data8 sys_setgroups
+	data8 sys_getpgid
+	data8 sys_setpgid			// 1080
+	data8 sys_setsid
+	data8 sys_getsid
+	data8 sys_sethostname
+	data8 sys_setrlimit
+	data8 sys_getrlimit			// 1085
+	data8 sys_getrusage
+	data8 sys_gettimeofday
+	data8 sys_settimeofday
+	data8 sys_select
+	data8 sys_poll				// 1090
+	data8 sys_symlink
+	data8 sys_readlink
+	data8 sys_uselib
+	data8 sys_swapon
+	data8 sys_swapoff			// 1095
+	data8 sys_reboot
+	data8 sys_truncate
+	data8 sys_ftruncate
+	data8 sys_fchmod
+	data8 sys_fchown			// 1100
+	data8 ia64_getpriority
+	data8 sys_setpriority
+	data8 sys_statfs
+	data8 sys_fstatfs
+	data8 sys_ioperm			// 1105
+	data8 sys_semget
+	data8 sys_semop
+	data8 sys_semctl
+	data8 sys_msgget
+	data8 sys_msgsnd			// 1110
+	data8 sys_msgrcv
+	data8 sys_msgctl
+	data8 sys_shmget
+	data8 ia64_shmat
+	data8 sys_shmdt				// 1115
+	data8 sys_shmctl
+	data8 sys_syslog
+	data8 sys_setitimer
+	data8 sys_getitimer
+	data8 sys_newstat			// 1120
+	data8 sys_newlstat
+	data8 sys_newfstat
+	data8 sys_vhangup
+	data8 sys_lchown
+	data8 sys_vm86				// 1125
+	data8 sys_wait4
+	data8 sys_sysinfo
+	data8 sys_clone
+	data8 sys_setdomainname
+	data8 sys_newuname			// 1130
+	data8 sys_adjtimex
+	data8 sys_create_module
+	data8 sys_init_module
+	data8 sys_delete_module
+	data8 sys_get_kernel_syms		// 1135
+	data8 sys_query_module
+	data8 sys_quotactl
+	data8 sys_bdflush
+	data8 sys_sysfs
+	data8 sys_personality			// 1140
+	data8 ia64_ni_syscall		// sys_afs_syscall
+	data8 sys_setfsuid
+	data8 sys_setfsgid
+	data8 sys_getdents
+	data8 sys_flock				// 1145
+	data8 sys_readv
+	data8 sys_writev
+	data8 sys_pread
+	data8 sys_pwrite
+	data8 sys_sysctl			// 1150
+	data8 sys_mmap
+	data8 sys_munmap
+	data8 sys_mlock
+	data8 sys_mlockall
+	data8 sys_mprotect			// 1155
+	data8 sys_mremap
+	data8 sys_msync
+	data8 sys_munlock
+	data8 sys_munlockall
+	data8 sys_sched_getparam		// 1160
+	data8 sys_sched_setparam
+	data8 sys_sched_getscheduler
+	data8 sys_sched_setscheduler
+	data8 sys_sched_yield
+	data8 sys_sched_get_priority_max	// 1165
+	data8 sys_sched_get_priority_min
+	data8 sys_sched_rr_get_interval
+	data8 sys_nanosleep
+	data8 sys_nfsservctl
+	data8 sys_prctl				// 1170
+	data8 sys_getpagesize
+	data8 sys_mmap2
+	data8 sys_pciconfig_read
+	data8 sys_pciconfig_write
+	data8 sys_perfmonctl			// 1175
+	data8 sys_sigaltstack
+	data8 sys_rt_sigaction
+	data8 sys_rt_sigpending
+	data8 sys_rt_sigprocmask
+	data8 sys_rt_sigqueueinfo		// 1180
+	data8 sys_rt_sigreturn
+	data8 sys_rt_sigsuspend
+	data8 sys_rt_sigtimedwait
+	data8 sys_getcwd
+	data8 sys_capget			// 1185
+	data8 sys_capset
+	data8 sys_sendfile
+	data8 sys_ni_syscall		// sys_getpmsg (STREAMS)
+	data8 sys_ni_syscall		// sys_putpmsg (STREAMS)
+	data8 sys_socket			// 1190
+	data8 sys_bind
+	data8 sys_connect
+	data8 sys_listen
+	data8 sys_accept
+	data8 sys_getsockname			// 1195
+	data8 sys_getpeername
+	data8 sys_socketpair 
+	data8 sys_send
+	data8 sys_sendto
+	data8 sys_recv				// 1200
+	data8 sys_recvfrom
+	data8 sys_shutdown
+	data8 sys_setsockopt
+	data8 sys_getsockopt
+	data8 sys_sendmsg			// 1205
+	data8 sys_recvmsg
+	data8 sys_pivot_root
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1210
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1215
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1220
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1225
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1230
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1235
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1240
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1245
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1250
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1255
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1260
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1265
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1270
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall			// 1275
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+	data8 ia64_ni_syscall
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/entry.h linux/arch/ia64/kernel/entry.h
--- v2.3.42/linux/arch/ia64/kernel/entry.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/entry.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,8 @@
+/*
+ * Preserved registers that are shared between code in ivt.S and entry.S.  Be
+ * careful not to step on these!
+ */
+#define pEOI		p1	/* should leave_kernel write EOI? */
+#define pKern		p2	/* will leave_kernel return to kernel-mode? */
+#define pSys		p4	/* are we processing a (synchronous) system call? */
+#define pNonSys		p5	/* complement of pSys */
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/fw-emu.c linux/arch/ia64/kernel/fw-emu.c
--- v2.3.42/linux/arch/ia64/kernel/fw-emu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/fw-emu.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,444 @@
+/*
+ * PAL & SAL emulation.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * For the HP simulator, this file gets include in boot/bootloader.c.
+ * For SoftSDV, this file gets included in sys_softsdv.c.
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+# include <linux/pci.h>
+#endif
+
+#include <asm/efi.h>
+#include <asm/io.h>
+#include <asm/pal.h>
+#include <asm/sal.h>
+
+#define MB	(1024*1024UL)
+
+#define NUM_MEM_DESCS	3
+
+static char fw_mem[(  sizeof(efi_system_table_t)
+		    + sizeof(efi_runtime_services_t)
+		    + 1*sizeof(efi_config_table_t)
+		    + sizeof(struct ia64_sal_systab)
+		    + sizeof(struct ia64_sal_desc_entry_point)
+		    + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t))
+		    + 1024)] __attribute__ ((aligned (8)));
+
+#ifdef CONFIG_IA64_HP_SIM
+
+/* Simulator system calls: */
+
+#define SSC_EXIT	66
+
+/*
+ * Simulator system call.
+ */
+static long
+ssc (long arg0, long arg1, long arg2, long arg3, int nr)
+{
+	register long r8 asm ("r8");
+
+	asm volatile ("mov r15=%1\n\t"
+		      "break 0x80001"
+		      : "=r"(r8)
+		      : "r"(nr), "r"(arg0), "r"(arg1), "r"(arg2), "r"(arg3));
+	return r8;
+}
+
+#define SECS_PER_HOUR   (60 * 60)
+#define SECS_PER_DAY    (SECS_PER_HOUR * 24)
+
+/* Compute the `struct tm' representation of *T,
+   offset OFFSET seconds east of UTC,
+   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
+   Return nonzero if successful.  */
+int
+offtime (unsigned long t, efi_time_t *tp)
+{
+	const unsigned short int __mon_yday[2][13] =
+	{
+		/* Normal years.  */
+		{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+		/* Leap years.  */
+		{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+	};
+	long int days, rem, y;
+	const unsigned short int *ip;
+
+	days = t / SECS_PER_DAY;
+	rem = t % SECS_PER_DAY;
+	while (rem < 0) {
+		rem += SECS_PER_DAY;
+		--days;
+	}
+	while (rem >= SECS_PER_DAY) {
+		rem -= SECS_PER_DAY;
+		++days;
+	}
+	tp->hour = rem / SECS_PER_HOUR;
+	rem %= SECS_PER_HOUR;
+	tp->minute = rem / 60;
+	tp->second = rem % 60;
+	/* January 1, 1970 was a Thursday.  */
+	y = 1970;
+
+#	define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#	define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+#	define __isleap(year) \
+	  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+	while (days < 0 || days >= (__isleap (y) ? 366 : 365)) {
+		/* Guess a corrected year, assuming 365 days per year.  */
+		long int yg = y + days / 365 - (days % 365 < 0);
+
+		/* Adjust DAYS and Y to match the guessed year.  */
+		days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)
+			 - LEAPS_THRU_END_OF (y - 1));
+		y = yg;
+	}
+	tp->year = y;
+	ip = __mon_yday[__isleap(y)];
+	for (y = 11; days < (long int) ip[y]; --y)
+		continue;
+	days -= ip[y];
+	tp->month = y + 1;
+	tp->day = days + 1;
+	return 1;
+}
+
+#endif /* CONFIG_IA64_HP_SIM */
+
+/*
+ * Very ugly, but we need this in the simulator only.  Once we run on
+ * real hw, this can all go away.
+ */
+extern void pal_emulator_static (void);
+
+asm ("
+	.proc pal_emulator_static
+pal_emulator_static:
+	mov r8=-1
+	cmp.eq p6,p7=6,r28		/* PAL_PTCE_INFO */
+(p7)	br.cond.sptk.few 1f
+	;;
+	mov r8=0			/* status = 0 */
+	movl r9=0x100000000		/* tc.base */
+	movl r10=0x0000000200000003	/* count[0], count[1] */
+	movl r11=0x1000000000002000	/* stride[0], stride[1] */
+	br.cond.sptk.few rp
+
+1:	cmp.eq p6,p7=14,r28		/* PAL_FREQ_RATIOS */
+(p7)	br.cond.sptk.few 1f
+	mov r8=0			/* status = 0 */
+	movl r9 =0x100000064		/* proc_ratio (1/100) */
+	movl r10=0x100000100		/* bus_ratio<<32 (1/256) */
+	movl r11=0x100000064		/* itc_ratio<<32 (1/100) */
+1:	br.cond.sptk.few rp
+	.endp pal_emulator_static\n");
+
+/* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */
+
+#define BUILD_CMD(addr)		((0x80000000 | (addr)) & ~3)
+
+#define REG_OFFSET(addr)	(0x00000000000000FF & (addr))
+#define DEVICE_FUNCTION(addr)	(0x000000000000FF00 & (addr))
+#define BUS_NUMBER(addr)	(0x0000000000FF0000 & (addr))
+
+static efi_status_t
+efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
+{
+#ifdef CONFIG_IA64_HP_SIM
+	struct {
+		int tv_sec;	/* must be 32bits to work */
+		int tv_usec;
+	} tv32bits;
+
+	ssc((unsigned long) &tv32bits, 0, 0, 0, SSC_GET_TOD);
+
+	memset(tm, 0, sizeof(*tm));
+	offtime(tv32bits.tv_sec, tm);
+
+	if (tc)
+		memset(tc, 0, sizeof(*tc));
+#else
+#	error Not implemented yet...
+#endif
+	return EFI_SUCCESS;
+}
+
+static void
+efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
+{
+#ifdef CONFIG_IA64_HP_SIM
+	ssc(status, 0, 0, 0, SSC_EXIT);
+#else
+#	error Not implemented yet...
+#endif
+}
+
+static efi_status_t
+efi_unimplemented (void)
+{
+	return EFI_UNSUPPORTED;
+}
+
+static long
+sal_emulator (long index, unsigned long in1, unsigned long in2,
+	      unsigned long in3, unsigned long in4, unsigned long in5,
+	      unsigned long in6, unsigned long in7)
+{
+	register long r9 asm ("r9") = 0;
+	register long r10 asm ("r10") = 0;
+	register long r11 asm ("r11") = 0;
+	long status;
+
+	/*
+	 * Don't do a "switch" here since that gives us code that
+	 * isn't self-relocatable.
+	 */
+	status = 0;
+	if (index == SAL_FREQ_BASE) {
+		switch (in1) {
+		      case SAL_FREQ_BASE_PLATFORM:
+			r9 = 100000000;
+			break;
+
+		      case SAL_FREQ_BASE_INTERVAL_TIMER:
+			/*
+			 * Is this supposed to be the cr.itc frequency
+			 * or something platform specific?  The SAL
+			 * doc ain't exactly clear on this...
+			 */
+#if defined(CONFIG_IA64_SOFTSDV_HACKS)
+			r9 =   4000000;
+#elif defined(CONFIG_IA64_SDV)
+			r9 = 300000000;
+#else
+			r9 = 700000000;
+#endif
+			break;
+
+		      case SAL_FREQ_BASE_REALTIME_CLOCK:
+			r9 = 1;
+			break;
+
+		      default:
+			status = -1;
+			break;
+		}
+	} else if (index == SAL_SET_VECTORS) {
+		;
+	} else if (index == SAL_GET_STATE_INFO) {
+		;
+	} else if (index == SAL_GET_STATE_INFO_SIZE) {
+		;
+	} else if (index == SAL_CLEAR_STATE_INFO) {
+		;
+	} else if (index == SAL_MC_RENDEZ) {
+		;
+	} else if (index == SAL_MC_SET_PARAMS) {
+		;
+	} else if (index == SAL_CACHE_FLUSH) {
+		;
+	} else if (index == SAL_CACHE_INIT) {
+		;
+#ifdef CONFIG_PCI
+	} else if (index == SAL_PCI_CONFIG_READ) {
+		/*
+		 * in1 contains the PCI configuration address and in2
+		 * the size of the read.  The value that is read is
+		 * returned via the general register r9.
+		 */
+                outl(BUILD_CMD(in1), 0xCF8);
+                if (in2 == 1)                           /* Reading byte  */
+                        r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3)));
+                else if (in2 == 2)                      /* Reading word  */
+                        r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2)));
+                else                                    /* Reading dword */
+                        r9 = inl(0xCFC);
+                status = PCIBIOS_SUCCESSFUL;
+	} else if (index == SAL_PCI_CONFIG_WRITE) {
+	      	/*
+		 * in1 contains the PCI configuration address, in2 the
+		 * size of the write, and in3 the actual value to be
+		 * written out.
+		 */
+                outl(BUILD_CMD(in1), 0xCF8);
+                if (in2 == 1)                           /* Writing byte  */
+                        outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3)));
+                else if (in2 == 2)                      /* Writing word  */
+                        outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2)));
+                else                                    /* Writing dword */
+                        outl(in3, 0xCFC);
+                status = PCIBIOS_SUCCESSFUL;
+#endif /* CONFIG_PCI */
+	} else if (index == SAL_UPDATE_PAL) {
+		;
+	} else {
+		status = -1;
+	}
+	asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11));
+	return status;
+}
+
+
+/*
+ * This is here to work around a bug in egcs-1.1.1b that causes the
+ * compiler to crash (seems like a bug in the new alias analysis code.
+ */
+void *
+id (long addr)
+{
+	return (void *) addr;
+}
+
+void
+sys_fw_init (const char *args, int arglen)
+{
+	efi_system_table_t *efi_systab;
+	efi_runtime_services_t *efi_runtime;
+	efi_config_table_t *efi_tables;
+	struct ia64_sal_systab *sal_systab;
+	efi_memory_desc_t *efi_memmap, *md;
+	unsigned long *pal_desc, *sal_desc;
+	struct ia64_sal_desc_entry_point *sal_ed;
+	struct ia64_boot_param *bp;
+	unsigned char checksum = 0;
+	char *cp, *cmd_line;
+
+	memset(fw_mem, 0, sizeof(fw_mem));
+
+	pal_desc = (unsigned long *) &pal_emulator_static;
+	sal_desc = (unsigned long *) &sal_emulator;
+
+	cp = fw_mem;
+	efi_systab  = (void *) cp; cp += sizeof(*efi_systab);
+	efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
+	efi_tables  = (void *) cp; cp += sizeof(*efi_tables);
+	sal_systab  = (void *) cp; cp += sizeof(*sal_systab);
+	sal_ed      = (void *) cp; cp += sizeof(*sal_ed);
+	efi_memmap  = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
+	cmd_line    = (void *) cp;
+
+	if (args) {
+		if (arglen >= 1024)
+			arglen = 1023;
+		memcpy(cmd_line, args, arglen);
+	} else {
+		arglen = 0;
+	}
+	cmd_line[arglen] = '\0';
+
+	memset(efi_systab, 0, sizeof(efi_systab));
+	efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
+	efi_systab->hdr.revision  = EFI_SYSTEM_TABLE_REVISION;
+	efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
+	efi_systab->fw_vendor = __pa("H\0e\0w\0l\0e\0t\0t\0-\0P\0a\0c\0k\0a\0r\0d\0\0");
+	efi_systab->fw_revision = 1;
+	efi_systab->runtime = __pa(efi_runtime);
+	efi_systab->nr_tables = 1;
+	efi_systab->tables = __pa(efi_tables);
+
+	efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
+	efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
+	efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
+	efi_runtime->get_time = __pa(&efi_get_time);
+	efi_runtime->set_time = __pa(&efi_unimplemented);
+	efi_runtime->get_wakeup_time = __pa(&efi_unimplemented);
+	efi_runtime->set_wakeup_time = __pa(&efi_unimplemented);
+	efi_runtime->set_virtual_address_map = __pa(&efi_unimplemented);
+	efi_runtime->get_variable = __pa(&efi_unimplemented);
+	efi_runtime->get_next_variable = __pa(&efi_unimplemented);
+	efi_runtime->set_variable = __pa(&efi_unimplemented);
+	efi_runtime->get_next_high_mono_count = __pa(&efi_unimplemented);
+	efi_runtime->reset_system = __pa(&efi_reset_system);
+
+	efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
+	efi_tables->table = __pa(sal_systab);
+
+	/* fill in the SAL system table: */
+	memcpy(sal_systab->signature, "SST_", 4);
+	sal_systab->size = sizeof(*sal_systab);
+	sal_systab->sal_rev_minor = 1;
+	sal_systab->sal_rev_major = 0;
+	sal_systab->entry_count = 1;
+	sal_systab->ia32_bios_present = 0;
+
+#ifdef CONFIG_IA64_GENERIC
+        strcpy(sal_systab->oem_id, "Generic");
+        strcpy(sal_systab->product_id, "IA-64 system");
+#endif
+
+#ifdef CONFIG_IA64_HP_SIM
+	strcpy(sal_systab->oem_id, "Hewlett-Packard");
+	strcpy(sal_systab->product_id, "HP-simulator");
+#endif
+
+#ifdef CONFIG_IA64_SDV
+	strcpy(sal_systab->oem_id, "Intel");
+	strcpy(sal_systab->product_id, "SDV");
+#endif
+
+#ifdef CONFIG_IA64_SGI_SN1_SIM
+	strcpy(sal_systab->oem_id, "SGI");
+	strcpy(sal_systab->product_id, "SN1");
+#endif
+
+	/* fill in an entry point: */	
+	sal_ed->type = SAL_DESC_ENTRY_POINT;
+	sal_ed->pal_proc = __pa(pal_desc[0]);
+	sal_ed->sal_proc = __pa(sal_desc[0]);
+	sal_ed->gp = __pa(sal_desc[1]);
+
+	for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
+		checksum += *cp;
+
+	sal_systab->checksum = -checksum;
+
+	/* fill in a memory descriptor: */
+	md = &efi_memmap[0];
+	md->type = EFI_CONVENTIONAL_MEMORY;
+	md->pad = 0;
+	md->phys_addr = 2*MB;
+	md->virt_addr = 0;
+	md->num_pages = (64*MB) >> 12;	/* 64MB (in 4KB pages) */
+	md->attribute = EFI_MEMORY_WB;
+
+	/* descriptor for firmware emulator: */
+	md = &efi_memmap[1];
+	md->type = EFI_RUNTIME_SERVICES_DATA;
+	md->pad = 0;
+	md->phys_addr = 1*MB;
+	md->virt_addr = 0;
+	md->num_pages = (1*MB) >> 12;	/* 1MB (in 4KB pages) */
+	md->attribute = EFI_MEMORY_WB;
+
+	/* descriptor for high memory (>4GB): */
+	md = &efi_memmap[2];
+	md->type = EFI_CONVENTIONAL_MEMORY;
+	md->pad = 0;
+	md->phys_addr = 4096*MB;
+	md->virt_addr = 0;
+	md->num_pages = (32*MB) >> 12;	/* 32MB (in 4KB pages) */
+	md->attribute = EFI_MEMORY_WB;
+
+	bp = id(ZERO_PAGE_ADDR);
+	bp->efi_systab = __pa(&fw_mem);
+	bp->efi_memmap = __pa(efi_memmap);
+	bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t);
+	bp->efi_memdesc_size = sizeof(efi_memory_desc_t);
+	bp->efi_memdesc_version = 1;
+	bp->command_line = __pa(cmd_line);
+	bp->console_info.num_cols = 80;
+	bp->console_info.num_rows = 25;
+	bp->console_info.orig_x = 0;
+	bp->console_info.orig_y = 24;
+	bp->num_pci_vectors = 0;
+	bp->fpswa = 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/gate.S linux/arch/ia64/kernel/gate.S
--- v2.3.42/linux/arch/ia64/kernel/gate.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/gate.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,200 @@
+/*
+ * This file contains the code that gets mapped at the upper end of
+ * each task's text region.  For now, it contains the signal
+ * trampoline code only.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/offsets.h>
+#include <asm/sigcontext.h>
+#include <asm/system.h>
+#include <asm/unistd.h>
+#include <asm/page.h>
+
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.section __gate_section,"ax"
+
+	.align PAGE_SIZE
+
+#	define SIGINFO_OFF	16
+#	define SIGCONTEXT_OFF	(SIGINFO_OFF + ((IA64_SIGINFO_SIZE + 15) & ~15))
+#	define FLAGS_OFF	IA64_SIGCONTEXT_FLAGS_OFFSET
+#	define CFM_OFF		IA64_SIGCONTEXT_CFM_OFFSET
+#	define FR6_OFF		IA64_SIGCONTEXT_FR6_OFFSET
+#	define BSP_OFF		IA64_SIGCONTEXT_AR_BSP_OFFSET
+#	define RNAT_OFF		IA64_SIGCONTEXT_AR_RNAT_OFFSET
+#	define base0		r2
+#	define base1		r3
+	/*
+	 * When we get here, the memory stack looks like this:
+	 *
+	 *   +===============================+
+       	 *   |				     |
+       	 *   //	    struct sigcontext        //
+       	 *   |				     |
+	 *   +===============================+ <-- sp+SIGCONTEXT_OFF
+       	 *   |				     |
+	 *   //     rest of siginfo    	     //
+       	 *   | 			   	     |
+       	 *   +               +---------------+
+       	 *   | 		     | siginfo.code  |
+	 *   +---------------+---------------+
+	 *   | siginfo.errno | siginfo.signo |
+	 *   +-------------------------------+ <-- sp+SIGINFO_OFF
+	 *   |      16 byte of scratch       |
+	 *   |            space              |
+	 *   +-------------------------------+ <-- sp
+	 *
+	 * The register stack looks _exactly_ the way it looked at the
+	 * time the signal occurred.  In other words, we're treading
+	 * on a potential mine-field: each incoming general register
+	 * may be a NaT value (includeing sp, in which case the process
+	 * ends up dying with a SIGSEGV).
+	 *
+	 * The first need to do is a cover to get the registers onto
+	 * the backing store.  Once that is done, we invoke the signal
+	 * handler which may modify some of the machine state.  After
+	 * returning from the signal handler, we return control to the
+	 * previous context by executing a sigreturn system call.  A
+	 * signal handler may call the rt_sigreturn() function to
+	 * directly return to a given sigcontext.  However, the
+	 * user-level sigreturn() needs to do much more than calling
+	 * the rt_sigreturn() system call as it needs to unwind the
+	 * stack to restore preserved registers that may have been
+	 * saved on the signal handler's call stack.
+	 *
+	 * On entry:
+	 *	r2	= signal number
+	 *	r3	= plabel of signal handler
+	 *	r15	= new register backing store (ignored)
+	 *	[sp+16] = sigframe
+	 */
+
+	.global ia64_sigtramp
+	.proc ia64_sigtramp
+ia64_sigtramp:
+	ld8 r10=[r3],8				// get signal handler entry point
+	br.call.sptk.many rp=invoke_sighandler
+.ret0:	mov r15=__NR_rt_sigreturn
+	break __BREAK_SYSCALL
+	.endp ia64_sigramp
+
+	.proc invoke_sighandler
+invoke_sighandler:
+	ld8 gp=[r3]			// get signal handler's global pointer
+	mov b6=r10
+	cover				// push args in interrupted frame onto backing store
+	;;
+	alloc r8=ar.pfs,0,1,3,0		// get CFM0, EC0, and CPL0 into r8
+	mov r17=ar.bsp			// fetch ar.bsp
+	mov loc0=rp			// save return pointer
+	;;
+	cmp.ne p8,p0=r15,r0		// do we need to switch the rbs?
+	mov out0=r2			// signal number
+(p8)	br.cond.spnt.few setup_rbs	// yup -> (clobbers r14 and r16)
+back_from_setup_rbs:
+	adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
+	;;
+	st8 [base0]=r17,(CFM_OFF-BSP_OFF)	// save sc_ar_bsp
+	adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
+	;;
+
+	st8 [base0]=r8				// save CFM0, EC0, and CPL0
+	adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
+	;;
+	stf.spill [base0]=f6,32
+	stf.spill [base1]=f7,32
+	;;
+	stf.spill [base0]=f8,32
+	stf.spill [base1]=f9,32
+	;;
+	stf.spill [base0]=f10,32
+	stf.spill [base1]=f11,32
+	adds out1=SIGINFO_OFF,sp	// siginfo pointer
+	;;
+	stf.spill [base0]=f12,32
+	stf.spill [base1]=f13,32
+	adds out2=SIGCONTEXT_OFF,sp	// sigcontext pointer
+	;;
+	stf.spill [base0]=f14,32
+	stf.spill [base1]=f15,32
+	br.call.sptk.few rp=b6			// call the signal handler
+.ret2:	adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
+	;;
+	ld8 r15=[base0],(CFM_OFF-BSP_OFF)	// fetch sc_ar_bsp and advance to CFM_OFF
+	mov r14=ar.bsp
+	;;
+	ld8 r8=[base0]				// restore (perhaps modified) CFM0, EC0, and CPL0
+	cmp.ne p8,p0=r14,r15			// do we need to restore the rbs?
+(p8)	br.cond.spnt.few restore_rbs		// yup -> (clobbers r14 and r16)
+back_from_restore_rbs:
+	{
+	  and r9=0x7f,r8			// r9  <- CFM0.sof
+	  extr.u r10=r8,7,7			// r10 <- CFM0.sol
+	  mov r11=ip
+	}
+	;;
+	adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
+	adds r11=(cont-back_from_restore_rbs),r11
+	sub r9=r9,r10				// r9 <- CFM0.sof - CFM0.sol == CFM0.nout
+	;;
+	adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
+	dep r9=r9,r9,7,7			// r9.sol = r9.sof
+	mov b6=r11
+	;;
+	ldf.fill f6=[base0],32
+	ldf.fill f7=[base1],32
+	mov rp=loc0			// copy return pointer out of stacked register
+	;;
+	ldf.fill f8=[base0],32
+	ldf.fill f9=[base1],32
+	;;
+	ldf.fill f10=[base0],32
+	ldf.fill f11=[base1],32
+	;;
+	ldf.fill f12=[base0],32
+	ldf.fill f13=[base1],32
+	mov ar.pfs=r9
+	;;
+	ldf.fill f14=[base0],32
+	ldf.fill f15=[base1],32
+	br.ret.sptk.few b6
+cont:	mov ar.pfs=r8				// ar.pfs = CFM0
+	br.ret.sptk.few rp			// re-establish CFM0
+	.endp invoke_signal_handler
+
+	.proc setup_rbs
+setup_rbs:
+	flushrs					// must be first in insn
+	;;
+	mov ar.rsc=r0				// put RSE into enforced lazy mode
+	adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
+	mov r14=ar.rnat				// get rnat as updated by flushrs
+	;;
+	mov ar.bspstore=r15			// set new register backing store area
+	st8 [r16]=r14				// save sc_ar_rnat
+	;;
+	mov ar.rsc=0xf				// set RSE into eager mode, pl 3
+	invala					// invalidate ALAT
+	br.cond.sptk.many back_from_setup_rbs
+
+	.proc restore_rbs
+restore_rbs:
+	flushrs
+	mov ar.rsc=r0				// put RSE into enforced lazy mode
+	adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
+	;;
+	ld8 r14=[r16]				// get new rnat
+	mov ar.bspstore=r15			// set old register backing store area
+	;;
+	mov ar.rnat=r14				// establish new rnat
+	mov ar.rsc=0xf				// (will be restored later on from sc_ar_rsc)
+	// invala not necessary as that will happen when returning to user-mode
+	br.cond.sptk.many back_from_restore_rbs
+
+	.endp restore_rbs
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/head.S linux/arch/ia64/kernel/head.S
--- v2.3.42/linux/arch/ia64/kernel/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/head.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,646 @@
+/*
+ * Here is where the ball gets rolling as far as the kernel is concerned.
+ * When control is transferred to _start, the bootload has already
+ * loaded us to the correct address.  All that's left to do here is
+ * to set up the kernel's global pointer and jump to the kernel
+ * entry point.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 Intel Corp.
+ * Copyright (C) 1999 Asit Mallick <Asit.K.Mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <Don.Dugger@intel.com>
+ */
+
+#include <linux/config.h>
+
+#include <asm/fpu.h>
+#include <asm/pal.h>
+#include <asm/offsets.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.section __special_page_section,"ax"
+
+	.global empty_zero_page
+empty_zero_page:
+	.skip PAGE_SIZE
+
+	.global swapper_pg_dir
+swapper_pg_dir:
+	.skip PAGE_SIZE
+
+	.global empty_bad_page
+empty_bad_page:
+	.skip PAGE_SIZE
+
+	.global empty_bad_pte_table
+empty_bad_pte_table:
+	.skip PAGE_SIZE
+
+	.global empty_bad_pmd_table
+empty_bad_pmd_table:
+	.skip PAGE_SIZE
+
+	.rodata
+halt_msg:
+	stringz "Halting kernel\n"
+
+	.text
+	.align 16
+	.global _start
+	.proc _start
+_start:
+	// set IVT entry point---can't access I/O ports without it
+	movl r3=ia64_ivt
+	;;
+	mov cr.iva=r3
+	movl r2=FPSR_DEFAULT
+	;;
+	srlz.i
+	movl gp=__gp
+
+	mov ar.fpsr=r2
+	;;
+
+#ifdef CONFIG_IA64_EARLY_PRINTK
+	mov r2=6
+	mov r3=(8<<8) | (28<<2)
+	;;
+	mov rr[r2]=r3
+	;;
+	srlz.i
+	;;
+#endif
+
+#define isAP	p2	// are we booting an Application Processor (not the BSP)?
+
+	// Find the init_task for the currently booting CPU.  At poweron, and in
+	// UP mode, cpu_now_booting is 0
+	movl r3=cpu_now_booting
+ 	;;
+	ld4 r3=[r3]
+	movl r2=init_tasks
+	;; 
+	shladd r2=r3,3,r2
+	;;
+	ld8 r2=[r2]
+	cmp4.ne isAP,p0=r3,r0	// p9 == true if this is an application processor (ap)
+	;;			// RAW on r2
+	extr r3=r2,0,61		// r3 == phys addr of task struct
+	;;
+
+	// load the "current" pointer (r13) and ar.k6 with the current task 
+	mov r13=r2
+	mov ar.k6=r3		// Physical address
+	;;
+	/*
+	 * Reserve space at the top of the stack for "struct pt_regs".  Kernel threads
+	 * don't store interesting values in that structure, but the space still needs
+	 * to be there because time-critical stuff such as the context switching can
+	 * be implemented more efficiently (for example, __switch_to()
+	 * always sets the psr.dfh bit of the task it is switching to).
+	 */
+	addl r12=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
+	addl r2=IA64_RBS_OFFSET,r2	// initialize the RSE
+	mov ar.rsc=r0		// place RSE in enforced lazy mode
+	;;
+	mov ar.bspstore=r2	// establish the new RSE stack
+	;;
+	loadrs			// load zero bytes from the register stack
+	;;
+	mov ar.rsc=0x3		// place RSE in eager mode
+	;;
+
+#ifdef CONFIG_IA64_EARLY_PRINTK
+	.rodata
+alive_msg:
+	stringz "I'm alive and well\n"
+	.previous
+
+	alloc r2=ar.pfs,0,0,2,0
+	movl out0=alive_msg
+	;;
+	br.call.sptk.few rp=early_printk
+1:	// force new bundle
+#endif /* CONFIG_IA64_EARLY_PRINTK */
+
+	alloc r2=ar.pfs,8,0,2,0
+#ifdef CONFIG_SMP
+(isAP)	br.call.sptk.few rp=smp_callin
+.ret1:
+(isAP)	br.cond.sptk.few self
+#endif
+
+#undef isAP
+
+	// This is executed by the bootstrap processor (bsp) only:
+
+#ifdef CONFIG_IA64_FW_EMU
+	// initialize PAL & SAL emulator:
+	br.call.sptk.few rp=sys_fw_init
+	;;
+#endif
+	br.call.sptk.few rp=start_kernel
+.ret2:
+	addl r2=@ltoff(halt_msg),gp
+	;;
+	ld8 out0=[r2]
+	br.call.sptk.few b0=console_print
+self:	br.sptk.few self		// endless loop
+	.endp _start
+
+	.align 16
+	.global ia64_save_debug_regs
+	.proc ia64_save_debug_regs
+ia64_save_debug_regs:
+	alloc r16=ar.pfs,1,0,0,0
+	mov r20=ar.lc			// preserve ar.lc
+	mov ar.lc=IA64_NUM_DBG_REGS-1
+	mov r18=0
+	add r19=IA64_NUM_DBG_REGS*8,in0
+	;;
+1:	mov r16=dbr[r18]
+	mov r17=ibr[r18]
+	add r18=1,r18
+	;;
+	st8.nta [in0]=r16,8
+	st8.nta [r19]=r17,8
+	br.cloop.sptk.few 1b
+
+	mov ar.lc=r20			// restore ar.lc
+	br.ret.sptk.few b0
+	.endp ia64_save_debug_regs
+
+	.align 16
+	.global ia64_load_debug_regs
+	.proc ia64_load_debug_regs
+ia64_load_debug_regs:
+	alloc r16=ar.pfs,1,0,0,0
+	lfetch.nta [in0]
+	mov r20=ar.lc			// preserve ar.lc
+	add r19=IA64_NUM_DBG_REGS*8,in0
+	mov ar.lc=IA64_NUM_DBG_REGS-1
+	mov r18=-1
+	;;
+1:	ld8.nta r16=[in0],8
+	ld8.nta r17=[r19],8
+	add r18=1,r18
+	;;
+	mov dbr[r18]=r16
+	mov ibr[r18]=r17
+	br.cloop.sptk.few 1b
+
+	mov ar.lc=r20			// restore ar.lc
+	br.ret.sptk.few b0
+	.endp ia64_load_debug_regs
+
+	.align 16
+	.global __ia64_save_fpu
+	.proc __ia64_save_fpu
+__ia64_save_fpu:
+	alloc r2=ar.pfs,1,0,0,0
+	adds r3=16,in0
+	;;
+	stf.spill.nta [in0]=f32,32
+	stf.spill.nta [ r3]=f33,32
+	;;
+	stf.spill.nta [in0]=f34,32
+	stf.spill.nta [ r3]=f35,32
+	;;
+	stf.spill.nta [in0]=f36,32
+	stf.spill.nta [ r3]=f37,32
+	;;
+	stf.spill.nta [in0]=f38,32
+	stf.spill.nta [ r3]=f39,32
+	;;
+	stf.spill.nta [in0]=f40,32
+	stf.spill.nta [ r3]=f41,32
+	;;
+	stf.spill.nta [in0]=f42,32
+	stf.spill.nta [ r3]=f43,32
+	;;
+	stf.spill.nta [in0]=f44,32
+	stf.spill.nta [ r3]=f45,32
+	;;
+	stf.spill.nta [in0]=f46,32
+	stf.spill.nta [ r3]=f47,32
+	;;
+	stf.spill.nta [in0]=f48,32
+	stf.spill.nta [ r3]=f49,32
+	;;
+	stf.spill.nta [in0]=f50,32
+	stf.spill.nta [ r3]=f51,32
+	;;
+	stf.spill.nta [in0]=f52,32
+	stf.spill.nta [ r3]=f53,32
+	;;
+	stf.spill.nta [in0]=f54,32
+	stf.spill.nta [ r3]=f55,32
+	;;
+	stf.spill.nta [in0]=f56,32
+	stf.spill.nta [ r3]=f57,32
+	;;
+	stf.spill.nta [in0]=f58,32
+	stf.spill.nta [ r3]=f59,32
+	;;
+	stf.spill.nta [in0]=f60,32
+	stf.spill.nta [ r3]=f61,32
+	;;
+	stf.spill.nta [in0]=f62,32
+	stf.spill.nta [ r3]=f63,32
+	;;
+	stf.spill.nta [in0]=f64,32
+	stf.spill.nta [ r3]=f65,32
+	;;
+	stf.spill.nta [in0]=f66,32
+	stf.spill.nta [ r3]=f67,32
+	;;
+	stf.spill.nta [in0]=f68,32
+	stf.spill.nta [ r3]=f69,32
+	;;
+	stf.spill.nta [in0]=f70,32
+	stf.spill.nta [ r3]=f71,32
+	;;
+	stf.spill.nta [in0]=f72,32
+	stf.spill.nta [ r3]=f73,32
+	;;
+	stf.spill.nta [in0]=f74,32
+	stf.spill.nta [ r3]=f75,32
+	;;
+	stf.spill.nta [in0]=f76,32
+	stf.spill.nta [ r3]=f77,32
+	;;
+	stf.spill.nta [in0]=f78,32
+	stf.spill.nta [ r3]=f79,32
+	;;
+	stf.spill.nta [in0]=f80,32
+	stf.spill.nta [ r3]=f81,32
+	;;
+	stf.spill.nta [in0]=f82,32
+	stf.spill.nta [ r3]=f83,32
+	;;
+	stf.spill.nta [in0]=f84,32
+	stf.spill.nta [ r3]=f85,32
+	;;
+	stf.spill.nta [in0]=f86,32
+	stf.spill.nta [ r3]=f87,32
+	;;
+	stf.spill.nta [in0]=f88,32
+	stf.spill.nta [ r3]=f89,32
+	;;
+	stf.spill.nta [in0]=f90,32
+	stf.spill.nta [ r3]=f91,32
+	;;
+	stf.spill.nta [in0]=f92,32
+	stf.spill.nta [ r3]=f93,32
+	;;
+	stf.spill.nta [in0]=f94,32
+	stf.spill.nta [ r3]=f95,32
+	;;
+	stf.spill.nta [in0]=f96,32
+	stf.spill.nta [ r3]=f97,32
+	;;
+	stf.spill.nta [in0]=f98,32
+	stf.spill.nta [ r3]=f99,32
+	;;
+	stf.spill.nta [in0]=f100,32
+	stf.spill.nta [ r3]=f101,32
+	;;
+	stf.spill.nta [in0]=f102,32
+	stf.spill.nta [ r3]=f103,32
+	;;
+	stf.spill.nta [in0]=f104,32
+	stf.spill.nta [ r3]=f105,32
+	;;
+	stf.spill.nta [in0]=f106,32
+	stf.spill.nta [ r3]=f107,32
+	;;
+	stf.spill.nta [in0]=f108,32
+	stf.spill.nta [ r3]=f109,32
+	;;
+	stf.spill.nta [in0]=f110,32
+	stf.spill.nta [ r3]=f111,32
+	;;
+	stf.spill.nta [in0]=f112,32
+	stf.spill.nta [ r3]=f113,32
+	;;
+	stf.spill.nta [in0]=f114,32
+	stf.spill.nta [ r3]=f115,32
+	;;
+	stf.spill.nta [in0]=f116,32
+	stf.spill.nta [ r3]=f117,32
+	;;
+	stf.spill.nta [in0]=f118,32
+	stf.spill.nta [ r3]=f119,32
+	;;
+	stf.spill.nta [in0]=f120,32
+	stf.spill.nta [ r3]=f121,32
+	;;
+	stf.spill.nta [in0]=f122,32
+	stf.spill.nta [ r3]=f123,32
+	;;
+	stf.spill.nta [in0]=f124,32
+	stf.spill.nta [ r3]=f125,32
+	;;
+	stf.spill.nta [in0]=f126,32
+	stf.spill.nta [ r3]=f127,32
+	br.ret.sptk.few rp
+	.endp __ia64_save_fpu
+
+	.align 16
+	.global __ia64_load_fpu
+	.proc __ia64_load_fpu
+__ia64_load_fpu:
+	alloc r2=ar.pfs,1,0,0,0
+	adds r3=16,in0
+	;;
+	ldf.fill.nta f32=[in0],32
+	ldf.fill.nta f33=[ r3],32
+	;;
+	ldf.fill.nta f34=[in0],32
+	ldf.fill.nta f35=[ r3],32
+	;;
+	ldf.fill.nta f36=[in0],32
+	ldf.fill.nta f37=[ r3],32
+	;;
+	ldf.fill.nta f38=[in0],32
+	ldf.fill.nta f39=[ r3],32
+	;;
+	ldf.fill.nta f40=[in0],32
+	ldf.fill.nta f41=[ r3],32
+	;;
+	ldf.fill.nta f42=[in0],32
+	ldf.fill.nta f43=[ r3],32
+	;;
+	ldf.fill.nta f44=[in0],32
+	ldf.fill.nta f45=[ r3],32
+	;;
+	ldf.fill.nta f46=[in0],32
+	ldf.fill.nta f47=[ r3],32
+	;;
+	ldf.fill.nta f48=[in0],32
+	ldf.fill.nta f49=[ r3],32
+	;;
+	ldf.fill.nta f50=[in0],32
+	ldf.fill.nta f51=[ r3],32
+	;;
+	ldf.fill.nta f52=[in0],32
+	ldf.fill.nta f53=[ r3],32
+	;;
+	ldf.fill.nta f54=[in0],32
+	ldf.fill.nta f55=[ r3],32
+	;;
+	ldf.fill.nta f56=[in0],32
+	ldf.fill.nta f57=[ r3],32
+	;;
+	ldf.fill.nta f58=[in0],32
+	ldf.fill.nta f59=[ r3],32
+	;;
+	ldf.fill.nta f60=[in0],32
+	ldf.fill.nta f61=[ r3],32
+	;;
+	ldf.fill.nta f62=[in0],32
+	ldf.fill.nta f63=[ r3],32
+	;;
+	ldf.fill.nta f64=[in0],32
+	ldf.fill.nta f65=[ r3],32
+	;;
+	ldf.fill.nta f66=[in0],32
+	ldf.fill.nta f67=[ r3],32
+	;;
+	ldf.fill.nta f68=[in0],32
+	ldf.fill.nta f69=[ r3],32
+	;;
+	ldf.fill.nta f70=[in0],32
+	ldf.fill.nta f71=[ r3],32
+	;;
+	ldf.fill.nta f72=[in0],32
+	ldf.fill.nta f73=[ r3],32
+	;;
+	ldf.fill.nta f74=[in0],32
+	ldf.fill.nta f75=[ r3],32
+	;;
+	ldf.fill.nta f76=[in0],32
+	ldf.fill.nta f77=[ r3],32
+	;;
+	ldf.fill.nta f78=[in0],32
+	ldf.fill.nta f79=[ r3],32
+	;;
+	ldf.fill.nta f80=[in0],32
+	ldf.fill.nta f81=[ r3],32
+	;;
+	ldf.fill.nta f82=[in0],32
+	ldf.fill.nta f83=[ r3],32
+	;;
+	ldf.fill.nta f84=[in0],32
+	ldf.fill.nta f85=[ r3],32
+	;;
+	ldf.fill.nta f86=[in0],32
+	ldf.fill.nta f87=[ r3],32
+	;;
+	ldf.fill.nta f88=[in0],32
+	ldf.fill.nta f89=[ r3],32
+	;;
+	ldf.fill.nta f90=[in0],32
+	ldf.fill.nta f91=[ r3],32
+	;;
+	ldf.fill.nta f92=[in0],32
+	ldf.fill.nta f93=[ r3],32
+	;;
+	ldf.fill.nta f94=[in0],32
+	ldf.fill.nta f95=[ r3],32
+	;;
+	ldf.fill.nta f96=[in0],32
+	ldf.fill.nta f97=[ r3],32
+	;;
+	ldf.fill.nta f98=[in0],32
+	ldf.fill.nta f99=[ r3],32
+	;;
+	ldf.fill.nta f100=[in0],32
+	ldf.fill.nta f101=[ r3],32
+	;;
+	ldf.fill.nta f102=[in0],32
+	ldf.fill.nta f103=[ r3],32
+	;;
+	ldf.fill.nta f104=[in0],32
+	ldf.fill.nta f105=[ r3],32
+	;;
+	ldf.fill.nta f106=[in0],32
+	ldf.fill.nta f107=[ r3],32
+	;;
+	ldf.fill.nta f108=[in0],32
+	ldf.fill.nta f109=[ r3],32
+	;;
+	ldf.fill.nta f110=[in0],32
+	ldf.fill.nta f111=[ r3],32
+	;;
+	ldf.fill.nta f112=[in0],32
+	ldf.fill.nta f113=[ r3],32
+	;;
+	ldf.fill.nta f114=[in0],32
+	ldf.fill.nta f115=[ r3],32
+	;;
+	ldf.fill.nta f116=[in0],32
+	ldf.fill.nta f117=[ r3],32
+	;;
+	ldf.fill.nta f118=[in0],32
+	ldf.fill.nta f119=[ r3],32
+	;;
+	ldf.fill.nta f120=[in0],32
+	ldf.fill.nta f121=[ r3],32
+	;;
+	ldf.fill.nta f122=[in0],32
+	ldf.fill.nta f123=[ r3],32
+	;;
+	ldf.fill.nta f124=[in0],32
+	ldf.fill.nta f125=[ r3],32
+	;;
+	ldf.fill.nta f126=[in0],32
+	ldf.fill.nta f127=[ r3],32
+	br.ret.sptk.few rp
+	.endp __ia64_load_fpu
+
+	.align 16
+	.global __ia64_init_fpu
+	.proc __ia64_init_fpu
+__ia64_init_fpu:
+	alloc r2=ar.pfs,0,0,0,0
+	stf.spill [sp]=f0
+	mov      f32=f0
+	;;
+	ldf.fill f33=[sp]
+	ldf.fill f34=[sp]
+	mov      f35=f0
+	;;
+	ldf.fill f36=[sp]
+	ldf.fill f37=[sp]
+	mov      f38=f0
+	;;
+	ldf.fill f39=[sp]
+	ldf.fill f40=[sp]
+	mov      f41=f0
+	;;
+	ldf.fill f42=[sp]
+	ldf.fill f43=[sp]
+	mov      f44=f0
+	;;
+	ldf.fill f45=[sp]
+	ldf.fill f46=[sp]
+	mov      f47=f0
+	;;
+	ldf.fill f48=[sp]
+	ldf.fill f49=[sp]
+	mov      f50=f0
+	;;
+	ldf.fill f51=[sp]
+	ldf.fill f52=[sp]
+	mov      f53=f0
+	;;
+	ldf.fill f54=[sp]
+	ldf.fill f55=[sp]
+	mov      f56=f0
+	;;
+	ldf.fill f57=[sp]
+	ldf.fill f58=[sp]
+	mov      f59=f0
+	;;
+	ldf.fill f60=[sp]
+	ldf.fill f61=[sp]
+	mov      f62=f0
+	;;
+	ldf.fill f63=[sp]
+	ldf.fill f64=[sp]
+	mov      f65=f0
+	;;
+	ldf.fill f66=[sp]
+	ldf.fill f67=[sp]
+	mov      f68=f0
+	;;
+	ldf.fill f69=[sp]
+	ldf.fill f70=[sp]
+	mov      f71=f0
+	;;
+	ldf.fill f72=[sp]
+	ldf.fill f73=[sp]
+	mov      f74=f0
+	;;
+	ldf.fill f75=[sp]
+	ldf.fill f76=[sp]
+	mov      f77=f0
+	;;
+	ldf.fill f78=[sp]
+	ldf.fill f79=[sp]
+	mov      f80=f0
+	;;
+	ldf.fill f81=[sp]
+	ldf.fill f82=[sp]
+	mov      f83=f0
+	;;
+	ldf.fill f84=[sp]
+	ldf.fill f85=[sp]
+	mov      f86=f0
+	;;
+	ldf.fill f87=[sp]
+	ldf.fill f88=[sp]
+	mov      f89=f0
+	;;
+	ldf.fill f90=[sp]
+	ldf.fill f91=[sp]
+	mov      f92=f0
+	;;
+	ldf.fill f93=[sp]
+	ldf.fill f94=[sp]
+	mov      f95=f0
+	;;
+	ldf.fill f96=[sp]
+	ldf.fill f97=[sp]
+	mov      f98=f0
+	;;
+	ldf.fill f99=[sp]
+	ldf.fill f100=[sp]
+	mov      f101=f0
+	;;
+	ldf.fill f102=[sp]
+	ldf.fill f103=[sp]
+	mov      f104=f0
+	;;
+	ldf.fill f105=[sp]
+	ldf.fill f106=[sp]
+	mov      f107=f0
+	;;
+	ldf.fill f108=[sp]
+	ldf.fill f109=[sp]
+	mov      f110=f0
+	;;
+	ldf.fill f111=[sp]
+	ldf.fill f112=[sp]
+	mov      f113=f0
+	;;
+	ldf.fill f114=[sp]
+	ldf.fill f115=[sp]
+	mov      f116=f0
+	;;
+	ldf.fill f117=[sp]
+	ldf.fill f118=[sp]
+	mov      f119=f0
+	;;
+	ldf.fill f120=[sp]
+	ldf.fill f121=[sp]
+	mov      f122=f0
+	;;
+	ldf.fill f123=[sp]
+	ldf.fill f124=[sp]
+	mov      f125=f0
+	;;
+	ldf.fill f126=[sp]
+	mov      f127=f0
+	br.ret.sptk.few rp
+	.endp __ia64_init_fpu
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/init_task.c linux/arch/ia64/kernel/init_task.c
--- v2.3.42/linux/arch/ia64/kernel/init_task.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/init_task.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,31 @@
+/*
+ * This is where we statically allocate and initialize the initial
+ * task.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct vm_area_struct init_mmap = INIT_MMAP;
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS;
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is page aligned due to the way
+ * process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union task_union init_task_union
+	__attribute__((section("init_task"))) =
+		{ INIT_TASK(init_task_union.task) };
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c
--- v2.3.42/linux/arch/ia64/kernel/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/irq.c	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,657 @@
+/*
+ * linux/arch/ia64/kernel/irq.c
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ *  6/10/99: Updated to bring in sync with x86 version to facilitate
+ *	     support for SMP and different interrupt controllers.
+ */
+
+#include <linux/config.h>
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel_stat.h>
+#include <linux/malloc.h>
+#include <linux/ptrace.h>
+#include <linux/random.h>	/* for rand_initialize_irq() */
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/threads.h>
+
+#ifdef CONFIG_KDB
+# include <linux/kdb.h>
+#endif
+
+#include <asm/bitops.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+/* This is used to detect bad usage of probe_irq_on()/probe_irq_off().  */
+#define PROBE_IRQ_COOKIE	0xfeedC0FFEE
+
+struct irq_desc irq_desc[NR_IRQS];
+
+/*
+ * Micro-access to controllers is serialized over the whole
+ * system. We never hold this lock when we call the actual
+ * IRQ handler.
+ */
+spinlock_t irq_controller_lock;
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+spinlock_t ivr_read_lock;
+#endif
+
+unsigned int local_bh_count[NR_CPUS];
+/*
+ * used in irq_enter()/irq_exit()
+ */
+unsigned int local_irq_count[NR_CPUS];
+
+static struct irqaction timer_action = { NULL, 0, 0, NULL, NULL, NULL};
+
+#ifdef CONFIG_SMP
+static struct irqaction ipi_action = { NULL, 0, 0, NULL, NULL, NULL};
+#endif
+
+/*
+ * Legacy IRQ to IA-64 vector translation table.  Any vector not in
+ * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30)
+ */
+__u8 irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = {
+	/* 8259 IRQ translation, first 16 entries */
+	TIMER_IRQ, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54,
+	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41,
+};
+
+/*
+ * Reverse of the above table.
+ */
+static __u8 vector_to_legacy_map[256];
+
+/*
+ * used by proc fs (/proc/interrupts)
+ */
+int
+get_irq_list (char *buf)
+{
+	int i;
+	struct irqaction * action;
+	char *p = buf;
+
+#ifdef CONFIG_SMP
+	p += sprintf(p, "           ");
+	for (i = 0; i < smp_num_cpus; i++)
+		p += sprintf(p, "CPU%d       ", i);
+	*p++ = '\n';
+#endif
+	/*
+	 * Simply scans the external vectored interrupts
+	 */
+	for (i = 0; i < NR_IRQS; i++) {
+		action = irq_desc[i].action;
+		if (!action) 
+			continue;
+		p += sprintf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+		p += sprintf(p, "%10u ", kstat_irqs(i));
+#else
+		{
+			int j;
+			for (j = 0; j < smp_num_cpus; j++)
+				p += sprintf(p, "%10u ",
+					     kstat.irqs[cpu_logical_map(j)][i]);
+		}
+#endif
+		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
+		p += sprintf(p, "  %c%s", (action->flags & SA_INTERRUPT) ? '+' : ' ',
+			     action->name);
+
+		for (action = action->next; action; action = action->next) {
+			p += sprintf(p, ", %c%s",
+				     (action->flags & SA_INTERRUPT)?'+':' ',
+				     action->name);
+		}
+		*p++ = '\n';
+	}
+	return p - buf;
+}
+
+/*
+ * That's where the IVT branches when we get an external
+ * interrupt. This branches to the correct hardware IRQ handler via
+ * function ptr.
+ */
+void
+ia64_handle_irq (unsigned long irq, struct pt_regs *regs)
+{
+	unsigned long bsp, sp, saved_tpr;
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+# ifndef CONFIG_SMP
+	static unsigned int max_prio = 0;
+# endif
+	unsigned int prev_prio;
+	unsigned long eoi_ptr;
+ 
+# ifdef CONFIG_USB
+	disable_usb();
+# endif
+	/*
+	 * Stop IPIs by getting the ivr_read_lock
+	 */
+	spin_lock(&ivr_read_lock);
+
+	/*
+	 * Disable PCI writes
+	 */
+	outl(0x80ff81c0, 0xcf8);
+	outl(0x73002188, 0xcfc);
+	eoi_ptr = inl(0xcfc);
+
+	irq = ia64_get_ivr();
+
+	/*
+	 * Enable PCI writes
+	 */
+	outl(0x73182188, 0xcfc);
+
+	spin_unlock(&ivr_read_lock);
+
+# ifdef CONFIG_USB
+	reenable_usb();
+# endif
+
+# ifndef CONFIG_SMP
+	prev_prio = max_prio;
+	if (irq < max_prio) {
+		printk ("ia64_handle_irq: got irq %lu while %u was in progress!\n",
+			irq, max_prio);
+		
+	} else
+		max_prio = irq;
+# endif /* !CONFIG_SMP */
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+	/* Always set TPR to limit maximum interrupt nesting depth to
+	 * 16 (without this, it would be ~240, which could easily lead
+	 * to kernel stack overflows.
+	 */
+	saved_tpr = ia64_get_tpr();
+	ia64_srlz_d();
+	ia64_set_tpr(irq);
+	ia64_srlz_d();
+
+	asm ("mov %0=ar.bsp" : "=r"(bsp));
+	asm ("mov %0=sp" : "=r"(sp));
+
+	if ((sp - bsp) < 1024) {
+		static long last_time;
+		static unsigned char count;
+
+		if (count > 5 && jiffies - last_time > 5*HZ)
+			count = 0;
+		if (++count < 5) {
+			last_time = jiffies;
+			printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n"
+			       "(bsp=0x%lx, sp=%lx)\n", bsp, sp);
+		}
+#ifdef CONFIG_KDB
+		kdb(KDB_REASON_PANIC, 0, regs);
+#endif		
+	}
+
+	/*
+	 * The interrupt is now said to be in service
+	 */
+	if (irq >= NR_IRQS) {
+		printk("handle_irq: invalid irq=%lu\n", irq);
+		goto out;
+	}
+
+	++kstat.irqs[smp_processor_id()][irq];
+
+	if (irq == IA64_SPURIOUS_INT) {
+		printk("handle_irq: spurious interrupt\n");
+		goto out;
+	}
+
+	/* 
+	 * Handle the interrupt by calling the hardware specific handler (IOSAPIC, Internal, etc).
+	 */
+	(*irq_desc[irq].handler->handle)(irq, regs);
+  out:
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+	{
+		long pEOI;
+
+		asm ("mov %0=0;; (p1) mov %0=1" : "=r"(pEOI));
+		if (!pEOI) {
+			printk("Yikes: ia64_handle_irq() without pEOI!!\n");
+			asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI));
+# ifdef CONFIG_KDB
+			kdb(KDB_REASON_PANIC, 0, regs);
+# endif
+		}
+	}
+
+	local_irq_disable();
+# ifndef CONFIG_SMP
+	if (max_prio == irq)
+		max_prio = prev_prio;
+# endif /* !CONFIG_SMP */
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+	ia64_srlz_d();
+	ia64_set_tpr(saved_tpr);
+	ia64_srlz_d();
+}
+
+
+/*
+ * This should really return information about whether we should do
+ * bottom half handling etc. Right now we end up _always_ checking the
+ * bottom half, which is a waste of time and is not what some drivers
+ * would prefer.
+ */
+int
+invoke_irq_handlers (unsigned int irq, struct pt_regs *regs, struct irqaction *action)
+{
+	void (*handler)(int, void *, struct pt_regs *);
+	unsigned long flags, flags_union = 0;
+	int cpu = smp_processor_id();
+	unsigned int requested_irq;
+	void *dev_id;
+
+	irq_enter(cpu, irq);
+
+	if ((action->flags & SA_INTERRUPT) == 0)
+		__sti();
+
+	do {
+		flags = action->flags;
+		requested_irq = irq;
+		if ((flags & SA_LEGACY) != 0)
+			requested_irq = vector_to_legacy_map[irq];
+		flags_union |= flags;
+		handler = action->handler;
+		dev_id = action->dev_id;
+		action = action->next;
+		(*handler)(requested_irq, dev_id, regs);
+	} while (action);
+	if ((flags_union & SA_SAMPLE_RANDOM) != 0)
+		add_interrupt_randomness(irq);
+	__cli();
+
+	irq_exit(cpu, irq);
+	return flags_union | 1;	/* force the "do bottom halves" bit */
+}
+
+void
+disable_irq_nosync (unsigned int irq)
+{
+	unsigned long flags;
+
+	irq = map_legacy_irq(irq);
+
+	spin_lock_irqsave(&irq_controller_lock, flags);
+	if (irq_desc[irq].depth++ > 0) {
+		irq_desc[irq].status &= ~IRQ_ENABLED;
+		irq_desc[irq].handler->disable(irq);
+	}
+	spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+
+/*
+ * Synchronous version of the above, making sure the IRQ is
+ * no longer running on any other IRQ..
+ */
+void
+disable_irq (unsigned int irq)
+{
+	disable_irq_nosync(irq);
+
+	irq = map_legacy_irq(irq);
+
+	if (!local_irq_count[smp_processor_id()]) {
+		do {
+			barrier();
+		} while ((irq_desc[irq].status & IRQ_INPROGRESS) != 0);
+	}
+}
+
+void
+enable_irq (unsigned int irq)
+{
+	unsigned long flags;
+
+	irq = map_legacy_irq(irq);
+
+	spin_lock_irqsave(&irq_controller_lock, flags);
+	switch (irq_desc[irq].depth) {
+	      case 1:
+		irq_desc[irq].status |= IRQ_ENABLED;
+		(*irq_desc[irq].handler->enable)(irq);
+		/* fall through */
+	      default:
+		--irq_desc[irq].depth;
+		break;
+
+	      case 0:
+		printk("enable_irq: unbalanced from %p\n", __builtin_return_address(0));
+	}
+	spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+
+/*
+ * This function encapsulates the initialization that needs to be
+ * performed under the protection of lock irq_controller_lock.  The
+ * lock must have been acquired by the time this is called.
+ */
+static inline int
+setup_irq (unsigned int irq, struct irqaction *new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+
+	p = &irq_desc[irq].action;
+	old = *p;
+	if (old) {
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			return -EBUSY;
+		}
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+	*p = new;
+
+	/* when sharing do not unmask */
+	if (!shared) {
+		irq_desc[irq].depth = 0;
+		irq_desc[irq].status |= IRQ_ENABLED;
+		(*irq_desc[irq].handler->startup)(irq);
+	}
+	return 0;
+}
+
+int
+request_irq (unsigned int requested_irq, void (*handler)(int, void *, struct pt_regs *),
+	     unsigned long irqflags, const char * devname, void *dev_id)
+{
+	int retval, need_kfree = 0;
+	struct irqaction *action;
+	unsigned long flags;
+	unsigned int irq;
+
+#ifdef IA64_DEBUG
+	printk("request_irq(0x%x) called\n", requested_irq);
+#endif
+	/*
+	 * Sanity-check: shared interrupts should REALLY pass in
+	 * a real dev-ID, otherwise we'll have trouble later trying
+	 * to figure out which interrupt is which (messes up the
+	 * interrupt freeing logic etc).
+	 */
+	if ((irqflags & SA_SHIRQ) && !dev_id)
+		printk("Bad boy: %s (at %p) called us without a dev_id!\n",
+		       devname, current_text_addr());
+
+	irq = map_legacy_irq(requested_irq);
+	if (irq != requested_irq)
+		irqflags |= SA_LEGACY;
+
+	if (irq >= NR_IRQS)
+		return -EINVAL;
+
+	if (!handler)
+		return -EINVAL;
+
+	/*
+	 * The timer_action and ipi_action cannot be allocated
+	 * dynamically because its initialization happens really early
+	 * on in init/main.c at this point the memory allocator has
+	 * not yet been initialized.  So we use a statically reserved
+	 * buffer for it. In some sense that's no big deal because we
+	 * need one no matter what.
+	 */
+	if (irq == TIMER_IRQ)
+		action = &timer_action;
+#ifdef CONFIG_SMP
+	else if (irq == IPI_IRQ)
+		action = &ipi_action;
+#endif
+	else {
+		action = kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+		need_kfree = 1;
+	}
+
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	if ((irqflags & SA_SAMPLE_RANDOM) != 0)
+		rand_initialize_irq(irq);
+
+	spin_lock_irqsave(&irq_controller_lock, flags);
+	retval = setup_irq(irq, action);
+	spin_unlock_irqrestore(&irq_controller_lock, flags);
+
+	if (need_kfree && retval)
+		kfree(action);
+
+	return retval;
+}
+		
+void
+free_irq (unsigned int irq, void *dev_id)
+{
+	struct irqaction *action, **p;
+	unsigned long flags;
+
+	/*
+	 * some sanity checks first
+	 */
+	if (irq >= NR_IRQS) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+
+	irq = map_legacy_irq(irq);
+
+	/*
+	 * Find the corresponding irqaction
+	 */
+	spin_lock_irqsave(&irq_controller_lock, flags);
+	for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now remove it from the list of entries */
+		*p = action->next;
+		if (!irq_desc[irq].action) {
+			irq_desc[irq].status &= ~IRQ_ENABLED;
+			(*irq_desc[irq].handler->shutdown)(irq);
+		}
+
+		spin_unlock_irqrestore(&irq_controller_lock, flags);
+
+#ifdef CONFIG_SMP
+		/* Wait to make sure it's not being used on another CPU */
+		while (irq_desc[irq].status & IRQ_INPROGRESS)
+			barrier();
+#endif
+
+		if (action != &timer_action
+#ifdef CONFIG_SMP
+		    && action != &ipi_action
+#endif
+		   )
+			kfree(action);
+		return;
+	}
+	printk("Trying to free free IRQ%d\n", irq);
+}
+
+/*
+ * IRQ autodetection code.  Note that the return value of
+ * probe_irq_on() is no longer being used (it's role has been replaced
+ * by the IRQ_AUTODETECT flag).
+ */
+unsigned long
+probe_irq_on (void)
+{
+	struct irq_desc *id;
+	unsigned long delay;
+
+#ifdef IA64_DEBUG
+	printk("probe_irq_on() called\n");
+#endif
+
+	spin_lock_irq(&irq_controller_lock);
+	for (id = irq_desc; id < irq_desc + NR_IRQS; ++id) {
+		if (!id->action) {
+			id->status |= IRQ_AUTODETECT | IRQ_WAITING;
+			(*id->handler->startup)(id - irq_desc);
+		}
+	}
+	spin_unlock_irq(&irq_controller_lock);
+
+	/* wait for spurious interrupts to trigger: */
+
+	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
+		/* about 100ms delay */
+		synchronize_irq();
+
+	/* filter out obviously spurious interrupts: */
+	spin_lock_irq(&irq_controller_lock);
+	for (id = irq_desc; id < irq_desc + NR_IRQS; ++id) {
+		unsigned int status = id->status;
+
+		if (!(status & IRQ_AUTODETECT))
+			continue;
+
+		if (!(status & IRQ_WAITING)) {
+			id->status = status & ~IRQ_AUTODETECT;
+			(*id->handler->shutdown)(id - irq_desc);
+		}
+	}
+	spin_unlock_irq(&irq_controller_lock);
+	return PROBE_IRQ_COOKIE;		/* return meaningless return value  */
+}
+
+int
+probe_irq_off (unsigned long cookie)
+{
+	int irq_found, nr_irqs;
+	struct irq_desc *id;
+
+#ifdef IA64_DEBUG
+	printk("probe_irq_off(cookie=0x%lx) -> ", cookie);
+#endif
+
+	if (cookie != PROBE_IRQ_COOKIE)
+		printk("bad irq probe from %p\n", __builtin_return_address(0));
+
+	nr_irqs = 0;
+	irq_found = 0;
+	spin_lock_irq(&irq_controller_lock);
+	for (id = irq_desc + IA64_MIN_VECTORED_IRQ; id < irq_desc + NR_IRQS; ++id) {
+		unsigned int status = id->status;
+
+		if (!(status & IRQ_AUTODETECT))
+			continue;
+
+		if (!(status & IRQ_WAITING)) {
+			if (!nr_irqs)
+				irq_found = (id - irq_desc);
+			++nr_irqs;
+		}
+		id->status = status & ~IRQ_AUTODETECT;
+		(*id->handler->shutdown)(id - irq_desc);
+	}
+	spin_unlock_irq(&irq_controller_lock);
+
+	if (nr_irqs > 1)
+		irq_found = -irq_found;
+
+#ifdef IA64_DEBUG
+	printk("%d\n", irq_found);
+#endif
+	return irq_found;
+}
+
+#ifdef CONFIG_SMP
+
+void __init
+init_IRQ_SMP (void)
+{
+	if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL))
+		panic("Could not allocate IPI Interrupt Handler!");
+}
+
+#endif
+
+void __init
+init_IRQ (void)
+{
+	int i;
+
+	for (i = 0; i < IA64_MIN_VECTORED_IRQ; ++i)
+		vector_to_legacy_map[irq_to_vector_map[i]] = i;
+
+	for (i = 0; i < NR_IRQS; ++i) {
+		irq_desc[i].handler = &irq_type_default;
+	}
+
+	irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal;
+#ifdef CONFIG_SMP
+	/* 
+	 * Configure the IPI vector and handler
+	 */
+	irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal;
+	init_IRQ_SMP();
+#endif
+
+	ia64_set_pmv(1 << 16);
+	ia64_set_cmcv(CMC_IRQ);			/* XXX fix me */
+
+	platform_irq_init(irq_desc);
+
+	/* clear TPR to enable all interrupt classes: */
+	ia64_set_tpr(0);
+}
+
+/* TBD:
+ * 	Certain IA64 platforms can have inter-processor interrupt support.
+ * 	This interface is supposed to default to the IA64 IPI block-based
+ * 	mechanism if the platform doesn't provide a separate mechanism
+ *	for IPIs.
+ *	Choices : (1) Extend hw_interrupt_type interfaces 
+ *		  (2) Use machine vector mechanism
+ *	For now defining the following interface as a place holder.
+ */
+void
+ipi_send (int cpu, int vector, int delivery_mode)
+{
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/irq_default.c linux/arch/ia64/kernel/irq_default.c
--- v2.3.42/linux/arch/ia64/kernel/irq_default.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/irq_default.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,30 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+
+
+static int
+irq_default_handle_irq (unsigned int irq, struct pt_regs *regs)
+{
+	printk("Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id());
+	return 0;		/* don't call do_bottom_half() for spurious interrupts */
+}
+
+static void
+irq_default_noop (unsigned int irq)
+{
+	/* nuthing to do... */
+}
+
+struct hw_interrupt_type irq_type_default = {
+	"default",
+	(void (*)(unsigned long)) irq_default_noop,	/* init */
+	irq_default_noop,				/* startup */
+	irq_default_noop,				/* shutdown */
+	irq_default_handle_irq,				/* handle */
+	irq_default_noop,				/* enable */
+	irq_default_noop				/* disable */
+};
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/irq_internal.c linux/arch/ia64/kernel/irq_internal.c
--- v2.3.42/linux/arch/ia64/kernel/irq_internal.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/irq_internal.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,71 @@
+/*
+ * Internal Interrupt Vectors 
+ *
+ * This takes care of interrupts that are generated by the CPU
+ * internally, such as the ITC and IPI interrupts.
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+
+/*
+ * This is identical to IOSAPIC handle_irq.  It may go away . . .
+ */
+static int
+internal_handle_irq (unsigned int irq, struct pt_regs *regs)
+{
+	struct irqaction *action = 0;
+	struct irq_desc *id = irq_desc + irq;
+	unsigned int status;
+	int retval;
+
+	spin_lock(&irq_controller_lock);
+	{
+		status = id->status;
+		if ((status & IRQ_ENABLED) != 0)
+			action = id->action;
+		id->status = status & ~(IRQ_REPLAY | IRQ_WAITING);
+	}
+	spin_unlock(&irq_controller_lock);
+
+	if (!action) {
+		if (!(id->status & IRQ_AUTODETECT))
+			printk("irq_hpsim_handle_irq: unexpected interrupt %u\n", irq);
+		return 0;
+	}
+
+	retval = invoke_irq_handlers(irq, regs, action);
+
+	spin_lock(&irq_controller_lock);
+	{
+		status = (id->status & ~IRQ_INPROGRESS);
+		id->status = status;
+	}
+	spin_unlock(&irq_controller_lock);
+
+	return retval;
+}
+
+static void
+internal_noop (unsigned int irq)
+{
+	/* nuthing to do... */
+}
+
+struct hw_interrupt_type irq_type_ia64_internal = {
+	"IA64 internal",
+	(void (*)(unsigned long)) internal_noop,	/* init */
+	internal_noop,					/* startup */
+	internal_noop,					/* shutdown */
+	internal_handle_irq,				/* handle */
+	internal_noop,					/* enable */
+	internal_noop					/* disable */
+};
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/irq_lock.c linux/arch/ia64/kernel/irq_lock.c
--- v2.3.42/linux/arch/ia64/kernel/irq_lock.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/irq_lock.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,287 @@
+/*
+ * SMP IRQ Lock support
+ *
+ * Global interrupt locks for SMP. Allow interrupts to come in on any
+ * CPU, yet make cli/sti act globally to protect critical regions..
+ * These function usually appear in irq.c, but I think it's cleaner this way.
+ * 
+ * Copyright (C) 1999 VA Linux Systems 
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ */ 
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/delay.h>
+
+int global_irq_holder = NO_PROC_ID;
+spinlock_t global_irq_lock;
+atomic_t global_irq_count;
+atomic_t global_bh_count;
+atomic_t global_bh_lock;
+
+#define INIT_STUCK (1<<26)
+
+void
+irq_enter(int cpu, int irq)
+{
+        int stuck = INIT_STUCK;
+
+        hardirq_enter(cpu, irq);
+        barrier();
+        while (global_irq_lock.lock) {
+                if (cpu == global_irq_holder) {
+			break;
+                }
+
+		if (!--stuck) {
+			printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",
+			       irq, cpu,global_irq_holder);
+			stuck = INIT_STUCK;
+		}
+                barrier();
+        }
+}
+
+void
+irq_exit(int cpu, int irq)
+{
+        hardirq_exit(cpu, irq);
+        release_irqlock(cpu);
+}
+
+static void
+show(char * str)
+{
+        int i;
+        unsigned long *stack;
+        int cpu = smp_processor_id();
+
+        printk("\n%s, CPU %d:\n", str, cpu);
+        printk("irq:  %d [%d %d]\n",
+                atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
+        printk("bh:   %d [%d %d]\n",
+                atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+
+        stack = (unsigned long *) &stack;
+        for (i = 40; i ; i--) {
+                unsigned long x = *++stack;
+                if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) {
+                        printk("<[%08lx]> ", x);
+                }
+        }
+}
+        
+#define MAXCOUNT 100000000
+
+static inline void 
+wait_on_bh(void)
+{
+        int count = MAXCOUNT;
+        do {
+                if (!--count) {
+                        show("wait_on_bh");
+                        count = ~0;
+                }
+                /* nothing .. wait for the other bh's to go away */
+        } while (atomic_read(&global_bh_count) != 0);
+}
+
+static inline void 
+wait_on_irq(int cpu)
+{
+        int count = MAXCOUNT;
+
+        for (;;) {
+
+                /*
+                 * Wait until all interrupts are gone. Wait
+                 * for bottom half handlers unless we're
+                 * already executing in one..
+                 */
+                if (!atomic_read(&global_irq_count)) {
+                        if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
+                                break;
+                }
+
+                /* Duh, we have to loop. Release the lock to avoid deadlocks */
+		spin_unlock(&global_irq_lock);
+		mb();
+
+                for (;;) {
+                        if (!--count) {
+                                show("wait_on_irq");
+                                count = ~0;
+                        }
+                        __sti();
+                        udelay(cpu + 1);
+                        __cli();
+                        if (atomic_read(&global_irq_count))
+                                continue;
+                        if (global_irq_lock.lock)
+                                continue;
+                        if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
+                                continue;
+                        if (spin_trylock(&global_irq_lock))
+                                break;
+                }
+        }
+}
+
+/*
+ * This is called when we want to synchronize with
+ * bottom half handlers. We need to wait until
+ * no other CPU is executing any bottom half handler.
+ *
+ * Don't wait if we're already running in an interrupt
+ * context or are inside a bh handler. 
+ */
+void 
+synchronize_bh(void)
+{
+        if (atomic_read(&global_bh_count)) {
+                int cpu = smp_processor_id();
+                if (!local_irq_count[cpu] && !local_bh_count[cpu]) {
+                        wait_on_bh();
+                }
+        }
+}
+
+
+/*
+ * This is called when we want to synchronize with
+ * interrupts. We may for example tell a device to
+ * stop sending interrupts: but to make sure there
+ * are no interrupts that are executing on another
+ * CPU we need to call this function.
+ */
+void 
+synchronize_irq(void)
+{
+        int cpu = smp_processor_id();
+        int local_count;
+        int global_count;
+
+        mb();
+        do {
+                local_count = local_irq_count[cpu];
+                global_count = atomic_read(&global_irq_count);
+        } while (global_count != local_count);
+}
+
+static inline void 
+get_irqlock(int cpu)
+{
+        if (!spin_trylock(&global_irq_lock)) {
+                /* do we already hold the lock? */
+                if ((unsigned char) cpu == global_irq_holder)
+                        return;
+                /* Uhhuh.. Somebody else got it. Wait.. */
+		spin_lock(&global_irq_lock);
+        }
+        /* 
+         * We also to make sure that nobody else is running
+         * in an interrupt context. 
+         */
+        wait_on_irq(cpu);
+
+        /*
+         * Ok, finally..
+         */
+        global_irq_holder = cpu;
+}
+
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
+ */
+void 
+__global_cli(void)
+{
+	unsigned long flags;
+
+	__save_flags(flags);
+	if (flags & IA64_PSR_I) {
+		int cpu = smp_processor_id();
+		__cli();
+		if (!local_irq_count[cpu])
+			get_irqlock(cpu);
+	}
+}
+
+void 
+__global_sti(void)
+{
+        int cpu = smp_processor_id();
+
+        if (!local_irq_count[cpu])
+                release_irqlock(cpu);
+        __sti();
+}
+
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
+unsigned long 
+__global_save_flags(void)
+{
+        int retval;
+        int local_enabled;
+        unsigned long flags;
+
+        __save_flags(flags);
+        local_enabled = flags & IA64_PSR_I;
+        /* default to local */
+        retval = 2 + local_enabled;
+
+        /* check for global flags if we're not in an interrupt */
+        if (!local_irq_count[smp_processor_id()]) {
+                if (local_enabled)
+                        retval = 1;
+                if (global_irq_holder == (unsigned char) smp_processor_id())
+                        retval = 0;
+        }
+        return retval;
+}
+
+void 
+__global_restore_flags(unsigned long flags)
+{
+        switch (flags) {
+        case 0:
+                __global_cli();
+                break;
+        case 1:
+                __global_sti();
+                break;
+        case 2:
+                __cli();
+                break;
+        case 3:
+                __sti();
+                break;
+        default:
+                printk("global_restore_flags: %08lx (%08lx)\n",
+                        flags, (&flags)[-1]);
+        }
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/ivt.S linux/arch/ia64/kernel/ivt.S
--- v2.3.42/linux/arch/ia64/kernel/ivt.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/ivt.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,1342 @@
+/*
+ * arch/ia64/kernel/ivt.S
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1998-2000 David Mosberger <davidm@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+
+#include <asm/break.h>
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/unistd.h>
+
+#include "entry.h"
+
+/*
+ * A couple of convenience macros that make writing and reading
+ * SAVE_MIN and SAVE_REST easier.
+ */
+#define rARPR		r31
+#define rCRIFS		r30
+#define rCRIPSR		r29
+#define rCRIIP		r28
+#define rARRSC		r27
+#define rARPFS		r26
+#define rARUNAT		r25
+#define rARRNAT		r24
+#define rARBSPSTORE	r23
+#define rKRBS		r22
+#define rB6		r21
+#define rR1		r20
+
+/*
+ * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
+ * the minimum state necessary that allows us to turn psr.ic back
+ * on.
+ *
+ * Assumed state upon entry:
+ *	psr.ic: off
+ *	psr.dt: off
+ *	r31:	contains saved predicates (pr)
+ *
+ * Upon exit, the state is as follows:
+ *	psr.ic: off
+ *	psr.dt: off
+ *	r2 = points to &pt_regs.r16
+ *	r12 = kernel sp (kernel virtual address)
+ *	r13 = points to current task_struct (kernel virtual address)
+ *	p15 = TRUE if psr.i is set in cr.ipsr
+ *	predicate registers (other than p6, p7, and p15), b6, r3, r8, r9, r10, r11, r14, r15:
+ *		preserved
+ *
+ * Note that psr.ic is NOT turned on by this macro.  This is so that
+ * we can pass interruption state as arguments to a handler.
+ */
+#define DO_SAVE_MIN(COVER,EXTRA)								  \
+	mov rARRSC=ar.rsc;									  \
+	mov rARPFS=ar.pfs;									  \
+	mov rR1=r1;										  \
+	mov rARUNAT=ar.unat;									  \
+	mov rCRIPSR=cr.ipsr;									  \
+	mov rB6=b6;		/* rB6 = branch reg 6 */					  \
+	mov rCRIIP=cr.iip;									  \
+	mov r1=ar.k6;		/* r1 = current */						  \
+	;;											  \
+	invala;											  \
+	extr.u r16=rCRIPSR,32,2;		/* extract psr.cpl */				  \
+	;;											  \
+	cmp.eq pKern,p7=r0,r16;			/* are we in kernel mode already? (psr.cpl==0) */ \
+	/* switch from user to kernel RBS: */							  \
+	COVER;											  \
+	;;											  \
+(p7)	mov ar.rsc=r0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	  \
+(p7)	addl rKRBS=IA64_RBS_OFFSET,r1;		/* compute base of register backing store */	  \
+	;;											  \
+(p7)	mov rARRNAT=ar.rnat;									  \
+(pKern)	dep r1=0,sp,61,3;				/* compute physical addr of sp  */	  \
+(p7)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	  \
+(p7)	mov rARBSPSTORE=ar.bspstore;			/* save ar.bspstore */			  \
+(p7)	dep rKRBS=-1,rKRBS,61,3;			/* compute kernel virtual addr of RBS */  \
+	;;											  \
+(pKern)	addl r1=-IA64_PT_REGS_SIZE,r1;		/* if in kernel mode, use sp (r12) */		  \
+(p7)	mov ar.bspstore=rKRBS;			/* switch to kernel RBS */			  \
+	;;											  \
+(p7)	mov r18=ar.bsp;										  \
+(p7)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		  \
+												  \
+	mov r16=r1;		/* initialize first base pointer */				  \
+	adds r17=8,r1;		/* initialize second base pointer */				  \
+	;;											  \
+	st8 [r16]=rCRIPSR,16;	/* save cr.ipsr */						  \
+	st8 [r17]=rCRIIP,16;	/* save cr.iip */						  \
+(pKern)	mov r18=r0;		/* make sure r18 isn't NaT */					  \
+	;;											  \
+	st8 [r16]=rCRIFS,16;	/* save cr.ifs */						  \
+	st8 [r17]=rARUNAT,16;	/* save ar.unat */						  \
+(p7)	sub r18=r18,rKRBS;	/* r18=RSE.ndirty*8 */						  \
+	;;											  \
+	st8 [r16]=rARPFS,16;	/* save ar.pfs */						  \
+	st8 [r17]=rARRSC,16;	/* save ar.rsc */						  \
+	tbit.nz p15,p0=rCRIPSR,IA64_PSR_I_BIT							  \
+	;;			/* avoid RAW on r16 & r17 */					  \
+(pKern)	adds r16=16,r16;	/* skip over ar_rnat field */					  \
+(pKern)	adds r17=16,r17;	/* skip over ar_bspstore field */				  \
+(p7)	st8 [r16]=rARRNAT,16;	/* save ar.rnat */						  \
+(p7)	st8 [r17]=rARBSPSTORE,16;	/* save ar.bspstore */					  \
+	;;											  \
+	st8 [r16]=rARPR,16;	/* save predicates */						  \
+	st8 [r17]=rB6,16;	/* save b6 */							  \
+	shl r18=r18,16;		/* compute ar.rsc to be used for "loadrs" */			  \
+	;;											  \
+	st8 [r16]=r18,16;	/* save ar.rsc value for "loadrs" */				  \
+	st8.spill [r17]=rR1,16;	/* save original r1 */						  \
+	cmp.ne pEOI,p0=r0,r0	/* clear pEOI by default */					  \
+	;;											  \
+	st8.spill [r16]=r2,16;									  \
+	st8.spill [r17]=r3,16;									  \
+	adds r2=IA64_PT_REGS_R16_OFFSET,r1;							  \
+	;;											  \
+	st8.spill [r16]=r12,16;									  \
+	st8.spill [r17]=r13,16;									  \
+	cmp.eq pNonSys,pSys=r0,r0	/* initialize pSys=0, pNonSys=1 */			  \
+	;;											  \
+	st8.spill [r16]=r14,16;									  \
+	st8.spill [r17]=r15,16;									  \
+	dep r14=-1,r0,61,3;									  \
+	;;											  \
+	st8.spill [r16]=r8,16;									  \
+	st8.spill [r17]=r9,16;									  \
+	adds r12=-16,r1;	/* switch to kernel memory stack (with 16 bytes of scratch) */	  \
+	;;											  \
+	st8.spill [r16]=r10,16;									  \
+	st8.spill [r17]=r11,16;									  \
+	mov r13=ar.k6;		/* establish `current' */					  \
+	;;											  \
+	or r2=r2,r14;		/* make first base a kernel virtual address */			  \
+	EXTRA;											  \
+	movl r1=__gp;		/* establish kernel global pointer */				  \
+	;;											  \
+	or r12=r12,r14;		/* make sp a kernel virtual address */				  \
+	or r13=r13,r14;		/* make `current' a kernel virtual address */			  \
+	bsw.1;;			/* switch back to bank 1 (must be last in insn group) */
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+# define STOPS	nop.i 0x0;; nop.i 0x0;; nop.i 0x0;;
+#else
+# define STOPS
+#endif
+
+#define SAVE_MIN_WITH_COVER	DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs,) STOPS
+#define SAVE_MIN_WITH_COVER_R19	DO_SAVE_MIN(cover;; mov rCRIFS=cr.ifs, mov r15=r19) STOPS
+#define SAVE_MIN		DO_SAVE_MIN(mov rCRIFS=r0,) STOPS
+
+/*
+ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).  This
+ * macro guarantees to preserve all predicate registers, r8, r9, r10,
+ * r11, r14, and r15.
+ *
+ * Assumed state upon entry:
+ *	psr.ic: on
+ *	psr.dt: on
+ *	r2:	points to &pt_regs.r16
+ *	r3:	points to &pt_regs.r17
+ */
+#define SAVE_REST				\
+	st8.spill [r2]=r16,16;			\
+	st8.spill [r3]=r17,16;			\
+	;;					\
+	st8.spill [r2]=r18,16;			\
+	st8.spill [r3]=r19,16;			\
+	;;					\
+	mov r16=ar.ccv;		/* M-unit */	\
+	movl r18=FPSR_DEFAULT	/* L-unit */	\
+	;;					\
+	mov r17=ar.fpsr;	/* M-unit */	\
+	mov ar.fpsr=r18;	/* M-unit */	\
+	;;					\
+	st8.spill [r2]=r20,16;			\
+	st8.spill [r3]=r21,16;			\
+	mov r18=b0;				\
+	;;					\
+	st8.spill [r2]=r22,16;			\
+	st8.spill [r3]=r23,16;			\
+	mov r19=b7;				\
+	;;					\
+	st8.spill [r2]=r24,16;			\
+	st8.spill [r3]=r25,16;			\
+	;;					\
+	st8.spill [r2]=r26,16;			\
+	st8.spill [r3]=r27,16;			\
+	;;					\
+	st8.spill [r2]=r28,16;			\
+	st8.spill [r3]=r29,16;			\
+	;;					\
+	st8.spill [r2]=r30,16;			\
+	st8.spill [r3]=r31,16;			\
+	;;					\
+	st8 [r2]=r16,16;	/* ar.ccv */	\
+	st8 [r3]=r17,16;	/* ar.fpsr */	\
+	;;					\
+	st8 [r2]=r18,16;	/* b0 */	\
+	st8 [r3]=r19,16+8;	/* b7 */	\
+	;;					\
+	stf.spill [r2]=f6,32;			\
+	stf.spill [r3]=f7,32;			\
+	;;					\
+	stf.spill [r2]=f8,32;			\
+	stf.spill [r3]=f9,32
+
+/*
+ * This file defines the interrupt vector table used by the CPU.
+ * It does not include one entry per possible cause of interruption.
+ *
+ * External interrupts only use 1 entry. All others are internal interrupts
+ *
+ * The first 20 entries of the table contain 64 bundles each while the 
+ * remaining 48 entries contain only 16 bundles each.
+ *
+ * The 64 bundles are used to allow inlining the whole handler for critical
+ * interrupts like TLB misses.
+ *
+ *  For each entry, the comment is as follows:
+ *
+ * 		// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ *  entry offset ----/     /         /                  /          /
+ *  entry number ---------/         /                  /          /
+ *  size of the entry -------------/                  /          /
+ *  vector name -------------------------------------/          /
+ *  related interrupts (what is the real interrupt?) ----------/
+ *
+ * The table is 32KB in size and must be aligned on 32KB boundary.
+ * (The CPU ignores the 15 lower bits of the address)
+ *
+ * Table is based upon EAS2.4 (June 1998)
+ */
+
+#define FAULT(n)									\
+	rsm psr.dt;			/* avoid nested faults due to TLB misses... */	\
+	;;										\
+	srlz.d;				/* ensure everyone knows psr.dt is off... */	\
+	mov r31=pr;									\
+	mov r19=n;;			/* prepare to save predicates */		\
+	br.cond.sptk.many dispatch_to_fault_handler
+
+/*
+ * As we don't (hopefully) use the space available, we need to fill it with
+ * nops. the parameter may be used for debugging and is representing the entry
+ * number
+ */ 
+#define BREAK_BUNDLE(a) 	break.m (a); \
+				break.i (a); \
+				break.i (a)
+/*
+ * 4 breaks bundles all together
+ */
+#define BREAK_BUNDLE4(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a); BREAK_BUNDLE(a)
+
+/*
+ * 8 bundles all together (too lazy to use only 4 at a time !)
+ */
+#define BREAK_BUNDLE8(a); BREAK_BUNDLE4(a); BREAK_BUNDLE4(a)
+
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.section __ivt_section,"ax"
+
+	.align 32768	// align on 32KB boundary
+	.global ia64_ivt
+ia64_ivt:
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
+	/*
+	 * The VHPT vector is invoked when the TLB entry for the virtual page table
+	 * is missing.  This happens only as a result of a previous
+	 * (the "original") TLB miss, which may either be caused by an instruction
+	 * fetch or a data access (or non-access).
+	 *
+	 * What we do here is normal TLB miss handing for the _original_ miss, followed
+	 * by inserting the TLB entry for the virtual page table page that the VHPT
+	 * walker was attempting to access.  The latter gets inserted as long
+	 * as both L1 and L2 have valid mappings for the faulting address.
+	 * The TLB entry for the original miss gets inserted only if
+	 * the L3 entry indicates that the page is present.
+	 *
+	 * do_page_fault gets invoked in the following cases:
+	 *	- the faulting virtual address uses unimplemented address bits
+	 *	- the faulting virtual address has no L1, L2, or L3 mapping
+	 */
+	mov r16=cr.ifa				// get address that caused the TLB miss
+	;;
+	rsm psr.dt				// use physical addressing for data
+	mov r31=pr				// save the predicate registers
+	mov r19=ar.k7				// get page table base address
+	shl r21=r16,3				// shift bit 60 into sign bit
+	shr.u r17=r16,61			// get the region number into r17
+	;;
+	cmp.eq p6,p7=5,r17			// is IFA pointing into to region 5?
+	shr.u r18=r16,PGDIR_SHIFT		// get bits 33-63 of the faulting address
+	;;
+(p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
+	srlz.d					// ensure "rsm psr.dt" has taken effect
+(p6)	movl r19=__pa(SWAPPER_PGD_ADDR)		// region 5 is rooted at swapper_pg_dir
+(p6)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-1
+(p7)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-4
+	;;
+(p6)	dep r17=r18,r19,3,(PAGE_SHIFT-3)	// r17=PTA + IFA(33,42)*8
+(p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
+	cmp.eq p7,p6=0,r21			// unused address bits all zeroes?
+	shr.u r18=r16,PMD_SHIFT			// shift L2 index into position
+	;;
+(p6)	cmp.eq p7,p6=-1,r21			// unused address bits all ones?
+	ld8 r17=[r17]				// fetch the L1 entry (may be 0)
+	;;
+(p7)	cmp.eq p6,p7=r17,r0			// was L1 entry NULL?
+	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// compute address of L2 page table entry
+	;;
+(p7)	ld8 r17=[r17]				// fetch the L2 entry (may be 0)
+	shr.u r19=r16,PAGE_SHIFT		// shift L3 index into position
+	;;
+(p7)	cmp.eq.or.andcm p6,p7=r17,r0		// was L2 entry NULL?
+	dep r17=r19,r17,3,(PAGE_SHIFT-3)	// compute address of L3 page table entry
+	;;
+(p7)	ld8 r18=[r17]				// read the L3 PTE
+	mov r19=cr.isr				// cr.isr bit 0 tells us if this is an insn miss
+	;;
+(p7)	tbit.z p6,p7=r18,0			// page present bit cleared?
+	mov r21=cr.iha				// get the VHPT address that caused the TLB miss
+	;;					// avoid RAW on p7
+(p7)	tbit.nz.unc p10,p11=r19,32		// is it an instruction TLB miss?
+	dep r17=0,r17,0,PAGE_SHIFT		// clear low bits to get page address
+	;;
+(p10)	itc.i r18;;	// insert the instruction TLB entry (EAS2.6: must be last in insn group!)
+(p11)	itc.d r18;;	// insert the data TLB entry (EAS2.6: must be last in insn group!)
+(p6)	br.spnt.few page_fault			// handle bad address/page not present (page fault)
+	mov cr.ifa=r21
+
+	// Now compute and insert the TLB entry for the virtual page table.
+	// We never execute in a page table page so there is no need to set
+	// the exception deferral bit.
+	adds r16=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r17
+	;;
+(p7)	itc.d r16;;	// EAS2.6: must be last in insn group!
+	mov pr=r31,-1				// restore predicate registers
+	rfi;;					// must be last insn in an insn group
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
+	/*
+	 * The ITLB basically does the same as the VHPT handler except
+	 * that we always insert exactly one instruction TLB entry.
+	 */
+	mov r16=cr.ifa				// get address that caused the TLB miss
+	;;
+	rsm psr.dt				// use physical addressing for data
+	mov r31=pr				// save the predicate registers
+	mov r19=ar.k7				// get page table base address
+	shl r21=r16,3				// shift bit 60 into sign bit
+	shr.u r17=r16,61			// get the region number into r17
+	;;
+	cmp.eq p6,p7=5,r17			// is IFA pointing into to region 5?
+	shr.u r18=r16,PGDIR_SHIFT		// get bits 33-63 of the faulting address
+	;;
+(p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
+	srlz.d					// ensure "rsm psr.dt" has taken effect
+(p6)	movl r19=__pa(SWAPPER_PGD_ADDR)		// region 5 is rooted at swapper_pg_dir
+(p6)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-1
+(p7)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-4
+	;;
+(p6)	dep r17=r18,r19,3,(PAGE_SHIFT-3)	// r17=PTA + IFA(33,42)*8
+(p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
+	cmp.eq p7,p6=0,r21			// unused address bits all zeroes?
+	shr.u r18=r16,PMD_SHIFT			// shift L2 index into position
+	;;
+(p6)	cmp.eq p7,p6=-1,r21			// unused address bits all ones?
+	ld8 r17=[r17]				// fetch the L1 entry (may be 0)
+	;;
+(p7)	cmp.eq p6,p7=r17,r0			// was L1 entry NULL?
+	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// compute address of L2 page table entry
+	;;
+(p7)	ld8 r17=[r17]				// fetch the L2 entry (may be 0)
+	shr.u r19=r16,PAGE_SHIFT		// shift L3 index into position
+	;;
+(p7)	cmp.eq.or.andcm p6,p7=r17,r0		// was L2 entry NULL?
+	dep r17=r19,r17,3,(PAGE_SHIFT-3)	// compute address of L3 page table entry
+	;;
+(p7)	ld8 r18=[r17]				// read the L3 PTE
+	;;
+(p7)	tbit.z p6,p7=r18,0			// page present bit cleared?
+	;;
+(p7)	itc.i r18;;	// insert the instruction TLB entry (EAS2.6: must be last in insn group!)
+(p6)	br.spnt.few page_fault			// handle bad address/page not present (page fault)
+	;;
+	mov pr=r31,-1				// restore predicate registers
+	rfi;;					// must be last insn in an insn group
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
+	/*
+	 * The DTLB basically does the same as the VHPT handler except
+	 * that we always insert exactly one data TLB entry.
+	 */
+	mov r16=cr.ifa				// get address that caused the TLB miss
+	;;
+	rsm psr.dt				// use physical addressing for data
+	mov r31=pr				// save the predicate registers
+	mov r19=ar.k7				// get page table base address
+	shl r21=r16,3				// shift bit 60 into sign bit
+	shr.u r17=r16,61			// get the region number into r17
+	;;
+	cmp.eq p6,p7=5,r17			// is IFA pointing into to region 5?
+	shr.u r18=r16,PGDIR_SHIFT		// get bits 33-63 of the faulting address
+	;;
+(p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
+	srlz.d					// ensure "rsm psr.dt" has taken effect
+(p6)	movl r19=__pa(SWAPPER_PGD_ADDR)		// region 5 is rooted at swapper_pg_dir
+(p6)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-1
+(p7)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-4
+	;;
+(p6)	dep r17=r18,r19,3,(PAGE_SHIFT-3)	// r17=PTA + IFA(33,42)*8
+(p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
+	cmp.eq p7,p6=0,r21			// unused address bits all zeroes?
+	shr.u r18=r16,PMD_SHIFT			// shift L2 index into position
+	;;
+(p6)	cmp.eq p7,p6=-1,r21			// unused address bits all ones?
+	ld8 r17=[r17]				// fetch the L1 entry (may be 0)
+	;;
+(p7)	cmp.eq p6,p7=r17,r0			// was L1 entry NULL?
+	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// compute address of L2 page table entry
+	;;
+(p7)	ld8 r17=[r17]				// fetch the L2 entry (may be 0)
+	shr.u r19=r16,PAGE_SHIFT		// shift L3 index into position
+	;;
+(p7)	cmp.eq.or.andcm p6,p7=r17,r0		// was L2 entry NULL?
+	dep r17=r19,r17,3,(PAGE_SHIFT-3)	// compute address of L3 page table entry
+	;;
+(p7)	ld8 r18=[r17]				// read the L3 PTE
+	;;
+(p7)	tbit.z p6,p7=r18,0			// page present bit cleared?
+	;;
+(p7)	itc.d r18;;	// insert the instruction TLB entry (EAS2.6: must be last in insn group!)
+(p6)	br.spnt.few page_fault			// handle bad address/page not present (page fault)
+	;;
+	mov pr=r31,-1				// restore predicate registers
+	rfi;;					// must be last insn in an insn group
+
+	//-----------------------------------------------------------------------------------
+	// call do_page_fault (predicates are in r31, psr.dt is off, r16 is faulting address)
+page_fault:
+	SAVE_MIN_WITH_COVER
+	//
+	// Copy control registers to temporary registers, then turn on psr bits,
+	// then copy the temporary regs to the output regs.  We have to do this
+	// because the "alloc" can cause a mandatory store which could lead to
+	// an "Alt DTLB" fault which we can handle only if psr.ic is on.
+	//
+	mov r8=cr.ifa
+	mov r9=cr.isr
+	adds r3=8,r2				// set up second base pointer
+	;;
+	ssm psr.ic | psr.dt
+	;;
+	srlz.d					// guarantee that interrupt collection is enabled
+(p15)	ssm psr.i				// restore psr.i
+	;;
+	srlz.i					// must precede "alloc"! (srlz.i implies srlz.d)
+	movl r14=ia64_leave_kernel
+	;;
+	alloc r15=ar.pfs,0,0,3,0		// must be first in insn group
+	mov out0=r8
+	mov out1=r9
+	;;
+	SAVE_REST
+	mov rp=r14
+	;;
+	adds out2=16,r12			// out2 = pointer to pt_regs
+	br.call.sptk.few b6=ia64_do_page_fault	// ignore return address
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
+	mov r16=cr.ifa		// get address that caused the TLB miss
+	movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RX
+	;;
+	shr.u r18=r16,57	// move address bit 61 to bit 4
+	dep r16=0,r16,52,12	// clear top 12 bits of address
+	;;
+	andcm r18=0x10,r18	// bit 4=~address-bit(61)
+	dep r16=r17,r16,0,12	// insert PTE control bits into r16
+	;;
+	or r16=r16,r18		// set bit 4 (uncached) if the access was to region 6
+	;;
+	itc.i r16;;	// insert the TLB entry(EAS2.6: must be last in insn group!)
+	rfi;;			// must be last insn in an insn group
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
+	mov r16=cr.ifa		// get address that caused the TLB miss
+	movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RW
+	;;
+	shr.u r18=r16,57	// move address bit 61 to bit 4
+	dep r16=0,r16,52,12	// clear top 12 bits of address
+	;;
+	andcm r18=0x10,r18	// bit 4=~address-bit(61)
+	dep r16=r17,r16,0,12	// insert PTE control bits into r16
+	;;
+	or r16=r16,r18		// set bit 4 (uncached) if the access was to region 6
+	;;
+	itc.d r16;;	// insert the TLB entry (EAS2.6: must be last in insn group!)
+	rfi;;			// must be last insn in an insn group
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
+	//
+	// In the absence of kernel bugs, we get here when the Dirty-bit, Instruction
+	// Access-bit, or Data Access-bit faults cause a nested fault because the
+	// dTLB entry for the virtual page table isn't present.  In such a case,
+	// we lookup the pte for the faulting address by walking the page table
+	// and return to the contination point passed in register r30.
+	// In accessing the page tables, we don't need to check for NULL entries
+	// because if the page tables didn't map the faulting address, it would not
+	// be possible to receive one of the above faults.
+	//
+	// Input:	r16:	faulting address
+	//		r29:	saved b0
+	//		r30:	continuation address
+	//
+	// Output:	r17:	physical address of L3 PTE of faulting address
+	//		r29:	saved b0
+	//		r30:	continuation address
+	//
+	// Clobbered:	b0, r18, r19, r21, r31, psr.dt (cleared)
+	//
+	rsm psr.dt				// switch to using physical data addressing
+	mov r19=ar.k7				// get the page table base address
+	shl r21=r16,3				// shift bit 60 into sign bit
+	;;
+	mov r31=pr				// save the predicate registers
+	shr.u r17=r16,61			// get the region number into r17
+	;;
+	cmp.eq p6,p7=5,r17			// is faulting address in region 5?
+	shr.u r18=r16,PGDIR_SHIFT		// get bits 33-63 of faulting address
+	;;
+(p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
+	srlz.d
+(p6)	movl r17=__pa(SWAPPER_PGD_ADDR)		// region 5 is rooted at swapper_pg_dir
+(p6)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-1
+(p7)	shr r21=r21,PGDIR_SHIFT+PAGE_SHIFT-4
+	;;
+(p6)	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// r17=PTA + IFA(33,42)*8
+(p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
+	shr.u r18=r16,PMD_SHIFT			// shift L2 index into position
+	;;
+	ld8 r17=[r17]				// fetch the L1 entry
+	mov b0=r30
+	;;
+	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// compute address of L2 page table entry
+	;;
+	ld8 r17=[r17]				// fetch the L2 entry
+	shr.u r19=r16,PAGE_SHIFT		// shift L3 index into position
+	;;
+	dep r17=r19,r17,3,(PAGE_SHIFT-3)	// compute address of L3 page table entry
+	;;
+	mov pr=r31,-1				// restore predicates
+	br.cond.sptk.few b0			// return to continuation point
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
+	FAULT(6)
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+	FAULT(7)
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
+	//
+	// What we do here is to simply turn on the dirty bit in the PTE.  We need
+	// to update both the page-table and the TLB entry.  To efficiently access
+	// the PTE, we address it through the virtual page table.  Most likely, the
+	// TLB entry for the relevant virtual page table page is still present in
+	// the TLB so we can normally do this without additional TLB misses.
+	// In case the necessary virtual page table TLB entry isn't present, we take
+	// a nested TLB miss hit where we look up the physical address of the L3 PTE
+	// and then continue at label 1 below.
+	//
+	mov r16=cr.ifa				// get the address that caused the fault
+	movl r30=1f				// load continuation point in case of nested fault
+	;;
+	thash r17=r16				// compute virtual address of L3 PTE
+	mov r29=b0				// save b0 in case of nested fault
+	;;
+1:	ld8 r18=[r17]
+	;;					// avoid RAW on r18
+	or r18=_PAGE_D,r18			// set the dirty bit
+	mov b0=r29				// restore b0
+	;;
+	st8 [r17]=r18				// store back updated PTE
+	itc.d r18;;		// install updated PTE (EAS2.6: must be last in insn group!)
+	rfi;;					// must be last insn in an insn group
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
+	// Like Entry 8, except for instruction access
+	mov r16=cr.ifa				// get the address that caused the fault
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+	mov r31=pr				// save predicates
+	mov r30=cr.ipsr
+	;;
+	extr.u r17=r30,IA64_PSR_IS_BIT,1	// get instruction arch. indicator
+	;;
+	cmp.eq p6,p0 = r17,r0			// check if IA64 instruction set
+	;;
+(p6)	mov r16=cr.iip				// get real faulting address
+	;;
+(p6)	mov cr.ifa=r16				// reset IFA
+	mov pr=r31,-1
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+	movl r30=1f				// load continuation point in case of nested fault
+	;;
+	thash r17=r16				// compute virtual address of L3 PTE
+	mov r29=b0				// save b0 in case of nested fault)
+	;;
+1:	ld8 r18=[r17]
+	;;					// avoid raw on r18
+	or r18=_PAGE_A,r18			// set the accessed bit
+	mov b0=r29				// restore b0
+	;;
+	st8 [r17]=r18				// store back updated PTE
+	itc.i r18;;		// install updated PTE (EAS2.6: must be last in insn group!)
+	rfi;;					// must be last insn in an insn group
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
+	// Like Entry 8, except for data access
+	mov r16=cr.ifa				// get the address that caused the fault
+	movl r30=1f				// load continuation point in case of nested fault
+	;;
+	thash r17=r16				// compute virtual address of L3 PTE
+	mov r29=b0				// save b0 in case of nested fault)
+	;;
+1:	ld8 r18=[r17]
+	;;					// avoid RAW on r18
+	or r18=_PAGE_A,r18			// set the accessed bit
+	mov b0=r29				// restore b0
+	;;
+	st8 [r17]=r18				// store back updated PTE
+	itc.d r18;;		// install updated PTE (EAS2.6: must be last in insn group!)
+	rfi;;					// must be last insn in an insn group
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
+	mov r16=cr.iim
+	mov r17=__IA64_BREAK_SYSCALL
+	mov r31=pr		// prepare to save predicates
+	rsm psr.dt		// avoid nested faults due to TLB misses...
+	;;
+	srlz.d			// ensure everyone knows psr.dt is off...
+	cmp.eq p0,p7=r16,r17	// is this a system call? (p7 <- false, if so)
+
+#if 1
+	// Allow syscalls via the old system call number for the time being.  This is
+	// so we can transition to the new syscall number in a relatively smooth
+	// fashion.
+	mov r17=0x80000
+	;;
+(p7)	cmp.eq.or.andcm p0,p7=r16,r17		// is this the old syscall number?
+#endif
+
+(p7)	br.cond.spnt.many non_syscall
+
+	SAVE_MIN				// uses r31; defines r2:
+
+	// turn interrupt collection and data translation back on:
+	ssm psr.ic | psr.dt
+	srlz.d					// guarantee that interrupt collection is enabled
+	cmp.eq pSys,pNonSys=r0,r0		// set pSys=1, pNonSys=0
+	;;
+(p15)	ssm psr.i		// restore psr.i
+	;;
+	srlz.i			// ensure everybody knows psr.ic and psr.dt are back on
+	adds r8=(IA64_PT_REGS_R8_OFFSET-IA64_PT_REGS_R16_OFFSET),r2
+	;;
+	stf8 [r8]=f1		// ensure pt_regs.r8 != 0 (see handle_syscall_error)
+	adds r3=8,r2		// set up second base pointer for SAVE_REST
+	;;
+	SAVE_REST
+	;;			// avoid WAW on r2 & r3
+
+	mov r3=255
+	adds r15=-1024,r15			// r15 contains the syscall number---subtract 1024
+	adds r2=IA64_TASK_FLAGS_OFFSET,r13	// r2 = &current->flags
+
+	;;
+	cmp.geu.unc p6,p7=r3,r15		// (syscall > 0 && syscall <= 1024+255) ?
+	movl r16=sys_call_table
+	;;
+(p6)	shladd r16=r15,3,r16
+	movl r15=ia64_ret_from_syscall
+(p7)	adds r16=(__NR_ni_syscall-1024)*8,r16	// force __NR_ni_syscall
+	;;
+	ld8 r16=[r16]				// load address of syscall entry point
+	mov rp=r15				// set the real return addr
+	;;
+	ld8 r2=[r2]				// r2 = current->flags
+	mov b6=r16
+
+	// arrange things so we skip over break instruction when returning:
+
+	adds r16=16,sp				// get pointer to cr_ipsr
+	adds r17=24,sp				// get pointer to cr_iip
+	;;
+	ld8 r18=[r16]				// fetch cr_ipsr
+	tbit.z p8,p0=r2,5			// (current->flags & PF_TRACESYS) == 0?
+	;;
+	ld8 r19=[r17]				// fetch cr_iip
+	extr.u r20=r18,41,2			// extract ei field
+	;;
+	cmp.eq p6,p7=2,r20			// isr.ei==2?
+	adds r19=16,r19				// compute address of next bundle
+	;;
+(p6)	mov r20=0				// clear ei to 0
+(p7)	adds r20=1,r20				// increment ei to next slot
+	;;
+(p6)	st8 [r17]=r19				// store new cr.iip if cr.isr.ei wrapped around
+	dep r18=r20,r18,41,2			// insert new ei into cr.isr
+	;;
+	st8 [r16]=r18				// store new value for cr.isr
+
+(p8)	br.call.sptk.few b6=b6			// ignore this return addr 
+	br.call.sptk.few rp=ia64_trace_syscall	// rp will be overwritten (ignored)
+	// NOT REACHED
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
+	rsm psr.dt		// avoid nested faults due to TLB misses...
+	;;
+	srlz.d			// ensure everyone knows psr.dt is off...
+	mov r31=pr		// prepare to save predicates
+	;;
+
+	SAVE_MIN_WITH_COVER	// uses r31; defines r2 and r3
+	ssm psr.ic | psr.dt	// turn interrupt collection and data translation back on
+	;;
+	adds r3=8,r2		// set up second base pointer for SAVE_REST
+	cmp.eq pEOI,p0=r0,r0	// set pEOI flag so that ia64_leave_kernel writes cr.eoi
+	srlz.i			// ensure everybody knows psr.ic and psr.dt are back on
+	;;
+	SAVE_REST
+	;;
+	alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
+#ifdef	CONFIG_ITANIUM_ASTEP_SPECIFIC
+	mov out0=r0		// defer reading of cr.ivr to handle_irq...
+#else
+	mov out0=cr.ivr		// pass cr.ivr as first arg
+#endif
+	add out1=16,sp		// pass pointer to pt_regs as second arg
+	;;
+	srlz.d			// make  sure we see the effect of cr.ivr
+	movl r14=ia64_leave_kernel
+	;;
+	mov rp=r14
+	br.call.sptk.few b6=ia64_handle_irq
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3400 Entry 13 (size 64 bundles) Reserved
+	FAULT(13)
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3800 Entry 14 (size 64 bundles) Reserved
+	FAULT(14)
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3c00 Entry 15 (size 64 bundles) Reserved
+	FAULT(15)
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4000 Entry 16 (size 64 bundles) Reserved
+	FAULT(16)
+
+#ifdef CONFIG_IA32_SUPPORT
+
+	// There is no particular reason for this code to be here, other than that
+	// there happens to be space here that would go unused otherwise.  If this
+	// fault ever gets "unreserved", simply moved the following code to a more
+	// suitable spot...
+
+	// IA32 interrupt entry point
+
+dispatch_to_ia32_handler:
+	SAVE_MIN
+	;;
+	mov r14=cr.isr
+	ssm psr.ic | psr.dt
+	srlz.d					// guarantee that interrupt collection is enabled
+	;;
+(p15)	ssm psr.i
+	;;
+	srlz.d
+	adds r3=8,r2            // Base pointer for SAVE_REST
+	;;
+	SAVE_REST
+	;;
+	mov r15=0x80
+	shr r14=r14,16          // Get interrupt number
+	;; 
+	cmp.ne p6,p0=r14,r15
+(p6)    br.call.dpnt.few b6=non_ia32_syscall
+
+	adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp	// 16 byte hole per SW conventions
+
+	;;
+	alloc r15=ar.pfs,0,0,6,0	// must first in an insn group
+	;; 
+	ld4 r8=[r14],8          // r8 == EAX (syscall number)
+	mov r15=0xff
+	;;
+	cmp.ltu.unc p6,p7=r8,r15
+	ld4 out1=[r14],8        // r9 == ecx
+	;;
+	ld4 out2=[r14],8         // r10 == edx
+	;;
+	ld4 out0=[r14]           // r11 == ebx
+	adds r14=(IA64_PT_REGS_R8_OFFSET-(8*3)) + 16,sp
+	;;
+	ld4 out5=[r14],8         // r13 == ebp
+	;;
+	ld4 out3=[r14],8         // r14 == esi
+	adds r2=IA64_TASK_FLAGS_OFFSET,r13	// r2 = &current->flags
+	;;
+	ld4 out4=[r14]           // R15 == edi
+	movl r16=ia32_syscall_table
+	;; 
+(p6)    shladd r16=r8,3,r16     // Force ni_syscall if not valid syscall number
+	ld8 r2=[r2]		// r2 = current->flags
+	;; 
+	ld8 r16=[r16]
+	tbit.z p8,p0=r2,5	// (current->flags & PF_TRACESYS) == 0?
+	;;
+	movl r15=ia32_ret_from_syscall
+	mov b6=r16
+	;;
+	mov rp=r15
+(p8)	br.call.sptk.few b6=b6
+	br.call.sptk.few rp=ia32_trace_syscall	// rp will be overwritten (ignored)
+
+non_ia32_syscall:       
+	alloc r15=ar.pfs,0,0,2,0
+	mov out0=r14                            // interrupt #
+	add out1=16,sp                          // pointer to pt_regs
+	;;			// avoid WAW on CFM
+	br.call.sptk.few rp=ia32_bad_interrupt
+	;; 
+	movl r15=ia64_leave_kernel
+	;;
+	mov rp=r15
+	br.ret.sptk.many rp
+
+#endif /* CONFIG_IA32_SUPPORT */
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4400 Entry 17 (size 64 bundles) Reserved
+	FAULT(17)
+
+non_syscall:
+
+#ifdef CONFIG_KDB
+	mov r17=__IA64_BREAK_KDB
+	;;
+	cmp.eq p8,p0=r16,r17		// is this a kernel breakpoint?
+#endif
+
+	SAVE_MIN_WITH_COVER
+
+	// There is no particular reason for this code to be here, other than that
+	// there happens to be space here that would go unused otherwise.  If this
+	// fault ever gets "unreserved", simply moved the following code to a more
+	// suitable spot...
+
+	mov r8=cr.iim			// get break immediate (must be done while psr.ic is off)
+	adds r3=8,r2			// set up second base pointer for SAVE_REST
+
+	// turn interrupt collection and data translation back on:
+	ssm psr.ic | psr.dt
+	srlz.d					// guarantee that interrupt collection is enabled
+	;;
+(p15)	ssm psr.i			// restore psr.i
+	;;
+	srlz.i				// ensure everybody knows psr.ic and psr.dt are back on
+	movl r15=ia64_leave_kernel
+	;;
+	alloc r14=ar.pfs,0,0,2,0
+	mov out0=r8			// break number
+	add out1=16,sp			// pointer to pt_regs
+	;;
+	SAVE_REST
+	mov rp=r15
+	;;
+#ifdef CONFIG_KDB
+(p8)	br.call.sptk.few b6=ia64_invoke_kdb
+#endif
+	br.call.sptk.few b6=ia64_bad_break	// avoid WAW on CFM and ignore return addr
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4800 Entry 18 (size 64 bundles) Reserved
+	FAULT(18)
+
+	// There is no particular reason for this code to be here, other than that
+	// there happens to be space here that would go unused otherwise.  If this
+	// fault ever gets "unreserved", simply moved the following code to a more
+	// suitable spot...
+
+dispatch_unaligned_handler:
+	SAVE_MIN_WITH_COVER
+	;;
+	//
+	// we can't have the alloc while psr.ic is cleared because 
+	// we might get a mandatory RSE (when you reach the end of the 
+	// rotating partition when doing the alloc) spill which could cause 
+	// a page fault on the kernel virtual address and the handler 
+	// wouldn't get the state to recover.
+	//
+	mov r15=cr.ifa
+	ssm psr.ic | psr.dt
+	srlz.d					// guarantee that interrupt collection is enabled
+	;;
+(p15)	ssm psr.i				// restore psr.i
+	;;
+	srlz.i
+	adds r3=8,r2				// set up second base pointer
+	;;
+	SAVE_REST
+	;;
+	alloc r14=ar.pfs,0,0,2,0		// now it's safe (must be first in insn group!)
+	;;					// avoid WAW on r14
+	movl r14=ia64_leave_kernel
+	mov out0=r15				// out0 = faulting address
+	adds out1=16,sp				// out1 = pointer to pt_regs
+	;;
+	mov rp=r14
+	br.sptk.few ia64_prepare_handle_unaligned
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4c00 Entry 19 (size 64 bundles) Reserved
+	FAULT(19)
+
+	// There is no particular reason for this code to be here, other than that
+	// there happens to be space here that would go unused otherwise.  If this
+	// fault ever gets "unreserved", simply moved the following code to a more
+	// suitable spot...
+
+dispatch_to_fault_handler:
+	//
+	// Input:
+	//	psr.ic:	off
+	//	psr.dt:	off
+	//	r19:	fault vector number (e.g., 24 for General Exception)
+	//	r31:	contains saved predicates (pr)
+	//
+	SAVE_MIN_WITH_COVER_R19
+	//
+	// Copy control registers to temporary registers, then turn on psr bits,
+	// then copy the temporary regs to the output regs.  We have to do this
+	// because the "alloc" can cause a mandatory store which could lead to
+	// an "Alt DTLB" fault which we can handle only if psr.ic is on.
+	//
+	mov r8=cr.isr
+	mov r9=cr.ifa
+	mov r10=cr.iim
+	mov r11=cr.itir
+	;;
+	ssm psr.ic | psr.dt
+	srlz.d					// guarantee that interrupt collection is enabled
+	;;
+(p15)	ssm psr.i				// restore psr.i
+	adds r3=8,r2				// set up second base pointer for SAVE_REST
+	;;
+	srlz.i					// must precede "alloc"!
+	;;
+	alloc r14=ar.pfs,0,0,5,0		// must be first in insn group
+	mov out0=r15
+	mov out1=r8
+	mov out2=r9
+	mov out3=r10
+	mov out4=r11
+	;;
+	SAVE_REST
+	movl r14=ia64_leave_kernel
+	;;
+	mov rp=r14
+#ifdef CONFIG_KDB
+	br.call.sptk.few b6=ia64_invoke_kdb_fault_handler
+#else
+	br.call.sptk.few b6=ia64_fault
+#endif
+//
+// --- End of long entries, Beginning of short entries
+//
+
+	.align 1024
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
+	mov r16=cr.ifa
+	rsm psr.dt
+#if 0
+	// If you disable this, you MUST re-enable to update_mmu_cache() code in pgtable.h
+	mov r17=_PAGE_SIZE_4K<<2
+	;;
+	ptc.l r16,r17
+#endif
+	;;
+	mov r31=pr
+	srlz.d
+	br.cond.sptk.many page_fault
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
+	mov r16=cr.ifa
+	rsm psr.dt
+	mov r31=pr
+	;;
+	srlz.d
+	br.cond.sptk.many page_fault
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
+	mov r16=cr.ifa
+	rsm psr.dt
+	mov r31=pr
+	;;
+	srlz.d
+	br.cond.sptk.many page_fault
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
+	mov r16=cr.ifa
+	rsm psr.dt
+	mov r31=pr
+	;;
+	srlz.d
+	br.cond.sptk.many page_fault
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
+	FAULT(24)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
+	rsm psr.dt | psr.dfh			// ensure we can access fph
+	;;
+	srlz.d
+	mov r31=pr
+	mov r19=25
+	br.cond.sptk.many dispatch_to_fault_handler
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
+	FAULT(26)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
+	//
+	// A [f]chk.[as] instruction needs to take the branch to
+	// the recovery code but this part of the architecture is
+	// not implemented in hardware on some CPUs, such as Itanium.
+	// Thus, in general we need to emulate the behavior.
+	// IIM contains the relative target (not yet sign extended).
+	// So after sign extending it we simply add it to IIP.
+	// We also need to reset the EI field of the IPSR to zero,
+	// i.e., the slot to restart into.
+	//
+	// cr.imm contains zero_ext(imm21)
+	//
+	mov r18=cr.iim
+	;;
+	mov r17=cr.iip
+	shl r18=r18,43			// put sign bit in position (43=64-21)
+	;;
+
+	mov r16=cr.ipsr
+	shr r18=r18,39			// sign extend (39=43-4)
+	;;
+
+	add r17=r17,r18			// now add the offset
+	;;
+	mov cr.iip=r17
+	dep r16=0,r16,41,2		// clear EI
+	;;
+
+	mov cr.ipsr=r16
+	;;
+
+	rfi;;				// and go back (must be last insn in group)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5800 Entry 28 (size 16 bundles) Reserved
+	FAULT(28)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
+	FAULT(29)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
+	rsm psr.dt		// avoid nested faults due to TLB misses...
+	mov r16=cr.ipsr
+	mov r31=pr		// prepare to save predicates
+	;;									
+	srlz.d			// ensure everyone knows psr.dt is off
+	mov r19=30		// error vector for fault_handler (when kernel)
+	extr.u r16=r16,32,2	// extract psr.cpl
+	;;
+	cmp.eq p6,p7=r0,r16	// if kernel cpl then fault else emulate
+(p7)	br.cond.sptk.many dispatch_unaligned_handler
+(p6)	br.cond.sptk.many dispatch_to_fault_handler
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
+	FAULT(31)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
+	FAULT(32)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
+	FAULT(33)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Tranfer Trap (66)
+	FAULT(34)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
+	FAULT(35)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
+	FAULT(36)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6100 Entry 37 (size 16 bundles) Reserved
+	FAULT(37)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6200 Entry 38 (size 16 bundles) Reserved
+	FAULT(38)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6300 Entry 39 (size 16 bundles) Reserved
+	FAULT(39)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6400 Entry 40 (size 16 bundles) Reserved
+	FAULT(40)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6500 Entry 41 (size 16 bundles) Reserved
+	FAULT(41)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6600 Entry 42 (size 16 bundles) Reserved
+	FAULT(42)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6700 Entry 43 (size 16 bundles) Reserved
+	FAULT(43)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6800 Entry 44 (size 16 bundles) Reserved
+	FAULT(44)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
+	FAULT(45)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept  (30,31,59,70,71)
+	FAULT(46)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt  (74)
+#ifdef CONFIG_IA32_SUPPORT
+	rsm psr.dt
+	;;
+	srlz.d
+	mov r31=pr
+	br.cond.sptk.many dispatch_to_ia32_handler
+#else
+	FAULT(47)
+#endif
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6c00 Entry 48 (size 16 bundles) Reserved
+	FAULT(48)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6d00 Entry 49 (size 16 bundles) Reserved
+	FAULT(49)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6e00 Entry 50 (size 16 bundles) Reserved
+	FAULT(50)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6f00 Entry 51 (size 16 bundles) Reserved
+	FAULT(51)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7000 Entry 52 (size 16 bundles) Reserved
+	FAULT(52)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7100 Entry 53 (size 16 bundles) Reserved
+	FAULT(53)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7200 Entry 54 (size 16 bundles) Reserved
+	FAULT(54)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7300 Entry 55 (size 16 bundles) Reserved
+	FAULT(55)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7400 Entry 56 (size 16 bundles) Reserved
+	FAULT(56)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7500 Entry 57 (size 16 bundles) Reserved
+	FAULT(57)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7600 Entry 58 (size 16 bundles) Reserved
+	FAULT(58)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7700 Entry 59 (size 16 bundles) Reserved
+	FAULT(59)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7800 Entry 60 (size 16 bundles) Reserved
+	FAULT(60)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7900 Entry 61 (size 16 bundles) Reserved
+	FAULT(61)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7a00 Entry 62 (size 16 bundles) Reserved
+	FAULT(62)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7b00 Entry 63 (size 16 bundles) Reserved
+	FAULT(63)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7c00 Entry 64 (size 16 bundles) Reserved
+	FAULT(64)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7d00 Entry 65 (size 16 bundles) Reserved
+	FAULT(65)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7e00 Entry 66 (size 16 bundles) Reserved
+	FAULT(66)
+
+	.align 256
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7f00 Entry 67 (size 16 bundles) Reserved
+	FAULT(67)
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/machvec.c linux/arch/ia64/kernel/machvec.c
--- v2.3.42/linux/arch/ia64/kernel/machvec.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/machvec.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,48 @@
+#include <linux/kernel.h>
+
+#include <asm/page.h>
+#include <asm/machvec.h>
+
+struct ia64_machine_vector ia64_mv;
+
+void
+machvec_noop (void)
+{
+}
+
+/*
+ * Most platforms use this routine for mapping page frame addresses
+ * into a memory map index.
+ */
+unsigned long
+map_nr_dense (unsigned long addr)
+{
+	return MAP_NR_DENSE(addr);
+}
+
+static struct ia64_machine_vector *
+lookup_machvec (const char *name)
+{
+	extern struct ia64_machine_vector machvec_start[];
+	extern struct ia64_machine_vector machvec_end[];
+	struct ia64_machine_vector *mv;
+
+	for (mv = machvec_start; mv < machvec_end; ++mv)
+		if (strcmp (mv->name, name) == 0)
+			return mv;
+
+	return 0;
+}
+
+void
+machvec_init (const char *name)
+{
+	struct ia64_machine_vector *mv;
+
+	mv = lookup_machvec(name);
+	if (!mv) {
+		panic("generic kernel failed to find machine vector for platform %s!", name);
+	}
+	ia64_mv = *mv;
+	printk("booting generic kernel on platform %s\n", name);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/mca.c linux/arch/ia64/kernel/mca.c
--- v2.3.42/linux/arch/ia64/kernel/mca.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/mca.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,842 @@
+/*
+ * File: 	mca.c
+ * Purpose: 	Generic MCA handling layer
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/sal.h>
+#include <asm/mca.h>
+#include <asm/spinlock.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+
+
+ia64_mc_info_t			ia64_mc_info;
+ia64_mca_sal_to_os_state_t	ia64_sal_to_os_handoff_state;
+ia64_mca_os_to_sal_state_t	ia64_os_to_sal_handoff_state;
+u64				ia64_mca_proc_state_dump[256];
+u64				ia64_mca_stack[1024];
+u64				ia64_mca_stackframe[32];
+u64				ia64_mca_bspstore[1024];
+
+static void			ia64_mca_cmc_vector_setup(int 		enable, 
+							  int_vector_t 	cmc_vector);
+static void			ia64_mca_wakeup_ipi_wait(void);
+static void			ia64_mca_wakeup(int cpu);
+static void			ia64_mca_wakeup_all(void);
+static void			ia64_log_init(int,int);
+static void			ia64_log_get(int,int, prfunc_t);
+static void			ia64_log_clear(int,int,int, prfunc_t);
+
+/*
+ * ia64_mca_cmc_vector_setup
+ *	Setup the correctable machine check vector register in the processor
+ * Inputs
+ *	Enable (1 - enable cmc interrupt , 0 - disable)
+ *	CMC handler entry point (if enabled)
+ *
+ * Outputs
+ *	None
+ */
+static void
+ia64_mca_cmc_vector_setup(int 		enable, 
+			  int_vector_t 	cmc_vector)
+{
+	cmcv_reg_t	cmcv;
+
+	cmcv.cmcv_regval 	= 0;
+	cmcv.cmcv_mask  	= enable;
+	cmcv.cmcv_vector 	= cmc_vector;
+	ia64_set_cmcv(cmcv.cmcv_regval);
+}
+
+
+#if defined(MCA_TEST)
+
+sal_log_processor_info_t	slpi_buf;
+
+void
+mca_test(void)
+{
+	slpi_buf.slpi_valid.slpi_psi = 1;
+	slpi_buf.slpi_valid.slpi_cache_check = 1;
+	slpi_buf.slpi_valid.slpi_tlb_check = 1;
+	slpi_buf.slpi_valid.slpi_bus_check = 1;
+	slpi_buf.slpi_valid.slpi_minstate = 1;
+	slpi_buf.slpi_valid.slpi_bank1_gr = 1;
+	slpi_buf.slpi_valid.slpi_br = 1;
+	slpi_buf.slpi_valid.slpi_cr = 1;
+	slpi_buf.slpi_valid.slpi_ar = 1;
+	slpi_buf.slpi_valid.slpi_rr = 1;
+	slpi_buf.slpi_valid.slpi_fr = 1;
+
+	ia64_os_mca_dispatch();
+}
+
+#endif /* #if defined(MCA_TEST) */
+
+/*
+ * mca_init
+ *	Do all the mca specific initialization on a per-processor basis.
+ *
+ *	1. Register spinloop and wakeup request interrupt vectors
+ *
+ *	2. Register OS_MCA handler entry point
+ *
+ *	3. Register OS_INIT handler entry point
+ *
+ *	4. Initialize CMCV register to enable/disable CMC interrupt on the
+ *	   processor and hook a handler in the platform-specific mca_init.
+ *
+ *	5. Initialize MCA/CMC/INIT related log buffers maintained by the OS.
+ *
+ * Inputs
+ *	None
+ * Outputs
+ *	None
+ */
+void __init
+mca_init(void)
+{
+	int	i;
+
+	MCA_DEBUG("mca_init : begin\n");
+	/* Clear the Rendez checkin flag for all cpus */
+	for(i = 0 ; i < IA64_MAXCPUS; i++)
+		ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+
+	/* NOTE : The actual irqs for the rendez, wakeup and 
+	 * cmc interrupts are requested in the platform-specific
+	 * mca initialization code.
+	 */
+	/* 
+	 * Register the rendezvous spinloop and wakeup mechanism with SAL
+	 */
+
+	/* Register the rendezvous interrupt vector with SAL */
+	if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT,
+				   SAL_MC_PARAM_MECHANISM_INT,
+				   IA64_MCA_RENDEZ_INT_VECTOR,
+				   IA64_MCA_RENDEZ_TIMEOUT))
+		return;
+
+	/* Register the wakeup interrupt vector with SAL */
+	if (ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP,
+				   SAL_MC_PARAM_MECHANISM_INT,
+				   IA64_MCA_WAKEUP_INT_VECTOR,
+				   0))
+		return;
+
+	MCA_DEBUG("mca_init : registered mca rendezvous spinloop and wakeup mech.\n");
+	/*
+	 * Setup the correctable machine check vector
+	 */
+	ia64_mca_cmc_vector_setup(IA64_CMC_INT_ENABLE, 
+				  IA64_MCA_CMC_INT_VECTOR);
+
+	MCA_DEBUG("mca_init : correctable mca vector setup done\n");
+
+	ia64_mc_info.imi_mca_handler 		= __pa(ia64_os_mca_dispatch);
+	ia64_mc_info.imi_mca_handler_size	= 
+		__pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch);
+	/* Register the os mca handler with SAL */
+	if (ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
+				 ia64_mc_info.imi_mca_handler,
+				 __pa(ia64_get_gp()),
+				 ia64_mc_info.imi_mca_handler_size,
+				 0,0,0))
+
+		return;
+
+	MCA_DEBUG("mca_init : registered os mca handler with SAL\n");
+
+	ia64_mc_info.imi_monarch_init_handler 		= __pa(ia64_monarch_init_handler);
+	ia64_mc_info.imi_monarch_init_handler_size	= IA64_INIT_HANDLER_SIZE;
+	ia64_mc_info.imi_slave_init_handler 		= __pa(ia64_slave_init_handler);
+	ia64_mc_info.imi_slave_init_handler_size	= IA64_INIT_HANDLER_SIZE;
+	/* Register the os init handler with SAL */
+	if (ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
+				 ia64_mc_info.imi_monarch_init_handler,
+				 __pa(ia64_get_gp()),
+				 ia64_mc_info.imi_monarch_init_handler_size,
+				 ia64_mc_info.imi_slave_init_handler,
+				 __pa(ia64_get_gp()),
+				 ia64_mc_info.imi_slave_init_handler_size))
+
+
+		return;
+
+	MCA_DEBUG("mca_init : registered os init handler with SAL\n");
+
+	/* Initialize the areas set aside by the OS to buffer the 
+	 * platform/processor error states for MCA/INIT/CMC
+	 * handling.
+	 */
+	ia64_log_init(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR);
+	ia64_log_init(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM);
+	ia64_log_init(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PROCESSOR);
+	ia64_log_init(SAL_INFO_TYPE_INIT, SAL_SUB_INFO_TYPE_PLATFORM);
+	ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR);
+	ia64_log_init(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM);
+
+	mca_init_platform();
+	
+	MCA_DEBUG("mca_init : platform-specific mca handling setup done\n");
+
+#if defined(MCA_TEST)
+	mca_test();
+#endif /* #if defined(MCA_TEST) */
+
+	printk("Mca related initialization done\n");
+}
+
+/*
+ * ia64_mca_wakeup_ipi_wait
+ *	Wait for the inter-cpu interrupt to be sent by the
+ * 	monarch processor once it is done with handling the
+ *	MCA.
+ * Inputs 
+ *	None
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_wakeup_ipi_wait(void)
+{
+	int	irr_num = (IA64_MCA_WAKEUP_INT_VECTOR >> 6);
+	int	irr_bit = (IA64_MCA_WAKEUP_INT_VECTOR & 0x3f);
+	u64	irr = 0;
+
+	do {
+		switch(irr_num) {
+		case 0:
+			irr = ia64_get_irr0();
+			break;
+		case 1:
+			irr = ia64_get_irr1();
+			break;
+		case 2:
+			irr = ia64_get_irr2();
+			break;
+		case 3:
+			irr = ia64_get_irr3();
+			break;
+		}
+	} while (!(irr & (1 << irr_bit))) ;
+}
+
+/*
+ * ia64_mca_wakeup
+ *	Send an inter-cpu interrupt to wake-up a particular cpu
+ * 	and mark that cpu to be out of rendez.
+ * Inputs
+ *	cpuid
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_wakeup(int cpu)
+{
+	ipi_send(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT);
+	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+	
+}
+/*
+ * ia64_mca_wakeup_all
+ *	Wakeup all the cpus which have rendez'ed previously.
+ * Inputs
+ *	None
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_wakeup_all(void)
+{
+	int cpu;
+
+	/* Clear the Rendez checkin flag for all cpus */
+	for(cpu = 0 ; cpu < IA64_MAXCPUS; cpu++)
+		if (ia64_mc_info.imi_rendez_checkin[cpu] == IA64_MCA_RENDEZ_CHECKIN_DONE)
+			ia64_mca_wakeup(cpu);
+
+}
+/*
+ * ia64_mca_rendez_interrupt_handler
+ *	This is handler used to put slave processors into spinloop 
+ *	while the monarch processor does the mca handling and later
+ *	wake each slave up once the monarch is done.
+ * Inputs 
+ *	None
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
+{
+	int flags;
+	/* Mask all interrupts */
+        save_and_cli(flags);
+
+	ia64_mc_info.imi_rendez_checkin[ia64_get_cpuid(0)] = IA64_MCA_RENDEZ_CHECKIN_DONE;
+	/* Register with the SAL monarch that the slave has
+	 * reached SAL
+	 */
+	ia64_sal_mc_rendez();
+
+	/* Wait for the wakeup IPI from the monarch 
+	 * This waiting is done by polling on the wakeup-interrupt
+	 * vector bit in the processor's IRRs
+	 */
+	ia64_mca_wakeup_ipi_wait();
+
+	/* Enable all interrupts */
+	restore_flags(flags);
+
+
+}
+
+
+/*
+ * ia64_mca_wakeup_int_handler
+ *	The interrupt handler for processing the inter-cpu interrupt to the
+ * 	slave cpu which was spinning in the rendez loop.
+ *	Since this spinning is done by turning off the interrupts and
+ *	polling on the wakeup-interrupt bit in the IRR, there is 
+ *	nothing useful to be done in the handler.
+ *  Inputs
+ *	wakeup_irq	(Wakeup-interrupt bit)
+ *	arg		(Interrupt handler specific argument)
+ *	ptregs		(Exception frame at the time of the interrupt)
+ *  Outputs
+ *	
+ */
+void
+ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
+{
+	
+}
+
+/*
+ * ia64_return_to_sal_check
+ *	This is function called before going back from the OS_MCA handler
+ * 	to the OS_MCA dispatch code which finally takes the control back
+ * 	to the SAL.
+ *	The main purpose of this routine is to setup the OS_MCA to SAL
+ *	return state which can be used by the OS_MCA dispatch code 
+ *	just before going back to SAL.
+ * Inputs
+ *	None
+ * Outputs
+ *	None
+ */
+
+void
+ia64_return_to_sal_check(void)
+{
+	/* Copy over some relevant stuff from the sal_to_os_mca_handoff
+	 * so that it can be used at the time of os_mca_to_sal_handoff
+	 */
+	ia64_os_to_sal_handoff_state.imots_sal_gp = 
+		ia64_sal_to_os_handoff_state.imsto_sal_gp;
+
+	ia64_os_to_sal_handoff_state.imots_sal_check_ra = 
+		ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
+
+	/* For now ignore the MCA */
+	ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
+}
+/* 
+ * ia64_mca_ucmc_handler
+ *	This is uncorrectable machine check handler called from OS_MCA
+ *	dispatch code which is in turn called from SAL_CHECK().
+ *	This is the place where the core of OS MCA handling is done.
+ *	Right now the logs are extracted and displayed in a well-defined
+ *	format. This handler code is supposed to be run only on the
+ *	monarch processor. Once the  monarch is done with MCA handling
+ *	further MCA logging is enabled by clearing logs.
+ *	Monarch also has the duty of sending wakeup-IPIs to pull the
+ *	slave processors out of rendez. spinloop.
+ * Inputs
+ *	None
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_ucmc_handler(void)
+{
+
+	/* Get the MCA processor log */
+	ia64_log_get(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
+	/* Get the MCA platform log */
+	ia64_log_get(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk);
+
+	ia64_log_print(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
+
+	/* 
+	 * Do some error handling - Platform-specific mca handler is called at this point
+	 */
+
+	mca_handler_platform() ;
+
+	/* Clear the SAL MCA logs */
+	ia64_log_clear(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PROCESSOR, 1, printk);
+	ia64_log_clear(SAL_INFO_TYPE_MCA, SAL_SUB_INFO_TYPE_PLATFORM, 1, printk);
+
+	/* Wakeup all the processors which are spinning in the rendezvous
+	 * loop.
+	 */
+	ia64_mca_wakeup_all();
+	ia64_return_to_sal_check();
+}
+
+/*
+ * SAL to OS entry point for INIT on the monarch processor
+ * This has been defined for registration purposes with SAL 
+ * as a part of mca_init.
+ */
+void
+ia64_monarch_init_handler()
+{
+}
+/*
+ * SAL to OS entry point for INIT on the slave processor
+ * This has been defined for registration purposes with SAL 
+ * as a part of mca_init.
+ */
+
+void
+ia64_slave_init_handler()
+{
+}
+/* 
+ * ia64_mca_cmc_int_handler
+ *	This is correctable machine check interrupt handler.
+ *	Right now the logs are extracted and displayed in a well-defined
+ *	format. 
+ * Inputs
+ *	None
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
+{	
+	/* Get the CMC processor log */
+	ia64_log_get(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
+	/* Get the CMC platform log */
+	ia64_log_get(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM, (prfunc_t)printk);
+
+
+	ia64_log_print(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR, (prfunc_t)printk);
+	cmci_handler_platform(cmc_irq, arg, ptregs);
+
+	/* Clear the CMC SAL logs now that they have been saved in the OS buffer */
+	ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PROCESSOR);
+	ia64_sal_clear_state_info(SAL_INFO_TYPE_CMC, SAL_SUB_INFO_TYPE_PLATFORM);
+}
+
+/*
+ * IA64_MCA log support
+ */
+#define IA64_MAX_LOGS		2	/* Double-buffering for nested MCAs */
+#define IA64_MAX_LOG_TYPES	3	/* MCA, CMC, INIT */
+#define IA64_MAX_LOG_SUBTYPES	2	/* Processor, Platform */
+
+typedef struct ia64_state_log_s {
+	spinlock_t		isl_lock;
+	int			isl_index;
+	sal_log_header_t	isl_log[IA64_MAX_LOGS];
+
+} ia64_state_log_t;
+
+static ia64_state_log_t	ia64_state_log[IA64_MAX_LOG_TYPES][IA64_MAX_LOG_SUBTYPES];
+
+#define IA64_LOG_LOCK_INIT(it, sit)	spin_lock_init(&ia64_state_log[it][sit].isl_lock)
+#define IA64_LOG_LOCK(it, sit)	 	spin_lock_irqsave(&ia64_state_log[it][sit].isl_lock, s)
+#define IA64_LOG_UNLOCK(it, sit) 	spin_unlock_irqrestore(&ia64_state_log[it][sit].isl_lock,\
+							       s)
+#define IA64_LOG_NEXT_INDEX(it, sit)	ia64_state_log[it][sit].isl_index
+#define IA64_LOG_CURR_INDEX(it, sit) 	1 - ia64_state_log[it][sit].isl_index
+#define IA64_LOG_INDEX_INC(it, sit)	\
+	ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index
+#define IA64_LOG_INDEX_DEC(it, sit)	\
+	ia64_state_log[it][sit].isl_index = 1 - ia64_state_log[it][sit].isl_index
+#define IA64_LOG_NEXT_BUFFER(it, sit) 	(void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_NEXT_INDEX(it,sit)]))
+#define IA64_LOG_CURR_BUFFER(it, sit) 	(void *)(&(ia64_state_log[it][sit].isl_log[IA64_LOG_CURR_INDEX(it,sit)]))
+
+/*
+ * ia64_log_init
+ * 	Reset the OS ia64 log buffer
+ * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
+ * Outputs	: 	None
+ */
+void
+ia64_log_init(int sal_info_type, int sal_sub_info_type)
+{
+	IA64_LOG_LOCK_INIT(sal_info_type, sal_sub_info_type);
+	IA64_LOG_NEXT_INDEX(sal_info_type, sal_sub_info_type) = 0;
+	memset(IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type), 0, 
+	       sizeof(sal_log_header_t) * IA64_MAX_LOGS);
+}
+
+/* 
+ * ia64_log_get
+ * 	Get the current MCA log from SAL and copy it into the OS log buffer.
+ * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
+ * Outputs	: 	None
+ *
+ */
+void
+ia64_log_get(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc)
+{
+	sal_log_header_t	*log_buffer;
+	int			s;
+
+	IA64_LOG_LOCK(sal_info_type, sal_sub_info_type);
+
+
+	/* Get the process state information */
+	log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type, sal_sub_info_type);
+
+	if (ia64_sal_get_state_info(sal_info_type, sal_sub_info_type ,(u64 *)log_buffer))
+		prfunc("ia64_mca_log_get : Getting processor log failed\n");
+
+	IA64_LOG_INDEX_INC(sal_info_type, sal_sub_info_type);
+
+	IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type);
+
+}
+
+/* 
+ * ia64_log_clear
+ * 	Clear the current MCA log from SAL and dpending on the clear_os_buffer flags
+ *	clear the OS log buffer also
+ * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
+ *			clear_os_buffer 
+ *			prfunc		(print function)
+ * Outputs	: 	None
+ *
+ */
+void
+ia64_log_clear(int sal_info_type, int sal_sub_info_type, int clear_os_buffer, prfunc_t prfunc)
+{
+	if (ia64_sal_clear_state_info(sal_info_type, sal_sub_info_type))
+		prfunc("ia64_mca_log_get : Clearing processor log failed\n");
+
+	if (clear_os_buffer) {
+		sal_log_header_t	*log_buffer;
+		int			s;
+
+		IA64_LOG_LOCK(sal_info_type, sal_sub_info_type);
+
+		/* Get the process state information */
+		log_buffer = IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type);
+
+		memset(log_buffer, 0, sizeof(sal_log_header_t));
+
+		IA64_LOG_INDEX_DEC(sal_info_type, sal_sub_info_type);
+	
+		IA64_LOG_UNLOCK(sal_info_type, sal_sub_info_type);
+	}
+
+}
+
+/*
+ * ia64_log_processor_regs_print
+ *	Print the contents of the saved processor register(s) in the format
+ *		<reg_prefix>[<index>] <value>
+ *		
+ * Inputs	:	regs 		(Register save buffer)
+ *			reg_num 	(# of registers)
+ *			reg_class	(application/banked/control/bank1_general)
+ *			reg_prefix	(ar/br/cr/b1_gr)
+ * Outputs	: 	None
+ *
+ */
+void
+ia64_log_processor_regs_print(u64 	*regs, 
+			      int 	reg_num,
+			      char 	*reg_class,
+			      char 	*reg_prefix,
+			      prfunc_t	prfunc)
+{
+	int i;
+
+	prfunc("+%s Registers\n", reg_class);
+	for (i = 0; i < reg_num; i++)
+		prfunc("+ %s[%d] 0x%lx\n", reg_prefix, i, regs[i]);
+}
+
+static char *pal_mesi_state[] = {
+	"Invalid",
+	"Shared",
+	"Exclusive",
+	"Modified",
+	"Reserved1",
+	"Reserved2",
+	"Reserved3",
+	"Reserved4"
+};
+
+static char *pal_cache_op[] = {
+	"Unknown",
+	"Move in",
+	"Cast out",
+	"Coherency check",
+	"Internal",
+	"Instruction fetch",
+	"Implicit Writeback",
+	"Reserved"
+};
+
+/*
+ * ia64_log_cache_check_info_print
+ *	Display the machine check information related to cache error(s).
+ * Inputs	:	i		(Multiple errors are logged, i - index of logged error)
+ *			info		(Machine check info logged by the PAL and later 
+ *					 captured by the SAL)
+ *			target_addr	(Address which caused the cache error)
+ * Outputs	: 	None
+ */
+void 
+ia64_log_cache_check_info_print(int 			i, 
+				pal_cache_check_info_t 	info,
+				u64			target_addr,
+				prfunc_t		prfunc)
+{
+	prfunc("+ Cache check info[%d]\n+", i);
+	prfunc("  Level: L%d",info.level);
+	if (info.mv)
+		prfunc(" ,Mesi: %s",pal_mesi_state[info.mesi]);
+	prfunc(" ,Index: %d,", info.index);
+	if (info.ic)
+		prfunc(" ,Cache: Instruction");
+	if (info.dc)
+		prfunc(" ,Cache: Data");
+	if (info.tl)
+		prfunc(" ,Line: Tag");
+	if (info.dl)
+		prfunc(" ,Line: Data");
+	prfunc(" ,Operation: %s,", pal_cache_op[info.op]);
+	if (info.wv)
+		prfunc(" ,Way: %d,", info.way);
+	if (info.tv)
+		prfunc(" ,Target Addr: 0x%lx", target_addr);
+	if (info.mc)
+		prfunc(" ,MC: Corrected");
+	prfunc("\n");
+}
+
+/*
+ * ia64_log_tlb_check_info_print
+ *	Display the machine check information related to tlb error(s).
+ * Inputs	:	i		(Multiple errors are logged, i - index of logged error)
+ *			info		(Machine check info logged by the PAL and later 
+ *					 captured by the SAL)
+ * Outputs	: 	None
+ */
+
+void
+ia64_log_tlb_check_info_print(int 			i,
+			      pal_tlb_check_info_t	info,
+			      prfunc_t			prfunc)
+{
+	prfunc("+ TLB Check Info [%d]\n+", i);
+	if (info.itc)
+		prfunc("  Failure: Instruction Translation Cache");
+	if (info.dtc)
+		prfunc("  Failure: Data Translation Cache");
+	if (info.itr) {
+		prfunc("  Failure: Instruction Translation Register");
+		prfunc(" ,Slot: %d", info.tr_slot);
+	}
+	if (info.dtr) {
+		prfunc("  Failure: Data Translation Register");
+		prfunc(" ,Slot: %d", info.tr_slot);
+	}
+	if (info.mc)
+		prfunc(" ,MC: Corrected");
+	prfunc("\n");
+}
+
+/*
+ * ia64_log_bus_check_info_print
+ *	Display the machine check information related to bus error(s).
+ * Inputs	:	i		(Multiple errors are logged, i - index of logged error)
+ *			info		(Machine check info logged by the PAL and later 
+ *					 captured by the SAL)
+ *			req_addr	(Address of the requestor of the transaction)
+ *			resp_addr	(Address of the responder of the transaction)
+ *			target_addr	(Address where the data was to be delivered to  or
+ *					 obtained from)
+ * Outputs	: 	None
+ */
+void
+ia64_log_bus_check_info_print(int 			i,
+			      pal_bus_check_info_t	info,
+			      u64			req_addr,
+			      u64			resp_addr,
+			      u64			targ_addr,
+			      prfunc_t			prfunc)
+{
+	prfunc("+ BUS Check Info [%d]\n+", i);
+	prfunc(" Status Info: %d", info.bsi);
+	prfunc(" ,Severity: %d", info.sev);
+	prfunc(" ,Transaction Type: %d", info.type);
+	prfunc(" ,Transaction Size: %d", info.size);
+	if (info.cc)
+		prfunc(" ,Cache-cache-transfer");
+	if (info.ib)
+		prfunc(" ,Error: Internal");
+	if (info.eb)
+		prfunc(" ,Error: External");
+	if (info.mc)
+		prfunc(" ,MC: Corrected");
+	if (info.tv)
+		prfunc(" ,Target Address: 0x%lx", targ_addr);
+	if (info.rq)
+		prfunc(" ,Requestor Address: 0x%lx", req_addr);
+	if (info.tv)
+		prfunc(" ,Responder Address: 0x%lx", resp_addr);
+	prfunc("\n");
+}
+
+/*
+ * ia64_log_processor_info_print
+ *	Display the processor-specific information logged by PAL as a part
+ *	of MCA or INIT or CMC.
+ * Inputs 	:	lh	(Pointer of the sal log header which specifies the format
+ *				 of SAL state info as specified by the SAL spec).
+ * Outputs	: 	None
+ */
+void
+ia64_log_processor_info_print(sal_log_header_t *lh, prfunc_t prfunc)
+{
+	sal_log_processor_info_t	*slpi;
+	int				i;
+
+	if (!lh)
+		return;
+
+	if (lh->slh_log_type != SAL_SUB_INFO_TYPE_PROCESSOR)
+		return;
+
+#if defined(MCA_TEST)
+	slpi = &slpi_buf;
+#else
+	slpi = (sal_log_processor_info_t *)lh->slh_log_dev_spec_info;
+#endif /#if defined(MCA_TEST) */
+
+	if (!slpi) {
+		prfunc("No Processor Error Log found\n");
+		return;
+	}
+
+	/* Print branch register contents if valid */
+	if (slpi->slpi_valid.slpi_br) 
+		ia64_log_processor_regs_print(slpi->slpi_br, 8, "Branch", "br", prfunc);
+
+	/* Print control register contents if valid */
+	if (slpi->slpi_valid.slpi_cr) 
+		ia64_log_processor_regs_print(slpi->slpi_cr, 128, "Control", "cr", prfunc);
+
+	/* Print application register contents if valid */
+	if (slpi->slpi_valid.slpi_ar) 
+		ia64_log_processor_regs_print(slpi->slpi_br, 128, "Application", "ar", prfunc);
+
+	/* Print region register contents if valid */
+	if (slpi->slpi_valid.slpi_rr) 
+		ia64_log_processor_regs_print(slpi->slpi_rr, 8, "Region", "rr", prfunc);
+
+	/* Print floating-point register contents if valid */
+	if (slpi->slpi_valid.slpi_fr) 
+		ia64_log_processor_regs_print(slpi->slpi_fr, 128, "Floating-point", "fr", 
+					      prfunc);
+
+	/* Print bank1-gr NAT register contents if valid */
+	ia64_log_processor_regs_print(&slpi->slpi_bank1_nat_bits, 1, "NAT", "nat", prfunc);
+
+	/* Print bank 1 register contents if valid */
+	if (slpi->slpi_valid.slpi_bank1_gr) 
+		ia64_log_processor_regs_print(slpi->slpi_bank1_gr, 16, "Bank1-General", "gr",
+					      prfunc);
+
+	/* Print the cache check information if any*/
+	for (i = 0 ; i < MAX_CACHE_ERRORS; i++)
+		ia64_log_cache_check_info_print(i, 
+					slpi->slpi_cache_check_info[i].slpi_cache_check,
+					slpi->slpi_cache_check_info[i].slpi_target_address,
+						prfunc);
+	/* Print the tlb check information if any*/
+	for (i = 0 ; i < MAX_TLB_ERRORS; i++)
+		ia64_log_tlb_check_info_print(i,slpi->slpi_tlb_check_info[i], prfunc);
+
+	/* Print the bus check information if any*/
+	for (i = 0 ; i < MAX_BUS_ERRORS; i++)
+		ia64_log_bus_check_info_print(i, 
+					slpi->slpi_bus_check_info[i].slpi_bus_check,
+					slpi->slpi_bus_check_info[i].slpi_requestor_addr,
+					slpi->slpi_bus_check_info[i].slpi_responder_addr,
+					slpi->slpi_bus_check_info[i].slpi_target_addr,
+					      prfunc);
+
+}
+
+/*
+ * ia64_log_print
+ * 	Display the contents of the OS error log information
+ * Inputs 	:	info_type 	(SAL_INFO_TYPE_{MCA,INIT,CMC})
+ *			sub_info_type	(SAL_SUB_INFO_TYPE_{PROCESSOR,PLATFORM})
+ * Outputs	: 	None
+ */
+void
+ia64_log_print(int sal_info_type, int sal_sub_info_type, prfunc_t prfunc)
+{
+	char 	*info_type, *sub_info_type;
+
+	switch(sal_info_type) {
+	case SAL_INFO_TYPE_MCA:
+		info_type = "MCA";
+		break;
+	case SAL_INFO_TYPE_INIT:
+		info_type = "INIT";
+		break;
+	case SAL_INFO_TYPE_CMC:
+		info_type = "CMC";
+		break;
+	default:
+		info_type = "UNKNOWN";
+		break;
+	}
+
+	switch(sal_sub_info_type) {
+	case SAL_SUB_INFO_TYPE_PROCESSOR:
+		sub_info_type = "PROCESSOR";
+		break;
+	case SAL_SUB_INFO_TYPE_PLATFORM:
+		sub_info_type = "PLATFORM";
+		break;
+	default:
+		sub_info_type = "UNKNOWN";
+		break;
+	}
+
+	prfunc("+BEGIN HARDWARE ERROR STATE [%s %s]\n", info_type, sub_info_type);
+	if (sal_sub_info_type == SAL_SUB_INFO_TYPE_PROCESSOR)
+		ia64_log_processor_info_print(
+				      IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type),
+				      prfunc);
+	else
+		log_print_platform(IA64_LOG_CURR_BUFFER(sal_info_type, sal_sub_info_type),prfunc);
+	prfunc("+END HARDWARE ERROR STATE [%s %s]\n", info_type, sub_info_type);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/mca_asm.S linux/arch/ia64/kernel/mca_asm.S
--- v2.3.42/linux/arch/ia64/kernel/mca_asm.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/mca_asm.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,621 @@
+#include <asm/processor.h>
+#include <asm/mcaasm.h>
+#include <asm/page.h>
+#include <asm/mca.h>
+	
+	.psr abi64
+	.psr lsb
+	.lsb
+
+/*
+ *	SAL_TO_OS_MCA_HANDOFF_STATE
+ *		1. GR1 = OS GP
+ *		2. GR8 = PAL_PROC physical address
+ *		3. GR9 = SAL_PROC physical address
+ *		4. GR10 = SAL GP (physical)
+ *		5. GR11 = Rendez state
+ *		6. GR12 = Return address to location within SAL_CHECK
+ */
+#define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp)		\
+        movl	_tmp=ia64_sal_to_os_handoff_state;;	\
+        st8	[_tmp]=r1,0x08;;			\
+        st8	[_tmp]=r8,0x08;;			\
+        st8	[_tmp]=r9,0x08;;			\
+        st8	[_tmp]=r10,0x08;;			\
+        st8	[_tmp]=r11,0x08;;			\
+        st8	[_tmp]=r12,0x08;;
+
+/*
+ *	OS_MCA_TO_SAL_HANDOFF_STATE
+ *		1. GR8 = OS_MCA status
+ *		2. GR9 = SAL GP (physical)
+ *		3. GR22 = New min state save area pointer
+ */	
+#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp)	\
+        movl	_tmp=ia64_os_to_sal_handoff_state;;	\
+	DATA_VA_TO_PA(_tmp);;				\
+        ld8	r8=[_tmp],0x08;;			\
+        ld8	r9=[_tmp],0x08;;			\
+        ld8	r22=[_tmp],0x08;;
+
+/*
+ *	BRANCH
+ *		Jump to the instruction referenced by
+ *	"to_label".
+ *		Branch is taken only if the predicate
+ *	register "p" is true.
+ *		"ip" is the address of the instruction
+ *	located at "from_label".
+ *		"temp" is a scratch register like r2
+ *		"adjust" needed for HP compiler. 
+ *	A screwup somewhere with constant arithmetic.
+ */	
+#define BRANCH(to_label, temp, p, adjust)		\
+100:	(p)	mov		temp=ip;		\
+		;;					\
+	(p)	adds		temp=to_label-100b,temp;\
+	(p)	adds		temp=adjust,temp;	\
+	(p)	mov		b1=temp	;		\
+	(p)	br		b1	
+
+	.global ia64_os_mca_dispatch
+	.global ia64_os_mca_dispatch_end
+	.global ia64_sal_to_os_handoff_state
+	.global	ia64_os_to_sal_handoff_state
+	.global	ia64_os_mca_ucmc_handler
+	.global	ia64_mca_proc_state_dump
+	.global ia64_mca_proc_state_restore
+	.global	ia64_mca_stack
+	.global	ia64_mca_stackframe
+	.global	ia64_mca_bspstore
+			
+	.text
+	.align 16
+	
+ia64_os_mca_dispatch:
+
+#if defined(MCA_TEST)
+	// Pretend that we are in interrupt context
+	mov		r2=psr
+	dep		r2=0, r2, PSR_IC, 2;
+	mov		psr.l = r2
+#endif	/* #if defined(MCA_TEST) */
+
+	// Save the SAL to OS MCA handoff state as defined
+	// by SAL SPEC 2.5
+	// NOTE : The order in which the state gets saved
+	//	  is dependent on the way the C-structure
+	//	  for ia64_mca_sal_to_os_state_t has been
+	//	  defined in include/asm/mca.h
+	SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
+
+	// LOG PROCESSOR STATE INFO FROM HERE ON..
+	;;
+begin_os_mca_dump:
+	BRANCH(ia64_os_mca_proc_state_dump, r2, p0, 0x0)
+        ;;
+ia64_os_mca_done_dump:
+
+	// Setup new stack frame for OS_MCA handling 
+        movl        r2=ia64_mca_bspstore		// local bspstore area location in r2
+        movl        r3=ia64_mca_stackframe		// save stack frame to memory in r3
+        rse_switch_context(r6,r3,r2);;                  // RSC management in this new context
+        movl        r12=ia64_mca_stack;;
+
+	// Enter virtual mode from physical mode
+	VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
+ia64_os_mca_virtual_begin:
+
+	// call our handler
+        movl		r2=ia64_mca_ucmc_handler;;
+        mov		b6=r2;;
+        br.call.sptk.few	b0=b6
+        ;;
+
+	// Revert back to physical mode before going back to SAL
+	PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
+ia64_os_mca_virtual_end:
+
+#if defined(MCA_TEST)
+	// Pretend that we are in interrupt context
+	mov		r2=psr
+	dep		r2=0, r2, PSR_IC, 2;
+	mov		psr.l = r2
+#endif	/* #if defined(MCA_TEST) */
+
+	// restore the original stack frame here
+        movl    r2=ia64_mca_stackframe               // restore stack frame from memory at r2
+	;;
+	DATA_VA_TO_PA(r2)
+        movl    r4=IA64_PSR_MC
+	;;
+        rse_return_context(r4,r3,r2)                 // switch from interrupt context for RSE
+	
+	// let us restore all the registers from our PSI structure
+        mov		r8=gp
+	;;
+begin_os_mca_restore:
+	BRANCH(ia64_os_mca_proc_state_restore, r2, p0, 0x0)
+        ;;
+
+ia64_os_mca_done_restore:
+	;;
+#ifdef SOFTSDV
+	VIRTUAL_MODE_ENTER(r2,r3, vmode_enter, r4)
+vmode_enter:	
+	br.ret.sptk.few		b0	
+#else
+	// branch back to SALE_CHECK
+	OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2)
+        ld8		r3=[r2];;              
+        mov		b0=r3                       // SAL_CHECK return address
+        br		b0
+        ;;
+#endif /* #ifdef SOFTSDV */
+ia64_os_mca_dispatch_end:	
+//EndMain//////////////////////////////////////////////////////////////////////
+
+
+//++
+// Name:
+//      ia64_os_mca_proc_state_dump()
+// 
+// Stub Description:
+//
+//       This stub dumps the processor state during MCHK to a data area
+//
+//--
+
+ia64_os_mca_proc_state_dump:
+// Get and save GR0-31 from Proc. Min. State Save Area to SAL PSI
+        movl		r2=ia64_mca_proc_state_dump;;           // Os state dump area
+
+// save ar.NaT 
+        mov		r5=ar.unat                  // ar.unat
+
+// save banked GRs 16-31 along with NaT bits
+        bsw.1;;
+        st8.spill	[r2]=r16,8;;
+        st8.spill	[r2]=r17,8;;
+        st8.spill	[r2]=r18,8;;
+        st8.spill	[r2]=r19,8;;
+        st8.spill	[r2]=r20,8;;
+        st8.spill	[r2]=r21,8;;
+        st8.spill	[r2]=r22,8;;
+        st8.spill	[r2]=r23,8;;
+        st8.spill	[r2]=r24,8;;
+        st8.spill	[r2]=r25,8;;
+        st8.spill	[r2]=r26,8;;
+        st8.spill	[r2]=r27,8;;
+        st8.spill	[r2]=r28,8;;
+        st8.spill	[r2]=r29,8;;
+        st8.spill	[r2]=r30,8;;
+        st8.spill	[r2]=r31,8;;
+
+        mov		r4=ar.unat;;
+        st8		[r2]=r4,8                // save User NaT bits for r16-r31
+        mov		ar.unat=r5                  // restore original unat
+        bsw.0;;
+
+//save BRs
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2                // duplicate r2 in r4
+
+        mov		r3=b0
+        mov		r5=b1
+        mov		r7=b2;;
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;  
+
+        mov		r3=b3
+        mov		r5=b4
+        mov		r7=b5;;
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;  
+
+        mov		r3=b6
+        mov		r5=b7;;
+        st8		[r2]=r3,2*8
+        st8		[r4]=r5,2*8;;
+
+cSaveCRs:
+// save CRs
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2                // duplicate r2 in r4
+
+        mov		r3=cr0                      // cr.dcr
+        mov		r5=cr1                      // cr.itm
+        mov		r7=cr2;;                    // cr.iva
+
+        st8		[r2]=r3,8*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;            // 48 byte rements
+
+        mov		r3=cr8;;                    // cr.pta
+        st8		[r2]=r3,8*8;;            // 64 byte rements
+
+// if PSR.ic=0, reading interruption registers causes an illegal operation fault
+        mov		r3=psr;;
+        tbit.nz.unc	p2,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
+(p2)    st8		[r2]=r0,9*8+160             // increment by 168 byte inc.
+begin_skip_intr_regs:	
+	BRANCH(SkipIntrRegs,  r9, p2, 0x0)
+	;; 
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2                // duplicate r2 in r6
+        
+        mov		r3=cr16                     // cr.ipsr
+        mov		r5=cr17                     // cr.isr
+        mov		r7=r0;;                     // cr.ida => cr18
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;                                      
+
+        mov		r3=cr19                     // cr.iip
+        mov		r5=cr20                     // cr.idtr
+        mov		r7=cr21;;                   // cr.iitr
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;                                      
+
+        mov		r3=cr22                     // cr.iipa
+        mov		r5=cr23                     // cr.ifs
+        mov		r7=cr24;;                   // cr.iim
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;    
+                                          
+        mov		r3=cr25;;                   // cr.iha
+        st8		[r2]=r3,160;;               // 160 byte rement
+
+SkipIntrRegs:
+        st8		[r2]=r0,168                 // another 168 byte .
+
+        mov		r3=cr66;;                   // cr.lid
+        st8		[r2]=r3,40                  // 40 byte rement
+
+        mov		r3=cr71;;                   // cr.ivr
+        st8		[r2]=r3,8
+
+        mov		r3=cr72;;                   // cr.tpr
+        st8		[r2]=r3,24                  // 24 byte increment
+    
+        mov		r3=r0;;                     // cr.eoi => cr75
+        st8		[r2]=r3,168                 // 168 byte inc.
+    
+        mov		r3=r0;;                     // cr.irr0 => cr96
+        st8		[r2]=r3,16               // 16 byte inc.
+
+        mov		r3=r0;;                     // cr.irr1 => cr98
+        st8		[r2]=r3,16               // 16 byte inc.
+
+        mov		r3=r0;;                     // cr.irr2 => cr100
+        st8		[r2]=r3,16               // 16 byte inc
+
+        mov		r3=r0;;                     // cr.irr3 => cr100
+        st8		[r2]=r3,16               // 16b inc.
+
+        mov		r3=r0;;                     // cr.itv => cr114
+        st8		[r2]=r3,16               // 16 byte inc.
+
+        mov		r3=r0;;                     // cr.pmv => cr116
+        st8		[r2]=r3,8
+
+        mov		r3=r0;;                     // cr.lrr0 => cr117
+        st8		[r2]=r3,8
+
+        mov		r3=r0;;                     // cr.lrr1 => cr118
+        st8		[r2]=r3,8
+
+        mov		r3=r0;;                     // cr.cmcv => cr119
+        st8		[r2]=r3,8*10;;
+
+cSaveARs:
+// save ARs
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2                // duplicate r2 in r6
+
+        mov		r3=ar0                      // ar.kro
+        mov		r5=ar1                      // ar.kr1
+        mov		r7=ar2;;                    // ar.kr2
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;
+
+        mov		r3=ar3                      // ar.kr3                               
+        mov		r5=ar4                      // ar.kr4
+        mov		r7=ar5;;                    // ar.kr5
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;
+
+        mov		r3=ar6                      // ar.kr6
+        mov		r5=ar7                      // ar.kr7
+        mov		r7=r0;;                     // ar.kr8
+        st8		[r2]=r3,10*8
+        st8		[r4]=r5,10*8
+        st8		[r6]=r7,10*8;;           // rement by 72 bytes
+
+        mov		r3=ar16                     // ar.rsc
+	mov		ar16=r0			    // put RSE in enforced lazy mode
+        mov		r5=ar17                     // ar.bsp
+        mov		r7=ar18;;                   // ar.bspstore
+        st8		[r2]=r3,3*8
+        st8		[r4]=r5,3*8
+        st8		[r6]=r7,3*8;;
+
+        mov		r3=ar19;;                   // ar.rnat
+        st8		[r2]=r3,8*13             // increment by 13x8 bytes
+
+        mov		r3=ar32;;                   // ar.ccv
+        st8		[r2]=r3,8*4
+
+        mov		r3=ar36;;                   // ar.unat
+        st8		[r2]=r3,8*4
+
+        mov		r3=ar40;;                   // ar.fpsr
+        st8		[r2]=r3,8*4
+
+        mov		r3=ar44;;                   // ar.itc
+        st8		[r2]=r3,160                 // 160
+
+        mov		r3=ar64;;                   // ar.pfs
+        st8		[r2]=r3,8
+
+        mov		r3=ar65;;                   // ar.lc
+        st8		[r2]=r3,8
+
+        mov		r3=ar66;;                   // ar.ec
+        st8		[r2]=r3
+        add		r2=8*62,r2               //padding
+    
+// save RRs
+        mov		ar.lc=0x08-1
+        movl		r4=0x00;;
+
+cStRR:
+        mov		r3=rr[r4];;
+        st8		[r2]=r3,8
+        add		r4=1,r4
+        br.cloop.sptk.few	cStRR
+        ;;
+end_os_mca_dump:
+	BRANCH(ia64_os_mca_done_dump, r2, p0, -0x10)
+        ;;
+
+//EndStub//////////////////////////////////////////////////////////////////////
+
+
+//++
+// Name:
+//       ia64_os_mca_proc_state_restore()
+// 
+// Stub Description:
+//
+//       This is a stub to restore the saved processor state during MCHK
+//
+//--
+
+ia64_os_mca_proc_state_restore:
+
+// Restore bank1 GR16-31 
+	movl		r2=ia64_mca_proc_state_dump	// Convert virtual address
+	;;						// of OS state dump area
+	DATA_VA_TO_PA(r2)				// to physical address
+	;;
+restore_GRs:                                    // restore bank-1 GRs 16-31
+        bsw.1;;
+        add		r3=16*8,r2;;                // to get to NaT of GR 16-31
+        ld8		r3=[r3];;
+        mov		ar.unat=r3;;                // first restore NaT
+
+        ld8.fill	r16=[r2],8;;
+        ld8.fill	r17=[r2],8;;
+        ld8.fill	r18=[r2],8;;
+        ld8.fill	r19=[r2],8;;
+        ld8.fill	r20=[r2],8;;
+        ld8.fill	r21=[r2],8;;
+        ld8.fill	r22=[r2],8;;
+        ld8.fill	r23=[r2],8;;
+        ld8.fill	r24=[r2],8;;
+        ld8.fill	r25=[r2],8;;
+        ld8.fill	r26=[r2],8;;
+        ld8.fill	r27=[r2],8;;
+        ld8.fill	r28=[r2],8;;
+        ld8.fill	r29=[r2],8;;
+        ld8.fill	r30=[r2],8;;
+        ld8.fill	r31=[r2],8;;
+
+        ld8		r3=[r2],8;;              // increment to skip NaT
+        bsw.0;;
+
+restore_BRs:
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2;;              // duplicate r2 in r4
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;  
+        mov		b0=r3
+        mov		b1=r5
+        mov		b2=r7;;
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;  
+        mov		b3=r3
+        mov		b4=r5
+        mov		b5=r7;;
+
+        ld8		r3=[r2],2*8
+        ld8		r5=[r4],2*8;;  
+        mov		b6=r3
+        mov		b7=r5;;
+
+restore_CRs:
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2;;              // duplicate r2 in r4
+
+        ld8		r3=[r2],8*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;            // 48 byte increments
+        mov		cr0=r3                      // cr.dcr
+        mov		cr1=r5                      // cr.itm
+        mov		cr2=r7;;                    // cr.iva
+
+        ld8		r3=[r2],8*8;;            // 64 byte increments
+//      mov		cr8=r3                      // cr.pta
+
+
+// if PSR.ic=1, reading interruption registers causes an illegal operation fault
+        mov		r3=psr;;
+        tbit.nz.unc	p2,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
+(p2)    st8		[r2]=r0,9*8+160             // increment by 160 byte inc.
+
+begin_rskip_intr_regs:	
+	BRANCH(rSkipIntrRegs, r9, p2, 0x0)
+	;; 
+
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2;;              // duplicate r2 in r4
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;
+        mov		cr16=r3                     // cr.ipsr
+        mov		cr17=r5                     // cr.isr is read only
+//      mov		cr18=r7;;                   // cr.ida
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;
+        mov		cr19=r3                     // cr.iip
+        mov		cr20=r5                     // cr.idtr
+        mov		cr21=r7;;                   // cr.iitr
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;
+        mov		cr22=r3                     // cr.iipa
+        mov		cr23=r5                     // cr.ifs
+        mov		cr24=r7                     // cr.iim
+
+        ld8		r3=[r2],160;;               // 160 byte increment
+        mov		cr25=r3                     // cr.iha 
+
+rSkipIntrRegs:
+        ld8		r3=[r2],168;;               // another 168 byte inc.
+
+        ld8		r3=[r2],40;;                // 40 byte increment
+        mov		cr66=r3                     // cr.lid
+
+        ld8		r3=[r2],8;;
+//      mov		cr71=r3                     // cr.ivr is read only
+        ld8		r3=[r2],24;;                // 24 byte increment
+        mov		cr72=r3                     // cr.tpr
+   
+        ld8		r3=[r2],168;;               // 168 byte inc.
+//      mov		cr75=r3                     // cr.eoi
+   
+        ld8		r3=[r2],16;;             // 16 byte inc.
+//      mov		cr96=r3                     // cr.irr0 is read only
+
+        ld8		r3=[r2],16;;             // 16 byte inc.
+//      mov		cr98=r3                     // cr.irr1 is read only
+
+        ld8		r3=[r2],16;;             // 16 byte inc
+//      mov		cr100=r3                    // cr.irr2 is read only
+
+        ld8		r3=[r2],16;;             // 16b inc.
+//      mov		cr102=r3                    // cr.irr3 is read only
+
+        ld8		r3=[r2],16;;             // 16 byte inc.
+//      mov		cr114=r3                    // cr.itv
+
+        ld8		r3=[r2],8;;
+//      mov		cr116=r3                    // cr.pmv
+        ld8		r3=[r2],8;;
+//      mov		cr117=r3                    // cr.lrr0
+        ld8		r3=[r2],8;;
+//      mov		cr118=r3                    // cr.lrr1
+        ld8		r3=[r2],8*10;;
+//      mov		cr119=r3                    // cr.cmcv
+
+restore_ARs:
+        add		r4=8,r2                  // duplicate r2 in r4
+        add		r6=2*8,r2;;              // duplicate r2 in r4
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;
+        mov		ar0=r3                      // ar.kro
+        mov		ar1=r5                      // ar.kr1
+        mov		ar2=r7;;                    // ar.kr2
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;
+        mov		ar3=r3                      // ar.kr3                               
+        mov		ar4=r5                      // ar.kr4
+        mov		ar5=r7;;                    // ar.kr5
+
+        ld8		r3=[r2],10*8
+        ld8		r5=[r4],10*8
+        ld8		r7=[r6],10*8;;
+        mov		ar6=r3                      // ar.kr6
+        mov		ar7=r5                      // ar.kr7
+//      mov		ar8=r6                      // ar.kr8
+        ;;
+
+        ld8		r3=[r2],3*8
+        ld8		r5=[r4],3*8
+        ld8		r7=[r6],3*8;;
+//      mov		ar16=r3                     // ar.rsc
+//      mov		ar17=r5                     // ar.bsp is read only
+	mov		ar16=r0			    // make sure that RSE is in enforced lazy mode
+        mov		ar18=r7;;                   // ar.bspstore
+
+        ld8		r9=[r2],8*13;;
+        mov		ar19=r9                     // ar.rnat
+
+	mov		ar16=r3			    // ar.rsc
+        ld8		r3=[r2],8*4;;
+        mov		ar32=r3                     // ar.ccv
+
+        ld8		r3=[r2],8*4;;
+        mov		ar36=r3                     // ar.unat
+
+        ld8		r3=[r2],8*4;;
+        mov		ar40=r3                     // ar.fpsr
+
+        ld8		r3=[r2],160;;               // 160
+//      mov		ar44=r3                     // ar.itc
+
+        ld8		r3=[r2],8;;
+        mov		ar64=r3                     // ar.pfs
+
+        ld8		r3=[r2],8;;
+        mov		ar65=r3                     // ar.lc
+
+        ld8		r3=[r2];;
+        mov		ar66=r3                     // ar.ec
+        add		r2=8*62,r2;;             // padding 
+    
+restore_RRs:
+        mov		r5=ar.lc
+        mov		ar.lc=0x08-1
+        movl		r4=0x00
+cStRRr:
+        ld8		r3=[r2],8;;
+//      mov		rr[r4]=r3                   // what are its access previledges?
+        add		r4=1,r4
+        br.cloop.sptk.few	cStRRr
+        ;;
+        mov		ar.lc=r5
+	;;
+end_os_mca_restore:
+	BRANCH(ia64_os_mca_done_restore, r2, p0, -0x20)
+	;; 
+//EndStub//////////////////////////////////////////////////////////////////////
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/pal.S linux/arch/ia64/kernel/pal.S
--- v2.3.42/linux/arch/ia64/kernel/pal.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/pal.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,119 @@
+/*
+ * PAL Firmware support
+ * IA-64 Processor Programmers Reference Vol 2
+ *
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 David Mosberger <davidm@hpl.hp.com>
+ */
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.data
+pal_entry_point:
+	data8 ia64_pal_default_handler
+	.text
+
+/*
+ * Set the PAL entry point address.  This could be written in C code, but we do it here
+ * to keep it all in one module (besides, it's so trivial that it's
+ * not a big deal).
+ *
+ * in0		Address of the PAL entry point (text address, NOT a function descriptor).
+ */
+	.align 16
+	.global ia64_pal_handler_init
+	.proc ia64_pal_handler_init
+ia64_pal_handler_init:
+	alloc r3=ar.pfs,1,0,0,0
+	movl r2=pal_entry_point
+	;;
+	st8 [r2]=in0
+	br.ret.sptk.few rp
+	
+	.endp ia64_pal_handler_init	
+
+/*
+ * Default PAL call handler.  This needs to be coded in assembly because it uses
+ * the static calling convention, i.e., the RSE may not be used and calls are
+ * done via "br.cond" (not "br.call").
+ */
+	.align 16
+	.global ia64_pal_default_handler
+	.proc ia64_pal_default_handler
+ia64_pal_default_handler:
+	mov r8=-1
+	br.cond.sptk.few rp
+
+/*
+ * Make a PAL call using the static calling convention.
+ *
+ * in0         Pointer to struct ia64_pal_retval
+ * in1         Index of PAL service
+ * in2 - in4   Remaning PAL arguments
+ *
+ */
+
+#ifdef __GCC_MULTIREG_RETVALS__
+# define arg0	in0
+# define arg1	in1
+# define arg2	in2
+# define arg3	in3
+# define arg4	in4
+#else
+# define arg0	in1
+# define arg1	in2
+# define arg2	in3
+# define arg3	in4
+# define arg4	in5
+#endif
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 16
+	.global	ia64_pal_call_static
+	.proc ia64_pal_call_static
+ia64_pal_call_static:
+	alloc	loc0 = ar.pfs,6,90,0,0
+	movl	loc2 = pal_entry_point
+1:	{
+	  mov	r28 = arg0
+	  mov	r29 = arg1
+	  mov	r8 = ip
+	}
+	;;
+	ld8	loc2 = [loc2]		// loc2 <- entry point
+	mov	r30 = arg2
+	mov	r31 = arg3
+	;;
+	mov	loc3 = psr
+	mov	loc1 = rp
+	adds	r8 = .ret0-1b,r8
+	;; 
+	rsm	psr.i
+	mov	b7 = loc2
+	mov	rp = r8
+	;; 
+	br.cond.sptk.few b7
+.ret0:	mov	psr.l = loc3
+#ifndef __GCC_MULTIREG_RETVALS__
+	st8	[in0] = r8, 8
+	;;
+	st8	[in0] = r9, 8 
+	;;
+	st8	[in0] = r10, 8
+	;;
+	st8	[in0] = r11, 8
+#endif
+	mov	ar.pfs = loc0
+	mov	rp = loc1
+	;;
+	srlz.d				// seralize restoration of psr.l
+	br.ret.sptk.few	b0
+	.endp ia64_pal_call_static
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/pci-dma.c linux/arch/ia64/kernel/pci-dma.c
--- v2.3.42/linux/arch/ia64/kernel/pci-dma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/pci-dma.c	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,56 @@
+/*
+ * Dynamic DMA mapping support.
+ *
+ * This implementation is for IA-64 platforms that do not support
+ * I/O TLBs (aka DMA address translation hardware).
+ *
+ * XXX This doesn't do the right thing yet.  It appears we would have
+ * to add additional zones so we can implement the various address
+ * mask constraints that we might encounter.  A zone for memory < 32
+ * bits is obviously necessary...
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+
+/* Pure 2^n version of get_order */
+extern __inline__ unsigned long
+get_order (unsigned long size)
+{
+	unsigned long order = ia64_fls(size);
+
+	printk ("get_order: size=%lu, order=%lu\n", size, order);
+
+	if (order > PAGE_SHIFT)
+		order -= PAGE_SHIFT;
+	else
+		order = 0;
+	return order;
+}
+
+void *
+pci_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+	if (!hwdev || hwdev->dma_mask != 0xffffffff)
+		gfp |= GFP_DMA;
+	ret = (void *)__get_free_pages(gfp, get_order(size));
+
+	if (ret) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	return ret;
+}
+
+void
+pci_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages((unsigned long) vaddr, get_order(size));
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/pci.c linux/arch/ia64/kernel/pci.c
--- v2.3.42/linux/arch/ia64/kernel/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/pci.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,239 @@
+/*
+ * pci.c - Low-Level PCI Access in IA64
+ * 
+ * Derived from bios32.c of i386 tree.
+ *
+ */
+
+#include <linux/config.h>
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+
+#include <asm/machvec.h>
+#include <asm/page.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <asm/sal.h>
+
+
+#ifdef CONFIG_SMP
+# include <asm/smp.h>
+#endif
+#include <asm/irq.h>
+
+
+#undef DEBUG
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/*
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
+ */
+
+spinlock_t pci_lock = SPIN_LOCK_UNLOCKED;
+
+struct pci_fixup pcibios_fixups[] = { { 0 } };
+
+#define PCI_NO_CHECKS		0x400
+#define PCI_NO_PEER_FIXUP	0x800
+
+static unsigned int pci_probe = PCI_NO_CHECKS;
+
+/* Macro to build a PCI configuration address to be passed as a parameter to SAL. */
+
+#define PCI_CONFIG_ADDRESS(dev, where) (((u64) dev->bus->number << 16) | ((u64) (dev->devfn & 0xff) << 8) | (where & 0xff))
+
+static int 
+pci_conf_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	s64 status;
+	u64 lval;
+
+	status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS(dev, where), 1, &lval);
+	*value = lval;
+	return status;
+}
+
+static int 
+pci_conf_read_config_word(struct pci_dev *dev, int where, u16 *value)
+{
+	s64 status;
+	u64 lval;
+
+	status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS(dev, where), 2, &lval);
+	*value = lval;
+	return status;
+}
+
+static int 
+pci_conf_read_config_dword(struct pci_dev *dev, int where, u32 *value)
+{
+	s64 status;
+	u64 lval;
+
+	status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS(dev, where), 4, &lval);
+	*value = lval;
+	return status;
+}
+
+static int 
+pci_conf_write_config_byte (struct pci_dev *dev, int where, u8 value)
+{
+	return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 1, value);
+}
+
+static int 
+pci_conf_write_config_word (struct pci_dev *dev, int where, u16 value)
+{
+	return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 2, value);
+}
+
+static int 
+pci_conf_write_config_dword (struct pci_dev *dev, int where, u32 value)
+{
+	return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 4, value);
+}
+
+
+static struct pci_ops pci_conf = {
+      pci_conf_read_config_byte,
+      pci_conf_read_config_word,
+      pci_conf_read_config_dword,
+      pci_conf_write_config_byte,
+      pci_conf_write_config_word,
+      pci_conf_write_config_dword
+};
+
+/*
+ * Try to find PCI BIOS.  This will always work for IA64.
+ */
+
+static struct pci_ops * __init
+pci_find_bios(void)
+{
+	return &pci_conf;
+}
+
+/*
+ * Initialization. Uses the SAL interface
+ */
+
+#define PCI_BUSSES_TO_SCAN 2	/* On "real" ;) hardware this will be 255 */
+
+void __init 
+pcibios_init(void)
+{
+	struct pci_ops *ops = NULL;
+	int i;
+
+	if ((ops = pci_find_bios()) == NULL) {
+		printk("PCI: No PCI bus detected\n");
+		return;
+	}
+
+	printk("PCI: Probing PCI hardware\n");
+	for (i = 0; i < PCI_BUSSES_TO_SCAN; i++) 
+		pci_scan_bus(i, ops, NULL);
+	platform_pci_fixup();
+	return;
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+
+void __init
+pcibios_fixup_bus(struct pci_bus *b)
+{
+	return;
+}
+
+int
+pci_assign_resource (struct pci_dev *dev, int i)
+{
+	printk("pci_assign_resource: not implemented!\n");
+	return -ENODEV;
+}
+
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			struct resource *res, int resource)
+{
+        unsigned long where, size;
+        u32 reg;
+
+        where = PCI_BASE_ADDRESS_0 + (resource * 4);
+        size = res->end - res->start;
+        pci_read_config_dword(dev, where, &reg);
+        reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+        pci_write_config_dword(dev, where, reg);
+
+	/* ??? FIXME -- record old value for shutdown.  */
+}
+
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+
+	/* ??? FIXME -- record old value for shutdown.  */
+}
+
+void __init
+pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
+{
+	ranges->io_start -= bus->resource[0]->start;
+	ranges->io_end -= bus->resource[0]->start;
+	ranges->mem_start -= bus->resource[1]->start;
+	ranges->mem_end -= bus->resource[1]->start;
+}
+
+int __init
+pcibios_enable_device (struct pci_dev *dev)
+{
+	/* Not needed, since we enable all devices at startup.  */
+	return 0;
+}
+
+/*
+ * PCI BIOS setup, always defaults to SAL interface
+ */
+
+char * __init 
+pcibios_setup(char *str)
+{
+	pci_probe =  PCI_NO_CHECKS;
+	return NULL;
+}
+
+void
+pcibios_align_resource (void *data, struct resource *res, unsigned long size)
+{
+}
+
+#if 0 /*def CONFIG_PROC_FS*/
+/*
+ * This is an ugly hack to get a (weak) unresolved reference to something that is
+ * in drivers/pci/proc.c.  Without this, the file does not get linked in at all
+ * (I suspect the reason this isn't needed on Linux/x86 is that most people compile
+ * with module support, in which case the EXPORT_SYMBOL() stuff will ensure the
+ * code gets linked in.  Sigh...  --davidm 99/12/20.
+ */
+asm ("data8 proc_bus_pci_add");
+#endif
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/perfmon.c linux/arch/ia64/kernel/perfmon.c
--- v2.3.42/linux/arch/ia64/kernel/perfmon.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/perfmon.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,227 @@
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+
+#include <asm/errno.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_PERFMON
+
+#define MAX_PERF_COUNTER	4	/* true for Itanium, at least */
+#define WRITE_PMCS_AND_START	0xa0
+#define WRITE_PMCS		0xa1
+#define READ_PMDS		0xa2
+#define STOP_PMCS		0xa3
+#define IA64_COUNTER_MASK	0xffffffffffffff6f
+#define PERF_OVFL_VAL		0xffffffff
+
+struct perfmon_counter {
+        unsigned long data;
+        int counter_num;
+};
+
+unsigned long pmds[MAX_PERF_COUNTER];
+struct task_struct *perf_owner;
+
+/*
+ * We set dcr.pp, psr.pp, and the appropriate pmc control values with
+ * this.  Notice that we go about modifying _each_ task's pt_regs to
+ * set cr_ipsr.pp.  This will start counting when "current" does an
+ * _rfi_. Also, since each task's cr_ipsr.pp, and cr_ipsr is inherited
+ * across forks, we do _not_ need additional code on context
+ * switches. On stopping of the counters we dont _need_ to go about
+ * changing every task's cr_ipsr back to where it wuz, because we can
+ * just set pmc[0]=1. But we do it anyways becuase we will probably
+ * add thread specific accounting later.
+ *
+ * The obvious problem with this is that on SMP systems, it is a bit
+ * of work (when someone wants to do it) - it would be easier if we
+ * just added code to the context-switch path.  I think we would need
+ * to lock the run queue to ensure no context switches, send an IPI to
+ * each processor, and in that IPI handler, just modify the psr bit of
+ * only the _current_ thread, since we have modified the psr bit
+ * correctly in the kernel stack for every process which is not
+ * running.  Might crash on SMP systems without the
+ * lock_kernel(). Hence the lock..
+ */
+asmlinkage unsigned long
+sys_perfmonctl (int cmd1, int cmd2, void *ptr)
+{
+        struct perfmon_counter tmp, *cptr = ptr;
+        unsigned long pmd, cnum, dcr, flags;
+        struct task_struct *p;
+        struct pt_regs *regs;
+        struct perf_counter;
+        int i;
+
+        switch (cmd1) {
+	      case WRITE_PMCS:           /* Writes to PMC's and clears PMDs */
+	      case WRITE_PMCS_AND_START: /* Also starts counting */
+
+		if (!access_ok(VERIFY_READ, cptr, sizeof(struct perf_counter)*cmd2))
+			return -EFAULT;
+
+		if (cmd2 >= MAX_PERF_COUNTER)
+			return -EFAULT;
+
+		if (perf_owner && perf_owner != current)
+			return -EBUSY;
+		perf_owner = current;
+
+		for (i = 0; i < cmd2; i++, cptr++) {
+			copy_from_user(&tmp, cptr, sizeof(tmp));
+			/* XXX need to check validity of counter_num and perhaps data!! */
+			ia64_set_pmc(tmp.counter_num, tmp.data);
+			ia64_set_pmd(tmp.counter_num, 0);
+			pmds[tmp.counter_num - 4] = 0;
+		}
+
+		if (cmd1 == WRITE_PMCS_AND_START) {
+			local_irq_save(flags);
+			dcr = ia64_get_dcr();
+			dcr |= IA64_DCR_PP;
+			ia64_set_dcr(dcr);
+			local_irq_restore(flags);
+
+			/*
+			 * This is a no can do.  It obviously wouldn't
+			 * work on SMP where another process may not
+			 * be blocked at all.
+			 *
+			 * Perhaps we need a global predicate in the
+			 * leave_kernel path to control if pp should
+			 * be on or off?
+			 */
+			lock_kernel();
+			for_each_task(p) {
+				regs = (struct pt_regs *) (((char *)p) + IA64_STK_OFFSET) - 1;
+				ia64_psr(regs)->pp = 1;
+			}
+			unlock_kernel();
+			ia64_set_pmc(0, 0);
+		}
+                break;
+
+	      case READ_PMDS:
+		if (cmd2 >= MAX_PERF_COUNTER)
+			return -EFAULT;
+		if (!access_ok(VERIFY_WRITE, cptr, sizeof(struct perf_counter)*cmd2))
+			return -EFAULT;
+		local_irq_save(flags);
+		/* XXX this looks wrong */
+		__asm__ __volatile__("rsm psr.pp\n");
+		dcr = ia64_get_dcr();
+		dcr &= ~IA64_DCR_PP;
+		ia64_set_dcr(dcr);
+		local_irq_restore(flags);
+
+		/*
+		 * We cannot touch pmc[0] to stop counting here, as
+		 * that particular instruction might cause an overflow
+		 * and the mask in pmc[0] might get lost. I'm not very
+		 * sure of the hardware behavior here. So we stop
+		 * counting by psr.pp = 0. And we reset dcr.pp to
+		 * prevent an interrupt from mucking up psr.pp in the
+		 * meanwhile. Perfmon interrupts are pended, hence the
+		 * above code should be ok if one of the above
+		 * instructions cause overflows. Is this ok?  When I
+		 * muck with dcr, is the cli/sti needed??
+		 */
+		for (i = 0, cnum = 4; i < MAX_PERF_COUNTER; i++, cnum++, cptr++) {
+			pmd = pmds[i] + (ia64_get_pmd(cnum) & PERF_OVFL_VAL);
+			put_user(pmd, &cptr->data);
+		}
+		local_irq_save(flags);
+		/* XXX this looks wrong */
+		__asm__ __volatile__("ssm psr.pp");
+		dcr = ia64_get_dcr();
+		dcr |= IA64_DCR_PP;
+		ia64_set_dcr(dcr);
+		local_irq_restore(flags);
+                break;
+
+	      case STOP_PMCS:
+		ia64_set_pmc(0, 1);
+		for (i = 0; i < MAX_PERF_COUNTER; ++i)
+			ia64_set_pmc(i, 0);
+
+		local_irq_save(flags);
+		dcr = ia64_get_dcr();
+		dcr &= ~IA64_DCR_PP;
+		ia64_set_dcr(dcr);
+		local_irq_restore(flags);
+		/*
+		 * This is a no can do.  It obviously wouldn't
+		 * work on SMP where another process may not
+		 * be blocked at all.
+		 *
+		 * Perhaps we need a global predicate in the
+		 * leave_kernel path to control if pp should
+		 * be on or off?
+		 */
+		lock_kernel();
+		for_each_task(p) {
+			regs = (struct pt_regs *) (((char *)p) + IA64_STK_OFFSET) - 1;
+			ia64_psr(regs)->pp = 0;
+		}
+		unlock_kernel();
+		perf_owner = 0;
+		break;
+
+	      default:
+		break;
+        }
+        return 0;
+}
+
+static inline void
+update_counters (void)
+{
+	unsigned long mask, i, cnum, val;
+
+	mask = ia64_get_pmd(0) >> 4;
+	for (i = 0, cnum = 4; i < MAX_PERF_COUNTER; cnum++, i++, mask >>= 1) {
+		if (mask & 0x1) 
+			val = PERF_OVFL_VAL;
+		else
+			/* since we got an interrupt, might as well clear every pmd. */
+			val = ia64_get_pmd(cnum) & PERF_OVFL_VAL;
+		pmds[i] += val;
+		ia64_set_pmd(cnum, 0);
+	}
+}
+
+static void
+perfmon_interrupt (int irq, void *arg, struct pt_regs *regs)
+{
+	update_counters();
+	ia64_set_pmc(0, 0);
+	ia64_srlz_d();
+}
+
+void
+perfmon_init (void)
+{
+        if (request_irq(PERFMON_IRQ, perfmon_interrupt, 0, "perfmon", NULL)) {
+		printk("perfmon_init: could not allocate performance monitor vector %u\n",
+		       PERFMON_IRQ);
+		return;
+	}
+	ia64_set_pmv(PERFMON_IRQ);
+	ia64_srlz_d();
+}
+
+#else /* !CONFIG_PERFMON */
+
+asmlinkage unsigned long
+sys_perfmonctl (int cmd1, int cmd2, void *ptr)
+{
+	return -ENOSYS;
+}
+
+#endif /* !CONFIG_PERFMON */
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c
--- v2.3.42/linux/arch/ia64/kernel/process.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/process.c	Tue Feb  8 11:32:18 2000
@@ -0,0 +1,421 @@
+/*
+ * Architecture-specific setup.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#define __KERNEL_SYSCALLS__	/* see <asm/unistd.h> */
+#include <linux/config.h>
+
+#include <linux/pm.h>
+#include <linux/elf.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+
+#include <asm/delay.h>
+#include <asm/efi.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/sal.h>
+#include <asm/uaccess.h>
+#include <asm/user.h>
+
+
+void
+show_regs (struct pt_regs *regs)
+{
+	unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
+
+	printk("\npsr : %016lx ifs : %016lx ip  : [<%016lx>]\n",
+	       regs->cr_ipsr, regs->cr_ifs, ip);
+	printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
+	       regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
+	printk("rnat: %016lx bsps: %016lx pr  : %016lx\n",
+	       regs->ar_rnat, regs->ar_bspstore, regs->pr);
+	printk("ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
+	       regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
+	printk("b0  : %016lx b6  : %016lx b7  : %016lx\n", regs->b0, regs->b6, regs->b7);
+	printk("f6  : %05lx%016lx f7  : %05lx%016lx\n",
+	       regs->f6.u.bits[1], regs->f6.u.bits[0],
+	       regs->f7.u.bits[1], regs->f7.u.bits[0]);
+	printk("f8  : %05lx%016lx f9  : %05lx%016lx\n",
+	       regs->f8.u.bits[1], regs->f8.u.bits[0],
+	       regs->f9.u.bits[1], regs->f9.u.bits[0]);
+
+	printk("r1  : %016lx r2  : %016lx r3  : %016lx\n", regs->r1, regs->r2, regs->r3);
+	printk("r8  : %016lx r9  : %016lx r10 : %016lx\n", regs->r8, regs->r9, regs->r10);
+	printk("r11 : %016lx r12 : %016lx r13 : %016lx\n", regs->r11, regs->r12, regs->r13);
+	printk("r14 : %016lx r15 : %016lx r16 : %016lx\n", regs->r14, regs->r15, regs->r16);
+	printk("r17 : %016lx r18 : %016lx r19 : %016lx\n", regs->r17, regs->r18, regs->r19);
+	printk("r20 : %016lx r21 : %016lx r22 : %016lx\n", regs->r20, regs->r21, regs->r22);
+	printk("r23 : %016lx r24 : %016lx r25 : %016lx\n", regs->r23, regs->r24, regs->r25);
+	printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28);
+	printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31);
+
+	/* print the stacked registers if cr.ifs is valid: */
+	if (regs->cr_ifs & 0x8000000000000000) {
+		unsigned long val, sof, *bsp, ndirty;
+		int i, is_nat = 0;
+
+		sof = regs->cr_ifs & 0x7f;	/* size of frame */
+		ndirty = (regs->loadrs >> 19);
+		bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty);
+		for (i = 0; i < sof; ++i) {
+			get_user(val, ia64_rse_skip_regs(bsp, i));
+			printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
+			       ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
+		}
+	}
+}
+
+void __attribute__((noreturn))
+cpu_idle (void *unused)
+{
+	/* endless idle loop with no priority at all */
+	init_idle();
+	current->priority = 0;
+	current->counter = -100;
+
+#ifdef CONFIG_SMP
+	if (!current->need_resched)
+		min_xtp();
+#endif
+
+	while (1) {
+		while (!current->need_resched) {
+			continue;
+		}
+#ifdef CONFIG_SMP
+		normal_xtp();
+#endif
+		schedule();
+		check_pgt_cache();
+		if (pm_idle)
+			(*pm_idle)();
+	}
+}
+
+/*
+ * Copy the state of an ia-64 thread.
+ *
+ * We get here through the following  call chain:
+ *
+ *	<clone syscall>
+ *	sys_clone
+ *	do_fork
+ *	copy_thread
+ *
+ * This means that the stack layout is as follows:
+ *
+ *	+---------------------+ (highest addr)
+ *	|   struct pt_regs    |
+ *	+---------------------+
+ *	| struct switch_stack |
+ *	+---------------------+
+ *	|                     |
+ *	|    memory stack     |
+ *	|                     | <-- sp (lowest addr)
+ *	+---------------------+
+ *
+ * Note: if we get called through kernel_thread() then the memory
+ * above "(highest addr)" is valid kernel stack memory that needs to
+ * be copied as well.
+ *
+ * Observe that we copy the unat values that are in pt_regs and
+ * switch_stack.  Since the interpretation of unat is dependent upon
+ * the address to which the registers got spilled, doing this is valid
+ * only as long as we preserve the alignment of the stack.  Since the
+ * stack is always page aligned, we know this is the case.
+ *
+ * XXX Actually, the above isn't true when we create kernel_threads().
+ * If we ever needs to create kernel_threads() that preserve the unat
+ * values we'll need to fix this.  Perhaps an easy workaround would be
+ * to always clear the unat bits in the child thread.
+ */
+int
+copy_thread (int nr, unsigned long clone_flags, unsigned long usp,
+	     struct task_struct *p, struct pt_regs *regs)
+{
+	unsigned long rbs, child_rbs, rbs_size, stack_offset, stack_top, stack_used;
+	struct switch_stack *child_stack, *stack;
+	extern char ia64_ret_from_syscall_clear_r8;
+	extern char ia64_strace_clear_r8;
+	struct pt_regs *child_ptregs;
+
+#ifdef CONFIG_SMP
+	/*
+	 * For SMP idle threads, fork_by_hand() calls do_fork with
+	 * NULL regs.
+	 */
+	if (!regs)
+		return 0;
+#endif
+
+	stack_top = (unsigned long) current + IA64_STK_OFFSET;
+	stack = ((struct switch_stack *) regs) - 1;
+	stack_used = stack_top - (unsigned long) stack;
+	stack_offset = IA64_STK_OFFSET - stack_used;
+
+	child_stack = (struct switch_stack *) ((unsigned long) p + stack_offset);
+	child_ptregs = (struct pt_regs *) (child_stack + 1);
+
+	/* copy parent's switch_stack & pt_regs to child: */
+	memcpy(child_stack, stack, stack_used);
+
+	rbs = (unsigned long) current + IA64_RBS_OFFSET;
+	child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
+	rbs_size = stack->ar_bspstore - rbs;
+
+	/* copy the parent's register backing store to the child: */
+	memcpy((void *) child_rbs, (void *) rbs, rbs_size);
+
+	child_ptregs->r8 = 0;			/* child gets a zero return value */
+	if (user_mode(child_ptregs))
+		child_ptregs->r12 = usp;			/* user stack pointer */
+	else {
+		/*
+		 * Note: we simply preserve the relative position of
+		 * the stack pointer here.  There is no need to
+		 * allocate a scratch area here, since that will have
+		 * been taken care of by the caller of sys_clone()
+		 * already.
+		 */
+		child_ptregs->r12 = (unsigned long) (child_ptregs + 1); /* kernel sp */
+		child_ptregs->r13 = (unsigned long) p;		/* set `current' pointer */
+	}
+	if (p->flags & PF_TRACESYS)
+		child_stack->b0 = (unsigned long) &ia64_strace_clear_r8;
+	else
+		child_stack->b0 = (unsigned long) &ia64_ret_from_syscall_clear_r8;
+	child_stack->ar_bspstore = child_rbs + rbs_size;
+
+	/* copy the thread_struct: */
+	p->thread.ksp = (unsigned long) child_stack - 16;
+	/*
+	 * NOTE: The calling convention considers all floating point
+	 * registers in the high partition (fph) to be scratch.  Since
+	 * the only way to get to this point is through a system call,
+	 * we know that the values in fph are all dead.  Hence, there
+	 * is no need to inherit the fph state from the parent to the
+	 * child and all we have to do is to make sure that
+	 * IA64_THREAD_FPH_VALID is cleared in the child.
+	 *
+	 * XXX We could push this optimization a bit further by
+	 * clearing IA64_THREAD_FPH_VALID on ANY system call.
+	 * However, it's not clear this is worth doing.  Also, it
+	 * would be a slight deviation from the normal Linux system
+	 * call behavior where scratch registers are preserved across
+	 * system calls (unless used by the system call itself).
+	 *
+	 * If we wanted to inherit the fph state from the parent to the
+	 * child, we would have to do something along the lines of:
+	 *
+	 *	if (ia64_get_fpu_owner() == current && ia64_psr(regs)->mfh) {
+	 *		p->thread.flags |= IA64_THREAD_FPH_VALID;
+	 *		ia64_save_fpu(&p->thread.fph);
+	 *	} else if (current->thread.flags & IA64_THREAD_FPH_VALID) {
+	 *		memcpy(p->thread.fph, current->thread.fph, sizeof(p->thread.fph));
+	 *	}
+	 */
+	p->thread.flags = (current->thread.flags & ~IA64_THREAD_FPH_VALID);
+	return 0;
+}
+
+void
+ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
+{
+	struct switch_stack *sw = ((struct switch_stack *) pt) - 1;
+	unsigned long ar_ec, cfm, ar_bsp, ndirty, *krbs;
+
+	ar_ec = (sw->ar_pfs >> 52) & 0x3f;
+
+	cfm = pt->cr_ifs & ((1UL << 63) - 1);
+	if ((pt->cr_ifs & (1UL << 63)) == 0) {
+		/* if cr_ifs isn't valid, we got here through a syscall or a break */
+		cfm = sw->ar_pfs & ((1UL << 38) - 1);
+	}
+
+	krbs = (unsigned long *) current + IA64_RBS_OFFSET/8;
+	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 16));
+	ar_bsp = (long) ia64_rse_skip_regs((long *) pt->ar_bspstore, ndirty);
+
+	/*	r0-r31
+	 *	NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
+	 *	predicate registers (p0-p63)
+	 *	b0-b7
+	 *	ip cfm user-mask
+	 *	ar.rsc ar.bsp ar.bspstore ar.rnat
+	 *	ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
+	 */
+	memset(dst, 0, sizeof (dst));	/* don't leak any "random" bits */
+
+	/* r0 is zero */   dst[ 1] =  pt->r1; dst[ 2] =  pt->r2; dst[ 3] = pt->r3;
+	dst[ 4] =  sw->r4; dst[ 5] =  sw->r5; dst[ 6] =  sw->r6; dst[ 7] = sw->r7;
+	dst[ 8] =  pt->r8; dst[ 9] =  pt->r9; dst[10] = pt->r10; dst[11] = pt->r11;
+	dst[12] = pt->r12; dst[13] = pt->r13; dst[14] = pt->r14; dst[15] = pt->r15;
+	memcpy(dst + 16, &pt->r16, 16*8);	/* r16-r31 are contiguous */
+
+	dst[32] = ia64_get_nat_bits(pt, sw);
+	dst[33] = pt->pr;
+
+	/* branch regs: */
+	dst[34] = pt->b0; dst[35] = sw->b1; dst[36] = sw->b2; dst[37] = sw->b3;
+	dst[38] = sw->b4; dst[39] = sw->b5; dst[40] = pt->b6; dst[41] = pt->b7;
+
+	dst[42] = pt->cr_iip; dst[43] = pt->cr_ifs;
+	dst[44] = pt->cr_ipsr;	/* XXX perhaps we should filter out some bits here? --davidm */
+
+	dst[45] = pt->ar_rsc; dst[46] = ar_bsp; dst[47] = pt->ar_bspstore;  dst[48] = pt->ar_rnat;
+	dst[49] = pt->ar_ccv; dst[50] = pt->ar_unat; dst[51] = sw->ar_fpsr; dst[52] = pt->ar_pfs;
+	dst[53] = sw->ar_lc; dst[54] = (sw->ar_pfs >> 52) & 0x3f;
+}
+
+int
+dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
+{
+	struct switch_stack *sw = ((struct switch_stack *) pt) - 1;
+	struct task_struct *fpu_owner = ia64_get_fpu_owner();
+
+	memset(dst, 0, sizeof (dst));	/* don't leak any "random" bits */
+
+	/* f0 is 0.0 */  /* f1 is 1.0 */  dst[2] = sw->f2; dst[3] = sw->f3;
+	dst[4] = sw->f4; dst[5] = sw->f5; dst[6] = pt->f6; dst[7] = pt->f7;
+	dst[8] = pt->f8; dst[9] = pt->f9;
+	memcpy(dst + 10, &sw->f10, 22*16);	/* f10-f31 are contiguous */
+
+	if ((fpu_owner == current) || (current->thread.flags & IA64_THREAD_FPH_VALID)) {
+		if (fpu_owner == current) {
+			__ia64_save_fpu(current->thread.fph);
+		}
+		memcpy(dst + 32, current->thread.fph, 96*16);
+	}
+	return 1;	/* f0-f31 are always valid so we always return 1 */
+}
+
+asmlinkage long
+sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs)
+{
+	int error;
+
+	lock_kernel();
+	filename = getname(filename);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve(filename, argv, envp, regs);
+	putname(filename);
+out:
+	unlock_kernel();
+	return error;
+}
+
+pid_t
+kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct task_struct *parent = current;
+	int result;
+
+	clone(flags | CLONE_VM, 0);
+	if (parent != current) {
+		result = (*fn)(arg);
+		_exit(result);
+	}
+	return 0;		/* parent: just return */
+}
+
+/*
+ * Flush thread state.  This is called when a thread does an execve().
+ */
+void
+flush_thread (void)
+{
+	/* drop floating-point and debug-register state if it exists: */
+	current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
+
+	if (ia64_get_fpu_owner() == current) {
+		ia64_set_fpu_owner(0);
+	}
+}
+
+/*
+ * Clean up state associated with current thread.  This is called when
+ * the thread calls exit().
+ */
+void
+exit_thread (void)
+{
+	if (ia64_get_fpu_owner() == current) {
+		ia64_set_fpu_owner(0);
+	}
+}
+
+/*
+ * Free remaining state associated with DEAD_TASK.  This is called
+ * after the parent of DEAD_TASK has collected the exist status of the
+ * task via wait().
+ */
+void
+release_thread (struct task_struct *dead_task)
+{
+	/* nothing to do */
+}
+
+unsigned long
+get_wchan (struct task_struct *p)
+{
+	struct ia64_frame_info info;
+	unsigned long ip;
+	int count = 0;
+	/*
+	 * These bracket the sleeping functions..
+	 */
+	extern void scheduling_functions_start_here(void);
+	extern void scheduling_functions_end_here(void);
+#	define first_sched	((unsigned long) scheduling_functions_start_here)
+#	define last_sched	((unsigned long) scheduling_functions_end_here)
+
+	/*
+	 * Note: p may not be a blocked task (it could be current or
+	 * another process running on some other CPU.  Rather than
+	 * trying to determine if p is really blocked, we just assume
+	 * it's blocked and rely on the unwind routines to fail
+	 * gracefully if the process wasn't really blocked after all.
+	 * --davidm 99/12/15
+	 */
+	ia64_unwind_init_from_blocked_task(&info, p);
+	do {
+		if (ia64_unwind_to_previous_frame(&info) < 0)
+			return 0;
+		ip = ia64_unwind_get_ip(&info);
+		if (ip < first_sched || ip >= last_sched)
+			return ip;
+	} while (count++ < 16);
+	return 0;
+#	undef first_sched
+#	undef last_sched
+}
+
+void
+machine_restart (char *restart_cmd)
+{
+	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, 0);
+}
+
+void
+machine_halt (void)
+{
+	printk("machine_halt: need PAL or ACPI version here!!\n");
+	machine_restart(0);
+}
+
+void
+machine_power_off (void)
+{
+	printk("machine_power_off: unimplemented (need ACPI version here)\n");
+	machine_halt ();
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/ptrace.c linux/arch/ia64/kernel/ptrace.c
--- v2.3.42/linux/arch/ia64/kernel/ptrace.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/ptrace.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,653 @@
+/*
+ * Kernel support for the ptrace() and syscall tracing interfaces.
+ *
+ * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Derived from the x86 and Alpha versions.  Most of the code in here
+ * could actually be factored into a common set of routines.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/smp_lock.h>
+#include <linux/user.h>
+
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace_offsets.h>
+#include <asm/rse.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+/*
+ * Collect the NaT bits for r1-r31 from sw->caller_unat and
+ * sw->ar_unat and return a NaT bitset where bit i is set iff the NaT
+ * bit of register i is set.
+ */
+long
+ia64_get_nat_bits (struct pt_regs *pt, struct switch_stack *sw)
+{
+#	define GET_BITS(str, first, last, unat)						\
+	({										\
+		unsigned long bit = ia64_unat_pos(&str->r##first);			\
+		unsigned long mask = ((1UL << (last - first + 1)) - 1) << first;	\
+		(ia64_rotl(unat, first) >> bit) & mask;					\
+	})
+	unsigned long val;
+
+	val  = GET_BITS(pt,  1,  3, sw->caller_unat);
+	val |= GET_BITS(pt, 12, 15, sw->caller_unat);
+	val |= GET_BITS(pt,  8, 11, sw->caller_unat);
+	val |= GET_BITS(pt, 16, 31, sw->caller_unat);
+	val |= GET_BITS(sw,  4,  7, sw->ar_unat);
+	return val;
+
+#	undef GET_BITS
+}
+
+/*
+ * Store the NaT bitset NAT in pt->caller_unat and sw->ar_unat.
+ */
+void
+ia64_put_nat_bits (struct pt_regs *pt, struct switch_stack *sw, unsigned long nat)
+{
+#	define PUT_BITS(str, first, last, nat)					\
+	({									\
+		unsigned long bit = ia64_unat_pos(&str->r##first);		\
+		unsigned long mask = ((1UL << (last - first + 1)) - 1) << bit;	\
+		(ia64_rotr(nat, first) << bit) & mask;				\
+	})
+	sw->caller_unat  = PUT_BITS(pt,  1,  3, nat);
+	sw->caller_unat |= PUT_BITS(pt, 12, 15, nat);
+	sw->caller_unat |= PUT_BITS(pt,  8, 11, nat);
+	sw->caller_unat |= PUT_BITS(pt, 16, 31, nat);
+	sw->ar_unat      = PUT_BITS(sw,  4,  7, nat);
+
+#	undef PUT_BITS
+}
+
+#define IA64_MLI_TEMPLATE	0x2
+#define IA64_MOVL_OPCODE	6
+
+void
+ia64_increment_ip (struct pt_regs *regs)
+{
+	unsigned long w0, w1, ri = ia64_psr(regs)->ri + 1;
+
+	if (ri > 2) {
+		ri = 0;
+		regs->cr_iip += 16;
+	} else if (ri == 2) {
+		get_user(w0, (char *) regs->cr_iip + 0);
+		get_user(w1, (char *) regs->cr_iip + 8);
+		if (((w0 >> 1) & 0xf) == IA64_MLI_TEMPLATE && (w1 >> 60) == IA64_MOVL_OPCODE) {
+			/*
+			 * rfi'ing to slot 2 of an MLI bundle causes
+			 * an illegal operation fault.  We don't want
+			 * that to happen...  Note that we check the
+			 * opcode only.  "movl" has a vc bit of 0, but
+			 * since a vc bit of 1 is currently reserved,
+			 * we might just as well treat it like a movl.
+			 */
+			ri = 0;
+			regs->cr_iip += 16;
+		}
+	}
+	ia64_psr(regs)->ri = ri;
+}
+
+void
+ia64_decrement_ip (struct pt_regs *regs)
+{
+	unsigned long w0, w1, ri = ia64_psr(regs)->ri - 1;
+
+	if (ia64_psr(regs)->ri == 0) {
+		regs->cr_iip -= 16;
+		ri = 2;
+		get_user(w0, (char *) regs->cr_iip + 0);
+		get_user(w1, (char *) regs->cr_iip + 8);
+		if (((w0 >> 1) & 0xf) == IA64_MLI_TEMPLATE && (w1 >> 60) == IA64_MOVL_OPCODE) {
+			/*
+			 * rfi'ing to slot 2 of an MLI bundle causes
+			 * an illegal operation fault.  We don't want
+			 * that to happen...  Note that we check the
+			 * opcode only.  "movl" has a vc bit of 0, but
+			 * since a vc bit of 1 is currently reserved,
+			 * we might just as well treat it like a movl.
+			 */
+			ri = 1;
+		}
+	}
+	ia64_psr(regs)->ri = ri;
+}
+
+/*
+ * This routine is used to read an rnat bits that are stored on the
+ * kernel backing store.  Since, in general, the alignment of the user
+ * and kernel are different, this is not completely trivial.  In
+ * essence, we need to construct the user RNAT based on up to two
+ * kernel RNAT values and/or the RNAT value saved in the child's
+ * pt_regs.
+ *
+ * user rbs
+ *
+ * +--------+ <-- lowest address
+ * | slot62 |
+ * +--------+
+ * |  rnat  | 0x....1f8
+ * +--------+
+ * | slot00 | \
+ * +--------+ |
+ * | slot01 | > child_regs->ar_rnat
+ * +--------+ |
+ * | slot02 | /				kernel rbs
+ * +--------+ 				+--------+
+ *	    <- child_regs->ar_bspstore	| slot61 | <-- krbs
+ * +- - - - +				+--------+
+ *					| slot62 |
+ * +- - - - +				+--------+
+ *					|  rnat	 |
+ * +- - - - +				+--------+
+ *   vrnat				| slot00 |
+ * +- - - - +				+--------+
+ *					=	 =
+ *					+--------+
+ *					| slot00 | \
+ *					+--------+ |
+ *					| slot01 | > child_stack->ar_rnat
+ *					+--------+ |
+ *					| slot02 | /
+ *					+--------+
+ *						  <--- child_stack->ar_bspstore
+ *
+ * The way to think of this code is as follows: bit 0 in the user rnat
+ * corresponds to some bit N (0 <= N <= 62) in one of the kernel rnat
+ * value.  The kernel rnat value holding this bit is stored in
+ * variable rnat0.  rnat1 is loaded with the kernel rnat value that
+ * form the upper bits of the user rnat value.
+ *
+ * Boundary cases:
+ *
+ * o when reading the rnat "below" the first rnat slot on the kernel
+ *   backing store, rnat0/rnat1 are set to 0 and the low order bits
+ *   are merged in from pt->ar_rnat.
+ *
+ * o when reading the rnat "above" the last rnat slot on the kernel
+ *   backing store, rnat0/rnat1 gets its value from sw->ar_rnat.
+ */
+static unsigned long
+get_rnat (struct pt_regs *pt, struct switch_stack *sw,
+	  unsigned long *krbs, unsigned long *urnat_addr)
+{
+	unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, kmask = ~0UL;
+	unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
+	long num_regs;
+
+	kbsp = (unsigned long *) sw->ar_bspstore;
+	ubspstore = (unsigned long *) pt->ar_bspstore;
+	/*
+	 * First, figure out which bit number slot 0 in user-land maps
+	 * to in the kernel rnat.  Do this by figuring out how many
+	 * register slots we're beyond the user's backingstore and
+	 * then computing the equivalent address in kernel space.
+	 */
+	num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1);
+	slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
+	shift = ia64_rse_slot_num(slot0_kaddr);
+	rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
+	rnat0_kaddr = rnat1_kaddr - 64;
+
+	if (ubspstore + 63 > urnat_addr) {
+		/* some bits need to be merged in from pt->ar_rnat */
+		kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1);
+		urnat = (pt->ar_rnat & ~kmask);
+	} 
+	if (rnat0_kaddr >= kbsp) {
+		rnat0 = sw->ar_rnat;
+	} else if (rnat0_kaddr > krbs) {
+		rnat0 = *rnat0_kaddr;
+	}
+	if (rnat1_kaddr >= kbsp) {
+		rnat1 = sw->ar_rnat;
+	} else if (rnat1_kaddr > krbs) {
+		rnat1 = *rnat1_kaddr;
+	}
+	urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & kmask;
+	return urnat;
+}
+
+/*
+ * The reverse of get_rnat.
+ */
+static void
+put_rnat (struct pt_regs *pt, struct switch_stack *sw,
+	  unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat)
+{
+	unsigned long rnat0 = 0, rnat1 = 0, rnat = 0, *slot0_kaddr, kmask = ~0UL, mask;
+	unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift;
+	long num_regs;
+
+	kbsp = (unsigned long *) sw->ar_bspstore;
+	ubspstore = (unsigned long *) pt->ar_bspstore;
+	/*
+	 * First, figure out which bit number slot 0 in user-land maps
+	 * to in the kernel rnat.  Do this by figuring out how many
+	 * register slots we're beyond the user's backingstore and
+	 * then computing the equivalent address in kernel space.
+	 */
+	num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1);
+	slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs);
+	shift = ia64_rse_slot_num(slot0_kaddr);
+	rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr);
+	rnat0_kaddr = rnat1_kaddr - 64;
+
+	if (ubspstore + 63 > urnat_addr) {
+		/* some bits need to be place in pt->ar_rnat: */
+		kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1);
+		pt->ar_rnat = (pt->ar_rnat & kmask) | (rnat & ~kmask);
+	} 
+	/*
+	 * Note: Section 11.1 of the EAS guarantees that bit 63 of an
+	 * rnat slot is ignored. so we don't have to clear it here.
+	 */
+	rnat0 = (urnat << shift);
+	mask = ~0UL << shift;
+	if (rnat0_kaddr >= kbsp) {
+		sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat0 & mask);
+	} else if (rnat0_kaddr > krbs) {
+		*rnat0_kaddr = ((*rnat0_kaddr & ~mask) | (rnat0 & mask));
+	}
+
+	rnat1 = (urnat >> (63 - shift));
+	mask = ~0UL >> (63 - shift);
+	if (rnat1_kaddr >= kbsp) {
+		sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat1 & mask);
+	} else if (rnat1_kaddr > krbs) {
+		*rnat1_kaddr = ((*rnat1_kaddr & ~mask) | (rnat1 & mask));
+	}
+}
+
+long
+ia64_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, long *val)
+{
+	unsigned long *bspstore, *krbs, krbs_num_regs, regnum, *rbs_end, *laddr;
+	struct switch_stack *child_stack;
+	struct pt_regs *child_regs;
+	size_t copied;
+	long ret;
+
+	laddr = (unsigned long *) addr;
+	child_regs = ia64_task_regs(child);
+	child_stack = (struct switch_stack *) child_regs - 1;
+	bspstore = (unsigned long *) child_regs->ar_bspstore;
+	krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
+	krbs_num_regs = ia64_rse_num_regs(krbs, (unsigned long *) child_stack->ar_bspstore);
+	rbs_end = ia64_rse_skip_regs(bspstore, krbs_num_regs);
+	if (laddr >= bspstore && laddr <= ia64_rse_rnat_addr(rbs_end)) {
+		/*
+		 * Attempt to read the RBS in an area that's actually
+		 * on the kernel RBS => read the corresponding bits in
+		 * the kernel RBS.
+		 */
+		if (ia64_rse_is_rnat_slot(laddr))
+			ret = get_rnat(child_regs, child_stack, krbs, laddr);
+		else {
+			regnum = ia64_rse_num_regs(bspstore, laddr);
+			laddr = ia64_rse_skip_regs(krbs, regnum);
+			if (regnum >= krbs_num_regs) {
+				ret = 0;
+			} else {
+				if  ((unsigned long) laddr >= (unsigned long) high_memory) {
+					printk("yikes: trying to access long at %p\n", laddr);
+					return -EIO;
+				}
+				ret = *laddr;
+			}
+		}
+	} else {
+		copied = access_process_vm(child, addr, &ret, sizeof(ret), 0);
+		if (copied != sizeof(ret))
+			return -EIO;
+	}
+	*val = ret;
+	return 0;
+}
+
+long
+ia64_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, long val)
+{
+	unsigned long *bspstore, *krbs, krbs_num_regs, regnum, *rbs_end, *laddr;
+	struct switch_stack *child_stack;
+	struct pt_regs *child_regs;
+
+	laddr = (unsigned long *) addr;
+	child_regs = ia64_task_regs(child);
+	child_stack = (struct switch_stack *) child_regs - 1;
+	bspstore = (unsigned long *) child_regs->ar_bspstore;
+	krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
+	krbs_num_regs = ia64_rse_num_regs(krbs, (unsigned long *) child_stack->ar_bspstore);
+	rbs_end = ia64_rse_skip_regs(bspstore, krbs_num_regs);
+	if (laddr >= bspstore && laddr <= ia64_rse_rnat_addr(rbs_end)) {
+		/*
+		 * Attempt to write the RBS in an area that's actually
+		 * on the kernel RBS => write the corresponding bits
+		 * in the kernel RBS.
+		 */
+		if (ia64_rse_is_rnat_slot(laddr))
+			put_rnat(child_regs, child_stack, krbs, laddr, val);
+		else {
+			regnum = ia64_rse_num_regs(bspstore, laddr);
+			laddr = ia64_rse_skip_regs(krbs, regnum);
+			if (regnum < krbs_num_regs) {
+				*laddr = val;
+			}
+		}
+	} else if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) {
+		return -EIO;
+	}
+	return 0;
+}
+
+/*
+ * Ensure the state in child->thread.fph is up-to-date.
+ */
+static void
+sync_fph (struct task_struct *child)
+{
+	if (ia64_psr(ia64_task_regs(child))->mfh && ia64_get_fpu_owner() == child) {
+		ia64_save_fpu(&child->thread.fph[0]);
+		child->thread.flags |= IA64_THREAD_FPH_VALID;
+	}
+	if (!(child->thread.flags & IA64_THREAD_FPH_VALID)) {
+		memset(&child->thread.fph, 0, sizeof(child->thread.fph));
+		child->thread.flags |= IA64_THREAD_FPH_VALID;
+	}
+}
+
+asmlinkage long
+sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
+	    long arg4, long arg5, long arg6, long arg7, long stack)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+	struct switch_stack *child_stack;
+	struct pt_regs *child_regs;
+	struct task_struct *child;
+	unsigned long flags, *base;
+	long ret, regnum;
+
+	lock_kernel();
+	ret = -EPERM;
+	if (request == PTRACE_TRACEME) {
+		/* are we already being traced? */
+		if (current->flags & PF_PTRACED)
+			goto out;
+		current->flags |= PF_PTRACED;
+		ret = 0;
+		goto out;
+	}
+
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+	ret = -EPERM;
+	if (pid == 1)		/* no messing around with init! */
+		goto out;
+
+	if (request == PTRACE_ATTACH) {
+		if (child == current)
+			goto out;
+		if ((!child->dumpable ||
+		    (current->uid != child->euid) ||
+		    (current->uid != child->suid) ||
+		    (current->uid != child->uid) ||
+	 	    (current->gid != child->egid) ||
+	 	    (current->gid != child->sgid) ||
+	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+			goto out;
+		/* the same process cannot be attached many times */
+		if (child->flags & PF_PTRACED)
+			goto out;
+		child->flags |= PF_PTRACED;
+		if (child->p_pptr != current) {
+			unsigned long flags;
+
+			write_lock_irqsave(&tasklist_lock, flags);
+			REMOVE_LINKS(child);
+			child->p_pptr = current;
+			SET_LINKS(child);
+			write_unlock_irqrestore(&tasklist_lock, flags);
+		}
+		send_sig(SIGSTOP, child, 1);
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	if (!(child->flags & PF_PTRACED))
+		goto out;
+	if (child->state != TASK_STOPPED) {
+		if (request != PTRACE_KILL)
+			goto out;
+	}
+	if (child->p_pptr != current)
+		goto out;
+
+	switch (request) {
+	      case PTRACE_PEEKTEXT:
+	      case PTRACE_PEEKDATA:		/* read word at location addr */
+		ret = ia64_peek(regs, child, addr, &data);
+		if (ret == 0) {
+			ret = data;
+			regs->r8 = 0;	/* ensure "ret" is not mistaken as an error code */
+		}
+		goto out;
+
+	      case PTRACE_POKETEXT:
+	      case PTRACE_POKEDATA:		/* write the word at location addr */
+		ret = ia64_poke(regs, child, addr, data);
+		goto out;
+
+	      case PTRACE_PEEKUSR:		/* read the word at addr in the USER area */
+		ret = -EIO;
+		if ((addr & 0x7) != 0)
+			goto out;
+
+		if (addr < PT_CALLER_UNAT) {
+			/* accessing fph */
+			sync_fph(child);
+			addr += (unsigned long) &child->thread.fph;
+			ret = *(unsigned long *) addr;
+		} else if (addr < PT_F9+16) {
+			/* accessing switch_stack or pt_regs: */
+			child_regs = ia64_task_regs(child);
+			child_stack = (struct switch_stack *) child_regs - 1;
+			ret = *(unsigned long *) ((long) child_stack + addr - PT_CALLER_UNAT);
+
+			if (addr == PT_AR_BSP) {
+				/* ret currently contains pt_regs.loadrs */
+				unsigned long *rbs, *bspstore, ndirty;
+
+				rbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
+				bspstore = (unsigned long *) child_regs->ar_bspstore;
+				ndirty = ia64_rse_num_regs(rbs, rbs + (ret >> 19));
+				ret = (unsigned long) ia64_rse_skip_regs(bspstore, ndirty);
+			}
+		} else {
+			if (addr >= PT_IBR) {
+				regnum = (addr - PT_IBR) >> 3;
+				base = &child->thread.ibr[0];
+			} else {
+				regnum = (addr - PT_DBR) >> 3;
+				base = &child->thread.dbr[0];
+			}
+			if (regnum >= 8)
+				goto out;
+			data = base[regnum];
+		}
+		regs->r8 = 0;	/* ensure "ret" is not mistaken as an error code */
+		goto out;
+
+	      case PTRACE_POKEUSR:	      /* write the word at addr in the USER area */
+		ret = -EIO;
+		if ((addr & 0x7) != 0)
+			goto out;
+
+		if (addr < PT_CALLER_UNAT) {
+			/* accessing fph */
+			sync_fph(child);
+			addr += (unsigned long) &child->thread.fph;
+			*(unsigned long *) addr = data;
+			if (ret < 0)
+				goto out;
+		} else if (addr < PT_F9+16) {
+			/* accessing switch_stack or pt_regs */
+			child_regs = ia64_task_regs(child);
+			child_stack = (struct switch_stack *) child_regs - 1;
+
+			if (addr == PT_AR_BSP) {
+				/* compute the loadrs value based on bsp and bspstore: */
+				unsigned long *rbs, *bspstore, ndirty, *kbsp;
+
+				bspstore = (unsigned long *) child_regs->ar_bspstore;
+				ndirty = ia64_rse_num_regs(bspstore, (unsigned long *) data);
+				rbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
+				kbsp = ia64_rse_skip_regs(rbs, ndirty);
+				data = (kbsp - rbs) << 19;
+			}
+			*(unsigned long *) ((long) child_stack + addr - PT_CALLER_UNAT) = data;
+		} else {
+			if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
+				child->thread.flags |= IA64_THREAD_DBG_VALID;
+				memset(current->thread.dbr, 0, sizeof current->thread.dbr);
+				memset(current->thread.ibr, 0, sizeof current->thread.ibr);
+			}
+
+			if (addr >= PT_IBR) {
+				regnum = (addr - PT_IBR) >> 3;
+				base = &child->thread.ibr[0];
+			} else {
+				regnum = (addr - PT_DBR) >> 3;
+				base = &child->thread.dbr[0];
+			}
+			if (regnum >= 8)
+				goto out;
+			if (regnum & 1) {
+				/* force breakpoint to be effective a most for user-level: */
+				data &= ~(0x7UL << 56);
+			}
+			base[regnum] = data;
+		}
+		ret = 0;
+		goto out;
+
+	      case PTRACE_SYSCALL:	/* continue and stop at next (return from) syscall */
+	      case PTRACE_CONT:		/* restart after signal. */
+		ret = -EIO;
+		if (data > _NSIG)
+			goto out;
+		if (request == PTRACE_SYSCALL)
+			child->flags |= PF_TRACESYS;
+		else
+			child->flags &= ~PF_TRACESYS;
+		child->exit_code = data;
+
+		/* make sure the single step/take-branch tra bits are not set: */
+		ia64_psr(ia64_task_regs(child))->ss = 0;
+		ia64_psr(ia64_task_regs(child))->tb = 0;
+
+		wake_up_process(child);
+		ret = 0;
+		goto out;
+
+	      case PTRACE_KILL:
+		/*
+		 * Make the child exit.  Best I can do is send it a
+		 * sigkill.  Perhaps it should be put in the status
+		 * that it wants to exit.
+		 */
+		if (child->state == TASK_ZOMBIE)		/* already dead */
+			goto out;
+		child->exit_code = SIGKILL;
+
+		/* make sure the single step/take-branch tra bits are not set: */
+		ia64_psr(ia64_task_regs(child))->ss = 0;
+		ia64_psr(ia64_task_regs(child))->tb = 0;
+
+		wake_up_process(child);
+		ret = 0;
+		goto out;
+
+	      case PTRACE_SINGLESTEP:		/* let child execute for one instruction */
+	      case PTRACE_SINGLEBLOCK:
+		ret = -EIO;
+		if (data > _NSIG)
+			goto out;
+
+		child->flags &= ~PF_TRACESYS;
+		if (request == PTRACE_SINGLESTEP) {
+			ia64_psr(ia64_task_regs(child))->ss = 1;
+		} else {
+			ia64_psr(ia64_task_regs(child))->tb = 1;
+		}
+		child->exit_code = data;
+
+		/* give it a chance to run. */
+		wake_up_process(child);
+		ret = 0;
+		goto out;
+
+	      case PTRACE_DETACH:		/* detach a process that was attached. */
+		ret = -EIO;
+		if (data > _NSIG)
+			goto out;
+
+		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+		child->exit_code = data;
+		write_lock_irqsave(&tasklist_lock, flags);
+		REMOVE_LINKS(child);
+		child->p_pptr = child->p_opptr;
+		SET_LINKS(child);
+		write_unlock_irqrestore(&tasklist_lock, flags);
+
+		/* make sure the single step/take-branch tra bits are not set: */
+		ia64_psr(ia64_task_regs(child))->ss = 0;
+		ia64_psr(ia64_task_regs(child))->tb = 0;
+
+		wake_up_process(child);
+		ret = 0;
+		goto out;
+
+	      default:
+		ret = -EIO;
+		goto out;
+	}
+  out:
+	unlock_kernel();
+	return ret;
+}
+
+void
+syscall_trace (void)
+{
+	if ((current->flags & (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS))
+		return;
+	current->exit_code = SIGTRAP;
+	set_current_state(TASK_STOPPED);
+	notify_parent(current, SIGCHLD);
+	schedule();
+	/*
+	 * This isn't the same as continuing with a signal, but it
+	 * will do for normal use.  strace only continues with a
+	 * signal if the stopping signal is not SIGTRAP.  -brl
+	 */
+	if (current->exit_code) {
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
+	}
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/sal.c linux/arch/ia64/kernel/sal.c
--- v2.3.42/linux/arch/ia64/kernel/sal.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/sal.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,157 @@
+/*
+ * System Abstraction Layer (SAL) interface routines.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/sal.h>
+#include <asm/pal.h>
+
+#define SAL_DEBUG
+
+spinlock_t sal_lock = SPIN_LOCK_UNLOCKED;
+
+static struct {
+	void *addr;	/* function entry point */
+	void *gpval;	/* gp value to use */
+} pdesc;
+
+static long
+default_handler (void)
+{
+	return -1;
+}
+
+ia64_sal_handler ia64_sal = (ia64_sal_handler) default_handler;
+
+const char *
+ia64_sal_strerror (long status)
+{
+	const char *str;
+	switch (status) {
+	      case 0: str = "Call completed without error"; break;
+	      case 1: str = "Effect a warm boot of the system to complete "
+			      "the update"; break;
+	      case -1: str = "Not implemented"; break;
+	      case -2: str = "Invalid argument"; break;
+	      case -3: str = "Call completed with error"; break;
+	      case -4: str = "Virtual address not registered"; break;
+	      case -5: str = "No information available"; break;
+	      case -6: str = "Insufficient space to add the entry"; break;
+	      case -7: str = "Invalid entry_addr value"; break;
+	      case -8: str = "Invalid interrupt vector"; break;
+	      case -9: str = "Requested memory not available"; break;
+	      case -10: str = "Unable to write to the NVM device"; break;
+	      case -11: str = "Invalid partition type specified"; break;
+	      case -12: str = "Invalid NVM_Object id specified"; break;
+	      case -13: str = "NVM_Object already has the maximum number "
+				"of partitions"; break;
+	      case -14: str = "Insufficient space in partition for the "
+				"requested write sub-function"; break;
+	      case -15: str = "Insufficient data buffer space for the "
+				"requested read record sub-function"; break;
+	      case -16: str = "Scratch buffer required for the write/delete "
+				"sub-function"; break;
+	      case -17: str = "Insufficient space in the NVM_Object for the "
+				"requested create sub-function"; break;
+	      case -18: str = "Invalid value specified in the partition_rec "
+				"argument"; break;
+	      case -19: str = "Record oriented I/O not supported for this "
+				"partition"; break;
+	      case -20: str = "Bad format of record to be written or "
+				"required keyword variable not "
+				"specified"; break;
+	      default: str = "Unknown SAL status code"; break;
+	}
+	return str;
+}
+
+static void __init 
+ia64_sal_handler_init (void *entry_point, void *gpval)
+{
+	/* fill in the SAL procedure descriptor and point ia64_sal to it: */
+	pdesc.addr = entry_point;
+	pdesc.gpval = gpval;
+	ia64_sal = (ia64_sal_handler) &pdesc;
+}
+
+
+void __init
+ia64_sal_init (struct ia64_sal_systab *systab)
+{
+	unsigned long min, max;
+	char *p;
+	struct ia64_sal_desc_entry_point *ep;
+	int i;
+
+	if (!systab) {
+		printk("Hmm, no SAL System Table.\n");
+		return;
+	}
+
+	if (strncmp(systab->signature, "SST_", 4) != 0)
+		printk("bad signature in system table!");
+
+	printk("SAL v%u.%02u: ia32bios=%s, oem=%.32s, product=%.32s\n",
+	       systab->sal_rev_major, systab->sal_rev_minor,
+	       systab->ia32_bios_present ? "present" : "absent",
+	       systab->oem_id, systab->product_id);
+
+	min = ~0UL;
+	max = 0;
+
+	p = (char *) (systab + 1);
+	for (i = 0; i < systab->entry_count; i++) {
+		/*
+		 * The first byte of each entry type contains the type desciptor.
+		 */
+		switch (*p) {
+		      case SAL_DESC_ENTRY_POINT:
+			ep = (struct ia64_sal_desc_entry_point *) p;
+#ifdef SAL_DEBUG
+			printk("sal[%d] - entry: pal_proc=0x%lx, sal_proc=0x%lx\n",
+			       i, ep->pal_proc, ep->sal_proc);
+#endif
+			ia64_pal_handler_init(__va(ep->pal_proc));
+			ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp));
+			break;
+
+		      case SAL_DESC_AP_WAKEUP:
+#ifdef CONFIG_SMP
+		      {
+			      struct ia64_sal_desc_ap_wakeup *ap = (void *) p;
+# ifdef SAL_DEBUG
+			      printk("sal[%d] - wakeup type %x, 0x%lx\n",
+				     i, ap->mechanism, ap->vector);
+# endif
+			      switch (ap->mechanism) {
+				    case IA64_SAL_AP_EXTERNAL_INT:
+				      ap_wakeup_vector = ap->vector;
+# ifdef SAL_DEBUG
+				      printk("SAL: AP wakeup using external interrupt; "
+					     "vector 0x%lx\n", ap_wakeup_vector);
+# endif
+				      break;
+
+				    default:
+				      printk("SAL: AP wakeup mechanism unsupported!\n");
+				      break;
+			      }
+			      break;
+		      }
+#endif
+		}
+		p += SAL_DESC_SIZE(*p);
+	}
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/sal_stub.S linux/arch/ia64/kernel/sal_stub.S
--- v2.3.42/linux/arch/ia64/kernel/sal_stub.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/sal_stub.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,116 @@
+/*
+ * gcc currently does not conform to the ia-64 calling convention as far
+ * as returning function values are concerned.  Instead of returning
+ * values up to 32 bytes in size in r8-r11, gcc returns any value
+ * bigger than a doubleword via a structure that's allocated by the
+ * caller and whose address is passed into the function.  Since
+ * SAL_PROC returns values according to the calling convention, this
+ * stub takes care of copying r8-r11 to the place where gcc expects
+ * them.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#ifndef __GCC_MULTIREG_RETVALS__
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 16
+	.global ia64_sal_stub
+ia64_sal_stub:
+	/*
+	 * Sheesh, the Cygnus backend passes the pointer to a return value structure in
+	 * in0 whereas the HP backend passes it in r8.  Don't you hate those little
+	 * differences...
+	 */
+#ifdef GCC_RETVAL_POINTER_IN_R8
+	adds r2=-24,sp
+	adds sp=-48,sp
+	mov r14=rp
+	;;
+	st8	[r2]=r8,8	// save pointer to return value
+	addl	r3=@ltoff(ia64_sal),gp
+	;;
+	ld8	r3=[r3]
+	st8	[r2]=gp,8	// save global pointer
+	;;
+	ld8	r3=[r3]		// fetch the value of ia64_sal
+	st8	[r2]=r14	// save return pointer
+	;;
+	ld8	r2=[r3],8	// load function's entry point
+	;;
+	ld8	gp=[r3]		// load function's global pointer
+	;;
+	mov	b6=r2
+	br.call.sptk.few rp=b6
+.ret0:	adds	r2=24,sp
+	;;
+	ld8	r3=[r2],8	// restore pointer to return value
+	;;
+	ld8	gp=[r2],8	// restore global pointer
+	st8	[r3]=r8,8
+	;;
+	ld8	r14=[r2]	// restore return pointer
+	st8	[r3]=r9,8
+	;;
+	mov	rp=r14
+	st8	[r3]=r10,8
+	;;
+	st8	[r3]=r11,8
+	adds	sp=48,sp
+	br.sptk.few rp
+#else
+	/*
+	 * On input:
+	 *	in0 = pointer to return value structure
+	 *	in1 = index of SAL function to call
+	 *	in2..inN = remaining args to SAL call
+	 */
+	/*
+	 * We allocate one input and eight output register such that the br.call instruction
+	 * will rename in1-in7 to in0-in6---exactly what we want because SAL doesn't want to
+	 * see the pointer to the return value structure.
+	 */
+	alloc	r15=ar.pfs,1,0,8,0
+
+	adds	r2=-24,sp
+	adds	sp=-48,sp
+	mov	r14=rp
+	;;
+	st8	[r2]=r15,8	// save ar.pfs
+	addl	r3=@ltoff(ia64_sal),gp
+	;;
+	ld8	r3=[r3]		// get address of ia64_sal
+	st8	[r2]=gp,8	// save global pointer
+	;;
+	ld8	r3=[r3]		// get value of ia64_sal
+	st8	[r2]=r14,8	// save return address (rp)
+	;;
+	ld8	r2=[r3],8	// load function's entry point
+	;;
+	ld8	gp=[r3]		// load function's global pointer
+	mov	b6=r2
+	br.call.sptk.few rp=b6	// make SAL call
+.ret0:	adds	r2=24,sp
+	;;
+	ld8	r15=[r2],8	// restore ar.pfs
+	;;
+	ld8	gp=[r2],8	// restore global pointer
+	st8	[in0]=r8,8	// store 1. dword of return value
+	;;
+	ld8	r14=[r2]	// restore return address (rp)
+	st8	[in0]=r9,8	// store 2. dword of return value
+	;;
+	mov	rp=r14
+	st8	[in0]=r10,8	// store 3. dword of return value
+	;;
+	st8	[in0]=r11,8
+	adds	sp=48,sp	// pop stack frame
+	mov	ar.pfs=r15
+	br.ret.sptk.few rp
+#endif
+
+	.endp ia64_sal_stub
+#endif /* __GCC_MULTIREG_RETVALS__ */
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/semaphore.c linux/arch/ia64/kernel/semaphore.c
--- v2.3.42/linux/arch/ia64/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/semaphore.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,336 @@
+/*
+ * IA-64 semaphore implementation (derived from x86 version).
+ *
+ * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/*
+ * Semaphores are implemented using a two-way counter: The "count"
+ * variable is decremented for each process that tries to aquire the
+ * semaphore, while the "sleepers" variable is a count of such
+ * aquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can efficiently
+ * test if they need to do any extra work (up needs to do something
+ * only if count was negative before the increment operation.
+ *
+ * "sleepers" and the contention routine ordering is protected by the
+ * semaphore spinlock.
+ *
+ * Note that these functions are only called when there is contention
+ * on the lock, and as such all this is the "non-critical" part of the
+ * whole semaphore business. The critical part is the inline stuff in
+ * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
+ */
+#include <linux/sched.h>
+
+#include <asm/semaphore.h>
+
+/*
+ * Logic:
+ *  - Only on a boundary condition do we need to care. When we go
+ *    from a negative count to a non-negative, we wake people up.
+ *  - When we go from a non-negative count to a negative do we
+ *    (a) synchronize with the "sleepers" count and (b) make sure
+ *    that we're on the wakeup list before we synchronize so that
+ *    we cannot lose wakeup events.
+ */
+
+void
+__up (struct semaphore *sem)
+{
+	wake_up(&sem->wait);
+}
+
+static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
+
+void
+__down (struct semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	spin_lock_irq(&semaphore_lock);
+	sem->sleepers++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			sem->sleepers = 0;
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irq(&semaphore_lock);
+
+		schedule();
+		tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
+		spin_lock_irq(&semaphore_lock);
+	}
+	spin_unlock_irq(&semaphore_lock);
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+	wake_up(&sem->wait);
+}
+
+int
+__down_interruptible (struct semaphore * sem)
+{
+	int retval = 0;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	spin_lock_irq(&semaphore_lock);
+	sem->sleepers ++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * With signals pending, this turns into
+		 * the trylock failure case - we won't be
+		 * sleeping, and we* can't get the lock as
+		 * it has contention. Just correct the count
+		 * and exit.
+		 */
+		if (signal_pending(current)) {
+			retval = -EINTR;
+			sem->sleepers = 0;
+			atomic_add(sleepers, &sem->count);
+			break;
+		}
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock. The
+		 * "-1" is because we're still hoping to get
+		 * the lock.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			sem->sleepers = 0;
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irq(&semaphore_lock);
+
+		schedule();
+		tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
+		spin_lock_irq(&semaphore_lock);
+	}
+	spin_unlock_irq(&semaphore_lock);
+	tsk->state = TASK_RUNNING;
+	remove_wait_queue(&sem->wait, &wait);
+	wake_up(&sem->wait);
+	return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for having decremented the
+ * count.
+ */
+int
+__down_trylock (struct semaphore *sem)
+{
+	int sleepers;
+
+	spin_lock_irq(&semaphore_lock);
+	sleepers = sem->sleepers + 1;
+	sem->sleepers = 0;
+
+	/*
+	 * Add "everybody else" and us into it. They aren't
+	 * playing, because we own the spinlock.
+	 */
+	if (!atomic_add_negative(sleepers, &sem->count))
+		wake_up(&sem->wait);
+
+	spin_unlock_irq(&semaphore_lock);
+	return 1;
+}
+
+/*
+ * Helper routines for rw semaphores.  These could be optimized some
+ * more, but since they're off the critical path, I prefer clarity for
+ * now...
+ */
+
+/*
+ * This gets called if we failed to acquire the lock, but we're biased
+ * to acquire the lock by virtue of causing the count to change from 0
+ * to -1.  Being biased, we sleep and attempt to grab the lock until
+ * we succeed.  When this function returns, we own the lock.
+ */
+static inline void
+down_read_failed_biased (struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
+
+	for (;;) {
+		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
+			break;
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		if (!sem->read_bias_granted)
+			schedule();
+	}
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+}
+
+/*
+ * This gets called if we failed to aquire the lock and we are not
+ * biased to acquire the lock.  We undo the decrement that was
+ * done earlier, go to sleep, and then attempt to re-acquire the
+ * lock afterwards.
+ */
+static inline void
+down_read_failed (struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	/*
+	 * Undo the decrement we did in down_read() and check if we
+	 * need to wake up someone.
+	 */
+	__up_read(sem);
+
+	add_wait_queue(&sem->wait, &wait);
+	while (sem->count < 0) {
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		if (sem->count >= 0)
+			break;
+		schedule();
+	}
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+}
+
+/*
+ * Wait for the lock to become unbiased.  Readers are non-exclusive.
+ */
+void
+__down_read_failed (struct rw_semaphore *sem, long count)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	while (1) {
+		if (count == -1) {
+			down_read_failed_biased(sem);
+			return;
+		}
+		/* unbiased */
+		down_read_failed(sem);
+
+		count = ia64_fetch_and_add(-1, &sem->count);
+		if (count >= 0)
+			return;
+	}
+}
+
+static inline void
+down_write_failed_biased (struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	/* put ourselves at the end of the list */
+	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
+
+	for (;;) {
+		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
+			break;
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+		if (!sem->write_bias_granted)
+			schedule();
+	}
+
+	remove_wait_queue(&sem->write_bias_wait, &wait);
+	tsk->state = TASK_RUNNING;
+
+	/*
+	 * If the lock is currently unbiased, awaken the sleepers
+	 * FIXME: this wakes up the readers early in a bit of a
+	 * stampede -> bad!
+	 */
+	if (sem->count >= 0)
+		wake_up(&sem->wait);
+}
+
+
+static inline void
+down_write_failed (struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	__up_write(sem);	/* this takes care of granting the lock */
+
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	while (sem->count < 0) {
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+		if (sem->count >= 0)
+			break;	/* we must attempt to aquire or bias the lock */
+		schedule();
+	}
+
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+}
+
+
+/*
+ * Wait for the lock to become unbiased.  Since we're a writer, we'll
+ * make ourselves exclusive.
+ */
+void
+__down_write_failed (struct rw_semaphore *sem, long count)
+{
+	long old_count;
+
+	while (1) {
+		if (count == -RW_LOCK_BIAS) {
+			down_write_failed_biased(sem);
+			return;
+		}
+		down_write_failed(sem);
+
+		do {
+			old_count = sem->count;
+			count = old_count - RW_LOCK_BIAS;
+		} while (cmpxchg(&sem->count, old_count, count) != old_count);
+
+		if (count == 0)
+			return;
+	}
+}
+
+void
+__rwsem_wake (struct rw_semaphore *sem, long count)
+{
+	wait_queue_head_t *wq;
+
+	if (count == 0) {
+		/* wake a writer */
+		if (xchg(&sem->write_bias_granted, 1))
+			BUG();
+		wq = &sem->write_bias_wait;
+	} else {
+		/* wake reader(s) */
+		if (xchg(&sem->read_bias_granted, 1))
+			BUG();
+		wq = &sem->wait;
+	}
+	wake_up(wq);	/* wake up everyone on the wait queue */
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/setup.c linux/arch/ia64/kernel/setup.c
--- v2.3.42/linux/arch/ia64/kernel/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/setup.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,326 @@
+/*
+ * Architecture-specific setup.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ *
+ * 02/04/00 D.Mosberger some more get_cpuinfo fixes...
+ * 02/01/00 R.Seth fixed get_cpuinfo for SMP
+ * 01/07/99 S.Eranian added the support for command line argument
+ * 06/24/99 W.Drummond added boot_cpu_data.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/threads.h>
+#include <linux/console.h>
+
+#include <asm/acpi-ext.h>
+#include <asm/page.h>
+#include <asm/machvec.h>
+#include <asm/processor.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+#include <asm/efi.h>
+
+extern char _end;
+
+/* cpu_data[bootstrap_processor] is data for the bootstrap processor: */
+struct cpuinfo_ia64 cpu_data[NR_CPUS];
+
+unsigned long ia64_cycles_per_usec;
+struct ia64_boot_param ia64_boot_param;
+struct screen_info screen_info;
+unsigned long cpu_initialized = 0;
+/* This tells _start which CPU is booting.  */
+int cpu_now_booting = 0;
+
+#define COMMAND_LINE_SIZE	512
+
+char saved_command_line[COMMAND_LINE_SIZE]; /* used in proc filesystem */
+
+static int
+find_max_pfn (unsigned long start, unsigned long end, void *arg)
+{
+	unsigned long *max_pfn = arg, pfn;
+
+	pfn = (PAGE_ALIGN(end - 1) - PAGE_OFFSET) >> PAGE_SHIFT;
+	if (pfn > *max_pfn)
+		*max_pfn = pfn;
+	return 0;
+}
+
+static int
+free_available_memory (unsigned long start, unsigned long end, void *arg)
+{
+#	define KERNEL_END	((unsigned long) &_end)
+#	define MIN(a,b)		((a) < (b) ? (a) : (b))
+#	define MAX(a,b)		((a) > (b) ? (a) : (b))
+	unsigned long range_start, range_end;
+
+	range_start = MIN(start, KERNEL_START);
+	range_end   = MIN(end, KERNEL_START);
+
+	/*
+	 * XXX This should not be necessary, but the bootmem allocator
+	 * is broken and fails to work correctly when the starting
+	 * address is not properly aligned.
+	 */
+	range_start = PAGE_ALIGN(range_start);
+
+	if (range_start < range_end)
+		free_bootmem(__pa(range_start), range_end - range_start);
+
+	range_start = MAX(start, KERNEL_END);
+	range_end   = MAX(end, KERNEL_END);
+
+	/*
+	 * XXX This should not be necessary, but the bootmem allocator
+	 * is broken and fails to work correctly when the starting
+	 * address is not properly aligned.
+	 */
+	range_start = PAGE_ALIGN(range_start);
+
+	if (range_start < range_end)
+		free_bootmem(__pa(range_start), range_end - range_start);
+
+	return 0;
+}
+
+void __init
+setup_arch (char **cmdline_p)
+{
+	unsigned long max_pfn, bootmap_start, bootmap_size;
+
+	/*
+	 * The secondary bootstrap loader passes us the boot
+	 * parameters at the beginning of the ZERO_PAGE, so let's
+	 * stash away those values before ZERO_PAGE gets cleared out.
+	 */
+	memcpy(&ia64_boot_param, (void *) ZERO_PAGE_ADDR, sizeof(ia64_boot_param));
+
+	efi_init();
+
+	max_pfn = 0;
+	efi_memmap_walk(find_max_pfn, &max_pfn);
+
+	/*
+	 * This is wrong, wrong, wrong.  Darn it, you'd think if they
+	 * change APIs, they'd do things for the better.  Grumble...
+	 */
+	bootmap_start = PAGE_ALIGN(__pa(&_end));
+	bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
+
+	efi_memmap_walk(free_available_memory, 0);
+
+	reserve_bootmem(bootmap_start, bootmap_size);
+#if 0
+	/* XXX fix me */
+	init_mm.start_code = (unsigned long) &_stext;
+	init_mm.end_code = (unsigned long) &_etext;
+	init_mm.end_data = (unsigned long) &_edata;
+	init_mm.brk = (unsigned long) &_end;
+
+	code_resource.start = virt_to_bus(&_text);
+	code_resource.end = virt_to_bus(&_etext) - 1;
+	data_resource.start = virt_to_bus(&_etext);
+	data_resource.end = virt_to_bus(&_edata) - 1;
+#endif
+
+	/* process SAL system table: */
+	ia64_sal_init(efi.sal_systab);
+
+	*cmdline_p = __va(ia64_boot_param.command_line);
+	strncpy(saved_command_line, *cmdline_p, sizeof(saved_command_line));
+	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';		/* for safety */
+
+	printk("args to kernel: %s\n", *cmdline_p);
+
+#ifndef CONFIG_SMP
+	cpu_init();
+	identify_cpu(&cpu_data[0]);
+#endif
+
+	if (efi.acpi) {
+		/* Parse the ACPI tables */
+		acpi_parse(efi.acpi);
+	}
+
+#ifdef CONFIG_IA64_GENERIC
+	machvec_init(acpi_get_sysname());
+#endif
+
+#ifdef CONFIG_VT
+# if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+# elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+# endif
+#endif
+	platform_setup(cmdline_p);
+}
+
+/*
+ * Display cpu info for all cpu's.
+ */
+int
+get_cpuinfo (char *buffer)
+{
+	char family[32], model[32], features[128], *cp, *p = buffer;
+	struct cpuinfo_ia64 *c;
+	unsigned long mask;
+
+	for (c = cpu_data; c < cpu_data + NR_CPUS; ++c) {
+		if (!(cpu_initialized & (1UL << (c - cpu_data))))
+			continue;
+
+		mask = c->features;
+
+		if (c->family == 7)
+			memcpy(family, "IA-64", 6);
+		else
+			sprintf(family, "%u", c->family);
+
+		switch (c->model) {
+		      case 0:	strcpy(model, "Itanium"); break;
+		      default:	sprintf(model, "%u", c->model); break;
+		}
+
+		/* build the feature string: */
+		memcpy(features, " standard", 10);
+		cp = features;
+		if (mask & 1) {
+			strcpy(cp, " branchlong");
+			cp = strchr(cp, '\0');
+			mask &= ~1UL;
+		}
+		if (mask)
+			sprintf(cp, " 0x%lx", mask);
+
+		p += sprintf(buffer,
+			     "CPU# %lu\n"
+			     "\tvendor     : %s\n"
+			     "\tfamily     : %s\n"
+			     "\tmodel      : %s\n"
+			     "\trevision   : %u\n"
+			     "\tarchrev    : %u\n"
+			     "\tfeatures   :%s\n"	/* don't change this---it _is_ right! */
+			     "\tcpu number : %lu\n"
+			     "\tcpu regs   : %u\n"
+			     "\tcpu MHz    : %lu.%06lu\n"
+			     "\titc MHz    : %lu.%06lu\n"
+			     "\tBogoMIPS   : %lu.%02lu\n\n",
+			     c - cpu_data, c->vendor, family, model, c->revision, c->archrev,
+			     features,
+			     c->ppn, c->number, c->proc_freq / 1000000, c->proc_freq % 1000000,
+			     c->itc_freq / 1000000, c->itc_freq % 1000000,
+			     loops_per_sec() / 500000, (loops_per_sec() / 5000) % 100);
+        }
+	return p - buffer;
+}
+
+void
+identify_cpu (struct cpuinfo_ia64 *c)
+{
+	union {
+		unsigned long bits[5];
+		struct {
+			/* id 0 & 1: */
+			char vendor[16];
+
+			/* id 2 */
+			u64 ppn;		/* processor serial number */
+
+			/* id 3: */
+			unsigned number		:  8;
+			unsigned revision	:  8;
+			unsigned model		:  8;
+			unsigned family		:  8;
+			unsigned archrev	:  8;
+			unsigned reserved	: 24;
+
+			/* id 4: */
+			u64 features;
+		} field;
+	} cpuid;
+	int i;
+
+	for (i = 0; i < 5; ++i) {
+		cpuid.bits[i] = ia64_get_cpuid(i);
+	}
+
+#ifdef CONFIG_SMP
+	/*
+	 * XXX Instead of copying the ITC info from the bootstrap
+	 * processor, ia64_init_itm() should be done per CPU.  That
+	 * should get you the right info.  --davidm 1/24/00
+	 */
+	if (c != &cpu_data[bootstrap_processor]) {
+		memset(c, 0, sizeof(struct cpuinfo_ia64));
+		c->proc_freq = cpu_data[bootstrap_processor].proc_freq;
+		c->itc_freq = cpu_data[bootstrap_processor].itc_freq;
+		c->cyc_per_usec = cpu_data[bootstrap_processor].cyc_per_usec;
+		c->usec_per_cyc = cpu_data[bootstrap_processor].usec_per_cyc;
+	}
+#else
+	memset(c, 0, sizeof(struct cpuinfo_ia64));
+#endif
+
+	memcpy(c->vendor, cpuid.field.vendor, 16);
+#ifdef CONFIG_IA64_SOFTSDV_HACKS
+        /* BUG: SoftSDV doesn't support the cpuid registers. */
+	if (c->vendor[0] == '\0') 
+		memcpy(c->vendor, "Intel", 6);
+#endif                                   
+	c->ppn = cpuid.field.ppn;
+	c->number = cpuid.field.number;
+	c->revision = cpuid.field.revision;
+	c->model = cpuid.field.model;
+	c->family = cpuid.field.family;
+	c->archrev = cpuid.field.archrev;
+	c->features = cpuid.field.features;
+#ifdef CONFIG_SMP
+	c->loops_per_sec = loops_per_sec;
+#endif
+}
+
+/*
+ * cpu_init() initializes state that is per-CPU.  This function acts
+ * as a 'CPU state barrier', nothing should get across.
+ */
+void
+cpu_init (void)
+{
+	int nr = smp_processor_id();
+
+	/* Clear the stack memory reserved for pt_regs: */
+	memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));
+
+	/*
+	 * Initialize default control register to defer speculative
+	 * faults.  On a speculative load, we want to defer access
+	 * right, key miss, and key permission faults.  We currently
+	 * do NOT defer TLB misses, page-not-present, access bit, or
+	 * debug faults but kernel code should not rely on any
+	 * particular setting of these bits.
+	 */
+	ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_PP);
+	ia64_set_fpu_owner(0);		/* initialize ar.k5 */
+
+	if (test_and_set_bit(nr, &cpu_initialized)) {
+		printk("CPU#%d already initialized!\n", nr);
+		machine_halt();
+	}
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/signal.c linux/arch/ia64/kernel/signal.c
--- v2.3.42/linux/arch/ia64/kernel/signal.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/signal.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,537 @@
+/*
+ * Architecture-specific signal handling support.
+ *
+ * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Derived from i386 and Alpha versions.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/wait.h>
+
+#include <asm/ia32.h>
+#include <asm/uaccess.h>
+#include <asm/rse.h>
+#include <asm/sigcontext.h>
+
+#define DEBUG_SIG	0
+#define STACK_ALIGN	16		/* minimal alignment for stack pointer */
+#define _BLOCKABLE	(~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+#if _NSIG_WORDS > 1
+# define PUT_SIGSET(k,u)	__copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t))
+# define GET_SIGSET(k,u)	__copy_from_user((k)->sig, (u)->sig, sizeof(sigset_t))
+#else
+# define PUT_SIGSET(k,u)	__put_user((k)->sig[0], &(u)->sig[0])
+# define GET_SIGSET(k,u)	__get_user((k)->sig[0], &(u)->sig[0])
+#endif
+
+struct sigframe {
+	struct siginfo info;
+	struct sigcontext sc;
+};
+
+extern long sys_wait4 (int, int *, int, struct rusage *);
+extern long ia64_do_signal (sigset_t *, struct pt_regs *, long);	/* forward decl */
+
+long
+ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct pt_regs *pt)
+{
+	sigset_t oldset, set;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+	if (GET_SIGSET(&set, uset))
+		return -EFAULT;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+
+	spin_lock_irq(&current->sigmask_lock);
+	{
+		oldset = current->blocked;
+		current->blocked = set;
+		recalc_sigpending(current);
+	}
+	spin_unlock_irq(&current->sigmask_lock);
+
+	/*
+	 * The return below usually returns to the signal handler.  We need to
+	 * pre-set the correct error code here to ensure that the right values
+	 * get saved in sigcontext by ia64_do_signal.
+	 */
+	pt->r8 = EINTR;
+	pt->r10 = -1;
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (ia64_do_signal(&oldset, pt, 1))
+			return -EINTR;
+	}
+}
+
+asmlinkage long
+sys_sigaltstack (const stack_t *uss, stack_t *uoss, long arg2, long arg3, long arg4,
+		 long arg5, long arg6, long arg7, long stack)
+{
+	struct pt_regs *pt = (struct pt_regs *) &stack;
+
+	return do_sigaltstack(uss, uoss, pt->r12);
+}
+
+static long
+restore_sigcontext (struct sigcontext *sc, struct pt_regs *pt)
+{
+	struct switch_stack *sw = (struct switch_stack *) pt - 1;
+	unsigned long ip, flags, nat, um;
+	long err;
+
+	/* restore scratch that always needs gets updated during signal delivery: */
+	err = __get_user(flags, &sc->sc_flags);
+
+	err |= __get_user(nat, &sc->sc_nat);
+	err |= __get_user(ip, &sc->sc_ip);			/* instruction pointer */
+	err |= __get_user(pt->ar_fpsr, &sc->sc_ar_fpsr);
+	err |= __get_user(pt->ar_pfs, &sc->sc_ar_pfs);
+	err |= __get_user(um, &sc->sc_um);			/* user mask */
+	err |= __get_user(pt->ar_rsc, &sc->sc_ar_rsc);
+	err |= __get_user(pt->ar_ccv, &sc->sc_ar_ccv);
+	err |= __get_user(pt->ar_unat, &sc->sc_ar_unat);
+	err |= __get_user(pt->pr, &sc->sc_pr);			/* predicates */
+	err |= __get_user(pt->b0, &sc->sc_br[0]);		/* b0 (rp) */
+	err |= __get_user(pt->b6, &sc->sc_br[6]);
+	err |= __copy_from_user(&pt->r1, &sc->sc_gr[1], 3*8);	/* r1-r3 */
+	err |= __copy_from_user(&pt->r8, &sc->sc_gr[8], 4*8);	/* r8-r11 */
+	err |= __copy_from_user(&pt->r12, &sc->sc_gr[12], 4*8);	/* r12-r15 */
+	err |= __copy_from_user(&pt->r16, &sc->sc_gr[16], 16*8);	/* r16-r31 */
+
+	/* establish new instruction pointer: */
+	pt->cr_iip = ip & ~0x3UL;
+	ia64_psr(pt)->ri = ip & 0x3;
+	pt->cr_ipsr = (pt->cr_ipsr & ~IA64_PSR_UM) | (um & IA64_PSR_UM);
+
+	ia64_put_nat_bits (pt, sw, nat);	/* restore the original scratch NaT bits */
+
+	if (flags & IA64_SC_FLAG_FPH_VALID) {
+		struct task_struct *fpu_owner = ia64_get_fpu_owner();
+
+		__copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
+		if (fpu_owner == current) {
+			__ia64_load_fpu(current->thread.fph);
+		}
+	}
+	return err;
+}
+
+/*
+ * When we get here, ((struct switch_stack *) pt - 1) is a
+ * switch_stack frame that has no defined value.  Upon return, we
+ * expect sw->caller_unat to contain the new unat value.  The reason
+ * we use a full switch_stack frame is so everything is symmetric
+ * with ia64_do_signal().
+ */
+long
+ia64_rt_sigreturn (struct pt_regs *pt)
+{
+	extern char ia64_strace_leave_kernel, ia64_leave_kernel;
+	struct sigcontext *sc;
+	struct siginfo si;
+	sigset_t set;
+	long retval;
+
+	sc = &((struct sigframe *) (pt->r12 + 16))->sc;
+
+	/*
+	 * When we return to the previously executing context, r8 and
+	 * r10 have already been setup the way we want them.  Indeed,
+	 * if the signal wasn't delivered while in a system call, we
+	 * must not touch r8 or r10 as otherwise user-level stat could
+	 * be corrupted.
+	 */
+	retval = (long) &ia64_leave_kernel | 1;
+	if ((current->flags & PF_TRACESYS)
+	    && (sc->sc_flags & IA64_SC_FLAG_IN_SYSCALL))
+		retval = (long) &ia64_strace_leave_kernel;
+
+	if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
+		goto give_sigsegv;
+
+	if (GET_SIGSET(&set, &sc->sc_mask))
+		goto give_sigsegv;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = set;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	if (restore_sigcontext(sc, pt))
+		goto give_sigsegv;
+
+#if DEBUG_SIG
+	printk("SIG return (%s:%d): sp=%lx ip=%lx\n",
+	       current->comm, current->pid, pt->r12, pt->cr_iip);
+#endif
+	/*
+	 * It is more difficult to avoid calling this function than to
+	 * call it and ignore errors.
+	 */
+	do_sigaltstack(&sc->sc_stack, 0, pt->r12);
+	return retval;
+
+  give_sigsegv:
+	si.si_signo = SIGSEGV;
+	si.si_errno = 0;
+	si.si_code = SI_KERNEL;
+	si.si_pid = current->pid;
+	si.si_uid = current->uid;
+	si.si_addr = sc;
+	force_sig_info(SIGSEGV, &si, current);
+	return retval;
+}
+
+/*
+ * This does just the minimum required setup of sigcontext.
+ * Specifically, it only installs data that is either not knowable at
+ * the user-level or that gets modified before execution in the
+ * trampoline starts.  Everything else is done at the user-level.
+ */
+static long
+setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct pt_regs *pt)
+{
+	struct switch_stack *sw = (struct switch_stack *) pt - 1;
+	struct task_struct *fpu_owner = ia64_get_fpu_owner();
+	unsigned long flags = 0, ifs, nat;
+	long err;
+
+	ifs = pt->cr_ifs;
+
+	if (on_sig_stack((unsigned long) sc))
+		flags |= IA64_SC_FLAG_ONSTACK;
+	if ((ifs & (1UL << 63)) == 0) {
+		/* if cr_ifs isn't valid, we got here through a syscall */
+		flags |= IA64_SC_FLAG_IN_SYSCALL;
+	}
+	if ((fpu_owner == current) || (current->thread.flags & IA64_THREAD_FPH_VALID)) {
+		flags |= IA64_SC_FLAG_FPH_VALID;
+		if (fpu_owner == current) {
+			__ia64_save_fpu(current->thread.fph);
+		}
+		__copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16);
+	}
+
+	/*
+	 * Note: sw->ar_unat is UNDEFINED unless the process is being
+	 * PTRACED.  However, this is OK because the NaT bits of the
+	 * preserved registers (r4-r7) are never being looked at by
+	 * the signal handler (register r4-r7 are used instead).
+	 */
+	nat = ia64_get_nat_bits(pt, sw);
+
+	err  = __put_user(flags, &sc->sc_flags);
+	err |= __put_user(nat, &sc->sc_nat);
+	err |= PUT_SIGSET(mask, &sc->sc_mask);
+	err |= __put_user(pt->cr_ipsr & IA64_PSR_UM, &sc->sc_um);
+	err |= __put_user(pt->ar_rsc, &sc->sc_ar_rsc);
+	err |= __put_user(pt->ar_ccv, &sc->sc_ar_ccv);
+	err |= __put_user(pt->ar_unat, &sc->sc_ar_unat);		/* ar.unat */
+	err |= __put_user(pt->ar_fpsr, &sc->sc_ar_fpsr);		/* ar.fpsr */
+	err |= __put_user(pt->ar_pfs, &sc->sc_ar_pfs);
+	err |= __put_user(pt->pr, &sc->sc_pr);				/* predicates */
+	err |= __put_user(pt->b0, &sc->sc_br[0]);			/* b0 (rp) */
+	err |= __put_user(pt->b6, &sc->sc_br[6]);			/* b6 */
+	err |= __put_user(pt->b7, &sc->sc_br[7]);			/* b7 */
+
+	err |= __copy_to_user(&sc->sc_gr[1], &pt->r1, 3*8);		/* r1-r3 */
+	err |= __copy_to_user(&sc->sc_gr[8], &pt->r8, 4*8);		/* r8-r11 */
+	err |= __copy_to_user(&sc->sc_gr[12], &pt->r12, 4*8);	/* r12-r15 */
+	err |= __copy_to_user(&sc->sc_gr[16], &pt->r16, 16*8);	/* r16-r31 */
+
+	err |= __put_user(pt->cr_iip + ia64_psr(pt)->ri, &sc->sc_ip);
+	err |= __put_user(pt->r12, &sc->sc_gr[12]);			/* r12 */
+	return err;
+}
+
+static long
+setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *pt)
+{
+	struct switch_stack *sw = (struct switch_stack *) pt - 1;
+	extern char ia64_sigtramp[], __start_gate_section[];
+	unsigned long tramp_addr, new_rbs = 0;
+	struct sigframe *frame;
+	struct siginfo si;
+	long err;
+
+	frame = (void *) pt->r12;
+	tramp_addr = GATE_ADDR + (ia64_sigtramp - __start_gate_section);
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack((unsigned long) frame)) {
+		new_rbs  = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
+		frame = (void *) ((current->sas_ss_sp + current->sas_ss_size)
+				  & ~(STACK_ALIGN - 1));
+	}
+	frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	err  = __copy_to_user(&frame->info, info, sizeof(siginfo_t));
+
+	err |= __put_user(current->sas_ss_sp, &frame->sc.sc_stack.ss_sp);
+	err |= __put_user(current->sas_ss_size, &frame->sc.sc_stack.ss_size);
+	err |= __put_user(sas_ss_flags(pt->r12), &frame->sc.sc_stack.ss_flags);
+	err |= setup_sigcontext(&frame->sc, set, pt);
+
+	if (err)
+		goto give_sigsegv;
+
+	pt->r12 = (unsigned long) frame - 16;		/* new stack pointer */
+	pt->r2  = sig;					/* signal number */
+	pt->r3  = (unsigned long) ka->sa.sa_handler;	/* addr. of handler's proc. descriptor */
+	pt->r15 = new_rbs;
+	pt->ar_fpsr = FPSR_DEFAULT;			/* reset fpsr for signal handler */
+	pt->cr_iip = tramp_addr;
+	ia64_psr(pt)->ri = 0;				/* start executing in first slot */
+
+	/*
+	 * Note: this affects only the NaT bits of the scratch regs
+	 * (the ones saved in pt_regs, which is exactly what we want.
+	 * The NaT bits for the preserved regs (r4-r7) are in
+	 * sw->ar_unat iff this process is being PTRACED.
+	 */
+	sw->caller_unat = 0;	/* ensure NaT bits of at least r2, r3, r12, and r15 are clear */
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%lx\n",
+	       current->comm, current->pid, sig, pt->r12, pt->cr_iip, pt->r3);
+#endif
+	return 1;
+
+  give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	si.si_signo = SIGSEGV;
+	si.si_errno = 0;
+	si.si_code = SI_KERNEL;
+	si.si_pid = current->pid;
+	si.si_uid = current->uid;
+	si.si_addr = frame;
+	force_sig_info(SIGSEGV, &si, current);
+	return 0;
+}
+
+static long
+handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset,
+	       struct pt_regs *pt)
+{
+#ifdef CONFIG_IA32_SUPPORT
+	if (IS_IA32_PROCESS(pt)) {
+		/* send signal to IA-32 process */
+		if (!ia32_setup_frame1(sig, ka, info, oldset, pt))
+			return 0;
+	} else
+#endif
+	/* send signal to IA-64 process */
+	if (!setup_frame(sig, ka, info, oldset, pt))
+		return 0;
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+
+	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+		spin_lock_irq(&current->sigmask_lock);
+		sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+		sigaddset(&current->blocked, sig);
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
+	}
+	return 1;
+}
+
+/*
+ * When we get here, `pt' points to struct pt_regs and ((struct
+ * switch_stack *) pt - 1) points to a switch stack structure.
+ * HOWEVER, in the normal case, the ONLY value valid in the
+ * switch_stack is the caller_unat field.  The entire switch_stack is
+ * valid ONLY if current->flags has PF_PTRACED set.
+ *
+ * Note that `init' is a special process: it doesn't get signals it
+ * doesn't want to handle.  Thus you cannot kill init even with a
+ * SIGKILL even by mistake.
+ *
+ * Note that we go through the signals twice: once to check the
+ * signals that the kernel can handle, and then we build all the
+ * user-level signal handling stack-frames in one go after that.
+ */
+long
+ia64_do_signal (sigset_t *oldset, struct pt_regs *pt, long in_syscall)
+{
+	struct k_sigaction *ka;
+	siginfo_t info;
+	long restart = in_syscall;
+
+	/*
+	 * In the ia64_leave_kernel code path, we want the common case
+	 * to go fast, which is why we may in certain cases get here
+	 * from kernel mode. Just return without doing anything if so.
+	 */
+	if (!user_mode(pt))
+		return 0;
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	if (pt->r10 != -1) {
+		/*
+		 * A system calls has to be restarted only if one of
+		 * the error codes ERESTARTNOHAND, ERESTARTSYS, or
+		 * ERESTARTNOINTR is returned.  If r10 isn't -1 then
+		 * r8 doesn't hold an error code and we don't need to
+		 * restart the syscall, so we set in_syscall to zero.
+		 */
+		restart = 0;
+	}
+
+	for (;;) {
+		unsigned long signr;
+
+		spin_lock_irq(&current->sigmask_lock);
+		signr = dequeue_signal(&current->blocked, &info);
+		spin_unlock_irq(&current->sigmask_lock);
+
+		if (!signr)
+			break;
+
+		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+			/* Let the debugger run.  */
+			current->exit_code = signr;
+			set_current_state(TASK_STOPPED);
+			notify_parent(current, SIGCHLD);
+			schedule();
+			signr = current->exit_code;
+
+			/* We're back.  Did the debugger cancel the sig?  */
+			if (!signr)
+				continue;
+			current->exit_code = 0;
+
+			/* The debugger continued.  Ignore SIGSTOP.  */
+			if (signr == SIGSTOP)
+				continue;
+
+			/* Update the siginfo structure.  Is this good?  */
+			if (signr != info.si_signo) {
+				info.si_signo = signr;
+				info.si_errno = 0;
+				info.si_code = SI_USER;
+				info.si_pid = current->p_pptr->pid;
+				info.si_uid = current->p_pptr->uid;
+			}
+
+			/* If the (new) signal is now blocked, requeue it.  */
+			if (sigismember(&current->blocked, signr)) {
+				send_sig_info(signr, &info, current);
+				continue;
+			}
+		}
+
+		ka = &current->sig->action[signr - 1];
+		if (ka->sa.sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
+				continue;
+			/* Check for SIGCHLD: it's special.  */
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+				/* nothing */;
+			continue;
+		}
+
+		if (ka->sa.sa_handler == SIG_DFL) {
+			int exit_code = signr;
+
+			/* Init gets no signals it doesn't want.  */
+			if (current->pid == 1)
+				continue;
+
+			switch (signr) {
+			      case SIGCONT: case SIGCHLD: case SIGWINCH:
+				continue;
+
+			      case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if (is_orphaned_pgrp(current->pgrp))
+					continue;
+				/* FALLTHRU */
+
+			      case SIGSTOP:
+				set_current_state(TASK_STOPPED);
+				current->exit_code = signr;
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags
+				      & SA_NOCLDSTOP))
+					notify_parent(current, SIGCHLD);
+				schedule();
+				continue;
+
+			      case SIGQUIT: case SIGILL: case SIGTRAP:
+			      case SIGABRT: case SIGFPE: case SIGSEGV:
+			      case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
+				if (do_coredump(signr, pt))
+					exit_code |= 0x80;
+				/* FALLTHRU */
+
+			      default:
+				lock_kernel();
+				sigaddset(&current->signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
+				/* NOTREACHED */
+			}
+		}
+
+		if (restart) {
+			switch (pt->r8) {
+			      case ERESTARTSYS:
+				if ((ka->sa.sa_flags & SA_RESTART) == 0) {
+			      case ERESTARTNOHAND:
+					pt->r8 = EINTR;
+					/* note: pt->r10 is already -1 */
+					break;
+				}
+			      case ERESTARTNOINTR:
+				ia64_decrement_ip(pt);
+			}
+		}
+
+		/* Whee!  Actually deliver the signal.  If the
+		   delivery failed, we need to continue to iterate in
+		   this loop so we can deliver the SIGSEGV... */
+		if (handle_signal(signr, ka, &info, oldset, pt))
+			return 1;
+	}
+
+	/* Did we come from a system call? */
+	if (restart) {
+		/* Restart the system call - no handlers present */
+		if (pt->r8 == ERESTARTNOHAND ||
+		    pt->r8 == ERESTARTSYS ||
+		    pt->r8 == ERESTARTNOINTR) {
+			/*
+			 * Note: the syscall number is in r15 which is
+			 * saved in pt_regs so all we need to do here
+			 * is adjust ip so that the "break"
+			 * instruction gets re-executed.
+			 */
+			ia64_decrement_ip(pt);
+		}
+	}
+	return 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/smp.c linux/arch/ia64/kernel/smp.c
--- v2.3.42/linux/arch/ia64/kernel/smp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/smp.c	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,777 @@
+/*
+ * SMP Support
+ *
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * 
+ * Lots of stuff stolen from arch/alpha/kernel/smp.c
+ *
+ *  99/10/05 davidm	Update to bring it in sync with new command-line processing scheme.
+ */
+#define __KERNEL_SYSCALLS__
+
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+#include <asm/current.h>
+#include <asm/delay.h>
+
+#ifdef CONFIG_KDB
+#include <linux/kdb.h>
+void smp_kdb_interrupt (struct pt_regs* regs);
+void kdb_global(int cpuid);
+extern unsigned long smp_kdb_wait;
+extern int kdb_new_cpu;
+#endif
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+#include <asm/unistd.h>
+
+extern int cpu_idle(void * unused);
+extern void _start(void);
+
+extern int cpu_now_booting;                          /* Used by head.S to find idle task */
+extern unsigned long cpu_initialized;                /* Bitmap of available cpu's */
+extern struct cpuinfo_ia64 cpu_data[NR_CPUS];        /* Duh... */
+
+spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+
+#ifdef CONFIG_KDB
+unsigned long cpu_online_map = 1;
+#endif
+
+volatile int cpu_number_map[NR_CPUS] = { -1, };      /* SAPIC ID -> Logical ID */
+volatile int __cpu_logical_map[NR_CPUS] = { -1, };   /* logical ID -> SAPIC ID */
+int smp_num_cpus = 1;		
+int bootstrap_processor = -1;                        /* SAPIC ID of BSP */
+int smp_threads_ready = 0;	                     /* Set when the idlers are all forked */
+unsigned long ipi_base_addr = IPI_DEFAULT_BASE_ADDR; /* Base addr of IPI table */
+cycles_t cacheflush_time = 0;
+unsigned long ap_wakeup_vector = -1;                 /* External Int to use to wakeup AP's */
+static int max_cpus = -1;	                     /* Command line */
+static unsigned long ipi_op[NR_CPUS];
+struct smp_call_struct {
+	void (*func) (void *info);
+	void *info;
+	long wait;
+	atomic_t unstarted_count;
+	atomic_t unfinished_count;
+};
+static struct smp_call_struct *smp_call_function_data;
+
+#ifdef CONFIG_KDB
+unsigned long smp_kdb_wait = 0;                         /* Bitmask of waiters */
+#endif
+
+#ifdef	CONFIG_ITANIUM_ASTEP_SPECIFIC
+extern spinlock_t ivr_read_lock;
+#endif
+
+int use_xtp = 0;		/* XXX */
+
+#define IPI_RESCHEDULE	        0
+#define IPI_CALL_FUNC	        1
+#define IPI_CPU_STOP	        2
+#define IPI_KDB_INTERRUPT	4
+
+/*
+ *	Setup routine for controlling SMP activation
+ *
+ *	Command-line option of "nosmp" or "maxcpus=0" will disable SMP
+ *      activation entirely (the MPS table probe still happens, though).
+ *
+ *	Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
+ *	greater than 0, limits the maximum number of CPUs activated in
+ *	SMP mode to <NUM>.
+ */
+
+static int __init nosmp(char *str)
+{
+	max_cpus = 0;
+	return 1;
+}
+
+__setup("nosmp", nosmp);
+
+static int __init maxcpus(char *str)
+{
+	get_option(&str, &max_cpus);
+	return 1;
+}
+
+__setup("maxcpus=", maxcpus);
+
+/*
+ * Yoink this CPU from the runnable list... 
+ */
+void
+halt_processor(void) 
+{
+        clear_bit(smp_processor_id(), &cpu_initialized);
+	max_xtp();
+	__cli();
+        for (;;)
+		;
+
+}
+
+void
+handle_IPI(int irq, void *dev_id, struct pt_regs *regs) 
+{
+	int this_cpu = smp_processor_id();
+	unsigned long *pending_ipis = &ipi_op[this_cpu];
+	unsigned long ops;
+
+	/* Count this now; we may make a call that never returns. */
+	cpu_data[this_cpu].ipi_count++;
+
+	mb();	/* Order interrupt and bit testing. */
+	while ((ops = xchg(pending_ipis, 0)) != 0) {
+	  mb();	/* Order bit clearing and data access. */
+	  do {
+		unsigned long which;
+
+		which = ffz(~ops);
+		ops &= ~(1 << which);
+		
+		switch (which) {
+		case IPI_RESCHEDULE:
+			/* 
+			 * Reschedule callback.  Everything to be done is done by the 
+			 * interrupt return path.  
+			 */
+			break;
+			
+		case IPI_CALL_FUNC: 
+			{
+				struct smp_call_struct *data;
+				void (*func)(void *info);
+				void *info;
+				int wait;
+
+				data = smp_call_function_data;
+				func = data->func;
+				info = data->info;
+				wait = data->wait;
+
+				mb();
+				atomic_dec (&data->unstarted_count);
+
+				/* At this point the structure may be gone unless wait is true.  */
+				(*func)(info);
+
+				/* Notify the sending CPU that the task is done.  */
+				mb();
+				if (wait) 
+					atomic_dec (&data->unfinished_count);
+			}
+			break;
+
+		case IPI_CPU_STOP:
+			halt_processor();
+			break;
+
+#ifdef CONFIG_KDB
+		case IPI_KDB_INTERRUPT:
+			smp_kdb_interrupt(regs);
+			break;
+#endif
+
+		default:
+			printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
+			break;
+		} /* Switch */
+	  } while (ops);
+
+	  mb();	/* Order data access and bit testing. */
+	}
+}
+
+static inline void
+send_IPI(int dest_cpu, unsigned char vector)
+{
+	unsigned long ipi_addr;
+	unsigned long ipi_data;
+#ifdef	CONFIG_ITANIUM_ASTEP_SPECIFIC
+	unsigned long flags;
+#endif
+
+	ipi_data = vector;
+	ipi_addr = ipi_base_addr | ((dest_cpu << 8) << 4); /* 16-bit SAPIC ID's; assume CPU bus 0 */
+	mb();
+
+#ifdef	CONFIG_ITANIUM_ASTEP_SPECIFIC
+	/*
+	 * Disable IVR reads
+	 */
+	spin_lock_irqsave(&ivr_read_lock, flags);
+	writeq(ipi_data, ipi_addr);
+	spin_unlock_irqrestore(&ivr_read_lock, flags);
+#else
+ 	writeq(ipi_data, ipi_addr);
+#endif	/* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+}
+
+static inline void
+send_IPI_single(int dest_cpu, int op) 
+{
+	
+	if (dest_cpu == -1) 
+                return;
+        
+        ipi_op[dest_cpu] |= (1 << op);
+	send_IPI(dest_cpu, IPI_IRQ);
+}
+
+static inline void
+send_IPI_allbutself(int op)
+{
+	int i;
+	int cpu_id = 0;
+	
+	for (i = 0; i < smp_num_cpus; i++) {
+		cpu_id = __cpu_logical_map[i];
+		if (cpu_id != smp_processor_id())
+			send_IPI_single(cpu_id, op);
+	}
+}
+
+static inline void
+send_IPI_all(int op)
+{
+	int i;
+
+	for (i = 0; i < smp_num_cpus; i++)
+		send_IPI_single(__cpu_logical_map[i], op);
+}
+
+static inline void
+send_IPI_self(int op)
+{
+	send_IPI_single(smp_processor_id(), op);
+}
+
+void
+smp_send_reschedule(int cpu)
+{
+	send_IPI_single(cpu, IPI_RESCHEDULE);
+}
+
+void
+smp_send_stop(void)
+{
+	send_IPI_allbutself(IPI_CPU_STOP);
+}
+
+/*
+ * Run a function on all other CPUs.
+ *  <func>	The function to run. This must be fast and non-blocking.
+ *  <info>	An arbitrary pointer to pass to the function.
+ *  <retry>	If true, keep retrying until ready.
+ *  <wait>	If true, wait until function has completed on other CPUs.
+ *  [RETURNS]   0 on success, else a negative status code.
+ *
+ * Does not return until remote CPUs are nearly ready to execute <func>
+ * or are or have executed.
+ */
+
+int
+smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
+{
+	struct smp_call_struct data;
+	long timeout;
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+	
+	data.func = func;
+	data.info = info;
+	data.wait = wait;
+	atomic_set(&data.unstarted_count, smp_num_cpus - 1);
+	atomic_set(&data.unfinished_count, smp_num_cpus - 1);
+
+	if (retry) {
+		while (1) {
+			if (smp_call_function_data) {
+				schedule ();  /*  Give a mate a go  */
+				continue;
+			}
+			spin_lock (&lock);
+			if (smp_call_function_data) {
+				spin_unlock (&lock);  /*  Bad luck  */
+				continue;
+			}
+			/*  Mine, all mine!  */
+			break;
+		}
+	}
+	else {
+		if (smp_call_function_data) 
+			return -EBUSY;
+		spin_lock (&lock);
+		if (smp_call_function_data) {
+			spin_unlock (&lock);
+			return -EBUSY;
+		}
+	}
+
+	smp_call_function_data = &data;
+	spin_unlock (&lock);
+	data.func = func;
+	data.info = info;
+	atomic_set (&data.unstarted_count, smp_num_cpus - 1);
+	data.wait = wait;
+	if (wait) 
+		atomic_set (&data.unfinished_count, smp_num_cpus - 1);
+	
+	/*  Send a message to all other CPUs and wait for them to respond  */
+	send_IPI_allbutself(IPI_CALL_FUNC);
+
+	/*  Wait for response  */
+	timeout = jiffies + HZ;
+	while ( (atomic_read (&data.unstarted_count) > 0) &&
+		time_before (jiffies, timeout) )
+		barrier ();
+	if (atomic_read (&data.unstarted_count) > 0) {
+		smp_call_function_data = NULL;
+		return -ETIMEDOUT;
+	}
+	if (wait)
+		while (atomic_read (&data.unfinished_count) > 0)
+			barrier ();
+	smp_call_function_data = NULL;
+	return 0;
+}
+
+/*
+ * Flush all other CPU's tlb and then mine.  Do this with smp_call_function() as we
+ * want to ensure all TLB's flushed before proceeding.
+ *
+ * XXX: Is it OK to use the same ptc.e info on all cpus?
+ */
+void
+smp_flush_tlb_all(void)
+{
+	smp_call_function((void (*)(void *))__flush_tlb_all, NULL, 1, 1);
+	__flush_tlb_all();
+}
+
+/*
+ * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
+ */
+static inline void __init
+smp_setup_percpu_timer(int cpuid)
+{
+        cpu_data[cpuid].prof_counter = 1;
+        cpu_data[cpuid].prof_multiplier = 1;
+}
+
+void 
+smp_do_timer(struct pt_regs *regs)
+{
+        int cpu = smp_processor_id();
+        int user = user_mode(regs);
+	struct cpuinfo_ia64 *data = &cpu_data[cpu];
+
+	extern void update_one_process(struct task_struct *, unsigned long, unsigned long, 
+				       unsigned long, int);
+        if (!--data->prof_counter) {
+		irq_enter(cpu, TIMER_IRQ);
+
+		update_one_process(current, 1, user, !user, cpu);
+		if (current->pid) { 
+			if (--current->counter < 0) {
+				current->counter = 0;
+				current->need_resched = 1;
+			}
+
+			if (user) {
+				if (current->priority < DEF_PRIORITY) {
+					kstat.cpu_nice++;
+					kstat.per_cpu_nice[cpu]++;
+				} else {
+					kstat.cpu_user++;
+					kstat.per_cpu_user[cpu]++;
+				}
+			} else {
+				kstat.cpu_system++;
+				kstat.per_cpu_system[cpu]++;
+			}
+		} 
+		
+		data->prof_counter = data->prof_multiplier;
+		irq_exit(cpu, TIMER_IRQ);
+	}
+}
+
+
+/*
+ * Called by both boot and secondaries to move global data into
+ * per-processor storage.
+ */
+static inline void __init
+smp_store_cpu_info(int cpuid)
+{
+	struct cpuinfo_ia64 *c = &cpu_data[cpuid];
+
+	identify_cpu(c);
+}
+
+/* 
+ * SAL shoves the AP's here when we start them.  Physical mode, no kernel TR, 
+ * no RRs set, better than even chance that psr is bogus.  Fix all that and 
+ * call _start.  In effect, pretend to be lilo.
+ *
+ * Stolen from lilo_start.c.  Thanks David! 
+ */
+void
+start_ap(void)
+{
+	unsigned long flags;
+
+	/*
+	 * Install a translation register that identity maps the
+	 * kernel's 256MB page(s).
+	 */
+	ia64_clear_ic(flags);
+	ia64_set_rr(          0, (0x1000 << 8) | (_PAGE_SIZE_1M << 2));
+	ia64_set_rr(PAGE_OFFSET, (ia64_rid(0, PAGE_OFFSET) << 8) | (_PAGE_SIZE_256M << 2));
+	ia64_itr(0x3, 1, PAGE_OFFSET,
+		 pte_val(mk_pte_phys(0, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))),
+		 _PAGE_SIZE_256M);
+
+	flags = (IA64_PSR_IT | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_DFH | 
+		 IA64_PSR_BN);
+	
+	asm volatile ("movl r8 = 1f\n"
+		      ";;\n"
+		      "mov cr.ipsr=%0\n"
+		      "mov cr.iip=r8\n" 
+		      "mov cr.ifs=r0\n"
+		      ";;\n"
+		      "rfi;;"
+		      "1:\n"
+		      "movl r1 = __gp" :: "r"(flags) : "r8");
+	_start();
+}
+
+
+/*
+ * AP's start using C here.
+ */
+void __init
+smp_callin(void) 
+{
+	extern void ia64_rid_init(void);
+	extern void ia64_init_itm(void);
+	extern void ia64_cpu_local_tick(void);
+
+	ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_PP);
+	ia64_set_fpu_owner(0);	       
+	ia64_rid_init();		/* initialize region ids */
+
+	cpu_init();
+	__flush_tlb_all();
+
+	smp_store_cpu_info(smp_processor_id());
+	smp_setup_percpu_timer(smp_processor_id());
+
+	while (!smp_threads_ready) 
+		mb();
+
+	normal_xtp();
+
+	/* setup the CPU local timer tick */
+	ia64_cpu_local_tick();
+
+	/* Disable all local interrupts */
+	ia64_set_lrr0(0, 1);	
+	ia64_set_lrr1(0, 1);	
+
+	__sti();		/* Interrupts have been off till now. */
+	cpu_idle(NULL);
+}
+
+/*
+ * Create the idle task for a new AP.  DO NOT use kernel_thread() because
+ * that could end up calling schedule() in the ia64_leave_kernel exit
+ * path in which case the new idle task could get scheduled before we
+ * had a chance to remove it from the run-queue...
+ */
+static int __init 
+fork_by_hand(void)
+{
+	/*
+	 * Don't care about the usp and regs settings since we'll never
+	 * reschedule the forked task.
+	 */
+	return do_fork(CLONE_VM|CLONE_PID, 0, 0);
+}
+
+/*
+ * Bring one cpu online.
+ *
+ * NB: cpuid is the CPU BUS-LOCAL ID, not the entire SAPIC ID.  See asm/smp.h.
+ */
+static int __init
+smp_boot_one_cpu(int cpuid, int cpunum)
+{
+	struct task_struct *idle;
+	long timeout;
+
+	/* 
+	 * Create an idle task for this CPU.  Note that the address we
+	 * give to kernel_thread is irrelevant -- it's going to start
+	 * where OS_BOOT_RENDEVZ vector in SAL says to start.  But
+	 * this gets all the other task-y sort of data structures set
+	 * up like we wish.   We need to pull the just created idle task 
+	 * off the run queue and stuff it into the init_tasks[] array.  
+	 * Sheesh . . .
+	 */
+	if (fork_by_hand() < 0) 
+		panic("failed fork for CPU %d", cpuid);
+	/*
+	 * We remove it from the pidhash and the runqueue
+	 * once we got the process:
+	 */
+	idle = init_task.prev_task;
+	if (!idle)
+		panic("No idle process for CPU %d", cpuid);
+	init_tasks[cpunum] = idle;
+	del_from_runqueue(idle);
+        unhash_process(idle);
+
+	/* Schedule the first task manually.  */
+	idle->processor = cpuid;
+	idle->has_cpu = 1;
+
+	/* Let _start know what logical CPU we're booting (offset into init_tasks[] */
+	cpu_now_booting = cpunum;
+	
+	/* Kick the AP in the butt */
+	send_IPI(cpuid, ap_wakeup_vector);
+	ia64_srlz_i();
+	mb();
+
+	/* 
+	 * OK, wait a bit for that CPU to finish staggering about.  smp_callin() will
+	 * call cpu_init() which will set a bit for this AP.  When that bit flips, the AP
+	 * is waiting for smp_threads_ready to be 1 and we can move on.
+	 */
+	for (timeout = 0; timeout < 100000; timeout++) {
+		if (test_bit(cpuid, &cpu_initialized))
+			goto alive;
+		udelay(10);
+		barrier();
+	}
+
+	printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid);
+	return -1;
+
+alive:
+	/* Remember the AP data */
+	cpu_number_map[cpuid] = cpunum;
+#ifdef CONFIG_KDB
+        cpu_online_map |= (1<<cpunum);
+        printk ("DEBUGGER: cpu_online_map = 0x%08x\n", cpu_online_map);
+#endif
+	__cpu_logical_map[cpunum] = cpuid;
+	return 0;
+}
+
+
+
+/*
+ * Called by smp_init bring all the secondaries online and hold them.  
+ * XXX: this is ACPI specific; it uses "magic" variables exported from acpi.c 
+ *      to 'discover' the AP's.  Blech.
+ */
+void __init
+smp_boot_cpus(void)
+{
+	int i, cpu_count = 1;
+	unsigned long bogosum;
+	int sapic_id;
+	extern int acpi_cpus;
+	extern int acpi_apic_map[32];
+
+	/* Take care of some initial bookkeeping.  */
+	memset(&cpu_number_map, -1, sizeof(cpu_number_map));
+	memset(&__cpu_logical_map, -1, sizeof(__cpu_logical_map));
+	memset(&ipi_op, 0, sizeof(ipi_op));
+
+	/* Setup BSP mappings */
+	cpu_number_map[bootstrap_processor] = 0;
+	__cpu_logical_map[0] = bootstrap_processor;
+	current->processor = bootstrap_processor;
+
+	/* Mark BSP booted and get active_mm context */
+	cpu_init();
+
+	/* reset XTP for interrupt routing */
+	normal_xtp();
+
+	/* And generate an entry in cpu_data */
+	smp_store_cpu_info(bootstrap_processor);
+#if 0
+	smp_tune_scheduling();
+#endif
+ 	smp_setup_percpu_timer(bootstrap_processor);
+
+	init_idle();
+
+	/* Nothing to do when told not to.  */
+	if (max_cpus == 0) {
+	        printk(KERN_INFO "SMP mode deactivated.\n");
+		return;
+	}
+
+	if (acpi_cpus > 1) {
+		printk(KERN_INFO "SMP: starting up secondaries.\n");
+
+		for (i = 0; i < NR_CPUS; i++) {
+			if (acpi_apic_map[i] == -1 || 
+			    acpi_apic_map[i] == bootstrap_processor << 8) /* XXX Fix me Walt */
+				continue;
+
+			/*
+			 * IA64 SAPIC ID's are 16-bits.  See asm/smp.h for more info 
+			 */
+			sapic_id = acpi_apic_map[i] >> 8;
+			if (smp_boot_one_cpu(sapic_id, cpu_count))
+				continue;
+
+			cpu_count++; /* Count good CPUs only... */
+		}
+	}
+
+	if (cpu_count == 1) {
+		printk(KERN_ERR "SMP: Bootstrap processor only.\n");
+		return;
+	}
+
+	bogosum = 0;
+        for (i = 0; i < NR_CPUS; i++) {
+		if (cpu_initialized & (1L << i))
+			bogosum += cpu_data[i].loops_per_sec;
+        }
+
+	printk(KERN_INFO "SMP: Total of %d processors activated "
+	       "(%lu.%02lu BogoMIPS).\n",
+	       cpu_count, (bogosum + 2500) / 500000,
+	       ((bogosum + 2500) / 5000) % 100);
+
+	smp_num_cpus = cpu_count;
+}
+
+/* 
+ * Called from main.c by each AP.
+ */
+void __init 
+smp_commence(void)
+{
+	mb();
+}
+
+/*
+ * Not used; part of the i386 bringup
+ */
+void __init 
+initialize_secondary(void)
+{
+}
+
+int __init
+setup_profiling_timer(unsigned int multiplier)
+{
+        return -EINVAL;
+}
+
+/*
+ * Assume that CPU's have been discovered by some platform-dependant
+ * interface.  For SoftSDV/Lion, that would be ACPI.
+ *
+ * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP().
+ *
+ * So this just gets the BSP SAPIC ID and print's it out.  Dull, huh?
+ *
+ * Not anymore.  This also registers the AP OS_MC_REDVEZ address with SAL.
+ */
+void __init
+init_smp_config(void)
+{
+	struct fptr {
+		unsigned long fp;
+		unsigned long gp;
+	} *ap_startup;
+	long sal_ret;
+
+	/* Grab the BSP ID */
+	bootstrap_processor = hard_smp_processor_id();
+
+	/* Tell SAL where to drop the AP's.  */
+	ap_startup = (struct fptr *) start_ap;
+	sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
+				       __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 
+				       0, 0, 0);
+	if (sal_ret < 0) {
+		printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret));
+		printk("     Forcing UP mode\n");
+		smp_num_cpus = 1; 
+	}
+
+}
+
+#ifdef CONFIG_KDB
+void smp_kdb_stop (int all, struct pt_regs* regs)
+{
+        if (all)
+      {
+              printk ("Sending IPI to all on CPU %i\n", smp_processor_id ());
+                smp_kdb_wait = 0xffffffff;
+                clear_bit (smp_processor_id(), &smp_kdb_wait);
+                send_IPI_allbutself (IPI_KDB_INTERRUPT);
+        }
+      else
+      {
+              printk ("Sending IPI to self on CPU %i\n",
+                      smp_processor_id ());
+                set_bit (smp_processor_id(), &smp_kdb_wait);
+              clear_bit (__cpu_logical_map[kdb_new_cpu], &smp_kdb_wait);
+                smp_kdb_interrupt (regs);
+        }
+}
+
+void smp_kdb_interrupt (struct pt_regs* regs)
+{
+        printk ("kdb: IPI on CPU %i with mask 0x%08x\n",
+              smp_processor_id (), smp_kdb_wait);
+
+      /* All CPUs spin here forever */
+        while (test_bit (smp_processor_id(), &smp_kdb_wait));
+
+      /* Enter KDB on CPU selected by KDB on the last CPU */
+        if (__cpu_logical_map[kdb_new_cpu] == smp_processor_id ())
+      {
+                kdb (KDB_REASON_SWITCH, 0, regs);
+        }
+}
+
+#endif
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/sys_ia64.c linux/arch/ia64/kernel/sys_ia64.c
--- v2.3.42/linux/arch/ia64/kernel/sys_ia64.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/sys_ia64.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,216 @@
+/*
+ * This file contains various system calls that have different calling
+ * conventions on different platforms.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/file.h>		/* doh, must come after sched.h... */
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+asmlinkage long
+ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6, 
+		  long arg7, long stack)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+	extern long sys_getpriority (int, int);
+	long prio;
+
+	prio = sys_getpriority(which, who);
+	if (prio >= 0) {
+		regs->r8 = 0;	/* ensure negative priority is not mistaken as error code */
+		prio = 20 - prio;
+	}
+	return prio;
+}
+
+asmlinkage unsigned long
+sys_getpagesize (void)
+{
+	return PAGE_SIZE;
+}
+
+asmlinkage unsigned long
+ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6,
+	    long arg7, long stack)
+{
+	extern int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+	unsigned long raddr;
+	int retval;
+
+	retval = sys_shmat(shmid, shmaddr, shmflg, &raddr);
+	if (retval < 0)
+		return retval;
+
+	regs->r8 = 0;	/* ensure negative addresses are not mistaken as an error code */
+	return raddr;
+}
+
+asmlinkage unsigned long
+ia64_brk (long brk, long arg1, long arg2, long arg3,
+	  long arg4, long arg5, long arg6, long arg7, long stack)
+{
+	extern unsigned long sys_brk (unsigned long brk);
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+	unsigned long retval;
+
+	retval = sys_brk(brk);
+
+	regs->r8 = 0;	/* ensure large retval isn't mistaken as error code */
+	return retval;
+}
+
+/*
+ * On IA-64, we return the two file descriptors in ret0 and ret1 (r8
+ * and r9) as this is faster than doing a copy_to_user().
+ */
+asmlinkage long
+sys_pipe (long arg0, long arg1, long arg2, long arg3,
+	  long arg4, long arg5, long arg6, long arg7, long stack)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+	int fd[2];
+	int retval;
+
+	lock_kernel();
+	retval = do_pipe(fd);
+	if (retval)
+		goto out;
+	retval = fd[0];
+	regs->r9 = fd[1];
+  out:
+	unlock_kernel();
+	return retval;
+}
+
+static inline unsigned long
+do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
+{
+	struct file *file = 0;
+
+	/*
+	 * A zero mmap always succeeds in Linux, independent of
+	 * whether or not the remaining arguments are valid.
+	 */
+	if (PAGE_ALIGN(len) == 0)
+		return addr;
+
+#ifdef notyet
+	/* Don't permit mappings that would cross a region boundary: */
+	region_start = IA64_GET_REGION(addr);
+	region_end   = IA64_GET_REGION(addr + len);
+	if (region_start != region_end)
+		return -EINVAL;
+
+	<<x??x>>
+#endif
+
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+	if (!(flags & MAP_ANONYMOUS)) {
+		file = fget(fd);
+		if (!file)
+			return -EBADF;
+	}
+
+	down(&current->mm->mmap_sem);
+	lock_kernel();
+
+	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+
+	unlock_kernel();
+	up(&current->mm->mmap_sem);
+
+	if (file)
+		fput(file);
+	return addr;
+}
+
+/*
+ * mmap2() is like mmap() except that the offset is expressed in units
+ * of PAGE_SIZE (instead of bytes).  This allows to mmap2() (pieces
+ * of) files that are larger than the address space of the CPU.
+ */
+asmlinkage unsigned long
+sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff,
+	   long arg6, long arg7, long stack)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+
+	addr = do_mmap2(addr, len, prot, flags, fd, pgoff);
+	if (!IS_ERR(addr))
+		regs->r8 = 0;	/* ensure large addresses are not mistaken as failures... */
+	return addr;
+}
+
+asmlinkage unsigned long
+sys_mmap (unsigned long addr, unsigned long len, int prot, int flags,
+	  int fd, long off, long arg6, long arg7, long stack)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+
+	addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+	if (!IS_ERR(addr))
+		regs->r8 = 0;	/* ensure large addresses are not mistaken as failures... */
+	return addr;
+}
+
+asmlinkage long
+sys_ioperm (unsigned long from, unsigned long num, int on)
+{
+        printk(KERN_ERR "sys_ioperm(from=%lx, num=%lx, on=%d)\n", from, num, on);
+        return -EIO;
+}
+
+asmlinkage long
+sys_iopl (int level, long arg1, long arg2, long arg3)
+{
+        lock_kernel();
+        printk(KERN_ERR "sys_iopl(level=%d)!\n", level);
+        unlock_kernel();
+        return -ENOSYS;
+}
+
+asmlinkage long
+sys_vm86 (long arg0, long arg1, long arg2, long arg3)
+{
+        lock_kernel();
+        printk(KERN_ERR "sys_vm86(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
+        unlock_kernel();
+        return -ENOSYS;
+}
+
+asmlinkage long
+sys_modify_ldt (long arg0, long arg1, long arg2, long arg3)
+{
+        lock_kernel();
+        printk(KERN_ERR "sys_modify_ldt(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
+        unlock_kernel();
+        return -ENOSYS;
+}
+
+#ifndef CONFIG_PCI
+
+asmlinkage long
+sys_pciconfig_read (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
+		    void *buf)
+{
+	return -ENOSYS;
+}
+
+asmlinkage long
+sys_pciconfig_write (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
+		     void *buf)
+{
+	return -ENOSYS;
+}
+
+
+#endif /* CONFIG_PCI */
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/time.c linux/arch/ia64/kernel/time.c
--- v2.3.42/linux/arch/ia64/kernel/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/time.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,290 @@
+/*
+ * linux/arch/ia64/kernel/time.c
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1999-2000 David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ * Copyright (C) 1999-2000 VA Linux Systems
+ * Copyright (C) 1999-2000 Walt Drummond <drummond@valinux.com>
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/delay.h>
+#include <asm/efi.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/ptrace.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+
+extern rwlock_t xtime_lock;
+extern volatile unsigned long lost_ticks;
+
+#ifdef CONFIG_IA64_DEBUG_IRQ
+
+unsigned long last_cli_ip;
+
+#endif
+
+static struct {
+	unsigned long delta;
+	unsigned long next[NR_CPUS];
+} itm;
+
+static void
+do_profile (unsigned long ip)
+{
+	extern char _stext;
+
+	if (prof_buffer && current->pid) {
+		ip -= (unsigned long) &_stext;
+		ip >>= prof_shift;
+		/*
+		 * Don't ignore out-of-bounds IP values silently,
+		 * put them into the last histogram slot, so if
+		 * present, they will show up as a sharp peak.
+		 */
+		if (ip > prof_len - 1)
+			ip = prof_len - 1;
+
+		atomic_inc((atomic_t *) &prof_buffer[ip]);
+	} 
+}
+
+/*
+ * Return the number of micro-seconds that elapsed since the last
+ * update to jiffy.  The xtime_lock must be at least read-locked when
+ * calling this routine.
+ */
+static inline unsigned long
+gettimeoffset (void)
+{
+	unsigned long now = ia64_get_itc();
+	unsigned long elapsed_cycles, lost;
+
+	elapsed_cycles = now - (itm.next[smp_processor_id()] - itm.delta);
+
+	lost = lost_ticks;
+	if (lost)
+		elapsed_cycles += lost*itm.delta;
+
+	return (elapsed_cycles*my_cpu_data.usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
+}
+
+void
+do_settimeofday (struct timeval *tv)
+{
+	write_lock_irq(&xtime_lock);
+	{
+		/*
+		 * This is revolting. We need to set the xtime.tv_usec
+		 * correctly. However, the value in this location is
+		 * is value at the last tick.  Discover what
+		 * correction gettimeofday would have done, and then
+		 * undo it!
+		 */
+		tv->tv_usec -= gettimeoffset();
+		while (tv->tv_usec < 0) {
+			tv->tv_usec += 1000000;
+			tv->tv_sec--;
+		}
+
+		xtime = *tv;
+		time_adjust = 0;		/* stop active adjtime() */
+		time_status |= STA_UNSYNC;
+		time_maxerror = NTP_PHASE_LIMIT;
+		time_esterror = NTP_PHASE_LIMIT;
+	}
+	write_unlock_irq(&xtime_lock);
+}
+
+void
+do_gettimeofday (struct timeval *tv)
+{
+	unsigned long flags, usec, sec;
+
+	read_lock_irqsave(&xtime_lock, flags);
+	{
+		usec = gettimeoffset();
+	
+		sec = xtime.tv_sec;
+		usec += xtime.tv_usec;
+	}
+	read_unlock_irqrestore(&xtime_lock, flags);
+
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		++sec;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+static void
+timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	static unsigned long last_time;
+	static unsigned char count;
+	int cpu = smp_processor_id();
+
+	/*
+	 * Here we are in the timer irq handler. We have irqs locally
+	 * disabled, but we don't know if the timer_bh is running on
+	 * another CPU. We need to avoid to SMP race by acquiring the
+	 * xtime_lock.
+	 */
+	write_lock(&xtime_lock);
+	while (1) {
+		/* do kernel PC profiling here.  */
+		if (!user_mode(regs)) 
+			do_profile(regs->cr_iip);
+
+#ifdef CONFIG_SMP
+		smp_do_timer(regs);
+		if (smp_processor_id() == bootstrap_processor)
+			do_timer(regs);
+#else
+		do_timer(regs);
+#endif
+
+		itm.next[cpu] += itm.delta;
+		/*
+		 * There is a race condition here: to be on the "safe"
+		 * side, we process timer ticks until itm.next is
+		 * ahead of the itc by at least half the timer
+		 * interval.  This should give us enough time to set
+		 * the new itm value without losing a timer tick.
+		 */
+		if (time_after(itm.next[cpu], ia64_get_itc() + itm.delta/2)) {
+			ia64_set_itm(itm.next[cpu]);
+			break;
+		}
+
+#if !(defined(CONFIG_IA64_SOFTSDV_HACKS) && defined(CONFIG_SMP))
+		/*
+		 * SoftSDV in SMP mode is _slow_, so we do "loose" ticks, 
+		 * but it's really OK...
+		 */
+		if (count > 0 && jiffies - last_time > 5*HZ)
+			count = 0;
+		if (count++ == 0) {
+			last_time = jiffies;
+			printk("Lost clock tick on CPU %d (now=%lx, next=%lx)!!\n",
+			       cpu, ia64_get_itc(), itm.next[cpu]);
+# ifdef CONFIG_IA64_DEBUG_IRQ
+			printk("last_cli_ip=%lx\n", last_cli_ip);
+# endif
+		}
+#endif
+	}
+	write_unlock(&xtime_lock);
+}
+
+/*
+ * Encapsulate access to the itm structure for SMP.
+ */
+void __init
+ia64_cpu_local_tick(void)
+{
+	/* arrange for the cycle counter to generate a timer interrupt: */
+	ia64_set_itv(TIMER_IRQ, 0);
+	ia64_set_itc(0);
+	itm.next[smp_processor_id()] = ia64_get_itc() + itm.delta;
+	ia64_set_itm(itm.next[smp_processor_id()]);
+}
+
+void __init
+ia64_init_itm (void)
+{
+	unsigned long platform_base_freq, itc_freq, drift;
+	struct pal_freq_ratio itc_ratio, proc_ratio;
+	long status;
+
+	/*
+	 * According to SAL v2.6, we need to use a SAL call to determine the
+	 * platform base frequency and then a PAL call to determine the
+	 * frequency ratio between the ITC and the base frequency.
+	 */
+	status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM, &platform_base_freq, &drift);
+	if (status != 0) {
+		printk("SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status));
+	} else {
+		status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio);
+		if (status != 0)
+			printk("PAL_FREQ_RATIOS failed with status=%ld\n", status);
+	}
+	if (status != 0) {
+		/* invent "random" values */
+		printk("SAL/PAL failed to obtain frequency info---inventing reasonably values\n");
+		platform_base_freq = 100000000;
+		itc_ratio.num = 3;
+		itc_ratio.den = 1;
+	}
+#if defined(CONFIG_IA64_LION_HACKS)
+	/* Our Lion currently returns base freq 104.857MHz, which
+	   ain't right (it really is 100MHz).  */
+	printk("SAL/PAL returned: base-freq=%lu, itc-ratio=%lu/%lu, proc-ratio=%lu/%lu\n",
+	       platform_base_freq, itc_ratio.num, itc_ratio.den,
+	       proc_ratio.num, proc_ratio.den);
+	platform_base_freq = 100000000;
+#elif 0 && defined(CONFIG_IA64_BIGSUR_HACKS)
+	/* BigSur with 991020 firmware returned itc-ratio=9/2 and base
+	   freq 75MHz, which wasn't right.  The 991119 firmware seems
+	   to return the right values, so this isn't necessary
+	   anymore... */
+	printk("SAL/PAL returned: base-freq=%lu, itc-ratio=%lu/%lu, proc-ratio=%lu/%lu\n",
+	       platform_base_freq, itc_ratio.num, itc_ratio.den,
+	       proc_ratio.num, proc_ratio.den);
+	platform_base_freq = 100000000;
+	proc_ratio.num = 5; proc_ratio.den = 1;
+	itc_ratio.num  = 5; itc_ratio.den  = 1;
+#elif defined(CONFIG_IA64_SOFTSDV_HACKS)
+	platform_base_freq = 10000000;
+	proc_ratio.num = 4; proc_ratio.den = 1;
+	itc_ratio.num  = 4; itc_ratio.den  = 1;
+#else
+	if (platform_base_freq < 40000000) {
+		printk("Platform base frequency %lu bogus---resetting to 75MHz!\n",
+		       platform_base_freq);
+		platform_base_freq = 75000000;
+	}
+#endif
+	if (!proc_ratio.den)
+		proc_ratio.num = 1;	/* avoid division by zero */
+	if (!itc_ratio.den)
+		itc_ratio.num = 1;	/* avoid division by zero */
+
+        itc_freq = (platform_base_freq*itc_ratio.num)/itc_ratio.den;
+        itm.delta = itc_freq / HZ;
+        printk("timer: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, ITC freq=%lu.%03luMHz\n",
+               platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
+               itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000);
+
+	my_cpu_data.proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
+	my_cpu_data.itc_freq = itc_freq;
+	my_cpu_data.cyc_per_usec = itc_freq / 1000000;
+	my_cpu_data.usec_per_cyc = (1000000UL << IA64_USEC_PER_CYC_SHIFT) / itc_freq;
+
+	/* Setup the CPU local timer tick */
+	ia64_cpu_local_tick();
+}
+
+void __init
+time_init (void)
+{
+	/*
+	 * Request the IRQ _before_ doing anything to cause that
+	 * interrupt to be posted.
+	 */
+	if (request_irq(TIMER_IRQ, timer_interrupt, 0, "timer", NULL)) 
+		panic("Could not allocate timer IRQ!");
+
+	efi_gettimeofday(&xtime);
+	ia64_init_itm();
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/traps.c linux/arch/ia64/kernel/traps.c
--- v2.3.42/linux/arch/ia64/kernel/traps.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/traps.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,423 @@
+/*
+ * Architecture-specific trap handling.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/*
+ * The fpu_fault() handler needs to be able to access and update all
+ * floating point registers.  Those saved in pt_regs can be accessed
+ * through that structure, but those not saved, will be accessed
+ * directly.  To make this work, we need to ensure that the compiler
+ * does not end up using a preserved floating point register on its
+ * own.  The following achieves this by declaring preserved registers
+ * that are not marked as "fixed" as global register variables.
+ */
+register double f2 asm ("f2"); register double f3 asm ("f3");
+register double f4 asm ("f4"); register double f5 asm ("f5");
+
+register long f16 asm ("f16"); register long f17 asm ("f17");
+register long f18 asm ("f18"); register long f19 asm ("f19");
+register long f20 asm ("f20"); register long f21 asm ("f21");
+register long f22 asm ("f22"); register long f23 asm ("f23");
+
+register double f24 asm ("f24"); register double f25 asm ("f25");
+register double f26 asm ("f26"); register double f27 asm ("f27");
+register double f28 asm ("f28"); register double f29 asm ("f29");
+register double f30 asm ("f30"); register double f31 asm ("f31");
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_KDB
+# include <linux/kdb.h>
+#endif
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#include <asm/fpswa.h>
+
+static fpswa_interface_t *fpswa_interface;
+
+void __init
+trap_init (void)
+{
+	printk("fpswa interface at %lx\n", ia64_boot_param.fpswa);
+	if (ia64_boot_param.fpswa) {
+#define OLD_FIRMWARE
+#ifdef OLD_FIRMWARE
+		/*
+		 * HACK to work around broken firmware.  This code
+		 * applies the label fixup to the FPSWA interface and
+		 * works both with old and new (fixed) firmware.
+		 */
+		unsigned long addr = (unsigned long) __va(ia64_boot_param.fpswa);
+		unsigned long gp_val = *(unsigned long *)(addr + 8);
+
+		/* go indirect and indexed to get table address */
+		addr = gp_val;
+		gp_val = *(unsigned long *)(addr + 8);
+
+		while (gp_val == *(unsigned long *)(addr + 8)) {
+			*(unsigned long *)addr |= PAGE_OFFSET;
+			*(unsigned long *)(addr + 8) |= PAGE_OFFSET;
+			addr += 16;
+		}
+#endif
+		/* FPSWA fixup: make the interface pointer a kernel virtual address: */
+		fpswa_interface = __va(ia64_boot_param.fpswa);
+	}
+}
+
+void
+die_if_kernel (char *str, struct pt_regs *regs, long err)
+{
+	if (user_mode(regs)) {
+#if 1
+		/* XXX for debugging only */
+		printk ("!!die_if_kernel: %s(%d): %s %ld\n",
+			current->comm, current->pid, str, err);
+		show_regs(regs);
+#endif
+		return;
+	}
+
+	printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
+
+#ifdef CONFIG_KDB
+	while (1) {
+                kdb(KDB_REASON_PANIC, 0, regs);
+                printk("Cant go anywhere from Panic!\n");
+	}
+#endif
+
+	show_regs(regs);
+
+	if (current->thread.flags & IA64_KERNEL_DEATH) {
+		printk("die_if_kernel recursion detected.\n");
+		sti();
+		while (1);
+	}
+	current->thread.flags |= IA64_KERNEL_DEATH;
+	do_exit(SIGSEGV);
+}
+
+void
+ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
+{
+	siginfo_t siginfo;
+
+	/* gdb uses a break number of 0xccccc for debug breakpoints: */
+	if (break_num != 0xccccc)
+		die_if_kernel("Bad break", regs, break_num);
+
+	siginfo.si_signo = SIGTRAP;
+	siginfo.si_errno = break_num;	/* XXX is it legal to abuse si_errno like this? */
+	siginfo.si_code = TRAP_BRKPT;
+	send_sig_info(SIGTRAP, &siginfo, current);
+}
+
+/*
+ * Unimplemented system calls.  This is called only for stuff that
+ * we're supposed to implement but haven't done so yet.  Everything
+ * else goes to sys_ni_syscall.
+ */
+asmlinkage long
+ia64_ni_syscall (unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3,
+		 unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7,
+		 unsigned long stack)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+
+	printk("<sc%ld(%lx,%lx,%lx,%lx)>\n", regs->r15, arg0, arg1, arg2, arg3);
+	return -ENOSYS;
+}
+
+/*
+ * disabled_fp_fault() is called when a user-level process attempts to
+ * access one of the registers f32..f127 while it doesn't own the
+ * fp-high register partition.  When this happens, we save the current
+ * fph partition in the task_struct of the fpu-owner (if necessary)
+ * and then load the fp-high partition of the current task (if
+ * necessary).
+ */
+static inline void
+disabled_fph_fault (struct pt_regs *regs)
+{
+	struct task_struct *fpu_owner = ia64_get_fpu_owner();
+
+	regs->cr_ipsr &= ~(IA64_PSR_DFH | IA64_PSR_MFH);
+	if (fpu_owner != current) {
+		ia64_set_fpu_owner(current);
+
+		if (fpu_owner && ia64_psr(ia64_task_regs(fpu_owner))->mfh) {
+			fpu_owner->thread.flags |= IA64_THREAD_FPH_VALID;
+			__ia64_save_fpu(fpu_owner->thread.fph);
+		}
+		if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
+			__ia64_load_fpu(current->thread.fph);
+		} else {
+			__ia64_init_fpu();
+		}
+	}
+}
+
+static inline int
+fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
+	    struct pt_regs *regs)
+{
+	fp_state_t fp_state;
+	fpswa_ret_t ret;
+#ifdef FPSWA_BUG
+	struct ia64_fpreg f6_15[10];
+#endif
+
+	if (!fpswa_interface)
+		return -1;
+
+	memset(&fp_state, 0, sizeof(fp_state_t));
+
+	/*
+	 * compute fp_state.  only FP registers f6 - f11 are used by the 
+	 * kernel, so set those bits in the mask and set the low volatile
+	 * pointer to point to these registers.
+	 */
+	fp_state.bitmask_low64 = 0xffc0;  /* bit6..bit15 */
+#ifndef FPSWA_BUG
+	fp_state.fp_state_low_volatile = &regs->f6;
+#else
+	f6_15[0] = regs->f6;
+	f6_15[1] = regs->f7;
+	f6_15[2] = regs->f8;
+	f6_15[3] = regs->f9;
+ 	__asm__ ("stf.spill %0=f10" : "=m"(f6_15[4]));
+ 	__asm__ ("stf.spill %0=f11" : "=m"(f6_15[5]));
+ 	__asm__ ("stf.spill %0=f12" : "=m"(f6_15[6]));
+ 	__asm__ ("stf.spill %0=f13" : "=m"(f6_15[7]));
+ 	__asm__ ("stf.spill %0=f14" : "=m"(f6_15[8]));
+ 	__asm__ ("stf.spill %0=f15" : "=m"(f6_15[9]));
+	fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) f6_15;
+#endif
+        /*
+	 * unsigned long (*EFI_FPSWA) (
+	 *      unsigned long    trap_type,
+	 *	void             *Bundle,
+	 *	unsigned long    *pipsr,
+	 *	unsigned long    *pfsr,
+	 *	unsigned long    *pisr,
+	 *	unsigned long    *ppreds,
+	 *	unsigned long    *pifs,
+	 *	void             *fp_state);
+	 */
+	ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,
+					(unsigned long *) ipsr, (unsigned long *) fpsr,
+					(unsigned long *) isr, (unsigned long *) pr,
+					(unsigned long *) ifs, &fp_state);
+#ifdef FPSWA_BUG
+ 	__asm__ ("ldf.fill f10=%0" :: "m"(f6_15[4]));
+ 	__asm__ ("ldf.fill f11=%0" :: "m"(f6_15[5]));
+ 	__asm__ ("ldf.fill f12=%0" :: "m"(f6_15[6]));
+ 	__asm__ ("ldf.fill f13=%0" :: "m"(f6_15[7]));
+ 	__asm__ ("ldf.fill f14=%0" :: "m"(f6_15[8]));
+ 	__asm__ ("ldf.fill f15=%0" :: "m"(f6_15[9]));
+	regs->f6 = f6_15[0];
+	regs->f7 = f6_15[1];
+	regs->f8 = f6_15[2];
+	regs->f9 = f6_15[3];
+#endif
+	return ret.status;
+}
+
+/*
+ * Handle floating-point assist faults and traps.
+ */
+static int
+handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
+{
+	long exception, bundle[2];
+	unsigned long fault_ip;
+	static int fpu_swa_count = 0;
+	static unsigned long last_time;
+
+	fault_ip = regs->cr_iip;
+	if (!fp_fault && (ia64_psr(regs)->ri == 0))
+		fault_ip -= 16;
+	if (copy_from_user(bundle, (void *) fault_ip, sizeof(bundle)))
+		return -1;
+
+	if (fpu_swa_count > 5 && jiffies - last_time > 5*HZ)
+		fpu_swa_count = 0;
+	if (++fpu_swa_count < 5) {
+		last_time = jiffies;
+		printk("%s(%d): floating-point assist fault at ip %016lx\n",
+		       current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri);
+	}
+
+	exception = fp_emulate(fp_fault, bundle, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
+ 			       &regs->cr_ifs, regs);
+	if (fp_fault) {
+		if (exception == 0) {
+			/* emulation was successful */
+ 			ia64_increment_ip(regs);
+		} else if (exception == -1) {
+			printk("handle_fpu_swa: fp_emulate() returned -1\n");
+			return -2;
+		} else {
+			/* is next instruction a trap? */
+			if (exception & 2) {
+				ia64_increment_ip(regs);
+			}
+			return -1;
+		}
+	} else {
+		if (exception == -1) {
+			printk("handle_fpu_swa: fp_emulate() returned -1\n");
+			return -2;
+		} else if (exception != 0) {
+			/* raise exception */
+			return -1;
+		}
+	}
+	return 0;
+}
+
+void
+ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
+	    unsigned long iim, unsigned long itir, unsigned long arg5,
+	    unsigned long arg6, unsigned long arg7, unsigned long stack)
+{
+	struct pt_regs *regs = (struct pt_regs *) &stack;
+	unsigned long code, error = isr;
+	struct siginfo siginfo;
+	char buf[128];
+	int result;
+	static const char *reason[] = {
+		"IA-64 Illegal Operation fault",
+		"IA-64 Privileged Operation fault",
+		"IA-64 Privileged Register fault",
+		"IA-64 Reserved Register/Field fault",
+		"Disabled Instruction Set Transition fault",
+		"Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
+		"Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12", 
+		"Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
+	};
+
+#if 0
+	/* this is for minimal trust debugging; yeah this kind of stuff is useful at times... */
+
+	if (vector != 25) {
+		static unsigned long last_time;
+		static char count;
+		unsigned long n = vector;
+		char buf[32], *cp;
+
+		if (count > 5 && jiffies - last_time > 5*HZ)
+			count = 0;
+
+		if (count++ < 5) {
+			last_time = jiffies;
+			cp = buf + sizeof(buf);
+			*--cp = '\0';
+			while (n) {
+				*--cp = "0123456789abcdef"[n & 0xf];
+				n >>= 4;
+			}
+			printk("<0x%s>", cp);
+		}
+	}
+#endif
+
+	switch (vector) {
+	      case 24: /* General Exception */
+		code = (isr >> 4) & 0xf;
+		sprintf(buf, "General Exception: %s%s", reason[code],
+			(code == 3) ? ((isr & (1UL << 37))
+				       ? " (RSE access)" : " (data access)") : "");
+#ifndef CONFIG_ITANIUM_ASTEP_SPECIFIC
+		if (code == 8) {
+# ifdef CONFIG_IA64_PRINT_HAZARDS
+			printk("%016lx:possible hazard, pr = %016lx\n", regs->cr_iip, regs->pr);
+# endif
+			return;
+		}
+#endif
+		break;
+
+	      case 25: /* Disabled FP-Register */
+		if (isr & 2) {
+			disabled_fph_fault(regs);
+			return;
+		}
+		sprintf(buf, "Disabled FPL fault---not supposed to happen!");
+		break;
+
+	      case 29: /* Debug */
+	      case 35: /* Taken Branch Trap */
+	      case 36: /* Single Step Trap */
+		switch (vector) {
+		      case 29: siginfo.si_code = TRAP_BRKPT; break;
+		      case 35: siginfo.si_code = TRAP_BRANCH; break;
+		      case 36: siginfo.si_code = TRAP_TRACE; break;
+		}
+		siginfo.si_signo = SIGTRAP;
+		siginfo.si_errno = 0;
+		force_sig_info(SIGTRAP, &siginfo, current);
+		return;
+
+	      case 30: /* Unaligned fault */
+		sprintf(buf, "Unaligned access in kernel mode---don't do this!");
+		break;
+
+	      case 32: /* fp fault */
+	      case 33: /* fp trap */
+		result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, isr);
+		if (result < 0) {
+			siginfo.si_signo = SIGFPE;
+			siginfo.si_errno = 0;
+			siginfo.si_code = 0;	/* XXX fix me */
+			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			send_sig_info(SIGFPE, &siginfo, current);
+			if (result == -1)
+				send_sig_info(SIGFPE, &siginfo, current);
+			else
+				force_sig(SIGFPE, current);
+		}
+		return;
+
+	      case 34:		/* Unimplemented Instruction Address Trap */
+		if (user_mode(regs)) {
+			printk("Woah! Unimplemented Instruction Address Trap!\n");
+			siginfo.si_code = ILL_BADIADDR;
+			siginfo.si_signo = SIGILL;
+			siginfo.si_errno = 0;
+			force_sig_info(SIGILL, &siginfo, current);
+			return;
+		}
+		sprintf(buf, "Unimplemented Instruction Address fault");
+		break;
+
+	      case 45:
+		printk("Unexpected IA-32 exception\n");
+		force_sig(SIGSEGV, current);
+		return;
+
+	      case 46:
+		printk("Unexpected IA-32 intercept trap\n");
+		force_sig(SIGSEGV, current);
+		return;
+
+	      case 47:
+		sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
+		break;
+
+	      default:
+		sprintf(buf, "Fault %lu", vector);
+		break;
+	}
+	die_if_kernel(buf, regs, error);
+	force_sig(SIGILL, current);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/unaligned.c linux/arch/ia64/kernel/unaligned.c
--- v2.3.42/linux/arch/ia64/kernel/unaligned.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/unaligned.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,1554 @@
+/*
+ * Architecture-specific unaligned trap handling.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <asm/rse.h>
+#include <asm/processor.h>
+#include <asm/unaligned.h>
+
+extern void die_if_kernel(char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+
+#undef DEBUG_UNALIGNED_TRAP
+
+#ifdef DEBUG_UNALIGNED_TRAP
+#define DPRINT(a) { printk("%s, line %d: ", __FUNCTION__, __LINE__); printk a;}
+#else
+#define DPRINT(a)
+#endif
+
+#define IA64_FIRST_STACKED_GR	32
+#define IA64_FIRST_ROTATING_FR	32
+#define SIGN_EXT9		__IA64_UL(0xffffffffffffff00)
+
+/*
+ * For M-unit:
+ *
+ *  opcode |   m  |   x6    |
+ * --------|------|---------|
+ * [40-37] | [36] | [35:30] |
+ * --------|------|---------|
+ *     4   |   1  |    6    | = 11 bits
+ * --------------------------
+ * However bits [31:30] are not directly useful to distinguish between 
+ * load/store so we can use [35:32] instead, which gives the following 
+ * mask ([40:32]) using 9 bits. The 'e' comes from the fact that we defer
+ * checking the m-bit until later in the load/store emulation.
+ */
+#define IA64_OPCODE_MASK	0x1ef00000000
+
+/*
+ * Table C-28 Integer Load/Store
+ * 
+ * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF
+ *
+ * ld8.fill, st8.fill  MUST be aligned because the RNATs are based on 
+ * the address (bits [8:3]), so we must failed.
+ */
+#define LD_OP            0x08000000000
+#define LDS_OP           0x08100000000
+#define LDA_OP           0x08200000000
+#define LDSA_OP          0x08300000000
+#define LDBIAS_OP        0x08400000000
+#define LDACQ_OP         0x08500000000
+/* 0x086, 0x087 are not relevant */
+#define LDCCLR_OP        0x08800000000
+#define LDCNC_OP         0x08900000000
+#define LDCCLRACQ_OP     0x08a00000000
+#define ST_OP            0x08c00000000
+#define STREL_OP         0x08d00000000
+/* 0x08e,0x8f are not relevant */
+
+/*
+ * Table C-29 Integer Load +Reg
+ *
+ * we use the ld->m (bit [36:36]) field to determine whether or not we have
+ * a load/store of this form.
+ */
+
+/*
+ * Table C-30 Integer Load/Store +Imm
+ * 
+ * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF
+ *
+ * ld8.fill, st8.fill  must be aligned because the Nat register are based on 
+ * the address, so we must fail and the program must be fixed.
+ */
+#define LD_IMM_OP            0x0a000000000
+#define LDS_IMM_OP           0x0a100000000
+#define LDA_IMM_OP           0x0a200000000
+#define LDSA_IMM_OP          0x0a300000000
+#define LDBIAS_IMM_OP        0x0a400000000
+#define LDACQ_IMM_OP         0x0a500000000
+/* 0x0a6, 0xa7 are not relevant */
+#define LDCCLR_IMM_OP        0x0a800000000
+#define LDCNC_IMM_OP         0x0a900000000
+#define LDCCLRACQ_IMM_OP     0x0aa00000000
+#define ST_IMM_OP            0x0ac00000000
+#define STREL_IMM_OP         0x0ad00000000
+/* 0x0ae,0xaf are not relevant */
+
+/*
+ * Table C-32 Floating-point Load/Store
+ */
+#define LDF_OP           0x0c000000000
+#define LDFS_OP          0x0c100000000
+#define LDFA_OP          0x0c200000000
+#define LDFSA_OP         0x0c300000000
+/* 0x0c6 is irrelevant */
+#define LDFCCLR_OP       0x0c800000000
+#define LDFCNC_OP        0x0c900000000
+/* 0x0cb is irrelevant  */
+#define STF_OP           0x0cc00000000
+
+/*
+ * Table C-33 Floating-point Load +Reg
+ *
+ * we use the ld->m (bit [36:36]) field to determine whether or not we have
+ * a load/store of this form.
+ */
+
+/*
+ * Table C-34 Floating-point Load/Store +Imm
+ */
+#define LDF_IMM_OP       0x0e000000000
+#define LDFS_IMM_OP      0x0e100000000
+#define LDFA_IMM_OP      0x0e200000000
+#define LDFSA_IMM_OP     0x0e300000000
+/* 0x0e6 is irrelevant */
+#define LDFCCLR_IMM_OP   0x0e800000000
+#define LDFCNC_IMM_OP    0x0e900000000
+#define STF_IMM_OP       0x0ec00000000
+
+typedef struct {
+	unsigned long  	 qp:6;	/* [0:5]   */
+	unsigned long    r1:7;	/* [6:12]  */
+	unsigned long   imm:7;	/* [13:19] */
+	unsigned long    r3:7;	/* [20:26] */
+	unsigned long     x:1;  /* [27:27] */
+	unsigned long  hint:2;	/* [28:29] */
+	unsigned long x6_sz:2;	/* [30:31] */
+	unsigned long x6_op:4;	/* [32:35], x6 = x6_sz|x6_op */
+	unsigned long     m:1;	/* [36:36] */
+	unsigned long    op:4;	/* [37:40] */
+	unsigned long   pad:23; /* [41:63] */
+} load_store_t;
+
+
+typedef enum {
+	UPD_IMMEDIATE,	/* ldXZ r1=[r3],imm(9) */
+	UPD_REG		/* ldXZ r1=[r3],r2     */
+} update_t;
+
+/*
+ * We use tables to keep track of the offsets of registers in the saved state.
+ * This way we save having big switch/case statements.
+ *
+ * We use bit 0 to indicate switch_stack or pt_regs.
+ * The offset is simply shifted by 1 bit.
+ * A 2-byte value should be enough to hold any kind of offset
+ *
+ * In case the calling convention changes (and thus pt_regs/switch_stack)
+ * simply use RSW instead of RPT or vice-versa.
+ */
+
+#define RPO(x)	((size_t) &((struct pt_regs *)0)->x)
+#define RSO(x)	((size_t) &((struct switch_stack *)0)->x)
+
+#define RPT(x)		(RPO(x) << 1)
+#define RSW(x)		(1| RSO(x)<<1)
+
+#define GR_OFFS(x)	(gr_info[x]>>1)
+#define GR_IN_SW(x)	(gr_info[x] & 0x1)
+
+#define FR_OFFS(x)	(fr_info[x]>>1)
+#define FR_IN_SW(x)	(fr_info[x] & 0x1)
+
+static u16 gr_info[32]={
+	0, 			/* r0 is read-only : WE SHOULD NEVER GET THIS */
+
+	RPT(r1), RPT(r2), RPT(r3),
+
+	RSW(r4), RSW(r5), RSW(r6), RSW(r7),
+
+	RPT(r8), RPT(r9), RPT(r10), RPT(r11),
+	RPT(r12), RPT(r13), RPT(r14), RPT(r15),
+
+	RPT(r16), RPT(r17), RPT(r18), RPT(r19),
+	RPT(r20), RPT(r21), RPT(r22), RPT(r23),
+	RPT(r24), RPT(r25), RPT(r26), RPT(r27),
+	RPT(r28), RPT(r29), RPT(r30), RPT(r31)
+};
+
+static u16 fr_info[32]={
+	0, 			/* constant : WE SHOULD NEVER GET THIS */
+	0,			/* constant : WE SHOULD NEVER GET THIS */
+
+	RSW(f2), RSW(f3), RSW(f4), RSW(f5),
+
+	RPT(f6), RPT(f7), RPT(f8), RPT(f9),
+
+	RSW(f10), RSW(f11), RSW(f12), RSW(f13), RSW(f14),
+	RSW(f15), RSW(f16), RSW(f17), RSW(f18), RSW(f19),
+	RSW(f20), RSW(f21), RSW(f22), RSW(f23), RSW(f24),
+	RSW(f25), RSW(f26), RSW(f27), RSW(f28), RSW(f29),
+	RSW(f30), RSW(f31)
+};
+
+/* Invalidate ALAT entry for integer register REGNO.  */
+static void
+invala_gr (int regno)
+{
+#	define F(reg)	case reg: __asm__ __volatile__ ("invala.e r%0" :: "i"(reg)); break
+
+	switch (regno) {
+		F(  0); F(  1); F(  2); F(  3); F(  4); F(  5); F(  6); F(  7);
+		F(  8); F(  9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15);
+		F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23);
+		F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31);
+		F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39);
+		F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47);
+		F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55);
+		F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63);
+		F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71);
+		F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79);
+		F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87);
+		F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95);
+		F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103);
+		F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111);
+		F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119);
+		F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127);
+	}
+#	undef F
+}
+
+/* Invalidate ALAT entry for floating-point register REGNO.  */
+static void
+invala_fr (int regno)
+{
+#	define F(reg)	case reg: __asm__ __volatile__ ("invala.e f%0" :: "i"(reg)); break
+
+	switch (regno) {
+		F(  0); F(  1); F(  2); F(  3); F(  4); F(  5); F(  6); F(  7);
+		F(  8); F(  9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15);
+		F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23);
+		F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31);
+		F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39);
+		F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47);
+		F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55);
+		F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63);
+		F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71);
+		F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79);
+		F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87);
+		F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95);
+		F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103);
+		F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111);
+		F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119);
+		F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127);
+	}
+#	undef F
+}
+
+static void
+set_rse_reg(struct pt_regs *regs, unsigned long r1, unsigned long val, int nat)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs - 1;
+	unsigned long *kbs	= ((unsigned long *)current) + IA64_RBS_OFFSET/8;
+	unsigned long on_kbs;
+	unsigned long *bsp, *bspstore, *addr, *ubs_end, *slot;
+	unsigned long rnats;
+	long nlocals;
+
+	/*
+	 * cr_ifs=[rv:ifm], ifm=[....:sof(6)]
+	 * nlocal=number of locals (in+loc) register of the faulting function
+	 */
+	nlocals = (regs->cr_ifs) & 0x7f;
+
+	DPRINT(("sw.bsptore=%lx pt.bspstore=%lx\n", sw->ar_bspstore, regs->ar_bspstore));
+	DPRINT(("cr.ifs=%lx sof=%ld sol=%ld\n",
+		regs->cr_ifs, regs->cr_ifs &0x7f, (regs->cr_ifs>>7)&0x7f));
+
+	on_kbs   = ia64_rse_num_regs(kbs, (unsigned long *)sw->ar_bspstore);
+	bspstore = (unsigned long *)regs->ar_bspstore;
+
+	DPRINT(("rse_slot_num=0x%lx\n",ia64_rse_slot_num((unsigned long *)sw->ar_bspstore)));
+	DPRINT(("kbs=%p nlocals=%ld\n", kbs, nlocals));
+	DPRINT(("bspstore next rnat slot %p\n",
+		ia64_rse_rnat_addr((unsigned long *)sw->ar_bspstore)));
+	DPRINT(("on_kbs=%ld rnats=%ld\n",
+		on_kbs, ((sw->ar_bspstore-(unsigned long)kbs)>>3) - on_kbs));
+
+	/*
+	 * See get_rse_reg() for an explanation on the following instructions
+	 */
+	ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
+	bsp     = ia64_rse_skip_regs(ubs_end, -nlocals);
+	addr    = slot = ia64_rse_skip_regs(bsp, r1 - 32);
+
+	DPRINT(("ubs_end=%p bsp=%p addr=%p slot=0x%lx\n",
+		ubs_end, bsp, addr, ia64_rse_slot_num(addr)));
+
+	ia64_poke(regs, current, (unsigned long)addr, val);
+
+	/*
+	 * addr will now contain the address of the RNAT for the register
+	 */
+	addr = ia64_rse_rnat_addr(addr);
+
+	ia64_peek(regs, current, (unsigned long)addr, &rnats);
+	DPRINT(("rnat @%p = 0x%lx nat=%d rnatval=%lx\n",
+		addr, rnats, nat, rnats &ia64_rse_slot_num(slot)));
+	
+	if ( nat ) {
+		rnats |= __IA64_UL(1) << ia64_rse_slot_num(slot);
+	} else {
+		rnats &= ~(__IA64_UL(1) << ia64_rse_slot_num(slot));
+	}
+	ia64_poke(regs, current, (unsigned long)addr, rnats);
+
+	DPRINT(("rnat changed to @%p = 0x%lx\n", addr, rnats));
+}
+
+
+static void
+get_rse_reg(struct pt_regs *regs, unsigned long r1, unsigned long *val, int *nat)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs - 1;
+	unsigned long *kbs	= (unsigned long *)current + IA64_RBS_OFFSET/8;
+	unsigned long on_kbs;
+	long nlocals;
+	unsigned long *bsp, *addr, *ubs_end, *slot, *bspstore;
+	unsigned long rnats;
+
+	/*
+	 * cr_ifs=[rv:ifm], ifm=[....:sof(6)]
+	 * nlocals=number of local registers in the faulting function
+	 */
+	nlocals = (regs->cr_ifs) & 0x7f;
+
+	/*
+	 * save_switch_stack does a flushrs and saves bspstore.
+	 * on_kbs = actual number of registers saved on kernel backing store
+	 *          (taking into accound potential RNATs)
+	 *
+	 * Note that this number can be greater than nlocals if the dirty
+	 * parititions included more than one stack frame at the time we
+	 * switched to KBS
+	 */
+	on_kbs   = ia64_rse_num_regs(kbs, (unsigned long *)sw->ar_bspstore);
+	bspstore = (unsigned long *)regs->ar_bspstore;
+
+	/*
+	 * To simplify the logic, we calculate everything as if there was only
+	 * one backing store i.e., the user one (UBS). We let it to peek/poke
+	 * to figure out whether the register we're looking for really is
+	 * on the UBS or on KBS.
+	 *
+	 * regs->ar_bsptore = address of last register saved on UBS (before switch)
+	 *
+	 * ubs_end = virtual end of the UBS (if everything had been spilled there)
+	 *
+	 * We know that ubs_end is the point where the last register on the
+	 * stack frame we're interested in as been saved. So we need to walk
+	 * our way backward to figure out what the BSP "was" for that frame,
+	 * this will give us the location of r32. 
+	 *
+	 * bsp = "virtual UBS" address of r32 for our frame
+	 *
+	 * Finally, get compute the address of the register we're looking for
+	 * using bsp as our base (move up again).
+	 *
+	 * Please note that in our case, we know that the register is necessarily
+	 * on the KBS because we are only interested in the current frame at the moment
+	 * we got the exception i.e., bsp is not changed until we switch to KBS.
+	 */
+	ubs_end = ia64_rse_skip_regs(bspstore, on_kbs);
+	bsp     = ia64_rse_skip_regs(ubs_end, -nlocals);
+	addr    = slot = ia64_rse_skip_regs(bsp, r1 - 32);
+
+	DPRINT(("ubs_end=%p bsp=%p addr=%p slot=0x%lx\n",
+		ubs_end, bsp, addr, ia64_rse_slot_num(addr)));
+	
+	ia64_peek(regs, current, (unsigned long)addr, val);
+
+	/*
+	 * addr will now contain the address of the RNAT for the register
+	 */
+	addr = ia64_rse_rnat_addr(addr);
+
+	ia64_peek(regs, current, (unsigned long)addr, &rnats);
+	DPRINT(("rnat @%p = 0x%lx\n", addr, rnats));
+	
+	if ( nat ) *nat = rnats >> ia64_rse_slot_num(slot) & 0x1;
+}
+
+
+static void
+setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs -1;
+	unsigned long addr;
+	unsigned long bitmask;
+	unsigned long *unat;
+
+
+	/*
+	 * First takes care of stacked registers
+	 */
+ 	if ( regnum >= IA64_FIRST_STACKED_GR ) {
+		set_rse_reg(regs, regnum, val, nat);
+		return;
+	}
+
+	/*
+	 * Using r0 as a target raises a General Exception fault which has 
+	 * higher priority than the Unaligned Reference fault.
+	 */ 
+
+	/*
+	 * Now look at registers in [0-31] range and init correct UNAT
+	 */
+	if ( GR_IN_SW(regnum) ) {
+		addr = (unsigned long)sw;
+		unat = &sw->ar_unat;
+	} else {
+		addr = (unsigned long)regs;
+		unat = &sw->caller_unat;
+	}
+	DPRINT(("tmp_base=%lx switch_stack=%s offset=%d\n",
+		addr, unat==&sw->ar_unat ? "yes":"no", GR_OFFS(regnum)));
+	/*
+	 * add offset from base of struct
+	 * and do it !
+	 */
+	addr += GR_OFFS(regnum);
+
+	*(unsigned long *)addr = val;
+
+	/*
+	 * We need to clear the corresponding UNAT bit to fully emulate the load
+	 * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4
+	 */
+	bitmask   = __IA64_UL(1) << (addr >> 3 & 0x3f);
+	DPRINT(("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, unat, *unat));
+	if ( nat ) {
+		*unat |= bitmask;
+	} else {
+		*unat &= ~bitmask;
+	}
+	DPRINT(("*0x%lx=0x%lx NaT=%d new unat: %p=%lx\n", addr, val, nat, unat,*unat));
+}
+
+#define IA64_FPH_OFFS(r) (r - IA64_FIRST_ROTATING_FR)
+
+static void
+setfpreg(unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs - 1;
+	unsigned long addr;
+
+	/*
+	 * From EAS-2.5: FPDisableFault has higher priority than 
+	 * Unaligned Fault. Thus, when we get here, we know the partition is 
+	 * enabled.
+	 *
+	 * The registers [32-127] are ususally saved in the tss. When get here,
+	 * they are NECESSARY live because they are only saved explicitely.
+	 * We have 3 ways of updating the values: force a save of the range
+	 * in tss, use a gigantic switch/case statement or generate code on the
+	 * fly to store to the right register.
+	 * For now, we are using the (slow) save/restore way.
+	 */
+ 	if ( regnum >= IA64_FIRST_ROTATING_FR ) {
+		/*
+		 * force a save of [32-127] to tss
+		 * we use the __() form to avoid fiddling with the dfh bit
+		 */
+		__ia64_save_fpu(&current->thread.fph[0]);
+
+		current->thread.fph[IA64_FPH_OFFS(regnum)] = *fpval;
+
+		__ia64_load_fpu(&current->thread.fph[0]);
+
+		/*
+	 	 * mark the high partition as being used now
+		 *
+		 * This is REQUIRED because the disabled_fph_fault() does
+		 * not set it, it's relying on the faulting instruction to
+		 * do it. In our case the faulty instruction never gets executed
+		 * completely, so we need to toggle the bit.
+	 	 */
+		regs->cr_ipsr |= IA64_PSR_MFH;
+	} else {
+		/*
+		 * pt_regs or switch_stack ?
+		 */
+		if ( FR_IN_SW(regnum) ) {
+			addr = (unsigned long)sw;
+		} else {
+			addr = (unsigned long)regs;
+		}
+		
+		DPRINT(("tmp_base=%lx offset=%d\n", addr, FR_OFFS(regnum)));
+
+		addr += FR_OFFS(regnum);
+		*(struct ia64_fpreg *)addr = *fpval;
+
+		/*
+	 	 * mark the low partition as being used now
+		 *
+		 * It is highly unlikely that this bit is not already set, but
+		 * let's do it for safety.
+	 	 */
+		regs->cr_ipsr |= IA64_PSR_MFL;
+
+	}
+}
+
+/*
+ * Those 2 inline functions generate the spilled versions of the constant floating point
+ * registers which can be used with stfX
+ */
+static inline void 
+float_spill_f0(struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("stf.spill [%0]=f0" :: "r"(final) : "memory");
+}
+
+static inline void 
+float_spill_f1(struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("stf.spill [%0]=f1" :: "r"(final) : "memory");
+}
+
+static void
+getfpreg(unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs -1;
+	unsigned long addr;
+
+	/*
+	 * From EAS-2.5: FPDisableFault has higher priority than 
+	 * Unaligned Fault. Thus, when we get here, we know the partition is 
+	 * enabled.
+	 *
+	 * When regnum > 31, the register is still live and
+	 * we need to force a save to the tss to get access to it.
+	 * See discussion in setfpreg() for reasons and other ways of doing this.
+	 */
+ 	if ( regnum >= IA64_FIRST_ROTATING_FR ) {
+	
+		/*
+		 * force a save of [32-127] to tss
+		 * we use the__ia64_save_fpu() form to avoid fiddling with
+		 * the dfh bit.
+		 */
+		__ia64_save_fpu(&current->thread.fph[0]);
+
+		*fpval =  current->thread.fph[IA64_FPH_OFFS(regnum)];
+	} else {
+		/*
+		 * f0 = 0.0, f1= 1.0. Those registers are constant and are thus
+	 	 * not saved, we must generate their spilled form on the fly
+		 */
+		switch(regnum) {
+		case 0:
+			float_spill_f0(fpval);
+			break;
+		case 1:
+			float_spill_f1(fpval);
+			break;
+		default:
+			/*
+			 * pt_regs or switch_stack ?
+			 */
+			addr =  FR_IN_SW(regnum) ? (unsigned long)sw
+						 : (unsigned long)regs;
+
+			DPRINT(("is_sw=%d tmp_base=%lx offset=0x%x\n",
+				FR_IN_SW(regnum), addr, FR_OFFS(regnum)));
+
+			addr  += FR_OFFS(regnum);
+			*fpval = *(struct ia64_fpreg *)addr;
+		}
+	}
+}
+
+
+static void
+getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs -1;
+	unsigned long addr, *unat;
+
+ 	if ( regnum >= IA64_FIRST_STACKED_GR ) {
+		get_rse_reg(regs, regnum, val, nat);
+		return;
+	}
+
+	/*
+	 * take care of r0 (read-only always evaluate to 0)
+	 */
+	if ( regnum == 0 ) {
+		*val = 0;
+		*nat = 0;
+		return;
+	}
+
+	/*
+	 * Now look at registers in [0-31] range and init correct UNAT
+	 */
+	if ( GR_IN_SW(regnum) ) {
+		addr = (unsigned long)sw;
+		unat = &sw->ar_unat;
+	} else {
+		addr = (unsigned long)regs;
+		unat = &sw->caller_unat;
+	}
+
+	DPRINT(("addr_base=%lx offset=0x%x\n", addr,  GR_OFFS(regnum)));
+
+	addr += GR_OFFS(regnum);
+
+	*val  = *(unsigned long *)addr;
+
+	/*
+	 * do it only when requested
+	 */
+	if ( nat ) *nat  = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL;
+}
+
+static void
+emulate_load_updates(update_t type, load_store_t *ld, struct pt_regs *regs, unsigned long ifa)
+{		
+	/*
+	 * IMPORTANT: 
+	 * Given the way we handle unaligned speculative loads, we should
+	 * not get to this point in the code but we keep this sanity check,
+	 * just in case.
+	 */
+	if ( ld->x6_op == 1 || ld->x6_op == 3 ) {
+		printk(KERN_ERR __FUNCTION__": register update on speculative load, error\n");	
+		die_if_kernel("unaligned reference on specualtive load with register update\n",
+			      regs, 30);
+	}
+
+
+	/*
+	 * at this point, we know that the base register to update is valid i.e.,
+	 * it's not r0
+	 */
+	if ( type == UPD_IMMEDIATE ) {
+		unsigned long imm;
+
+		/* 
+	 	 * Load +Imm: ldXZ r1=[r3],imm(9)
+	 	 *
+		 *
+	   	 * form imm9: [13:19] contain the first 7 bits
+      		 */		 
+		imm = ld->x << 7 | ld->imm;
+
+		/*
+		 * sign extend (1+8bits) if m set
+		 */
+		if (ld->m) imm |= SIGN_EXT9;
+
+		/*
+		 * ifa == r3 and we know that the NaT bit on r3 was clear so
+		 * we can directly use ifa.
+		 */
+		ifa += imm;
+
+		setreg(ld->r3, ifa, 0, regs);
+
+		DPRINT(("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld->x, ld->m, imm, ifa));
+
+	} else if ( ld->m ) {
+		unsigned long r2;
+		int nat_r2;
+
+		/*
+		 * Load +Reg Opcode: ldXZ r1=[r3],r2
+		 *
+		 * Note: that we update r3 even in the case of ldfX.a 
+		 * (where the load does not happen)
+		 *
+		 * The way the load algorithm works, we know that r3 does not
+		 * have its NaT bit set (would have gotten NaT consumption
+		 * before getting the unaligned fault). So we can use ifa 
+		 * which equals r3 at this point.
+		 *
+		 * IMPORTANT:
+	 	 * The above statement holds ONLY because we know that we
+		 * never reach this code when trying to do a ldX.s.
+		 * If we ever make it to here on an ldfX.s then 
+		 */
+		getreg(ld->imm, &r2, &nat_r2, regs);
+		
+		ifa += r2;
+		
+		/*
+		 * propagate Nat r2 -> r3
+		 */
+		setreg(ld->r3, ifa, nat_r2, regs);
+
+		DPRINT(("imm=%d r2=%ld r3=0x%lx nat_r2=%d\n",ld->imm, r2, ifa, nat_r2));
+	}
+}
+
+
+static int
+emulate_load_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+{
+	unsigned long val;
+	unsigned int len = 1<< ld->x6_sz;
+
+	/*
+	 * the macro supposes sequential access (which is the case)
+	 * if the first byte is an invalid address we return here. Otherwise
+	 * there is a guard page at the top of the user's address page and 
+	 * the first access would generate a NaT consumption fault and return
+	 * with a SIGSEGV, which is what we want.
+	 *
+	 * Note: the first argument is ignored 
+	 */
+	if ( access_ok(VERIFY_READ, (void *)ifa, len) < 0 ) {
+		DPRINT(("verify area failed on %lx\n", ifa));
+		return -1;
+	}
+
+	/*
+	 * r0, as target, doesn't need to be checked because Illegal Instruction
+	 * faults have higher priority than unaligned faults.
+	 *
+	 * r0 cannot be found as the base as it would never generate an 
+	 * unaligned reference.
+	 */
+
+	/*
+	 * ldX.a we don't try to emulate anything but we must
+	 * invalidate the ALAT entry.
+	 * See comment below for explanation on how we handle ldX.a
+	 */
+	if ( ld->x6_op != 0x2 ) {
+		/*
+		 * we rely on the macros in unaligned.h for now i.e.,
+		 * we let the compiler figure out how to read memory gracefully.
+		 *
+		 * We need this switch/case because the way the inline function
+		 * works. The code is optimized by the compiler and looks like
+		 * a single switch/case.
+		 */
+		switch(len) {
+			case 2:
+				val = ia64_get_unaligned((void *)ifa, 2);
+				break;
+			case 4:
+				val = ia64_get_unaligned((void *)ifa, 4);
+				break;
+			case 8:
+				val = ia64_get_unaligned((void *)ifa, 8);
+				break;
+			default:
+				DPRINT(("unknown size: x6=%d\n", ld->x6_sz));
+				return -1;
+		}
+
+		setreg(ld->r1, val, 0, regs);
+	}
+
+	/*
+	 * check for updates on any kind of loads
+	 */
+	if ( ld->op == 0x5 || ld->m )
+		emulate_load_updates(ld->op == 0x5 ? UPD_IMMEDIATE: UPD_REG, 
+				ld, regs, ifa);
+
+	/*
+	 * handling of various loads (based on EAS2.4):
+	 *
+	 * ldX.acq (ordered load):
+	 *	- acquire semantics would have been used, so force fence instead.
+	 *
+	 *
+	 * ldX.c.clr (check load and clear):
+	 *	- if we get to this handler, it's because the entry was not in the ALAT.
+	 *	  Therefore the operation reverts to a normal load
+	 *
+	 * ldX.c.nc (check load no clear):
+	 *	- same as previous one
+	 *
+	 * ldX.c.clr.acq (ordered check load and clear):
+	 *	- same as above for c.clr part. The load needs to have acquire semantics. So
+	 *	  we use the fence semantics which is stronger and thus ensures correctness.
+	 *	
+	 * ldX.a (advanced load):
+	 *	- suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the 
+	 * 	  address doesn't match requested size alignement. This means that we would 
+	 *	  possibly need more than one load to get the result.
+	 *
+	 *	  The load part can be handled just like a normal load, however the difficult
+	 *	  part is to get the right thing into the ALAT. The critical piece of information
+	 * 	  in the base address of the load & size. To do that, a ld.a must be executed,
+	 *	  clearly any address can be pushed into the table by using ld1.a r1=[r3]. Now
+	 *	  if we use the same target register, we will be okay for the check.a instruction.
+	 *	  If we look at the store, basically a stX [r3]=r1 checks the ALAT  for any entry
+	 *	  which would overlap within [r3,r3+X] (the size of the load was store in the
+	 *	  ALAT). If such an entry is found the entry is invalidated. But this is not good
+	 *	  enough, take the following example:
+	 *		r3=3
+	 *		ld4.a r1=[r3]
+	 *
+	 *	  Could be emulated by doing:
+	 *		ld1.a r1=[r3],1
+	 *		store to temporary;
+	 *		ld1.a r1=[r3],1
+	 *		store & shift to temporary;
+	 *		ld1.a r1=[r3],1
+	 *		store & shift to temporary;
+	 *		ld1.a r1=[r3]
+	 *		store & shift to temporary;
+	 * 		r1=temporary
+	 *
+	 *	  So int this case, you would get the right value is r1 but the wrong info in
+	 *	  the ALAT.  Notice that you could do it in reverse to finish with address 3
+	 *	  but you would still get the size wrong.  To get the size right, one needs to
+	 *	  execute exactly the same kind of load. You could do it from a aligned
+	 *	  temporary location, but you would get the address wrong.
+	 *
+	 *	  So no matter what, it is not possible to emulate an advanced load
+	 *	  correctly. But is that really critical ?
+	 *
+	 *
+	 *	  Now one has to look at how ld.a is used, one must either do a ld.c.* or
+	 *	  chck.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no
+	 *	  entry found in ALAT), and that's perfectly ok because:
+	 *
+	 *		- ld.c.*, if the entry is not present a  normal load is executed
+	 *		- chk.a.*, if the entry is not present, execution jumps to recovery code
+	 *
+	 *	  In either case, the load can be potentially retried in another form.
+	 *
+	 *	  So it's okay NOT to do any actual load on an unaligned ld.a. However the ALAT
+	 *	  must be invalidated for the register (so that's chck.a.*,ld.c.* don't pick up
+	 *	  a stale entry later) The register base update MUST also be performed.
+	 *	  
+	 *	  Now what is the content of the register and its NaT bit in the case we don't
+	 *	  do the load ?  EAS2.4, says (in case an actual load is needed)
+	 *
+	 *		- r1 = [r3], Nat = 0 if succeeds
+	 *		- r1 = 0 Nat = 0 if trying to access non-speculative memory
+	 *
+	 *	  For us, there is nothing to do, because both ld.c.* and chk.a.* are going to
+	 *	  retry and thus eventually reload the register thereby changing Nat and
+	 *	  register content.
+	 */
+
+	/*
+	 * when the load has the .acq completer then 
+	 * use ordering fence.
+	 */
+	if (ld->x6_op == 0x5 || ld->x6_op == 0xa)
+		mb();
+
+	/*
+	 * invalidate ALAT entry in case of advanced load
+	 */
+	if (ld->x6_op == 0x2)
+		invala_gr(ld->r1);
+
+	return 0;
+}
+
+static int
+emulate_store_int(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+{
+	unsigned long r2;
+	unsigned int len = 1<< ld->x6_sz;
+	
+	/*
+	 * the macro supposes sequential access (which is the case)
+	 * if the first byte is an invalid address we return here. Otherwise
+	 * there is a guard page at the top of the user's address page and 
+	 * the first access would generate a NaT consumption fault and return
+	 * with a SIGSEGV, which is what we want.
+	 *
+	 * Note: the first argument is ignored 
+	 */
+	if ( access_ok(VERIFY_WRITE, (void *)ifa, len) < 0 ) {
+		DPRINT(("verify area failed on %lx\n",ifa));
+		return -1;
+	}
+
+	/*
+	 * if we get to this handler, Nat bits on both r3 and r2 have already
+	 * been checked. so we don't need to do it
+	 *
+	 * extract the value to be stored
+	 */
+	getreg(ld->imm, &r2, 0, regs);
+
+	/*
+	 * we rely on the macros in unaligned.h for now i.e.,
+	 * we let the compiler figure out how to read memory gracefully.
+	 *
+	 * We need this switch/case because the way the inline function
+	 * works. The code is optimized by the compiler and looks like
+	 * a single switch/case.
+	 */
+	DPRINT(("st%d [%lx]=%lx\n", len, ifa, r2));
+
+	switch(len) {
+		case 2:
+			ia64_put_unaligned(r2, (void *)ifa, 2);
+			break;
+		case 4:
+			ia64_put_unaligned(r2, (void *)ifa, 4);
+			break;
+		case 8:
+			ia64_put_unaligned(r2, (void *)ifa, 8);
+			break;
+		default:
+			DPRINT(("unknown size: x6=%d\n", ld->x6_sz));
+			return -1;
+	}
+	/*
+	 * stX [r3]=r2,imm(9)
+	 *
+	 * NOTE:
+	 * ld->r3 can never be r0, because r0 would not generate an 
+	 * unaligned access.
+	 */
+	if ( ld->op == 0x5 ) {
+		unsigned long imm;
+
+		/*
+		 * form imm9: [12:6] contain first 7bits
+		 */
+		imm = ld->x << 7 | ld->r1;
+		/*
+		 * sign extend (8bits) if m set
+		 */
+		if ( ld->m ) imm |= SIGN_EXT9; 
+		/*
+		 * ifa == r3 (NaT is necessarily cleared)
+		 */
+		ifa += imm;
+
+		DPRINT(("imm=%lx r3=%lx\n", imm, ifa));
+	
+		setreg(ld->r3, ifa, 0, regs);
+	}
+	/*
+	 * we don't have alat_invalidate_multiple() so we need
+	 * to do the complete flush :-<<
+	 */
+	ia64_invala();
+
+	/*
+	 * stX.rel: use fence instead of release
+	 */
+	if ( ld->x6_op == 0xd ) mb();
+
+	return 0;
+}
+
+/*
+ * floating point operations sizes in bytes
+ */
+static const unsigned short float_fsz[4]={
+	16, /* extended precision (e) */
+	8,  /* integer (8)            */
+	4,  /* single precision (s)   */
+	8   /* double precision (d)   */
+};
+
+static inline void 
+mem2float_extended(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldfe f6=[%0];; stf.spill [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static inline void 
+mem2float_integer(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldf8 f6=[%0];; stf.spill [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static inline void 
+mem2float_single(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldfs f6=[%0];; stf.spill [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static inline void 
+mem2float_double(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldfd f6=[%0];; stf.spill [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static inline void 
+float2mem_extended(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldf.fill f6=[%0];; stfe [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static inline void 
+float2mem_integer(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldf.fill f6=[%0];; stf8 [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static inline void 
+float2mem_single(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldf.fill f6=[%0];; stfs [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static inline void 
+float2mem_double(struct ia64_fpreg *init, struct ia64_fpreg *final)
+{
+	__asm__ __volatile__ ("ldf.fill f6=[%0];; stfd [%1]=f6"
+			      :: "r"(init), "r"(final) : "f6","memory");
+}
+
+static int
+emulate_load_floatpair(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+{
+	struct ia64_fpreg fpr_init[2];
+	struct ia64_fpreg fpr_final[2];
+	unsigned long len = float_fsz[ld->x6_sz];
+
+	if ( access_ok(VERIFY_READ, (void *)ifa, len<<1) < 0 ) {
+		DPRINT(("verify area failed on %lx\n", ifa));
+		return -1;
+	}
+	/*
+	 * fr0 & fr1 don't need to be checked because Illegal Instruction
+	 * faults have higher priority than unaligned faults.
+	 *
+	 * r0 cannot be found as the base as it would never generate an 
+	 * unaligned reference.
+	 */
+
+	/* 
+	 * make sure we get clean buffers
+	 */
+	memset(&fpr_init,0, sizeof(fpr_init));
+	memset(&fpr_final,0, sizeof(fpr_final));
+
+	/*
+	 * ldfpX.a: we don't try to emulate anything but we must
+	 * invalidate the ALAT entry and execute updates, if any.
+	 */
+	if ( ld->x6_op != 0x2 ) {
+		/*
+		 * does the unaligned access
+		 */
+		memcpy(&fpr_init[0], (void *)ifa, len);
+		memcpy(&fpr_init[1], (void *)(ifa+len), len);
+
+		DPRINT(("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld->r1, ld->imm, ld->x6_sz));
+#ifdef DEBUG_UNALIGNED_TRAP
+		{ int i; char *c = (char *)&fpr_init;
+			printk("fpr_init= ");
+			for(i=0; i < len<<1; i++ ) {
+				printk("%02x ", c[i]&0xff);
+			}
+			printk("\n");
+		}
+#endif
+		/*
+		 * XXX fixme
+		 * Could optimize inlines by using ldfpX & 2 spills 
+		 */
+		switch( ld->x6_sz ) {
+			case 0:
+				mem2float_extended(&fpr_init[0], &fpr_final[0]);
+				mem2float_extended(&fpr_init[1], &fpr_final[1]);
+				break;
+			case 1:
+				mem2float_integer(&fpr_init[0], &fpr_final[0]);
+				mem2float_integer(&fpr_init[1], &fpr_final[1]);
+				break;
+			case 2:
+				mem2float_single(&fpr_init[0], &fpr_final[0]);
+				mem2float_single(&fpr_init[1], &fpr_final[1]);
+				break;
+			case 3:
+				mem2float_double(&fpr_init[0], &fpr_final[0]);
+				mem2float_double(&fpr_init[1], &fpr_final[1]);
+				break;
+		}
+#ifdef DEBUG_UNALIGNED_TRAP
+		{ int i; char *c = (char *)&fpr_final;
+			printk("fpr_final= ");
+			for(i=0; i < len<<1; i++ ) {
+				printk("%02x ", c[i]&0xff);
+			}
+			printk("\n");
+		}
+#endif
+		/*
+		 * XXX fixme
+		 *
+		 * A possible optimization would be to drop fpr_final
+		 * and directly use the storage from the saved context i.e.,
+		 * the actual final destination (pt_regs, switch_stack or tss).
+		 */
+		setfpreg(ld->r1, &fpr_final[0], regs);
+		setfpreg(ld->imm, &fpr_final[1], regs);
+	}
+
+	/*
+	 * Check for updates: only immediate updates are available for this
+	 * instruction.
+	 */
+	if ( ld->m ) {
+
+		/*
+		 * the immediate is implicit given the ldsz of the operation:
+		 * single: 8 (2x4) and for  all others it's 16 (2x8)
+		 */
+		ifa += len<<1;
+
+		/*
+		 * IMPORTANT: 
+		 * the fact that we force the NaT of r3 to zero is ONLY valid
+		 * as long as we don't come here with a ldfpX.s.
+		 * For this reason we keep this sanity check
+		 */
+		if ( ld->x6_op == 1 || ld->x6_op == 3 ) {
+			printk(KERN_ERR "%s: register update on speculative load pair, error\n", __FUNCTION__);	
+		}
+
+
+		setreg(ld->r3, ifa, 0, regs);
+	}
+
+	/*
+	 * Invalidate ALAT entries, if any, for both registers.
+	 */
+	if ( ld->x6_op == 0x2 ) {
+		invala_fr(ld->r1);
+		invala_fr(ld->imm);
+	}
+	return 0;
+}
+
+
+static int
+emulate_load_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+{
+	struct ia64_fpreg fpr_init;
+	struct ia64_fpreg fpr_final;
+	unsigned long len = float_fsz[ld->x6_sz];
+
+	/*
+	 * check for load pair because our masking scheme is not fine grain enough
+	if ( ld->x == 1 ) return emulate_load_floatpair(ifa,ld,regs);
+	 */
+
+	if ( access_ok(VERIFY_READ, (void *)ifa, len) < 0 ) {
+		DPRINT(("verify area failed on %lx\n", ifa));
+		return -1;
+	}
+	/*
+	 * fr0 & fr1 don't need to be checked because Illegal Instruction
+	 * faults have higher priority than unaligned faults.
+	 *
+	 * r0 cannot be found as the base as it would never generate an 
+	 * unaligned reference.
+	 */
+
+
+	/* 
+	 * make sure we get clean buffers
+	 */
+	memset(&fpr_init,0, sizeof(fpr_init));
+	memset(&fpr_final,0, sizeof(fpr_final));
+
+	/*
+	 * ldfX.a we don't try to emulate anything but we must
+	 * invalidate the ALAT entry.
+	 * See comments in ldX for descriptions on how the various loads are handled.
+	 */
+	if ( ld->x6_op != 0x2 ) {
+
+		/*
+		 * does the unaligned access
+		 */
+		memcpy(&fpr_init, (void *)ifa, len);
+
+		DPRINT(("ld.r1=%d x6_sz=%d\n", ld->r1, ld->x6_sz));
+#ifdef DEBUG_UNALIGNED_TRAP
+		{ int i; char *c = (char *)&fpr_init;
+			printk("fpr_init= ");
+			for(i=0; i < len; i++ ) {
+				printk("%02x ", c[i]&0xff);
+			}
+			printk("\n");
+		}
+#endif
+		/*
+		 * we only do something for x6_op={0,8,9}
+		 */
+		switch( ld->x6_sz ) {
+			case 0:
+				mem2float_extended(&fpr_init, &fpr_final);
+				break;
+			case 1:
+				mem2float_integer(&fpr_init, &fpr_final);
+				break;
+			case 2:
+				mem2float_single(&fpr_init, &fpr_final);
+				break;
+			case 3:
+				mem2float_double(&fpr_init, &fpr_final);
+				break;
+		}
+#ifdef DEBUG_UNALIGNED_TRAP
+		{ int i; char *c = (char *)&fpr_final;
+			printk("fpr_final= ");
+			for(i=0; i < len; i++ ) {
+				printk("%02x ", c[i]&0xff);
+			}
+			printk("\n");
+		}
+#endif
+		/*
+		 * XXX fixme
+		 *
+		 * A possible optimization would be to drop fpr_final
+		 * and directly use the storage from the saved context i.e.,
+		 * the actual final destination (pt_regs, switch_stack or tss).
+		 */
+		setfpreg(ld->r1, &fpr_final, regs);
+	}
+
+	/*
+	 * check for updates on any loads
+	 */
+	if ( ld->op == 0x7 || ld->m )
+		emulate_load_updates(ld->op == 0x7 ? UPD_IMMEDIATE: UPD_REG, 
+				ld, regs, ifa);
+
+
+	/*
+	 * invalidate ALAT entry in case of advanced floating point loads
+	 */
+	if (ld->x6_op == 0x2)
+		invala_fr(ld->r1);
+
+	return 0;
+}
+
+
+static int
+emulate_store_float(unsigned long ifa, load_store_t *ld, struct pt_regs *regs)
+{
+	struct ia64_fpreg fpr_init;
+	struct ia64_fpreg fpr_final;
+	unsigned long len = float_fsz[ld->x6_sz];
+	
+	/*
+	 * the macro supposes sequential access (which is the case)
+	 * if the first byte is an invalid address we return here. Otherwise
+	 * there is a guard page at the top of the user's address page and 
+	 * the first access would generate a NaT consumption fault and return
+	 * with a SIGSEGV, which is what we want.
+	 *
+	 * Note: the first argument is ignored 
+	 */
+	if ( access_ok(VERIFY_WRITE, (void *)ifa, len) < 0 ) {
+		DPRINT(("verify area failed on %lx\n",ifa));
+		return -1;
+	}
+
+	/* 
+	 * make sure we get clean buffers
+	 */
+	memset(&fpr_init,0, sizeof(fpr_init));
+	memset(&fpr_final,0, sizeof(fpr_final));
+
+
+	/*
+	 * if we get to this handler, Nat bits on both r3 and r2 have already
+	 * been checked. so we don't need to do it
+	 *
+	 * extract the value to be stored
+	 */
+	getfpreg(ld->imm, &fpr_init, regs);
+	/*
+	 * during this step, we extract the spilled registers from the saved
+	 * context i.e., we refill. Then we store (no spill) to temporary
+	 * aligned location
+	 */
+	switch( ld->x6_sz ) {
+		case 0:
+			float2mem_extended(&fpr_init, &fpr_final);
+			break;
+		case 1:
+			float2mem_integer(&fpr_init, &fpr_final);
+			break;
+		case 2:
+			float2mem_single(&fpr_init, &fpr_final);
+			break;
+		case 3:
+			float2mem_double(&fpr_init, &fpr_final);
+			break;
+	}
+	DPRINT(("ld.r1=%d x6_sz=%d\n", ld->r1, ld->x6_sz));
+#ifdef DEBUG_UNALIGNED_TRAP
+		{ int i; char *c = (char *)&fpr_init;
+			printk("fpr_init= ");
+			for(i=0; i < len; i++ ) {
+				printk("%02x ", c[i]&0xff);
+			}
+			printk("\n");
+		}
+		{ int i; char *c = (char *)&fpr_final;
+			printk("fpr_final= ");
+			for(i=0; i < len; i++ ) {
+				printk("%02x ", c[i]&0xff);
+			}
+			printk("\n");
+		}
+#endif
+
+	/*
+	 * does the unaligned store
+	 */
+	memcpy((void *)ifa, &fpr_final, len);
+
+	/*
+	 * stfX [r3]=r2,imm(9)
+	 *
+	 * NOTE:
+	 * ld->r3 can never be r0, because r0 would not generate an 
+	 * unaligned access.
+	 */
+	if ( ld->op == 0x7 ) {
+		unsigned long imm;
+
+		/*
+		 * form imm9: [12:6] contain first 7bits
+		 */
+		imm = ld->x << 7 | ld->r1;
+		/*
+		 * sign extend (8bits) if m set
+		 */
+		if ( ld->m ) imm |= SIGN_EXT9; 
+		/*
+		 * ifa == r3 (NaT is necessarily cleared)
+		 */
+		ifa += imm;
+
+		DPRINT(("imm=%lx r3=%lx\n", imm, ifa));
+	
+		setreg(ld->r3, ifa, 0, regs);
+	}
+	/*
+	 * we don't have alat_invalidate_multiple() so we need
+	 * to do the complete flush :-<<
+	 */
+	ia64_invala();
+
+	return 0;
+}
+
+void
+ia64_handle_unaligned(unsigned long ifa, struct pt_regs *regs)
+{
+	static unsigned long unalign_count;
+	static long last_time;
+
+	struct ia64_psr *ipsr = ia64_psr(regs);
+	unsigned long *bundle_addr;
+	unsigned long opcode;
+	unsigned long op;
+	load_store_t *insn;
+	int ret = -1;
+
+	/*
+	 * We flag unaligned references while in kernel as
+	 * errors: the kernel must be fixed. The switch code
+	 * is in ivt.S at entry 30.
+	 *
+	 * So here we keep a simple sanity check.
+	 */
+	if ( !user_mode(regs) ) {
+		die_if_kernel("Unaligned reference while in kernel\n", regs, 30);
+		/* NOT_REACHED */
+	}
+
+	/*
+	 * Make sure we log the unaligned access, so that user/sysadmin can notice it
+	 * and eventually fix the program.
+	 *
+	 * We don't want to do that for every access so we pace it with jiffies.
+	 */
+	if ( unalign_count > 5 && jiffies - last_time > 5*HZ )  unalign_count = 0;
+	if ( ++unalign_count < 5 ) {
+		last_time = jiffies;
+		printk("%s(%d): unaligned trap accessing %016lx (ip=%016lx)\n",
+			current->comm, current->pid, ifa, regs->cr_iip + ipsr->ri);
+		
+	}
+
+	DPRINT(("iip=%lx ifa=%lx isr=%lx\n", regs->cr_iip, ifa, regs->cr_ipsr));
+	DPRINT(("ISR.ei=%d ISR.sp=%d\n", ipsr->ri, ipsr->it));
+
+	bundle_addr = (unsigned long *)(regs->cr_iip);
+
+	/*
+	 * extract the instruction from the bundle given the slot number
+	 */
+	switch ( ipsr->ri ) {
+		case 0: op = *bundle_addr >> 5;
+			break;
+
+		case 1: op = *bundle_addr >> 46 | (*(bundle_addr+1) & 0x7fffff)<<18;
+			break;
+
+		case 2: op = *(bundle_addr+1) >> 23;
+		 	break;
+	}
+
+	insn   = (load_store_t *)&op;
+	opcode = op & IA64_OPCODE_MASK;
+
+	DPRINT(("opcode=%lx ld.qp=%d ld.r1=%d ld.imm=%d ld.r3=%d ld.x=%d ld.hint=%d "
+		"ld.x6=0x%x ld.m=%d ld.op=%d\n",
+		opcode,
+		insn->qp,
+		insn->r1,
+		insn->imm,
+		insn->r3,
+		insn->x,
+		insn->hint,
+		insn->x6_sz,
+		insn->m,
+		insn->op));
+
+	/*
+  	 * IMPORTANT:
+	 * Notice that the swictch statement DOES not cover all possible instructions
+	 * that DO generate unaligned references. This is made on purpose because for some
+	 * instructions it DOES NOT make sense to try and emulate the access. Sometimes it
+	 * is WRONG to try and emulate. Here is a list of instruction we don't emulate i.e.,
+	 * the program will get a signal and die:
+	 *
+	 *	load/store:
+	 *		- ldX.spill
+	 *		- stX.spill
+	 * 	Reason: RNATs are based on addresses
+	 *
+	 *	synchronization:
+	 *		- cmpxchg
+	 *		- fetchadd
+	 *		- xchg
+	 * 	Reason: ATOMIC operations cannot be emulated properly using multiple 
+	 * 	        instructions.
+	 *
+	 *	speculative loads:
+	 *		- ldX.sZ
+	 *	Reason: side effects, code must be ready to deal with failure so simpler 
+	 * 		to let the load fail.
+	 * ---------------------------------------------------------------------------------
+	 * XXX fixme
+	 *
+	 * I would like to get rid of this switch case and do something
+	 * more elegant.
+	 */
+	switch(opcode) {
+		case LDS_OP:
+		case LDSA_OP:
+		case LDS_IMM_OP:
+		case LDSA_IMM_OP:
+		case LDFS_OP:
+		case LDFSA_OP:
+		case LDFS_IMM_OP:
+			/*
+			 * The instruction will be retried with defered exceptions
+			 * turned on, and we should get Nat bit installed
+			 *
+			 * IMPORTANT:
+			 * When PSR_ED is set, the register & immediate update
+			 * forms are actually executed even though the operation
+			 * failed. So we don't need to take care of this.
+			 */
+			DPRINT(("forcing PSR_ED\n"));
+			regs->cr_ipsr |= IA64_PSR_ED;
+			return;
+
+		case LD_OP:
+		case LDA_OP:
+		case LDBIAS_OP:
+		case LDACQ_OP:
+		case LDCCLR_OP:
+		case LDCNC_OP:
+		case LDCCLRACQ_OP:
+		case LD_IMM_OP:
+		case LDA_IMM_OP:
+		case LDBIAS_IMM_OP:
+		case LDACQ_IMM_OP:
+		case LDCCLR_IMM_OP:
+		case LDCNC_IMM_OP:
+		case LDCCLRACQ_IMM_OP:
+			ret = emulate_load_int(ifa, insn, regs);
+			break;
+		case ST_OP:
+		case STREL_OP:
+		case ST_IMM_OP:
+		case STREL_IMM_OP:
+			ret = emulate_store_int(ifa, insn, regs);
+			break;
+		case LDF_OP:
+		case LDFA_OP:
+		case LDFCCLR_OP:
+		case LDFCNC_OP:
+		case LDF_IMM_OP:
+		case LDFA_IMM_OP:
+		case LDFCCLR_IMM_OP:
+		case LDFCNC_IMM_OP:
+			ret = insn->x ? 
+			      emulate_load_floatpair(ifa, insn, regs):
+			      emulate_load_float(ifa, insn, regs);
+			break;
+		case STF_OP:
+		case STF_IMM_OP:
+			ret = emulate_store_float(ifa, insn, regs);
+	}
+
+	DPRINT(("ret=%d\n", ret));
+	if ( ret ) {
+		lock_kernel();
+	        force_sig(SIGSEGV, current);
+	        unlock_kernel();
+	} else {
+		/*
+	 	 * given today's architecture this case is not likely to happen
+	 	 * because a memory access instruction (M) can never be in the 
+	 	 * last slot of a bundle. But let's keep it for  now.
+	 	 */
+		if ( ipsr->ri == 2 ) regs->cr_iip += 16;
+		ipsr->ri = ++ipsr->ri & 3;
+	}
+
+	DPRINT(("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip));
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/kernel/unwind.c linux/arch/ia64/kernel/unwind.c
--- v2.3.42/linux/arch/ia64/kernel/unwind.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/unwind.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/unwind.h>
+
+void
+ia64_unwind_init_from_blocked_task (struct ia64_frame_info *info, struct task_struct *t)
+{
+	struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
+	unsigned long sol, limit, top;
+
+	memset(info, 0, sizeof(*info));
+
+	sol = (sw->ar_pfs >> 7) & 0x7f;	/* size of locals */
+
+	limit = (unsigned long) t + IA64_RBS_OFFSET;
+	top   = sw->ar_bspstore;
+	if (top - (unsigned long) t >= IA64_STK_OFFSET)
+		top = limit;
+
+	info->regstk.limit = (unsigned long *) limit;
+	info->regstk.top   = (unsigned long *) top;
+	info->bsp	   = ia64_rse_skip_regs(info->regstk.top, -sol);
+	info->top_rnat	   = sw->ar_rnat;
+	info->cfm	   = sw->ar_pfs;
+	info->ip	   = sw->b0;
+}
+
+void
+ia64_unwind_init_from_current (struct ia64_frame_info *info, struct pt_regs *regs)
+{
+	struct switch_stack *sw = (struct switch_stack *) regs - 1;
+	unsigned long sol, sof, *bsp, limit, top;
+
+	limit = (unsigned long) current + IA64_RBS_OFFSET;
+	top   = sw->ar_bspstore;
+	if (top - (unsigned long) current >= IA64_STK_OFFSET)
+		top = limit;
+
+	memset(info, 0, sizeof(*info));
+
+	sol = (sw->ar_pfs >> 7) & 0x7f;	/* size of frame */
+	info->regstk.limit = (unsigned long *) limit;
+	info->regstk.top   = (unsigned long *) top;
+	info->top_rnat	   = sw->ar_rnat;
+
+	/* this gives us the bsp top level frame (kdb interrupt frame): */
+	bsp = ia64_rse_skip_regs((unsigned long *) top, -sol);
+
+	/* now skip past the interrupt frame: */
+	sof = regs->cr_ifs & 0x7f;	/* size of frame */
+	info->cfm = regs->cr_ifs;
+	info->bsp = ia64_rse_skip_regs(bsp, -sof);
+	info->ip  = regs->cr_iip;
+}
+
+static unsigned long
+read_reg (struct ia64_frame_info *info, int regnum, int *is_nat)
+{
+	unsigned long *addr, *rnat_addr, rnat;
+
+	addr = ia64_rse_skip_regs(info->bsp, regnum);
+	if (addr < info->regstk.limit || addr >= info->regstk.top || ((long) addr & 0x7) != 0) {
+		*is_nat = 1;
+		return 0xdeadbeefdeadbeef;
+	}
+	rnat_addr = ia64_rse_rnat_addr(addr);
+
+	if (rnat_addr >= info->regstk.top)
+		rnat = info->top_rnat;
+	else
+		rnat = *rnat_addr;
+	*is_nat = (rnat & (1UL << ia64_rse_slot_num(addr))) != 0;
+	return *addr;
+}
+
+/*
+ * On entry, info->regstk.top should point to the register backing
+ * store for r32.
+ */
+int
+ia64_unwind_to_previous_frame (struct ia64_frame_info *info)
+{
+	unsigned long sol, cfm = info->cfm;
+	int is_nat;
+
+	sol = (cfm >> 7) & 0x7f;	/* size of locals */
+
+	/*
+	 * In general, we would have to make use of unwind info to
+	 * unwind an IA-64 stack, but for now gcc uses a special
+	 * convention that makes this possible without full-fledged
+	 * unwindo info.  Specifically, we expect "rp" in the second
+	 * last, and "ar.pfs" in the last local register, so the
+	 * number of locals in a frame must be at least two.  If it's
+	 * less than that, we reached the end of the C call stack.
+	 */
+	if (sol < 2)
+		return -1;
+
+	info->ip = read_reg(info, sol - 2, &is_nat);
+	if (is_nat)
+		return -1;
+
+	cfm = read_reg(info, sol - 1, &is_nat);
+	if (is_nat)
+		return -1;
+
+	sol = (cfm >> 7) & 0x7f;
+
+	info->cfm = cfm;
+	info->bsp = ia64_rse_skip_regs(info->bsp, -sol);
+	return 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/Makefile linux/arch/ia64/lib/Makefile
--- v2.3.42/linux/arch/ia64/lib/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,42 @@
+#
+# Makefile for ia64-specific library routines..
+#
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $@
+
+OBJS  = __divdi3.o __divsi3.o __udivdi3.o __udivsi3.o		\
+	__moddi3.o __modsi3.o __umoddi3.o __umodsi3.o		\
+	checksum.o clear_page.o csum_partial_copy.o copy_page.o	\
+	copy_user.o clear_user.o memset.o strncpy_from_user.o	\
+	strlen.o strlen_user.o strnlen_user.o			\
+	flush.o do_csum.o
+
+lib.a: $(OBJS)
+	$(AR) rcs lib.a $(OBJS)
+
+__divdi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -o $@ $<
+
+__divsi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -DSINGLE -c -o $@ $<
+
+__udivdi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -DUNSIGNED -c -o $@ $<
+
+__udivsi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -DUNSIGNED -DSINGLE -c -o $@ $<
+
+__moddi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -DMODULO -c -o $@ $<
+
+__modsi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -DMODULO -DSINGLE -c -o $@ $<
+
+__umoddi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -c -o $@ $<
+
+__umodsi3.o: idiv.S
+	$(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -DSINGLE -c -o $@ $<
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/checksum.c linux/arch/ia64/lib/checksum.c
--- v2.3.42/linux/arch/ia64/lib/checksum.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/checksum.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,110 @@
+/*
+ * Network checksum routines
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * Most of the code coming from arch/alpha/lib/checksum.c
+ *
+ * This file contains network checksum routines that are better done
+ * in an architecture-specific manner due to speed..
+ */
+ 
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+
+static inline unsigned short
+from64to16(unsigned long x)
+{
+	/* add up 32-bit words for 33 bits */
+	x = (x & 0xffffffff) + (x >> 32);
+	/* add up 16-bit and 17-bit words for 17+c bits */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up 16-bit and 2-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+unsigned short int csum_tcpudp_magic(unsigned long saddr,
+				   unsigned long daddr,
+				   unsigned short len,
+				   unsigned short proto,
+				   unsigned int sum)
+{
+	return ~from64to16(saddr + daddr + sum +
+		((unsigned long) ntohs(len) << 16) +
+		((unsigned long) proto << 8));
+}
+
+unsigned int csum_tcpudp_nofold(unsigned long saddr,
+				   unsigned long daddr,
+				   unsigned short len,
+				   unsigned short proto,
+				   unsigned int sum)
+{
+	unsigned long result;
+
+	result = (saddr + daddr + sum +
+		  ((unsigned long) ntohs(len) << 16) +
+		  ((unsigned long) proto << 8));
+
+	/* Fold down to 32-bits so we don't loose in the typedef-less 
+	   network stack.  */
+	/* 64 to 33 */
+	result = (result & 0xffffffff) + (result >> 32);
+	/* 33 to 32 */
+	result = (result & 0xffffffff) + (result >> 32);
+	return result;
+}
+
+extern unsigned long do_csum(const unsigned char *, unsigned int, unsigned int);
+extern unsigned long do_csum_c(const unsigned char *, unsigned int, unsigned int);
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ */
+unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+	return ~do_csum(iph,ihl*4,0);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+{
+	unsigned long result = do_csum(buff, len, 0);
+
+	/* add in old sum, and carry.. */
+	result += sum;
+	/* 32+c bits -> 32 bits */
+	result = (result & 0xffffffff) + (result >> 32);
+	return result;
+}
+
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+	return ~do_csum(buff,len, 0);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/clear_page.S linux/arch/ia64/lib/clear_page.S
--- v2.3.42/linux/arch/ia64/lib/clear_page.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/clear_page.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,42 @@
+/*
+ *
+ * Optimized version of the standard clearpage() function
+ *
+ * Based on comments from ddd. Try not to overflow the write buffer.
+ *
+ * Inputs:
+ *	in0:	address of page
+ * 
+ * Output:
+ * 	none
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <asm/page.h>
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+	.global clear_page
+	.proc clear_page
+clear_page:
+	alloc r11=ar.pfs,1,0,0,0
+	mov r16=ar.lc		// slow
+	mov r17=PAGE_SIZE/32-1	// -1 = repeat/until
+	;;
+	adds r18=16,in0
+	mov ar.lc=r17
+	;;
+1:	stf.spill.nta [in0]=f0,32
+	stf.spill.nta [r18]=f0,32
+	br.cloop.dptk.few 1b
+	;;
+	mov ar.lc=r16		// restore lc
+	br.ret.sptk.few rp
+
+	.endp clear_page
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/clear_user.S linux/arch/ia64/lib/clear_user.S
--- v2.3.42/linux/arch/ia64/lib/clear_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/clear_user.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,224 @@
+/*
+ * This routine clears to zero a linear memory buffer in user space.
+ *
+ * Inputs:
+ *	in0:	address of buffer
+ *	in1:	length of buffer in bytes
+ * Outputs:
+ *	r8:	number of bytes that didn't get cleared due to a fault
+ * 
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ */
+
+//
+// arguments
+//
+#define buf		r32
+#define len		r33
+
+//
+// local registers
+//
+#define cnt		r16
+#define buf2		r17
+#define saved_lc	r18
+#define saved_pr	r19
+#define saved_pfs	r20
+#define tmp		r21
+#define len2		r22
+#define len3		r23
+
+//
+// Theory of operations:
+//	- we check whether or not the buffer is small, i.e., less than 17
+//	  in which case we do the byte by byte loop.
+//
+//	- Otherwise we go progressively from 1 byte store to 8byte store in
+//	  the head part, the body is a 16byte store loop and we finish we the
+//	  tail for the last 15 bytes.
+//	  The good point about this breakdown is that the long buffer handling
+//	  contains only 2 branches.
+//
+//	The reason for not using shifting & masking for both the head and the
+//	tail is to stay semantically correct. This routine is not supposed
+//	to write bytes outside of the buffer. While most of the time this would
+//	be ok, we can't tolerate a mistake. A classical example is the case
+//	of multithreaded code were to the extra bytes touched is actually owned
+//	by another thread which runs concurrently to ours. Another, less likely,
+//	example is with device drivers where reading an I/O mapped location may
+//	have side effects (same thing for writing).
+//
+
+// The label comes first because our store instruction contains a comma
+// and confuse the preprocessor otherwise
+//
+#define EX(y,x...)				\
+	.section __ex_table,"a";		\
+	data4 @gprel(99f);			\
+	data4 y-99f;				\
+	.previous;				\
+99:	x
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+ 	.global	__do_clear_user
+ 	.proc	__do_clear_user
+
+__do_clear_user:
+ 	alloc	saved_pfs=ar.pfs,2,0,0,0
+	cmp.eq p6,p0=r0,len		// check for zero length
+	mov saved_lc=ar.lc		// preserve ar.lc (slow)
+	;;				// avoid WAW on CFM
+	adds tmp=-1,len			// br.ctop is repeat/until
+	mov ret0=len			// return value is length at this point
+(p6)	br.ret.spnt.few rp
+	;;
+	cmp.lt p6,p0=16,len		// if len > 16 then long memset
+	mov ar.lc=tmp			// initialize lc for small count 
+(p6)	br.cond.dptk.few long_do_clear
+	;;				// WAR on ar.lc
+	//
+	// worst case 16 cyles, avg 8 cycles
+	//
+	// We could have played with the predicates to use the extra
+	// M slot for 2 stores/iteration but the cost the initialization
+	// the various counters compared to how long the loop is supposed
+	// to last on average does not make this solution viable.
+	//
+1:	
+	EX( .Lexit1, st1 [buf]=r0,1 )
+	adds len=-1,len			// countdown length using len
+	br.cloop.dptk.few 1b
+	;;				// avoid RAW on ar.lc
+	//
+	// .Lexit4: comes from byte by byte loop
+	//	    len contains bytes left
+.Lexit1:			
+	mov ret0=len			// faster than using ar.lc
+	mov ar.lc=saved_lc
+	br.ret.sptk.few rp		// end of short clear_user
+
+
+	//
+	// At this point we know we have more than 16 bytes to copy
+	// so we focus on alignment (no branches required)
+	//
+	// The use of len/len2 for countdown of the number of bytes left
+	// instead of ret0 is due to the fact that the exception code 
+	// changes the values of r8.
+	//
+long_do_clear:
+	tbit.nz p6,p0=buf,0		// odd alignment (for long_do_clear)
+	;;
+	EX( .Lexit3, (p6) st1 [buf]=r0,1 )	// 1-byte aligned
+(p6)	adds len=-1,len;;		// sync because buf is modified
+	tbit.nz p6,p0=buf,1
+	;;
+	EX( .Lexit3, (p6) st2 [buf]=r0,2 )	// 2-byte aligned
+(p6)	adds len=-2,len;;
+	tbit.nz p6,p0=buf,2
+	;;
+	EX( .Lexit3, (p6) st4 [buf]=r0,4 )	// 4-byte aligned
+(p6)	adds len=-4,len;;
+	tbit.nz p6,p0=buf,3
+	;;
+	EX( .Lexit3, (p6) st8 [buf]=r0,8 )	// 8-byte aligned
+(p6)	adds len=-8,len;;
+	shr.u cnt=len,4		// number of 128-bit (2x64bit) words
+	;;	
+	cmp.eq p6,p0=r0,cnt
+	adds tmp=-1,cnt
+(p6)	br.cond.dpnt.few .dotail 	// we have less than 16 bytes left
+	;;
+	adds buf2=8,buf			// setup second base pointer
+	mov ar.lc=tmp
+	;;
+
+	//
+	// 16bytes/iteration core loop
+	//
+	// The second store can never generate a fault because 
+	// we come into the loop only when we are 16-byte aligned.
+	// This means that if we cross a page then it will always be
+	// in the first store and never in the second.
+	//
+	// 
+	// We need to keep track of the remaining length. A possible (optimistic)
+	// way would be to ue ar.lc and derive how many byte were left by
+	// doing : left= 16*ar.lc + 16.  this would avoid the addition at
+	// every iteration. 
+	// However we need to keep the synchronization point. A template
+	// M;;MB does not exist and thus we can keep the addition at no
+	// extra cycle cost (use a nop slot anyway). It also simplifies the
+	// (unlikely)  error recovery code
+	//
+
+2:					
+
+	EX(.Lexit3, st8 [buf]=r0,16 )
+	;;				// needed to get len correct when error
+	st8 [buf2]=r0,16
+	adds len=-16,len		
+	br.cloop.dptk.few 2b
+	;;
+	mov ar.lc=saved_lc
+	// 
+	// tail correction based on len only
+	//
+	// We alternate the use of len3,len2 to allow parallelism and correct
+	// error handling. We also reuse p6/p7 to return correct value.
+	// The addition of len2/len3 does not cost anything more compared to
+	// the regular memset as we had empty slots.
+	//
+.dotail:				
+	mov len2=len			// for parallelization of error handling
+	mov len3=len
+	tbit.nz p6,p0=len,3	
+	;;
+	EX( .Lexit2, (p6) st8 [buf]=r0,8 )	// at least 8 bytes
+(p6)	adds len3=-8,len2
+	tbit.nz p7,p6=len,2	
+	;;
+	EX( .Lexit2, (p7) st4 [buf]=r0,4 )	// at least 4 bytes
+(p7)	adds len2=-4,len3
+	tbit.nz p6,p7=len,1
+	;;
+	EX( .Lexit2, (p6) st2 [buf]=r0,2 )	// at least 2 bytes
+(p6)	adds len3=-2,len2
+	tbit.nz p7,p6=len,0
+	;;
+	EX( .Lexit2, (p7) st1 [buf]=r0 )	// only 1 byte left
+	mov ret0=r0				// success
+	br.ret.dptk.few rp			// end of most likely path
+
+	//
+	// Outlined error handling code
+	//
+
+	//
+	// .Lexit3: comes from core loop, need restore pr/lc
+	//	    len contains bytes left
+	//
+	//
+	// .Lexit2:
+	// 	if p6 -> coming from st8 or st2 : len2 contains what's left
+	// 	if p7 -> coming from st4 or st1 : len3 contains what's left
+	// We must restore lc/pr even though might not have been used.
+.Lexit2:
+(p6)	mov len=len2
+(p7)	mov len=len3
+	;;
+	//
+	// .Lexit4: comes from head, need not restore pr/lc
+	//	    len contains bytes left
+	//
+.Lexit3:
+	mov ret0=len
+	mov ar.lc=saved_lc
+	br.ret.dptk.few rp
+ 	.endp
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/copy_page.S linux/arch/ia64/lib/copy_page.S
--- v2.3.42/linux/arch/ia64/lib/copy_page.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/copy_page.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,87 @@
+/*
+ *
+ * Optimized version of the standard copy_page() function
+ *
+ * Based on comments from ddd. Try not to overflow write buffer.
+ * 
+ * Inputs:
+ * 	in0:	address of target page
+ *	in1:	address of source page
+ * Output:
+ * 	no return value
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ */
+#include <asm/page.h>
+
+#define lcount		r16
+#define saved_pr	r17
+#define saved_lc	r18
+#define saved_pfs	r19
+#define src1		r20
+#define src2		r21
+#define tgt1		r22
+#define tgt2		r23
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+	.global copy_page
+	.proc copy_page
+
+copy_page:
+	alloc saved_pfs=ar.pfs,10,0,0,8	// we need 6 roatating (8 minimum)
+					// + 2 input
+
+	.rotr t1[4], t2[4]	// our 2 pipelines with depth of 4 each
+
+	mov saved_lc=ar.lc	// save ar.lc ahead of time
+	mov saved_pr=pr		// rotating predicates are preserved
+				// resgisters we must save.
+	mov src1=in1		// initialize 1st stream source 
+	adds src2=8,in1		// initialize 2nd stream source 
+	mov lcount=PAGE_SIZE/16-1 // as many 16bytes as there are on a page
+				  // -1 is because br.ctop is repeat/until
+
+	adds tgt2=8,in0		// initialize 2nd stream target
+	mov tgt1=in0		// initialize 1st stream target
+	;;
+	mov pr.rot=1<<16	// pr16=1 & pr[17-63]=0 , 63 not modified
+
+	mov ar.lc=lcount	// set loop counter
+	mov ar.ec=4		// ar.ec must match pipeline depth
+	;;
+
+	// We need to preload the n-1 stages of the pipeline (n=depth).
+	// We do this during the "prolog" of the loop: we execute
+	// n-1 times the "load" bundle. Then both loads & stores are
+	// enabled until we reach the end of the last word of the page
+	// on the load side. Then, we enter the epilogue (controlled by ec)
+	// where we just do the stores and no loads n-1 times : drain the pipe.
+	//
+	// The initialization of the prolog is done via the predicate registers:
+	// the choice of pr19 DEPENDS on the depth of the pipeline (n).
+	// When lc > 0 pr63=1 and it is fed back into pr16 and pr16-pr62 
+	// are then shifted right at every iteration,
+	// Thus by initializing pr16=1 and pr17-19=0 (19=16+4-1) before the loop
+	// we get pr19=1 after 4 iterations (n in our case).
+	//
+1:				// engage loop now, let the magic happen...
+(p16)	ld8 t1[0]=[src1],16	// new data on top of pipeline in 1st stream
+(p16)	ld8 t2[0]=[src2],16	// new data on top of pipeline in 2nd stream
+	nop.i 0x0
+(p19)	st8 [tgt1]=t1[3],16	// store top of  1st pipeline
+(p19)	st8 [tgt2]=t2[3],16	// store top of 2nd pipeline
+	br.ctop.dptk.few 1b	// once lc==0, ec-- & p16=0
+				// stores but no loads anymore
+	;;
+	mov pr=saved_pr,0xffffffffffff0000	// restore predicates
+	mov ar.pfs=saved_pfs	// restore ar.ec 
+	mov ar.lc=saved_lc	// restore saved lc
+	br.ret.sptk.few rp	// bye...
+
+	.endp copy_page
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/copy_user.S linux/arch/ia64/lib/copy_user.S
--- v2.3.42/linux/arch/ia64/lib/copy_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/copy_user.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,71 @@
+/*
+ * This routine copies a linear memory buffer across the user/kernel boundary.  When
+ * reading a byte from the source causes a fault, the remainder of the destination
+ * buffer is zeroed out.  Note that this can happen only when copying from user
+ * to kernel memory and we do this to absolutely guarantee that the
+ * kernel doesn't operate on random data.
+ *
+ * This file is derived from arch/alpha/lib/copy_user.S.
+ *
+ * Inputs:
+ *	in0:	address of destination buffer
+ *	in1:	address of source buffer
+ *	in2:	length of buffer in bytes
+ * Outputs:
+ *	r8:	number of bytes that didn't get copied due to a fault
+ * 
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define EXI(x...)				\
+99:	x;					\
+	.section __ex_table,"a";		\
+	data4 @gprel(99b);			\
+	data4 .Lexit_in-99b;			\
+	.previous
+
+#define EXO(x...)				\
+99:	x;					\
+	.section __ex_table,"a";		\
+	data4 @gprel(99b);			\
+	data4 .Lexit_out-99b;			\
+	.previous
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+	.global __copy_user
+	.proc __copy_user
+__copy_user:
+	alloc r10=ar.pfs,3,0,0,0
+	mov r9=ar.lc		// save ar.lc
+	mov ar.lc=in2		// set ar.lc to length of buffer
+	br.sptk.few .Lentr
+
+	// XXX braindead copy loop---this needs to be optimized
+.Loop1:
+	EXI(ld1 r8=[in1],1)
+	;;
+	EXO(st1 [in0]=r8,1)
+.Lentr:	br.cloop.dptk.few .Loop1	// repeat unless ar.lc--==0
+	;;			// avoid RAW on ar.lc
+.Lexit_out:
+	mov r8=ar.lc		// return how many bytes we _didn't_ copy
+	mov ar.lc=r9
+	br.ret.sptk.few rp
+
+.Lexit_in:
+	// clear the remainder of the buffer:
+	mov r8=ar.lc	// return how many bytes we _didn't_ copy
+.Loop2:
+	st1 [in0]=r0,1	// this cannot fault because we get here only on user->kernel copies
+	br.cloop.dptk.few .Loop2
+	;;				// avoid RAW on ar.lc
+	mov ar.lc=r9
+	br.ret.sptk.few rp
+
+	.endp __copy_user
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/csum_partial_copy.c linux/arch/ia64/lib/csum_partial_copy.c
--- v2.3.42/linux/arch/ia64/lib/csum_partial_copy.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/csum_partial_copy.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,165 @@
+/*
+ * Network Checksum & Copy routine
+ * 
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * Most of the code has been imported from Linux/Alpha
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/uaccess.h>
+
+/*
+ * XXX Fixme: those 2 inlines are meant for debugging and will go away
+ */
+static inline unsigned
+short from64to16(unsigned long x)
+{
+	/* add up 32-bit words for 33 bits */
+	x = (x & 0xffffffff) + (x >> 32);
+	/* add up 16-bit and 17-bit words for 17+c bits */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up 16-bit and 2-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+static inline
+unsigned long do_csum_c(const unsigned char * buff, int len, unsigned int psum)
+{
+	int odd, count;
+	unsigned long result = (unsigned long)psum;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long) buff;
+	if (odd) {
+		result = *buff << 8;
+		len--;
+		buff++;
+	}
+	count = len >> 1;		/* nr of 16-bit words.. */
+	if (count) {
+		if (2 & (unsigned long) buff) {
+			result += *(unsigned short *) buff;
+			count--;
+			len -= 2;
+			buff += 2;
+		}
+		count >>= 1;		/* nr of 32-bit words.. */
+		if (count) {
+			if (4 & (unsigned long) buff) {
+				result += *(unsigned int *) buff;
+				count--;
+				len -= 4;
+				buff += 4;
+			}
+			count >>= 1;	/* nr of 64-bit words.. */
+			if (count) {
+				unsigned long carry = 0;
+				do {
+					unsigned long w = *(unsigned long *) buff;
+					count--;
+					buff += 8;
+					result += carry;
+					result += w;
+					carry = (w > result);
+				} while (count);
+				result += carry;
+				result = (result & 0xffffffff) + (result >> 32);
+			}
+			if (len & 4) {
+				result += *(unsigned int *) buff;
+				buff += 4;
+			}
+		}
+		if (len & 2) {
+			result += *(unsigned short *) buff;
+			buff += 2;
+		}
+	}
+	if (len & 1)
+		result += *buff;
+
+	result = from64to16(result);
+
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+
+out:
+	return result;
+}
+
+/*
+ * XXX Fixme
+ *
+ * This is very ugly but temporary. THIS NEEDS SERIOUS ENHANCEMENTS.
+ * But it's very tricky to get right even in C.
+ */
+extern unsigned long do_csum(const unsigned char *, int);
+
+static unsigned int
+do_csum_partial_copy_from_user (const char *src, char *dst, int len,
+				unsigned int psum, int *errp)
+{
+	const unsigned char *psrc = src;
+	unsigned long result;
+	int cplen = len;
+	int r = 0;
+
+	/* XXX Fixme
+	 * for now we separate the copy from checksum for obvious 
+	 * alignment difficulties. Look at the Alpha code and you'll be
+	 * scared.
+	 */
+
+	while ( cplen-- ) r |=__get_user(*dst++,psrc++);
+
+	if ( r && errp ) *errp = r;
+
+	result = do_csum(src, len);
+
+	/* add in old sum, and carry.. */
+	result += psum;
+	/* 32+c bits -> 32 bits */
+	result = (result & 0xffffffff) + (result >> 32);
+	return result;
+}
+
+unsigned int
+csum_partial_copy_from_user(const char *src, char *dst, int len,
+			    unsigned int sum, int *errp)
+{
+	if (!access_ok(src, len, VERIFY_READ)) {
+		*errp = -EFAULT;
+		memset(dst, 0, len);
+		return sum;
+	}
+
+	return do_csum_partial_copy_from_user(src, dst, len, sum, errp);
+}
+
+unsigned int
+csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
+{
+	return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
+}
+
+unsigned int
+csum_partial_copy (const char *src, char *dst, int len, unsigned int sum)
+{
+	unsigned int ret;
+	int error = 0;
+
+	ret = do_csum_partial_copy_from_user(src, dst, len, sum, &error);
+	if (error)
+		printk("csum_partial_copy_old(): tell mingo to convert me!\n");
+
+	return ret;
+}
+
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/do_csum.S linux/arch/ia64/lib/do_csum.S
--- v2.3.42/linux/arch/ia64/lib/do_csum.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/do_csum.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,230 @@
+/*
+ *
+ * Optmized version of the standard do_csum() function
+ *
+ * Return: a 64bit quantity containing the 16bit Internet checksum
+ *
+ * Inputs:
+ *	in0: address of buffer to checksum (char *)
+ *	in1: length of the buffer (int)
+ * 
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ */
+
+//
+// Theory of operations:
+//	The goal is to go as quickly as possible to the point where
+//	we can checksum 8 bytes/loop. Before reaching that point we must
+//	take care of incorrect alignment of first byte.
+//
+//	The code hereafter also takes care of the "tail" part of the buffer
+//	before entering the core loop, if any. The checksum is a sum so it
+//	allows us to commute operations. So we do do the "head" and "tail"
+//	first to finish at full speed in the body. Once we get the head and
+//	tail values, we feed them into the pipeline, very handy initialization.
+//
+//	Of course we deal with the special case where the whole buffer fits
+//	into one 8 byte word. In this case we have only one entry in the pipeline.
+//
+//	We use a (3+1)-stage pipeline in the loop to account for possible
+//	load latency and also to accomodate for head and tail.
+//
+//	The end of the function deals with folding the checksum from 64bits
+//	down to 16bits taking care of the carry.
+//
+//	This version avoids synchronization in the core loop by also using a
+//	pipeline for the accumulation of the checksum in result[].
+//
+//	 p[]     
+//	|---|
+//     0|   | r32 : new value loaded in pipeline
+//	|---|
+//     1|   | r33 : in transit data
+//	|---|
+//     2|   | r34 : current value to add to checksum
+//	|---|
+//     3|   | r35 : previous value added to checksum (previous iteration)
+//      |---|
+//
+//	result[] 
+//	|---|
+//     0|   | r36 : new checksum
+//	|---|
+//     1|   | r37 : previous value of checksum
+//	|---|
+//     2|   | r38 : final checksum when out of the loop (after 2 epilogue rots)
+//	|---|
+//
+//
+// NOT YET DONE:
+//	- Take advantage of the MMI bandwidth to load more than 8byte per loop
+//	  iteration
+//	- use the lfetch instruction to augment the chances of the data being in
+//	  the cache when we need it.
+//	- Maybe another algorithm which would take care of the folding at the
+//	  end in a different manner
+//	- Work with people more knowledgeable than me on the network stack
+//	  to figure out if we could not split the function depending on the 
+//	  type of packet or alignment we get. Like the ip_fast_csum() routine
+//	  where we know we have at least 20bytes worth of data to checksum.
+//	- Look at RFCs about checksums to see whether or not we can do better
+//
+//	- Do a better job of handling small packets.
+//
+#define saved_pfs	r11
+#define hmask		r16
+#define tmask		r17
+#define first		r18
+#define firstval	r19
+#define firstoff	r20
+#define last		r21
+#define lastval		r22
+#define lastoff		r23
+#define saved_lc	r24
+#define saved_pr	r25
+#define tmp1		r26
+#define tmp2		r27
+#define tmp3		r28
+#define carry		r29
+
+#define buf		in0
+#define len		in1
+
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+// unsigned long do_csum(unsigned char *buf,int len)
+
+	.align 32
+	.global do_csum
+	.proc do_csum
+do_csum:
+	alloc saved_pfs=ar.pfs,2,8,0,8
+
+	.rotr p[4], result[3]
+	mov ret0=r0		// in case we have zero length
+	cmp4.lt p0,p6=r0,len	// check for zero length or negative (32bit len)
+	;;			// avoid WAW on CFM
+	mov tmp3=0x7		// a temporary mask/value
+	add tmp1=buf,len	// last byte's address
+(p6)	br.ret.spnt.few rp	// return if true (hope we can avoid that)
+
+	and firstoff=7,buf	// how many bytes off for first element
+	tbit.nz p10,p0=buf,0	// is buf an odd address ?
+	mov hmask=-1		// intialize head mask
+	;;
+
+	andcm first=buf,tmp3	// 8byte aligned down address of first element
+	mov tmask=-1		// initialize tail mask
+	adds tmp2=-1,tmp1	// last-1
+	;;
+	and lastoff=7,tmp1	// how many bytes off for last element
+	andcm last=tmp2,tmp3	// address of word containing last byte
+	mov saved_pr=pr		// preserve predicates (rotation)
+	;;
+	sub tmp3=last,first	// tmp3=distance from first to last
+	cmp.eq p8,p9=last,first	// everything fits in one word ?
+	sub tmp1=8,lastoff	// complement to lastoff
+
+	ld8 firstval=[first],8	// load,ahead of time, "first" word
+	shl tmp2=firstoff,3	// number of bits
+	;;
+	and tmp1=7, tmp1	// make sure that if tmp1==8 -> tmp1=0
+
+(p9)	ld8 lastval=[last]	// load,ahead of time, "last" word, if needed
+(p8)	mov lastval=r0		// we don't need lastval if first==last
+	mov result[1]=r0	// initialize result
+	;;
+
+	shl tmp1=tmp1,3		// number of bits
+	shl hmask=hmask,tmp2 	// build head mask, mask off [0,firstoff[
+	;;
+	shr.u tmask=tmask,tmp1	// build tail mask, mask off ]8,lastoff]
+	mov saved_lc=ar.lc	// save lc
+	;;
+(p8)	and hmask=hmask,tmask	// apply tail mask to head mask if 1 word only
+(p9)	and p[1]=lastval,tmask	// mask last it as appropriate
+	shr.u tmp3=tmp3,3	// we do 8 bytes per loop
+	;;
+	cmp.lt p6,p7=2,tmp3	// tmp3 > 2 ?
+	and p[2]=firstval,hmask	// and mask it as appropriate
+	add tmp1=-2,tmp3	// -2 = -1 (br.ctop) -1 (last-first)
+	;;
+	// XXX Fixme: not very nice initialization here
+	//
+	// Setup loop control registers: 
+	//
+	// tmp3=0 (1 word)   : lc=0, ec=2, p16=F
+	// tmp3=1 (2 words)  : lc=0, ec=3, p16=F
+	// tmp3=2 (3 words)  : lc=0, ec=4, p16=T
+	// tmp3>2 (4 or more): lc=tmp3-2, ec=4, p16=T
+	//
+	cmp.eq p8,p9=r0,tmp3	// tmp3 == 0 ?
+(p6)	mov ar.lc=tmp1
+(p7)	mov ar.lc=0
+	;;
+	cmp.lt p6,p7=1,tmp3	// tmp3 > 1 ?
+(p8)	mov ar.ec=2		// we need the extra rotation on result[]
+(p9)	mov ar.ec=3		// hard not to set it twice sometimes
+	;;
+	mov carry=r0			// initialize carry
+(p6)	mov ar.ec=4
+(p6)	mov pr.rot=0xffffffffffff0000	// p16=T, p18=T
+
+	cmp.ne p8,p0=r0,r0		// p8 is false
+	mov p[3]=r0			// make sure first compare fails
+(p7)	mov pr.rot=0xfffffffffffe0000	// p16=F, p18=T
+	;;
+1:
+(p16)	ld8 p[0]=[first],8		// load next
+(p8)	adds carry=1,carry		// add carry on prev_prev_value
+(p18)	add result[0]=result[1],p[2]	// new_res = prev_res + cur_val
+	cmp.ltu p8,p0=result[1],p[3]	// p8= prev_result < prev_val
+	br.ctop.dptk.few 1b		// loop until lc--==0
+	;;				// RAW on carry when loop exits
+ (p8)	adds carry=1,carry;;		// correct for carry on prev_value
+	add result[2]=carry,result[2];;	// add carry to final result
+	cmp.ltu p6,p7=result[2], carry	// check for new carry
+	;;
+(p6)	adds result[2]=1,result[1]	// correct if required
+	movl tmp3=0xffffffff
+	;;
+	// XXX Fixme
+	//
+	// now fold 64 into 16 bits taking care of carry
+	// that's not very good because it has lots of sequentiality
+	//
+	and tmp1=result[2],tmp3
+	shr.u tmp2=result[2],32
+	;;
+	add result[2]=tmp1,tmp2
+	shr.u tmp3=tmp3,16
+	;;
+	and tmp1=result[2],tmp3
+	shr.u tmp2=result[2],16
+	;;
+	add result[2]=tmp1,tmp2
+	;;
+	and tmp1=result[2],tmp3
+	shr.u tmp2=result[2],16
+	;;
+	add result[2]=tmp1,tmp2
+	;;
+	and tmp1=result[2],tmp3
+	shr.u tmp2=result[2],16
+	;;
+	add ret0=tmp1,tmp2
+	mov pr=saved_pr,0xffffffffffff0000
+	;;
+	// if buf was odd then swap bytes 
+	mov ar.pfs=saved_pfs		// restore ar.ec
+(p10)	mux1 ret0=ret0,@rev		// reverse word
+	;;
+	mov ar.lc=saved_lc
+(p10)	shr.u ret0=ret0,64-16	// + shift back to position = swap bytes
+	br.ret.sptk.few rp
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/flush.S linux/arch/ia64/lib/flush.S
--- v2.3.42/linux/arch/ia64/lib/flush.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/flush.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,37 @@
+/*
+ * Cache flushing routines.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <asm/page.h>
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 16
+	.global ia64_flush_icache_page
+	.proc ia64_flush_icache_page
+ia64_flush_icache_page:
+	alloc r2=ar.pfs,1,0,0,0
+	mov r3=ar.lc			// save ar.lc	
+	mov r8=PAGE_SIZE/64-1		// repeat/until loop
+	;;
+	mov ar.lc=r8
+	add r8=32,in0
+	;;
+.Loop1:	fc in0				// issuable on M0 only
+	add in0=64,in0
+	fc r8
+	add r8=64,r8
+	br.cloop.sptk.few .Loop1
+	;;
+	sync.i
+	;;
+	srlz.i
+	;;	
+	mov ar.lc=r3			// restore ar.lc
+	br.ret.sptk.few rp
+	.endp ia64_flush_icache_page
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/idiv.S linux/arch/ia64/lib/idiv.S
--- v2.3.42/linux/arch/ia64/lib/idiv.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/idiv.S	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,158 @@
+/*
+ * Integer division routine.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+/* Simple integer division.  It uses the straight forward division
+   algorithm.  This may not be the absolutely fastest way to do it,
+   but it's not horrible either.  According to ski, the worst case
+   scenario of dividing 0xffffffffffffffff by 1 takes 133 cycles.
+
+   An alternative would be to use an algorithm similar to the
+   floating point division algorithm (Newton-Raphson iteration),
+   but that approach is rather tricky (one has to be very careful
+   to get the last bit right...).
+
+   While this algorithm is straight-forward, it does use a couple
+   of neat ia-64 specific tricks:
+
+	- it uses the floating point unit to determine the initial
+	  shift amount (shift = floor(ld(x)) - floor(ld(y)))
+
+	- it uses predication to avoid a branch in the case where
+	  x < y (this is what p8 is used for)
+
+	- it uses rotating registers and the br.ctop branch to
+	  implement a software-pipelined loop that's unrolled
+	  twice (without any code expansion!)
+
+	- the code is relatively well scheduled to avoid unnecessary
+	  nops while maximizing parallelism
+*/
+
+#include <asm/break.h>
+
+	.text
+	.psr abi64
+#ifdef __BIG_ENDIAN__
+	.psr msb
+	.msb
+#else
+	.psr lsb
+	.lsb
+#endif
+
+#ifdef MODULO
+# define OP	mod
+# define Q	r9
+# define R	r8
+#else
+# define OP div
+# define Q	r8
+# define R	r9
+#endif
+
+#ifdef SINGLE
+# define PREC si
+#else
+# define PREC di
+#endif
+
+#ifdef UNSIGNED
+# define SGN		u
+# define INT_TO_FP(a,b)	fma.s0 a=b,f1,f0
+# define FP_TO_INT(a,b)	fcvt.fxu.trunc.s0 a=b
+#else
+# define SGN
+# define INT_TO_FP(a,b)	fcvt.xf a=b
+# define FP_TO_INT(a,b)	fcvt.fx.trunc.s0 a=b
+#endif
+
+#define PASTE1(a,b)	a##b
+#define PASTE(a,b)	PASTE1(a,b)
+#define NAME		PASTE(PASTE(__,SGN),PASTE(OP,PASTE(PREC,3)))
+
+	.align 32
+	.global NAME
+	.proc NAME
+NAME:
+
+	alloc r2=ar.pfs,2,6,0,8
+	mov r18=pr
+#ifdef SINGLE
+# ifdef UNSIGNED
+	zxt4 in0=in0
+	zxt4 in1=in1
+# else
+	sxt4 in0=in0
+	sxt4 in1=in1
+# endif
+	;;
+#endif
+
+#ifndef UNSIGNED
+	cmp.lt p6,p0=in0,r0	// x negative?
+	cmp.lt p7,p0=in1,r0	// y negative?
+	;;
+(p6)	sub in0=r0,in0		// make x positive
+(p7)	sub in1=r0,in1		// ditto for y
+	;;
+#endif
+
+	setf.sig f8=in0
+	mov r3=ar.lc		// save ar.lc
+	setf.sig f9=in1
+	;;
+	mov Q=0			// initialize q
+	mov R=in0		// stash away x in a static register
+	mov r16=1		// r16 = 1
+	INT_TO_FP(f8,f8)
+	cmp.eq p8,p0=0,in0	// x==0?
+	cmp.eq p9,p0=0,in1	// y==0?
+	;;
+	INT_TO_FP(f9,f9)
+(p8)	br.dpnt.few .L3
+(p9)	break __IA64_BREAK_KDB	// attempted division by zero (should never happen)
+	mov ar.ec=r0		// epilogue count = 0
+	;;
+	getf.exp r14=f8		// r14 = exponent of x
+	getf.exp r15=f9		// r15 = exponent of y
+	mov ar.lc=r0		// loop count = 0
+	;;
+	sub r17=r14,r15		// r17 = (exp of x - exp y) = shift amount
+	cmp.ge p8,p0=r14,r15
+	;;
+
+	.rotr y[2], mask[2]	// in0 and in1 may no longer be valid after
+				// the first write to a rotating register!
+
+(p8)	shl y[1]=in1,r17	// y[1]    = y<<shift
+(p8)	shl mask[1]=r16,r17	// mask[1] = 1<<shift
+
+(p8)	mov ar.lc=r17		// loop count = r17
+	;;
+.L1:
+(p8)	cmp.geu.unc p9,p0=R,y[1]// p9 = (x >= y[1])
+(p8)	shr.u mask[0]=mask[1],1	// prepare mask[0] and y[0] for next
+(p8)	shr.u y[0]=y[1],1	// iteration
+	;;
+(p9)	sub R=R,y[1]		// if (x >= y[1]), subtract y[1] from x
+(p9)	add Q=Q,mask[1]		// and set corresponding bit in q (Q)
+	br.ctop.dptk.few .L1	// repeated unless ar.lc-- == 0
+	;;
+.L2:
+#ifndef UNSIGNED
+# ifdef MODULO
+(p6)	sub R=r0,R		// set sign of remainder according to x
+# else
+(p6)	sub Q=r0,Q		// set sign of quotient
+	;;
+(p7)	sub Q=r0,Q
+# endif
+#endif
+.L3:
+	mov ar.pfs=r2		// restore ar.pfs
+	mov ar.lc=r3		// restore ar.lc
+	mov pr=r18,0xffffffffffff0000	// restore p16-p63
+	br.ret.sptk.few rp
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/memset.S linux/arch/ia64/lib/memset.S
--- v2.3.42/linux/arch/ia64/lib/memset.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/memset.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,111 @@
+/*
+ *
+ * Optimized version of the standard memset() function
+ *
+ * Return: none
+ *         
+ *
+ * Inputs:
+ *	in0:	address of buffer
+ * 	in1:	byte value to use for storing
+ *	in2:	length of the buffer
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ */
+
+
+// arguments
+//
+#define buf		r32
+#define val		r33
+#define len		r34
+
+//
+// local registers
+//
+#define saved_pfs	r14
+#define cnt		r18
+#define buf2		r19
+#define saved_lc	r20
+#define saved_pr	r21
+#define tmp		r22
+
+ 	.text
+ 	.psr	abi64
+ 	.psr	lsb
+
+ 	.align	16
+ 	.global	memset
+ 	.proc	memset
+
+memset:
+ 	alloc	saved_pfs=ar.pfs,3,0,0,0	// cnt is sink here
+	cmp.eq p8,p0=r0,len	// check for zero length
+	mov saved_lc=ar.lc	// preserve ar.lc (slow)
+	;; 
+	adds tmp=-1,len		// br.ctop is repeat/until
+	tbit.nz p6,p0=buf,0	// odd alignment
+(p8)	br.ret.spnt.few rp
+
+	cmp.lt p7,p0=16,len	// if len > 16 then long memset
+	mux1 val=val,@brcst	// prepare value
+(p7)	br.cond.dptk.few long_memset
+	;;
+	mov ar.lc=tmp		// initialize lc for small count
+	;;			// avoid RAW and WAW on ar.lc
+1:				// worst case 15 cyles, avg 8 cycles
+	st1 [buf]=val,1
+	br.cloop.dptk.few 1b
+	;;				// avoid RAW on ar.lc
+	mov ar.lc=saved_lc
+	mov ar.pfs=saved_pfs
+	br.ret.sptk.few rp	// end of short memset
+
+	// at this point we know we have more than 16 bytes to copy
+	// so we focus on alignment
+long_memset:
+(p6)	st1 [buf]=val,1		// 1-byte aligned
+(p6)	adds len=-1,len;;	// sync because buf is modified
+	tbit.nz p6,p0=buf,1
+	;;
+(p6)	st2 [buf]=val,2		// 2-byte aligned
+(p6)	adds len=-2,len;;
+	tbit.nz p6,p0=buf,2
+	;;
+(p6)	st4 [buf]=val,4		// 4-byte aligned
+(p6)	adds len=-4,len;;
+	tbit.nz p6,p0=buf,3
+	;;
+(p6)	st8 [buf]=val,8		// 8-byte aligned
+(p6)	adds len=-8,len;;
+	shr.u cnt=len,4		// number of 128-bit (2x64bit) words
+	;;	
+	cmp.eq p6,p0=r0,cnt
+	adds tmp=-1,cnt
+(p6)	br.cond.dpnt.few .dotail // we have less than 16 bytes left
+	;;
+	adds buf2=8,buf		// setup second base pointer
+	mov ar.lc=tmp
+	;;
+2:				// 16bytes/iteration
+	st8 [buf]=val,16
+	st8 [buf2]=val,16
+	br.cloop.dptk.few 2b
+	;;
+.dotail:			// tail correction based on len only
+	tbit.nz p6,p0=len,3	
+	;;
+(p6)	st8 [buf]=val,8		// at least 8 bytes
+	tbit.nz p6,p0=len,2	
+	;;
+(p6)	st4 [buf]=val,4		// at least 4 bytes
+	tbit.nz p6,p0=len,1
+	;;
+(p6)	st2 [buf]=val,2		// at least 2 bytes
+	tbit.nz p6,p0=len,0
+	mov ar.lc=saved_lc
+	;;
+(p6)	st1 [buf]=val		// only 1 byte left
+	br.ret.dptk.few rp
+ 	.endp
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/strlen.S linux/arch/ia64/lib/strlen.S
--- v2.3.42/linux/arch/ia64/lib/strlen.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/strlen.S	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,197 @@
+/*
+ *
+ * Optimized version of the standard strlen() function
+ *
+ *
+ * Inputs:
+ *	in0	address of string
+ * 
+ * Outputs: 
+ * 	ret0	the number of characters in the string (0 if empty string)
+ *         	does not count the \0
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * 09/24/99 S.Eranian add speculation recovery code
+ */
+
+//
+//
+// This is an enhanced version of the basic strlen. it includes a combination
+// of compute zero index (czx), parallel comparisons, speculative loads and
+// loop unroll using rotating registers.
+//
+// General Ideas about the algorithm:
+//	  The goal is to look at the string in chunks of 8 bytes.
+//	  so we need to do a few extra checks at the beginning because the
+//	  string may not be 8-byte aligned. In this case we load the 8byte
+//	  quantity which includes the start of the string and mask the unused
+//	  bytes with 0xff to avoid confusing czx.
+//	  We use speculative loads and software pipelining to hide memory 
+//	  latency and do read ahead safely. This way we defer any exception.
+//
+//	  Because we don't want the kernel to be relying on particular
+//	  settings of the DCR register, we provide recovery code in case
+//	  speculation fails. The recovery code is going to "redo" the work using
+//	  only normal loads. If we still get a fault then we generate a
+//	  kernel panic. Otherwise we return the strlen as usual.
+//
+//	  The fact that speculation may fail can be caused, for instance, by
+//	  the DCR.dm bit being set. In this case TLB misses are deferred, i.e.,
+//	  a NaT bit will be set if the translation is not present. The normal
+//	  load, on the other hand, will cause the translation to be inserted 
+//	  if the mapping exists.
+//
+//	  It should be noted that we execute recovery code only when we need
+//	  to use the data that has been speculatively loaded: we don't execute
+//	  recovery code on pure read ahead data.
+//
+// Remarks:
+//	- the cmp r0,r0 is used as a fast way to initialize a predicate 
+//	  register to 1. This is required to make sure that we get the parallel
+//	  compare correct.
+//
+//	- we don't use the epilogue counter to exit the loop but we need to set
+//	  it to zero beforehand.
+//
+//	- after the loop we must test for Nat values because neither the 
+//	  czx nor cmp instruction raise a NaT consumption fault. We must be
+//	  careful not to look too far for a Nat for which we don't care. 
+//	  For instance we don't need to look at a NaT in val2 if the zero byte
+//	  was in val1.
+//
+//	- Clearly performance tuning is required.
+//
+// 
+//
+#define saved_pfs	r11
+#define	tmp		r10
+#define base		r16
+#define orig		r17
+#define saved_pr	r18
+#define src		r19
+#define mask		r20
+#define val		r21
+#define val1		r22
+#define val2		r23
+
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+	.global strlen
+	.proc strlen
+strlen:
+	alloc saved_pfs=ar.pfs,11,0,0,8 // rotating must be multiple of 8
+
+	.rotr v[2], w[2]	// declares our 4 aliases
+
+	extr.u tmp=in0,0,3	// tmp=least significant 3 bits
+	mov orig=in0		// keep trackof initial byte address
+	dep src=0,in0,0,3	// src=8byte-aligned in0 address
+	mov saved_pr=pr		// preserve predicates (rotation)
+	;;
+	ld8 v[1]=[src],8	// must not speculate: can fail here
+	shl tmp=tmp,3		// multiply by 8bits/byte
+	mov mask=-1		// our mask
+	;;
+	ld8.s w[1]=[src],8	// speculatively load next
+	cmp.eq p6,p0=r0,r0	// sets p6 to true for cmp.and
+	sub tmp=64,tmp		// how many bits to shift our mask on the right
+	;;
+	shr.u	mask=mask,tmp	// zero enough bits to hold v[1] valuable part
+	mov ar.ec=r0		// clear epilogue counter (saved in ar.pfs)
+	;;
+	add base=-16,src	// keep track of aligned base
+	or v[1]=v[1],mask	// now we have a safe initial byte pattern
+	;;
+1:
+	ld8.s v[0]=[src],8	// speculatively load next 
+	czx1.r val1=v[1]	// search 0 byte from right 
+	czx1.r val2=w[1]	// search 0 byte from right following 8bytes
+	;;
+	ld8.s w[0]=[src],8	// speculatively load next to next
+	cmp.eq.and p6,p0=8,val1	// p6 = p6 and val1==8
+	cmp.eq.and p6,p0=8,val2	// p6 = p6 and mask==8
+(p6)	br.wtop.dptk.few 1b	// loop until p6 == 0
+	;;
+	//
+	// We must return try the recovery code iff
+	// val1_is_nat || (val1==8 && val2_is_nat)
+	//
+	// XXX Fixme
+	//	- there must be a better way of doing the test
+	//
+	cmp.eq  p8,p9=8,val1	// p6 = val1 had zero (disambiguate)
+#ifdef notyet
+	tnat.nz p6,p7=val1	// test NaT on val1
+#else
+	tnat.z p7,p6=val1	// test NaT on val1
+#endif
+(p6)	br.cond.spnt.few recover// jump to recovery if val1 is NaT
+	;;
+	//
+	// if we come here p7 is true, i.e., initialized for // cmp
+	//
+	cmp.eq.and  p7,p0=8,val1// val1==8?
+	tnat.nz.and p7,p0=val2	// test NaT if val2
+(p7)	br.cond.spnt.few recover// jump to recovery if val2 is NaT
+	;;
+(p8)	mov val1=val2		// the other test got us out of the loop
+(p8)	adds src=-16,src	// correct position when 3 ahead
+(p9)	adds src=-24,src	// correct position when 4 ahead
+	;;
+	sub ret0=src,orig	// distance from base
+	sub tmp=8,val1		// which byte in word
+	mov pr=saved_pr,0xffffffffffff0000
+	;;
+	sub ret0=ret0,tmp	// adjust 
+	mov ar.pfs=saved_pfs	// because of ar.ec, restore no matter what
+	br.ret.sptk.few rp	// end of normal execution
+
+	//
+	// Outlined recovery code when speculation failed
+	//
+	// This time we don't use speculation and rely on the normal exception
+	// mechanism. that's why the loop is not as good as the previous one
+	// because read ahead is not possible
+	//
+	// IMPORTANT:
+	// Please note that in the case of strlen() as opposed to strlen_user()
+	// we don't use the exception mechanism, as this function is not 
+	// supposed to fail. If that happens it means we have a bug and the 
+	// code will cause of kernel fault.
+	//
+	// XXX Fixme
+	//	- today we restart from the beginning of the string instead
+	//	  of trying to continue where we left off.
+	//
+recover:
+	ld8 val=[base],8	// will fail if unrecoverable fault
+	;;
+	or val=val,mask		// remask first bytes
+	cmp.eq p0,p6=r0,r0	// nullify first ld8 in loop
+	;;
+	//
+	// ar.ec is still zero here
+	//
+2:
+(p6)	ld8 val=[base],8	// will fail if unrecoverable fault
+	;;
+	czx1.r val1=val		// search 0 byte from right 
+	;;
+	cmp.eq p6,p0=8,val1	// val1==8 ?
+(p6)	br.wtop.dptk.few 2b	// loop until p6 == 0
+	sub ret0=base,orig	// distance from base
+	sub tmp=8,val1
+	mov pr=saved_pr,0xffffffffffff0000
+	;;
+	sub ret0=ret0,tmp	// length=now - back -1
+	mov ar.pfs=saved_pfs	// because of ar.ec, restore no matter what
+	br.ret.sptk.few rp	// end of sucessful recovery code
+
+	.endp strlen
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/strlen_user.S linux/arch/ia64/lib/strlen_user.S
--- v2.3.42/linux/arch/ia64/lib/strlen_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/strlen_user.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,213 @@
+/*
+ * Optimized version of the strlen_user() function
+ *
+ * Inputs:
+ *	in0	address of buffer
+ *
+ * Outputs:
+ *	ret0	0 in case of fault, strlen(buffer)+1 otherwise
+ * 
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * 01/19/99 S.Eranian heavily enhanced version (see details below)
+ * 09/24/99 S.Eranian added speculation recovery code
+ */
+
+//
+// int strlen_user(char *)
+// ------------------------
+// Returns:
+//	- length of string + 1
+//	- 0 in case an exception is raised
+//
+// This is an enhanced version of the basic strlen_user. it includes a 
+// combination of compute zero index (czx), parallel comparisons, speculative 
+// loads and loop unroll using rotating registers.
+//
+// General Ideas about the algorithm:
+//	  The goal is to look at the string in chunks of 8 bytes.
+//	  so we need to do a few extra checks at the beginning because the
+//	  string may not be 8-byte aligned. In this case we load the 8byte
+//	  quantity which includes the start of the string and mask the unused
+//	  bytes with 0xff to avoid confusing czx.
+//	  We use speculative loads and software pipelining to hide memory 
+//	  latency and do read ahead safely. This way we defer any exception.
+//
+//	  Because we don't want the kernel to be relying on particular
+//	  settings of the DCR register, we provide recovery code in case
+//	  speculation fails. The recovery code is going to "redo" the work using
+//	  only normal loads. If we still get a fault then we return an
+//	  error (ret0=0). Otherwise we return the strlen+1 as usual.
+//	  The fact that speculation may fail can be caused, for instance, by
+//	  the DCR.dm bit being set. In this case TLB misses are deferred, i.e.,
+//	  a NaT bit will be set if the translation is not present. The normal
+//	  load, on the other hand, will cause the translation to be inserted 
+//	  if the mapping exists.
+//
+//	  It should be noted that we execute recovery code only when we need
+//	  to use the data that has been speculatively loaded: we don't execute
+//	  recovery code on pure read ahead data.
+//
+// Remarks:
+//	- the cmp r0,r0 is used as a fast way to initialize a predicate 
+//	  register to 1. This is required to make sure that we get the parallel
+//	  compare correct.
+//
+//	- we don't use the epilogue counter to exit the loop but we need to set
+//	  it to zero beforehand.
+//
+//	- after the loop we must test for Nat values because neither the 
+//	  czx nor cmp instruction raise a NaT consumption fault. We must be
+//	  careful not to look too far for a Nat for which we don't care. 
+//	  For instance we don't need to look at a NaT in val2 if the zero byte
+//	  was in val1.
+//
+//	- Clearly performance tuning is required.
+//
+// 
+//
+
+#define EX(y,x...)				\
+	.section __ex_table,"a";		\
+	data4 @gprel(99f);			\
+	data4 y-99f;				\
+	.previous;				\
+99:	x
+
+#define saved_pfs	r11
+#define	tmp		r10
+#define base		r16
+#define orig		r17
+#define saved_pr	r18
+#define src		r19
+#define mask		r20
+#define val		r21
+#define val1		r22
+#define val2		r23
+
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+	.global __strlen_user
+	.proc __strlen_user
+__strlen_user:
+	alloc saved_pfs=ar.pfs,11,0,0,8
+
+	.rotr v[2], w[2]	// declares our 4 aliases
+
+	extr.u tmp=in0,0,3	// tmp=least significant 3 bits
+	mov orig=in0		// keep trackof initial byte address
+	dep src=0,in0,0,3	// src=8byte-aligned in0 address
+	mov saved_pr=pr		// preserve predicates (rotation)
+	;;
+	ld8.s v[1]=[src],8	// load the initial 8bytes (must speculate)
+	shl tmp=tmp,3		// multiply by 8bits/byte
+	mov mask=-1		// our mask
+	;;
+	ld8.s w[1]=[src],8	// load next 8 bytes in 2nd pipeline
+	cmp.eq p6,p0=r0,r0	// sets p6 (required because of // cmp.and)
+	sub tmp=64,tmp		// how many bits to shift our mask on the right
+	;;
+	shr.u	mask=mask,tmp	// zero enough bits to hold v[1] valuable part
+	mov ar.ec=r0		// clear epilogue counter (saved in ar.pfs)
+	;;
+	add base=-16,src	// keep track of aligned base
+	chk.s v[1], recover	// if already NaT, then directly skip to recover
+	or v[1]=v[1],mask	// now we have a safe initial byte pattern
+	;;
+1:
+	ld8.s v[0]=[src],8	// speculatively load next 
+	czx1.r val1=v[1]	// search 0 byte from right 
+	czx1.r val2=w[1]	// search 0 byte from right following 8bytes
+	;;
+	ld8.s w[0]=[src],8	// speculatively load next to next
+	cmp.eq.and p6,p0=8,val1	// p6 = p6 and val1==8
+	cmp.eq.and p6,p0=8,val2	// p6 = p6 and mask==8
+(p6)	br.wtop.dptk.few 1b	// loop until p6 == 0
+	;;
+	//
+	// We must return try the recovery code iff
+	// val1_is_nat || (val1==8 && val2_is_nat)
+	//
+	// XXX Fixme
+	//	- there must be a better way of doing the test
+	//
+	cmp.eq  p8,p9=8,val1	// p6 = val1 had zero (disambiguate)
+#ifdef notyet
+	tnat.nz p6,p7=val1	// test NaT on val1
+#else
+	tnat.z p7,p6=val1	// test NaT on val1
+#endif
+(p6)	br.cond.spnt.few recover// jump to recovery if val1 is NaT
+	;;
+	//
+	// if we come here p7 is true, i.e., initialized for // cmp
+	//
+	cmp.eq.and  p7,p0=8,val1// val1==8?
+	tnat.nz.and p7,p0=val2	// test NaT if val2
+(p7)	br.cond.spnt.few recover// jump to recovery if val2 is NaT
+	;;
+(p8)	mov val1=val2		// val2 contains the value
+(p8)	adds src=-16,src	// correct position when 3 ahead
+(p9)	adds src=-24,src	// correct position when 4 ahead
+	;;
+	sub ret0=src,orig	// distance from origin
+	sub tmp=7,val1		// 7=8-1 because this strlen returns strlen+1
+	mov pr=saved_pr,0xffffffffffff0000
+	;;
+	sub ret0=ret0,tmp	// length=now - back -1
+	mov ar.pfs=saved_pfs	// because of ar.ec, restore no matter what
+	br.ret.sptk.few rp	// end of normal execution
+
+	//
+	// Outlined recovery code when speculation failed
+	//
+	// This time we don't use speculation and rely on the normal exception
+	// mechanism. that's why the loop is not as good as the previous one
+	// because read ahead is not possible
+	//
+	// XXX Fixme
+	//	- today we restart from the beginning of the string instead
+	//	  of trying to continue where we left off.
+	//
+recover:
+	EX(.Lexit1, ld8 val=[base],8)	// load the initial bytes
+	;;
+	or val=val,mask			// remask first bytes
+	cmp.eq p0,p6=r0,r0		// nullify first ld8 in loop
+	;;
+	//
+	// ar.ec is still zero here
+	//
+2:
+	EX(.Lexit1, (p6) ld8 val=[base],8)
+	;;
+	czx1.r val1=val		// search 0 byte from right 
+	;;
+	cmp.eq p6,p0=8,val1	// val1==8 ?
+(p6)	br.wtop.dptk.few 2b	// loop until p6 == 0
+	;;
+	sub ret0=base,orig	// distance from base
+	sub tmp=7,val1		// 7=8-1 because this strlen returns strlen+1
+	mov pr=saved_pr,0xffffffffffff0000
+	;;
+	sub ret0=ret0,tmp	// length=now - back -1
+	mov ar.pfs=saved_pfs	// because of ar.ec, restore no matter what
+	br.ret.sptk.few rp	// end of sucessful recovery code
+
+	//
+	// We failed even on the normal load (called from exception handler)
+	//
+.Lexit1:
+	mov ret0=0
+	mov pr=saved_pr,0xffffffffffff0000
+	mov ar.pfs=saved_pfs	// because of ar.ec, restore no matter what
+	br.ret.sptk.few rp
+	
+	.endp __strlen_user
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/strncpy_from_user.S linux/arch/ia64/lib/strncpy_from_user.S
--- v2.3.42/linux/arch/ia64/lib/strncpy_from_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/strncpy_from_user.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,53 @@
+/*
+ * Just like strncpy() except for the return value.  If no fault occurs during
+ * the copying, the number of bytes copied is returned.  If a fault occurs,
+ * -EFAULT is returned.
+ *
+ * Inputs:
+ *	in0:	address of destination buffer
+ *	in1:	address of string to be copied
+ *	in2:	length of buffer in bytes
+ * Outputs:
+ *	r8:	-EFAULT in case of fault or number of bytes copied if no fault
+ * 
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define EX(x...)				\
+99:	x;					\
+	.section __ex_table,"a";		\
+	data4 @gprel(99b);			\
+	data4 .Lexit-99b;			\
+	.previous
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+	.global __strncpy_from_user
+	.proc __strncpy_from_user
+__strncpy_from_user:
+	alloc r11=ar.pfs,3,0,0,0
+	mov r9=in1
+	add r10=in1,in2
+
+	// XXX braindead copy loop---this needs to be optimized
+.Loop1:
+	EX(ld1 r8=[in1],1)
+	;;
+	st1 [in0]=r8,1
+	cmp.ltu p6,p0=in1,r10
+	;;
+(p6)	cmp.ne.and p6,p0=r8,r0
+	;;
+(p6)	br.cond.dpnt.few .Loop1
+
+1:	sub r8=in1,r9		// length of string (including NUL character)
+.Lexit:
+	mov ar.pfs=r11
+	br.ret.sptk.few rp
+
+	.endp __strncpy_from_user
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/lib/strnlen_user.S linux/arch/ia64/lib/strnlen_user.S
--- v2.3.42/linux/arch/ia64/lib/strnlen_user.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/lib/strnlen_user.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,55 @@
+/*
+ * Returns 0 if exception before NUL or reaching the supplied limit (N),
+ * a value greater than N if the string is longer than the limit, else
+ * strlen.
+ *
+ * Inputs:
+ *	in0:	address of buffer
+ *	in1:	string length limit N
+ * Outputs:
+ *	r8:	0 in case of fault, strlen(buffer)+1 otherwise
+ * 
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/* If a fault occurs, r8 gets set to -EFAULT and r9 gets cleared.  */
+#define EX(x...)				\
+	.section __ex_table,"a";		\
+	data4 @gprel(99f);			\
+	data4 (.Lexit-99f)|1;			\
+	.previous				\
+99:	x;
+
+	.text
+	.psr abi64
+	.psr lsb
+	.lsb
+
+	.align 32
+	.global __strnlen_user
+	.proc __strnlen_user
+__strnlen_user:
+	alloc r2=ar.pfs,2,0,0,0
+	mov r16=ar.lc			// preserve ar.lc
+	add r3=-1,in1
+	;;
+	mov ar.lc=r3
+	mov r9=0
+
+	// XXX braindead strlen loop---this needs to be optimized
+.Loop1:
+	EX(ld1 r8=[in0],1)
+	add r9=1,r9
+	;;
+	cmp.eq p6,p0=r8,r0
+(p6)	br.dpnt.few .Lexit
+	br.cloop.dptk.few .Loop1
+
+	add r9=1,in1			// NUL not found---return N+1
+	;;
+.Lexit:
+	mov r8=r9
+	mov ar.lc=r16			// restore ar.lc
+	br.ret.sptk.few rp
+
+	.endp __strnlen_user
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/mm/Makefile linux/arch/ia64/mm/Makefile
--- v2.3.42/linux/arch/ia64/mm/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/mm/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,14 @@
+#
+# Makefile for the ia64-specific parts of the memory manager.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := mm.o
+#O_OBJS	 := ioremap.o
+O_OBJS	 := init.o fault.o tlb.o extable.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/mm/extable.c linux/arch/ia64/mm/extable.c
--- v2.3.42/linux/arch/ia64/mm/extable.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/mm/extable.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,68 @@
+/*
+ * Kernel exception handling table support.  Derived from arch/alpha/mm/extable.c.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline const struct exception_table_entry *
+search_one_table (const struct exception_table_entry *first,
+		  const struct exception_table_entry *last,
+		  signed long value)
+{
+	/* Abort early if the search value is out of range.  */
+	if (value != (signed int)value)
+		return 0;
+
+        while (first <= last) {
+		const struct exception_table_entry *mid;
+		long diff;
+		/*
+		 * We know that first and last are both kernel virtual
+		 * pointers (region 7) so first+last will cause an
+		 * overflow.  We fix that by calling __va() on the
+		 * result, which will ensure that the top two bits get
+		 * set again.
+		 */
+		mid = (void *) __va((((__u64) first + (__u64) last)/2/sizeof(*mid))*sizeof(*mid));
+		diff = mid->addr - value;
+                if (diff == 0)
+                        return mid;
+                else if (diff < 0)
+                        first = mid+1;
+                else
+                        last = mid-1;
+        }
+        return 0;
+}
+
+register unsigned long gp __asm__("gp");
+
+const struct exception_table_entry *
+search_exception_table (unsigned long addr)
+{
+#ifndef CONFIG_MODULE
+	/* There is only the kernel to search.  */
+	return search_one_table(__start___ex_table, __stop___ex_table - 1, addr - gp);
+#else
+	struct exception_table_entry *ret;
+	/* The kernel is the last "module" -- no need to treat it special. */
+	struct module *mp;
+
+	for (mp = module_list; mp ; mp = mp->next) {
+		if (!mp->ex_table_start)
+			continue;
+		ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr - mp->gp);
+		if (ret)
+			return ret;
+	}
+	return 0;
+#endif
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/mm/fault.c linux/arch/ia64/mm/fault.c
--- v2.3.42/linux/arch/ia64/mm/fault.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/mm/fault.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,164 @@
+/*
+ * MMU fault handling support.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+
+extern void die_if_kernel (char *, struct pt_regs *, long);
+
+/*
+ * This routine is analogous to expand_stack() but instead grows the
+ * register backing store (which grows towards higher addresses).
+ * Since the register backing store is access sequentially, we
+ * disallow growing the RBS by more than a page at a time.  Note that
+ * the VM_GROWSUP flag can be set on any VM area but that's fine
+ * because the total process size is still limited by RLIMIT_STACK and
+ * RLIMIT_AS.
+ */
+static inline long
+expand_backing_store (struct vm_area_struct *vma, unsigned long address)
+{
+	unsigned long grow;
+
+	grow = PAGE_SIZE >> PAGE_SHIFT;
+	if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur
+	    || (((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur))
+		return -ENOMEM;
+	vma->vm_end += PAGE_SIZE;
+	vma->vm_mm->total_vm += grow;
+	if (vma->vm_flags & VM_LOCKED)
+		vma->vm_mm->locked_vm += grow;
+	return 0;
+}
+
+void
+ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
+{
+	struct mm_struct *mm = current->mm;
+	const struct exception_table_entry *fix;
+	struct vm_area_struct *vma, *prev_vma;
+	struct siginfo si;
+	int signal = SIGSEGV;
+	unsigned long mask;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (in_interrupt() || !mm)
+		goto no_context;
+
+	down(&mm->mmap_sem);
+
+	vma = find_vma_prev(mm, address, &prev_vma);
+	if (!vma)
+		goto bad_area;
+
+	/* find_vma_prev() returns vma such that address < vma->vm_end or NULL */
+	if (address < vma->vm_start)
+		goto check_expansion;
+
+  good_area:
+	/* OK, we've got a good vm_area for this memory area.  Check the access permissions: */
+
+#	define VM_READ_BIT	0
+#	define VM_WRITE_BIT	1
+#	define VM_EXEC_BIT	2
+
+#	if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \
+	    || (1 << VM_EXEC_BIT) != VM_EXEC)
+#		error File is out of sync with <linux/mm.h>.  Pleaes update.
+#	endif
+
+	mask = (  (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
+		| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
+		| (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
+
+	if ((vma->vm_flags & mask) != mask)
+		goto bad_area;
+
+	/*
+	 * If for any reason at all we couldn't handle the fault, make
+	 * sure we exit gracefully rather than endlessly redo the
+	 * fault.
+	 */
+	if (!handle_mm_fault(current, vma, address, (isr & IA64_ISR_W) != 0)) {
+		/*
+		 * We ran out of memory, or some other thing happened
+		 * to us that made us unable to handle the page fault
+		 * gracefully.
+		 */
+		signal = SIGBUS;
+		goto bad_area;
+	}
+	up(&mm->mmap_sem);
+	return;
+
+  check_expansion:
+	if (!(prev_vma && (prev_vma->vm_flags & VM_GROWSUP) && (address == prev_vma->vm_end))) {
+		if (!(vma->vm_flags & VM_GROWSDOWN))
+			goto bad_area;
+		if (expand_stack(vma, address))
+			goto bad_area;
+	} else if (expand_backing_store(prev_vma, address))
+		goto bad_area;
+	goto good_area;
+
+  bad_area:
+	up(&mm->mmap_sem);
+	if (isr & IA64_ISR_SP) {
+		/*
+		 * This fault was due to a speculative load set the
+		 * "ed" bit in the psr to ensure forward progress
+		 * (target register will get a NaT).
+		 */
+		ia64_psr(regs)->ed = 1;
+		return;
+	}
+	if (user_mode(regs)) {
+#if 0
+printk("%s(%d): segfault accessing %lx\n", current->comm, current->pid, address);
+show_regs(regs);
+#endif
+		si.si_signo = signal;
+		si.si_errno = 0;
+		si.si_code = SI_KERNEL;
+		si.si_addr = (void *) address;
+		force_sig_info(SIGSEGV, &si, current);
+		return;
+	}
+
+  no_context:
+	fix = search_exception_table(regs->cr_iip);
+	if (fix) {
+		regs->r8 = -EFAULT;
+		if (fix->skip & 1) {
+			regs->r9 = 0;
+		}
+		regs->cr_iip += ((long) fix->skip) & ~15;
+		regs->cr_ipsr &= ~IA64_PSR_RI;	/* clear exception slot number */
+		return;
+	}
+
+	/*
+	 * Oops. The kernel tried to access some bad page. We'll have
+	 * to terminate things with extreme prejudice.
+	 */
+	printk(KERN_ALERT "Unable to handle kernel paging request at "
+	       "virtual address %016lx\n", address);
+	die_if_kernel("Oops", regs, isr);
+	do_exit(SIGKILL);
+	return;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c
--- v2.3.42/linux/arch/ia64/mm/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -0,0 +1,461 @@
+/*
+ * Initialize MMU support.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/swap.h>
+
+#include <asm/dma.h>
+#include <asm/efi.h>
+#include <asm/ia32.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+
+/* References to section boundaries: */
+extern char _stext, _etext, _edata, __init_begin, __init_end;
+
+/*
+ * These are allocated in head.S so that we get proper page alignment.
+ * If you change the size of these then change head.S as well.
+ */
+extern char empty_bad_page[PAGE_SIZE];
+extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD];
+extern pte_t empty_bad_pte_table[PTRS_PER_PTE];
+
+extern void ia64_tlb_init (void);
+
+static unsigned long totalram_pages;
+
+/*
+ * Fill in empty_bad_pmd_table with entries pointing to
+ * empty_bad_pte_table and return the address of this PMD table.
+ */
+static pmd_t *
+get_bad_pmd_table (void)
+{
+	pmd_t v;
+	int i;
+
+	pmd_set(&v, empty_bad_pte_table);
+
+	for (i = 0; i < PTRS_PER_PMD; ++i)
+		empty_bad_pmd_table[i] = v;
+
+	return empty_bad_pmd_table;
+}
+
+/*
+ * Fill in empty_bad_pte_table with PTEs pointing to empty_bad_page
+ * and return the address of this PTE table.
+ */
+static pte_t *
+get_bad_pte_table (void)
+{
+	pte_t v;
+	int i;
+
+	set_pte(&v, pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED)));
+
+	for (i = 0; i < PTRS_PER_PTE; ++i)
+		empty_bad_pte_table[i] = v;
+
+	return empty_bad_pte_table;
+}
+
+void
+__handle_bad_pgd (pgd_t *pgd)
+{
+	pgd_ERROR(*pgd);
+	pgd_set(pgd, get_bad_pmd_table());
+}
+
+void
+__handle_bad_pmd (pmd_t *pmd)
+{
+	pmd_ERROR(*pmd);
+	pmd_set(pmd, get_bad_pte_table());
+}
+
+/*
+ * Allocate and initialize an L3 directory page and set
+ * the L2 directory entry PMD to the newly allocated page.
+ */
+pte_t*
+get_pte_slow (pmd_t *pmd, unsigned long offset)
+{
+	pte_t *pte;
+
+	pte = (pte_t *) __get_free_page(GFP_KERNEL);
+	if (pmd_none(*pmd)) {
+		if (pte) {
+			/* everything A-OK */
+			clear_page(pte);
+			pmd_set(pmd, pte);
+			return pte + offset;
+		}
+		pmd_set(pmd, get_bad_pte_table());
+		return NULL;
+	}
+	free_page((unsigned long) pte);
+	if (pmd_bad(*pmd)) {
+		__handle_bad_pmd(pmd);
+		return NULL;
+	}
+	return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+int
+do_check_pgt_cache (int low, int high)
+{
+	int freed = 0;
+
+        if (pgtable_cache_size > high) {
+                do {
+                        if (pgd_quicklist)
+                                free_page((unsigned long)get_pgd_fast()), ++freed;
+                        if (pmd_quicklist)
+                                free_page((unsigned long)get_pmd_fast()), ++freed;
+                        if (pte_quicklist)
+                                free_page((unsigned long)get_pte_fast()), ++freed;
+                } while (pgtable_cache_size > low);
+        }
+        return freed;
+}
+
+/*
+ * This performs some platform-dependent address space initialization.
+ * On IA-64, we want to setup the VM area for the register backing
+ * store (which grows upwards) and install the gateway page which is
+ * used for signal trampolines, etc.
+ */
+void
+ia64_init_addr_space (void)
+{
+	struct vm_area_struct *vma;
+
+	/*
+	 * If we're out of memory and kmem_cache_alloc() returns NULL,
+	 * we simply ignore the problem.  When the process attempts to
+	 * write to the register backing store for the first time, it
+	 * will get a SEGFAULT in this case.
+	 */
+	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	if (vma) {
+		vma->vm_mm = current->mm;
+		vma->vm_start = IA64_RBS_BOT;
+		vma->vm_end = vma->vm_start + PAGE_SIZE;
+		vma->vm_page_prot = PAGE_COPY;
+		vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP;
+		vma->vm_ops = NULL;
+		vma->vm_pgoff = 0;
+		vma->vm_file = NULL;
+		vma->vm_private_data = NULL;
+		insert_vm_struct(current->mm, vma);
+	}
+}
+
+void
+free_initmem (void)
+{
+	unsigned long addr;
+
+	addr = (unsigned long) &__init_begin;
+	for (; addr < (unsigned long) &__init_end; addr += PAGE_SIZE) {
+		clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
+		set_page_count(&mem_map[MAP_NR(addr)], 1);
+		free_page(addr);
+		++totalram_pages;
+	}
+	printk ("Freeing unused kernel memory: %ldkB freed\n",
+		(&__init_end - &__init_begin) >> 10);
+}
+
+void
+si_meminfo (struct sysinfo *val)
+{
+	val->totalram = totalram_pages;
+	val->sharedram = 0;
+	val->freeram = nr_free_pages();
+	val->bufferram = atomic_read(&buffermem_pages);
+	val->totalhigh = 0;
+	val->freehigh = 0;
+	val->mem_unit = PAGE_SIZE;
+	return;
+}
+
+void
+show_mem (void)
+{
+	int i,free = 0,total = 0,reserved = 0;
+	int shared = 0, cached = 0;
+
+	printk("Mem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+	i = max_mapnr;
+	while (i-- > 0) {
+		total++;
+		if (PageReserved(mem_map+i))
+			reserved++;
+		else if (PageSwapCache(mem_map+i))
+			cached++;
+		else if (!page_count(mem_map + i))
+			free++;
+		else
+			shared += page_count(mem_map + i) - 1;
+	}
+	printk("%d pages of RAM\n", total);
+	printk("%d reserved pages\n", reserved);
+	printk("%d pages shared\n", shared);
+	printk("%d pages swap cached\n", cached);
+	printk("%ld pages in page table cache\n", pgtable_cache_size);
+	show_buffers();
+}
+
+/*
+ * This is like put_dirty_page() but installs a clean page with PAGE_GATE protection
+ * (execute-only, typically).
+ */
+struct page *
+put_gate_page (struct page *page, unsigned long address)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (!PageReserved(page))
+		printk("put_gate_page: gate page at 0x%lx not in reserved memory\n",
+		       page_address(page));
+	pgd = pgd_offset_k(address);		/* note: this is NOT pgd_offset()! */
+	pmd = pmd_alloc(pgd, address);
+	if (!pmd) {
+		__free_page(page);
+		oom(current);
+		return 0;
+	}
+	pte = pte_alloc(pmd, address);
+	if (!pte) {
+		__free_page(page);
+		oom(current);
+		return 0;
+	}
+	if (!pte_none(*pte)) {
+		pte_ERROR(*pte);
+		__free_page(page);
+		return 0;
+	}
+	flush_page_to_ram(page);
+	set_pte(pte, page_pte_prot(page, PAGE_GATE));
+	/* no need for flush_tlb */
+	return page;
+}
+
+void __init
+ia64_rid_init (void)
+{
+	unsigned long flags, rid, pta;
+
+	/* Set up the kernel identity mappings (regions 6 & 7) and the vmalloc area (region 5): */
+	ia64_clear_ic(flags);
+
+	rid = ia64_rid(IA64_REGION_ID_KERNEL, __IA64_UNCACHED_OFFSET);
+	ia64_set_rr(__IA64_UNCACHED_OFFSET, (rid << 8) | (_PAGE_SIZE_256M << 2));
+
+	rid = ia64_rid(IA64_REGION_ID_KERNEL, PAGE_OFFSET);
+	ia64_set_rr(PAGE_OFFSET, (rid << 8) | (_PAGE_SIZE_256M << 2));
+
+	rid = ia64_rid(IA64_REGION_ID_KERNEL, VMALLOC_START);
+	ia64_set_rr(VMALLOC_START, (rid << 8) | (PAGE_SHIFT << 2) | 1);
+
+	__restore_flags(flags);
+
+	/*
+	 * Check if the virtually mapped linear page table (VMLPT)
+	 * overlaps with a mapped address space.  The IA-64
+	 * architecture guarantees that at least 50 bits of virtual
+	 * address space are implemented but if we pick a large enough
+	 * page size (e.g., 64KB), the VMLPT is big enough that it
+	 * will overlap with the upper half of the kernel mapped
+	 * region.  I assume that once we run on machines big enough
+	 * to warrant 64KB pages, IMPL_VA_MSB will be significantly
+	 * bigger, so we can just adjust the number below to get
+	 * things going.  Alternatively, we could truncate the upper
+	 * half of each regions address space to not permit mappings
+	 * that would overlap with the VMLPT.  --davidm 99/11/13
+	 */
+#	define ld_pte_size		3
+#	define ld_max_addr_space_pages	3*(PAGE_SHIFT - ld_pte_size) /* max # of mappable pages */
+#	define ld_max_addr_space_size	(ld_max_addr_space_pages + PAGE_SHIFT)
+#	define ld_max_vpt_size		(ld_max_addr_space_pages + ld_pte_size)
+#	define POW2(n)			(1ULL << (n))
+#	define IMPL_VA_MSB		50
+	if (POW2(ld_max_addr_space_size - 1) + POW2(ld_max_vpt_size) > POW2(IMPL_VA_MSB))
+		panic("mm/init: overlap between virtually mapped linear page table and "
+		      "mapped kernel space!");
+	pta = POW2(61) - POW2(IMPL_VA_MSB);
+	/*
+	 * Set the (virtually mapped linear) page table address.  Bit
+	 * 8 selects between the short and long format, bits 2-7 the
+	 * size of the table, and bit 0 whether the VHPT walker is
+	 * enabled.
+	 */
+	ia64_set_pta(pta | (0<<8) | ((3*(PAGE_SHIFT-3)+3)<<2) | 1);
+}
+
+#ifdef CONFIG_IA64_VIRTUAL_MEM_MAP
+
+static int
+create_mem_map_page_table (u64 start, u64 end, void *arg)
+{
+	unsigned long address, start_page, end_page;
+	struct page *map_start, *map_end;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	void *page;
+
+	map_start = mem_map + MAP_NR(start);
+	map_end   = mem_map + MAP_NR(end);
+
+	start_page = (unsigned long) map_start & PAGE_MASK;
+	end_page = PAGE_ALIGN((unsigned long) map_end);
+
+	printk("[%lx,%lx) -> %lx-%lx\n", start, end, start_page, end_page);
+
+	for (address = start_page; address < end_page; address += PAGE_SIZE) {
+		pgd = pgd_offset_k(address);
+		if (pgd_none(*pgd)) {
+			pmd = alloc_bootmem_pages(PAGE_SIZE);
+			clear_page(pmd);
+			pgd_set(pgd, pmd);
+			pmd += (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+		} else
+			pmd = pmd_offset(pgd, address);
+		if (pmd_none(*pmd)) {
+			pte = alloc_bootmem_pages(PAGE_SIZE);
+			clear_page(pte);
+			pmd_set(pmd, pte);
+			pte += (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+		} else
+			pte = pte_offset(pmd, address);
+
+		if (pte_none(*pte)) {
+			page = alloc_bootmem_pages(PAGE_SIZE);
+			clear_page(page);
+			set_pte(pte, mk_pte_phys(__pa(page), PAGE_KERNEL));
+		}
+	}
+	return 0;
+}
+
+#endif /* CONFIG_IA64_VIRTUAL_MEM_MAP */
+
+/*
+ * Set up the page tables.
+ */
+void
+paging_init (void)
+{
+	unsigned long max_dma, zones_size[MAX_NR_ZONES];
+
+	clear_page((void *) ZERO_PAGE_ADDR);
+
+	ia64_rid_init();
+	__flush_tlb_all();
+
+	/* initialize mem_map[] */
+
+	memset(zones_size, 0, sizeof(zones_size));
+
+	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS);
+	if (max_low_pfn < max_dma)
+		zones_size[ZONE_DMA] = max_low_pfn;
+	else {
+		zones_size[ZONE_DMA] = max_dma;
+		zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
+	}
+	free_area_init(zones_size);
+}
+
+static int
+count_pages (u64 start, u64 end, void *arg)
+{
+	unsigned long *count = arg;
+
+	*count += (end - start) >> PAGE_SHIFT;
+	return 0;
+}
+
+static int
+count_reserved_pages (u64 start, u64 end, void *arg)
+{
+	unsigned long num_reserved = 0;
+	unsigned long *count = arg;
+	struct page *pg;
+
+	for (pg = mem_map + MAP_NR(start); pg < mem_map + MAP_NR(end); ++pg)
+		if (PageReserved(pg))
+			++num_reserved;
+	*count += num_reserved;
+	return 0;
+}
+
+void
+mem_init (void)
+{
+	extern char __start_gate_section[];
+	long reserved_pages, codesize, datasize, initsize;
+
+	if (!mem_map)
+		BUG();
+
+	num_physpages = 0;
+	efi_memmap_walk(count_pages, &num_physpages);
+
+	max_mapnr = max_low_pfn;
+	high_memory = __va(max_low_pfn * PAGE_SIZE);
+
+	ia64_tlb_init();
+
+	totalram_pages += free_all_bootmem();
+
+	reserved_pages = 0;
+	efi_memmap_walk(count_reserved_pages, &reserved_pages);
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_stext;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+	printk("Memory: %luk/%luk available (%luk code, %luk reserved, %luk data, %luk init)\n",
+	       (unsigned long) nr_free_pages() << (PAGE_SHIFT - 10),
+	       max_mapnr << (PAGE_SHIFT - 10), codesize >> 10, reserved_pages << (PAGE_SHIFT - 10),
+	       datasize >> 10, initsize >> 10);
+
+	/* install the gate page in the global page table: */
+	put_gate_page(mem_map + MAP_NR(__start_gate_section), GATE_ADDR);
+
+#ifndef CONFIG_IA64_SOFTSDV_HACKS
+	/*
+	 * (Some) SoftSDVs seem to have a problem with this call.
+	 * Since it's mostly a performance optimization, just don't do
+	 * it for now...  --davidm 99/12/6
+	 */
+	efi_enter_virtual_mode();
+#endif
+
+#ifdef CONFIG_IA32_SUPPORT
+	ia32_gdt_init();
+#endif
+	return;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/mm/tlb.c linux/arch/ia64/mm/tlb.c
--- v2.3.42/linux/arch/ia64/mm/tlb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/mm/tlb.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,166 @@
+/*
+ * TLB support routines.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/mm.h>
+
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/pal.h>
+
+#define SUPPORTED_PGBITS (			\
+		1 << _PAGE_SIZE_256M |		\
+		1 << _PAGE_SIZE_64M  |		\
+		1 << _PAGE_SIZE_16M  |		\
+		1 << _PAGE_SIZE_4M   |		\
+		1 << _PAGE_SIZE_1M   |		\
+		1 << _PAGE_SIZE_256K |		\
+		1 << _PAGE_SIZE_64K  |		\
+		1 << _PAGE_SIZE_16K  |		\
+		1 << _PAGE_SIZE_8K   |		\
+		1 << _PAGE_SIZE_4K )
+
+static void wrap_context (struct mm_struct *mm);
+
+unsigned long ia64_next_context = (1UL << IA64_HW_CONTEXT_BITS) + 1;
+
+ /*
+  * Put everything in a struct so we avoid the global offset table whenever
+  * possible.
+  */
+ia64_ptce_info_t ia64_ptce_info;
+
+/*
+ * Seralize usage of ptc.g 
+ */
+spinlock_t ptcg_lock = SPIN_LOCK_UNLOCKED; /* see <asm/pgtable.h> */
+
+void
+get_new_mmu_context (struct mm_struct *mm)
+{
+	if ((ia64_next_context & IA64_HW_CONTEXT_MASK) == 0) {
+		wrap_context(mm);
+	}
+	mm->context = ia64_next_context++;
+}
+
+/*
+ * This is where we handle the case where (ia64_next_context &
+ * IA64_HW_CONTEXT_MASK) == 0.  Whenever this happens, we need to
+ * flush the entire TLB and skip over region id number 0, which is
+ * used by the kernel.
+ */
+static void
+wrap_context (struct mm_struct *mm)
+{
+	struct task_struct *task;
+
+	/*
+	 * We wrapped back to the first region id so we nuke the TLB
+	 * so we can switch to the next generation of region ids.
+	 */
+	__flush_tlb_all();
+	if (ia64_next_context++ == 0) {
+		/*
+		 * Oops, we've used up all 64 bits of the context
+		 * space---walk through task table to ensure we don't
+		 * get tricked into using an old context.  If this
+		 * happens, the machine has been running for a long,
+		 * long time!
+		 */
+		ia64_next_context = (1UL << IA64_HW_CONTEXT_BITS) + 1;
+
+		read_lock(&tasklist_lock);
+		for_each_task (task) {
+			if (task->mm == mm)
+				continue;
+			flush_tlb_mm(mm);
+		}
+		read_unlock(&tasklist_lock);
+	}
+}
+
+void
+__flush_tlb_all (void)
+{
+	unsigned long i, j, flags, count0, count1, stride0, stride1, addr = ia64_ptce_info.base;
+
+	count0  = ia64_ptce_info.count[0];
+	count1  = ia64_ptce_info.count[1];
+	stride0 = ia64_ptce_info.stride[0];
+	stride1 = ia64_ptce_info.stride[1];
+
+	save_and_cli(flags);
+	for (i = 0; i < count0; ++i) {
+		for (j = 0; j < count1; ++j) {
+			asm volatile ("ptc.e %0" :: "r"(addr));
+			addr += stride1;
+		}
+		addr += stride0;
+	}
+	restore_flags(flags);
+	ia64_insn_group_barrier();
+	ia64_srlz_i();			/* srlz.i implies srlz.d */
+	ia64_insn_group_barrier();
+}
+
+void
+flush_tlb_range (struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+	unsigned long size = end - start;
+	unsigned long nbits;
+
+	if (mm != current->active_mm) {
+		/* this doesn't happen often, if at all, so it's not worth optimizing for... */
+		mm->context = 0;
+		return;
+	}
+
+	nbits = ia64_fls(size + 0xfff);
+	if (((1UL << nbits) & SUPPORTED_PGBITS) == 0) {
+		if (nbits > _PAGE_SIZE_256M)
+			nbits = _PAGE_SIZE_256M;
+		else
+			/*
+			 * Some page sizes are not implemented in the
+			 * IA-64 arch, so if we get asked to clear an
+			 * unsupported page size, round up to the
+			 * nearest page size.  Note that we depend on
+			 * the fact that if page size N is not
+			 * implemented, 2*N _is_ implemented.
+			 */
+			++nbits;
+		if (((1UL << nbits) & SUPPORTED_PGBITS) == 0)
+		  panic("flush_tlb_range: BUG: nbits=%lu\n", nbits);
+	}
+	start &= ~((1UL << nbits) - 1);
+
+	spin_lock(&ptcg_lock);
+	do {
+#ifdef CONFIG_SMP
+		__asm__ __volatile__ ("ptc.g %0,%1;;srlz.i;;"
+				      :: "r"(start), "r"(nbits<<2) : "memory");
+#else
+		__asm__ __volatile__ ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory");
+#endif
+		start += (1UL << nbits);
+	} while (start < end);
+	spin_unlock(&ptcg_lock);
+	ia64_insn_group_barrier();
+	ia64_srlz_i();			/* srlz.i implies srlz.d */
+	ia64_insn_group_barrier();
+}
+
+void
+ia64_tlb_init (void)
+{
+	ia64_get_ptce(&ia64_ptce_info);
+	__flush_tlb_all();		/* nuke left overs from bootstrapping... */
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/sn/Makefile linux/arch/ia64/sn/Makefile
--- v2.3.42/linux/arch/ia64/sn/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,25 @@
+#
+# ia64/sn/Makefile
+#
+# Copyright (C) 1999 Silicon Graphics, Inc.
+# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+#
+
+CFLAGS          :=     $(CFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSN -DSOFTSDV \
+			-DLANGUAGE_C=1 -D_LANGUAGE_C=1
+AFLAGS          :=      $(AFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSOFTSDV
+
+.S.s:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
+all: sn.a
+
+O_TARGET        = sn.a
+O_HEADERS       =
+O_OBJS          = sn1/sn1.a
+
+clean::
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/sn/sn1/Makefile linux/arch/ia64/sn/sn1/Makefile
--- v2.3.42/linux/arch/ia64/sn/sn1/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,29 @@
+#
+# ia64/platform/sn/sn1/Makefile
+#
+# Copyright (C) 1999 Silicon Graphics, Inc.
+# Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+#
+
+CFLAGS          :=     $(CFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSN -DSOFTSDV \
+			-DLANGUAGE_C=1 -D_LANGUAGE_C=1
+AFLAGS          :=      $(AFLAGS) -DCONFIG_SGI_SN1 -DSN1 -DSOFTSDV
+
+.S.s:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
+all: sn1.a
+
+O_TARGET        = sn1.a
+O_HEADERS       =
+O_OBJS          = irq.o setup.o
+
+ifeq ($(CONFIG_IA64_GENERIC),y)
+O_OBJS		+= machvec.o
+endif
+
+clean::
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/sn/sn1/irq.c linux/arch/ia64/sn/sn1/irq.c
--- v2.3.42/linux/arch/ia64/sn/sn1/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/irq.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,50 @@
+#include <linux/kernel.h>
+
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+
+static int
+sn1_startup_irq(unsigned int irq)
+{
+        return(0);
+}
+
+static void
+sn1_shutdown_irq(unsigned int irq)
+{
+}
+
+static void
+sn1_disable_irq(unsigned int irq)
+{
+}
+
+static void
+sn1_enable_irq(unsigned int irq)
+{
+}
+
+static int
+sn1_handle_irq(unsigned int irq, struct pt_regs *regs)
+{
+       return(0);
+}
+
+struct hw_interrupt_type irq_type_sn1 = {
+        "sn1_irq",
+        sn1_startup_irq,
+        sn1_shutdown_irq,
+        sn1_handle_irq,
+        sn1_enable_irq,
+        sn1_disable_irq
+};
+
+void
+sn1_irq_init (struct irq_desc desc[NR_IRQS])
+{
+	int i;
+
+	for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) {
+		irq_desc[i].handler = &irq_type_sn1;
+	}
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/sn/sn1/machvec.c linux/arch/ia64/sn/sn1/machvec.c
--- v2.3.42/linux/arch/ia64/sn/sn1/machvec.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/machvec.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,4 @@
+#include <asm/machvec_init.h>
+#include <asm/machvec_sn1.h>
+
+MACHVEC_DEFINE(sn1)
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/sn/sn1/setup.c linux/arch/ia64/sn/sn1/setup.c
--- v2.3.42/linux/arch/ia64/sn/sn1/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/sn/sn1/setup.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,77 @@
+/*
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+
+#include <asm/io.h>
+#include <asm/machvec.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+
+
+/*
+ * The format of "screen_info" is strange, and due to early i386-setup
+ * code. This is just enough to make the console code think we're on a
+ * VGA color display.
+ */
+struct screen_info sn1_screen_info = {
+	orig_x:			 0,
+	orig_y:			 0,
+	orig_video_mode:	 3,
+	orig_video_cols:	80,
+	orig_video_ega_bx:	 3,
+	orig_video_lines:	25,
+	orig_video_isVGA:	 1,
+	orig_video_points:	16
+};
+
+/*
+ * This is here so we can use the CMOS detection in ide-probe.c to
+ * determine what drives are present.  In theory, we don't need this
+ * as the auto-detection could be done via ide-probe.c:do_probe() but
+ * in practice that would be much slower, which is painful when
+ * running in the simulator.  Note that passing zeroes in DRIVE_INFO
+ * is sufficient (the IDE driver will autodetect the drive geometry).
+ */
+char drive_info[4*16];
+
+unsigned long
+sn1_map_nr (unsigned long addr)
+{
+	return MAP_NR_SN1(addr);
+}
+
+void
+sn1_setup(char **cmdline_p)
+{
+
+	ROOT_DEV = to_kdev_t(0x0301);		/* default to first IDE drive */
+
+#if !defined (CONFIG_IA64_SOFTSDV_HACKS)
+	/* 
+	 * Program the timer to deliver timer ticks.  0x40 is the I/O port
+	 * address of PIT counter 0, 0x43 is the I/O port address of the 
+	 * PIT control word. 
+	 */
+	request_region(0x40,0x20,"timer");
+	outb(0x34, 0x43);            /* Control word */
+	outb(LATCH & 0xff , 0x40);   /* LSB */
+	outb(LATCH >> 8, 0x40);	     /* MSB */
+	printk("PIT: LATCH at 0x%x%x for %d HZ\n", LATCH >> 8, LATCH & 0xff, HZ);
+#endif
+#ifdef __SMP__
+	init_smp_config();
+#endif
+	screen_info = sn1_screen_info;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/tools/Makefile linux/arch/ia64/tools/Makefile
--- v2.3.42/linux/arch/ia64/tools/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/tools/Makefile	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,49 @@
+CFLAGS	= -D__KERNEL__ -g -O2 -Wall -I$(TOPDIR)/include
+
+ifdef CONFIG_SMP
+ CFLAGS += -D__SMP__
+endif
+
+TARGET	= $(TOPDIR)/include/asm-ia64/offsets.h
+
+all: 
+
+clean:
+	rm -f print_offsets.s print_offsets offsets.h
+
+fastdep: offsets.h
+	@if ! cmp -s offsets.h ${TARGET}; then	\
+		echo "Updating ${TARGET}...";	\
+		cp offsets.h ${TARGET};		\
+	else					\
+		echo "${TARGET} is up to date";	\
+	fi
+
+#
+# If we're cross-compiling, we use the cross-compiler to translate
+# print_offsets.c into an assembly file and then awk to translate this
+# file into offsets.h.  This avoids having to use a simulator to
+# generate this file.  This is based on an idea suggested by Asit
+# Mallick.  If we're running natively, we can of course just build
+# print_offsets and run it. --davidm
+#
+
+ifeq ($(CROSS_COMPILE),)
+
+offsets.h: print_offsets
+	./print_offsets > offsets.h
+
+print_offsets: print_offsets.c
+	$(CC) $(CFLAGS) print_offsets.c -o $@
+
+else
+
+offsets.h: print_offsets.s
+	$(AWK) -f print_offsets.awk $^ > $@
+
+print_offsets.s: print_offsets.c
+	$(CC) $(CFLAGS) -S print_offsets.c -o $@
+
+endif
+
+.PHONY: all
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/tools/print_offsets.awk linux/arch/ia64/tools/print_offsets.awk
--- v2.3.42/linux/arch/ia64/tools/print_offsets.awk	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/tools/print_offsets.awk	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,70 @@
+BEGIN {
+	print "#ifndef _ASM_IA64_OFFSETS_H"
+	print "#define _ASM_IA64_OFFSETS_H"
+	print "/*"
+	print " * DO NOT MODIFY"
+	print " *"
+	print " * This file was generated by arch/ia64/tools/print_offsets.awk."
+	print " *"
+	print " */"
+	#
+	# This is a cheesy hack.  Make sure that
+	# PF_PTRACED == 1<<PF_PTRACED_BIT.
+	#
+	print "#define PF_PTRACED_BIT		4"
+}
+
+# look for .tab:
+#	stringz "name"
+#	data value
+# sequence
+
+/.*[.]size/ {
+	inside_table = 0
+}
+
+/\/\/ end/ {
+	inside_table = 0
+}
+
+{
+	if (inside_table) {
+		if ($1 == "//") getline;
+		name=$2
+		getline
+		getline
+		if ($1 == "//") getline;
+		value=$2
+		len = length(name)
+		name = substr(name, 2, len - 2)
+		len -= 2
+		if (len == 0)
+			print ""
+		else {
+			len += 8
+			if (len >= 40) {
+				space=" "
+			} else {
+				space=""
+				while (len < 40) {
+					len += 8
+					space = space"\t"
+				}
+			}
+			printf("#define %s%s%lu\t/* 0x%lx */\n", name, space, value, value)
+		}
+	}
+}
+
+/tab:/ {
+	inside_table = 1
+}
+
+/tab#:/ {
+	inside_table = 1
+}
+
+END {
+	print ""
+	print "#endif /* _ASM_IA64_OFFSETS_H */"
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/tools/print_offsets.c linux/arch/ia64/tools/print_offsets.c
--- v2.3.42/linux/arch/ia64/tools/print_offsets.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/tools/print_offsets.c	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,109 @@
+/*
+ * Utility to generate asm-ia64/offsets.h.
+ *
+ * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Note that this file has dual use: when building the kernel
+ * natively, the file is translated into a binary and executed.  When
+ * building the kernel in a cross-development environment, this file
+ * gets translated into an assembly file which, in turn, is processed
+ * by awk to generate offsets.h.  So if you make any changes to this
+ * file, be sure to verify that the awk procedure still works (see
+ * prin_offsets.awk).
+ */
+#include <linux/sched.h>
+
+#include <asm-ia64/processor.h>
+#include <asm-ia64/ptrace.h>
+#include <asm-ia64/siginfo.h>
+#include <asm-ia64/sigcontext.h>
+
+#ifdef offsetof
+# undef offsetof
+#endif
+
+/*
+ * We _can't_ include the host's standard header file, as those are in
+ *  potential conflict with the what the Linux kernel declares for the
+ *  target system.
+ */
+extern int printf (const char *, ...);
+
+#define offsetof(type,field)	((char *) &((type *) 0)->field - (char *) 0)
+
+struct
+  {
+    const char name[256];
+    unsigned long value;
+  }
+tab[] =
+  {
+    { "IA64_TASK_SIZE",			sizeof (struct task_struct) },
+    { "IA64_PT_REGS_SIZE",		sizeof (struct pt_regs) },
+    { "IA64_SWITCH_STACK_SIZE",		sizeof (struct switch_stack) },
+    { "IA64_SIGINFO_SIZE",		sizeof (struct siginfo) },
+    { "", 0 },			/* spacer */
+    { "IA64_TASK_FLAGS_OFFSET",		offsetof (struct task_struct, flags) },
+    { "IA64_TASK_SIGPENDING_OFFSET",	offsetof (struct task_struct, sigpending) },
+    { "IA64_TASK_NEED_RESCHED_OFFSET",	offsetof (struct task_struct, need_resched) },
+    { "IA64_TASK_THREAD_OFFSET",	offsetof (struct task_struct, thread) },
+    { "IA64_TASK_THREAD_KSP_OFFSET",	offsetof (struct task_struct, thread.ksp) },
+    { "IA64_TASK_PID_OFFSET",		offsetof (struct task_struct, pid) },
+    { "IA64_TASK_MM_OFFSET",		offsetof (struct task_struct, mm) },
+    { "IA64_PT_REGS_CR_IPSR_OFFSET",	offsetof (struct pt_regs, cr_ipsr) },
+    { "IA64_PT_REGS_R12_OFFSET",	offsetof (struct pt_regs, r12) },
+    { "IA64_PT_REGS_R8_OFFSET",		offsetof (struct pt_regs, r8) },
+    { "IA64_PT_REGS_R16_OFFSET",	offsetof (struct pt_regs, r16) },
+    { "IA64_SWITCH_STACK_B0_OFFSET",	offsetof (struct switch_stack, b0) },
+    { "IA64_SWITCH_STACK_CALLER_UNAT_OFFSET", offsetof (struct switch_stack, caller_unat) },
+    { "IA64_SIGCONTEXT_AR_BSP_OFFSET",	offsetof (struct sigcontext, sc_ar_bsp) },
+    { "IA64_SIGCONTEXT_AR_RNAT_OFFSET",	offsetof (struct sigcontext, sc_ar_rnat) },
+    { "IA64_SIGCONTEXT_FLAGS_OFFSET",	offsetof (struct sigcontext, sc_flags) },
+    { "IA64_SIGCONTEXT_CFM_OFFSET",	offsetof (struct sigcontext, sc_cfm) },
+    { "IA64_SIGCONTEXT_FR6_OFFSET",	offsetof (struct sigcontext, sc_fr[6]) },
+};
+
+static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
+
+int
+main (int argc, char **argv)
+{
+  const char *space;
+  int i, num_tabs;
+  size_t len;
+
+  printf ("#ifndef _ASM_IA64_OFFSETS_H\n");
+  printf ("#define _ASM_IA64_OFFSETS_H\n\n");
+
+  printf ("/*\n * DO NOT MODIFY\n *\n * This file was generated by "
+	  "arch/ia64/tools/print_offsets.\n *\n */\n\n");
+
+  /* This is stretching things a bit, but entry.S needs the bit number
+     for PF_PTRACED and it can't include <linux/sched.h> so this seems
+     like a reasonably solution.  At least the code won't break shoudl
+     PF_PTRACED ever change.  */
+  printf ("#define PF_PTRACED_BIT\t\t\t%u\n\n", ffs (PF_PTRACED) - 1);
+
+  for (i = 0; i < sizeof (tab) / sizeof (tab[0]); ++i)
+    {
+      if (tab[i].name[0] == '\0')
+	printf ("\n");
+      else
+	{
+	  len = strlen (tab[i].name);
+
+	  num_tabs = (40 - len) / 8;
+	  if (num_tabs <= 0)
+	    space = " ";
+	  else
+	    space = strchr(tabs, '\0') - (40 - len) / 8;
+
+	  printf ("#define %s%s%lu\t/* 0x%lx */\n",
+		  tab[i].name, space, tab[i].value, tab[i].value);
+	}
+    }
+
+  printf ("\n#endif /* _ASM_IA64_OFFSETS_H */\n");
+  return 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ia64/vmlinux.lds.S linux/arch/ia64/vmlinux.lds.S
--- v2.3.42/linux/arch/ia64/vmlinux.lds.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/vmlinux.lds.S	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,164 @@
+#include <linux/config.h>
+
+#include <asm/page.h>
+#include <asm/system.h>
+
+OUTPUT_FORMAT("elf64-ia64-little")
+OUTPUT_ARCH(ia64)
+ENTRY(_start)
+SECTIONS
+{
+  v = PAGE_OFFSET;	/* this symbol is here to make debugging with kdb easier... */
+
+  . = KERNEL_START;
+
+  _text = .;
+  _stext = .;
+  .text : AT(ADDR(.text) - PAGE_OFFSET)
+    {
+	*(__ivt_section)
+	/* these are not really text pages, but the zero page needs to be in a fixed location: */
+	*(__special_page_section)
+	__start_gate_section = .;
+	*(__gate_section)
+	__stop_gate_section = .;
+	*(.text)
+    }
+  .text2 : AT(ADDR(.text2) - PAGE_OFFSET)
+	{ *(.text2) }
+#ifdef CONFIG_SMP
+  .text.lock : AT(ADDR(.text.lock) - PAGE_OFFSET)
+	{ *(.text.lock) }
+#endif
+  _etext = .;
+
+  /* Exception table */
+  . = ALIGN(16);
+  __start___ex_table = .;
+  __ex_table : AT(ADDR(__ex_table) - PAGE_OFFSET)
+	{ *(__ex_table) }
+  __stop___ex_table = .;
+
+#if defined(CONFIG_KDB)
+  /* Kernel symbols and strings for kdb */
+# define KDB_MEAN_SYMBOL_SIZE	48
+# define KDB_SPACE		(CONFIG_KDB_STBSIZE * KDB_MEAN_SYMBOL_SIZE)
+  . = ALIGN(8);
+  _skdb = .;
+  .kdb : AT(ADDR(.kdb) - PAGE_OFFSET)
+    {
+	*(kdbsymtab)
+	*(kdbstrings)
+    }
+  _ekdb = .;
+  . = _skdb + KDB_SPACE;
+#endif
+
+  /* Kernel symbol names for modules: */
+  .kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET)
+	{ *(.kstrtab) }
+
+  /* The initial task and kernel stack */
+  . = ALIGN(PAGE_SIZE);
+  init_task : AT(ADDR(init_task) - PAGE_OFFSET)
+	{ *(init_task) }
+
+  /* Startup code */
+  __init_begin = .;
+  .text.init : AT(ADDR(.text.init) - PAGE_OFFSET)
+	{ *(.text.init) }
+  .data.init : AT(ADDR(.data.init) - PAGE_OFFSET)
+	{ *(.data.init) }
+   . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : AT(ADDR(.setup.init) - PAGE_OFFSET)
+        { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : AT(ADDR(.initcall.init) - PAGE_OFFSET)
+        { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(PAGE_SIZE);
+  __init_end = .;
+
+  .data.page_aligned : AT(ADDR(.data.page_aligned) - PAGE_OFFSET)
+        { *(.data.idt) }
+
+  . = ALIGN(64);
+  .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - PAGE_OFFSET)
+        { *(.data.cacheline_aligned) }
+
+  /* Global data */
+  _data = .;
+
+  .rodata : AT(ADDR(.rodata) - PAGE_OFFSET)
+	{ *(.rodata) }
+  .opd : AT(ADDR(.opd) - PAGE_OFFSET)
+	{ *(.opd) }
+  .data : AT(ADDR(.data) - PAGE_OFFSET)
+	{ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
+
+  __gp = ALIGN (8) + 0x200000;
+
+  .got : AT(ADDR(.got) - PAGE_OFFSET)
+	{ *(.got.plt) *(.got) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata : AT(ADDR(.sdata) - PAGE_OFFSET)
+	{ *(.sdata) }
+  _edata  =  .;
+  _bss = .;
+  .sbss : AT(ADDR(.sbss) - PAGE_OFFSET)
+	{ *(.sbss) *(.scommon) }
+  .bss : AT(ADDR(.bss) - PAGE_OFFSET)
+	{ *(.bss) *(COMMON) }
+  . = ALIGN(64 / 8);
+  _end = .;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+	*(.text.exit)
+	*(.data.exit)
+	}
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* These must appear regardless of  .  */
+  /* Discard them for now since Intel SoftSDV cannot handle them.
+  .comment 0 : { *(.comment) }
+  .note 0 : { *(.note) }
+  */
+  /DISCARD/ : { *(.comment) }
+  /DISCARD/ : { *(.note) }
+}
diff -u --recursive --new-file v2.3.42/linux/arch/m68k/atari/joystick.c linux/arch/m68k/atari/joystick.c
--- v2.3.42/linux/arch/m68k/atari/joystick.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/m68k/atari/joystick.c	Wed Feb  9 11:42:35 2000
@@ -118,16 +118,11 @@
 }
 
 struct file_operations atari_joystick_fops = {
-	NULL,		/* joystick_seek */
-	read_joystick,
-	write_joystick,
-	NULL,		/* joystick_readdir */
-	joystick_poll,
-	NULL,		/* joystick_ioctl */
-	NULL,		/* joystick_mmap */
-	open_joystick,
-	NULL,		/* flush */
-	release_joystick
+	read:		read_joystick,
+	write:		write_joystick,
+	poll:		joystick_poll,
+	open:		open_joystick,
+	release:	release_joystick,
 };
 
 int __init atari_joystick_init(void)
diff -u --recursive --new-file v2.3.42/linux/arch/m68k/bvme6000/rtc.c linux/arch/m68k/bvme6000/rtc.c
--- v2.3.42/linux/arch/m68k/bvme6000/rtc.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/m68k/bvme6000/rtc.c	Wed Feb  9 11:42:35 2000
@@ -158,16 +158,9 @@
  */
 
 static struct file_operations rtc_fops = {
-	NULL,
-	NULL,
-	NULL,		/* No write */
-	NULL,		/* No readdir */
-	NULL,
-	rtc_ioctl,
-	NULL,		/* No mmap */
-	rtc_open,
-	NULL,		/* flush */
-	rtc_release
+	ioctl:		rtc_ioctl,
+	open:		rtc_open,
+	release:	rtc_release,
 };
 
 static struct miscdevice rtc_dev=
diff -u --recursive --new-file v2.3.42/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c
--- v2.3.42/linux/arch/m68k/mac/adb-bus.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/m68k/mac/adb-bus.c	Wed Feb  9 11:42:35 2000
@@ -2498,16 +2498,11 @@
 }
 
 static struct file_operations adb_fops = {
-	adb_lseek,
-	adb_read,
-	adb_write,
-	NULL,		/* no readdir */
-	NULL,		/* no poll yet */
-	NULL,		/* no ioctl yet */
-	NULL,		/* no mmap */
-	adb_open,
-	NULL,		/* flush */
-	adb_release
+	llseek:		adb_lseek,
+	read:		adb_read,
+	write:		adb_write,
+	open:		adb_open,
+	release:	adb_release,
 };
 
 int adbdev_register(int subtype, struct file_operations *fops)
@@ -2683,16 +2678,11 @@
 }
 
 static struct file_operations adb_fops = {
-	adb_lseek,
-	adb_read,
-	adb_write,
-	NULL,		/* no readdir */
-	NULL,		/* no select */
-	NULL,		/* no ioctl */
-	NULL,		/* no mmap */
-	adb_open,
-	NULL,		/* flush */
-	adb_release
+	llseek:		adb_lseek,
+	read:		adb_read,
+	write:		adb_write,
+	open:		adb_open,
+	release:	adb_release,
 };
 
 static struct miscdevice adb_dev = {
diff -u --recursive --new-file v2.3.42/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.3.42/linux/arch/m68k/mm/init.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/m68k/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -38,8 +38,6 @@
 void mmu_emu_reserve_pages(unsigned long max_page);
 #endif
 
-extern void show_net_buffers(void);
-
 int do_check_pgt_cache(int low, int high)
 {
 	int freed = 0;
@@ -116,9 +114,6 @@
     printk("%d pages swap cached\n",cached);
     printk("%ld pages in page table cache\n",pgtable_cache_size);
     show_buffers();
-#ifdef CONFIG_NET
-    show_net_buffers();
-#endif
 }
 
 extern void init_pointer_table(unsigned long ptable);
diff -u --recursive --new-file v2.3.42/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c
--- v2.3.42/linux/arch/m68k/mvme16x/rtc.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/m68k/mvme16x/rtc.c	Wed Feb  9 11:42:35 2000
@@ -147,16 +147,9 @@
  */
 
 static struct file_operations rtc_fops = {
-	NULL,
-	NULL,
-	NULL,		/* No write */
-	NULL,		/* No readdir */
-	NULL,
-	rtc_ioctl,
-	NULL,		/* No mmap */
-	rtc_open,
-	NULL,		/* flush */
-	rtc_release
+	ioctl:		rtc_ioctl,
+	open:		rtc_open,
+	release:	rtc_release,
 };
 
 static struct miscdevice rtc_dev=
diff -u --recursive --new-file v2.3.42/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c
--- v2.3.42/linux/arch/mips/mm/init.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/mips/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -35,8 +35,6 @@
 #endif
 #include <asm/mmu_context.h>
 
-extern void show_net_buffers(void);
-
 void __bad_pte_kernel(pmd_t *pmd)
 {
 	printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
@@ -266,9 +264,6 @@
 	printk("%ld pages in page table cache\n",pgtable_cache_size);
 	printk("%d free pages\n", free);
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 }
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.3.42/linux/arch/ppc/Makefile	Tue Jan 11 22:31:36 2000
+++ linux/arch/ppc/Makefile	Wed Feb  9 19:43:47 2000
@@ -106,19 +106,24 @@
 znetboot: $(CHECKS) vmlinux
 ifdef CONFIG_ALL_PPC
 ifdef CONFIG_SMP
-ifdef CONFIG_PPC64
-	cp -f vmlinux /tftpboot/vmlinux.smp.64
-else
 	cp -f vmlinux /tftpboot/vmlinux.smp
-endif
-else
-ifdef CONFIG_PPC64
-	cp -f vmlinux /tftpboot/vmlinux.64
 else
 	cp -f vmlinux /tftpboot/vmlinux
 endif
 endif
+	@$(MAKECOFFBOOT) $@
+	@$(MAKEBOOT) $@
+	@$(MAKECHRPBOOT) $@
 endif
+
+ifdef CONFIG_PPC64
+$(BOOT_TARGETS): $(CHECKS) vmlinux
+	@$(MAKECOFFBOOT) $@
+	@$(MAKEBOOT) $@
+	@$(MAKECHRPBOOT) $@
+
+znetboot: $(CHECKS) vmlinux
+	cp -f vmlinux /tftpboot/vmlinux.64
 	@$(MAKECOFFBOOT) $@
 	@$(MAKEBOOT) $@
 	@$(MAKECHRPBOOT) $@
@@ -129,31 +134,31 @@
 	rm -f .config arch/ppc/defconfig
 
 gemini_config: clean_config
-	ln -s configs/gemini_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/gemini_defconfig arch/ppc/defconfig
 
 pmac_config: clean_config
-	ln -s configs/pmac_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/pmac_defconfig arch/ppc/defconfig
 
 prep_config: clean_config
-	ln -s configs/prep_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/prep_defconfig arch/ppc/defconfig
 
 chrp_config: clean_config
-	ln -s configs/chrp_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/chrp_defconfig arch/ppc/defconfig
 
 common_config: clean_config
-	ln -s configs/common_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/common_defconfig arch/ppc/defconfig
 
 mbx_config: clean_config
-	ln -s configs/mbx_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/mbx_defconfig arch/ppc/defconfig
 
 apus_config: clean_config
-	ln -s configs/apus_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/apus_defconfig arch/ppc/defconfig
 
 oak_config: clean_config
-	ln -s configs/oak_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/oak_defconfig arch/ppc/defconfig
 
 walnut_config: clean_config
-	ln -s configs/walnut_defconfig arch/ppc/defconfig
+	cp -f arch/ppc/configs/walnut_defconfig arch/ppc/defconfig
 
 archclean:
 	rm -f arch/ppc/kernel/{mk_defs,ppc_defs.h,find_name,checks}
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c
--- v2.3.42/linux/arch/ppc/amiga/amiints.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/amiga/amiints.c	Wed Feb  9 19:43:47 2000
@@ -350,7 +350,8 @@
 void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
 {
 	irq_node_t *node, *slow_nodes;
-	unsigned short flags, intena;
+	unsigned short intena;
+	unsigned long flags;
 
 	kstat.irqs[0][SYS_IRQS + irq]++;
 	if (server->count++)
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/amiga/cia.c linux/arch/ppc/amiga/cia.c
--- v2.3.42/linux/arch/ppc/amiga/cia.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/amiga/cia.c	Wed Feb  9 19:43:47 2000
@@ -45,10 +45,10 @@
 do {						\
 	if (irq >= IRQ_AMIGA_CIAB) {		\
 		base = &ciab_base;		\
-		irq =- IRQ_AMIGA_CIAB;		\
+		irq -= IRQ_AMIGA_CIAB;		\
 	} else {				\
 		base = &ciaa_base;		\
-		irq =- IRQ_AMIGA_CIAA;		\
+		irq -= IRQ_AMIGA_CIAA;		\
 	}					\
 } while (0)
 
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.3.42/linux/arch/ppc/boot/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/boot/Makefile	Wed Feb  9 19:43:47 2000
@@ -14,7 +14,7 @@
 .s.o:
 	$(AS) -o $*.o $<
 .c.o:
-	$(CC) $(CFLAGS)  -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -c -o $*.o $<
+	$(CC) $(CFLAGS)  -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -D__BOOTER__ -c -o $*.o $<
 .S.s:
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.o $<
 .S.o:
@@ -49,7 +49,7 @@
 
 ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00800000
 
-GZIP_FLAGS = -v9
+GZIP_FLAGS = -v9f
 
 OBJECTS := head.o misc.o ../coffboot/zlib.o
 CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin
@@ -73,6 +73,7 @@
 		-DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
 		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
 		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
+		-D__BOOTER__ \
 		-c -o misc.o misc.c
 	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
@@ -85,6 +86,10 @@
 ifdef CONFIG_PREP
 	./mkprep -pbp zvmlinux zImage
 endif
+ifdef CONFIG_APUS
+	$(STRIP) ../../../vmlinux -o vmapus
+	gzip $(GZIP_FLAGS) vmapus
+endif
 
 sImage: ../../../vmlinux
 ifdef CONFIG_GEMINI
@@ -110,6 +115,7 @@
 	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
 		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
 		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \
+		-D__BOOTER__ \
 		-c -o misc.o misc.c
 	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.3.42/linux/arch/ppc/chrpboot/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/chrpboot/Makefile	Wed Feb  9 19:43:47 2000
@@ -20,7 +20,7 @@
 LD_ARGS = -Ttext 0x00400000
 OBJCOPY = $(CROSS_COMPILE)objcopy
 
-OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o # initrd.o
+OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o sysmap.o
 LIBS = $(TOPDIR)/lib/lib.a
 
 ifeq ($(CONFIG_PPC64),y)
@@ -64,6 +64,9 @@
 
 image.o: piggyback ../coffboot/vmlinux.gz
 	./piggyback image < ../coffboot/vmlinux.gz | $(AS) -o image.o
+
+sysmap.o: piggyback ../../../System.map
+	./piggyback sysmap < ../../../System.map | $(AS) -o sysmap.o
 
 initrd.o: ramdisk.image.gz piggyback
 	./piggyback initrd < ramdisk.image.gz | $(AS) -o initrd.o
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c
--- v2.3.42/linux/arch/ppc/chrpboot/main.c	Tue Dec  7 09:32:41 1999
+++ linux/arch/ppc/chrpboot/main.c	Wed Feb  9 19:43:47 2000
@@ -34,6 +34,8 @@
 extern int image_len;
 extern char initrd_data[];
 extern int initrd_len;
+extern char sysmap_data[];
+extern int sysmap_len;
 
 
 chrpboot(int a1, int a2, void *prom)
@@ -78,12 +80,12 @@
     {
 	    struct bi_record *rec;
 	    
-	    rec = (struct bi_record *)PAGE_ALIGN((unsigned long)dst+len);
-	    
+	    rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20));
+
 	    rec->tag = BI_FIRST;
 	    rec->size = sizeof(struct bi_record);
 	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
+	    
 	    rec->tag = BI_BOOTLOADER_ID;
 	    sprintf( (char *)rec->data, "chrpboot");
 	    rec->size = sizeof(struct bi_record) + strlen("chrpboot") + 1;
@@ -95,6 +97,11 @@
 	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
 	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
 	    
+	    rec->tag = BI_SYSMAP;
+	    rec->data[0] = sysmap_data;
+	    rec->data[1] = sysmap_len;
+	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
 	    rec->tag = BI_LAST;
 	    rec->size = sizeof(struct bi_record);
 	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.3.42/linux/arch/ppc/coffboot/Makefile	Tue Jan 11 22:31:36 2000
+++ linux/arch/ppc/coffboot/Makefile	Wed Feb  9 19:43:47 2000
@@ -36,6 +36,9 @@
 endif
 
 ifeq ($(CONFIG_PMAC),y)
+chrpmain.o: chrpmain.c
+	$(CC) $(CFLAGS) -DSYSMAP_OFFSET=0 -DSYSMAP_SIZE=0 -c chrpmain.c
+
 hack-coff: hack-coff.c
 	$(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c
 
@@ -52,6 +55,12 @@
 #	cp vmlinux.coff /mnt
 #	umount /mnt
 
+miboot.image: dummy.o vmlinux.gz
+	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=vmlinux.gz dummy.o $@
+
+miboot.image.initrd: dummy.o vmlinux.gz
+	$(OBJCOPY) $(OBJCOPY_ARGS) --add-section=initrd=ramdisk.image.gz miboot.image $@
+
 coffboot: $(COFFOBJS) no_initrd.o ld.script
 	$(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) no_initrd.o $(LIBS)
 
@@ -82,16 +91,23 @@
 vmlinux.elf: $(CHRPOBJS) no_initrd.o mknote
 	$(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) no_initrd.o $(LIBS)
 	./mknote > note
-	$(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
+	$(OBJCOPY) $@ $@ --add-section=.note=note \
+		--add-section=sysmap=../../../System.map -R .comment
+	$(CC) $(CFLAGS) chrpmain.c -c -o chrpmain.o \
+		-DSYSMAP_OFFSET=`sh ../boot/offset $(OBJDUMP) $@ sysmap` \
+		-DSYSMAP_SIZE=`sh ../boot/size $(OBJDUMP) $@ sysmap`
+	$(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) no_initrd.o $(LIBS)
+	$(OBJCOPY) $@ $@ --add-section=.note=note \
+		--add-section=sysmap=../../../System.map -R .comment
 
 vmlinux.elf.initrd: $(CHRPOBJS) initrd.o mknote
 	$(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) initrd.o $(LIBS)
 	./mknote > note
 	$(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
 
-zImage: vmlinux.coff vmlinux.elf
+zImage: vmlinux.coff vmlinux.elf miboot.image
 
-zImage.initrd: vmlinux.coff.initrd vmlinux.elf.initrd
+zImage.initrd: vmlinux.coff.initrd vmlinux.elf.initrd miboot.image.initrd
 
 else
 znetboot: vmlinux.gz
@@ -118,5 +134,7 @@
 
 clean:
 	rm -f hack-coff coffboot zImage vmlinux.coff vmlinux.gz
+	rm -f mknote piggyback vmlinux.elf note
+	rm -f miboot.image miboot.image.initrd
 
 fastdep:
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/coffboot/chrpmain.c linux/arch/ppc/coffboot/chrpmain.c
--- v2.3.42/linux/arch/ppc/coffboot/chrpmain.c	Tue Jan 11 22:31:36 2000
+++ linux/arch/ppc/coffboot/chrpmain.c	Wed Feb  9 19:43:47 2000
@@ -92,8 +92,7 @@
 void make_bi_recs(unsigned long addr)
 {
 	struct bi_record *rec;
-
-	rec = (struct bi_record *)PAGE_ALIGN(addr);
+	rec = (struct bi_record *)_ALIGN((unsigned long)addr+(1<<20)-1,(1<<20));
 	    
 	rec->tag = BI_FIRST;
 	rec->size = sizeof(struct bi_record);
@@ -109,7 +108,15 @@
 	rec->data[1] = 1;
 	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
+	
+#ifdef SYSMAP_OFFSET
+	rec->tag = BI_SYSMAP;
+	rec->data[0] = SYSMAP_OFFSET;
+	rec->data[1] = SYSMAP_SIZE;
+	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+#endif /* SYSMAP_OFFSET */
+	
 	rec->tag = BI_LAST;
 	rec->size = sizeof(struct bi_record);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/coffboot/dummy.c linux/arch/ppc/coffboot/dummy.c
--- v2.3.42/linux/arch/ppc/coffboot/dummy.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/coffboot/dummy.c	Wed Feb  9 19:43:47 2000
@@ -0,0 +1,4 @@
+int main(void)
+{
+	return 0;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/coffboot/main.c linux/arch/ppc/coffboot/main.c
--- v2.3.42/linux/arch/ppc/coffboot/main.c	Tue Dec  7 09:32:41 1999
+++ linux/arch/ppc/coffboot/main.c	Wed Feb  9 19:43:47 2000
@@ -112,8 +112,8 @@
 #endif
     {
 	    struct bi_record *rec;
-
-	    rec = (struct bi_record *)PAGE_ALIGN((unsigned long)dst+len);
+	    
+	    rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20));
 	    
 	    rec->tag = BI_FIRST;
 	    rec->size = sizeof(struct bi_record);
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.42/linux/arch/ppc/config.in	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/config.in	Wed Feb  9 19:43:47 2000
@@ -15,7 +15,7 @@
 comment 'Platform support'
 define_bool CONFIG_PPC y
 choice 'Processor Type'	\
-	"6xx/7xx		CONFIG_6xx	\
+	"6xx/7xx/7400		CONFIG_6xx	\
 	 4xx			CONFIG_4xx	\
 	 630/Power3(64-Bit)	CONFIG_PPC64	\
 	 82xx			CONFIG_82xx	\
@@ -97,6 +97,9 @@
 if [ "$CONFIG_6xx" = "y" -a "$CONFIG_APUS" != "y" ]; then
     define_bool CONFIG_PCI y
 fi
+if [ "$CONFIG_PREP" = "y" -o "$CONFIG_PMAC" = "y" -o "$CONFIG_CHRP" = "y" -o "$CONFIG_ALL_PPC" = "y"]; then
+    define_bool CONFIG_PCI y
+fi
 
 bool 'Networking support' CONFIG_NET
 bool 'Sysctl support' CONFIG_SYSCTL
@@ -140,6 +143,7 @@
      bool '   Include MacIO ADB driver' CONFIG_ADB_MACIO
      bool '   Include PMU (Powerbook) ADB driver' CONFIG_ADB_PMU
      bool 'Support for ADB keyboard' CONFIG_ADB_KEYBOARD 
+     bool 'Support for ADB mouse' CONFIG_ADBMOUSE
   fi
   bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
   bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig
--- v2.3.42/linux/arch/ppc/configs/common_defconfig	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/configs/common_defconfig	Wed Feb  9 19:43:47 2000
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
 #
+# CONFIG_UID16 is not set
 
 #
 # Code maturity level options
@@ -37,6 +38,7 @@
 #
 # CONFIG_PCI is not set
 CONFIG_PCI=y
+CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -45,6 +47,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_PCI_NAMES is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_PARPORT is not set
 CONFIG_VGA_CONSOLE=y
@@ -58,6 +61,7 @@
 CONFIG_ADB_MACIO=y
 CONFIG_ADB_PMU=y
 CONFIG_ADB_KEYBOARD=y
+CONFIG_ADBMOUSE=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_TOTALMP is not set
 CONFIG_BOOTX_TEXT=y
@@ -84,7 +88,7 @@
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDESCSI=y
 
 #
 # IDE chipset support/bugfixes
@@ -111,7 +115,6 @@
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_HD is not set
@@ -178,11 +181,12 @@
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SG=y
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
+# CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -244,6 +248,12 @@
 CONFIG_SCSI_MESH=y
 CONFIG_SCSI_MESH_SYNC_RATE=5
 CONFIG_SCSI_MAC53C94=y
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
 
 #
 # Network device support
@@ -266,6 +276,7 @@
 CONFIG_MACE=y
 CONFIG_BMAC=y
 # CONFIG_NCR885E is not set
+# CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -407,17 +418,27 @@
 CONFIG_UNIX98_PTY_COUNT=256
 
 #
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
 # Mice
 #
 CONFIG_BUSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
-# CONFIG_ADBMOUSE is not set
+CONFIG_ADBMOUSE=y
 CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -431,11 +452,6 @@
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -445,9 +461,10 @@
 #
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
+# CONFIG_AGP is not set
 
 #
-# Support for USB
+# USB support
 #
 CONFIG_USB=y
 
@@ -456,31 +473,40 @@
 #
 # CONFIG_USB_UHCI is not set
 CONFIG_USB_OHCI=y
-CONFIG_USB_OHCI_DEBUG=y
-# CONFIG_USB_OHCI_HCD is not set
 
 #
 # Miscellaneous USB options
 #
-CONFIG_USB_DEBUG_ISOC=y
-CONFIG_USB_PROC=y
-# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_DEVICEFS is not set
 
 #
 # USB Devices
 #
-CONFIG_USB_HUB=y
-CONFIG_USB_MOUSE=y
-CONFIG_USB_HP_SCANNER=m
-CONFIG_USB_KBD=y
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCANNER is not set
 # CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
 # CONFIG_USB_SERIAL is not set
 # CONFIG_USB_CPIA is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
 # CONFIG_USB_DC2XX is not set
 CONFIG_USB_SCSI=m
 CONFIG_USB_SCSI_DEBUG=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# USB HID
+#
+# CONFIG_USB_HID is not set
+CONFIG_USB_KBD=y
+CONFIG_USB_MOUSE=y
+# CONFIG_USB_GRAPHIRE is not set
+# CONFIG_USB_WMFORCE is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
 
 #
 # Filesystems
@@ -493,9 +519,9 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
-# CONFIG_UDF_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -505,6 +531,7 @@
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -513,7 +540,7 @@
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFSD=y
-# CONFIG_NFSD_SUN is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -525,8 +552,6 @@
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
@@ -540,6 +565,7 @@
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 CONFIG_SOUND_OSS=y
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig
--- v2.3.42/linux/arch/ppc/configs/gemini_defconfig	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/configs/gemini_defconfig	Wed Feb  9 19:43:47 2000
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
 #
+# CONFIG_UID16 is not set
 
 #
 # Code maturity level options
@@ -217,6 +218,11 @@
 # CONFIG_SCSI_MAC53C94 is not set
 
 #
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
 # Network device support
 #
 CONFIG_NETDEVICES=y
@@ -237,6 +243,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 CONFIG_NCR885E=y
+# CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -414,4 +421,4 @@
 #
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_KGDB is not set
-CONFIG_XMON=y
+# CONFIG_XMON is not set
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig
--- v2.3.42/linux/arch/ppc/configs/oak_defconfig	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/configs/oak_defconfig	Wed Feb  9 19:43:47 2000
@@ -18,7 +18,6 @@
 # CONFIG_8xx is not set
 CONFIG_OAK=y
 # CONFIG_WALNUT is not set
-# CONFIG_PCI is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
@@ -33,6 +32,7 @@
 #
 # General setup
 #
+# CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -233,6 +233,11 @@
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
 
 #
 # Mice
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig
--- v2.3.42/linux/arch/ppc/configs/walnut_defconfig	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/configs/walnut_defconfig	Wed Feb  9 19:43:47 2000
@@ -18,7 +18,6 @@
 # CONFIG_8xx is not set
 # CONFIG_OAK is not set
 CONFIG_WALNUT=y
-CONFIG_PCI=y
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
@@ -33,6 +32,7 @@
 #
 # General setup
 #
+CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -235,6 +235,11 @@
 # CONFIG_UNIX98_PTYS is not set
 
 #
+# I2C support
+#
+CONFIG_I2C=y
+
+#
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
@@ -315,8 +320,8 @@
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.42/linux/arch/ppc/defconfig	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/defconfig	Wed Feb  9 19:43:47 2000
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
 #
+# CONFIG_UID16 is not set
 
 #
 # Code maturity level options
@@ -37,6 +38,7 @@
 #
 # CONFIG_PCI is not set
 CONFIG_PCI=y
+CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -45,6 +47,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_PCI_NAMES is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_PARPORT is not set
 CONFIG_VGA_CONSOLE=y
@@ -58,6 +61,7 @@
 CONFIG_ADB_MACIO=y
 CONFIG_ADB_PMU=y
 CONFIG_ADB_KEYBOARD=y
+CONFIG_ADBMOUSE=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_TOTALMP is not set
 CONFIG_BOOTX_TEXT=y
@@ -84,7 +88,7 @@
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDESCSI=y
 
 #
 # IDE chipset support/bugfixes
@@ -111,7 +115,6 @@
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_HD is not set
@@ -178,11 +181,12 @@
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SG=y
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
+# CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -244,6 +248,12 @@
 CONFIG_SCSI_MESH=y
 CONFIG_SCSI_MESH_SYNC_RATE=5
 CONFIG_SCSI_MAC53C94=y
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
 
 #
 # Network device support
@@ -266,6 +276,7 @@
 CONFIG_MACE=y
 CONFIG_BMAC=y
 # CONFIG_NCR885E is not set
+# CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -407,17 +418,27 @@
 CONFIG_UNIX98_PTY_COUNT=256
 
 #
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
 # Mice
 #
 CONFIG_BUSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
-# CONFIG_ADBMOUSE is not set
+CONFIG_ADBMOUSE=y
 CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -431,11 +452,6 @@
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -445,9 +461,10 @@
 #
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
+# CONFIG_AGP is not set
 
 #
-# Support for USB
+# USB support
 #
 CONFIG_USB=y
 
@@ -456,31 +473,40 @@
 #
 # CONFIG_USB_UHCI is not set
 CONFIG_USB_OHCI=y
-CONFIG_USB_OHCI_DEBUG=y
-# CONFIG_USB_OHCI_HCD is not set
 
 #
 # Miscellaneous USB options
 #
-CONFIG_USB_DEBUG_ISOC=y
-CONFIG_USB_PROC=y
-# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_DEVICEFS is not set
 
 #
 # USB Devices
 #
-CONFIG_USB_HUB=y
-CONFIG_USB_MOUSE=y
-CONFIG_USB_HP_SCANNER=m
-CONFIG_USB_KBD=y
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCANNER is not set
 # CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
 # CONFIG_USB_SERIAL is not set
 # CONFIG_USB_CPIA is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
 # CONFIG_USB_DC2XX is not set
 CONFIG_USB_SCSI=m
 CONFIG_USB_SCSI_DEBUG=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# USB HID
+#
+# CONFIG_USB_HID is not set
+CONFIG_USB_KBD=y
+CONFIG_USB_MOUSE=y
+# CONFIG_USB_GRAPHIRE is not set
+# CONFIG_USB_WMFORCE is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
 
 #
 # Filesystems
@@ -493,9 +519,9 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
-# CONFIG_UDF_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -505,6 +531,7 @@
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -513,7 +540,7 @@
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFSD=y
-# CONFIG_NFSD_SUN is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -525,8 +552,6 @@
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
@@ -540,6 +565,7 @@
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 CONFIG_SOUND_OSS=y
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.3.42/linux/arch/ppc/kernel/Makefile	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/Makefile	Wed Feb  9 19:43:47 2000
@@ -38,7 +38,7 @@
 endif
 
 ifdef CONFIG_PCI
-O_OBJS += pci.o
+O_OBJS += pci.o pci-dma.o
 endif
 
 ifdef CONFIG_KGDB
@@ -59,8 +59,16 @@
 
 ifeq ($(CONFIG_4xx),y)
   O_OBJS += ppc4xx_pic.o
-  ifeq ($(CONFIG_OAK),y)
-    O_OBJS += oak_setup.o
+endif
+
+ifeq ($(CONFIG_OAK),y)
+  O_OBJS += oak_setup.o
+endif
+
+ifeq ($(CONFIG_WALNUT),y)
+  O_OBJS += walnut_setup.o
+  ifeq ($(CONFIG_PCI),y)
+    O_OBJS += galaxy_pci.o
   endif
 endif
 
@@ -81,6 +89,9 @@
   O_OBJS += pmac_nvram.o
 endif
 ifeq ($(CONFIG_6xx),y)
+  O_OBJS += open_pic.o indirect_pci.o
+endif
+ifeq ($(CONFIG_PPC64),y)
   O_OBJS += open_pic.o indirect_pci.o
 endif
 ifeq ($(CONFIG_APUS),y)
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.3.42/linux/arch/ppc/kernel/apus_setup.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/apus_setup.c	Wed Feb  9 19:43:47 2000
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <linux/kd.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/hdreg.h>
 #include <linux/blk.h>
 #include <linux/pci.h>
@@ -28,8 +27,41 @@
 #include <asm/logging.h>
 #endif
 
-/* Get the IDE stuff from the 68k file */
 #include <linux/ide.h>
+#define T_CHAR          (0x0000)        /* char:  don't touch  */
+#define T_SHORT         (0x4000)        /* short: 12 -> 21     */
+#define T_INT           (0x8000)        /* int:   1234 -> 4321 */
+#define T_TEXT          (0xc000)        /* text:  12 -> 21     */
+
+#define T_MASK_TYPE     (0xc000)
+#define T_MASK_COUNT    (0x3fff)
+
+#define D_CHAR(cnt)     (T_CHAR  | (cnt))
+#define D_SHORT(cnt)    (T_SHORT | (cnt))
+#define D_INT(cnt)      (T_INT   | (cnt))
+#define D_TEXT(cnt)     (T_TEXT  | (cnt))
+
+static u_short driveid_types[] = {
+        D_SHORT(10),    /* config - vendor2 */
+        D_TEXT(20),     /* serial_no */
+        D_SHORT(3),     /* buf_type, buf_size - ecc_bytes */
+        D_TEXT(48),     /* fw_rev - model */
+        D_CHAR(2),      /* max_multsect - vendor3 */
+        D_SHORT(1),     /* dword_io */
+        D_CHAR(2),      /* vendor4 - capability */
+        D_SHORT(1),     /* reserved50 */
+        D_CHAR(4),      /* vendor5 - tDMA */
+        D_SHORT(4),     /* field_valid - cur_sectors */
+        D_INT(1),       /* cur_capacity */
+        D_CHAR(2),      /* multsect - multsect_valid */
+        D_INT(1),       /* lba_capacity */
+        D_SHORT(194)    /* dma_1word - reservedyy */
+};
+
+#define num_driveid_types       (sizeof(driveid_types)/sizeof(*driveid_types))
+
+#if 0 /* Get rid of this crud */
+/* Get the IDE stuff from the 68k file */
 #define ide_init_hwif_ports m68k_ide_init_hwif_ports
 #define ide_default_irq m68k_ide_default_irq
 #undef ide_request_irq
@@ -57,6 +89,7 @@
 #undef ide_release_region
 #undef ide_fix_driveid
 /*-------------------------------------------*/
+#endif
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
@@ -411,33 +444,6 @@
 {
 }
 
-#if defined(CONFIG_WHIPPET_SERIAL)||defined(CONFIG_MULTIFACE_III_TTY)||defined(CONFIG_GVPIOEXT)||defined(CONFIG_AMIGA_BUILTIN_SERIAL)
-
-long m68k_rs_init(void);
-int m68k_register_serial(struct serial_struct *);
-void m68k_unregister_serial(int);
-long m68k_serial_console_init(long, long );
-
-int rs_init(void)
-{
-	return m68k_rs_init();
-}
-int register_serial(struct serial_struct *p)
-{
-	return m68k_register_serial(p);
-}
-void unregister_serial(int i)
-{
-	m68k_unregister_serial(i);
-}
-#ifdef CONFIG_SERIAL_CONSOLE
-long serial_console_init(long kmem_start, long kmem_end)
-{
-	return m68k_serial_console_init(kmem_start, kmem_end);
-}
-#endif
-#endif
-
 /*********************************************************** FLOPPY */
 #if defined(CONFIG_AMIGA_FLOPPY)
 __init 
@@ -673,7 +679,7 @@
 int
 apus_ide_default_irq(ide_ioreg_t base)
 {
-        return m68k_ide_default_irq(base);
+        return 0;
 }
 
 ide_ioreg_t
@@ -685,7 +691,7 @@
 int
 apus_ide_check_region(ide_ioreg_t from, unsigned int extent)
 {
-        return m68k_ide_check_region(from, extent);
+        return 0;
 }
 
 void
@@ -693,27 +699,66 @@
 			unsigned int extent,
 			const char *name)
 {
-        m68k_ide_request_region(from, extent, name);
 }
 
 void
 apus_ide_release_region(ide_ioreg_t from,
 			unsigned int extent)
 {
-        m68k_ide_release_region(from, extent);
 }
 
 void
 apus_ide_fix_driveid(struct hd_driveid *id)
 {
-        m68k_ide_fix_driveid(id);
+   u_char *p = (u_char *)id;
+   int i, j, cnt;
+   u_char t;
+
+   if (!MACH_IS_AMIGA && !MACH_IS_MAC)
+   	return;
+   for (i = 0; i < num_driveid_types; i++) {
+      cnt = driveid_types[i] & T_MASK_COUNT;
+      switch (driveid_types[i] & T_MASK_TYPE) {
+         case T_CHAR:
+            p += cnt;
+            break;
+         case T_SHORT:
+            for (j = 0; j < cnt; j++) {
+               t = p[0];
+               p[0] = p[1];
+               p[1] = t;
+               p += 2;
+            }
+            break;
+         case T_INT:
+            for (j = 0; j < cnt; j++) {
+               t = p[0];
+               p[0] = p[3];
+               p[3] = t;
+               t = p[1];
+               p[1] = p[2];
+               p[2] = t;
+               p += 4;
+            }
+            break;
+         case T_TEXT:
+            for (j = 0; j < cnt; j += 2) {
+               t = p[0];
+               p[0] = p[1];
+               p[1] = t;
+               p += 2;
+            }
+            break;
+      }
+   }
 }
 
 __init
 void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, 
 			       ide_ioreg_t ctrl_port, int *irq)
 {
-        m68k_ide_init_hwif_ports(hw, data_port, ctrl_port, irq);
+        if (data_port || ctrl_port)
+                printk("apus_ide_init_hwif_ports: must not be called\n");
 }
 #endif
 /****************************************************** IRQ stuff */
@@ -732,7 +777,7 @@
 
 /* IPL must be between 0 and 7 */
 __apus
-static inline void apus_set_IPL(int ipl)
+static inline void apus_set_IPL(unsigned long ipl)
 {
 	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
 	APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
@@ -743,42 +788,22 @@
 __apus
 static inline unsigned long apus_get_IPL(void)
 {
-	unsigned short __f;
+	/* This returns the present IPL emulation level. */
+	unsigned long __f;
 	APUS_READ(APUS_IPL_EMU, __f);
 	return ((~__f) & IPLEMU_IPLMASK);
 }
 
 __apus
-static inline unsigned long apus_get_prev_IPL(void)
-{
-	unsigned short __f;
-	APUS_READ(APUS_IPL_EMU, __f);
-	return ((~__f >> 3) & IPLEMU_IPLMASK);
-}
-
-
-__apus
-static void apus_save_flags(unsigned long* flags)
+static inline unsigned long apus_get_prev_IPL(struct pt_regs* regs)
 {
-	*flags = apus_get_IPL();
-}
-
-__apus
-static void apus_restore_flags(unsigned long flags)
-{
-	apus_set_IPL(flags);
-}
-
-__apus
-static void apus_sti(void)
-{
-	apus_set_IPL(0);
-}
-
-__apus
-static void apus_cli(void)
-{
-	apus_set_IPL(7);
+	/* The value saved in mq is the IPL_EMU value at the time of
+	   interrupt. The lower bits are the current interrupt level,
+	   the upper bits the requested level. Thus, to restore the
+	   IPL level to the post-interrupt state, we will need to use
+	   the lower bits. */
+	unsigned long __f = regs->mq;
+	return ((~__f) & IPLEMU_IPLMASK);
 }
 
 
@@ -802,6 +827,22 @@
 
 	return amiga_request_irq (irq, handler, irqflags, devname, dev_id);
 }
+
+/* In Linux/m68k the sys_request_irq deals with vectors 0-7. That's what
+   callers expect - but on Linux/APUS we actually use the IRQ_AMIGA_AUTO
+   vectors (24-31), so we put this dummy function in between to adjust
+   the vector argument (rather have cruft here than in the generic irq.c). */
+int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+		    unsigned long irqflags, const char * devname, void *dev_id)
+{
+	extern int request_sysirq(unsigned int irq, 
+				  void (*handler)(int, void *, 
+						  struct pt_regs *),
+				  unsigned long irqflags,
+				  const char * devname, void *dev_id);
+	return request_sysirq(irq+IRQ_AMIGA_AUTO, handler, irqflags, 
+			      devname, dev_id);
+}
 #endif
 
 __apus
@@ -809,14 +850,17 @@
 {
 #ifdef CONFIG_APUS
 	int level = apus_get_IPL();
-	unsigned short ints = custom.intreqr & custom.intenar;
+
+#ifdef __INTERRUPT_DEBUG
+	printk("<%d:%d>", level, apus_get_prev_IPL(regs));
+#endif
 
 	if (0 == level)
-		return -1;
+		return -8;
 	if (7 == level)
-		return -2;
+		return -9;
 
-	return level;
+	return level + IRQ_AMIGA_AUTO;
 #else
 	return 0;
 #endif
@@ -824,10 +868,13 @@
 
 
 __apus
-void apus_post_irq(int level)
+void apus_post_irq(struct pt_regs* regs, int level)
 {
+#ifdef __INTERRUPT_DEBUG
+	printk("{%d}", apus_get_prev_IPL(regs));
+#endif
 	/* Restore IPL to the previous value */
-	apus_set_IPL(apus_get_IPL());
+	apus_set_IPL(apus_get_prev_IPL(regs));
 }
 
 
@@ -903,11 +950,28 @@
 	return NULL;
 }
 
+extern void amiga_enable_irq(unsigned int irq);
+extern void amiga_disable_irq(unsigned int irq);
+
+struct hw_interrupt_type amiga_irqctrl = {
+	" Amiga  ",
+	NULL,
+	NULL,
+	amiga_enable_irq,
+	amiga_disable_irq,
+	0,
+	0
+};
+
+
 __init
 void apus_init_IRQ(void)
 {
 	int i;
 
+	for ( i = 0 ; i < NR_IRQS ; i++ )
+		irq_desc[i].ctl = &amiga_irqctrl;
+
 	for (i = 0; i < NUM_IRQ_NODES; i++)
 		nodes[i].handler = NULL;
 
@@ -919,10 +983,10 @@
 
 	amiga_init_IRQ();
 
-	int_control.int_sti = apus_sti;
-	int_control.int_cli = apus_cli;
-	int_control.int_save_flags = apus_save_flags;
-	int_control.int_restore_flags = apus_restore_flags;
+	int_control.int_sti = __no_use_sti;
+	int_control.int_cli = __no_use_cli;
+	int_control.int_save_flags = __no_use_save_flags;
+	int_control.int_restore_flags = __no_use_restore_flags;
 }
 
 __init
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.3.42/linux/arch/ppc/kernel/chrp_pci.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/ppc/kernel/chrp_pci.c	Wed Feb  9 19:43:47 2000
@@ -273,14 +273,13 @@
 chrp_pcibios_fixup(void)
 {
 	struct pci_dev *dev;
-	
-	/* some of IBM chrps have > 1 bus */
-	if ( !strncmp("IBM", get_property(find_path_device("/"),
-					 "name", NULL),3) )
-	{
-		
-	}
-	
+	int i;
+	extern struct pci_ops generic_pci_ops;
+
+	/* Some IBM's with the python have >1 bus, this finds them */
+	for ( i = 0; i < python_busnr ; i++ )
+		pci_scan_bus(i+1, &generic_pci_ops, NULL);
+
 	/* PCI interrupts are controlled by the OpenPIC */
 	pci_for_each_dev(dev) {
 		if ( dev->irq )
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.42/linux/arch/ppc/kernel/chrp_setup.c	Wed Dec 29 13:13:12 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Wed Feb  9 19:43:47 2000
@@ -249,7 +249,6 @@
 	else
 #endif
 		ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
-sprintf(cmd_line, "console=ttyS0,9600 console=tty0");
 	printk("Boot arguments: %s\n", cmd_line);
 	
 	request_region(0x20,0x20,"pic1");
@@ -384,7 +383,7 @@
 	return irq;
 }
 
-void chrp_post_irq(int irq)
+void chrp_post_irq(struct pt_regs* regs, int irq)
 {
 	/*
 	 * If it's an i8259 irq then we've already done the
@@ -394,7 +393,7 @@
 	 * We do it this way since our irq_desc[irq].handler can change
 	 * with RTL and no longer be open_pic -- Cort
 	 */
-	if ( irq >= open_pic.irq_offset)
+	if ( irq >= open_pic_irq_offset)
 		openpic_eoi( smp_processor_id() );
 }
 
@@ -411,10 +410,11 @@
 			(*(unsigned long *)get_property(np,
 							"8259-interrupt-acknowledge", NULL));
 	}
-	open_pic.irq_offset = 16;
+	open_pic_irq_offset = 16;
 	for ( i = 16 ; i < NR_IRQS ; i++ )
 		irq_desc[i].handler = &open_pic;
 	openpic_init(1);
+	enable_irq(IRQ_8259_CASCADE);
 	for ( i = 0 ; i < 16  ; i++ )
 		irq_desc[i].handler = &i8259_pic;
 	i8259_init();
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- v2.3.42/linux/arch/ppc/kernel/chrp_time.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/ppc/kernel/chrp_time.c	Wed Feb  9 19:43:47 2000
@@ -171,9 +171,10 @@
 		if (fp != 0)
 			freq = *fp;
 	}
-	freq *= 60;	/* try to make freq/1e6 an integer */
-        divisor = 60;
-        printk("time_init: decrementer frequency = %lu/%d\n", freq, divisor);
+	freq *= 30;
+	divisor = 30; 
+        printk("time_init: decrementer frequency = %lu/%d (%d MHz)\n", freq,
+	       divisor, (freq/divisor)>>20);
         decrementer_count = freq / HZ / divisor;
         count_period_num = divisor;
         count_period_den = freq / 1000000;
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.3.42/linux/arch/ppc/kernel/entry.S	Fri Jan 28 15:09:07 2000
+++ linux/arch/ppc/kernel/entry.S	Wed Feb  9 19:43:47 2000
@@ -256,6 +256,15 @@
 	REST_8GPRS(23, r1)
 	REST_GPR(31, r1)
 	lwz	r2,_NIP(r1)	/* Restore environment */
+	/* 
+	 * We need to hard disable here even if RTL is active since
+	 * being interrupted after here trashes SRR{0,1}
+	 *  -- Cort
+	 */ 
+	mfmsr	r0		/* Get current interrupt state */
+	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
+	mtmsr	r0		/* Update machine state */
+	
 	lwz	r0,_MSR(r1)
 	mtspr	SRR0,r2
 	mtspr	SRR1,r0
@@ -271,7 +280,7 @@
 	bl	schedule_tail
 	b	ret_from_except
 #endif
-		
+
 	.globl	ret_from_intercept
 ret_from_intercept:
 	/*
@@ -291,7 +300,7 @@
 
 	.globl	ret_from_except
 ret_from_except:
-0:	/* disable interrupts */	
+0:	/* disable interrupts */
 	lis	r30,int_control@h
 	ori	r30,r30,int_control@l
 	lwz	r30,0(r30)
@@ -342,16 +351,26 @@
 	.globl	do_signal_ret
 do_signal_ret:
 	b	0b
-8:	addi	r4,r1,INT_FRAME_SIZE	/* size of frame */
+8:	/* 
+	 * We need to hard disable here even if RTL is active since
+	 * being interrupted after here trashes the SPRG2
+	 *  -- Cort
+	 */ 
+	mfmsr	r0		/* Get current interrupt state */
+	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
+	mtmsr	r0		/* Update machine state */
+	
+	addi	r4,r1,INT_FRAME_SIZE	/* size of frame */
 	stw	r4,THREAD+KSP(r2)	/* save kernel stack pointer */
 	tophys(r3,r1)
 	mtspr	SPRG2,r3	/* phys exception stack pointer */
+	b	11f
 10:	/* make sure we hard disable here, even if rtl is active -- Cort */
 	mfmsr	r0		/* Get current interrupt state */
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
 	sync			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
-	
+11: 
 	lwz	r2,_CTR(r1)
 	lwz	r0,_LINK(r1)
 	mtctr	r2
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
--- v2.3.42/linux/arch/ppc/kernel/feature.c	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/kernel/feature.c	Thu Feb 10 12:37:22 2000
@@ -8,85 +8,144 @@
  *  as published by the Free Software Foundation; either version
  *  2 of the License, or (at your option) any later version.
  *
+ *  BenH: Changed implementation to work on multiple registers
+ * 	  polarity is also taken into account. Removed delay (now
+ * 	  responsibility of the caller). Added spinlocks.
+ *
  */
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 #include <asm/errno.h>
 #include <asm/ohare.h>
+#include <asm/heathrow.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/feature.h>
 
-#define MAX_FEATURE_REGS		2
 #undef DEBUG_FEATURE
 
-static u32 feature_bits_pbook[] = {
-	0,			/* FEATURE_null */
-	OH_SCC_RESET,		/* FEATURE_Serial_reset */
-	OH_SCC_ENABLE,		/* FEATURE_Serial_enable */
-	OH_SCCA_IO,		/* FEATURE_Serial_IO_A */
-	OH_SCCB_IO,		/* FEATURE_Serial_IO_B */
-	OH_FLOPPY_ENABLE,	/* FEATURE_SWIM3_enable */
-	OH_MESH_ENABLE,		/* FEATURE_MESH_enable */
-	OH_IDE_ENABLE,		/* FEATURE_IDE_enable */
-	OH_VIA_ENABLE,		/* FEATURE_VIA_enable */
-	OH_IDECD_POWER,		/* FEATURE_CD_power */
-	OH_BAY_RESET,		/* FEATURE_Mediabay_reset */
-	OH_BAY_ENABLE,		/* FEATURE_Mediabay_enable */
-	OH_BAY_PCI_ENABLE,	/* FEATURE_Mediabay_PCI_enable */
-	OH_BAY_IDE_ENABLE,	/* FEATURE_Mediabay_IDE_enable */
-	OH_BAY_FLOPPY_ENABLE,	/* FEATURE_Mediabay_floppy_enable */
-	0,			/* FEATURE_BMac_reset */
-	0,			/* FEATURE_BMac_IO_enable */
-	0,			/* FEATURE_Modem_Reset -> guess... */
-	OH_IDE_POWER,		/* FEATURE_IDE_DiskPower -> guess... */
-	OH_IDE_RESET		/* FEATURE_IDE_Reset (0 based) -> guess... */
+#define MAX_FEATURE_CONTROLLERS		2
+#define MAX_FEATURE_OFFSET		0x50
+#define FREG(c,r)			(&(((c)->reg)[(r)>>2]))
+
+typedef struct feature_bit {
+	int		reg;		/* reg. offset from mac-io base */
+	unsigned int	polarity;	/* 0 = normal, 1 = inverse */
+	unsigned int	mask;		/* bit mask */
+} fbit;
+
+/* I don't have an OHare machine to test with, so I left those as they
+ * were. Someone with such a machine chould check out what OF says and
+ * try too see if they match the heathrow ones and should be changed too
+ */
+static fbit feature_bits_ohare_pbook[] = {
+	{0x38,0,0},			/* FEATURE_null */
+	{0x38,0,OH_SCC_RESET},		/* FEATURE_Serial_reset */
+	{0x38,0,OH_SCC_ENABLE},		/* FEATURE_Serial_enable */
+	{0x38,0,OH_SCCA_IO},		/* FEATURE_Serial_IO_A */
+	{0x38,0,OH_SCCB_IO},		/* FEATURE_Serial_IO_B */
+	{0x38,0,OH_FLOPPY_ENABLE},	/* FEATURE_SWIM3_enable */
+	{0x38,0,OH_MESH_ENABLE},	/* FEATURE_MESH_enable */
+	{0x38,0,OH_IDE0_ENABLE},	/* FEATURE_IDE0_enable */
+	{0x38,1,OH_IDE0_RESET_N},	/* FEATURE_IDE0_reset */
+	{0x38,0,OH_IOBUS_ENABLE},	/* FEATURE_IOBUS_enable */
+	{0x38,1,OH_BAY_RESET_N},	/* FEATURE_Mediabay_reset */
+	{0x38,1,OH_BAY_POWER_N},	/* FEATURE_Mediabay_power */
+	{0x38,0,OH_BAY_PCI_ENABLE},	/* FEATURE_Mediabay_PCI_enable */
+	{0x38,0,OH_BAY_IDE_ENABLE},	/* FEATURE_Mediabay_IDE_enable */
+	{0x38,1,OH_IDE1_RESET_N},	/* FEATURE_Mediabay_IDE_reset */
+	{0x38,0,OH_BAY_FLOPPY_ENABLE},	/* FEATURE_Mediabay_floppy_enable */
+	{0x38,0,0},			/* FEATURE_BMac_reset */
+	{0x38,0,0},			/* FEATURE_BMac_IO_enable */
+	{0x38,0,0},			/* FEATURE_Modem_power */
+	{0x38,0,0},			/* FEATURE_Slow_SCC_PCLK */
+	{0x38,0,0},			/* FEATURE_Sound_Power */
+	{0x38,0,0},			/* FEATURE_Sound_CLK_Enable */
+	{0x38,0,0},			/* FEATURE_IDE2_enable */
+	{0x38,0,0},			/* FEATURE_IDE2_reset */
 };
 
-/* assume these are the same as the ohare until proven otherwise */
-static u32 feature_bits_heathrow[] = {
-	0,			/* FEATURE_null */
-	OH_SCC_RESET,		/* FEATURE_Serial_reset */
-	OH_SCC_ENABLE,		/* FEATURE_Serial_enable */
-	OH_SCCA_IO,		/* FEATURE_Serial_IO_A */
-	OH_SCCB_IO,		/* FEATURE_Serial_IO_B */
-	OH_FLOPPY_ENABLE,	/* FEATURE_SWIM3_enable */
-	OH_MESH_ENABLE,		/* FEATURE_MESH_enable */
-	OH_IDE_ENABLE,		/* FEATURE_IDE_enable */
-	OH_VIA_ENABLE,		/* FEATURE_VIA_enable */
-	OH_IDECD_POWER,		/* FEATURE_CD_power */
-	OH_BAY_RESET,		/* FEATURE_Mediabay_reset */
-	OH_BAY_ENABLE,		/* FEATURE_Mediabay_enable */
-	OH_BAY_PCI_ENABLE,	/* FEATURE_Mediabay_PCI_enable */
-	OH_BAY_IDE_ENABLE,	/* FEATURE_Mediabay_IDE_enable */
-	OH_BAY_FLOPPY_ENABLE,	/* FEATURE_Mediabay_floppy_enable */
-	0x80000000,		/* FEATURE_BMac_reset */
-	0x60000000,		/* FEATURE_BMac_IO_enable */
-	0x02000000,		/* FEATURE_Modem_Reset -> guess...*/
-	OH_IDE_POWER,		/* FEATURE_IDE_DiskPower -> guess... */
-	OH_IDE_RESET		/* FEATURE_IDE_Reset (0 based) -> guess... */
+/* Those bits are from a PowerBook. It's possible that desktop machines
+ * based on heathrow need a different definition or some bits removed
+ */
+static fbit feature_bits_heathrow[] = {
+	{0x38,0,0},			/* FEATURE_null */
+	{0x38,0,HRW_RESET_SCC},		/* FEATURE_Serial_reset */
+	{0x38,0,HRW_SCC_ENABLE},	/* FEATURE_Serial_enable */
+	{0x38,0,HRW_SCCA_IO},		/* FEATURE_Serial_IO_A */
+	{0x38,0,HRW_SCCB_IO},		/* FEATURE_Serial_IO_B */
+	{0x38,0,HRW_SWIM_ENABLE},	/* FEATURE_SWIM3_enable */
+	{0x38,0,HRW_MESH_ENABLE},	/* FEATURE_MESH_enable */
+	{0x38,0,HRW_IDE0_ENABLE},	/* FEATURE_IDE0_enable */
+	{0x38,1,HRW_IDE0_RESET_N},	/* FEATURE_IDE0_reset */
+	{0x38,0,HRW_IOBUS_ENABLE},	/* FEATURE_IOBUS_enable */
+	{0x38,1,HRW_BAY_RESET_N},	/* FEATURE_Mediabay_reset */
+	{0x38,1,HRW_BAY_POWER_N},	/* FEATURE_Mediabay_power */
+	{0x38,0,HRW_BAY_PCI_ENABLE},	/* FEATURE_Mediabay_PCI_enable */
+	{0x38,0,HRW_BAY_IDE_ENABLE},	/* FEATURE_Mediabay_IDE_enable */
+	{0x38,1,HRW_IDE1_RESET_N},	/* FEATURE_Mediabay_IDE_reset */
+	{0x38,0,HRW_BAY_FLOPPY_ENABLE},	/* FEATURE_Mediabay_floppy_enable */
+	{0x38,0,HRW_BMAC_RESET},	/* FEATURE_BMac_reset */
+	{0x38,0,HRW_BMAC_IO_ENABLE},	/* FEATURE_BMac_IO_enable */
+	{0x38,1,HRW_MODEM_POWER_N},	/* FEATURE_Modem_power */
+	{0x38,0,HRW_SLOW_SCC_PCLK},	/* FEATURE_Slow_SCC_PCLK */
+	{0x38,1,HRW_SOUND_POWER_N},	/* FEATURE_Sound_Power */
+	{0x38,0,HRW_SOUND_CLK_ENABLE},	/* FEATURE_Sound_CLK_Enable */
+	{0x38,0,0},			/* FEATURE_IDE2_enable */
+	{0x38,0,0},			/* FEATURE_IDE2_reset */
+};
+
+/* Those bits are from an iBook.
+ */
+static fbit feature_bits_keylargo[] = {
+	{0x38,0,0},			/* FEATURE_null */
+	{0x38,0,0},			/* FEATURE_Serial_reset */
+	{0x38,0,0x00000054},		/* FEATURE_Serial_enable */
+	{0x38,0,0},			/* FEATURE_Serial_IO_A */
+	{0x38,0,0},			/* FEATURE_Serial_IO_B */
+	{0x38,0,0},			/* FEATURE_SWIM3_enable */
+	{0x38,0,0},			/* FEATURE_MESH_enable */
+	{0x38,0,0},			/* FEATURE_IDE0_enable */
+	{0x3c,1,0x01000000},		/* FEATURE_IDE0_reset */
+	{0x38,0,0},			/* FEATURE_IOBUS_enable */
+	{0x38,0,0},			/* FEATURE_Mediabay_reset */
+	{0x38,0,0},			/* FEATURE_Mediabay_power */
+	{0x38,0,0},			/* FEATURE_Mediabay_PCI_enable */
+	{0x38,0,0},			/* FEATURE_Mediabay_IDE_enable */
+	{0x3c,1,0x08000000},		/* FEATURE_Mediabay_IDE_reset */
+	{0x38,0,0},			/* FEATURE_Mediabay_floppy_enable */
+	{0x38,0,0},			/* FEATURE_BMac_reset */
+	{0x38,0,0},			/* FEATURE_BMac_IO_enable */
+	{0x40,1,0x02000000},		/* FEATURE_Modem_power */
+	{0x38,0,0},			/* FEATURE_Slow_SCC_PCLK */
+	{0x38,0,0},			/* FEATURE_Sound_Power */
+	{0x38,0,0},			/* FEATURE_Sound_CLK_Enable */
+	{0x38,0,0},			/* FEATURE_IDE2_enable */
+	{0x3c,1,0x40000000},		/* FEATURE_IDE2_reset */
 };
 
 /* definition of a feature controller object */
-struct feature_controller
-{
-	u32*			bits;
+struct feature_controller {
+	fbit*			bits;
 	volatile u32*		reg;
 	struct device_node*	device;
+	spinlock_t		lock;
 };
 
 /* static functions */
 static void
-feature_add_controller(struct device_node *controller_device, u32* bits);
+feature_add_controller(struct device_node *controller_device, fbit* bits);
 
-static int
+static struct feature_controller*
 feature_lookup_controller(struct device_node *device);
 
 /* static varialbles */
-static struct feature_controller	controllers[MAX_FEATURE_REGS];
+static struct feature_controller	controllers[MAX_FEATURE_CONTROLLERS];
 static int				controller_count = 0;
 
 
@@ -96,18 +155,23 @@
 	struct device_node *np;
 
 	np = find_devices("mac-io");
-	while (np != NULL)
-	{
-		feature_add_controller(np, feature_bits_heathrow);
+	while (np != NULL) {
+		/* KeyLargo contains several (5 ?) FCR registers in mac-io,
+		 * plus some gpio's which could eventually be handled here.
+		 */
+		if (device_is_compatible(np, "Keylargo")) {
+			feature_add_controller(np, feature_bits_keylargo);
+		} else {
+			feature_add_controller(np, feature_bits_heathrow);
+		}
 		np = np->next;
 	}
 	if (controller_count == 0)
 	{
 		np = find_devices("ohare");
-		if (np)
-		{
+		if (np) {
 			if (find_devices("via-pmu") != NULL)
-				feature_add_controller(np, feature_bits_pbook);
+				feature_add_controller(np, feature_bits_ohare_pbook);
 			else
 				/* else not sure; maybe this is a Starmax? */
 				feature_add_controller(np, NULL);
@@ -116,17 +180,26 @@
 
 	if (controller_count)
 		printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
+
+#ifdef CONFIG_PMAC_PBOOK
+#ifdef CONFIG_DMASOUND_MODULE
+	/* On PowerBooks, we disable the sound chip when dmasound is a module */
+	if (controller_count && find_devices("via-pmu") != NULL) {
+		feature_clear(controllers[0].device, FEATURE_Sound_power);
+		feature_clear(controllers[0].device, FEATURE_Sound_CLK_enable);
+	}
+#endif	
+#endif
 }
 
 static void
-feature_add_controller(struct device_node *controller_device, u32* bits)
+feature_add_controller(struct device_node *controller_device, fbit* bits)
 {
 	struct feature_controller*	controller;
 	
-	if (controller_count >= MAX_FEATURE_REGS)
-	{
+	if (controller_count >= MAX_FEATURE_CONTROLLERS) {
 		printk(KERN_INFO "Feature controller %s skipped(MAX:%d)\n",
-			controller_device->full_name, MAX_FEATURE_REGS);
+			controller_device->full_name, MAX_FEATURE_CONTROLLERS);
 		return;
 	}
 	controller = &controllers[controller_count];
@@ -140,30 +213,32 @@
 	}
 
 	controller->reg		= (volatile u32 *)ioremap(
-		controller_device->addrs[0].address + OHARE_FEATURE_REG, 4);
+		controller_device->addrs[0].address, MAX_FEATURE_OFFSET);
 
 	if (bits == NULL) {
 		printk(KERN_INFO "Twiddling the magic ohare bits\n");
-		out_le32(controller->reg, STARMAX_FEATURES);
+		out_le32(FREG(controller,OHARE_FEATURE_REG), STARMAX_FEATURES);
 		return;
 	}
 
+	spin_lock_init(&controller->lock);
+
 	controller_count++;
 }
 
-static int
+static struct feature_controller*
 feature_lookup_controller(struct device_node *device)
 {
 	int	i;
 	
 	if (device == NULL)
-		return -EINVAL;
+		return NULL;
 		
 	while(device)
 	{
 		for (i=0; i<controller_count; i++)
 			if (device == controllers[i].device)
-				return i;
+				return &controllers[i];
 		device = device->parent;
 	}
 
@@ -172,35 +247,36 @@
 		device->name);
 #endif
 	
-	return -ENODEV;
+	return NULL;
 }
 
 int
 feature_set(struct device_node* device, enum system_feature f)
 {
-	int		controller;
-	unsigned long	flags;
+	struct feature_controller*	controller;
+	unsigned long			flags;
+	unsigned long			value;
+	fbit*				bit;
 
 	if (f >= FEATURE_last)
 		return -EINVAL;	
 
 	controller = feature_lookup_controller(device);
-	if (controller < 0)
-		return controller;
+	if (!controller)
+		return -ENODEV;
+	bit = &controller->bits[f];
 	
 #ifdef DEBUG_FEATURE
 	printk("feature: <%s> setting feature %d in controller @0x%x\n",
-		device->name, (int)f, (unsigned int)controllers[controller].reg);
+		device->name, (int)f, (unsigned int)controller->reg);
 #endif
 
-	save_flags(flags);
-	cli();
-	out_le32( controllers[controller].reg,
-		 in_le32(controllers[controller].reg) |
-		 controllers[controller].bits[f]);
-	(void)in_le32(controllers[controller].reg);
-	restore_flags(flags);
-	udelay(10);
+	spin_lock_irqsave(&controller->lock, flags);
+	value = in_le32(FREG(controller, bit->reg));
+	value = bit->polarity ? (value & ~bit->mask) : (value | bit->mask);
+	out_le32(FREG(controller, bit->reg), value);
+	(void)in_le32(FREG(controller, bit->reg));
+	spin_unlock_irqrestore(&controller->lock, flags);
 	
 	return 0;
 }
@@ -208,29 +284,30 @@
 int
 feature_clear(struct device_node* device, enum system_feature f)
 {
-	int		controller;
-	unsigned long	flags;
+	struct feature_controller*	controller;
+	unsigned long			flags;
+	unsigned long			value;
+	fbit*				bit;
 
 	if (f >= FEATURE_last)
 		return -EINVAL;	
 
 	controller = feature_lookup_controller(device);
-	if (controller < 0)
-		return controller;
+	if (!controller)
+		return -ENODEV;
+	bit = &controller->bits[f];
 	
 #ifdef DEBUG_FEATURE
 	printk("feature: <%s> clearing feature %d in controller @0x%x\n",
-		device->name, (int)f, (unsigned int)controllers[controller].reg);
+		device->name, (int)f, (unsigned int)controller->reg);
 #endif
 
-	save_flags(flags);
-	cli();
-	out_le32( controllers[controller].reg,
-		 in_le32(controllers[controller].reg) &
-		 ~(controllers[controller].bits[f]));
-	(void)in_le32(controllers[controller].reg);
-	restore_flags(flags);
-	udelay(10);
+	spin_lock_irqsave(&controller->lock, flags);
+	value = in_le32(FREG(controller, bit->reg));
+	value = bit->polarity ? (value | bit->mask) : (value & ~bit->mask);
+	out_le32(FREG(controller, bit->reg), value);
+	(void)in_le32(FREG(controller, bit->reg));
+	spin_unlock_irqrestore(&controller->lock, flags);
 	
 	return 0;
 }
@@ -238,16 +315,27 @@
 int
 feature_test(struct device_node* device, enum system_feature f)
 {
-	int		controller;
+	struct feature_controller*	controller;
+	unsigned long			value;
+	fbit*				bit;
 
 	if (f >= FEATURE_last)
 		return -EINVAL;	
 
 	controller = feature_lookup_controller(device);
-	if (controller < 0)
-		return controller;
+	if (!controller)
+		return -ENODEV;
+	bit = &controller->bits[f];
 	
-	return (in_le32(controllers[controller].reg) &
-		controllers[controller].bits[f]) != 0;
+#ifdef DEBUG_FEATURE
+	printk("feature: <%s> clearing feature %d in controller @0x%x\n",
+		device->name, (int)f, (unsigned int)controller->reg);
+#endif
+	/* If one feature contains several bits, all of them must be set
+	 * for value to be true, or all of them must be 0 if polarity is
+	 * inverse
+	 */
+	value = (in_le32(FREG(controller, bit->reg)) & bit->mask);
+	return bit->polarity ? (value == 0) : (value == bit->mask);
 }
 
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/galaxy_pci.c linux/arch/ppc/kernel/galaxy_pci.c
--- v2.3.42/linux/arch/ppc/kernel/galaxy_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/galaxy_pci.c	Thu Feb 10 12:37:51 2000
@@ -0,0 +1,102 @@
+/*
+ *
+ *    Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
+ *    All rights reserved.
+ *
+ *    Module name: galaxy_pci.c
+ *
+ *    Description:
+ *      PCI interface code for the IBM PowerPC 405GP on-chip PCI bus
+ *      interface.
+ *
+ *      Why is this file called "galaxy_pci"? Because on the original
+ *      IBM "Walnut" evaluation board schematic I have, the 405GP is
+ *      is labeled "GALAXY".
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+
+#include "pci.h"
+
+
+/* Preprocessor Defines */
+
+#define	PCICFGADDR	(volatile unsigned int *)(0xEEC00000)
+#define	PCICFGDATA	(volatile unsigned int *)(0xEEC00004)
+
+
+/* Function Prototypes */
+
+decl_config_access_method(galaxy);
+
+
+void __init
+galaxy_pcibios_fixup(void)
+{
+
+}
+
+void __init
+galaxy_setup_pci_ptrs(void)
+{
+	set_config_access_method(galaxy);
+
+	ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
+}
+
+int
+galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+				unsigned char offset, unsigned char *val)
+{
+
+	return (PCIBIOS_SUCCESSFUL);
+}
+
+int
+galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+				unsigned char offset, unsigned short *val)
+{
+
+	return (PCIBIOS_SUCCESSFUL);
+}
+
+int
+galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+				 unsigned char offset, unsigned int *val)
+{
+
+	return (PCIBIOS_SUCCESSFUL);
+}
+
+int
+galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+				 unsigned char offset, unsigned char val)
+{
+
+	return (PCIBIOS_SUCCESSFUL);
+}
+
+int
+galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+				 unsigned char offset, unsigned short val)
+{
+
+	return (PCIBIOS_SUCCESSFUL);
+}
+
+int
+galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+				  unsigned char offset, unsigned int val)
+{
+
+	return (PCIBIOS_SUCCESSFUL);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- v2.3.42/linux/arch/ppc/kernel/gemini_setup.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/gemini_setup.c	Wed Feb  9 19:43:47 2000
@@ -53,7 +53,7 @@
 };
 
 int chrp_get_irq(struct pt_regs *);
-void chrp_post_irq(int);		 
+void chrp_post_irq(struct pt_regs* regs, int);
 
 static inline unsigned long _get_HID1(void)
 {
@@ -132,6 +132,19 @@
 extern int root_mountflags;
 extern char cmd_line[];
 
+void
+gemini_heartbeat(void)
+{
+	static unsigned long led = GEMINI_LEDBASE+(4*8);
+	static char direction = 8;
+	*(char *)led = 0;
+	if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
+	     (led + direction) < (GEMINI_LEDBASE+(4*8)) )
+		direction *= -1;
+	led += direction;
+	*(char *)led = 0xff;
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
 
 void __init gemini_setup_arch(void)
 {
@@ -175,6 +188,10 @@
 	printk("CPU manufacturer: %s [rev=%04x]\n", (cpu & (1<<15)) ? "IBM" :
 	       "Motorola", (cpu & 0xffff));
 
+	ppc_md.heartbeat = gemini_heartbeat;
+	ppc_md.heartbeat_reset = HZ/8;
+	ppc_md.heartbeat_count = 1;
+	
 	/* take special pains to map the MPIC, since it isn't mapped yet */
 	gemini_openpic_init();
 	/* start the L2 */
@@ -505,7 +522,7 @@
 	return irq;
 }
 
-void gemini_post_irq(int irq)
+void gemini_post_irq(struct pt_regs* regs, int irq)
 {
 	/*
 	 * If it's an i8259 irq then we've already done the
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.3.42/linux/arch/ppc/kernel/head.S	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/kernel/head.S	Wed Feb  9 19:43:47 2000
@@ -156,6 +156,16 @@
 	bl	fix_mem_constants
 #endif /* CONFIG_APUS */
 
+#ifndef CONFIG_GEMINI
+/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
+ * the physical address we are running at, returned by prom_init()
+ */
+__after_prom_start:
+ 	bl	mmu_off
+	bl	clear_bats
+	bl	flush_tlbs
+#endif
+
 /*
  * Use the first pair of BAT registers to map the 1st 16MB
  * of RAM to KERNELBASE.  From this point on we can't safely
@@ -211,6 +221,11 @@
 	mtspr	DBAT0U,r11		/* bit in upper BAT register */
 	mtspr	IBAT0L,r8
 	mtspr	IBAT0U,r11
+#if 0 /* Useful debug code, please leave in for now so I don't have to
+       * look at docs when I need to setup a BAT ;
+       */
+	bl	setup_screen_bat
+#endif
 5:	isync
 
 #ifndef CONFIG_APUS
@@ -627,12 +642,8 @@
 	mtcrf	0x80,r3
 	rfi	
 
-/* Instruction address breakpoint exception (on 603/604) */
 	STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
-
-/* System management exception (603?) */
-	STD_EXCEPTION(0x1400, Trap_14, UnknownException)
-
+	STD_EXCEPTION(0x1400, SMI, SMIException)
 	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
 	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
 	STD_EXCEPTION(0x1700, Trap_17, TAUException)
@@ -644,10 +655,7 @@
 	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
 	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
 	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
-
-	/* Run mode exception */
 	STD_EXCEPTION(0x2000, RunMode, RunModeException)
-
 	STD_EXCEPTION(0x2100, Trap_21, UnknownException)
 	STD_EXCEPTION(0x2200, Trap_22, UnknownException)
 	STD_EXCEPTION(0x2300, Trap_23, UnknownException)
@@ -911,12 +919,16 @@
  * the kernel image to physical address 0.
  */
 relocate_kernel:
+#if 0 /* Is this still needed ? I don't think so. It breaks new
+       *  boot-with-mmu-off stuff
+       */
 	lis	r9,0x426f		/* if booted from BootX, don't */
 	addi	r9,r9,0x6f58		/* translate source addr */
 	cmpw	r31,r9			/* (we have to on chrp) */
 	beq	7f
 	rlwinm	r4,r4,0,8,31		/* translate source address */
 	add	r4,r4,r3		/* to region mapped with BATs */
+#endif	
 7:	addis	r9,r26,klimit@ha	/* fetch klimit */
 	lwz	r25,klimit@l(r9)
 	addis	r25,r25,-KERNELBASE@h
@@ -1194,14 +1206,26 @@
 	cmpi	0,r9,4			/* check for 604 */
 	cmpi	1,r9,9			/* or 604e */
 	cmpi	2,r9,10			/* or mach5 */
+	cmpi	3,r9,8			/* check for 750 (G3) */
+	cmpi	4,r9,12			/* or 7400 (G4) */
 	cror	2,2,6
 	cror	2,2,10
 	bne	4f
 	ori	r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
 	bne	2,5f
 	ori	r11,r11,HID0_BTCD
+	b	5f
+4:
+	cror	14,14,18
+	bne	3,6f
+	/* We should add ABE here if we want to use Store Gathering
+	 * and other nifty bridge features
+	 */
+	ori	r11,r11,HID0_SGE|HID0_BHTE|HID0_BTIC /* for g3/g4, enable */
+ 	li	r3,0
+ 	mtspr	ICTC,r3
 5:	mtspr	HID0,r11		/* superscalar exec & br history tbl */
-4:	blr
+6:	blr
 
 /*
  * Load stuff into the MMU.  Intended to be called with
@@ -1388,6 +1412,45 @@
 #endif /* !defined(CONFIG_GEMINI) */
 	blr
 
+#ifndef CONFIG_GEMINI
+flush_tlbs:
+	lis	r20, 0x1000
+1:	addic.	r20, r20, -0x1000
+	tlbie	r20
+	blt	1b
+	sync
+	blr
+
+mmu_off:
+ 	addi	r4, r3, __after_prom_start - _start
+	mfmsr	r3
+	andi.	r0,r3,MSR_DR|MSR_IR		/* MMU enabled? */
+	beq	1f
+	ori	r3,r3,MSR_DR|MSR_IR
+	xori	r3,r3,MSR_DR|MSR_IR
+	mtspr	SRR0,r4
+	mtspr	SRR1,r3
+	sync
+	rfi
+1:	blr
+#endif
+
+#if 0 /* That's useful debug stuff */
+setup_screen_bat:
+	lis	r3, 0x9100
+#ifdef __SMP__
+	ori	r3,r3,0x12
+#else
+	ori	r3,r3,0x2
+#endif
+	mtspr	DBAT1L, r3
+	mtspr	IBAT1L, r3
+	ori	r3,r3,(BL_8M<<2)|0x2	/* set up BAT registers for 604 */
+	mtspr	DBAT1U, r3
+	mtspr	IBAT1U, r3
+	blr
+#endif
+	
 /*
  * We put a few things here that have to be page-aligned.
  * This stuff goes at the beginning of the data segment,
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/head_4xx.S linux/arch/ppc/kernel/head_4xx.S
--- v2.3.42/linux/arch/ppc/kernel/head_4xx.S	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/kernel/head_4xx.S	Wed Feb  9 19:43:47 2000
@@ -78,13 +78,17 @@
 
 	li	r24,0
 
+	## Invalidate all TLB entries
+
+	tlbia
+	
 	## We should still be executing code at physical address 0x0000xxxx
 	## at this point. However, start_here is at virtual address
 	## 0xC000xxxx. So, set up a TLB mapping to cover this once
 	## translation is enabled.
 
 	lis	r3,KERNELBASE@h		# Load the kernel virtual address
-	addis	r3,r3,KERNELBASE@l
+	ori	r3,r3,KERNELBASE@l
 	tophys(r4,r3)			# Load the kernel physical address
 
 	## Save the existing PID and load the kernel PID.
@@ -96,11 +100,7 @@
 	## Configure and load entry into TLB slot 0.
 	
 	clrrwi	r4,r4,10		# Mask off the real page number
-
-	## XXX - Temporarily set the TLB_I bit because of cache issues that
-	##       seem to foul-up the exception handling code.
-
-	ori	r4,r4,(TLB_WR | TLB_EX | TLB_I)	# Set the write and execute bits
+	ori	r4,r4,(TLB_WR | TLB_EX)	# Set the write and execute bits
 	
 	clrrwi	r3,r3,10		# Mask off the effective page number
 	ori	r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
@@ -333,22 +333,12 @@
 #endif
 
 ### 0x1100 - Data TLB Miss Exception
-	
-	START_EXCEPTION(0x1100,	DTLBMiss)
-	STND_EXCEPTION_PROLOG
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	li	r7,STND_EXC
-	li	r20,MSR_KERNEL
-	FINISH_EXCEPTION(UnknownException)
+
+	STND_EXCEPTION(0x1100,	DTLBMiss, 		PPC4xx_dtlb_miss)
 
 ### 0x1200 - Instruction TLB Miss Exception
-	
-	START_EXCEPTION(0x1200,	ITLBMiss)
-	STND_EXCEPTION_PROLOG
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	li	r7,STND_EXC
-	li	r20,MSR_KERNEL
-	FINISH_EXCEPTION(UnknownException)	
+
+	STND_EXCEPTION(0x1200,	ITLBMiss, 		PPC4xx_itlb_miss)
 
 	STND_EXCEPTION(0x1300,	Trap_13,		UnknownException)
 	STND_EXCEPTION(0x1400,	Trap_14,		UnknownException)
@@ -560,8 +550,6 @@
 
 _GLOBAL(set_context)
 	mtspr	SPRN_PID,r3
-	tlbia
-	SYNC
 	blr
 
 ###
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.3.42/linux/arch/ppc/kernel/idle.c	Wed Oct 27 16:34:12 1999
+++ linux/arch/ppc/kernel/idle.c	Wed Feb  9 19:43:47 2000
@@ -154,11 +154,12 @@
 	if ( zero_quicklist )
 	{
 		/* atomically remove this page from the list */
-		asm (	"101:lwarx  %1,0,%2\n"  /* reserve zero_cache */
+		register unsigned long tmp;
+		asm (	"101:lwarx  %1,0,%3\n"  /* reserve zero_cache */
 			"    lwz    %0,0(%1)\n" /* get next -- new zero_cache */
-			"    stwcx. %0,0,%2\n"  /* update zero_cache */
+			"    stwcx. %0,0,%3\n"  /* update zero_cache */
 			"    bne-   101b\n"     /* if lost reservation try again */
-			: "=&r" (zero_quicklist), "=&r" (page)
+			: "=&r" (tmp), "=&r" (page), "+m" (zero_cache)
 			: "r" (&zero_quicklist)
 			: "cc" );
 #ifdef __SMP__
@@ -193,6 +194,7 @@
 {
 	unsigned long pageptr = 0;	/* current page being zero'd */
 	unsigned long bytecount = 0;  
+        register unsigned long tmp;
 	pte_t *pte;
 
 	if ( atomic_read(&zero_cache_sz) >= zero_cache_water[0] )
@@ -249,15 +251,14 @@
 		pte_cache(*pte);
 		flush_tlb_page(find_vma(&init_mm,pageptr),pageptr);
 		/* atomically add this page to the list */
-		asm (	"101:lwarx  %0,0,%1\n"  /* reserve zero_cache */
-			"    stw    %0,0(%2)\n" /* update *pageptr */
+		asm (	"101:lwarx  %0,0,%2\n"  /* reserve zero_cache */
+			"    stw    %0,0(%3)\n" /* update *pageptr */
 #ifdef __SMP__
 			"    sync\n"            /* let store settle */
 #endif			
-			"    mr     %0,%2\n"    /* update zero_cache in reg */
-			"    stwcx. %2,0,%1\n"  /* update zero_cache in mem */
+			"    stwcx. %3,0,%2\n"  /* update zero_cache in mem */
 			"    bne-   101b\n"     /* if lost reservation try again */
-			: "=&r" (zero_quicklist)
+			: "=&r" (tmp), "+m" (zero_quicklist)
 			: "r" (&zero_quicklist), "r" (pageptr)
 			: "cc" );
 		/*
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.3.42/linux/arch/ppc/kernel/irq.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/irq.c	Wed Feb  9 19:43:47 2000
@@ -126,7 +126,7 @@
  */
 int request_8xxirq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
 #elif defined(CONFIG_APUS)
-int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+int request_sysirq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
 #else
 int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
 #endif
@@ -315,7 +315,7 @@
 	}
 	ppc_irq_dispatch_handler( regs, irq );
 	if ( ppc_md.post_irq )
-		ppc_md.post_irq( irq );
+		ppc_md.post_irq( regs, irq );
 
  out:	
         hardirq_exit( cpu );
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h
--- v2.3.42/linux/arch/ppc/kernel/local_irq.h	Wed Dec 29 13:13:12 1999
+++ linux/arch/ppc/kernel/local_irq.h	Wed Feb  9 19:43:47 2000
@@ -4,6 +4,8 @@
 
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
+#include <linux/cache.h>
+#include <linux/spinlock.h>
 #include <linux/irq.h>
 
 void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.3.42/linux/arch/ppc/kernel/misc.S	Fri Jan 28 15:09:07 2000
+++ linux/arch/ppc/kernel/misc.S	Wed Feb  9 19:43:47 2000
@@ -20,13 +20,13 @@
 #include <asm/page.h>
 #include "ppc_asm.h"
 
-#ifndef CONFIG_8xx
-CACHE_LINE_SIZE = 32
-LG_CACHE_LINE_SIZE = 5
-#else
+#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
 CACHE_LINE_SIZE = 16
 LG_CACHE_LINE_SIZE = 4
-#endif /* CONFIG_8xx */
+#else
+CACHE_LINE_SIZE = 32
+LG_CACHE_LINE_SIZE = 5
+#endif /* CONFIG_4xx || CONFIG_8xx */
 
 	.text
 
@@ -590,6 +590,20 @@
 _GLOBAL(_get_PVR)
 	mfspr	r3,PVR
 	blr
+	
+_GLOBAL(_get_HID0)
+	mfspr	r3,HID0
+	blr
+
+_GLOBAL(_get_ICTC)
+	mfspr	r3,ICTC
+	blr
+
+_GLOBAL(_set_ICTC)
+	mtspr	ICTC,r3
+	blr
+
+	
 /*
 	L2CR functions
 	Copyright © 1997-1998 by PowerLogix R & D, Inc.
@@ -656,6 +670,8 @@
 	rlwinm	r4,r4,16,16,31
 	cmplwi	r4,0x0008
 	beq	thisIs750
+	cmplwi	r4,0x000c
+	beq thisIs750
 	li	r3,-1
 	blr
 	
@@ -750,9 +766,11 @@
 	mfspr	r3,PVR
 	rlwinm	r3,r3,16,16,31
 	cmplwi	r3,0x0008
+	beq	1f
+	cmplwi	r3,0x000c
 	li	r3,0
 	bnelr
-	
+1:	
 	/* Return the L2CR contents */
 	mfspr	r3,L2CR
 	blr
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/oak_setup.c linux/arch/ppc/kernel/oak_setup.c
--- v2.3.42/linux/arch/ppc/kernel/oak_setup.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/oak_setup.c	Wed Feb  9 19:43:47 2000
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
  *    Module name: oak_setup.c
  *
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/param.h>
 #include <linux/string.h>
+#include <linux/blk.h>
 
 #include <asm/processor.h>
 #include <asm/board.h>
@@ -30,6 +31,12 @@
 #include "time.h"
 #include "oak_setup.h"
 
+
+
+
+
+
+
 /* Function Prototypes */
 
 extern void abort(void);
@@ -95,32 +102,32 @@
 
 	/* Initialize machine-dependency vectors */
 
-	ppc_md.setup_arch	 = oak_setup_arch;
-	ppc_md.setup_residual	 = oak_setup_residual;
-	ppc_md.get_cpuinfo	 = NULL;
-	ppc_md.irq_cannonicalize = NULL;
-	ppc_md.init_IRQ		 = oak_init_IRQ;
-	ppc_md.get_irq		 = oak_get_irq;
-	ppc_md.init		 = NULL;
-
-	ppc_md.restart		 = oak_restart;
-	ppc_md.power_off	 = oak_power_off;
-	ppc_md.halt		 = oak_halt;
-
-	ppc_md.time_init	 = oak_time_init;
-	ppc_md.set_rtc_time	 = oak_set_rtc_time;
-	ppc_md.get_rtc_time	 = oak_get_rtc_time;
-	ppc_md.calibrate_decr	 = oak_calibrate_decr;
-
-	ppc_md.kbd_setkeycode    = NULL;
-	ppc_md.kbd_getkeycode    = NULL;
-	ppc_md.kbd_translate     = NULL;
-	ppc_md.kbd_unexpected_up = NULL;
-	ppc_md.kbd_leds          = NULL;
-	ppc_md.kbd_init_hw       = NULL;
+	ppc_md.setup_arch	 	= oak_setup_arch;
+	ppc_md.setup_residual	 	= oak_setup_residual;
+	ppc_md.get_cpuinfo	 	= NULL;
+	ppc_md.irq_cannonicalize 	= NULL;
+	ppc_md.init_IRQ		 	= oak_init_IRQ;
+	ppc_md.get_irq		 	= oak_get_irq;
+	ppc_md.init		 	= NULL;
+
+	ppc_md.restart		 	= oak_restart;
+	ppc_md.power_off	 	= oak_power_off;
+	ppc_md.halt		 	= oak_halt;
+
+	ppc_md.time_init	 	= oak_time_init;
+	ppc_md.set_rtc_time	 	= oak_set_rtc_time;
+	ppc_md.get_rtc_time	 	= oak_get_rtc_time;
+	ppc_md.calibrate_decr	 	= oak_calibrate_decr;
+
+	ppc_md.kbd_setkeycode    	= NULL;
+	ppc_md.kbd_getkeycode    	= NULL;
+	ppc_md.kbd_translate     	= NULL;
+	ppc_md.kbd_unexpected_up 	= NULL;
+	ppc_md.kbd_leds          	= NULL;
+	ppc_md.kbd_init_hw       	= NULL;
 
 #if defined(CONFIG_MAGIC_SYSRQ)
-	ppc_md.kbd_sysrq_xlate	 = NULL;
+	ppc_md.ppc_kbd_sysrq_xlate	= NULL;
 #endif
 
 	return;
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/oak_setup.h linux/arch/ppc/kernel/oak_setup.h
--- v2.3.42/linux/arch/ppc/kernel/oak_setup.h	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/oak_setup.h	Wed Feb  9 19:43:47 2000
@@ -1,14 +1,14 @@
 /*
  *
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
- *    Module name: oak_setup.c
+ *    Module name: oak_setup.h
  *
  *    Description:
  *      Architecture- / platform-specific boot-time initialization code for
  *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
  *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- *      <dmalek@jlc.net>.
+ *      <dan@netx4.com>.
  *
  */
 
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.3.42/linux/arch/ppc/kernel/open_pic.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/open_pic.c	Thu Feb 10 12:37:22 2000
@@ -8,6 +8,7 @@
  *  for more details.
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -17,17 +18,30 @@
 #include <asm/signal.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/prom.h>
 #include "local_irq.h"
 
 volatile struct OpenPIC *OpenPIC = NULL;
 u_int OpenPIC_NumInitSenses __initdata = 0;
 u_char *OpenPIC_InitSenses __initdata = NULL;
+int open_pic_irq_offset;
+extern int use_of_interrupt_tree;
 
 void chrp_mask_irq(unsigned int);
 void chrp_unmask_irq(unsigned int);
+void find_ISUs(void);
 
 static u_int NumProcessors;
 static u_int NumSources;
+OpenPIC_Source *ISU;
+/*
+ * We should use this if we have > 1 ISU.
+ * We can just point each entry to the
+ * appropriate source regs but it wastes a lot of space
+ * so until we have >1 ISU I'll leave it unimplemented.
+ * -- Cort
+OpenPIC_Source ISU[128];
+*/
 
 struct hw_interrupt_type open_pic = {
 	" OpenPIC  ",
@@ -38,7 +52,6 @@
 	0,
 	0
 };
-int open_pic_irq_offset;
 
 /*
  *  Accesses to the current processor's registers
@@ -96,7 +109,7 @@
 #endif /* __SMP__ */
 
 #ifdef __i386__
-static inline u_int ld_le32(volatile u_int *addr)
+static inline u_int in_le32(volatile u_int *addr)
 {
 	return *addr;
 }
@@ -111,7 +124,7 @@
 {
 	u_int val;
 
-	val = ld_le32(addr);
+	val = in_le32(addr);
 	return val;
 }
 
@@ -148,6 +161,9 @@
 {
 	openpic_setfield(addr, OPENPIC_MASK);
 	/* wait until it's not in use */
+	/* BenH: Is this code really enough ? I would rather check the result
+	 *       and eventually retry ...
+	 */
 	while (openpic_read(addr) & OPENPIC_ACTIVITY);
 	openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
 }
@@ -182,16 +198,18 @@
 			 OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
 	NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
 		      OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
-
-	printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
-	       NumProcessors, NumSources, OpenPIC);
-	timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
-	printk("OpenPIC timer frequency is ");
-	if (timerfreq)
-		printk("%d Hz\n", timerfreq);
-	else
-		printk("not set\n");
-
+	if ( _machine != _MACH_Pmac )
+	{
+		printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
+		       NumProcessors, NumSources, OpenPIC);
+		timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
+		printk("OpenPIC timer frequency is ");
+		if (timerfreq)
+			printk("%d MHz\n", timerfreq>>20);
+		else
+			printk("not set\n");
+	}
+	
 	if ( main_pic )
 	{
 		/* Initialize timer interrupts */
@@ -209,24 +227,59 @@
 			/* Disabled, Priority 8 */
 			openpic_initipi(i, 8, OPENPIC_VEC_IPI+i);
 		}
-	    
-		/* Initialize external interrupts */
-		if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc);
-		/* SIOint (8259 cascade) is special */
-		openpic_initirq(0, 8, open_pic_irq_offset, 1, 1);
-		openpic_mapirq(0, 1<<0);
-		for (i = 1; i < NumSources; i++) {
-			/* Enabled, Priority 8 */
-			openpic_initirq(i, 8, open_pic_irq_offset+i, 0,
-					i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
-			/* Processor 0 */
-			openpic_mapirq(i, 1<<0);
+		find_ISUs();
+		if ( _machine != _MACH_Pmac )
+		{
+			/* Initialize external interrupts */
+			if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc);
+			/* SIOint (8259 cascade) is special */
+			openpic_initirq(0, 8, open_pic_irq_offset, 1, 1);
+			openpic_mapirq(0, 1<<0);
+			for (i = 1; i < NumSources; i++) {
+				/* Enabled, Priority 8 */
+				openpic_initirq(i, 8, open_pic_irq_offset+i, 0,
+						i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
+				/* Processor 0 */
+				openpic_mapirq(i, 1<<0);
+			}
 		}
-	    
+		else
+		{
+			/* Prevent any interrupt from occuring during initialisation.
+			 * Hum... I believe this is not necessary, Apple does that in
+			 * Darwin's PowerExpress code.
+			 */
+			openpic_set_priority(0, 0xf);
+			
+			/* First disable all interrupts and map them to CPU 0 */
+			for (i = 0; i < NumSources; i++) {
+				openpic_disable_irq(i);
+				openpic_mapirq(i, 1<<0);
+			}
+			
+			/* If we use the device tree, then lookup all interrupts and
+			 * initialize them according to sense infos found in the tree
+			 */
+			if (use_of_interrupt_tree) {
+				struct device_node* np = find_all_nodes();
+			    	while(np) {
+					int j, pri;
+					pri = strcmp(np->name, "programmer-switch") ? 2 : 7;
+					for (j=0;j<np->n_intrs;j++)
+						openpic_initirq(	np->intrs[j].line,
+									pri,
+									np->intrs[j].line,
+									np->intrs[j].sense,
+									np->intrs[j].sense);
+					np = np->next;
+				}
+			}
+		}
+		
 		/* Initialize the spurious interrupt */
 		if ( ppc_md.progress ) ppc_md.progress("openpic spurious",0x3bd);
 		openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-		if ( _machine != _MACH_gemini )
+		if ( !(_machine && (_MACH_gemini|_MACH_Pmac)) )
 		{
 			if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
 					"82c59 cascade", NULL))
@@ -238,6 +291,20 @@
 	if ( ppc_md.progress ) ppc_md.progress("openpic exit",0x222);
 }
 
+void find_ISUs(void)
+{
+#ifdef CONFIG_PPC64
+	/* hardcode this for now since the IBM 260 is the only thing with
+	 * a distributed openpic right now.  -- Cort
+	 */
+	ISU = (OpenPIC_Source *)0xfeff7c00;
+	NumSources = 0x10;
+#else
+	/* for non-distributed OpenPIC implementations it's in the IDU -- Cort */
+	ISU = OpenPIC->Source;
+#endif
+}
+
 void openpic_reset(void)
 {
 	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
@@ -279,6 +346,8 @@
 {
 	check_arg_cpu(cpu);
 	openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
+	/* Handle PCI write posting */
+	(void)openpic_read(&OpenPIC->THIS_CPU.EOI);
 }
 
 
@@ -379,7 +448,7 @@
 #if 0	
  	/* let the openpic know we want intrs */
  	for ( i = 0; i < NumSources ; i++ )
- 		openpic_mapirq(i, openpic_read(&OpenPIC->Source[i].Destination)
+ 		openpic_mapirq(i, openpic_read(ISU[i].Destination)
  			       | (1<<smp_processor_id()) );
 #endif	
  	openpic_set_priority(smp_processor_id(), 0);
@@ -417,13 +486,23 @@
 void openpic_enable_irq(u_int irq)
 {
 	check_arg_irq(irq);
-	openpic_clearfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
+	openpic_clearfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
+	/* make sure mask gets to controller before we return to user */
+	do {
+		mb(); /* sync is probably useless here */
+	} while(openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
+			OPENPIC_MASK));
 }
 
 void openpic_disable_irq(u_int irq)
 {
 	check_arg_irq(irq);
-	openpic_setfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
+	openpic_setfield(&ISU[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
+	/* make sure mask gets to controller before we return to user */
+	do {
+		mb();  /* sync is probably useless here */
+	} while(!openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
+    			OPENPIC_MASK));
 }
 
 /*
@@ -440,12 +519,13 @@
 	check_arg_irq(irq);
 	check_arg_pri(pri);
 	check_arg_vec(vec);
-	openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
+	openpic_safe_writefield(&ISU[irq].Vector_Priority,
 				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
-				OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
+				OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
 				(pri << OPENPIC_PRIORITY_SHIFT) | vec |
-				(pol ? OPENPIC_SENSE_POLARITY : 0) |
-				(sense ? OPENPIC_SENSE_LEVEL : 0));
+				(pol ? OPENPIC_POLARITY_POSITIVE :
+			    		OPENPIC_POLARITY_NEGATIVE) |
+				(sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
 }
 
 /*
@@ -454,7 +534,7 @@
 void openpic_mapirq(u_int irq, u_int cpumask)
 {
 	check_arg_irq(irq);
-	openpic_write(&OpenPIC->Source[irq].Destination, cpumask);
+	openpic_write(&ISU[irq].Destination, cpumask);
 }
 
 /*
@@ -465,7 +545,7 @@
 void openpic_set_sense(u_int irq, int sense)
 {
 	check_arg_irq(irq);
-	openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
+	openpic_safe_writefield(&ISU[irq].Vector_Priority,
 				OPENPIC_SENSE_LEVEL,
 				(sense ? OPENPIC_SENSE_LEVEL : 0));
 }
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/pci-dma.c linux/arch/ppc/kernel/pci-dma.c
--- v2.3.42/linux/arch/ppc/kernel/pci-dma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/pci-dma.c	Wed Feb  9 19:43:47 2000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2000   Ani Joshi <ajoshi@unixbox.com>
+ *
+ *
+ * Dynamic DMA mapping support.
+ *
+ * swiped from i386
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+/* Pure 2^n version of get_order */
+extern __inline__ int __get_order(unsigned long size)
+{
+	int order;
+
+	size = (size-1) >> (PAGE_SHIFT-1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t *dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+	if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
+		gfp |= GFP_DMA;
+	ret = (void *)__get_free_pages(gfp, __get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	return ret;
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages((unsigned long)vaddr, __get_order(size));
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.3.42/linux/arch/ppc/kernel/pci.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/pci.c	Wed Feb  9 19:43:47 2000
@@ -71,9 +71,9 @@
 {
 	printk("PCI: Probing PCI hardware\n");
 	pci_scan_bus(0, &generic_pci_ops, NULL);
-	pcibios_claim_resources(&pci_root_buses);
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
+	pcibios_claim_resources(&pci_root_buses);
 }
 
 void __init
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/pmac_nvram.c linux/arch/ppc/kernel/pmac_nvram.c
--- v2.3.42/linux/arch/ppc/kernel/pmac_nvram.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/pmac_nvram.c	Wed Feb  9 19:43:47 2000
@@ -6,6 +6,7 @@
 #include <linux/stddef.h>
 #include <linux/nvram.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <asm/init.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -20,23 +21,37 @@
 static int nvram_naddrs;
 static volatile unsigned char *nvram_addr;
 static volatile unsigned char *nvram_data;
-static int nvram_mult;
-
-#define NVRAM_SIZE	0x2000	/* 8kB of non-volatile RAM */
-
+static int nvram_mult, is_core_99;
+static char* nvram_image;
+ 
+#define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
+ 
 __init
 void pmac_nvram_init(void)
 {
 	struct device_node *dp;
 
+	nvram_naddrs = 0;
+
 	dp = find_devices("nvram");
 	if (dp == NULL) {
 		printk(KERN_ERR "Can't find NVRAM device\n");
-		nvram_naddrs = 0;
 		return;
 	}
 	nvram_naddrs = dp->n_addrs;
-	if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+	is_core_99 = device_is_compatible(dp, "nvram,flash");
+	if (is_core_99)
+	{
+		int i;
+		if (nvram_naddrs < 1)
+			return;
+		nvram_image = kmalloc(dp->addrs[0].size, GFP_KERNEL);
+		if (!nvram_image)
+			return;
+		nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
+		for (i=0; i<dp->addrs[0].size; i++)
+			nvram_image[i] = in_8(nvram_data + i);
+	} else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
 		nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
 		nvram_mult = 1;
 	} else if (nvram_naddrs == 1) {
@@ -69,6 +84,8 @@
 		return req.reply[1];
 #endif
 	case 1:
+		if (is_core_99)
+			return nvram_image[addr];
 		return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
 	case 2:
 		*nvram_addr = addr >> 5;
@@ -94,6 +111,10 @@
 		break;
 #endif
 	case 1:
+		if (is_core_99) {
+			nvram_image[addr] = val;
+			break;
+		}
 		nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val;
 		break;
 	case 2:
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.3.42/linux/arch/ppc/kernel/pmac_pci.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/ppc/kernel/pmac_pci.c	Wed Feb  9 19:43:47 2000
@@ -30,6 +30,16 @@
 struct bridge_data **bridges, *bridge_list;
 static int max_bus;
 
+struct uninorth_data {
+	struct device_node*	node;
+	volatile unsigned int*	cfg_addr;
+	volatile unsigned int*	cfg_data;
+};
+
+static struct uninorth_data uninorth_bridges[3];
+static int uninorth_count;
+static int uninorth_default = -1;
+
 static void add_bridges(struct device_node *dev);
 
 /*
@@ -73,6 +83,159 @@
 	return 0;
 }
 
+/* This function only works for bus 0, uni-N uses a different mecanism for
+ * other busses (see below)
+ */
+#define UNI_N_CFA0(devfn, off)	\
+	((1 << (unsigned long)PCI_SLOT(dev_fn)) \
+	| (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
+	| (((unsigned long)(off)) & 0xFCUL))
+
+/* This one is for type 1 config accesses */
+#define UNI_N_CFA1(bus, devfn, off)	\
+	((((unsigned long)(bus)) << 16) \
+	|(((unsigned long)(devfn)) << 8) \
+	|(((unsigned long)(off)) & 0xFCUL) \
+	|1UL)
+	
+/* We should really use RTAS here, unfortunately, it's not available with BootX.
+ * (one more reason for writing a beautiful OF booter). I'll do the RTAS stuff
+ * later, once I have something that works enough with BootX.
+ */
+__pmac static
+unsigned int
+uni_north_access_data(unsigned char bus, unsigned char dev_fn,
+				unsigned char offset)
+{
+	struct device_node *node, *bridge_node;
+	int bridge = uninorth_default;
+	unsigned int caddr;
+
+	if (bus == 0) {
+		if (PCI_SLOT(dev_fn) < 11) {
+			return 0;
+		}
+		/* We look for the OF device corresponding to this bus/devfn pair. If we
+		 * don't find it, we default to the external PCI */
+		bridge_node = NULL;
+		node = find_pci_device_OFnode(bus, dev_fn & 0xf8);
+		if (node) {
+                    /* note: we don't stop on the first occurence since we need to go
+                     * up to the root bridge */
+		    do {
+			if (!strcmp(node->type, "pci"))
+				bridge_node = node;
+			node=node->parent;
+		    } while (node);
+		}
+		if (bridge_node) {
+		    int i;
+		    for (i=0;i<uninorth_count;i++)
+			if (uninorth_bridges[i].node == bridge_node) {
+			    bridge = i;
+			    break;
+			}
+		}
+		caddr = UNI_N_CFA0(dev_fn, offset);
+	} else
+		caddr = UNI_N_CFA1(bus, dev_fn, offset);
+
+	if (bridge == -1) {
+		printk(KERN_WARNING "pmac_pci: no default bridge !\n");
+		return 0;
+	}
+		
+	/* Uninorth will return garbage if we don't read back the value ! */
+	out_le32(uninorth_bridges[bridge].cfg_addr, caddr);
+	(void)in_le32(uninorth_bridges[bridge].cfg_addr);
+	/* Yes, offset is & 7, not & 3 ! */
+	return (unsigned int)(uninorth_bridges[bridge].cfg_data) + (offset & 0x07);
+}
+
+__pmac
+int uni_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+				  unsigned char offset, unsigned char *val)
+{
+	unsigned int addr;
+	
+	*val = 0xff;
+	addr = uni_north_access_data(bus, dev_fn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	*val = in_8((volatile unsigned char*)addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+__pmac
+int uni_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+				  unsigned char offset, unsigned short *val)
+{
+	unsigned int addr;
+	
+	*val = 0xffff;
+	addr = uni_north_access_data(bus, dev_fn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	*val = in_le16((volatile unsigned short*)addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+__pmac
+int uni_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+				   unsigned char offset, unsigned int *val)
+{
+	unsigned int addr;
+	
+	*val = 0xffff;
+	addr = uni_north_access_data(bus, dev_fn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	*val = in_le32((volatile unsigned int*)addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+__pmac
+int uni_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+				   unsigned char offset, unsigned char val)
+{
+	unsigned int addr;
+	
+	addr = uni_north_access_data(bus, dev_fn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	out_8((volatile unsigned char *)addr, val);
+	(void)in_8((volatile unsigned char *)addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+__pmac
+int uni_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+				   unsigned char offset, unsigned short val)
+{
+	unsigned int addr;
+	
+	addr = uni_north_access_data(bus, dev_fn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	out_le16((volatile unsigned short *)addr, val);
+	(void)in_le16((volatile unsigned short *)addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+__pmac
+int uni_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+				    unsigned char offset, unsigned int val)
+{
+	unsigned int addr;
+	
+	addr = uni_north_access_data(bus, dev_fn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	out_le32((volatile unsigned int *)addr, val);
+	(void)in_le32((volatile unsigned int *)addr);
+	return PCIBIOS_SUCCESSFUL;
+}
+
 __pmac
 int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
 				  unsigned char offset, unsigned char *val)
@@ -362,6 +525,21 @@
 	       bp->io_base);
 }
 
+#define GRACKLE_STG_ENABLE 0x00000040
+
+/* N.B. this is called before bridges is initialized, so we can't
+   use grackle_pcibios_{read,write}_config_dword. */
+static inline void grackle_set_stg(struct bridge_data *bp, int enable)
+{
+	unsigned int val;
+
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	val = in_le32((volatile unsigned int *)bp->cfg_data);
+	val = enable? (val | GRACKLE_STG_ENABLE): (val & ~GRACKLE_STG_ENABLE);
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	out_le32((volatile unsigned int *)bp->cfg_data, val);
+}
+
 void __init pmac_find_bridges(void)
 {
 	int bus;
@@ -411,20 +589,47 @@
 			printk(KERN_INFO "PCI buses %d..%d", bus_range[0],
 			       bus_range[1]);
 		printk(" controlled by %s at %x\n", dev->name, addr->address);
+		if (device_is_compatible(dev, "uni-north")) {
+			int i = uninorth_count++;
+			uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+			uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+			uninorth_bridges[i].node = dev;
+			/* XXX This is the bridge with the PCI expansion bus. This is also the
+			 * address of the bus that will receive type 1 config accesses and io
+			 * accesses. Appears to be correct for iMac DV and G4 Sawtooth too.
+			 * That means that we cannot do io cycles on the AGP bus nor the internal
+			 * ethernet/fw bus. Fortunately, they appear not to be needed on iMac DV
+			 * and G4 neither.
+			 */
+			if (addr->address == 0xf2000000)
+				uninorth_default = i;
+			else
+				continue;
+		}
+		
 		bp = (struct bridge_data *) alloc_bootmem(sizeof(*bp));
-		if (strcmp(dev->name, "pci") != 0) {
-			bp->cfg_addr = (volatile unsigned int *)
-				ioremap(addr->address + 0x800000, 0x1000);
-			bp->cfg_data = (volatile unsigned char *)
-				ioremap(addr->address + 0xc00000, 0x1000);
-			bp->io_base = (void *) ioremap(addr->address, 0x10000);
-		} else {
-			/* XXX */
+		if (device_is_compatible(dev, "uni-north")) {
+			bp->cfg_addr = 0;
+			bp->cfg_data = 0;
+			/* is 0x10000 enough for io space ? */
+			bp->io_base = (void *)ioremap(addr->address, 0x10000);
+		} else if (strcmp(dev->name, "pci") == 0) {
+			/* XXX assume this is a mpc106 (grackle) */
 			bp->cfg_addr = (volatile unsigned int *)
 				ioremap(0xfec00000, 0x1000);
 			bp->cfg_data = (volatile unsigned char *)
 				ioremap(0xfee00000, 0x1000);
                         bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
+#if 0 /* Disabled for now, HW problems */
+			grackle_set_stg(bp, 1);
+#endif
+		} else {
+			/* a `bandit' or `chaos' bridge */
+			bp->cfg_addr = (volatile unsigned int *)
+				ioremap(addr->address + 0x800000, 0x1000);
+			bp->cfg_data = (volatile unsigned char *)
+				ioremap(addr->address + 0xc00000, 0x1000);
+			bp->io_base = (void *) ioremap(addr->address, 0x10000);
 		}
 		if (isa_io_base == 0)
 			isa_io_base = (unsigned long) bp->io_base;
@@ -453,7 +658,7 @@
 
 	for (; node != 0;node = node->sibling) {
 		class_code = (unsigned int *) get_property(node, "class-code", 0);
-		if((*class_code >> 8) == PCI_CLASS_BRIDGE_PCI)
+		if(class_code && (*class_code >> 8) == PCI_CLASS_BRIDGE_PCI)
 			fix_intr(node->child, dev);
 		reg = (unsigned int *) get_property(node, "reg", 0);
 		if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)
@@ -490,20 +695,38 @@
 		if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
 		    !pin)
 			continue; /* No interrupt generated -> no fixup */
-                fix_intr(bp->node->child, dev);
+		/* We iterate all instances of uninorth for now */	
+		if (uninorth_count && dev->bus->number == 0) {
+			int i;
+			for (i=0;i<uninorth_count;i++)
+				fix_intr(uninorth_bridges[i].node->child, dev);
+		} else
+                	fix_intr(bp->node->child, dev);
 	}
 }
 
 void __init
 pmac_setup_pci_ptrs(void)
 {
-	if (find_devices("pci") != 0) {
-		/* looks like a G3 powermac */
-		set_config_access_method(grackle);
-	} else {
+	struct device_node* np;
+
+	np = find_devices("pci");
+	if (np != 0)
+	{
+		if (device_is_compatible(np, "uni-north"))
+		{
+			/* looks like an Core99 powermac */
+			set_config_access_method(uni);
+		} else
+		{
+			/* looks like a G3 powermac */
+			set_config_access_method(grackle);
+		}
+	} else
+	{
 		set_config_access_method(pmac);
 	}
-
+	
 	ppc_md.pcibios_fixup = pmac_pcibios_fixup;
 }
 
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.3.42/linux/arch/ppc/kernel/pmac_pic.c	Wed Dec 29 13:13:12 1999
+++ linux/arch/ppc/kernel/pmac_pic.c	Wed Feb  9 19:43:47 2000
@@ -3,6 +3,8 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
+#include <linux/pci.h>
+#include <linux/openpic.h>
 
 #include <asm/init.h>
 #include <asm/io.h>
@@ -27,12 +29,38 @@
 
 static int max_irqs;
 static int max_real_irqs;
+static int has_openpic = 0;
 
 #define MAXCOUNT 10000000
 
 #define GATWICK_IRQ_POOL_SIZE        10
 static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
 
+extern int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+                                      unsigned char offset, unsigned short *val);
+extern int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+                                      unsigned char offset, unsigned short val);
+
+static void pmac_openpic_mask_irq(unsigned int irq_nr)
+{
+	openpic_disable_irq(irq_nr);
+}
+
+static void pmac_openpic_unmask_irq(unsigned int irq_nr)
+{
+	openpic_enable_irq(irq_nr);
+}
+
+struct hw_interrupt_type pmac_open_pic = {
+	" OpenPIC  ",
+	NULL,
+	NULL,
+	pmac_openpic_unmask_irq,
+	pmac_openpic_mask_irq,
+	pmac_openpic_mask_irq,
+	0
+};
+
 static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
 {
         unsigned long bit = 1UL << (irq_nr & 0x1f);
@@ -141,74 +169,6 @@
 		ppc_irq_dispatch_handler( regs, irq );
 }
 
-#if 0
-void
-pmac_do_IRQ(struct pt_regs *regs,
-	    int            cpu,
-            int            isfake)
-{
-	int irq;
-	unsigned long bits = 0;
-
-#ifdef __SMP__
-        /* IPI's are a hack on the powersurge -- Cort */
-        if ( cpu != 0 )
-        {
-#ifdef CONFIG_XMON
-		static int xmon_2nd;
-		if (xmon_2nd)
-			xmon(regs);
-#endif
-		pmac_smp_message_recv();
-		return -1;
-        }
-
-        {
-                unsigned int loops = MAXCOUNT;
-                while (test_bit(0, &global_irq_lock)) {
-                        if (smp_processor_id() == global_irq_holder) {
-                                printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
-                                xmon(0);
-#endif
-                                break;
-                        }
-                        if (loops-- == 0) {
-                                printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
-                                xmon(0);
-#endif
-                        }
-                }
-        }
-#endif /* __SMP__ */
-
-        for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
-                int i = irq >> 5;
-                bits = ld_le32(&pmac_irq_hw[i]->flag)
-                        | ppc_lost_interrupts[i];
-                if (bits == 0)
-                        continue;
-                irq -= cntlzw(bits);
-                break;
-        }
-
-        if (irq < 0)
-        {
-                printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
-                       irq, regs->nip);
-                ppc_spurious_interrupts++;
-        }
-        else
-        {
-                ppc_irq_dispatch_handler( regs, irq );
-        }
-#ifdef CONFIG_SMP	
-out:
-#endif /* CONFIG_SMP */
-}
-#endif
-
 int
 pmac_get_irq(struct pt_regs *regs)
 {
@@ -248,15 +208,30 @@
         }
 #endif /* __SMP__ */
 
-        for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
-                int i = irq >> 5;
-                bits = ld_le32(&pmac_irq_hw[i]->flag)
-                        | ppc_lost_interrupts[i];
-                if (bits == 0)
-                        continue;
-                irq -= cntlzw(bits);
-                break;
-        }
+	/* Yeah, I know, this could be a separate do_IRQ function */
+	if (has_openpic)
+	{
+		irq = openpic_irq(smp_processor_id());
+		if (irq == OPENPIC_VEC_SPURIOUS)
+			/* We get those when doing polled ADB requests,
+			 * using -2 is a temp hack to disable the printk
+			 */
+			irq = -2; /*-1; */
+		else
+			openpic_eoi(smp_processor_id());
+	}
+	else
+	{
+		for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+			int i = irq >> 5;
+			bits = ld_le32(&pmac_irq_hw[i]->flag)
+				| ppc_lost_interrupts[i];
+			if (bits == 0)
+				continue;
+			irq -= cntlzw(bits);
+			break;
+		}
+	}
 
 	return irq;
 }
@@ -339,6 +314,51 @@
 	}
 }
 
+/*
+ * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
+ * card which includes an ohare chip that acts as a second interrupt
+ * controller.  If we find this second ohare, set it up and fix the
+ * interrupt value in the device tree for the ethernet chip.
+ */
+static void __init enable_second_ohare(void)
+{
+	unsigned char bus, devfn;
+	unsigned short cmd;
+        unsigned long addr;
+	int second_irq;
+	struct device_node *irqctrler = find_devices("pci106b,7");
+	struct device_node *ether;
+
+	if (irqctrler == NULL || irqctrler->n_addrs <= 0)
+		return;
+	addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
+	pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
+	max_irqs = 64;
+	if (pci_device_loc(irqctrler, &bus, &devfn) == 0) {
+		pmac_pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
+		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+		cmd &= ~PCI_COMMAND_IO;
+		pmac_pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+	}
+
+	second_irq = irqctrler->intrs[0].line;
+	printk(KERN_INFO "irq: secondary controller on irq %d\n", second_irq);
+	request_irq(second_irq, gatwick_action, SA_INTERRUPT,
+		    "interrupt cascade", 0 );
+
+	/* Fix interrupt for the modem/ethernet combo controller. The number
+	   in the device tree (27) is bogus (correct for the ethernet-only
+	   board but not the combo ethernet/modem board).
+	   The real interrupt is 28 on the second controller -> 28+32 = 60.
+	*/
+	ether = find_devices("pci1011,14");
+	if (ether && ether->n_intrs > 0) {
+		ether->intrs[0].line = 60;
+		printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
+		       ether->intrs[0].line);
+	}
+}
+
 void __init
 pmac_pic_init(void)
 {
@@ -347,9 +367,44 @@
         unsigned long addr;
 	int second_irq = -999;
 
+	/* We first try to detect Apple's new Core99 chipset, since mac-io
+	 * is quite different on those machines and contains an IBM MPIC2.
+	 */
+	irqctrler = find_type_devices("open-pic");
+	if (irqctrler != NULL)
+	{
+		printk("PowerMac using OpenPIC irq controller\n");
+		if (irqctrler->n_addrs > 0)
+		{
+#ifdef CONFIG_XMON
+			struct device_node* pswitch;
+#endif /* CONFIG_XMON */	
+			OpenPIC = (volatile struct OpenPIC *)
+				ioremap(irqctrler->addrs[0].address,
+					irqctrler->addrs[0].size);
+			for ( i = 0 ; i < NR_IRQS ; i++ )
+				irq_desc[i].handler = &pmac_open_pic;
+			openpic_init(1);
+			has_openpic = 1;
+#ifdef CONFIG_XMON
+			pswitch = find_devices("programmer-switch");
+			if (pswitch && pswitch->n_intrs)
+				request_irq(pswitch->intrs[0].line, xmon_irq, 0,
+					    "NMI - XMON", 0);
+#endif	/* CONFIG_XMON */
+			return;
+		}
+		irqctrler = NULL;
+	}
 
-	/* G3 powermacs have 64 interrupts, G3 Series PowerBook have 128, 
-	   others have 32 */
+	/*
+	 * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
+	 * 1998 G3 Series PowerBooks have 128, 
+	 * other powermacs have 32.
+	 * The combo ethernet/modem card for the Powerstar powerbooks
+	 * (2400/3400/3500, ohare based) has a second ohare chip
+	 * effectively making a total of 64.
+	 */
 	max_irqs = max_real_irqs = 32;
 	irqctrler = find_devices("mac-io");
 	if (irqctrler)
@@ -389,6 +444,12 @@
 		pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
 	}
 
+	/* PowerBooks 3400 and 3500 can have a second controller in a second
+	   ohare chip, on the combo ethernet/modem card */
+	if (machine_is_compatible("AAPL,3400/2400")
+	     || machine_is_compatible("AAPL,3500"))
+		enable_second_ohare();
+
 	/* disable all interrupts in all controllers */
 	for (i = 0; i * 32 < max_irqs; ++i)
 		out_le32(&pmac_irq_hw[i]->enable, 0);
@@ -435,7 +496,12 @@
 	out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
 	if (max_real_irqs > 32)
 		out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
-	mb();
+	(void)in_le32(&pmac_irq_hw[0]->flag);
+        do {
+                /* make sure mask gets to controller before we
+                   return to user */
+                mb();
+        } while(in_le32(&pmac_irq_hw[0]->enable) != ppc_cached_irq_mask[0]);
 }
 
 void
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.3.42/linux/arch/ppc/kernel/pmac_setup.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/ppc/kernel/pmac_setup.c	Wed Feb  9 19:43:47 2000
@@ -104,6 +104,10 @@
 extern void zs_kgdb_hook(int tty_num);
 static void ohare_init(void);
 static void init_p2pbridge(void);
+static void init_uninorth(void);
+#ifdef CONFIG_BOOTX_TEXT
+void pmac_progress(char *s, unsigned short hex);
+#endif
 
 __pmac
 int
@@ -232,8 +236,10 @@
 		if (fp != 0) {
 			switch (_get_PVR() >> 16) {
 			case 4:		/* 604 */
+			case 8:		/* G3 */
 			case 9:		/* 604e */
 			case 10:	/* mach V (604ev5) */
+			case 12:	/* G4 */
 			case 20:	/* 620 */
 				loops_per_sec = *fp;
 				break;
@@ -252,9 +258,10 @@
 
 	pmac_find_bridges();
 	init_p2pbridge();
-
+	init_uninorth();
+	
 	/* Checks "l2cr-value" property in the registry */
-	if ( (_get_PVR() >> 16) == 8) {
+	if ( (_get_PVR() >> 16) == 8 || (_get_PVR() >> 16) == 12 ) {
 		struct device_node *np = find_devices("cpus");		
 		if (np == 0)
 			np = find_type_devices("cpu");		
@@ -346,6 +353,33 @@
 	}
 }
 
+static void __init
+init_uninorth(void)
+{
+	/* 
+	 * Turns on the gmac clock so that it responds to PCI cycles
+	 * later, the driver may want to turn it off again to save
+	 * power when interface is down
+	 */
+	struct device_node* uni_n = find_devices("uni-n");
+	struct device_node* gmac = find_devices("ethernet");
+	unsigned long* addr;
+	
+	if (!uni_n || uni_n->n_addrs < 1)
+		return;
+	addr = ioremap(uni_n->addrs[0].address, 0x300);
+
+	while(gmac) {
+		if (device_is_compatible(gmac, "gmac"))
+			break;
+		gmac = gmac->next;
+	}
+	if (gmac) {
+		*(addr + 8) |= 2;
+		eieio();
+	}
+}
+
 extern char *bootpath;
 extern char *bootdevice;
 void *boot_host;
@@ -401,14 +435,11 @@
 #endif
 
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-extern int pmac_ide_count;
-extern struct device_node *pmac_ide_node[];
-static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 };
 
 kdev_t __init find_ide_boot(void)
 {
 	char *p;
-	int i, n;
+	int n;
 
 	if (bootdevice == NULL)
 		return 0;
@@ -417,18 +448,7 @@
 		return 0;
 	n = p - bootdevice;
 
-	/*
-	 * Look through the list of IDE interfaces for this one.
-	 */
-	for (i = 0; i < pmac_ide_count; ++i) {
-		char *name = pmac_ide_node[i]->full_name;
-		if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
-			/* XXX should cope with the 2nd drive as well... */
-			return MKDEV(ide_majors[i], 0);
-		}
-	}
-
-	return 0;
+	return pmac_find_ide_boot(bootdevice, n);
 }
 #endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
 
@@ -464,10 +484,10 @@
 		find_boot_device();
 		found_boot = 1;
 	}
-	if (dev == boot_dev) {
+	if (boot_dev == 0 || dev == boot_dev) {
 		ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + part);
 		boot_dev = NODEV;
-		printk(" (root)");
+		printk(" (root on %d)", part);
 	}
 }
 
@@ -550,11 +570,15 @@
         return 0;
 }
 
+#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+extern ide_ioreg_t pmac_ide_get_base(int index);
+#endif
+
 ide_ioreg_t
 pmac_ide_default_io_base(int index)
 {
 #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-        return pmac_ide_regbase[index];
+        return pmac_ide_get_base(index);
 #else
 	return 0;
 #endif
@@ -660,5 +684,22 @@
         ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
 
         ppc_ide_md.io_base = _IO_BASE;	/* actually too early for this :-( */
-#endif		
+#endif
+#ifdef CONFIG_BOOTX_TEXT
+	ppc_md.progress = pmac_progress;
+#endif
+	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
+	
 }
+
+#ifdef CONFIG_BOOTX_TEXT
+extern void drawchar(char c);
+extern void drawstring(const char *c);
+void
+pmac_progress(char *s, unsigned short hex)
+{
+	drawstring(s);
+	drawchar('\n');
+}
+#endif CONFIG_BOOTX_TEXT
+
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
--- v2.3.42/linux/arch/ppc/kernel/pmac_time.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/pmac_time.c	Wed Feb  9 19:43:47 2000
@@ -71,8 +71,8 @@
 		if (req.reply_len != 7)
 			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
 			       req.reply_len);
-		return (req.reply[3] << 24) + (req.reply[4] << 16)
-			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
+		return (unsigned long)(req.reply[1] << 24) + (req.reply[2] << 16)
+			+ (req.reply[3] << 8) + (unsigned long)req.reply[4] - RTC_OFFSET;
 #endif /* CONFIG_ADB_CUDA */
 #ifdef CONFIG_ADB_PMU
 	case SYS_CTRLER_PMU:
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/ppc-stub.c linux/arch/ppc/kernel/ppc-stub.c
--- v2.3.42/linux/arch/ppc/kernel/ppc-stub.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/ppc/kernel/ppc-stub.c	Wed Feb  9 19:43:47 2000
@@ -351,7 +351,7 @@
 
 static inline void set_msr(int msr)
 {
-	asm volatile("mfmsr %0" : : "r" (msr));
+	asm volatile("mtmsr %0" : : "r" (msr));
 }
 
 /* Set up exception handlers for tracing and breakpoints
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.3.42/linux/arch/ppc/kernel/ppc_htab.c	Tue Dec  7 09:32:41 1999
+++ linux/arch/ppc/kernel/ppc_htab.c	Wed Feb  9 19:43:47 2000
@@ -45,17 +45,9 @@
 extern unsigned long pte_errors;
 
 static struct file_operations ppc_htab_operations = {
-    ppc_htab_lseek,	/* lseek   */
-    ppc_htab_read,	/* read	   */
-    ppc_htab_write,	/* write   */
-    NULL,		/* readdir */
-    NULL,		/* poll    */
-    NULL,		/* ioctl   */
-    NULL,		/* mmap	   */
-    NULL,		/* no special open code	   */
-    NULL,		/* flush */
-    NULL,		/* no special release code */
-    NULL		/* can't fsync */
+	llseek:		ppc_htab_lseek,
+	read:		ppc_htab_read,
+	write:		ppc_htab_write,
 };
 
 /*
@@ -531,7 +523,8 @@
 		"0.5", "1.0", "(reserved2)", "(reserved3)"
 	};
 
-	if ( (_get_PVR() >> 16) != 8) return -EFAULT;
+	if ( ((_get_PVR() >> 16) != 8) && ((_get_PVR() >> 16) != 12))
+		return -EFAULT;
 	
 	if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) {
 		*lenp = 0;
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.3.42/linux/arch/ppc/kernel/ppc_ksyms.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Wed Feb  9 19:43:47 2000
@@ -229,6 +229,8 @@
 EXPORT_SYMBOL(find_phandle);
 EXPORT_SYMBOL(device_is_compatible);
 EXPORT_SYMBOL(machine_is_compatible);
+EXPORT_SYMBOL(find_pci_device_OFnode);
+EXPORT_SYMBOL(find_all_nodes);
 EXPORT_SYMBOL(get_property);
 EXPORT_SYMBOL(pci_io_base);
 EXPORT_SYMBOL(pci_device_loc);
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.3.42/linux/arch/ppc/kernel/prep_pci.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/ppc/kernel/prep_pci.c	Wed Feb  9 19:43:47 2000
@@ -40,7 +40,7 @@
 static unsigned long	*ProcInfo;
 
 extern int chrp_get_irq(struct pt_regs *);
-extern void chrp_post_irq(int);
+extern void chrp_post_irq(struct pt_regs* regs, int);
 
 /* Tables for known hardware */   
 
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.3.42/linux/arch/ppc/kernel/process.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/kernel/process.c	Wed Feb  9 19:43:47 2000
@@ -57,6 +57,8 @@
 };
 /* only used to get secondary processor up */
 struct task_struct *current_set[NR_CPUS] = {&init_task, };
+char *sysmap = NULL; 
+unsigned long sysmap_size = 0;
 
 #undef SHOW_TASK_SWITCHES 1
 #undef CHECK_STACK 1
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.3.42/linux/arch/ppc/kernel/prom.c	Tue Dec  7 09:32:42 1999
+++ linux/arch/ppc/kernel/prom.c	Wed Feb  9 19:43:47 2000
@@ -30,6 +30,10 @@
 #include <asm/system.h>
 #include <asm/gemini.h>
 
+#ifdef CONFIG_FB
+#include <asm/linux_logo.h>
+#endif
+
 /*
  * Properties whose value is longer than this get excluded from our
  * copy of the device tree.  This way we don't waste space storing
@@ -91,7 +95,7 @@
 char *of_stdout_device = 0;
 
 prom_entry prom = 0;
-ihandle prom_chosen = 0, prom_stdout = 0;
+ihandle prom_chosen = 0, prom_stdout = 0, prom_disp_node = 0;
 
 extern char *klimit;
 char *bootpath = 0;
@@ -102,33 +106,35 @@
 unsigned int rtas_size = 0;
 unsigned int old_rtas = 0;
 
+int use_of_interrupt_tree = 0;
 static struct device_node *allnodes = 0;
 
+#ifdef CONFIG_BOOTX_TEXT
+
 static void clearscreen(void);
 static void flushscreen(void);
 
-#ifdef CONFIG_BOOTX_TEXT
-
 void drawchar(char c);
 void drawstring(const char *c);
 static void drawhex(unsigned long v);
 static void scrollscreen(void);
 
 static void draw_byte(unsigned char c, long locX, long locY);
-static void draw_byte_32(unsigned char *bits, unsigned long *base);
-static void draw_byte_16(unsigned char *bits, unsigned long *base);
-static void draw_byte_8(unsigned char *bits, unsigned long *base);
-
-static long				g_loc_X;
-static long				g_loc_Y;
-static long				g_max_loc_X;
-static long				g_max_loc_Y;
+static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb);
+static void draw_byte_16(unsigned char *bits, unsigned long *base, int rb);
+static void draw_byte_8(unsigned char *bits, unsigned long *base, int rb);
+
+/* We want those in data, not BSS */
+static long				g_loc_X = 0;
+static long				g_loc_Y = 0;
+static long				g_max_loc_X = 0;
+static long				g_max_loc_Y = 0;
 
 #define cmapsz	(16*256)
 
 static unsigned char vga_font[cmapsz];
 
-#endif
+#endif /* CONFIG_BOOTX_TEXT */
 
 
 static void *call_prom(const char *service, int nargs, int nret, ...);
@@ -138,15 +144,25 @@
 				  unsigned long, struct device_node ***);
 static unsigned long finish_node(struct device_node *, unsigned long,
 				 interpret_func *);
+static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
 static unsigned long check_display(unsigned long);
 static int prom_next_node(phandle *);
 static void *early_get_property(unsigned long, unsigned long, char *);
 
+#ifdef CONFIG_BOOTX_TEXT
+static void setup_disp_fake_bi(ihandle dp);
+static void prom_welcome(boot_infos_t* bi, unsigned long phys);
+#endif
+
 extern void enter_rtas(void *);
 extern unsigned long reloc_offset(void);
 
 extern char cmd_line[512];	/* XXX */
 boot_infos_t *boot_infos = 0;	/* init it so it's in data segment not bss */
+#ifdef CONFIG_BOOTX_TEXT
+boot_infos_t *disp_bi = 0;
+boot_infos_t fake_bi = {0,};
+#endif
 unsigned long dev_tree_size;
 
 /*
@@ -240,7 +256,7 @@
 	if (RELOC(prom_stdout) == 0)
 	{
 #ifdef CONFIG_BOOTX_TEXT
-		if (RELOC(boot_infos) != 0)
+		if (RELOC(disp_bi) != 0)
 			drawstring(msg);
 #endif
 		return;
@@ -261,7 +277,6 @@
 	}
 }
 
-unsigned long smp_ibm_chrp_hack __initdata = 0;
 unsigned long smp_chrp_cpu_nr __initdata = 1;
 
 /*
@@ -269,23 +284,29 @@
  * handling exceptions and the MMU hash table for us.
  */
 __init
-void
+unsigned long
 prom_init(int r3, int r4, prom_entry pp)
 {
 #ifdef CONFIG_SMP	
 	int i;
 	phandle node;
 	char type[16], *path;
-#endif	
+#endif
+	int chrp = 0;
 	unsigned long mem;
-	ihandle prom_rtas;
+	ihandle prom_rtas, prom_mmu, prom_op;
 	unsigned long offset = reloc_offset();
 	int l;
 	char *p, *d;
+	int prom_version = 0;
+ 	unsigned long phys;
+
+ 	/* Default */
+ 	phys = offset + KERNELBASE;
 
 	/* check if we're apus, return if we are */
 	if ( r3 == 0x61707573 )
-		return;
+		return phys;
 
 	/* If we came here from BootX, clear the screen,
 	 * set up some pointers and return. */
@@ -294,22 +315,20 @@
 		unsigned long space;
 		unsigned long ptr, x;
 		char *model;
-#ifdef CONFIG_BOOTX_TEXT
-		unsigned long flags;
-#endif		
 
 		RELOC(boot_infos) = PTRUNRELOC(bi);
 		if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
 			bi->logicalDisplayBase = 0;
 
-		clearscreen();
-
 #ifdef CONFIG_BOOTX_TEXT
 		RELOC(g_loc_X) = 0;
 		RELOC(g_loc_Y) = 0;
 		RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8;
 		RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16;
+		RELOC(disp_bi) = PTRUNRELOC(bi);
 		
+		clearscreen();
+
 		/* Test if boot-info is compatible. Done only in config CONFIG_BOOTX_TEXT since
 		   there is nothing much we can do with an incompatible version, except display
 		   a message and eventually hang the processor...
@@ -320,23 +339,9 @@
 		if (!BOOT_INFO_IS_COMPATIBLE(bi))
 			prom_print(RELOC(" !!! WARNING - Incompatible version of BootX !!!\n\n\n"));
 		
-		prom_print(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n"));
-		prom_print(RELOC("\nstarted at       : 0x"));
-		drawhex(reloc_offset() + KERNELBASE);
-		prom_print(RELOC("\nlinked at        : 0x"));
-		drawhex(KERNELBASE);
-		prom_print(RELOC("\nframe buffer at  : 0x"));
-		drawhex((unsigned long)bi->dispDeviceBase);
-		prom_print(RELOC(" (phys), 0x"));
-		drawhex((unsigned long)bi->logicalDisplayBase);
-		prom_print(RELOC(" (log)"));
-		prom_print(RELOC("\nMSR              : 0x"));
-		__asm__ __volatile__ ("mfmsr %0" : "=r" ((flags)) : : "memory");
-		drawhex(flags);
-		prom_print(RELOC("\n\n"));
-#endif
-		/* Out of the #if/#endif since it flushes the clearscreen too */
+		prom_welcome(bi, phys);
 		flushscreen();
+#endif	/* CONFIG_BOOTX_TEXT */	
 		
 		/* New BootX enters kernel with MMU off, i/os are not allowed
 		   here. This hack will have been done by the boostrap anyway.
@@ -381,12 +386,12 @@
 		prom_print(RELOC("booting...\n"));
 		flushscreen();
 #endif
-		return;
+		return phys;
 	}
 
 	/* check if we're prep, return if we are */
 	if ( *(unsigned long *)(0) == 0xdeadc0de )
-		return;
+		return phys;
 
 	/* First get a handle for the stdout device */
 	RELOC(prom) = pp;
@@ -407,6 +412,30 @@
 	RELOC(of_stdout_device) = PTRUNRELOC(p);
 	mem += strlen(p) + 1;
 
+	/* Find the OF version */
+	prom_op = call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom"));
+	prom_version = 0;
+	if (prom_op != (void*)-1) {
+		char model[64];
+		int sz;
+		sz = (int)call_prom(RELOC("getprop"), 4, 1, prom_op, RELOC("model"), model, 64);
+		if (sz > 0) {
+			char *c;
+			/* hack to skip the ibm chrp firmware # */
+			if ( strncmp(model,RELOC("IBM"),3) ) {
+				for (c = model; *c; c++)
+					if (*c >= '0' && *c <= '9') {
+						prom_version = *c - '0';
+						break;
+					}
+			}
+			else
+				chrp = 1;
+		}
+	}
+	if (prom_version >= 3)
+		prom_print(RELOC("OF Version 3 detected.\n"));
+
 	/* Get the boot device and translate it to a full OF pathname. */
 	p = (char *) mem;
 	l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
@@ -478,6 +507,42 @@
 			prom_print(RELOC(" done\n"));
 	}
 
+	/* 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)
+		phys = 0;
+	else {
+ 	    if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
+			    RELOC("mmu"), &prom_mmu, sizeof(prom_mmu)) <= 0) {	
+		prom_print(RELOC(" no MMU found\n"));
+	    } else {
+		int nargs;
+		struct prom_args prom_args;
+		nargs = 4;
+		prom_args.service = RELOC("call-method");
+		prom_args.nargs = nargs;
+		prom_args.nret = 4;
+		prom_args.args[0] = RELOC("translate");
+		prom_args.args[1] = prom_mmu;
+		prom_args.args[2] = (void *)(offset + KERNELBASE);
+		prom_args.args[3] = (void *)1;
+		RELOC(prom)(&prom_args);
+
+		/* We assume the phys. address size is 3 cells */
+		if (prom_args.args[nargs] != 0)
+			prom_print(RELOC(" (translate failed) "));
+		else
+			phys = (unsigned long)prom_args.args[nargs+3];
+	    }
+	}
+
+#ifdef CONFIG_BOOTX_TEXT
+	if (!chrp && RELOC(prom_disp_node) != 0)
+		setup_disp_fake_bi(RELOC(prom_disp_node));
+#endif
+
 #ifdef CONFIG_SMP
 	/*
 	 * With CHRP SMP we need to use the OF to start the other
@@ -512,7 +577,7 @@
 		node = call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
 		if ( (int)call_prom(RELOC("getprop"), 4, 1, node,
 			    RELOC("device_type"),type, sizeof(type)) <= 0)
-			return;
+			return phys;
 		
 		/* copy the holding pattern code to someplace safe (8M) */
 		memcpy( (void *)(8<<20), RELOC(__secondary_hold), 0x100 );
@@ -554,6 +619,79 @@
 			prom_print(RELOC("...failed\n"));
 	}
 #endif
+	/* If OpenFirmware version >= 3, then use quiesce call */
+	if (prom_version >= 3) {
+		prom_print(RELOC("Calling quiesce ...\n"));
+		call_prom(RELOC("quiesce"), 0, 0);
+		offset = reloc_offset();
+		phys = offset + KERNELBASE;
+	}
+
+#ifdef CONFIG_BOOTX_TEXT
+	if (!chrp && RELOC(disp_bi)) {
+		RELOC(prom_stdout) = 0;
+		clearscreen();
+		prom_welcome(PTRRELOC(RELOC(disp_bi)), phys);
+		prom_print(RELOC("booting...\n"));
+	}
+#endif
+
+	return phys;
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+__init static void
+prom_welcome(boot_infos_t* bi, unsigned long phys)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long flags;
+	unsigned long pvr;
+	
+	prom_print(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n"));
+	prom_print(RELOC("\nstarted at       : 0x"));
+	drawhex(phys);
+	prom_print(RELOC("\nlinked at        : 0x"));
+	drawhex(KERNELBASE);
+	prom_print(RELOC("\nframe buffer at  : 0x"));
+	drawhex((unsigned long)bi->dispDeviceBase);
+	prom_print(RELOC(" (phys), 0x"));
+	drawhex((unsigned long)bi->logicalDisplayBase);
+	prom_print(RELOC(" (log)"));
+	prom_print(RELOC("\nMSR              : 0x"));
+	__asm__ __volatile__ ("mfmsr %0" : "=r" (flags));
+	drawhex(flags);
+	__asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr));
+	pvr >>= 16;
+	if (pvr > 1) {
+	    prom_print(RELOC("\nHID0             : 0x"));
+	    __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags));
+	    drawhex(flags);
+	}
+	if (pvr == 8 || pvr == 12) {
+	    prom_print(RELOC("\nICTC             : 0x"));
+	    __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags));
+	    drawhex(flags);
+	}
+	prom_print(RELOC("\n\n"));
+}
+#endif
+
+static int prom_set_color(ihandle ih, int i, int r, int g, int b)
+{
+	struct prom_args prom_args;
+	unsigned long offset = reloc_offset();
+
+	prom_args.service = RELOC("call-method");
+	prom_args.nargs = 6;
+	prom_args.nret = 1;
+	prom_args.args[0] = RELOC("color!");
+	prom_args.args[1] = ih;
+	prom_args.args[2] = (void *) i;
+	prom_args.args[3] = (void *) b;
+	prom_args.args[4] = (void *) g;
+	prom_args.args[5] = (void *) r;
+	RELOC(prom)(&prom_args);
+	return (int) prom_args.args[6];
 }
 
 /*
@@ -573,6 +711,26 @@
 	int i;
 	unsigned long offset = reloc_offset();
 	char type[16], *path;
+	static unsigned char default_colors[] = {
+		0x00, 0x00, 0x00,
+		0x00, 0x00, 0xaa,
+		0x00, 0xaa, 0x00,
+		0x00, 0xaa, 0xaa,
+		0xaa, 0x00, 0x00,
+		0xaa, 0x00, 0xaa,
+		0xaa, 0xaa, 0x00,
+		0xaa, 0xaa, 0xaa,
+		0x55, 0x55, 0x55,
+		0x55, 0x55, 0xff,
+		0x55, 0xff, 0x55,
+		0x55, 0xff, 0xff,
+		0xff, 0x55, 0x55,
+		0xff, 0x55, 0xff,
+		0xff, 0xff, 0x55,
+		0xff, 0xff, 0xff
+	};
+
+	RELOC(prom_disp_node) = 0;
 
 	for (node = 0; prom_next_node(&node); ) {
 		type[0] = 0;
@@ -595,6 +753,26 @@
 		}
 		prom_print(RELOC("... ok\n"));
 
+		if (RELOC(prom_disp_node) == 0)
+			RELOC(prom_disp_node) = node;
+			
+		/* Setup a useable color table when the appropriate
+		 * method is available. Should update this to set-colors */
+		for (i = 0; i < 32; i++)
+			if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
+					   RELOC(default_colors)[i*3+1],
+					   RELOC(default_colors)[i*3+2]) != 0)
+				break;
+
+#ifdef CONFIG_FB
+		for (i = 0; i < LINUX_LOGO_COLORS; i++)
+			if (prom_set_color(ih, i + 32,
+					   RELOC(linux_logo_red)[i],
+					   RELOC(linux_logo_green)[i],
+					   RELOC(linux_logo_blue)[i]) != 0)
+				break;
+#endif /* CONFIG_FB */
+
 		/*
 		 * If this display is the device that OF is using for stdout,
 		 * move it to the front of the list.
@@ -614,6 +792,79 @@
 	return ALIGN(mem);
 }
 
+/* This function will enable the early boot text when doing OF booting. This
+ * way, xmon output should work too
+ */
+#ifdef CONFIG_BOOTX_TEXT
+__init
+static void
+setup_disp_fake_bi(ihandle dp)
+{
+	unsigned int len;
+	int width = 640, height = 480, depth = 8, pitch;
+	unsigned  address;
+	boot_infos_t* bi;
+	unsigned long offset = reloc_offset();
+	
+	prom_print(RELOC("Initing fake screen\n"));
+
+	len = 0;
+	call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"), &len, sizeof(len));
+	if (len == 0)
+		prom_print(RELOC("Warning: assuming display depth = 8\n"));
+	else
+		depth = len;
+	width = len = 0;
+	call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &len, sizeof(len));
+	width = len;
+	if (width == 0) {
+		prom_print(RELOC("Failed to get width\n"));
+		return;
+	}
+	height = len = 0;
+	call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &len, sizeof(len));
+	height = len;
+	if (height == 0) {
+		prom_print(RELOC("Failed to get height\n"));
+		return;
+	}
+	pitch = len = 0;
+	call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"), &len, sizeof(len));
+	pitch = len;
+	if (pitch == 0) {
+		prom_print(RELOC("Failed to get pitch\n"));
+		return;
+	}
+	address = len = 0;
+	call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), &len, sizeof(len));
+	address = len;
+	if (address == 0) {
+		prom_print(RELOC("Failed to get address\n"));
+		return;
+	}
+#if 0
+	/* kludge for valkyrie */
+	if (strcmp(dp->name, "valkyrie") == 0) 
+	    address += 0x1000;
+    }
+#endif
+ 
+    RELOC(disp_bi) = &fake_bi;
+    bi = PTRRELOC((&fake_bi));
+    RELOC(g_loc_X) = 0;
+    RELOC(g_loc_Y) = 0;
+    RELOC(g_max_loc_X) = width / 8;
+    RELOC(g_max_loc_Y) = height / 16;
+    bi->logicalDisplayBase = (unsigned char *)address;
+    bi->dispDeviceBase = (unsigned char *)address;
+    bi->dispDeviceRowBytes = pitch;
+    bi->dispDeviceDepth = depth;
+    bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
+    bi->dispDeviceRect[2] = width;
+    bi->dispDeviceRect[3] = height;
+}
+#endif
+
 __init
 static int
 prom_next_node(phandle *nodep)
@@ -748,6 +999,16 @@
 finish_device_tree(void)
 {
 	unsigned long mem = (unsigned long) klimit;
+	char* model;
+	
+	/* Here, we decide if we'll use the interrupt-tree (new Core99 code) or not.
+	 * This code was only tested with Core99 machines so far, but should be easily
+	 * adapted to older newworld machines (iMac, B&W G3, Lombard).
+	 */
+	model = get_property(allnodes, "model", 0);
+	if ((boot_infos == 0) && model && (strcmp(model, "PowerBook2,1") == 0
+	    || strcmp(model, "PowerMac2,1") == 0 || strcmp(model, "PowerMac3,1") == 0))
+		use_of_interrupt_tree = 1;
 
 	mem = finish_node(allnodes, mem, NULL);
 	dev_tree_size = mem - (unsigned long) allnodes;
@@ -788,6 +1049,9 @@
 	if (ifunc != NULL) {
 		mem_start = ifunc(np, mem_start);
 	}
+	if (use_of_interrupt_tree) {
+		mem_start = finish_node_interrupts(np, mem_start);
+	}
 
 	/* the f50 sets the name to 'display' and 'compatible' to what we
 	 * expect for the name -- Cort
@@ -834,6 +1098,133 @@
 	return mem_start;
 }
 
+/* This routine walks the interrupt tree for a given device node and gather 
+ * all necessary informations according to the draft interrupt mapping
+ * for CHRP. The current version was only tested on Apple "Core99" machines
+ * and may not handle cascaded controllers correctly.
+ */
+__init
+static unsigned long
+finish_node_interrupts(struct device_node *np, unsigned long mem_start)
+{
+	/* Finish this node */
+	unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg;
+	phandle *parent;
+	struct device_node *node, *parent_node;
+	int l, isize, ipsize, asize, map_size, regpsize;
+
+	/* Currently, we don't look at all nodes with no "interrupts" property */
+	interrupts = (unsigned int *)get_property(np, "interrupts", &l);
+	if (interrupts == NULL)
+		return mem_start;
+	ipsize = l>>2;
+
+	reg = (unsigned int *)get_property(np, "reg", &l);
+	regpsize = l>>2;
+
+	/* We assume default interrupt cell size is 1 (bugus ?) */
+	isize = 1;
+	node = np;
+	
+	do {
+	    /* We adjust the cell size if the current parent contains an #interrupt-cells
+	     * property */
+	    isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l);
+	    if (isizep)
+	    	isize = *isizep;
+
+	    /* We don't do interrupt cascade (ISA) for now, we stop on the first 
+	     * controller found
+	     */
+	    if (get_property(node, "interrupt-controller", &l)) {
+	    	int i,j;
+	    	np->intrs = (struct interrupt_info *) mem_start;
+		np->n_intrs = ipsize / isize;
+		mem_start += np->n_intrs * sizeof(struct interrupt_info);
+		for (i = 0; i < np->n_intrs; ++i) {
+		    np->intrs[i].line = *interrupts++;
+		    np->intrs[i].sense = 0;
+		    if (isize > 1)
+		        np->intrs[i].sense = *interrupts++;
+		    for (j=2; j<isize; j++)
+		    	interrupts++;
+		}
+		return mem_start;
+	    }
+	    /* We lookup for an interrupt-map. This code can only handle one interrupt
+	     * per device in the map. We also don't handle #address-cells in the parent
+	     * I skip the pci node itself here, may not be necessary but I don't like it's
+	     * reg property.
+	     */
+	    if (np != node)
+	        map = (unsigned int *)get_property(node, "interrupt-map", &l);
+	     else
+	     	map = NULL;
+	    if (map && l) {
+	    	int i, found, temp_isize;
+	        map_size = l>>2;
+	        map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);
+	        asizep = (unsigned int *)get_property(node, "#address-cells", &l);
+	        if (asizep && l == sizeof(unsigned int))
+	            asize = *asizep;
+	        else
+	            asize = 0;
+	        found = 0;
+	        while(map_size>0 && !found) {
+	            found = 1;
+	            for (i=0; i<asize; i++) {
+	            	unsigned int mask = map_mask ? map_mask[i] : 0xffffffff;
+	            	if (!reg || (i>=regpsize) || ((mask & *map) != (mask & reg[i])))
+	           	    found = 0;
+	           	map++;
+	           	map_size--;
+	            }
+	            for (i=0; i<isize; i++) {
+	            	unsigned int mask = map_mask ? map_mask[i+asize] : 0xffffffff;
+	            	if ((mask & *map) != (mask & interrupts[i]))
+	            	    found = 0;
+	            	map++;
+	            	map_size--;
+	            }
+	            parent = *((phandle *)(map));
+	            map+=1; map_size-=1;
+	            parent_node = find_phandle(parent);
+	            temp_isize = isize;
+	            if (parent_node) {
+			isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);
+	    		if (isizep)
+	    		    temp_isize = *isizep;
+	            }
+	            if (!found) {
+	            	map += temp_isize;
+	            	map_size-=temp_isize;
+	            }
+	        }
+	        if (found) {
+	            node = parent_node;
+	            reg = NULL;
+	            regpsize = 0;
+	            interrupts = (unsigned int *)map;
+	            ipsize = temp_isize*1;
+		    continue;
+	        }
+	    }
+	    /* We look for an explicit interrupt-parent.
+	     */
+	    parent = (phandle *)get_property(node, "interrupt-parent", &l);
+	    if (parent && (l == sizeof(phandle)) &&
+	    	(parent_node = find_phandle(*parent))) {
+	    	node = parent_node;
+	    	continue;
+	    }
+	    /* Default, get real parent */
+	    node = node->parent;
+	} while(node);
+
+	return mem_start;
+}
+
+
 /*
  * When BootX makes a copy of the device tree from the MacOS
  * Name Registry, it is in the format we use but all of the pointers
@@ -892,6 +1283,9 @@
 		mem_start += i * sizeof(struct address_range);
 	}
 
+	if (use_of_interrupt_tree)
+		return mem_start;
+
 	/*
 	 * If the pci host bridge has an interrupt-map property,
 	 * look for our node in it.
@@ -901,14 +1295,28 @@
 		get_property(np->parent, "interrupt-map", &ml)) != 0
 	    && (ip = (int *) get_property(np, "interrupts", &l)) != 0) {
 		unsigned int devfn = pci_addrs[0].addr.a_hi & 0xff00;
+		unsigned int cell_size;
+		struct device_node* np2;
+		/* This is hackish, but is only used for BootX booting */
+		cell_size = sizeof(struct pci_intr_map);
+		np2 = np->parent;
+		while(np2) {
+			if (device_is_compatible(np2, "uni-north")) {
+				cell_size += 4;
+				break;
+			}
+			np2 = np2->parent;
+		}
 		np->n_intrs = 0;
 		np->intrs = (struct interrupt_info *) mem_start;
-		for (i = 0; (ml -= sizeof(struct pci_intr_map)) >= 0; ++i) {
-			if (imp[i].addr.a_hi == devfn) {
-				np->intrs[np->n_intrs].line = imp[i].intr;
-				np->intrs[np->n_intrs].sense = 0;
+		for (i = 0; (ml -= cell_size) >= 0; ++i) {
+			if (imp->addr.a_hi == devfn) {
+				np->intrs[np->n_intrs].line = imp->intr;
+				np->intrs[np->n_intrs].sense = 0; /* FIXME */
 				++np->n_intrs;
 			}
+			imp = (struct pci_intr_map *)(((unsigned int)imp)
+				+ cell_size);
 		}
 		if (np->n_intrs == 0)
 			np->intrs = 0;
@@ -965,6 +1373,9 @@
 		mem_start += i * sizeof(struct address_range);
 	}
 
+	if (use_of_interrupt_tree)
+		return mem_start;
+
 	ip = (int *) get_property(np, "AAPL,interrupts", &l);
 	if (ip == 0)
 		ip = (int *) get_property(np, "interrupts", &l);
@@ -988,13 +1399,14 @@
 	struct reg_property *rp;
 	struct address_range *adr;
 	unsigned long base_address;
-	int i, l, *ip;
+	int i, l, keylargo, *ip;
 	struct device_node *db;
 
 	base_address = 0;
 	for (db = np->parent; db != NULL; db = db->parent) {
 		if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
 			base_address = db->addrs[0].address;
+			keylargo = device_is_compatible(db, "Keylargo");
 			break;
 		}
 	}
@@ -1014,6 +1426,9 @@
 		mem_start += i * sizeof(struct address_range);
 	}
 
+	if (use_of_interrupt_tree)
+		return mem_start;
+
 	ip = (int *) get_property(np, "interrupts", &l);
 	if (ip == 0)
 		ip = (int *) get_property(np, "AAPL,interrupts", &l);
@@ -1022,9 +1437,15 @@
 		if (_machine == _MACH_Pmac) {
 			/* for the iMac */
 			np->n_intrs = l / sizeof(int);
+			/* Hack for BootX on Core99 */
+			if (keylargo)
+				np->n_intrs = np->n_intrs/2;
 			for (i = 0; i < np->n_intrs; ++i) {
 				np->intrs[i].line = *ip++;
-				np->intrs[i].sense = 0;
+				if (keylargo)
+					np->intrs[i].sense = *ip++;
+				else
+					np->intrs[i].sense = 0;
 			}
 		} else {
 			/* CHRP machines */
@@ -1064,6 +1485,9 @@
 		mem_start += i * sizeof(struct address_range);
 	}
 
+	if (use_of_interrupt_tree)
+		return mem_start;
+ 
 	ip = (int *) get_property(np, "interrupts", &l);
 	if (ip != 0) {
 		np->intrs = (struct interrupt_info *) mem_start;
@@ -1101,6 +1525,9 @@
 		mem_start += i * sizeof(struct address_range);
 	}
 
+	if (use_of_interrupt_tree)
+		return mem_start;
+
 	ip = (int *) get_property(np, "AAPL,interrupts", &l);
 	if (ip == 0)
 		ip = (int *) get_property(np, "interrupts", &l);
@@ -1157,6 +1584,49 @@
 	return head;
 }
 
+/* Finds a device node given its PCI bus number, device number
+ * and function number
+ */
+__openfirmware
+struct device_node *
+find_pci_device_OFnode(unsigned char bus, unsigned char dev_fn)
+{
+	struct device_node* np;
+	unsigned int *reg;
+	int l;
+	
+	for (np = allnodes; np != 0; np = np->allnext) {
+		char *pname = np->parent ?
+			(char *)get_property(np->parent, "name", &l) : 0;
+		if (pname && strcmp(pname, "mac-io") == 0)
+			continue;
+		reg = (unsigned int *) get_property(np, "reg", &l);
+		if (reg == 0 || l < sizeof(struct reg_property))
+			continue;
+		if (((reg[0] >> 8) & 0xff) == dev_fn && ((reg[0] >> 16) & 0xff) == bus)
+			break;
+	}
+	return np;
+}
+
+/*
+ * Returns all nodes linked together
+ */
+__openfirmware
+struct device_node *
+find_all_nodes(void)
+{
+	struct device_node *head, **prevp, *np;
+
+	prevp = &head;
+	for (np = allnodes; np != 0; np = np->allnext) {
+		*prevp = np;
+		prevp = &np->next;
+	}
+	*prevp = 0;
+	return head;
+}
+
 /* Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
  */
@@ -1377,18 +1847,28 @@
 	prom_exit();
 }
 
-#ifdef CONFIG_XMON
+#ifdef CONFIG_BOOTX_TEXT
+
+/* Here's a small text engine to use during early boot or for debugging purposes
+ * 
+ * todo:
+ * 
+ *  - build some kind of vgacon with it to enable early printk
+ *  - move to a separate file
+ *  - add a few video driver hooks to keep in sync with display
+ *    changes.
+ */
+
 __init
 void
 map_bootx_text(void)
 {
-	if (boot_infos == 0)
+	if (disp_bi == 0)
 		return;
-	boot_infos->logicalDisplayBase =
-		ioremap((unsigned long) boot_infos->dispDeviceBase,
-			boot_infos->dispDeviceRowBytes * boot_infos->dispDeviceRect[3]);
+	disp_bi->logicalDisplayBase =
+		ioremap((unsigned long) disp_bi->dispDeviceBase,
+			disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3]);
 }
-#endif /* CONFIG_XMON */
 
 /* Calc the base address of a given point (x,y) */
 __pmac
@@ -1410,7 +1890,7 @@
 clearscreen(void)
 {
 	unsigned long offset	= reloc_offset();
-	boot_infos_t* bi	= PTRRELOC(RELOC(boot_infos));
+	boot_infos_t* bi	= PTRRELOC(RELOC(disp_bi));
 	unsigned long *base	= (unsigned long *)calc_base(bi, 0, 0);
 	unsigned long width 	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
 					(bi->dispDeviceDepth >> 3)) >> 2;
@@ -1435,7 +1915,7 @@
 flushscreen(void)
 {
 	unsigned long offset	= reloc_offset();
-	boot_infos_t* bi	= PTRRELOC(RELOC(boot_infos));
+	boot_infos_t* bi	= PTRRELOC(RELOC(disp_bi));
 	unsigned long *base	= (unsigned long *)calc_base(bi, 0, 0);
 	unsigned long width 	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
 					(bi->dispDeviceDepth >> 3)) >> 2;
@@ -1452,14 +1932,12 @@
 	}
 }
 
-#ifdef CONFIG_BOOTX_TEXT
-
 __pmac
 static void
 scrollscreen(void)
 {
 	unsigned long offset		= reloc_offset();
-	boot_infos_t* bi		= PTRRELOC(RELOC(boot_infos));
+	boot_infos_t* bi		= PTRRELOC(RELOC(disp_bi));
 	unsigned long *src		= (unsigned long *)calc_base(bi,0,16);
 	unsigned long *dst		= (unsigned long *)calc_base(bi,0,0);
 	unsigned long width		= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
@@ -1563,19 +2041,20 @@
 draw_byte(unsigned char c, long locX, long locY)
 {
 	unsigned long offset	= reloc_offset();
-	boot_infos_t* bi	= PTRRELOC(RELOC(boot_infos));
+	boot_infos_t* bi	= PTRRELOC(RELOC(disp_bi));
 	unsigned char *base	= calc_base(bi, locX << 3, locY << 4);
 	unsigned char *font	= &RELOC(vga_font)[((unsigned long)c) * 16];
+	int rb			= bi->dispDeviceRowBytes;
 	
 	switch(bi->dispDeviceDepth) {
 		case 32:
-			draw_byte_32(font, (unsigned long *)base);
+			draw_byte_32(font, (unsigned long *)base, rb);
 			break;
 		case 16:
-			draw_byte_16(font, (unsigned long *)base);
+			draw_byte_16(font, (unsigned long *)base, rb);
 			break;
 		case 8:
-			draw_byte_8(font, (unsigned long *)base);
+			draw_byte_8(font, (unsigned long *)base, rb);
 			break;
 		default:
 			break;
@@ -1613,15 +2092,12 @@
 
 __pmac
 static void
-draw_byte_32(unsigned char *font, unsigned long *base)
+draw_byte_32(unsigned char *font, unsigned long *base, int rb)
 {
-	unsigned long offset = reloc_offset();
-	boot_infos_t* bi		= PTRRELOC(RELOC(boot_infos));
 	int l, bits;	
 	int fg = 0xFFFFFFFFUL;
 	int bg = 0x00000000UL;
 	
-
 	for (l = 0; l < 16; ++l)
 	{
 		bits = *font++;
@@ -1633,19 +2109,18 @@
 		base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
 		base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
 		base[7] = (-(bits & 1) & fg) ^ bg;
-		base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+		base = (unsigned long *) ((char *)base + rb);
 	}
 }
 
 __pmac
 static void
-draw_byte_16(unsigned char *font, unsigned long *base)
+draw_byte_16(unsigned char *font, unsigned long *base, int rb)
 {
-	unsigned long offset = reloc_offset();
-	boot_infos_t* bi		= PTRRELOC(RELOC(boot_infos));
 	int l, bits;	
 	int fg = 0xFFFFFFFFUL;
 	int bg = 0x00000000UL;
+	unsigned long offset = reloc_offset();
 	unsigned long *eb = RELOC(expand_bits_16);
 
 	for (l = 0; l < 16; ++l)
@@ -1655,19 +2130,18 @@
 		base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg;
 		base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg;
 		base[3] = (eb[bits & 3] & fg) ^ bg;
-		base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+		base = (unsigned long *) ((char *)base + rb);
 	}
 }
 
 __pmac
 static void
-draw_byte_8(unsigned char *font, unsigned long *base)
+draw_byte_8(unsigned char *font, unsigned long *base, int rb)
 {
-	unsigned long offset = reloc_offset();
-	boot_infos_t* bi		= PTRRELOC(RELOC(boot_infos));
 	int l, bits;	
 	int fg = 0x0F0F0F0FUL;
 	int bg = 0x00000000UL;
+	unsigned long offset = reloc_offset();
 	unsigned long *eb = RELOC(expand_bits_8);
 
 	for (l = 0; l < 16; ++l)
@@ -1675,7 +2149,7 @@
 		bits = *font++;
 		base[0] = (eb[bits >> 4] & fg) ^ bg;
 		base[1] = (eb[bits & 0xf] & fg) ^ bg;
-		base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+		base = (unsigned long *) ((char *)base + rb);
 	}
 }
 
@@ -2026,3 +2500,4 @@
 };
 
 #endif /* CONFIG_BOOTX_TEXT */
+
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/semaphore.c linux/arch/ppc/kernel/semaphore.c
--- v2.3.42/linux/arch/ppc/kernel/semaphore.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/ppc/kernel/semaphore.c	Wed Feb  9 19:43:47 2000
@@ -137,3 +137,44 @@
 {
 	return waking_non_zero_trylock(sem);
 }
+
+
+/*
+ * rw semaphores    Ani Joshi <ajoshi@unixbox.com>
+ * based on alpha port by Andrea Arcangeli <andrea@suse.de>
+ */
+
+void down_read_failed(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	do {
+		__set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+		spin_unlock_irq(&sem->lock);
+		schedule();
+		spin_lock_irq(&sem->lock);
+	} while(sem->wr);
+
+	remove_wait_queue(&sem->wait, &wait);
+}
+
+void down_write_failed(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	do {
+		__set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+		spin_unlock_irq(&sem->lock);
+		schedule();
+		spin_lock_irq(&sem->lock);
+	} while(sem->rd || sem->wr);
+
+	remove_wait_queue(&sem->wait, &wait);
+}
+
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.42/linux/arch/ppc/kernel/setup.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/kernel/setup.c	Wed Feb  9 19:43:47 2000
@@ -69,6 +69,13 @@
                       unsigned long r6,
                       unsigned long r7);
 
+#ifdef CONFIG_BOOTX_TEXT
+extern void map_bootx_text(void);
+#endif
+#ifdef CONFIG_XMON
+extern void xmon_map_scc(void);
+#endif
+
 extern boot_infos_t *boot_infos;
 char saved_command_line[256];
 unsigned char aux_device_present;
@@ -261,7 +268,7 @@
 			}
 			break;
 		case 0x000C:
-			len += sprintf(len+buffer, "7400\n");
+			len += sprintf(len+buffer, "7400 (G4)\n");
 			break;
 		case 0x0020:
 			len += sprintf(len+buffer, "403G");
@@ -292,7 +299,7 @@
 		 * Assume here that all clock rates are the same in a
 		 * smp system.  -- Cort
 		 */
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 		if ( have_of )
 		{
 			struct device_node *cpu_node;
@@ -316,7 +323,7 @@
 			len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
 				       *fp / 1000000);
 		}
-#endif
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
 
 		if (ppc_md.setup_residual != NULL)
 		{
@@ -410,8 +417,9 @@
 		 unsigned long r6, unsigned long r7)
 {
 	parse_bootinfo();
-	
+
 	if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
+	
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 #ifndef CONFIG_MACH_SPECIFIC
 	/* if we didn't get any bootinfo telling us what we are... */
@@ -477,11 +485,12 @@
 			char *p;
 			
 #ifdef CONFIG_BLK_DEV_INITRD
-			if (r3 - KERNELBASE < 0x800000
-			    && r4 != 0 && r4 != 0xdeadbeef) {
+			if (r3 && r4 && r4 != 0xdeadbeef)
+			{
 				initrd_start = r3;
 				initrd_end = r3 + r4;
 				ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+				initrd_below_start_ok = 1;
 			}
 #endif
 			cmd_line[0] = 0;
@@ -519,6 +528,7 @@
 	default:
 		printk("Unknown machine type in identify_machine!\n");
 	}
+
 	/* Check for nobats option (used in mapin_ram). */
 	if (strstr(cmd_line, "nobats")) {
 		extern int __map_without_bats;
@@ -567,9 +577,11 @@
 int parse_bootinfo(void)
 {
 	struct bi_record *rec;
-	extern char _end[];
+	extern char __bss_start[];
+	extern char *sysmap;
+	extern unsigned long sysmap_size;
 
-	rec = (struct bi_record *)PAGE_ALIGN((ulong)_end);
+	rec = (struct bi_record *)_ALIGN((ulong)__bss_start+(1<<20)-1,(1<<20));
 	if ( rec->tag != BI_FIRST )
 	{
 		/*
@@ -577,11 +589,10 @@
 		 * we have the bootloader handle all the relocation and
 		 * prom calls -- Cort
 		 */
-		rec = (struct bi_record *)PAGE_ALIGN((ulong)_end+0x10000);
+		rec = (struct bi_record *)_ALIGN((ulong)__bss_start+0x10000+(1<<20)-1,(1<<20));
 		if ( rec->tag != BI_FIRST )
 			return -1;
 	}
-
 	for ( ; rec->tag != BI_LAST ;
 	      rec = (struct bi_record *)((ulong)rec + rec->size) )
 	{
@@ -591,6 +602,11 @@
 		case BI_CMD_LINE:
 			memcpy(cmd_line, (void *)data, rec->size);
 			break;
+		case BI_SYSMAP:
+			sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] :
+					  (data[0]+KERNELBASE));
+			sysmap_size = data[1];
+			break;
 #ifdef CONFIG_BLK_DEV_INITRD
 		case BI_INITRD:
 			initrd_start = data[0];
@@ -603,7 +619,6 @@
 			have_of = data[1];
 			break;
 #endif /* CONFIG_MACH_SPECIFIC */
-			
 		}
 	}
 
@@ -613,7 +628,7 @@
 /* Checks "l2cr=xxxx" command-line option */
 void ppc_setup_l2cr(char *str, int *ints)
 {
-	if ( (_get_PVR() >> 16) == 8)
+	if ( ((_get_PVR() >> 16) == 8) || ((_get_PVR() >> 16) == 12) )
 	{
 		unsigned long val = simple_strtoul(str, NULL, 0);
 		printk(KERN_INFO "l2cr set to %lx\n", val);
@@ -639,12 +654,21 @@
 	extern char *klimit;
 	extern void do_init_bootmem(void);
 
+#ifdef CONFIG_BOOTX_TEXT
+	map_bootx_text();
+	prom_print("identify machine\n");
+#endif
+
 #ifdef CONFIG_XMON
-	extern void xmon_map_scc(void);
 	xmon_map_scc();
 	if (strstr(cmd_line, "xmon"))
 		xmon(0);
 #endif /* CONFIG_XMON */
+	if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
+#if defined(CONFIG_KGDB)
+	set_debug_traps();
+	breakpoint();
+#endif
 
 	/* reboot on panic */
 	panic_timeout = 180;
@@ -653,16 +677,16 @@
 	init_mm.end_code = (unsigned long) _etext;
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = (unsigned long) klimit;
-
+	
 	/* Save unparsed command line copy for /proc/cmdline */
 	strcpy(saved_command_line, cmd_line);
 	*cmdline_p = cmd_line;
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
+	if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
 
 	ppc_md.setup_arch();
-	/* clear the progress line */
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 }
 
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S
--- v2.3.42/linux/arch/ppc/kernel/sleep.S	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/kernel/sleep.S	Wed Feb  9 19:43:47 2000
@@ -171,6 +171,11 @@
  */
 	
 wake_up:
+	/* Flash inval the instruction cache */
+	mfspr	r3,HID0
+	ori	r3,r3, HID0_ICFI
+	mtspr	HID0,r3
+	isync
 	/* Restore the HID0 register.  This turns on the L1 caches. */
 	subi	r1,r1,SL_PC
 	lwz	r3,SL_HID0(r1)
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- v2.3.42/linux/arch/ppc/kernel/syscalls.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/ppc/kernel/syscalls.c	Wed Feb  9 19:43:47 2000
@@ -252,9 +252,14 @@
 
 asmlinkage int sys_uname(struct old_utsname * name)
 {
-	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
-		return 0;
-	return -EFAULT;
+	int err;
+	
+	if (!name)
+		return -EFAULT;
+	down_read(&uts_sem);
+	err = copy_to_user(name, &system_utsname, sizeof (*name));
+	up(&uts_sem);
+	return err ? -EFAULT : 0;
 }
 
 asmlinkage int sys_olduname(struct oldold_utsname * name)
@@ -266,6 +271,7 @@
 	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
 		return -EFAULT;
   
+	down_read(&uts_sem);
 	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
 	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
 	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
@@ -277,6 +283,7 @@
 	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
 	error = __put_user(0,name->machine+__OLD_UTS_LEN);
 	error = error ? -EFAULT : 0;
+	up(&uts_sem);
 
 	return error;
 }
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.3.42/linux/arch/ppc/kernel/traps.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/ppc/kernel/traps.c	Wed Feb  9 19:43:47 2000
@@ -128,6 +128,20 @@
 	_exception(SIGSEGV, regs);	
 }
 
+void
+SMIException(struct pt_regs *regs)
+{
+#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+	{
+		debugger(regs);
+		return;
+	}
+#endif
+	show_regs(regs);
+	print_backtrace((unsigned long *)regs->gpr[1]);
+	panic("System Management Interrupt");
+}
+
 #if defined(CONFIG_ALTIVEC)
 void
 AltiVecUnavailable(struct pt_regs *regs)
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/walnut_setup.c linux/arch/ppc/kernel/walnut_setup.c
--- v2.3.42/linux/arch/ppc/kernel/walnut_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/walnut_setup.c	Thu Feb 10 12:37:51 2000
@@ -0,0 +1,295 @@
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: walnut_setup.c
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ *      <dan@net4x.com>.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/interrupt.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+
+#include <asm/processor.h>
+#include <asm/board.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+
+#include "local_irq.h"
+#include "ppc4xx_pic.h"
+#include "time.h"
+#include "walnut_setup.h"
+
+
+/* Function Prototypes */
+
+extern void abort(void);
+
+/* Global Variables */
+
+unsigned char __res[sizeof(bd_t)];
+
+
+/*
+ * void __init walnut_init()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *   r3 - Optional pointer to a board information structure.
+ *   r4 - Optional pointer to the physical starting address of the init RAM
+ *        disk.
+ *   r5 - Optional pointer to the physical ending address of the init RAM
+ *        disk.
+ *   r6 - Optional pointer to the physical starting address of any kernel
+ *        command-line parameters.
+ *   r7 - Optional pointer to the physical ending address of any kernel
+ *        command-line parameters.
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, 
+	    unsigned long r6, unsigned long r7)
+{
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+	}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+ 		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+	}
+
+	/* Initialize machine-dependency vectors */
+
+	ppc_md.setup_arch	 	= walnut_setup_arch;
+	ppc_md.setup_residual	 	= walnut_setup_residual;
+	ppc_md.get_cpuinfo	 	= NULL;
+	ppc_md.irq_cannonicalize 	= NULL;
+	ppc_md.init_IRQ		 	= walnut_init_IRQ;
+	ppc_md.get_irq		 	= walnut_get_irq;
+	ppc_md.init		 	= NULL;
+
+	ppc_md.restart		 	= walnut_restart;
+	ppc_md.power_off	 	= walnut_power_off;
+	ppc_md.halt		 	= walnut_halt;
+
+	ppc_md.time_init	 	= walnut_time_init;
+	ppc_md.set_rtc_time	 	= walnut_set_rtc_time;
+	ppc_md.get_rtc_time	 	= walnut_get_rtc_time;
+	ppc_md.calibrate_decr	 	= walnut_calibrate_decr;
+
+	ppc_md.kbd_setkeycode    	= NULL;
+	ppc_md.kbd_getkeycode    	= NULL;
+	ppc_md.kbd_translate     	= NULL;
+	ppc_md.kbd_unexpected_up 	= NULL;
+	ppc_md.kbd_leds          	= NULL;
+	ppc_md.kbd_init_hw       	= NULL;
+
+#if defined(CONFIG_MAGIC_SYSRQ)
+	ppc_md.ppc_kbd_sysrq_xlate	= NULL;
+#endif
+
+	return;
+}
+
+/*
+ * Document me.
+ */
+void __init
+walnut_setup_arch(void)
+{
+	/* XXX - Implement me */
+}
+
+/*
+ * int walnut_setup_residual()
+ *
+ * Description:
+ *   This routine pretty-prints the platform's internal CPU and bus clock
+ *   frequencies into the buffer for usage in /proc/cpuinfo.
+ *
+ * Input(s):
+ *  *buffer - Buffer into which CPU and bus clock frequencies are to be
+ *            printed.
+ *
+ * Output(s):
+ *  *buffer - Buffer with the CPU and bus clock frequencies.
+ *
+ * Returns:
+ *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
+ *   on error.
+ */
+int
+walnut_setup_residual(char *buffer)
+{
+	int len = 0;
+	bd_t *bp = (bd_t *)__res;
+
+	len += sprintf(len + buffer,
+		       "clock\t\t: %dMHz\n"
+		       "bus clock\t\t: %dMHz\n",
+		       bp->bi_intfreq / 1000000,
+		       bp->bi_busfreq / 1000000);
+
+	return (len);
+}
+
+/*
+ * Document me.
+ */
+void __init
+walnut_init_IRQ(void)
+{
+	int i;
+
+	ppc4xx_pic_init();
+
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].handler = ppc4xx_pic;
+	}
+
+	return;
+}
+
+/*
+ * Document me.
+ */
+int
+walnut_get_irq(struct pt_regs *regs)
+{
+	return (ppc4xx_pic_get_irq(regs));
+}
+
+/*
+ * Document me.
+ */
+void
+walnut_restart(char *cmd)
+{
+	abort();
+}
+
+/*
+ * Document me.
+ */
+void
+walnut_power_off(void)
+{
+	walnut_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void
+walnut_halt(void)
+{
+	walnut_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void __init
+walnut_time_init(void)
+{
+	/* XXX - Implement me */
+}
+
+/*
+ * Document me.
+ */
+int __init
+walnut_set_rtc_time(unsigned long time)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * Document me.
+ */
+unsigned long __init
+walnut_get_rtc_time(void)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * void __init walnut_calibrate_decr()
+ *
+ * Description:
+ *   This routine retrieves the internal processor frequency from the board
+ *   information structure, sets up the kernel timer decrementer based on
+ *   that value, enables the 403 programmable interval timer (PIT) and sets
+ *   it up for auto-reload.
+ *
+ * Input(s):
+ *   N/A
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+walnut_calibrate_decr(void)
+{
+	unsigned int freq;
+	bd_t *bip = (bd_t *)__res;
+
+	freq = bip->bi_intfreq;
+
+	decrementer_count = freq / HZ;
+	count_period_num = 1;
+	count_period_den = freq;
+
+	/* Enable the PIT and set auto-reload of its value */
+
+	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+	/* Clear any pending timer interrupts */
+
+	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+}
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/kernel/walnut_setup.h linux/arch/ppc/kernel/walnut_setup.h
--- v2.3.42/linux/arch/ppc/kernel/walnut_setup.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/walnut_setup.h	Thu Feb 10 12:37:51 2000
@@ -0,0 +1,50 @@
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: walnut_setup.c
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
+ *      <dan@netx4.com>.
+ *
+ */
+
+#ifndef	__WALNUT_SETUP_H__
+#define	__WALNUT_SETUP_H__
+
+#include <asm/ptrace.h>
+#include <asm/board.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned char	 __res[sizeof(bd_t)];
+
+extern void		 walnut_init(unsigned long r3,
+				  unsigned long ird_start,
+				  unsigned long ird_end,
+				  unsigned long cline_start,
+				  unsigned long cline_end);
+extern void		 walnut_setup_arch(void);
+extern int		 walnut_setup_residual(char *buffer);
+extern void		 walnut_init_IRQ(void);
+extern int		 walnut_get_irq(struct pt_regs *regs);
+extern void		 walnut_restart(char *cmd);
+extern void		 walnut_power_off(void);
+extern void		 walnut_halt(void);
+extern void		 walnut_time_init(void);
+extern int		 walnut_set_rtc_time(unsigned long now);
+extern unsigned long	 walnut_get_rtc_time(void);
+extern void		 walnut_calibrate_decr(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WALNUT_SETUP_H__ */
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/mm/4xx_tlb.c linux/arch/ppc/mm/4xx_tlb.c
--- v2.3.42/linux/arch/ppc/mm/4xx_tlb.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/ppc/mm/4xx_tlb.c	Wed Feb  9 19:43:47 2000
@@ -1,6 +1,9 @@
 /*
  *
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *    Copyright (c) 1998-1999 TiVo, Inc.
+ *      Original implementation.
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *      Minor rework.
  *
  *    Module name: 4xx_tlb.c
  *
@@ -9,7 +12,10 @@
  *
  */
 
+#include <linux/mm.h>
+
 #include <asm/processor.h>
+#include <asm/io.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -26,372 +32,327 @@
 #endif
 
 
-/* Function Macros */
-
-
-/* Type Definitios */
-
-typedef struct pin_entry_s {
-	unsigned int	e_pinned: 1,	/* This TLB entry is pinned down. */
-			e_used: 23;	/* Number of users for this mapping. */
-} pin_entry_t;
-
-
 /* Global Variables */
 
-static pin_entry_t pin_table[PPC4XX_TLB_SIZE];
+static int pinned = 0;
 
 
 /* Function Prototypes */
 
+static int PPC4xx_tlb_miss(struct pt_regs *, unsigned long, int);
 
-void
-PPC4xx_tlb_pin(unsigned long va, unsigned long pa, int pagesz, int cache)
-{
-	int i, found = FALSE;
-	unsigned long tag, data;
-	unsigned long opid;
-
-	opid = mfspr(SPRN_PID);
-	mtspr(SPRN_PID, 0);
-
-	data = (pa & TLB_RPN_MASK) | TLB_WR;
-
-	if (cache)
-		data |= (TLB_EX | TLB_I);
-	else
-		data |= (TLB_G | TLB_I);
-
-	tag = (va & TLB_EPN_MASK) | TLB_VALID | pagesz;
-
-	for (i = 0; i < PPC4XX_TLB_SIZE; i++) {
-		if (pin_table[i].e_pinned == FALSE) {
-			found = TRUE;
-			break;
-		}
-	}
+extern void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
 
-	if (found) {
-		/* printk("Pinning %#x -> %#x in entry %d...\n", va, pa, i); */
-		asm("tlbwe %0,%1,1" : : "r" (data), "r" (i));
-		asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i));
-		asm("isync");
-		pin_table[i].e_pinned = found;
-	}
 
-	mtspr(SPRN_PID, opid);
-	return;
-}
-
-void
-PPC4xx_tlb_unpin(unsigned long va, unsigned long pa, int size)
+/*
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
+ */
+static inline void
+PPC4xx_tlb_write(unsigned long tag, unsigned long data, unsigned int index)
 {
-	/* XXX - To beimplemented. */
+	asm("tlbwe %0,%1,1" : : "r" (data), "r" (index));
+	asm("tlbwe %0,%1,0" : : "r" (tag), "r" (index));
 }
 
+/*
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
+ */
 void
-PPC4xx_tlb_flush_all(void)
+PPC4xx_flush_tlb_all(void)
 {
 	int i;
-	unsigned long flags, opid;
+	unsigned long flags, pid;
 
 	save_flags(flags);
 	cli();
 
-	opid = mfspr(SPRN_PID);
+	pid = mfspr(SPRN_PID);
 	mtspr(SPRN_PID, 0);
 
-	for (i = 0; i < PPC4XX_TLB_SIZE; i++) {
-		unsigned long ov = 0;
+	for (i = pinned; i < PPC4XX_TLB_SIZE; i++) {
+		PPC4xx_tlb_write(0, 0, i);
+	}
+	asm("sync;isync");
 
-		if (pin_table[i].e_pinned)
-			continue;
+	mtspr(SPRN_PID, pid);
+	restore_flags(flags);
+}
 
-		asm("tlbwe %0,%1,0" : : "r" (ov), "r" (i));
-		asm("tlbwe %0,%1,1" : : "r" (ov), "r" (i));
+/*
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
+ */
+void
+PPC4xx_dtlb_miss(struct pt_regs *regs)
+{
+	unsigned long addr = mfspr(SPRN_DEAR);
+	int write = mfspr(SPRN_ESR) & ESR_DST;
+
+	if (PPC4xx_tlb_miss(regs, addr, write) < 0) {
+		sti();
+		do_page_fault(regs, addr, write);
+		cli();
 	}
+	
+}
 
-	asm("sync;isync");
+/*
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
+ */
+void
+PPC4xx_itlb_miss(struct pt_regs *regs)
+{
+	unsigned long addr = regs->nip;
 
-	mtspr(SPRN_PID, opid);
-	restore_flags(flags);
+	if (PPC4xx_tlb_miss(regs, addr, 0) < 0) {
+		sti();
+		do_page_fault(regs, addr, 0);
+		cli();
+	}
 }
 
+/*
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
+ */
 void
-PPC4xx_tlb_flush(unsigned long va, int pid)
+PPC4xx_tlb_pin(unsigned long va, unsigned long pa, int pagesz, int cache)
 {
-	unsigned long i, tag, flags, found = 1, opid;
+	unsigned long tag, data;
+	unsigned long opid;
 
-	save_flags(flags);
-	cli();
+	if (pinned >= PPC4XX_TLB_SIZE)
+		return;
 
 	opid = mfspr(SPRN_PID);
-	mtspr(SPRN_PID, pid);
+	mtspr(SPRN_PID, 0);
 
-	asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (i), "=r" (found) : "r" (va));
+	data = (pa & TLB_RPN_MASK) | TLB_WR;
 
-	if (found && pin_table[i].e_pinned == 0) {
-		asm("tlbre %0,%1,0" : "=r" (tag) : "r" (i));
-		tag &= ~ TLB_VALID;
-		asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i));
-	}
+	if (cache)
+		data |= (TLB_EX);
+	else
+		data |= (TLB_G | TLB_I);
 
-	mtspr(SPRN_PID, opid);
+	tag = (va & TLB_EPN_MASK) | TLB_VALID | pagesz;
 
-	restore_flags(flags);
+	PPC4xx_tlb_write(tag, data, pinned++);
+
+	mtspr(SPRN_PID, opid);
+	return;
 }
 
-#if 0
 /*
- * TLB miss handling code.
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
  */
+void
+PPC4xx_tlb_unpin(unsigned long va, unsigned long pa, int size)
+{
+	/* XXX - To be implemented. */
+}
 
 /*
- * Handle TLB faults. We should push this back to assembly code eventually.
- * Caller is responsible for turning off interrupts ...
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
  */
 static inline void
-tlbDropin(unsigned long tlbhi, unsigned long tlblo) {
-	/*
-	 * Avoid the divide at the slight cost of a little too
-	 * much emphasis on the last few entries.
-	 */
-	unsigned long rand = mfspr(SPRN_TBLO);
-	rand &= 0x3f;
-        rand += NTLB_WIRED;
-        if (rand >= NTLB)
-		rand -= NTLB_WIRED;
-
-	asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (rand));
-	asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (rand));
-	asm("isync;sync");
-}
+PPC4xx_tlb_update(unsigned long addr, pte_t *pte)
+{
+        unsigned long data, tag, rand;
+        int i, found = 1;
 
-static inline void
-mkTlbEntry(unsigned long addr, pte_t *pte) {
-	unsigned long tlbhi;
-	unsigned long tlblo;
-	int found = 1;
-	int idx;
+        /* Construct the hardware TLB entry from the Linux-style PTE */
 
-	/*
-	 * Construct the TLB entry.
-	 */
-	tlbhi = addr & ~(PAGE_SIZE-1);
-	tlblo = virt_to_phys(pte_page(*pte)) & TLBLO_RPN;
-	if (pte_val(*pte) & _PAGE_HWWRITE)
-		tlblo |= TLBLO_WR;
-	if (pte_val(*pte) & _PAGE_NO_CACHE)
-		tlblo |= TLBLO_I;
-	tlblo |= TLBLO_EX;
-	if (addr < KERNELBASE)
-		tlblo |= TLBLO_Z_USER;
-	tlbhi |= TLBHI_PGSZ_4K;
-	tlbhi |= TLBHI_VALID;
+        tag = tag = (addr & PAGE_MASK) | TLB_VALID | TLB_PAGESZ(PAGESZ_4K);
+        data = data = (pte_val(*pte) & PAGE_MASK) | TLB_EX | TLB_WR;
 
-	/*
-	 * See if a match already exists in the TLB.
-	 */
-	asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (idx), "=r" (found) : "r" (tlbhi));
-	if (found) {
-		/*
-		 * Found an existing entry. Just reuse the index.
-		 */
-		asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (idx));
-		asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (idx));
-	}
-	else {
-		/*
-		 * Do the more expensive operation
-		 */
-		tlbDropin(tlbhi, tlblo);
-	}
-}
-
-/*
- * Mainline of the TLB miss handler. The above inline routines should fold into
- * this one, eliminating most function call overhead.
- */
-#ifdef TLBMISS_DEBUG
-volatile unsigned long miss_start;
-volatile unsigned long miss_end;
-#endif
-
-static inline int tlbMiss(struct pt_regs *regs, unsigned long badaddr, int wasWrite)
-{
-	int spid, ospid;
-	struct mm_struct *mm;
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte;
-
-	if (!user_mode(regs) && (badaddr >= KERNELBASE)) {
-		mm = task[0]->mm;
-		spid = 0;
-#ifdef TLBMISS_DEBUG
-                miss_start = 0;
-#endif
-	}
-	else {
-		mm = current->mm;
-		spid = mfspr(SPRN_PID);
-#ifdef TLBMISS_DEBUG
-                miss_start = 1;
-#endif
-	}
-#ifdef TLBMISS_DEBUG
-        store_cache_range((unsigned long)&miss_start, sizeof(miss_start));
+#if 0
+        if (pte_val(*pte) & _PAGE_HWWRITE)
+                data |= TLB_WR;
 #endif
 
-	pgd = pgd_offset(mm, badaddr);
-	if (pgd_none(*pgd))
-		goto NOGOOD;
-
-	pmd = pmd_offset(pgd, badaddr);
-	if (pmd_none(*pmd))
-		goto NOGOOD;
-
-	pte = pte_offset(pmd, badaddr);
-	if (pte_none(*pte))
-		goto NOGOOD;
-	if (!pte_present(*pte))
-		goto NOGOOD;
-#if 1
-        prohibit_if_guarded(badaddr, sizeof(int));
-#endif
-	if (wasWrite) {
-		if (!pte_write(*pte)) {
-			goto NOGOOD;
-		}
-		set_pte(pte, pte_mkdirty(*pte));
-	}
-	set_pte(pte, pte_mkyoung(*pte));
+        if (pte_val(*pte) & _PAGE_NO_CACHE)
+                data |= TLB_I;
 
-	ospid = mfspr(SPRN_PID);
-	mtspr(SPRN_PID, spid);
-	mkTlbEntry(badaddr, pte);
-	mtspr(SPRN_PID, ospid);
-
-#ifdef TLBMISS_DEBUG
-        miss_end = 0;
-        store_cache_range((unsigned long)&miss_end, sizeof(miss_end));
-#endif
-	return 0;
+        if (pte_val(*pte) & _PAGE_GUARDED)
+                data |= TLB_G;
 
-NOGOOD:
-#ifdef TLBMISS_DEBUG
-        miss_end = 1;
-        store_cache_range((unsigned long)&miss_end, sizeof(miss_end));
-#endif
-        return 1;
-}
+        if (addr < KERNELBASE)
+                data |= TLB_ZSEL(1);
 
-/*
- * End TLB miss handling code.
- */
-/* ---------- */
+        /* Attempt to match the new tag to an existing entry in the TLB. */
 
-/*
- * Used to flush the TLB if the page fault handler decides to change
- * something.
- */
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) {
-	int spid;
-	unsigned long flags;
+        asm("tlbsx. %0,0,%2;"
+	    "beq 1f;"
+	    "li %1,0;1:" : "=r" (i), "=r" (found) : "r" (tag));
 
-	save_flags(flags);
-	cli();
+	/*
+	 * If we found a match for the tag, reuse the entry index and update
+	 * the tag and data portions. Otherwise, we did not find a match. Use
+	 * the lower 5 bits of the lower time base register as a pseudo-random
+	 * index into the TLB and replace the entry at that index.
+	 */
 
-	if (addr >= KERNELBASE)
-		spid = 0;
-	else
-		spid = vma->vm_mm->context;
-	tlbFlush1(addr, spid);
+        if (found) {
+		PPC4xx_tlb_write(tag, data, i);
+        } else {
+		rand = mfspr(SPRN_TBLO) & (PPC4XX_TLB_SIZE - 1);
+		rand += pinned;
+		if (rand >= PPC4XX_TLB_SIZE)
+			rand -= pinned;
 
-	restore_flags(flags);
+		PPC4xx_tlb_write(tag, data, rand);
+		asm("isync;sync");
+        }
 }
 
 /*
- * Given a virtual address in the current address space, make
- * sure the associated physical page is present in memory,
- * and if the data is to be modified, that any copy-on-write
- * actions have taken place.
+ * ()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *
+ *
+ * Output(s):
+ *
+ *
+ * Returns:
+ *
+ *
  */
-unsigned long make_page_present(unsigned long p, int rw) {
+static int
+PPC4xx_tlb_miss(struct pt_regs *regs, unsigned long addr, int write)
+{
+        unsigned long spid, ospid;
+        struct mm_struct *mm;
+        pgd_t *pgd;
+        pmd_t *pmd;
         pte_t *pte;
-        char c;
 
-        get_user(c, (char *) p);
+        if (!user_mode(regs) && (addr >= KERNELBASE)) {
+                mm = &init_mm;
+                spid = 0;
+        } else {
+                mm = current->mm;
+                spid = mfspr(SPRN_PID);
+        }
+
+        pgd = pgd_offset(mm, addr);
+        if (pgd_none(*pgd))
+                goto bad;
+
+        pmd = pmd_offset(pgd, addr);
+        if (pmd_none(*pmd))
+                goto bad;
 
-        pte = findPTE(current->mm, p);
+        pte = pte_offset(pmd, addr);
         if (pte_none(*pte) || !pte_present(*pte))
-            debug("make_page_present didn't load page", 0);
+                goto bad;
 
-        if (rw) {
-            /*
-            * You have to write-touch the page, so that
-            * zero-filled pages are forced to be copied
-            * rather than still pointing at the zero
-            * page.
-            */
-            extern void tlbFlush1(unsigned long, int);
-            tlbFlush1(p, get_context());
-            put_user(c, (char *) p);
-            if (!pte_write(*pte))
-                debug("make_page_present didn't make page writable", 0);
+        if (write) {
+                if (!pte_write(*pte))
+                        goto bad;
 
-            tlbFlush1(p, get_context());
+                set_pte(pte, pte_mkdirty(*pte));
         }
-        return pte_page(*pte);
-}
-
-void DataTLBMissException(struct pt_regs *regs)
-{
-	unsigned long badaddr = mfspr(SPRN_DEAR);
-	int wasWrite = mfspr(SPRN_ESR) & 0x800000;
-	if (tlbMiss(regs, badaddr, wasWrite)) {
-		sti();
-		do_page_fault(regs, badaddr, wasWrite);
-		cli();
-    	}
-}
+        set_pte(pte, pte_mkyoung(*pte));
 
-void InstructionTLBMissException(struct pt_regs *regs)
-{
-	if (!current) {
-		debug("ITLB Miss with no current task", regs);
-		sti();
-		bad_page_fault(regs, regs->nip);
-		cli();
-		return;
-	}
-	if (tlbMiss(regs, regs->nip, 0)) {
-		sti();
-		do_page_fault(regs, regs->nip, 0);
-		cli();
-    	}
+        ospid = mfspr(SPRN_PID);
+        mtspr(SPRN_PID, spid);
+        PPC4xx_tlb_update(addr, pte);
+        mtspr(SPRN_PID, ospid);
+
+	return (0);
+bad:
+	return (-1);
 }
-
-void DataPageFault(struct pt_regs *regs)
-{
-	unsigned long badaddr = mfspr(SPRN_DEAR);
-	int wasWrite = mfspr(SPRN_ESR) & 0x800000;
-	sti();
-	do_page_fault(regs, badaddr, wasWrite);
-	cli();
-}
-
-void InstructionPageFault(struct pt_regs *regs)
-{
-	if (!current) {
-		debug("ITLB fault with no current task", regs);
-		sti();
-		bad_page_fault(regs, regs->nip);
-		cli();
-		return;
-	}
-	sti();
-	do_page_fault(regs, regs->nip, 0);
-	cli();
-}
-#endif
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.3.42/linux/arch/ppc/mm/init.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/ppc/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -107,7 +107,6 @@
 static void mapin_ram(void);
 void map_page(unsigned long va, unsigned long pa, int flags);
 extern void die_if_kernel(char *,struct pt_regs *,long);
-extern void show_net_buffers(void);
 
 struct mem_pieces phys_mem;
 
@@ -281,9 +280,6 @@
 	printk("%d pages swap cached\n",cached);
 	printk("%d pages in page table cache\n",(int)pgtable_cache_size);
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 	printk("%-8s %3s %8s %8s %8s %9s %8s", "Process", "Pid",
 	       "Ctx", "Ctx<<4", "Last Sys", "pc", "task");
 #ifdef __SMP__
@@ -643,7 +639,9 @@
 		wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX;
 		bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
 		bat[1].word[1] = phys | wimgxpp;
+#ifndef CONFIG_KGDB /* want user access for breakpoints */
 		if (flags & _PAGE_USER)
+#endif
 			bat[1].bat.batu.vp = 1;
 		if (flags & _PAGE_GUARDED) {
 			/* G bit must be zero in IBATs */
@@ -732,6 +730,10 @@
                          * don't get ASID compares on kernel space.
                          */
 			f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
+#ifdef CONFIG_KGDB
+ 			/* Allows stub to set breakpoints everywhere */
+ 			f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+#else
 			if ((char *) v < _stext || (char *) v >= etext)
 				f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
 #ifndef CONFIG_8xx
@@ -740,6 +742,7 @@
 				   forces R/W kernel access */
 				f |= _PAGE_USER;
 #endif /* CONFIG_8xx */
+#endif /* CONFIG_KGDB */
 			map_page(v, p, f);
 			v += PAGE_SIZE;
 			p += PAGE_SIZE;
@@ -844,6 +847,8 @@
 }
 #endif
 
+extern boot_infos_t *disp_bi;
+
 /*
  * Do very early mm setup such as finding the size of memory
  * and setting up the hash table.
@@ -855,25 +860,45 @@
 void __init
 MMU_init(void)
 {
+	/*
+	 * The Zone Protection Register (ZPR) defines how protection will
+	 * be applied to every page which is a member of a given zone. At
+	 * present, we utilize only two of the 4xx's zones. The first, zone
+	 * 0, is set at '00b and only allows access in supervisor-mode based
+	 * on the EX and WR bits. No user-mode access is allowed. The second,
+	 * zone 1, is set at '10b and in supervisor-mode allows access
+	 * without regard to the EX and WR bits. In user-mode, access is
+	 * allowed based on the EX and WR bits.
+	 */
+
+        mtspr(SPRN_ZPR, 0x2aaaaaaa);
+
+	/* Hardwire any TLB entries necessary here. */
+
 	PPC4xx_tlb_pin(KERNELBASE, 0, TLB_PAGESZ(PAGESZ_16M), 1);
-	PPC4xx_tlb_pin(OAKNET_IO_BASE, OAKNET_IO_BASE, TLB_PAGESZ(PAGESZ_4K), 0);
-        end_of_DRAM = oak_find_end_of_memory();
 
-        /* Map in all of RAM starting at KERNELBASE */
+	/*
+	 * Find the top of physical memory and map all of it in starting
+	 * at KERNELBASE.
+	 */
 
+        end_of_DRAM = oak_find_end_of_memory();
         mapin_ram();
 
-        /* Zone 0 - kernel (above 0x80000000), zone 1 - user */
+	/*
+	 * Set up the real-mode cache parameters for the exception vector
+	 * handlers (which are run in real-mode).
+	 */
 
-        mtspr(SPRN_ZPR, 0x2aaaaaaa);
-        mtspr(SPRN_DCWR, 0x00000000);	/* all caching is write-back */
+        mtspr(SPRN_DCWR, 0x00000000);	/* All caching is write-back */
 
-        /* Cache 128MB of space starting at KERNELBASE. */
+        /*
+	 * Cache instruction and data space where the exception
+	 * vectors and the kernel live in real-mode.
+	 */
 
-        mtspr(SPRN_DCCR, 0x00000000);
-        /* flush_instruction_cache(); XXX */
-        mtspr(SPRN_ICCR, 0x00000000);
-        
+        mtspr(SPRN_DCCR, 0x80000000);	/* 128 MB of data space at 0x0. */
+        mtspr(SPRN_ICCR, 0x80000000);	/* 128 MB of instr. space at 0x0. */
 }
 #else
 void __init MMU_init(void)
@@ -895,7 +920,11 @@
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
         hash_init();
+#ifdef CONFIG_PPC64
+	_SDR1 = 0;	/* temporary hack to just use bats -- Cort */
+#else	
         _SDR1 = __pa(Hash) | (Hash_mask >> 10);
+#endif	
 	ioremap_base = 0xf8000000;
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:mapin", 0x301);
@@ -916,8 +945,14 @@
 		break;
 	case _MACH_chrp:
 		setbat(0, 0xf8000000, 0xf8000000, 0x08000000, IO_PAGE);
+#ifdef CONFIG_PPC64
+		/* temporary hack to get working until page tables are stable -- Cort*/
+		setbat(1, 0x80000000, 0xc0000000, 0x10000000, IO_PAGE);
+		setbat(3, 0xd0000000, 0xd0000000, 0x10000000, IO_PAGE);
+#else
 		setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
 		setbat(3, 0x90000000, 0x90000000, 0x10000000, IO_PAGE);
+#endif		
 		break;
 	case _MACH_Pmac:
 #if 0
@@ -929,6 +964,10 @@
 			setbat(0, base, base, 0x100000, IO_PAGE);
 		}
 #endif
+#if 0
+		setbat(0, disp_bi->dispDeviceBase, disp_bi->dispDeviceBase, 0x100000, IO_PAGE);
+		disp_bi->logicalDisplayBase = disp_bi->dispDeviceBase;
+#endif		
 		ioremap_base = 0xf0000000;
 		break;
 	case _MACH_apus:
@@ -1087,6 +1126,8 @@
 
 void __init mem_init(void)
 {
+	extern char *sysmap; 
+	extern unsigned long sysmap_size;
 	unsigned long addr;
 	int codepages = 0;
 	int datapages = 0;
@@ -1116,6 +1157,11 @@
 		     addr += PAGE_SIZE)
 			SetPageReserved(mem_map + MAP_NR(addr));
 #endif /* defined(CONFIG_CHRP) || defined(CONFIG_ALL_PPC) */
+	if ( sysmap_size )
+		for (addr = (unsigned long)sysmap;
+		     addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
+		     addr += PAGE_SIZE)
+			SetPageReserved(mem_map + MAP_NR(addr));
 	
 	for (addr = PAGE_OFFSET; addr < (unsigned long)end_of_DRAM;
 	     addr += PAGE_SIZE) {
@@ -1131,10 +1177,8 @@
 	}
 
         printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n",
-	       (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
-	       codepages << (PAGE_SHIFT-10),
-	       datapages << (PAGE_SHIFT-10), 
-	       initpages << (PAGE_SHIFT-10),
+	       (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
+	       codepages, datapages, initpages,
 	       PAGE_OFFSET, (unsigned long) end_of_DRAM);
 	mem_init_done = 1;
 }
@@ -1153,7 +1197,7 @@
 	unsigned long a, total;
 	
 	/* max amount of RAM we allow -- Cort */
-#define RAM_LIMIT (768<<20)
+#define RAM_LIMIT (64<<20)
 
 	memory_node = find_devices("memory");
 	if (memory_node == NULL) {
@@ -1384,7 +1428,7 @@
 	{
 		if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
 		Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
-		__clear_user(Hash, Hash_size);
+		/*__clear_user(Hash, Hash_size);*/
 
 		/*
 		 * Patch up the instructions in head.S:hash_page
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c
--- v2.3.42/linux/arch/ppc/xmon/start.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/ppc/xmon/start.c	Wed Feb  9 19:43:47 2000
@@ -8,19 +8,34 @@
 #include <asm/page.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#include <linux/kernel.h>
 #include <asm/prom.h>
 #include <asm/bootx.h>
+#include <asm/feature.h>
 #include <asm/processor.h>
 
 static volatile unsigned char *sccc, *sccd;
 unsigned long TXRDY, RXRDY;
 extern void xmon_printf(const char *fmt, ...);
-extern void map_bootx_text(void);
 extern void drawchar(char);
 extern void drawstring(const char *str);
+static int xmon_expect(const char *str, unsigned int timeout);
 
 static int console = 0;
 static int use_screen = 0;
+static int via_modem = 0;
+static int xmon_use_sccb = 0;
+static struct device_node *macio_node;
+
+#define TB_SPEED	25000000
+
+static inline unsigned int readtb(void)
+{
+	unsigned int ret;
+
+	asm volatile("mftb %0" : "=r" (ret) :);
+	return ret;
+}
 
 void buf_access(void)
 {
@@ -36,17 +51,19 @@
 	if ( _machine == _MACH_Pmac )
 	{
 		struct device_node *np;
-		extern boot_infos_t *boot_infos;
 		unsigned long addr;
-
 #ifdef CONFIG_BOOTX_TEXT
-		if (boot_infos != 0 && find_via_pmu()) {
-			printk("xmon uses screen and keyboard\n");
+		extern boot_infos_t *disp_bi;
+
+		/* needs to be hacked if xmon_printk is to be used
+ 		   from within find_via_pmu() */
+		if (!via_modem && disp_bi && find_via_pmu()) {
+			drawstring("xmon uses screen and keyboard\n");
 			use_screen = 1;
-			map_bootx_text();
 			return;
 		}
 #endif
+
 #ifdef CHRP_ESCC
 		addr = 0xc1013020;
 #else
@@ -57,9 +74,10 @@
 		
 		np = find_devices("mac-io");
 		if (np && np->n_addrs) {
+			macio_node = np;
 			addr = np->addrs[0].address + 0x13000;
-			/* use the B channel on the iMac, A channel on others */
-			if (addr >= 0xf0000000)
+			/* use the B channel on the iMac */
+			if (!xmon_use_sccb)
 				addr += 0x20; /* use A channel */
 		}
 		base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
@@ -70,22 +88,22 @@
 		sccd = sccc + (0xf3013030 - 0xf3013020);
 #endif
 	}
-	else if ( _machine & _MACH_chrp )
+	else if ( _machine & _MACH_gemini )
 	{
 		/* should already be mapped by the kernel boot */
-		sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
-		sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
+		sccc = (volatile unsigned char *) 0xffeffb0d;
+		sccd = (volatile unsigned char *) 0xffeffb08;
 		TXRDY = 0x20;
 		RXRDY = 1;
+		console = 1;
 	}
-	else if ( _machine & _MACH_gemini )
+	else
 	{
 		/* should already be mapped by the kernel boot */
-		sccc = (volatile unsigned char *) 0xffeffb0d;
-		sccd = (volatile unsigned char *) 0xffeffb08;
+		sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
+		sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
 		TXRDY = 0x20;
 		RXRDY = 1;
-		console = 1;
 	}
 }
 
@@ -98,7 +116,7 @@
 xmon_write(void *handle, void *ptr, int nb)
 {
     char *p = ptr;
-    int i, ct;
+    int i, c, ct;
 
 #ifdef CONFIG_BOOTX_TEXT
     if (use_screen) {
@@ -111,20 +129,26 @@
     if (!scc_initialized)
 	xmon_init_scc();
     for (i = 0; i < nb; ++i) {
-#ifdef CONFIG_ADB	    
+    ct = 0;
 	while ((*sccc & TXRDY) == 0)
+#ifdef CONFIG_ADB	    
 	    if (sys_ctrler == SYS_CTRLER_PMU)
 		pmu_poll();
+#else
+		;
 #endif /* CONFIG_ADB */
-	buf_access();
-	if ( console && (*p != '\r'))
-		printk("%c", *p);
-	ct = 0;
-	if ( *p == '\n')
+	c = p[i];
+	if (c == '\n' && !ct) {
+	    c = '\r';
 		ct = 1;
-	*sccd = *p++;
-	if ( ct )
-		xmon_write(handle, "\r", 1);
+	    --i;
+	} else {
+	    if (console)
+		printk("%c", c);
+	    ct = 0;
+	}
+	buf_access();
+	*sccd = c;
     }
     return i;
 }
@@ -206,36 +230,49 @@
     if (!scc_initialized)
 	xmon_init_scc();
     for (i = 0; i < nb; ++i) {
-#ifdef CONFIG_ADB	    
 	while ((*sccc & RXRDY) == 0)
+#ifdef CONFIG_ADB	    
 	    if (sys_ctrler == SYS_CTRLER_PMU)
 		pmu_poll();
+#else
+		;
 #endif /* CONFIG_ADB */
 	buf_access();
-#if 0	
-	if ( 0/*console*/ )
-		*p++ = ppc_md.kbd_getkeycode();
-	else
-#endif		
 		*p++ = *sccd;
     }
     return i;
 }
 
+int
+xmon_read_poll(void)
+{
+	if ((*sccc & RXRDY) == 0) {
+#ifdef CONFIG_ADB	    
+		if (sys_ctrler == SYS_CTRLER_PMU)
+			pmu_poll();
+#else
+			;
+#endif			
+		return -1;
+	}
+	buf_access();
+	return *sccd;
+}
+
 static unsigned char scc_inittab[] = {
     13, 0,		/* set baud rate divisor */
     12, 1,
     14, 1,		/* baud rate gen enable, src=rtxc */
     11, 0x50,		/* clocks = br gen */
-    5,  0x6a,		/* tx 8 bits, assert RTS */
-    4,  0x44,		/* x16 clock, 1 stop */
+    5,  0xea,		/* tx 8 bits, assert DTR & RTS */
+    4,  0x46,		/* x16 clock, 1 stop */
     3,  0xc1,		/* rx enable, 8 bits */
 };
 
 void
 xmon_init_scc()
 {
-	if ( _machine & (_MACH_chrp|_MACH_gemini) )
+	if ( _machine == _MACH_chrp )
 	{
 		sccd[3] = 0x83; eieio();	/* LCR = 8N1 + DLAB */
 		sccd[0] = 3; eieio();		/* DLL = 38400 baud */
@@ -248,6 +285,14 @@
 	{
 		int i, x;
 
+		if (macio_node != 0) {
+			unsigned int t0;
+
+			feature_set(macio_node, FEATURE_Modem_power);
+			t0 = readtb();
+			while (readtb() - t0 < 3*TB_SPEED)
+				eieio();
+		}
 		for (i = 20000; i != 0; --i) {
 			x = *sccc; eieio();
 		}
@@ -259,6 +304,18 @@
 		}
 	}
 	scc_initialized = 1;
+	if (via_modem) {
+		for (;;) {
+			xmon_write(0, "ATE1V1\r", 7);
+			if (xmon_expect("OK", 5)) {
+				xmon_write(0, "ATA\r", 4);
+				if (xmon_expect("CONNECT", 40))
+					break;
+			}
+			xmon_write(0, "+++", 3);
+			xmon_expect("OK", 3);
+		}
+	}
 }
 
 #if 0
@@ -330,6 +387,35 @@
 static char line[256];
 static char *lineptr;
 static int lineleft;
+
+int xmon_expect(const char *str, unsigned int timeout)
+{
+	int c;
+	unsigned int t0;
+
+	timeout *= TB_SPEED;
+	t0 = readtb();
+	do {
+		lineptr = line;
+		for (;;) {
+			c = xmon_read_poll();
+			if (c == -1) {
+				if (readtb() - t0 > timeout) {
+					printk("timeout\n");
+					return 0;
+				}
+				continue;
+			}
+			if (c == '\n')
+				break;
+			printk("%c", c);
+			if (c != '\r' && lineptr < &line[sizeof(line) - 1])
+				*lineptr++ = c;
+		}
+		*lineptr = 0;
+	} while (strstr(line, str) == NULL);
+	return 1;
+}
 
 int
 xmon_getchar(void)
diff -u --recursive --new-file v2.3.42/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.3.42/linux/arch/ppc/xmon/xmon.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/ppc/xmon/xmon.c	Wed Feb  9 19:43:47 2000
@@ -1344,3 +1344,31 @@
 {
 	lineptr = str;
 }
+
+char last[64];
+char *
+lookup_addr(unsigned long addr)
+{
+	extern char *sysmap;
+	extern unsigned long sysmap_size;
+	char *c = sysmap;
+	unsigned long cmp;
+
+	if ( !sysmap || !sysmap_size )
+		return NULL;
+	
+	/* adjust if addr is relative to kernelbase */
+	if ( addr < PAGE_OFFSET )
+		addr += PAGE_OFFSET;
+
+	cmp = simple_strtoul(c, &c, 8);
+	strcpy( last, strsep( &c, "\n"));
+	while ( c < (sysmap+sysmap_size) )
+	{
+		cmp = simple_strtoul(c, &c, 8);
+		if ( cmp < addr )
+			break;
+		strcpy( last, strsep( &c, "\n"));
+	}
+	return last;
+}
diff -u --recursive --new-file v2.3.42/linux/arch/sh/mm/init.c linux/arch/sh/mm/init.c
--- v2.3.42/linux/arch/sh/mm/init.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/sh/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -41,7 +41,6 @@
 static unsigned long totalram_pages = 0;
 static unsigned long totalhigh_pages = 0;
 
-extern void show_net_buffers(void);
 extern unsigned long init_smp_mappings(unsigned long);
 
 /*
@@ -173,9 +172,6 @@
 	printk("%d pages swap cached\n",cached);
 	printk("%ld pages in page table cache\n",pgtable_cache_size);
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 }
 
 /* References to section boundaries */
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.3.42/linux/arch/sparc/config.in	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/config.in	Thu Feb 10 12:16:37 2000
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.84 2000/01/31 21:10:04 davem Exp $
+# $Id: config.in,v 1.86 2000/02/10 02:51:10 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -21,7 +21,7 @@
 
 bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
 if [ "$CONFIG_SUN4" != "y" ]; then
-   bool '  Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
+   bool 'Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
    source drivers/pci/Config.in
 fi
 
@@ -118,11 +118,24 @@
    comment 'SCSI support type (disk, tape, CDrom)'
 
    dep_tristate '  SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+
+   if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+      int  'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+   fi
+
    dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+
+   if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+      int  'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
+   fi
+
    dep_tristate '  SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+
    if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
       bool '    Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+      int  'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
    fi
+
    dep_tristate '  SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
 
    comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
@@ -130,6 +143,7 @@
    bool '  Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
 
    bool '  Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+   bool '  SCSI logging facility' CONFIG_SCSI_LOGGING
 
    mainmenu_option next_comment
    comment 'SCSI low-level drivers'
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.3.42/linux/arch/sparc/defconfig	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/defconfig	Thu Feb 10 12:16:37 2000
@@ -175,9 +175,12 @@
 # SCSI support type (disk, tape, CDrom)
 #
 CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=m
 
 #
@@ -185,6 +188,7 @@
 #
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
 
 #
 # SCSI low-level drivers
@@ -245,7 +249,6 @@
 CONFIG_AFFS_FS=m
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_BFS_FS_WRITE is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c
--- v2.3.42/linux/arch/sparc/kernel/ioport.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/kernel/ioport.c	Tue Feb  8 18:23:13 2000
@@ -1,10 +1,28 @@
-/* $Id: ioport.c,v 1.30 2000/01/28 13:41:55 jj Exp $
+/* $Id: ioport.c,v 1.31 2000/02/06 22:55:32 zaitcev Exp $
  * ioport.c:  Simple io mapping allocator.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
  *
  * 1996: sparc_free_io, 1999: ioremap()/iounmap() by Pete Zaitcev.
+ *
+ * 2000/01/29
+ * <rth> zait: as long as pci_alloc_consistent produces something addressable, 
+ *	things are ok.
+ * <zaitcev> rth: no, it is relevant, because get_free_pages returns you a
+ *	pointer into the big page mapping
+ * <rth> zait: so what?
+ * <rth> zait: remap_it_my_way(virt_to_phys(get_free_page()))
+ * <zaitcev> Hmm
+ * <zaitcev> Suppose I did this remap_it_my_way(virt_to_phys(get_free_page())).
+ *	So far so good.
+ * <zaitcev> Now, driver calls pci_free_consistent(with result of
+ *	remap_it_my_way()).
+ * <zaitcev> How do you find the address to pass to free_pages()?
+ * <rth> zait: walk the page tables?  It's only two or three level after all.
+ * <rth> zait: you have to walk them anyway to remove the mapping.
+ * <zaitcev> Hmm
+ * <zaitcev> Sounds reasonable
  */
 
 #include <linux/config.h>
@@ -15,6 +33,8 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/pci.h>		/* struct pci_dev */
+#include <linux/proc_fs.h>
 
 #include <asm/io.h>
 #include <asm/vaddrs.h>
@@ -23,8 +43,8 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 
-struct resource *sparc_find_resource_bystart(struct resource *, unsigned long);
-struct resource *sparc_find_resource_by_hit(struct resource *, unsigned long);
+struct resource *_sparc_find_resource(struct resource *r, unsigned long);
+int _sparc_len2order(unsigned long len);
 
 static void *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
 static void *_sparc_alloc_io(unsigned int busno, unsigned long phys,
@@ -32,15 +52,22 @@
 static void _sparc_free_io(struct resource *res);
 
 /* This points to the next to use virtual memory for DVMA mappings */
-static struct resource sparc_dvma = {
+static struct resource _sparc_dvma = {
 	"sparc_dvma", DVMA_VADDR, DVMA_VADDR + DVMA_LEN - 1
 };
 /* This points to the start of I/O mappings, cluable from outside. */
-       struct resource sparc_iomap = {
+/*ext*/ struct resource sparc_iomap = {
 	"sparc_iomap", IOBASE_VADDR, IOBASE_END-1
 };
 
 /*
+ * BTFIXUP would do as well but it seems overkill for the case.
+ */
+static void (*_sparc_mapioaddr)(unsigned long pa, unsigned long va,
+    int bus, int ro);
+static void (*_sparc_unmapioaddr)(unsigned long va);
+
+/*
  * Our mini-allocator...
  * Boy this is gross! We need it because we must map I/O for
  * timers and interrupt controller before the kmalloc is available.
@@ -77,55 +104,6 @@
 }
 
 /*
- */
-extern void sun4c_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
-extern void srmmu_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
-
-static void mapioaddr(unsigned long physaddr, unsigned long virt_addr,
-				 int bus, int rdonly)
-{
-	switch(sparc_cpu_model) {
-	case sun4c:
-	case sun4:
-		sun4c_mapioaddr(physaddr, virt_addr, bus, rdonly);
-		break;
-	case sun4m:
-	case sun4d:
-	case sun4e:
-		srmmu_mapioaddr(physaddr, virt_addr, bus, rdonly);
-		break;
-	default:
-		printk("mapioaddr: Trying to map IO space for unsupported machine.\n");
-		printk("mapioaddr: sparc_cpu_model = %d\n", sparc_cpu_model);
-		printk("mapioaddr: Halting...\n");
-		halt();
-	};
-	return;
-}
-
-extern void srmmu_unmapioaddr(unsigned long virt);
-extern void sun4c_unmapioaddr(unsigned long virt);
-
-static void unmapioaddr(unsigned long virt_addr)
-{
-	switch(sparc_cpu_model) {
-	case sun4c:
-	case sun4:
-		sun4c_unmapioaddr(virt_addr);
-		break;
-	case sun4m:
-	case sun4d:
-	case sun4e:
-		srmmu_unmapioaddr(virt_addr);
-		break;
-	default:
-		printk("unmapioaddr: sparc_cpu_model = %d, halt...\n", sparc_cpu_model);
-		halt();
-	};
-	return;
-}
-
-/*
  * These are typically used in PCI drivers
  * which are trying to be cross-platform.
  *
@@ -147,7 +125,7 @@
 	unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
 	struct resource *res;
 
-	if ((res = sparc_find_resource_bystart(&sparc_iomap, vaddr)) == NULL) {
+	if ((res = _sparc_find_resource(&sparc_iomap, vaddr)) == NULL) {
 		printk("free_io/iounmap: cannot free %lx\n", vaddr);
 		return;
 	}
@@ -161,7 +139,6 @@
 }
 
 /*
- * Davem's version of sbus_ioremap.
  */
 unsigned long sbus_ioremap(struct resource *phyres, unsigned long offset,
     unsigned long size, char *name)
@@ -218,8 +195,6 @@
 }
 
 /*
- * This is called from _sparc_alloc_io only, we left it separate
- * in case Davem changes his mind about interface to sbus_ioremap().
  */
 static void *
 _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
@@ -240,7 +215,7 @@
 	va = res->start;
 	pa &= PAGE_MASK;
 	for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) {
-		mapioaddr(pa, va, bus, 0);
+		(*_sparc_mapioaddr)(pa, va, bus, 0);
 		va += PAGE_SIZE;
 		pa += PAGE_SIZE;
 	}
@@ -270,7 +245,7 @@
 	plen = res->end - res->start + 1;
 	while (plen != 0) {
 		plen -= PAGE_SIZE;
-		unmapioaddr(res->start + plen);
+		(*_sparc_unmapioaddr)(res->start + plen);
 	}
 
 	release_resource(res);
@@ -305,9 +280,7 @@
 		return NULL;
 	}
 
-	for (order = 0; order < 6; order++)	/* 2^6 pages == 256K */
-		if ((1 << (order + PAGE_SHIFT)) >= len_total)
-			break;
+	order = _sparc_len2order(len_total);
 	va = __get_free_pages(GFP_KERNEL, order);
 	if (va == 0) {
 		/*
@@ -324,25 +297,17 @@
 	}
 	memset((char*)res, 0, sizeof(struct resource));
 
-	if (allocate_resource(&sparc_dvma, res, len_total,
-	    sparc_dvma.start, sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+	if (allocate_resource(&_sparc_dvma, res, len_total,
+	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
 		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
 		free_pages(va, order);
 		kfree(res);
 		return NULL;
 	}
 
-	*dma_addrp = res->start;
 	mmu_map_dma_area(va, res->start, len_total);
 
-	/*
-	 * "Official" or "natural" address of pages we got is va.
-	 * We want to return uncached range. We could make va[len]
-	 * uncached but it's difficult to make cached back [P3: hmm]
-	 * We use the artefact of sun4c, replicated everywhere else,
-	 * that CPU can use bus addresses to access the same memory.
-	 */
-	res->name = (void *)va;	/* XXX Ouch.. we got to hide it somewhere */
+	*dma_addrp = res->start;
 	return (void *)res->start;
 }
 
@@ -350,9 +315,8 @@
 {
 	struct resource *res;
 	unsigned long pgp;
-	int order;
 
-	if ((res = sparc_find_resource_bystart(&sparc_dvma,
+	if ((res = _sparc_find_resource(&_sparc_dvma,
 	    (unsigned long)p)) == NULL) {
 		printk("sbus_free_consistent: cannot free %p\n", p);
 		return;
@@ -370,17 +334,14 @@
 		return;
 	}
 
-	mmu_inval_dma_area((unsigned long)res->name, n);	/* XXX Ouch */
-	mmu_unmap_dma_area(ba, n);
 	release_resource(res);
+	kfree(res);
 
-	pgp = (unsigned long) res->name;	/* XXX Ouch */
-	for (order = 0; order < 6; order++)
-		if ((1 << (order + PAGE_SHIFT)) >= n)
-			break;
-	free_pages(pgp, order);
+	/* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */
+	pgp = (unsigned long) phys_to_virt(mmu_translate_dvma(ba));
+	mmu_unmap_dma_area(ba, n);
 
-	kfree(res);
+	free_pages(pgp, _sparc_len2order(n));
 }
 
 /*
@@ -408,10 +369,10 @@
 		return 0;
 	}
 	memset((char*)res, 0, sizeof(struct resource));
-	res->name = va;
+	res->name = va; /* XXX */
 
-	if (allocate_resource(&sparc_dvma, res, len_total,
-	    sparc_dvma.start, sparc_dvma.end, PAGE_SIZE) != 0) {
+	if (allocate_resource(&_sparc_dvma, res, len_total,
+	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE) != 0) {
 		printk("sbus_map_single: cannot occupy 0x%lx", len);
 		kfree(res);
 		return 0;
@@ -431,7 +392,6 @@
 	if (len > 256*1024) {			/* __get_free_pages() limit */
 		return 0;
 	}
-/* BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus) */
 	return mmu_get_scsi_one(va, len, sdev->bus);
 #endif
 }
@@ -442,7 +402,7 @@
 	struct resource *res;
 	unsigned long va;
 
-	if ((res = sparc_find_resource_bystart(&sparc_dvma, ba)) == NULL) {
+	if ((res = _sparc_find_resource(&_sparc_dvma, ba)) == NULL) {
 		printk("sbus_unmap_single: cannot find %08x\n", (unsigned)ba);
 		return;
 	}
@@ -461,14 +421,12 @@
 	kfree(res);
 #endif
 #if 1 /* "trampoline" version */
-/* BTFIXUPDEF_CALL(void,  mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus) */
 	mmu_release_scsi_one(ba, n, sdev->bus);
 #endif
 }
 
 int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
 {
-/* BTFIXUPDEF_CALL(void,  mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) */
 	mmu_get_scsi_sgl(sg, n, sdev->bus);
 
 	/*
@@ -480,65 +438,351 @@
 
 void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
 {
-/* BTFIXUPDEF_CALL(void,  mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) */
 	mmu_release_scsi_sgl(sg, n, sdev->bus);
 }
-#endif
 
 /*
- * P3: I think a partial flush is permitted...
- * We are not too efficient at doing it though.
- *
- * If only DaveM understood a concept of an allocation cookie,
- * we could avoid find_resource_by_hit() here and a major
- * performance hit.
  */
 void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size)
 {
 	unsigned long va;
 	struct resource *res;
 
-	res = sparc_find_resource_by_hit(&sparc_dvma, ba);
+	/* We do not need the resource, just print a message if invalid. */
+	res = _sparc_find_resource(&_sparc_dvma, ba);
 	if (res == NULL)
 		panic("sbus_dma_sync_single: 0x%x\n", ba);
 
-	va = (unsigned long) res->name;
-	/* if (va == 0) */
-
-	mmu_inval_dma_area(va, (res->end - res->start) + 1);
+	va = (unsigned long) phys_to_virt(mmu_translate_dvma(ba));
+	mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK);
 }
 
 void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
 {
-	printk("dma_sync_sg: not implemented yet\n");
+	printk("sbus_dma_sync_sg: not implemented yet\n");
+}
+#endif /* CONFIG_SBUS */
+
+#ifdef CONFIG_PCI
+
+/* Allocate and map kernel buffer using consistent mode DMA for a device.
+ * hwdev should be valid struct pci_dev pointer for PCI devices.
+ */
+void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
+{
+	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
+	unsigned long va;
+	struct resource *res;
+	int order;
+
+	if (len == 0) {
+		return NULL;
+	}
+	if (len > 256*1024) {			/* __get_free_pages() limit */
+		return NULL;
+	}
+
+	order = _sparc_len2order(len_total);
+	va = __get_free_pages(GFP_KERNEL, order);
+	if (va == 0) {
+		printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT);
+		return NULL;
+	}
+
+	if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
+		free_pages(va, order);
+		printk("sbus_alloc_consistent: no core\n");
+		return NULL;
+	}
+	memset((char*)res, 0, sizeof(struct resource));
+
+	if (allocate_resource(&_sparc_dvma, res, len_total,
+	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
+		free_pages(va, order);
+		kfree(res);
+		return NULL;
+	}
+
+	mmu_inval_dma_area(va, len_total);
+
+#if 1
+/* P3 */ printk("pci_alloc_consistent: kva %lx uncva %lx phys %lx size %x\n",
+  (long)va, (long)res->start, (long)virt_to_phys(va), len_total);
+#endif
+	{
+		unsigned long xva, xpa;
+		xva = res->start;
+		xpa = virt_to_phys(va);
+		while (len_total != 0) {
+			len_total -= PAGE_SIZE;
+			(*_sparc_mapioaddr)(xpa, xva, 0, 0);
+			xva += PAGE_SIZE;
+			xpa += PAGE_SIZE;
+		}
+	}
+
+	*pba = virt_to_bus(va);
+	return (void *) res->start;
 }
 
+/* Free and unmap a consistent DMA buffer.
+ * cpu_addr is what was returned from pci_alloc_consistent,
+ * size must be the same as what as passed into pci_alloc_consistent,
+ * and likewise dma_addr must be the same as what *dma_addrp was set to.
+ *
+ * References to the memory and mappings assosciated with cpu_addr/dma_addr
+ * past this call are illegal.
+ */
+void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
+{
+	struct resource *res;
+	unsigned long pgp;
+
+	if ((res = _sparc_find_resource(&_sparc_dvma,
+	    (unsigned long)p)) == NULL) {
+		printk("sbus_free_consistent: cannot free %p\n", p);
+		return;
+	}
+
+	if (((unsigned long)p & (PAGE_MASK-1)) != 0) {
+		printk("sbus_free_consistent: unaligned va %p\n", p);
+		return;
+	}
+
+	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	if ((res->end-res->start)+1 != n) {
+		printk("sbus_free_consistent: region 0x%lx asked 0x%lx\n",
+		    (long)((res->end-res->start)+1), (long)n);
+		return;
+	}
+
+	pgp = (unsigned long) bus_to_virt(ba);
+	mmu_inval_dma_area(pgp, n);
+	{
+		int x;
+		for (x = 0; x < n; x += PAGE_SIZE) {
+			(*_sparc_unmapioaddr)(p + n);
+		}
+	}
+
+	release_resource(res);
+	kfree(res);
+
+	free_pages(pgp, _sparc_len2order(n));
+}
+
+/* Map a single buffer of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory
+ * until either pci_unmap_single or pci_dma_sync_single is performed.
+ */
+dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size)
+{
+	return virt_to_bus(ptr);
+}
+
+/* Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guarenteed to see
+ * whatever the device wrote there.
+ */
+void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size)
+{
+	/* Nothing to do... */
+}
+
+/* Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+{
+	int n;
+	for (n = 0; n < nents; n++) {
+		sg->dvma_address = virt_to_bus(sg->address);
+		sg->dvma_length = sg->length;
+		sg++;
+	}
+	return nents;
+}
+
+/* Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents)
+{
+	/* Nothing to do... */
+}
+
+/* Make physical memory consistent for a single
+ * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, the
+ * device again owns the buffer.
+ */
+void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size)
+{
+	mmu_inval_dma_area((unsigned long)bus_to_virt(ba),
+	    (size + PAGE_SIZE-1) & PAGE_MASK);
+}
+
+/* Make physical memory consistent for a set of streaming
+ * mode DMA translations after a transfer.
+ *
+ * The same as pci_dma_sync_single but for a scatter-gather list,
+ * same rules and usage.
+ */
+void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+{
+	while (nents) {
+		--nents;
+		mmu_inval_dma_area((unsigned long)sg->address,
+		    (sg->dvma_length + PAGE_SIZE-1) & PAGE_MASK);
+		sg++;
+	}
+}
+#endif CONFIG_PCI
+
+#ifdef CONFIG_PROC_FS
+
+static int
+_sparc_io_get_info(char *buf, char **start, off_t fpos, int length, int *eof,
+    void *data)
+{
+	char *p = buf, *e = buf + length;
+	struct resource *r;
+	const char *nm;
+
+	for (r = ((struct resource *)data)->child; r != NULL; r = r->sibling) {
+		if (p + 32 >= e)	/* Better than nothing */
+			break;
+		if ((nm = r->name) == 0) nm = "???";
+		p += sprintf(p, "%08lx-%08lx: %s\n", r->start, r->end, nm);
+	}
+
+	return p-buf;
+}
+
+static struct proc_dir_entry _sparc_iomap_proc_entry = {
+	0,                      /* Inode number - dynamic */
+	6,                      /* Length of the file name */
+	"io_map",		/* The file name */
+	S_IFREG | S_IRUGO,      /* File mode */
+	1,                      /* Number of links */
+	0, 0,                   /* The uid and gid for the file */
+	0,                      /* The size of the file reported by ls. */
+	NULL,                   /* struct inode_operations * ops */
+	NULL,			/* get_info: backward compatibility */
+	NULL,			/* owner */
+	NULL, NULL, NULL,	/* linkage */
+	&sparc_iomap,
+	_sparc_io_get_info,	/* The read function for this file */
+	NULL,
+	/* and more stuff */
+};
+
+static struct proc_dir_entry _sparc_dvma_proc_entry = {
+	0,                      /* Inode number - dynamic */
+	8,			/* Length of the file name */
+	"dvma_map",		/* The file name */
+	S_IFREG | S_IRUGO,      /* File mode */
+	1,                      /* Number of links */
+	0, 0,                   /* The uid and gid for the file */
+	0,                      /* The size of the file reported by ls. */
+	NULL,                   /* struct inode_operations * ops */
+	NULL,			/* get_info: backward compatibility */
+	NULL,			/* owner */
+	NULL, NULL, NULL,	/* linkage */
+	&_sparc_dvma,
+	_sparc_io_get_info,
+	NULL,
+	/* some more stuff */
+};
+
+#endif CONFIG_PROC_FS
+
 /*
  * This is a version of find_resource and it belongs to kernel/resource.c.
  * Until we have agreement with Linus and Martin, it lingers here.
  *
- * "same start" is more strict than "hit into"
+ * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
+ * This probably warrants some sort of hashing.
  */
 struct resource *
-sparc_find_resource_bystart(struct resource *root, unsigned long start)
+_sparc_find_resource(struct resource *root, unsigned long hit)
 {
         struct resource *tmp;
 
-        for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
-                if (tmp->start == start)
+	for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
+		if (tmp->start <= hit && tmp->end >= hit)
 			return tmp;
-        }
-        return NULL;
+	}
+	return NULL;
 }
 
-struct resource *
-sparc_find_resource_by_hit(struct resource *root, unsigned long hit)
+int
+_sparc_len2order(unsigned long len)
 {
-        struct resource *tmp;
+	int order;
 
-        for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
-                if (tmp->start <= hit && tmp->end >= hit)
-			return tmp;
-        }
-        return NULL;
+	for (order = 0; order < 7; order++)	/* 2^6 pages == 256K */
+		if ((1 << (order + PAGE_SHIFT)) >= len)
+			return order;
+	printk("len2order: from %p: len %lu(0x%lx) yields order >=7.\n",
+	    __builtin_return_address(0), len, len);
+	return 1;
+}
+
+/*
+ * Necessary boot time initializations.
+ */
+
+void ioport_init(void)
+{
+	extern void sun4c_mapioaddr(unsigned long, unsigned long, int, int);
+	extern void srmmu_mapioaddr(unsigned long, unsigned long, int, int);
+	extern void sun4c_unmapioaddr(unsigned long);
+	extern void srmmu_unmapioaddr(unsigned long);
+
+	switch(sparc_cpu_model) {
+	case sun4c:
+	case sun4:
+	case sun4e:
+		_sparc_mapioaddr = sun4c_mapioaddr;
+		_sparc_unmapioaddr = sun4c_unmapioaddr;
+		break;
+	case sun4m:
+	case sun4d:
+		_sparc_mapioaddr = srmmu_mapioaddr;
+		_sparc_unmapioaddr = srmmu_unmapioaddr;
+		break;
+	default:
+		printk("ioport_init: cpu type %d is unknown.\n",
+		    sparc_cpu_model);
+		halt();
+	};
+
+#ifdef CONFIG_PROC_FS
+	proc_register(&proc_root, &_sparc_iomap_proc_entry);
+	proc_register(&proc_root, &_sparc_dvma_proc_entry);
+#endif
 }
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.3.42/linux/arch/sparc/kernel/irq.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/kernel/irq.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.100 2000/01/29 01:38:04 anton Exp $
+/*  $Id: irq.c,v 1.101 2000/02/09 11:15:03 davem Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
@@ -205,9 +205,6 @@
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 
-atomic_t global_bh_lock = ATOMIC_INIT(0);
-spinlock_t global_bh_count = SPIN_LOCK_UNLOCKED;
-
 /* Who has global_irq_lock. */
 unsigned char global_irq_holder = NO_PROC_ID;
 
@@ -217,9 +214,6 @@
 /* Global IRQ locking depth. */
 atomic_t global_irq_count = ATOMIC_INIT(0);
 
-/* This protects BH software state (masks, things like that). */
-spinlock_t sparc_bh_lock = SPIN_LOCK_UNLOCKED;
-
 void smp_show_backtrace_all_cpus(void);
 void show_backtrace(void);
 
@@ -239,7 +233,7 @@
 	}
 	printk("]\n");
 
-	printk("bh:   %d [ ", (spin_is_locked(&global_bh_count) ? 1 : 0));
+	printk("bh:   %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0));
 
 	for (i = 0; i < NR_CPUS; i++) {
 		printk("%d ", local_bh_count[cpu]);
@@ -253,18 +247,6 @@
 #endif
 }
 
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if(!--count) {
-			show("wait_on_bh");
-			count = 0;
-		}
-		barrier();
-	} while(spin_is_locked(&global_bh_count));
-}
-
 /*
  * We have to allow irqs to arrive between __sti and __cli
  */
@@ -281,7 +263,7 @@
 		 * already executing in one..
 		 */
 		if (!atomic_read(&global_irq_count)) {
-			if (local_bh_count[cpu] || !spin_is_locked(&global_bh_count))
+			if (local_bh_count[cpu] || !spin_is_locked(&global_bh_lock))
 				break;
 		}
 
@@ -300,26 +282,12 @@
 				continue;
 			if (spin_is_locked (&global_irq_lock))
 				continue;
-			if (!local_bh_count[cpu] && spin_is_locked(&global_bh_count))
+			if (!local_bh_count[cpu] && spin_is_locked(&global_bh_lock))
 				continue;
 			if (spin_trylock(&global_irq_lock))
 				break;
 		}
 	}
-}
-
-/*
- * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler. 
- */
-void synchronize_bh(void)
-{
-        if (spin_is_locked (&global_bh_count) && !in_interrupt())
-                wait_on_bh();
 }
 
 /*
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S
--- v2.3.42/linux/arch/sparc/kernel/rtrap.S	Tue Jan 11 22:31:38 2000
+++ linux/arch/sparc/kernel/rtrap.S	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.53 2000/01/08 16:38:18 anton Exp $
+/* $Id: rtrap.S,v 1.54 2000/02/09 11:15:03 davem Exp $
  * rtrap.S: Return from Sparc trap low-level code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -48,16 +48,18 @@
 	.globl	rtrap_patch3, rtrap_patch4, rtrap_patch5
 	.globl	C_LABEL(ret_trap_lockless_ipi)
 ret_trap_entry:
-	sethi	%hi(C_LABEL(bh_active)), %l3
-	sethi	%hi(C_LABEL(bh_mask)), %l4
-	ld	[%l4 + %lo(C_LABEL(bh_mask))], %g5
-	ld	[%l3 + %lo(C_LABEL(bh_active))], %g4
+	ld	[%curptr + AOFF_task_processor], %l3
+	sll	%l3, 5, %l3
+	sethi	%hi(C_LABEL(softirq_state)), %l4
+	add	%l4, %l3, %l4
+	ld	[%l4 + %lo(C_LABEL(softirq_state))], %g5
+	ld	[%l4 + %lo(C_LABEL(softirq_state) + 4)], %g4
 	andcc	%g4, %g5, %g0
 	be	C_LABEL(ret_trap_lockless_ipi)
 	 nop
-	call	C_LABEL(do_bottom_half)
+	call	C_LABEL(do_softirq)
 	 nop
-
+	
 C_LABEL(ret_trap_lockless_ipi):
 	andcc	%t_psr, PSR_PS, %g0
 	be	1f
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.3.42/linux/arch/sparc/kernel/sparc_ksyms.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.88 2000/01/28 13:41:55 jj Exp $
+/* $Id: sparc_ksyms.c,v 1.89 2000/02/09 11:15:03 davem Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -11,8 +11,10 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/smp.h>
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/in6.h>
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v2.3.42/linux/arch/sparc/kernel/sys_sparc.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/kernel/sys_sparc.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.59 2000/01/29 07:40:10 davem Exp $
+/* $Id: sys_sparc.c,v 1.60 2000/02/08 20:24:18 davem Exp $
  * linux/arch/sparc/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -9,7 +9,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.3.42/linux/arch/sparc/kernel/time.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/kernel/time.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.51 2000/01/29 01:08:59 anton Exp $
+/* $Id: time.c,v 1.53 2000/02/09 21:11:04 davem Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -429,12 +429,14 @@
 
 extern __inline__ unsigned long do_gettimeoffset(void)
 {
+	struct tasklet_struct *t;
 	unsigned long offset = 0;
 	unsigned int count;
 
 	count = (*master_l10_counter >> 10) & 0x1fffff;
 
-	if(test_bit(TIMER_BH, &bh_active))
+	t = &bh_task_vec[TIMER_BH];
+	if (test_bit(TASKLET_STATE_SCHED, &t->state))
 		offset = 1000000;
 
 	return offset + count;
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.3.42/linux/arch/sparc/mm/init.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.79 2000/01/29 01:09:06 anton Exp $
+/*  $Id: init.c,v 1.80 2000/02/09 21:11:06 davem Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -33,8 +33,6 @@
 #include <asm/pgtable.h>
 #include <asm/vaddrs.h>
 
-extern void show_net_buffers(void);
-
 unsigned long *sparc_valid_addr_bitmap;
 
 unsigned long phys_base;
@@ -89,9 +87,6 @@
 		printk("%ld entries in page dir cache\n",pgd_cache_size);
 #endif	
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 }
 
 extern pgprot_t protection_map[16];
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c
--- v2.3.42/linux/arch/sparc/mm/io-unit.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/sparc/mm/io-unit.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.20 2000/01/15 00:51:27 anton Exp $
+/* $Id: io-unit.c,v 1.21 2000/02/06 22:55:45 zaitcev Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
@@ -210,6 +210,20 @@
 
 static void iounit_unmap_dma_area(unsigned long addr, int len)
 {
+	/* XXX Somebody please fill this in */
+}
+
+/* XXX We do not pass sbus device here, bad. */
+static unsigned long iounit_translate_dvma(unsigned long addr)
+{
+	struct sbus_bus *sbus = sbus_root;	/* They are all the same */
+	struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+	int i;
+	iopte_t *iopte;
+
+	i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
+	iopte = (iopte_t *)(iounit->page_table + i);
+	return (iopte_val(*iopte) & 0xFFFFFFF0) << 4; /* XXX sun4d guru, help */
 }
 #endif
 
@@ -237,6 +251,7 @@
 #ifdef CONFIG_SBUS
 	BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_translate_dvma, iounit_translate_dvma, BTFIXUPCALL_NORM);
 #endif
 }
 
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c
--- v2.3.42/linux/arch/sparc/mm/iommu.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/sparc/mm/iommu.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.18 2000/01/15 00:51:27 anton Exp $
+/* $Id: iommu.c,v 1.19 2000/02/06 22:55:45 zaitcev Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -289,8 +289,32 @@
 	iommu_invalidate(iommu->regs);
 }
 
-static void iommu_unmap_dma_area(unsigned long addr, int len)
+static void iommu_unmap_dma_area(unsigned long busa, int len)
 {
+	struct iommu_struct *iommu = sbus_root->iommu;
+	iopte_t *iopte = iommu->page_table;
+	unsigned long end;
+
+	iopte += ((busa - iommu->start) >> PAGE_SHIFT);
+	end = PAGE_ALIGN((busa + len));
+	while (busa < end) {
+		iopte_val(*iopte++) = 0;
+		busa += PAGE_SIZE;
+	}
+	flush_tlb_all();	/* P3: Hmm... it would not hurt. */
+	iommu_invalidate(iommu->regs);
+}
+
+static unsigned long iommu_translate_dvma(unsigned long busa)
+{
+	struct iommu_struct *iommu = sbus_root->iommu;
+	iopte_t *iopte = iommu->page_table;
+	unsigned long pa;
+
+	iopte += ((busa - iommu->start) >> PAGE_SHIFT);
+	pa = pte_val(*iopte);
+	pa = (pa & 0xFFFFFFF0) << 4;		/* Loose higher bits of 36 */
+	return pa + PAGE_OFFSET;
 }
 #endif
 
@@ -327,5 +351,6 @@
 #ifdef CONFIG_SBUS
 	BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_translate_dvma, iommu_translate_dvma, BTFIXUPCALL_NORM);
 #endif
 }
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/mm/loadmmu.c linux/arch/sparc/mm/loadmmu.c
--- v2.3.42/linux/arch/sparc/mm/loadmmu.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/mm/loadmmu.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.54 2000/01/29 01:09:07 anton Exp $
+/* $Id: loadmmu.c,v 1.56 2000/02/08 20:24:21 davem Exp $
  * loadmmu.c:  This code loads up all the mm function pointers once the
  *             machine type has been determined.  It also sets the static
  *             mmu values such as PAGE_NONE, etc.
@@ -10,7 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/init.h>
-#include <linux/config.h>
 
 #include <asm/system.h>
 #include <asm/page.h>
@@ -27,6 +26,7 @@
 
 extern void ld_mmu_sun4c(void);
 extern void ld_mmu_srmmu(void);
+extern void ioport_init(void);
 
 void __init load_mmu(void)
 {
@@ -44,4 +44,5 @@
 		prom_halt();
 	}
 	btfixup();
+	ioport_init();
 }
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.3.42/linux/arch/sparc/mm/srmmu.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/sparc/mm/srmmu.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.205 2000/01/21 17:59:46 anton Exp $
+/* $Id: srmmu.c,v 1.206 2000/02/08 07:45:59 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -1304,7 +1304,7 @@
 	sparc_context_init(num_contexts);
 
 	{
-		unsigned int zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+		unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0};
 
 		zones_size[ZONE_DMA] = end_pfn;
 		free_area_init(zones_size);
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.3.42/linux/arch/sparc/mm/sun4c.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/sparc/mm/sun4c.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.185 2000/01/15 00:51:32 anton Exp $
+/* $Id: sun4c.c,v 1.187 2000/02/08 07:46:01 davem Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -584,15 +584,24 @@
 	}
 }
 
-static void sun4c_unmap_dma_area(unsigned long addr, int len)
+static unsigned long sun4c_translate_dvma(unsigned long busa)
 {
+	/* Fortunately for us, bus_addr == uncached_virt in sun4c. */
+	unsigned long pte = sun4c_get_pte(busa);
+	return (pte << PAGE_SHIFT) + PAGE_OFFSET;
 }
 
-static void sun4c_inval_dma_area(unsigned long addr, int len)
+static unsigned long sun4c_unmap_dma_area(unsigned long busa, int len)
 {
+	/* Fortunately for us, bus_addr == uncached_virt in sun4c. */
+	/* XXX Implement this */
 }
 
-static void sun4c_flush_dma_area(unsigned long addr, int len)
+static void sun4c_inval_dma_area(unsigned long virt, int len)
+{
+}
+
+static void sun4c_flush_dma_area(unsigned long virt, int len)
 {
 }
 
@@ -2574,7 +2583,7 @@
 	sparc_context_init(num_contexts);
 
 	{
-		unsigned int zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+		unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0};
 
 		zones_size[ZONE_DMA] = end_pfn;
 		free_area_init(zones_size);
@@ -2721,6 +2730,7 @@
 
 	BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_translate_dvma, sun4c_translate_dvma, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(mmu_flush_dma_area, sun4c_flush_dma_area, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(mmu_inval_dma_area, sun4c_inval_dma_area, BTFIXUPCALL_NORM);
 
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/prom/bootstr.c linux/arch/sparc/prom/bootstr.c
--- v2.3.42/linux/arch/sparc/prom/bootstr.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/prom/bootstr.c	Tue Feb  8 18:23:13 2000
@@ -1,10 +1,9 @@
-/* $Id: bootstr.c,v 1.19 2000/01/29 01:09:11 anton Exp $
+/* $Id: bootstr.c,v 1.20 2000/02/08 20:24:23 davem Exp $
  * bootstr.c:  Boot string/argument acquisition from the PROM.
  *
  * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <asm/oplib.h>
 #include <asm/sun4prom.h>
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/prom/console.c linux/arch/sparc/prom/console.c
--- v2.3.42/linux/arch/sparc/prom/console.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/prom/console.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: console.c,v 1.21 2000/01/29 01:09:12 anton Exp $
+/* $Id: console.c,v 1.22 2000/02/08 20:24:23 davem Exp $
  * console.c: Routines that deal with sending and receiving IO
  *            to/from the current console device using the PROM.
  *
@@ -6,7 +6,6 @@
  * Copyright (C) 1998 Pete Zaitcev <zaitcev@metabyte.com>
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/prom/printf.c linux/arch/sparc/prom/printf.c
--- v2.3.42/linux/arch/sparc/prom/printf.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc/prom/printf.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: printf.c,v 1.6 2000/01/29 01:09:12 anton Exp $
+/* $Id: printf.c,v 1.7 2000/02/08 20:24:23 davem Exp $
  * printf.c:  Internal prom library printf facility.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -8,7 +8,6 @@
  * about or use it!  It's simple and smelly anyway....
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 
 #include <asm/openprom.h>
diff -u --recursive --new-file v2.3.42/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds
--- v2.3.42/linux/arch/sparc/vmlinux.lds	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/vmlinux.lds	Tue Feb  8 18:23:13 2000
@@ -73,4 +73,5 @@
   .debug_pubnames 0 : { *(.debug_pubnames) }
   .debug_sfnames  0 : { *(.debug_sfnames) }
   .line           0 : { *(.line) }
+  /DISCARD/ : { *(.text.exit) *(.data.exit) }
 }
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.3.42/linux/arch/sparc64/config.in	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc64/config.in	Thu Feb 10 12:16:38 2000
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.89 2000/01/31 21:10:10 davem Exp $
+# $Id: config.in,v 1.95 2000/02/10 02:51:12 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -17,13 +17,6 @@
 
 bool 'Symmetric multi-processing support' CONFIG_SMP
 
-mainmenu_option next_comment
-comment 'Console drivers'
-bool 'PROM console' CONFIG_PROM_CONSOLE
-bool 'Support Frame buffer devices' CONFIG_FB
-source drivers/video/Config.in
-endmenu
-
 # Global things across all Sun machines.
 define_bool CONFIG_SBUS y
 define_bool CONFIG_SBUSCHAR y
@@ -38,6 +31,14 @@
 define_bool CONFIG_SUN_IO y
 bool 'PCI support' CONFIG_PCI
 source drivers/pci/Config.in
+
+mainmenu_option next_comment
+comment 'Console drivers'
+bool 'PROM console' CONFIG_PROM_CONSOLE
+bool 'Support Frame buffer devices' CONFIG_FB
+source drivers/video/Config.in
+endmenu
+
 source drivers/sbus/char/Config.in
 source drivers/sbus/audio/Config.in
 
@@ -129,11 +130,24 @@
    comment 'SCSI support type (disk, tape, CDrom)'
 
    dep_tristate '  SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+
+   if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+      int  'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+   fi
+
    dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+
+   if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+      int  'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
+   fi
+
    dep_tristate '  SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+
    if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
       bool '    Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+      int  'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
    fi
+
    dep_tristate '  SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
 
    comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
@@ -141,6 +155,7 @@
    bool '  Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
 
    bool '  Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+   bool '  SCSI logging facility' CONFIG_SCSI_LOGGING
 
    mainmenu_option next_comment
    comment 'SCSI low-level drivers'
@@ -198,26 +213,48 @@
 	 bool '    Keepalive and linefill' CONFIG_SLIP_SMART
 	 bool '    Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
       fi
-      bool '  Sun LANCE support' CONFIG_SUNLANCE
-      tristate '  Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
+
+      mainmenu_option next_comment
+      comment 'Ethernet (10 or 100Mbit)'
+
+      bool 'Sun LANCE support' CONFIG_SUNLANCE
+      tristate 'Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-	 tristate '  Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
+	 tristate 'Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
       fi
       tristate '  Sun QuadEthernet support' CONFIG_SUNQE
-      tristate '  MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
       if [ "$CONFIG_PCI" = "y" ]; then
-	 tristate '  Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
-	 tristate '  3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
-	 tristate '  RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
-	 tristate '  PCI NE2000 support' CONFIG_NE2K_PCI
-	 tristate '  EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
-	 tristate '  Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
+	 tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
+	 tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
+	 tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
+	 tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
+	 tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
+	 tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
       fi
+      endmenu
+
+      mainmenu_option next_comment
+      comment 'Ethernet (1000 Mbit)'
+
+      if [ "$CONFIG_PCI" = "y" ]; then
+	  tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC
+	  if [ "$CONFIG_ACENIC" != "n" ]; then
+	    bool '  Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I
+	  fi
+	  tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN
+      fi
+      tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
+      endmenu
+
 #      bool '  FDDI driver support' CONFIG_FDDI
 #      if [ "$CONFIG_FDDI" = "y" ]; then
 #      fi
+
+      if [ "$CONFIG_ATM" = "y" ]; then
+	source drivers/atm/Config.in
+      fi
    fi
-endmenu
+   endmenu
 fi
 
 # This one must be before the filesystem configs. -DaveM
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.42/linux/arch/sparc64/defconfig	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc64/defconfig	Thu Feb 10 12:16:38 2000
@@ -13,6 +13,19 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_SMP is not set
+CONFIG_SBUS=y
+CONFIG_SBUSCHAR=y
+CONFIG_BUSMOUSE=y
+CONFIG_SUN_MOUSE=y
+CONFIG_SERIAL=y
+CONFIG_SUN_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_SUN_KEYBOARD=y
+CONFIG_SUN_CONSOLE=y
+CONFIG_SUN_AUXIO=y
+CONFIG_SUN_IO=y
+CONFIG_PCI=y
+CONFIG_PCI_NAMES=y
 
 #
 # Console drivers
@@ -51,19 +64,6 @@
 CONFIG_FBCON_FONTWIDTH8_ONLY=y
 CONFIG_FONT_SUN8x16=y
 # CONFIG_FBCON_FONTS is not set
-CONFIG_SBUS=y
-CONFIG_SBUSCHAR=y
-CONFIG_BUSMOUSE=y
-CONFIG_SUN_MOUSE=y
-CONFIG_SERIAL=y
-CONFIG_SUN_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SUN_KEYBOARD=y
-CONFIG_SUN_CONSOLE=y
-CONFIG_SUN_AUXIO=y
-CONFIG_SUN_IO=y
-CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
 
 #
 # Misc Linux/SPARC drivers
@@ -75,10 +75,6 @@
 # CONFIG_SUN_BPP is not set
 # CONFIG_SUN_VIDEOPIX is not set
 CONFIG_SUN_AURORA=m
-# CONFIG_TADPOLE_TS102_UCTRL is not set
-# CONFIG_SUN_JSFLASH is not set
-CONFIG_APM_RTC_IS_GMT=y
-# CONFIG_RTC is not set
 
 #
 # Linux/SPARC audio subsystem (EXPERIMENTAL)
@@ -203,9 +199,12 @@
 # SCSI support type (disk, tape, CDrom)
 #
 CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=m
 
 #
@@ -213,6 +212,7 @@
 #
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
 
 #
 # SCSI low-level drivers
@@ -263,11 +263,14 @@
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 # CONFIG_SLIP_MODE_SLIP6 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_SUNLANCE=y
 CONFIG_HAPPYMEAL=y
 CONFIG_SUNBMAC=m
 CONFIG_SUNQE=m
-CONFIG_MYRI_SBUS=m
 CONFIG_DE4X5=m
 CONFIG_VORTEX=m
 CONFIG_RTL8139=m
@@ -276,6 +279,14 @@
 CONFIG_ADAPTEC_STARFIRE=m
 
 #
+# Ethernet (1000 Mbit)
+#
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_SK98LIN=m
+CONFIG_MYRI_SBUS=m
+
+#
 # Unix 98 PTY support
 #
 CONFIG_UNIX98_PTYS=y
@@ -297,7 +308,6 @@
 CONFIG_AFFS_FS=m
 # CONFIG_HFS_FS is not set
 CONFIG_BFS_FS=m
-# CONFIG_BFS_FS_WRITE is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.3.42/linux/arch/sparc64/kernel/Makefile	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/Makefile	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.50 1999/12/21 04:02:24 davem Exp $
+# $Id: Makefile,v 1.51 2000/02/08 05:11:31 jj Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -19,13 +19,13 @@
 O_OBJS   := process.o setup.o cpu.o idprom.o \
 	    traps.o devices.o auxio.o \
 	    irq.o ptrace.o time.o sys_sparc.o signal.o \
-	    unaligned.o central.o pci.o pci_common.o pci_iommu.o \
-	    pci_psycho.o pci_sabre.o starfire.o semaphore.o \
+	    unaligned.o central.o pci.o starfire.o semaphore.o \
 	    power.o sbus.o iommu_common.o
 OX_OBJS  := sparc64_ksyms.o
 
 ifdef CONFIG_PCI
-  O_OBJS += ebus.o
+  O_OBJS += ebus.o pci_common.o pci_iommu.o \
+	    pci_psycho.o pci_sabre.o 
 endif
 
 ifdef CONFIG_SUNOS_EMUL
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.3.42/linux/arch/sparc64/kernel/ioctl32.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc64/kernel/ioctl32.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.76 2000/01/31 21:10:15 davem Exp $
+/* $Id: ioctl32.c,v 1.79 2000/02/08 20:24:25 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -17,7 +17,9 @@
 #include <linux/if.h>
 #include <linux/malloc.h>
 #include <linux/hdreg.h>
+#if 0 /* New RAID code is half-merged... -DaveM */
 #include <linux/md.h>
+#endif
 #include <linux/kd.h>
 #include <linux/route.h>
 #include <linux/skbuff.h>
@@ -61,6 +63,18 @@
 
 #include <linux/soundcard.h>
 
+#include <linux/atm.h>
+#include <linux/atmarp.h>
+#include <linux/atmclip.h>
+#include <linux/atmdev.h>
+#include <linux/atmioc.h>
+#include <linux/atmlec.h>
+#include <linux/atmmpc.h>
+#include <linux/atmsvc.h>
+#include <linux/atm_tcp.h>
+#include <linux/sonet.h>
+#include <linux/atm_suni.h>
+
 /* Use this to get at 32-bit user passed pointers. 
    See sys_sparc32.c for description about these. */
 #define A(__x) ((unsigned long)(__x))
@@ -1753,6 +1767,217 @@
 	return err;
 }
 
+struct atmif_sioc32 {
+        int                number;
+        int                length;
+        __kernel_caddr_t32 arg;
+};
+
+struct atm_iobuf32 {
+	int                length;
+	__kernel_caddr_t32 buffer;
+};
+
+#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
+#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
+#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
+#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
+#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
+#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
+#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
+#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
+#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
+#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
+#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
+#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
+#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
+#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
+
+static struct {
+        unsigned int cmd32;
+        unsigned int cmd;
+} atm_ioctl_map[] = {
+        { ATM_GETLINKRATE32, ATM_GETLINKRATE },
+	{ ATM_GETNAMES32,    ATM_GETNAMES },
+        { ATM_GETTYPE32,     ATM_GETTYPE },
+        { ATM_GETESI32,      ATM_GETESI },
+        { ATM_GETADDR32,     ATM_GETADDR },
+        { ATM_RSTADDR32,     ATM_RSTADDR },
+        { ATM_ADDADDR32,     ATM_ADDADDR },
+        { ATM_DELADDR32,     ATM_DELADDR },
+        { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
+	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
+	{ ATM_SETESI32,      ATM_SETESI },
+	{ ATM_SETESIF32,     ATM_SETESIF },
+	{ ATM_GETSTAT32,     ATM_GETSTAT },
+	{ ATM_GETSTATZ32,    ATM_GETSTATZ }
+};
+
+#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
+
+
+static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct atm_iobuf32 iobuf32;
+	struct atm_iobuf   iobuf = { 0, NULL };
+	mm_segment_t old_fs;
+	int err;
+
+	err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg,
+	    sizeof(struct atm_iobuf32));
+	if (err)
+		return -EFAULT;
+
+	iobuf.length = iobuf32.length;
+
+	if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) {
+		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
+	} else {
+		iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
+		if (iobuf.buffer == NULL) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		err = copy_from_user(iobuf.buffer, A(iobuf32.buffer), iobuf.length);
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
+	set_fs (old_fs);
+        if(err)
+		goto out;
+
+        if(iobuf.buffer && iobuf.length > 0) {
+		err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length);
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
+
+ out:
+        if(iobuf32.buffer && iobuf32.length > 0)
+		kfree(iobuf.buffer);
+
+	return err;
+}
+
+
+static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+        struct atmif_sioc32 sioc32;
+        struct atmif_sioc   sioc = { 0, 0, NULL };
+        mm_segment_t old_fs;
+        int err;
+        
+        err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg,
+			     sizeof(struct atmif_sioc32));
+        if (err)
+                return -EFAULT;
+
+        sioc.number = sioc32.number;
+        sioc.length = sioc32.length;
+        
+	if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) {
+		sioc.arg = (void*)(unsigned long)sioc32.arg;
+        } else {
+                sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
+                if (sioc.arg == NULL) {
+                        err = -ENOMEM;
+			goto out;
+		}
+                
+                err = copy_from_user(sioc.arg, A(sioc32.arg), sioc32.length);
+                if (err) {
+                        err = -EFAULT;
+                        goto out;
+                }
+        }
+        
+        old_fs = get_fs(); set_fs (KERNEL_DS);
+        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
+        set_fs (old_fs);
+        if(err) {
+                goto out;
+	}
+        
+        if(sioc.arg && sioc.length > 0) {
+                err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length);
+                if (err) {
+                        err = -EFAULT;
+                        goto out;
+                }
+        }
+        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
+        
+ out:
+        if(sioc32.arg && sioc32.length > 0)
+		kfree(sioc.arg);
+        
+	return err;
+}
+
+
+static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
+{
+        int i;
+        unsigned int cmd = 0;
+        
+	switch (cmd32) {
+	case SUNI_GETLOOP:
+	case SUNI_SETLOOP:
+	case SONET_GETSTAT:
+	case SONET_GETSTATZ:
+	case SONET_GETDIAG:
+	case SONET_SETDIAG:
+	case SONET_CLRDIAG:
+	case SONET_SETFRAMING:
+	case SONET_GETFRAMING:
+	case SONET_GETFRSENSE:
+		return do_atmif_sioc(fd, cmd32, arg);
+	}
+
+	if (cmd == 0) {
+		for (i = 0; i < NR_ATM_IOCTL; i++) {
+			if (cmd32 == atm_ioctl_map[i].cmd32) {
+				cmd = atm_ioctl_map[i].cmd;
+				break;
+			}
+		}
+	        if (i == NR_ATM_IOCTL) {
+	        return -EINVAL;
+	        }
+	}
+        
+        switch (cmd) {
+	case ATM_GETNAMES:
+		return do_atm_iobuf(fd, cmd, arg);
+	    
+	case ATM_GETLINKRATE:
+        case ATM_GETTYPE:
+        case ATM_GETESI:
+        case ATM_GETADDR:
+        case ATM_RSTADDR:
+        case ATM_ADDADDR:
+        case ATM_DELADDR:
+        case ATM_GETCIRANGE:
+	case ATM_SETCIRANGE:
+	case ATM_SETESI:
+	case ATM_SETESIF:
+	case ATM_GETSTAT:
+	case ATM_GETSTATZ:
+                return do_atmif_sioc(fd, cmd, arg);
+        }
+
+        return -EINVAL;
+}
+
 asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct file * filp;
@@ -1945,6 +2170,33 @@
 		error = do_smb_getmountuid(fd, cmd, arg);
 		goto out;
 
+	case ATM_GETLINKRATE32:
+	case ATM_GETNAMES32:
+	case ATM_GETTYPE32:
+        case ATM_GETESI32:
+	case ATM_GETADDR32:
+        case ATM_RSTADDR32:
+        case ATM_ADDADDR32:
+        case ATM_DELADDR32:
+        case ATM_GETCIRANGE32:
+        case ATM_SETCIRANGE32:
+	case ATM_SETESI32:
+	case ATM_SETESIF32:
+	case ATM_GETSTAT32:
+	case ATM_GETSTATZ32:
+	case SUNI_GETLOOP:
+	case SUNI_SETLOOP:
+	case SONET_GETSTAT:
+	case SONET_GETSTATZ:
+	case SONET_GETDIAG:
+	case SONET_SETDIAG:
+	case SONET_CLRDIAG:
+	case SONET_SETFRAMING:
+	case SONET_GETFRAMING:
+	case SONET_GETFRSENSE:
+                error = do_atm_ioctl(fd, cmd, arg);
+                goto out;
+		
 	/* List here exlicitly which ioctl's are known to have
 	 * compatable types passed or none at all...
 	 */
@@ -2062,12 +2314,16 @@
 	case BLKRRPART:
 	case BLKFLSBUF:
 	case BLKRASET:
-	
+
+#if 0	/* New RAID code is being merged, fix up to handle
+	 * new RAID ioctls when fully merged in 2.3.x -DaveM
+	 */
 	/* 0x09 */
 	case REGISTER_DEV:
 	case REGISTER_DEV_NEW:
 	case START_MD:
 	case STOP_MD:
+#endif
 	
 	/* Big K */
 	case PIO_FONT:
@@ -2454,6 +2710,23 @@
 	/* SMB ioctls which do not need any translations */
 	case SMB_IOC_NEWCONN:
 
+	/* Little a */
+	case ATMSIGD_CTRL:
+	case ATMARPD_CTRL:
+	case ATMLEC_CTRL:
+	case ATMLEC_MCAST:
+	case ATMLEC_DATA:
+	case ATM_SETSC:
+        case SIOCSIFATMTCP:
+	case SIOCMKCLIP:
+        case ATMARP_MKIP:
+        case ATMARP_SETENTRY:
+        case ATMARP_ENCAP:
+        case ATMTCP_CREATE:
+        case ATMTCP_REMOVE:
+        case ATMMPC_CTRL:
+        case ATMMPC_DATA:
+	    
 		error = sys_ioctl (fd, cmd, arg);
 		goto out;
 
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.3.42/linux/arch/sparc64/kernel/irq.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/sparc64/kernel/irq.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.81 2000/01/21 06:33:59 davem Exp $
+/* $Id: irq.c,v 1.82 2000/02/09 11:15:07 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
+#include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/malloc.h>
 #include <linux/random.h> /* XXX ADD add_foo_randomness() calls... -DaveM */
@@ -546,8 +547,6 @@
 #define irq_enter(cpu, irq)	(local_irq_count++)
 #define irq_exit(cpu, irq)	(local_irq_count--)
 #else
-atomic_t global_bh_lock = ATOMIC_INIT(0);
-spinlock_t global_bh_count = SPIN_LOCK_UNLOCKED;
 
 /* Who has global_irq_lock. */
 unsigned char global_irq_holder = NO_PROC_ID;
@@ -573,24 +572,12 @@
 	       atomic_read(&global_irq_count),
 	       cpu_data[0].irq_count, cpu_data[1].irq_count);
 	printk("bh:   %d [%u %u]\n",
-	       (spin_is_locked(&global_bh_count) ? 1 : 0),
+	       (spin_is_locked(&global_bh_lock) ? 1 : 0),
 	       cpu_data[0].bh_count, cpu_data[1].bh_count);
 }
 
 #define MAXCOUNT 100000000
 
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if(!--count) {
-			show("wait_on_bh");
-			count = 0;
-		}
-		membar("#LoadLoad");
-	} while(spin_is_locked(&global_bh_count));
-}
-
 #define SYNC_OTHER_ULTRAS(x)	udelay(x+1)
 
 static inline void wait_on_irq(int cpu)
@@ -599,7 +586,7 @@
 	for(;;) {
 		membar("#LoadLoad");
 		if (!atomic_read (&global_irq_count)) {
-			if (local_bh_count || ! spin_is_locked(&global_bh_count))
+			if (local_bh_count || ! spin_is_locked(&global_bh_lock))
 				break;
 		}
 		spin_unlock (&global_irq_lock);
@@ -616,18 +603,12 @@
 				continue;
 			if (spin_is_locked (&global_irq_lock))
 				continue;
-			if (!local_bh_count && spin_is_locked (&global_bh_count))
+			if (!local_bh_count && spin_is_locked (&global_bh_lock))
 				continue;
 			if (spin_trylock(&global_irq_lock))
 				break;
 		}
 	}
-}
-
-void synchronize_bh(void)
-{
-	if (spin_is_locked (&global_bh_count) && !in_interrupt())
-		wait_on_bh();
 }
 
 void synchronize_irq(void)
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.3.42/linux/arch/sparc64/kernel/pci.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/sparc64/kernel/pci.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.14 2000/01/13 00:05:43 davem Exp $
+/* $Id: pci.c,v 1.15 2000/02/08 05:11:29 jj Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -19,11 +19,6 @@
 #include <asm/pbm.h>
 #include <asm/irq.h>
 #include <asm/ebus.h>
-
-#ifndef NEW_PCI_DMA_MAP
-unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
-unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
-#endif
 
 unsigned long pci_memspace_mask = 0xffffffffUL;
 
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h
--- v2.3.42/linux/arch/sparc64/kernel/pci_impl.h	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/pci_impl.h	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_impl.h,v 1.4 1999/12/17 12:32:03 jj Exp $
+/* $Id: pci_impl.h,v 1.5 2000/02/08 05:11:32 jj Exp $
  * pci_impl.h: Helper definitions for PCI controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -33,21 +33,6 @@
 extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
 extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
 extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
-
-#ifndef NEW_PCI_DMA_MAP
-/* IOMMU/DVMA initialization. */
-#define PCI_DVMA_HASH_NONE	~0UL
-static __inline__ void set_dvma_hash(unsigned long dvma_offset,
-				     unsigned long paddr,
-				     unsigned long daddr)
-{
-	unsigned long dvma_addr = dvma_offset + daddr;
-	unsigned long vaddr = (unsigned long)__va(paddr);
-
-	pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] = dvma_addr - vaddr;
-	pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr;
-}
-#endif
 
 /* Configuration space access. */
 extern spinlock_t pci_poke_lock;
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.3.42/linux/arch/sparc64/kernel/pci_psycho.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc64/kernel/pci_psycho.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.10 2000/01/28 13:42:00 jj Exp $
+/* $Id: pci_psycho.c,v 1.11 2000/02/08 05:11:32 jj Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1219,12 +1219,6 @@
 
 static void __init psycho_iommu_init(struct pci_controller_info *p)
 {
-#ifndef NEW_PCI_DMA_MAP
-	struct linux_mlist_p1275 *mlist;
-	unsigned long n;
-	iopte_t *iopte;
-	int tsbsize = 32;
-#endif
 	extern int this_is_starfire;
 	extern void *starfire_hookup(int);
 	unsigned long tsbbase, i;
@@ -1258,19 +1252,11 @@
 	control &= ~(PSYCHO_IOMMU_CTRL_DENAB);
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
 
-#ifndef NEW_PCI_DMA_MAP
-	/* Using assumed page size 64K with 32K entries we need 256KB iommu page
-	 * table (32K ioptes * 8 bytes per iopte).  This is
-	 * page order 5 on UltraSparc.
-	 */
-	tsbbase = __get_free_pages(GFP_KERNEL, 5);
-#else
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
 	 * page order 7 on UltraSparc.
 	 */
 	tsbbase = __get_free_pages(GFP_KERNEL, 7);
-#endif	
 	if (!tsbbase) {
 		prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n");
 		prom_halt();
@@ -1278,112 +1264,17 @@
 	p->iommu.page_table = (iopte_t *)tsbbase;
 	p->iommu.page_table_sz_bits = 17;
 	p->iommu.page_table_map_base = 0xc0000000;
-#ifndef NEW_PCI_DMA_MAP
-	memset((char *)tsbbase, 0, PAGE_SIZE << 5);
-#else
 	memset((char *)tsbbase, 0, PAGE_SIZE << 7);
-#endif
 
 	/* Make sure DMA address 0 is never returned just to allow catching
 	   of buggy drivers.  */
 	p->iommu.lowest_free[0] = 1;
 
-#ifndef NEW_PCI_DMA_MAP
-	iopte = (iopte_t *)tsbbase;
-	/* Initialize to "none" settings. */
-	for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
-		pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
-		pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
-	}
-
-	n = 0;
-	mlist = *prom_meminfo()->p1275_totphys;
-	while (mlist) {
-		unsigned long paddr = mlist->start_adr;
-		unsigned long num_bytes = mlist->num_bytes;
-
-		if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
-			goto next;
-
-		if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
-			num_bytes = (((unsigned long) high_memory) - PAGE_OFFSET) - paddr;
-
-		/* Align base and length so we map whole hash table sized chunks
-		 * at a time (and therefore full 64K IOMMU pages).
-		 */
-		paddr &= ~((1UL << 24UL) - 1);
-		num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
-
-		/* Move up the base for mappings already created. */
-		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
-		      PCI_DVMA_HASH_NONE) {
-			paddr += (1UL << 24UL);
-			num_bytes -= (1UL << 24UL);
-			if(num_bytes == 0UL)
-				goto next;
-		}
-
-		/* Move down the size for tail mappings already created. */
-		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
-		      PCI_DVMA_HASH_NONE) {
-			num_bytes -= (1UL << 24UL);
-			if(num_bytes == 0UL)
-				goto next;
-		}
-
-		/* Now map the rest. */
-		for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
-			iopte_val(*iopte) = ((IOPTE_VALID | IOPTE_64K |
-					      IOPTE_CACHE | IOPTE_WRITE) |
-					     (paddr & IOPTE_PAGE));
-
-			if (!(n & 0xff))
-				set_dvma_hash(0x80000000, paddr, (n << 16));
-
-			if (++n > (tsbsize * 1024))
-				goto out;
-
-			paddr += (1 << 16);
-			iopte++;
-		}
-	next:
-		mlist = mlist->theres_more;
-	}
-out:
-	if (mlist) {
-		prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
-		prom_printf("Try booting with mem=xxxM or similar\n");
-		prom_halt();
-	}
-#endif
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
 
 	control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
-#ifndef NEW_PCI_DMA_MAP
-	control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ);
-	control |= (PSYCHO_IOMMU_CTRL_TBWSZ | PSYCHO_IOMMU_CTRL_ENAB);
-	switch(tsbsize) {
-	case 8:
-		p->iommu.page_table_map_base = 0xe0000000;
-		control |= PSYCHO_IOMMU_TSBSZ_8K;
-		break;
-	case 16:
-		p->iommu.page_table_map_base = 0xc0000000;
-		control |= PSYCHO_IOMMU_TSBSZ_16K;
-		break;
-	case 32:
-		p->iommu.page_table_map_base = 0x80000000;
-		control |= PSYCHO_IOMMU_TSBSZ_32K;
-		break;
-	default:
-		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
-		prom_halt();
-		break;
-	}
-#else
 	control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
 	control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB);
-#endif
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
 
 	/* If necessary, hook us up for starfire IRQ translations. */
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.3.42/linux/arch/sparc64/kernel/pci_sabre.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc64/kernel/pci_sabre.c	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.11 2000/01/28 13:42:01 jj Exp $
+/* $Id: pci_sabre.c,v 1.12 2000/02/08 05:11:33 jj Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1107,11 +1107,6 @@
 static void __init sabre_iommu_init(struct pci_controller_info *p,
 				    int tsbsize, unsigned long dvma_offset)
 {
-#ifndef NEW_PCI_DMA_MAP
-	struct linux_mlist_p1275 *mlist;
-	unsigned long n;
-	iopte_t *iopte;
-#endif
 	unsigned long tsbbase, i, order;
 	u64 control;
 
@@ -1154,99 +1149,9 @@
 	   of buggy drivers.  */
 	p->iommu.lowest_free[0] = 1;
 
-#ifndef NEW_PCI_DMA_MAP
-	iopte = (iopte_t *)tsbbase;
-
-	/* Initialize to "none" settings. */
-	for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
-		pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
-		pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
-	}
-
-	n = 0;
-	mlist = *prom_meminfo()->p1275_totphys;
-	while (mlist) {
-		unsigned long paddr = mlist->start_adr;
-		unsigned long num_bytes = mlist->num_bytes;
-
-		if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
-			goto next;
-
-		if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
-			num_bytes =
-				(((unsigned long) high_memory) -
-				 PAGE_OFFSET) - paddr;
-
-		/* Align base and length so we map whole hash table sized chunks
-		 * at a time (and therefore full 64K IOMMU pages).
-		 */
-		paddr &= ~((1UL << 24UL) - 1);
-		num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
-
-		/* Move up the base for mappings already created. */
-		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
-		      PCI_DVMA_HASH_NONE) {
-			paddr += (1UL << 24UL);
-			num_bytes -= (1UL << 24UL);
-			if(num_bytes == 0UL)
-				goto next;
-		}
-
-		/* Move down the size for tail mappings already created. */
-		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
-		      PCI_DVMA_HASH_NONE) {
-			num_bytes -= (1UL << 24UL);
-			if(num_bytes == 0UL)
-				goto next;
-		}
-
-		/* Now map the rest. */
-		for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
-			iopte_val(*iopte) = ((IOPTE_VALID | IOPTE_64K |
-					      IOPTE_CACHE | IOPTE_WRITE) |
-					     (paddr & IOPTE_PAGE));
-
-			if (!(n & 0xff))
-				set_dvma_hash(dvma_offset, paddr, (n << 16));
-			if (++n > (tsbsize * 1024))
-				goto out;
-
-			paddr += (1 << 16);
-			iopte++;
-		}
-	next:
-		mlist = mlist->theres_more;
-	}
-out:
-	if (mlist) {
-		prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
-		prom_printf("Try booting with mem=xxxM or similar\n");
-		prom_halt();
-	}
-#endif
-
 	sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
 
 	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
-#ifndef NEW_PCI_DMA_MAP
-	control &= ~(SABRE_IOMMUCTRL_TSBSZ);
-	control |= (SABRE_IOMMUCTRL_TBWSZ | SABRE_IOMMUCTRL_ENAB);
-	switch(tsbsize) {
-	case 8:
-		control |= SABRE_IOMMU_TSBSZ_8K;
-		break;
-	case 16:
-		control |= SABRE_IOMMU_TSBSZ_16K;
-		break;
-	case 32:
-		control |= SABRE_IOMMU_TSBSZ_32K;
-		break;
-	default:
-		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
-		prom_halt();
-		break;
-	}
-#else
 	control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
 	control |= SABRE_IOMMUCTRL_ENAB;
 	switch(tsbsize) {
@@ -1263,7 +1168,6 @@
 		prom_halt();
 		break;
 	}
-#endif
 	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
 }
 
@@ -1472,17 +1376,6 @@
 	}
 
 	switch(vdma[1]) {
-#ifndef NEW_PCI_DMA_MAP
-		case 0x20000000:
-			tsbsize = 8;
-			break;
-		case 0x40000000:
-			tsbsize = 16;
-			break;
-		case 0x80000000:
-			tsbsize = 32;
-			break;
-#else
 		case 0x20000000:
 			tsbsize = 64;
 			break;
@@ -1490,7 +1383,6 @@
 		case 0x80000000:
 			tsbsize = 128;
 			break;
-#endif
 		default:
 			prom_printf("SABRE: strange virtual-dma size.\n");
 			prom_halt();
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S
--- v2.3.42/linux/arch/sparc64/kernel/rtrap.S	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/rtrap.S	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.47 1999/07/30 09:35:23 davem Exp $
+/* $Id: rtrap.S,v 1.48 2000/02/09 11:15:07 davem Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -20,15 +20,17 @@
 		.globl			rtrap_clr_l6, rtrap
 rtrap_clr_l6:	clr			%l6
 		/* Fall through */
-rtrap:		sethi			%hi(bh_active), %l2
-		sethi			%hi(bh_mask), %l1
-		ldx			[%l2 + %lo(bh_active)], %l4
-		ldx			[%l1 + %lo(bh_mask)], %l7
+rtrap:		lduw			[%g6 + AOFF_task_processor], %l0
+		sethi			%hi(softirq_state), %l2
+		or			%l2, %lo(softirq_state), %l2
+		sllx			%l0, 6, %l0
+		ldx			[%l2 + %l0], %l1
+		srlx			%l1, 32, %l2
 
-		andcc			%l4, %l7, %g0
-		be,pt			%xcc, 2f
+		andcc			%l1, %l2, %g0
+		be,pt			%icc, 2f
 		 nop
-		call			do_bottom_half
+		call			do_softirq
 		 nop
 2:		ldx			[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 		sethi			%hi(0xf << 20), %l4
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.3.42/linux/arch/sparc64/kernel/sparc64_ksyms.c	Tue Feb  1 01:35:43 2000
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.72 2000/01/28 13:41:59 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.74 2000/02/09 11:15:07 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -127,11 +127,6 @@
 /* Kernel wide locking */
 EXPORT_SYMBOL(kernel_flag);
 
-/* Software-IRQ BH locking */
-EXPORT_SYMBOL(global_bh_lock);
-EXPORT_SYMBOL(global_bh_count);
-EXPORT_SYMBOL(synchronize_bh);
-
 /* Hard IRQ locking */
 EXPORT_SYMBOL(global_irq_holder);
 EXPORT_SYMBOL(global_irq_lock);
@@ -160,8 +155,8 @@
 #endif
 
 #else
-EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(local_bh_count);
+EXPORT_SYMBOL(local_irq_count);
 #endif
 
 /* rw semaphores */
@@ -194,12 +189,8 @@
 EXPORT_SYMBOL(sbus_dma_sync_single);
 EXPORT_SYMBOL(sbus_dma_sync_sg);
 #endif
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 EXPORT_SYMBOL(ebus_chain);
-#ifndef NEW_PCI_DMA_MAP
-EXPORT_SYMBOL(pci_dvma_v2p_hash);
-EXPORT_SYMBOL(pci_dvma_p2v_hash);
-#endif
 EXPORT_SYMBOL(pci_memspace_mask);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(outsb);
@@ -208,8 +199,6 @@
 EXPORT_SYMBOL(insb);
 EXPORT_SYMBOL(insw);
 EXPORT_SYMBOL(insl);
-#endif
-#ifdef NEW_PCI_DMA_MAP
 EXPORT_SYMBOL(pci_alloc_consistent);
 EXPORT_SYMBOL(pci_free_consistent);
 EXPORT_SYMBOL(pci_map_single);
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.3.42/linux/arch/sparc64/mm/init.c	Fri Jan 28 15:09:07 2000
+++ linux/arch/sparc64/mm/init.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.144 2000/01/23 07:16:11 davem Exp $
+/*  $Id: init.c,v 1.146 2000/02/09 21:11:09 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -30,7 +30,6 @@
 #include <asm/vaddrs.h>
 #include <asm/dma.h>
 
-extern void show_net_buffers(void);
 extern void device_scan(void);
 
 struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
@@ -130,9 +129,6 @@
 	printk("%d entries in page dir cache\n",pgd_cache_size);
 #endif	
 	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
 }
 
 int mmu_info(char *buf)
@@ -926,7 +922,7 @@
 	flush_tlb_all();
 
 	{
-		unsigned int zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+		unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0};
 
 		zones_size[ZONE_DMA] = end_pfn;
 		free_area_init(zones_size);
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c
--- v2.3.42/linux/arch/sparc64/solaris/socksys.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/solaris/socksys.c	Wed Feb  9 19:39:04 2000
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.10 1999/08/31 06:55:08 davem Exp $
+/* $Id: socksys.c,v 1.11 2000/02/09 22:32:17 davem Exp $
  * socksys.c: /dev/inet/ stuff for Solaris emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -48,16 +48,7 @@
 static unsigned int (*sock_poll)(struct file *, poll_table *);
 
 static struct file_operations socksys_file_ops = {
-	NULL,		/* lseek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	NULL,		/* open */
-	NULL,		/* flush */
-	NULL,		/* release */
+	/* Currently empty */
 };
 
 static int socksys_open(struct inode * inode, struct file * filp)
@@ -162,16 +153,8 @@
 }
 	
 static struct file_operations socksys_fops = {
-	NULL,		/* lseek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	socksys_open,	/* open */
-	NULL,		/* flush */
-	socksys_release,/* release */
+	open:		socksys_open,
+	release:	socksys_release,
 };
 
 int __init
diff -u --recursive --new-file v2.3.42/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds
--- v2.3.42/linux/arch/sparc64/vmlinux.lds	Fri Aug  6 11:58:00 1999
+++ linux/arch/sparc64/vmlinux.lds	Tue Feb  8 18:23:13 2000
@@ -74,4 +74,5 @@
   .debug_pubnames 0 : { *(.debug_pubnames) }
   .debug_sfnames  0 : { *(.debug_sfnames) }
   .line           0 : { *(.line) }
+  /DISCARD/ : { *(.text.exit) *(.data.exit) }
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/acorn/char/Makefile linux/drivers/acorn/char/Makefile
--- v2.3.42/linux/drivers/acorn/char/Makefile	Tue Dec 14 01:27:23 1999
+++ linux/drivers/acorn/char/Makefile	Sun Feb  6 17:45:25 2000
@@ -11,19 +11,17 @@
 
 O_TARGET 	:= acorn-char.o
 M_OBJS   	:=
-O_OBJS   	:=
+O_OBJS   	:= i2c.o pcf8583.o
 
 O_OBJS_arc	:= keyb_arc.o
 O_OBJS_a5k	:= keyb_arc.o
 O_OBJS_rpc	:= keyb_ps2.o
 
-ifeq ($(MACHINE),rpc)
-  ifeq ($(CONFIG_BUSMOUSE),y)
-    OX_OBJS += mouse_rpc.o
-  else
-    ifeq ($(CONFIG_BUSMOUSE),m)
-      MX_OBJS += mouse_rpc.o
-    endif
+ifeq ($(CONFIG_RPCMOUSE),y)
+  OX_OBJS += mouse_rpc.o
+else
+  ifeq ($(CONFIG_RPCSMOUSE),m)
+    MX_OBJS += mouse_rpc.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.42/linux/drivers/acorn/char/i2c.c linux/drivers/acorn/char/i2c.c
--- v2.3.42/linux/drivers/acorn/char/i2c.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/i2c.c	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,203 @@
+/*
+ * linux/drivers/acorn/char/i2c.c
+ *
+ * Copyright (C) 2000 Russell King
+ *
+ * ARM IOC/IOMD i2c driver.
+ *
+ * On Acorn machines, the following i2c devices are on the bus:
+ *	- PCF8583 real time clock & static RAM
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/ioc.h>
+#include <asm/system.h>
+
+#include "pcf8583.h"
+
+extern unsigned long
+mktime(unsigned int year, unsigned int mon, unsigned int day,
+       unsigned int hour, unsigned int min, unsigned int sec);
+extern int (*set_rtc)(void);
+
+static struct i2c_client *rtc_client;
+
+static inline int rtc_command(int cmd, void *data)
+{
+	int ret = -EIO;
+
+	if (rtc_client)
+		ret = rtc_client->driver->command(rtc_client, cmd, data);
+
+	return ret;
+}
+
+/*
+ * Read the current RTC time and date, and update xtime.
+ */
+static void get_rtc_time(void)
+{
+	unsigned char ctrl;
+	unsigned char year;
+	struct rtc_tm rtctm;
+	struct mem rtcmem = { 0xc0, 1, &year };
+
+	/*
+	 * Ensure that the RTC is running.
+	 */
+	rtc_command(RTC_GETCTRL, &ctrl);
+	if (ctrl & 0xc0) {
+		unsigned char new_ctrl;
+
+		new_ctrl = ctrl & ~0xc0;
+
+		printk("RTC: resetting control %02X -> %02X\n",
+		       ctrl, new_ctrl);
+
+		rtc_command(RTC_SETCTRL, &new_ctrl);
+	}
+
+	/*
+	 * Acorn machines store the year in
+	 * the static RAM at location 192.
+	 */
+	if (rtc_command(MEM_READ, &rtcmem))
+		return;
+
+	if (rtc_command(RTC_GETDATETIME, &rtctm))
+		return;
+
+	if (year < 70)
+		year += 100;
+
+	xtime.tv_usec = rtctm.cs * 10000;
+	xtime.tv_sec  = mktime(1900 + year, rtctm.mon, rtctm.mday,
+			       rtctm.hours, rtctm.mins, rtctm.secs);
+}
+
+/*
+ * Set the RTC time only.  Note that
+ * we do not touch the date.
+ */
+static int set_rtc_time(void)
+{
+	struct rtc_tm new_rtctm, old_rtctm;
+	unsigned long nowtime = xtime.tv_sec;
+
+	if (rtc_command(RTC_GETDATETIME, &old_rtctm))
+		return 0;
+
+	new_rtctm.cs    = xtime.tv_usec / 10000;
+	new_rtctm.secs  = nowtime % 60;	nowtime /= 60;
+	new_rtctm.mins  = nowtime % 60;	nowtime /= 60;
+	new_rtctm.hours = nowtime % 24;
+
+	/*
+	 * avoid writing when we're going to change the day
+	 * of the month.  We will retry in the next minute.
+	 * This basically means that if the RTC must not drift
+	 * by more than 1 minute in 11 minutes.
+	 *
+	 * [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00,
+	 *   rtc gets set to 1/1/2000 00:01:00 ]
+	 */
+	if ((old_rtctm.hours == 23 && old_rtctm.mins  == 59) ||
+	    (new_rtctm.hours == 23 && new_rtctm.mins  == 59))
+		return 1;
+
+	return rtc_command(RTC_SETTIME, &new_rtctm);
+}
+
+
+#define FORCE_ONES	0xdc
+#define SCL		0x02
+#define SDA		0x01
+
+static int ioc_control;
+
+static void ioc_setscl(void *data, int state)
+{
+	if (state)
+		ioc_control |= SCL;
+	else
+		ioc_control &= ~SCL;
+ 	outb(ioc_control, IOC_CONTROL);
+}
+
+static void ioc_setsda(void *data, int state)
+{
+	if (state)
+		ioc_control |= SDA;
+	else
+		ioc_control &= ~SDA;
+ 	outb(ioc_control, IOC_CONTROL);
+}
+
+static int ioc_getscl(void *data)
+{
+	return (inb(IOC_CONTROL) & SCL) != 0;
+}
+
+static int ioc_getsda(void *data)
+{
+	return (inb(IOC_CONTROL) & SDA) != 0;
+}
+
+static struct i2c_algo_bit_data ioc_data = {
+	NULL,
+	ioc_setsda,
+	ioc_setscl,
+	ioc_getsda,
+	ioc_getscl,
+	80, 80, 100
+};
+
+static int ioc_client_reg(struct i2c_client *client)
+{
+	if (client->id == I2C_DRIVERID_PCF8583 &&
+	    client->addr == 0x50) {
+		rtc_client = client;
+		get_rtc_time();
+		set_rtc = set_rtc_time;
+	}
+
+	return 0;
+}
+
+static int ioc_client_unreg(struct i2c_client *client)
+{
+	if (client == rtc_client) {
+		set_rtc = NULL;
+		rtc_client = NULL;
+	}
+
+	return 0;
+}
+
+static struct i2c_adapter ioc_ops = {
+	"IOC/IOMD",
+	I2C_HW_B_IOC,
+	NULL,
+	&ioc_data,
+	NULL,
+	NULL,
+	ioc_client_reg,
+	ioc_client_unreg
+};
+
+static int __init i2c_ioc_init(void)
+{
+	ioc_control = inb(IOC_CONTROL) | FORCE_ONES;
+
+	ioc_setscl(NULL, 1);
+	ioc_setsda(NULL, 1);
+
+	return i2c_bit_add_bus(&ioc_ops);
+}
+
+__initcall(i2c_ioc_init);
diff -u --recursive --new-file v2.3.42/linux/drivers/acorn/char/pcf8583.c linux/drivers/acorn/char/pcf8583.c
--- v2.3.42/linux/drivers/acorn/char/pcf8583.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/pcf8583.c	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,232 @@
+/*
+ * linux/drivers/i2c/pcf8583.c
+ *
+ * Copyright (C) 2000 Russell King
+ *
+ * Driver for PCF8583 RTC & RAM chip
+ */
+
+#include <linux/i2c.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+
+#include "pcf8583.h"
+
+static struct i2c_driver pcf8583_driver;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x50, 0x51, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	force:			ignore,
+	ignore:			ignore,
+	ignore_range:		ignore,
+	normal_i2c:		ignore,
+	normal_i2c_range:	normal_addr,
+	probe:			ignore,
+	probe_range:		ignore
+};
+
+#define DAT(x) ((unsigned int)(x->data))
+
+static int
+pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags,
+	       int kind)
+{
+	struct i2c_client *c;
+	unsigned char buf[1], ad[1] = { 0 };
+	struct i2c_msg msgs[2] = {
+		{ addr, 0,        1, ad  },
+		{ addr, I2C_M_RD, 1, buf }
+	};
+
+	c = kmalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return -ENOMEM;
+
+	strcpy(c->name, "PCF8583");
+	c->id		= pcf8583_driver.id;
+	c->flags	= 0;
+	c->addr		= addr;
+	c->adapter	= adap;
+	c->driver	= &pcf8583_driver;
+	c->data		= NULL;
+
+	if (i2c_transfer(c->adapter, msgs, 2) == 2)
+		DAT(c) = buf[0];
+
+	return i2c_attach_client(c);
+}
+
+static int
+pcf8583_probe(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, pcf8583_attach);
+}
+
+static int
+pcf8583_detach(struct i2c_client *client)
+{
+	i2c_detach_client(client);
+	return 0;
+}
+
+static int
+pcf8583_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
+{
+	unsigned char buf[8], addr[1] = { 1 };
+	struct i2c_msg msgs[2] = {
+		{ client->addr, 0,        1, addr },
+		{ client->addr, I2C_M_RD, 6, buf  }
+	};
+	int ret = -EIO;
+
+	if (i2c_transfer(client->adapter, msgs, 2) == 2) {
+		dt->year_off = buf[4] >> 6;
+		dt->wday     = buf[5] >> 5;
+
+		buf[4] &= 0x3f;
+		buf[5] &= 0x1f;
+
+		dt->cs       = BCD_TO_BIN(buf[0]);
+		dt->secs     = BCD_TO_BIN(buf[1]);
+		dt->mins     = BCD_TO_BIN(buf[2]);
+		dt->hours    = BCD_TO_BIN(buf[3]);
+		dt->mday     = BCD_TO_BIN(buf[4]);
+		dt->mon      = BCD_TO_BIN(buf[5]);
+
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int
+pcf8583_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
+{
+	unsigned char buf[8];
+	int ret, len = 6;
+
+	buf[0] = 0;
+	buf[1] = DAT(client) | 0x80;
+	buf[2] = BIN_TO_BCD(dt->cs);
+	buf[3] = BIN_TO_BCD(dt->secs);
+	buf[4] = BIN_TO_BCD(dt->mins);
+	buf[5] = BIN_TO_BCD(dt->hours);
+
+	if (datetoo) {
+		len = 8;
+		buf[6] = BIN_TO_BCD(dt->mday) | (dt->year_off << 6);
+		buf[7] = BIN_TO_BCD(dt->mon)  | (dt->wday << 5);
+	}
+
+	ret = i2c_master_send(client, (char *)buf, len);
+
+	buf[1] = DAT(client);
+	i2c_master_send(client, (char *)buf, 2);
+
+	return ret;
+}
+
+static int
+pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+	*ctrl = DAT(client);
+	return 0;
+}
+
+static int
+pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+	unsigned char buf[2];
+
+	buf[0] = 0;
+	buf[1] = *ctrl;
+	DAT(client) = *ctrl;
+
+	return i2c_master_send(client, (char *)buf, 2);
+}
+
+static int
+pcf8583_read_mem(struct i2c_client *client, struct mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{ client->addr, 0,        1, addr },
+		{ client->addr, I2C_M_RD, 0, mem->data }
+	};
+
+	if (mem->loc < 8)
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+	msgs[1].len = mem->nr;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int
+pcf8583_write_mem(struct i2c_client *client, struct mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{ client->addr, 0, 1, addr },
+		{ client->addr, 0, 0, mem->data }
+	};
+
+	if (mem->loc < 8)
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+	msgs[1].len = mem->nr;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int
+pcf8583_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case RTC_GETDATETIME:
+		return pcf8583_get_datetime(client, arg);
+		
+	case RTC_SETTIME:
+		return pcf8583_set_datetime(client, arg, 0);
+
+	case RTC_SETDATETIME:
+		return pcf8583_set_datetime(client, arg, 1);
+
+	case RTC_GETCTRL:
+		return pcf8583_get_ctrl(client, arg);
+
+	case RTC_SETCTRL:
+		return pcf8583_set_ctrl(client, arg);
+
+	case MEM_READ:
+		return pcf8583_read_mem(client, arg);
+
+	case MEM_WRITE:
+		return pcf8583_write_mem(client, arg);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct i2c_driver pcf8583_driver = {
+	"PCF8583",
+	I2C_DRIVERID_PCF8583,
+	I2C_DF_NOTIFY,
+	pcf8583_probe,
+	pcf8583_detach,
+	pcf8583_command
+};
+
+static __init int pcf8583_init(void)
+{
+	return i2c_add_driver(&pcf8583_driver);
+}
+
+__initcall(pcf8583_init);
diff -u --recursive --new-file v2.3.42/linux/drivers/acorn/char/pcf8583.h linux/drivers/acorn/char/pcf8583.h
--- v2.3.42/linux/drivers/acorn/char/pcf8583.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/pcf8583.h	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,32 @@
+struct rtc_tm {
+	unsigned char	cs;
+	unsigned char	secs;
+	unsigned char	mins;
+	unsigned char	hours;
+	unsigned char	mday;
+	unsigned char	mon;
+	unsigned char	year_off;
+	unsigned char	wday;
+};
+
+struct mem {
+	unsigned int	loc;
+	unsigned int	nr;
+	unsigned char	*data;
+};
+
+#define RTC_GETDATETIME	0
+#define RTC_SETTIME	1
+#define RTC_SETDATETIME	2
+#define RTC_GETCTRL	3
+#define RTC_SETCTRL	4
+#define MEM_READ	5
+#define MEM_WRITE	6
+
+#define CTRL_STOP	0x80
+#define CTRL_HOLD	0x40
+#define CTRL_32KHZ	0x00
+#define CTRL_MASK	0x08
+#define CTRL_ALARMEN	0x04
+#define CTRL_ALARM	0x02
+#define CTRL_TIMER	0x01
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/Config.in linux/drivers/atm/Config.in
--- v2.3.42/linux/drivers/atm/Config.in	Sat Oct  9 11:47:50 1999
+++ linux/drivers/atm/Config.in	Tue Feb  8 18:23:13 2000
@@ -8,7 +8,7 @@
 fi
 if [ "$CONFIG_PCI" = "y" ]; then
    tristate 'Efficient Networks ENI155P' CONFIG_ATM_ENI
-   if [ ! "$CONFIG_ATM_ENI" = "n" ]; then
+   if [ "$CONFIG_ATM_ENI" != "n" ]; then
       bool '  Enable extended debugging' CONFIG_ATM_ENI_DEBUG
       bool '  Fine-tune burst settings' CONFIG_ATM_ENI_TUNE_BURST
       if [ "$CONFIG_ATM_ENI_TUNE_BURST" = "y" ]; then
@@ -23,17 +23,20 @@
       fi
    fi
    tristate 'ZeitNet ZN1221/ZN1225' CONFIG_ATM_ZATM
-   if [ ! "$CONFIG_ATM_ZATM" = "n" ]; then
+   if [ "$CONFIG_ATM_ZATM" != "n" ]; then
       bool '  Enable extended debugging' CONFIG_ATM_ZATM_DEBUG
-      bool '  Enable usec resolution timestamps' CONFIG_ATM_ZATM_EXACT_TS
+      if [ "$CONFIG_X86" = "y" ]; then
+	bool '  Enable usec resolution timestamps' CONFIG_ATM_ZATM_EXACT_TS
+      fi
    fi
 #   bool 'Rolfs TI TNETA1570' CONFIG_ATM_TNETA1570 y
 #   if [ "$CONFIG_ATM_TNETA1570" = "y" ]; then
 #      bool '  Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n
 #   fi
-   tristate 'IDT 77201 (NICStAR)' CONFIG_ATM_NICSTAR
+   tristate 'IDT 77201 (NICStAR) (ForeRunnerLE)' CONFIG_ATM_NICSTAR
    if [ "$CONFIG_ATM_NICSTAR" != "n" ]; then
-      bool '  Use suni PHY driver' CONFIG_ATM_NICSTAR_USE_SUNI
+      bool '  Use suni PHY driver (155Mbps)' CONFIG_ATM_NICSTAR_USE_SUNI
+      bool '  Use IDT77015 PHY driver (25Mbps)' CONFIG_ATM_NICSTAR_USE_IDT77105
    fi
    tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR
    if [ "$CONFIG_ATM_AMBASSADOR" != "n" ]; then
@@ -43,5 +46,9 @@
    if [ "$CONFIG_ATM_HORIZON" != "n" ]; then
       bool '  Enable debugging messages' CONFIG_ATM_HORIZON_DEBUG
    fi
+    tristate 'Interphase ATM PCI x575/x525/x531' CONFIG_ATM_IA
+    if [ "$CONFIG_ATM_IA" != "n" ]; then
+      bool '  Enable debugging messages' CONFIG_ATM_IA_DEBUG
+    fi
 fi
 endmenu
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/Makefile linux/drivers/atm/Makefile
--- v2.3.42/linux/drivers/atm/Makefile	Fri Sep 10 23:57:29 1999
+++ linux/drivers/atm/Makefile	Tue Feb  8 18:23:13 2000
@@ -34,21 +34,23 @@
 L_OBJS += tneta1570.o suni.o
 endif
 
-ifeq ($(CONFIG_ATM_FORE200),y)
-L_OBJS += fore200.o
-endif
-
 ifeq ($(CONFIG_ATM_NICSTAR),y)
 L_OBJS += nicstar.o
   ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
   NEED_SUNI_LX = suni.o
   endif
+  ifeq ($(CONFIG_ATM_NICSTAR_USE_IDT77105),y)
+  NEED_IDT77105_LX = idt77105.o
+  endif
 else
   ifeq ($(CONFIG_ATM_NICSTAR),m)
   M_OBJS += nicstar.o
     ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
     NEED_SUNI_MX = suni.o
     endif
+    ifeq ($(CONFIG_ATM_NICSTAR_USE_IDT77105),y)
+    NEED_SUNI_MX = idt77105.o
+    endif
   endif
 endif
 
@@ -68,18 +70,34 @@
   endif
 endif
 
+ifeq ($(CONFIG_ATM_TCP),y)
+L_OBJS += atmtcp.o
+else
+  ifeq ($(CONFIG_ATM_TCP),m)
+  M_OBJS += atmtcp.o
+  endif
+endif
+
+ifeq ($(CONFIG_ATM_IA),y)
+L_OBJS += iphase.o
+NEED_SUNI_LX = suni.o
+else
+ifeq ($(CONFIG_ATM_IA),m)
+  M_OBJS += iphase.o
+  NEED_SUNI_MX = suni.o
+  endif
+endif
+
 ifeq ($(NEED_SUNI_LX),)
   MX_OBJS += $(NEED_SUNI_MX)
 else
   LX_OBJS += $(NEED_SUNI_LX)
 endif
 
-ifeq ($(CONFIG_ATM_TCP),y)
-L_OBJS += atmtcp.o
+ifeq ($(NEED_IDT77105_LX),)
+  MX_OBJS += $(NEED_IDT77105_MX)
 else
-  ifeq ($(CONFIG_ATM_TCP),m)
-  M_OBJS += atmtcp.o
-  endif
+  LX_OBJS += $(NEED_IDT77105_LX)
 endif
 
 EXTRA_CFLAGS=-g
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/ambassador.c linux/drivers/atm/ambassador.c
--- v2.3.42/linux/drivers/atm/ambassador.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/atm/ambassador.c	Tue Feb  8 18:23:13 2000
@@ -1405,7 +1405,7 @@
     dont_panic (dev);
   } else {
     // moan
-    return -EINVAL;
+    return -ENOIOCTLCMD;
   }
 }
 #endif
@@ -1654,21 +1654,11 @@
 /********** Operation Structure **********/
 
 static const struct atmdev_ops amb_ops = {
-  NULL,          // no amb_dev_close
-  amb_open,
-  amb_close,
-  NULL,          // no amb_ioctl,
-  NULL,          // no amb_getsockopt,
-  NULL,          // no amb_setsockopt,
-  amb_send,
-  amb_sg_send,
-  NULL,          // no send_oam    - not in fact used yet
-  NULL,          // no amb_phy_put - not needed in this driver 
-  NULL,          // no amb_phy_get - not needed in this driver 
-  NULL,          // no feedback    - feedback to the driver!
-  NULL,          // no amb_change_qos
-  NULL,          // amb_free_rx_skb not used until checked by someone else
-  amb_proc_read
+  open:		amb_open,
+  close:	amb_close,
+  send:		amb_send,
+  sg_send:	amb_sg_send,
+  proc_read:	amb_proc_read
 };
 
 /********** housekeeping **********/
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/atmdev_init.c linux/drivers/atm/atmdev_init.c
--- v2.3.42/linux/drivers/atm/atmdev_init.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/atm/atmdev_init.c	Tue Feb  8 18:23:13 2000
@@ -16,9 +16,6 @@
 #ifdef CONFIG_ATM_TNETA1570
 extern int tneta1570_detect(void);
 #endif
-#ifdef CONFIG_ATM_FORE200
-extern int fore200_detect(void);
-#endif
 #ifdef CONFIG_ATM_NICSTAR
 extern int nicstar_detect(void);
 #endif
@@ -28,6 +25,9 @@
 #ifdef CONFIG_ATM_HORIZON
 extern int hrz_detect(void);
 #endif
+#ifdef CONFIG_ATM_IA
+extern int ia_detect(void);
+#endif
 
 
 int __init atmdev_init(void)
@@ -44,9 +44,6 @@
 #ifdef CONFIG_ATM_TNETA1570
 	devs += tneta1570_detect();
 #endif
-#ifdef CONFIG_ATM_FORE200
-	devs += fore200_detect();
-#endif
 #ifdef CONFIG_ATM_NICSTAR
 	devs += nicstar_detect();
 #endif
@@ -55,6 +52,9 @@
 #endif
 #ifdef CONFIG_ATM_HORIZON
 	devs += hrz_detect();
+#endif
+#ifdef CONFIG_ATM_IA
+	devs += ia_detect();
 #endif
 	return devs;
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/atmsar11.data linux/drivers/atm/atmsar11.data
--- v2.3.42/linux/drivers/atm/atmsar11.data	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/atmsar11.data	Tue Feb  8 18:23:13 2000
@@ -2,12 +2,12 @@
   Madge Ambassador ATM Adapter microcode.
   Copyright (C) 1995-1999  Madge Networks Ltd.
   
-  This is provided here for your convenience only.
+  This microcode data is placed under the terms of the GNU General
+  Public License. The GPL is contained in /usr/doc/copyright/GPL on a
+  Debian system and in the file COPYING in the Linux kernel source.
   
-  No restrictions are placed on its use, so long as this file remains
-  unchanged.
-  
-  You may not make, use or re-distribute modified versions of this code.
+  We would prefer you not to distribute modified versions without
+  consultation and not to ask for assembly/other microcode source.
 */
 
   0x401a6800,
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/atmsar11.regions linux/drivers/atm/atmsar11.regions
--- v2.3.42/linux/drivers/atm/atmsar11.regions	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/atmsar11.regions	Tue Feb  8 18:23:13 2000
@@ -1,3 +1,6 @@
+/*
+  See copyright and licensing conditions in ambassador.* files.
+*/
   { 0x00000080,  993, },
   { 0xa0d0d500,   80, },
   { 0xa0d0f000,  978, },
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/atmsar11.start linux/drivers/atm/atmsar11.start
--- v2.3.42/linux/drivers/atm/atmsar11.start	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/atmsar11.start	Tue Feb  8 18:23:13 2000
@@ -1 +1,4 @@
+/*
+  See copyright and licensing conditions in ambassador.* files.
+*/
   0xa0d0f000
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/atmtcp.c linux/drivers/atm/atmtcp.c
--- v2.3.42/linux/drivers/atm/atmtcp.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/atm/atmtcp.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
 
-/* Written 1997-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/module.h>
@@ -8,7 +8,9 @@
 #include <linux/atmdev.h>
 #include <linux/atm_tcp.h>
 #include <asm/uaccess.h>
-#include "../../net/atm/protocols.h" /* @@@ fix this */
+
+
+extern int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
 
 
 #define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data))
@@ -56,7 +58,8 @@
 	*new_msg = *msg;
 	new_msg->hdr.length = ATMTCP_HDR_MAGIC;
 	new_msg->type = type;
-	new_msg->vcc = (unsigned long) vcc;
+	memset(&new_msg->vcc,0,sizeof(atm_kptr_t));
+	*(struct atm_vcc **) &new_msg->vcc = vcc;
 	old_flags = vcc->flags;
 	out_vcc->push(out_vcc,skb);
 	while (!((vcc->flags ^ old_flags) & flag)) {
@@ -72,7 +75,7 @@
 
 static int atmtcp_recv_control(const struct atmtcp_control *msg)
 {
-	struct atm_vcc *vcc = (struct atm_vcc *) msg->vcc;
+	struct atm_vcc *vcc = *(struct atm_vcc **) &msg->vcc;
 
 	vcc->vpi = msg->addr.sap_addr.vpi;
 	vcc->vci = msg->addr.sap_addr.vci;
@@ -143,7 +146,7 @@
 	struct atm_cirange ci;
 	struct atm_vcc *vcc;
 
-	if (cmd != ATM_SETCIRANGE) return -EINVAL;
+	if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD;
 	if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
 	if (ci.vpi_bits == ATM_CI_MAX) ci.vpi_bits = MAX_VPI_BITS;
 	if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS;
@@ -190,6 +193,8 @@
 	if (vcc->pop) vcc->pop(vcc,skb);
 	else dev_kfree_skb(skb);
 	out_vcc->push(out_vcc,new_skb);
+	vcc->stats->tx++;
+	out_vcc->stats->rx++;
 	return 0;
 }
 
@@ -258,6 +263,8 @@
 	new_skb->stamp = xtime;
 	memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
 	out_vcc->push(out_vcc,new_skb);
+	vcc->stats->tx++;
+	out_vcc->stats->rx++;
 done:
 	if (vcc->pop) vcc->pop(vcc,skb);
 	else dev_kfree_skb(skb);
@@ -271,21 +278,12 @@
 
 
 static struct atmdev_ops atmtcp_v_dev_ops = {
-	atmtcp_v_dev_close,
-	atmtcp_v_open,
-	atmtcp_v_close,
-	atmtcp_v_ioctl,
-	NULL,		/* no getsockopt */
-	NULL,		/* no setsockopt */
-	atmtcp_v_send,
-	NULL,		/* no direct writes */
-	NULL,		/* no send_oam */
-	NULL,		/* no phy_put */
-	NULL,		/* no phy_get */
-	NULL,		/* no feedback */
-	NULL,		/* no change_qos */
-	NULL,		/* no free_rx_skb */
-	atmtcp_v_proc	/* proc_read */
+	dev_close:	atmtcp_v_dev_close,
+	open:		atmtcp_v_open,
+	close:		atmtcp_v_close,
+	ioctl:		atmtcp_v_ioctl,
+	send:		atmtcp_v_send,
+	proc_read:	atmtcp_v_proc
 };
 
 
@@ -295,21 +293,8 @@
 
 
 static struct atmdev_ops atmtcp_c_dev_ops = {
-	NULL,		/* no dev_close */
-	NULL,		/* no open */
-	atmtcp_c_close,
-	NULL,		/* no ioctl */
-	NULL,		/* no getsockopt */
-	NULL,		/* no setsockopt */
-	atmtcp_c_send,
-	NULL,		/* no sg_send */
-	NULL,		/* no send_oam */
-	NULL,		/* no phy_put */
-	NULL,		/* no phy_get */
-	NULL,		/* no feedback */
-	NULL,		/* no change_qos */
-	NULL,		/* no free_rx_skb */
-	NULL		/* no proc_read */
+	close:		atmtcp_c_close,
+	send:		atmtcp_c_send
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/eni.c linux/drivers/atm/eni.c
--- v2.3.42/linux/drivers/atm/eni.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/atm/eni.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* drivers/atm/eni.c - Efficient Networks ENI155P device driver */
  
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  
 
 #include <linux/module.h>
@@ -774,7 +774,7 @@
 	eni_vcc = ENI_VCC(vcc);
 	eni_vcc->rx = NULL;
 	if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0;
-	size = vcc->qos.rxtp.max_sdu*3; /* @@@ improve this */
+	size = vcc->qos.rxtp.max_sdu*eni_dev->rx_mult/100;
 	if (size > MID_MAX_BUF_SIZE && vcc->qos.rxtp.max_sdu <=
 	    MID_MAX_BUF_SIZE)
 		size = MID_MAX_BUF_SIZE;
@@ -885,6 +885,7 @@
 		return -ENOMEM;
 	}
 	memset(eni_dev->rx_map,0,PAGE_SIZE);
+	eni_dev->rx_mult = DEFAULT_RX_MULT;
 	eni_dev->fast = eni_dev->last_fast = NULL;
 	eni_dev->slow = eni_dev->last_slow = NULL;
 	init_waitqueue_head(&eni_dev->rx_wait);
@@ -1151,7 +1152,8 @@
 		if (tx->send)
 			while ((skb = skb_dequeue(&tx->backlog))) {
 				res = do_tx(skb);
-				if (res != enq_ok) {
+				if (res == enq_ok) tx->backlog_len--;
+				else {
 					DPRINTK("re-queuing TX PDU\n");
 					skb_queue_head(&tx->backlog,skb);
 requeued++;
@@ -1258,7 +1260,7 @@
 	unlimited = ubr && (!rate || rate <= -ATM_OC3_PCR ||
 	    rate >= ATM_OC3_PCR);
 	if (!unlimited) {
-		size = txtp->max_sdu*3; /* @@@ improve */
+		size = txtp->max_sdu*eni_dev->tx_mult/100;
 		if (size > MID_MAX_BUF_SIZE && txtp->max_sdu <=
 		    MID_MAX_BUF_SIZE)
 			size = MID_MAX_BUF_SIZE;
@@ -1287,6 +1289,7 @@
 		tx->send = mem;
 		tx->words = size >> 2;
 		skb_queue_head_init(&tx->backlog);
+		tx->backlog_len = 0;
 		for (order = 0; size > (1 << (order+10)); order++);
 		eni_out((order << MID_SIZE_SHIFT) |
 		    ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)),
@@ -1390,6 +1393,7 @@
 	eni_dev = ENI_DEV(dev);
 	eni_dev->lost = 0;
 	eni_dev->tx_bw = ATM_OC3_PCR;
+	eni_dev->tx_mult = DEFAULT_TX_MULT;
 	init_waitqueue_head(&eni_dev->tx_wait);
 	eni_dev->ubr = NULL;
 	skb_queue_head_init(&eni_dev->tx_queue);
@@ -1643,7 +1647,7 @@
 	struct midway_eprom *eprom;
 	struct eni_dev *eni_dev;
 	struct pci_dev *pci_dev;
-	unsigned int real_base,base;
+	unsigned long real_base,base;
 	unsigned char revision;
 	int error,i,last;
 
@@ -1668,7 +1672,7 @@
 		    "(0x%02x)\n",dev->number,error);
 		return error;
 	}
-	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%x,irq=%d,",
+	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
 	    dev->number,revision,real_base,eni_dev->irq);
 	if (!(base = (unsigned long) ioremap_nocache(real_base,MAP_MAX_SIZE))) {
 		printk("\n");
@@ -1748,6 +1752,10 @@
 		    "master (0x%02x)\n",dev->number,error);
 		return error;
 	}
+#ifdef __sparc_v9__ /* copied from drivers/net/sunhme.c */
+	/* NOTE: Cache line size is in 32-bit word units. */
+	pci_write_config_byte(eni_dev->pci_dev, PCI_CACHE_LINE_SIZE, 0x10);
+#endif
 	if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,
 	    END_SWAP_DMA))) {
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "
@@ -1947,12 +1955,29 @@
 
 static int eni_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
 {
+	struct eni_dev *eni_dev = ENI_DEV(dev);
+
 	if (cmd == ENI_MEMDUMP) {
+		if (!capable(CAP_NET_ADMIN)) return -EPERM;
 		printk(KERN_WARNING "Please use /proc/atm/" DEV_LABEL ":%d "
 		    "instead of obsolete ioctl ENI_MEMDUMP\n",dev->number);
 		dump(dev);
 		return 0;
 	}
+	if (cmd == ENI_SETMULT) {
+		struct eni_multipliers mult;
+
+		if (!capable(CAP_NET_ADMIN)) return -EPERM;
+		if (copy_from_user(&mult,(void *) arg,
+		    sizeof(struct eni_multipliers)))
+			return -EFAULT;
+		if ((mult.tx && mult.tx <= 100) || (mult.rx &&mult.rx <= 100) ||
+		    mult.tx > 65536 || mult.rx > 65536)
+			return -EINVAL;
+		if (mult.tx) eni_dev->tx_mult = mult.tx;
+		if (mult.rx) eni_dev->rx_mult = mult.rx;
+		return 0;
+	}
 	if (cmd == ATM_SETCIRANGE) {
 		struct atm_cirange ci;
 
@@ -1963,7 +1988,7 @@
 		    return 0;
 		return -EINVAL;
 	}
-	if (!dev->phy->ioctl) return -EINVAL;
+	if (!dev->phy->ioctl) return -ENOIOCTLCMD;
 	return dev->phy->ioctl(dev,cmd,arg);
 }
 
@@ -1971,21 +1996,6 @@
 static int eni_getsockopt(struct atm_vcc *vcc,int level,int optname,
     void *optval,int optlen)
 {
-#ifdef CONFIG_MMU_HACKS
-
-static const struct atm_buffconst bctx = { PAGE_SIZE,0,PAGE_SIZE,0,0,0 };
-static const struct atm_buffconst bcrx = { PAGE_SIZE,0,PAGE_SIZE,0,0,0 };
-
-#else
-
-static const struct atm_buffconst bctx = { sizeof(int),0,sizeof(int),0,0,0 };
-static const struct atm_buffconst bcrx = { sizeof(int),0,sizeof(int),0,0,0 };
-
-#endif
-	if (level == SOL_AAL && (optname == SO_BCTXOPT ||
-	    optname == SO_BCRXOPT))
-		return copy_to_user(optval,optname == SO_BCTXOPT ? &bctx :
-		      &bcrx,sizeof(struct atm_buffconst)) ? -EFAULT : 0;
 	return -EINVAL;
 }
 
@@ -2027,7 +2037,8 @@
 	cli(); /* brute force */
 	if (skb_peek(&ENI_VCC(vcc)->tx->backlog) || do_tx(skb)) {
 		skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
-		backlogged++;
+		ENI_VCC(vcc)->tx->backlog_len++;
+backlogged++;
 	}
 	restore_flags(flags);
 	return 0;
@@ -2068,9 +2079,8 @@
 		return sprintf(page,DEV_LABEL "(itf %d) signal %s, %dkB, "
 		    "%d cps remaining\n",dev->number,signal[(int) dev->signal],
 		    eni_dev->mem >> 10,eni_dev->tx_bw);
-	left--;
-	if (!left)
-		return sprintf(page,"Bursts: TX"
+	if (!--left)
+		return sprintf(page,"%4sBursts: TX"
 #if !defined(CONFIG_ATM_ENI_BURST_TX_16W) && \
     !defined(CONFIG_ATM_ENI_BURST_TX_8W) && \
     !defined(CONFIG_ATM_ENI_BURST_TX_4W) && \
@@ -2111,18 +2121,25 @@
 #ifndef CONFIG_ATM_ENI_TUNE_BURST
 		    " (default)"
 #endif
-		    "\n");
+		    "\n","");
+	if (!--left) 
+		return sprintf(page,"%4sBuffer multipliers: tx %d%%, rx %d%%\n",
+		    "",eni_dev->tx_mult,eni_dev->rx_mult);
 	for (i = 0; i < NR_CHAN; i++) {
 		struct eni_tx *tx = eni_dev->tx+i;
 
 		if (!tx->send) continue;
+		if (!--left) {
+			return sprintf(page,"tx[%d]:    0x%06lx-0x%06lx "
+			    "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
+			    tx->send-eni_dev->ram,
+			    tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
+			    tx->reserved,tx->shaping,
+			    tx == eni_dev->ubr ? " (UBR)" : "");
+		}
 		if (--left) continue;
-		return sprintf(page,"tx[%d]:    0x%06lx-0x%06lx (%6ld bytes), "
-		    "rsv %d cps, shp %d cps%s\n",i,
-		    tx->send-eni_dev->ram,
-		    tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
-		    tx->reserved,tx->shaping,
-		    tx == eni_dev->ubr ? " (UBR)" : "");
+		return sprintf(page,"%10sbacklog %d bytes\n","",
+		    tx->backlog_len);
 	}
 	for (vcc = dev->vccs; vcc; vcc = vcc->next) {
 		struct eni_vcc *eni_vcc = ENI_VCC(vcc);
@@ -2139,8 +2156,8 @@
 			if (eni_vcc->tx) length += sprintf(page+length,", ");
 		}
 		if (eni_vcc->tx)
-			length += sprintf(page+length,"tx[%d]",
-			    eni_vcc->tx->index);
+			length += sprintf(page+length,"tx[%d], txing %d bytes",
+			    eni_vcc->tx->index,eni_vcc->txing);
 		page[length] = '\n';
 		return length+1;
 	}
@@ -2159,21 +2176,17 @@
 
 
 static const struct atmdev_ops ops = {
-	NULL,			/* no dev_close */
-	eni_open,
-	eni_close,
-	eni_ioctl,
-	eni_getsockopt,
-	eni_setsockopt,
-	eni_send,
-	eni_sg_send,
-	NULL,			/* no send_oam */
-	eni_phy_put,
-	eni_phy_get,
-	NULL,			/* no feedback */
-	eni_change_qos,		/* no change_qos */
-	NULL,			/* no free_rx_skb */
-	eni_proc_read
+	open:		eni_open,
+	close:		eni_close,
+	ioctl:		eni_ioctl,
+	getsockopt:	eni_getsockopt,
+	setsockopt:	eni_setsockopt,
+	send:		eni_send,
+	sg_send:	eni_sg_send,
+	phy_put:	eni_phy_put,
+	phy_get:	eni_phy_get,
+	change_qos:	eni_change_qos,
+	proc_read:	eni_proc_read
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/eni.h linux/drivers/atm/eni.h
--- v2.3.42/linux/drivers/atm/eni.h	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/eni.h	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  
  
 #ifndef DRIVER_ATM_ENI_H
@@ -24,6 +24,9 @@
 #define RX_DMA_BUF	  8		/* burst and skip a few things */
 #define TX_DMA_BUF	100		/* should be enough for 64 kB */
 
+#define DEFAULT_RX_MULT	300		/* max_sdu*3 */
+#define DEFAULT_TX_MULT	300		/* max_sdu*3 */
+
 
 struct eni_free {
 	unsigned long start;		/* counting in bytes */
@@ -40,6 +43,7 @@
 	int reserved;			/* reserved peak cell rate */
 	int shaping;			/* shaped peak cell rate */
 	struct sk_buff_head backlog;	/* queue of waiting TX buffers */
+	int backlog_len;		/* length of backlog in bytes */
 };
 
 struct eni_vcc {
@@ -51,7 +55,7 @@
 	struct eni_tx *tx;		/* TXer, NULL if none */
 	int rxing;			/* number of pending PDUs */
 	int servicing;			/* number of waiting VCs (0 or 1) */
-	int txing;			/* number of pending TX cells/PDUs */
+	int txing;			/* number of pending TX bytes */
 	struct timeval timestamp;	/* for RX timing */
 	struct atm_vcc *next;		/* next pending RX */
 	struct sk_buff *last;		/* last PDU being DMAed (used to carry
@@ -75,6 +79,7 @@
 	wait_queue_head_t tx_wait;	/* for close */
 	int tx_bw;			/* remaining bandwidth */
 	u32 dma[TX_DMA_BUF*2];		/* DMA request scratch area */
+	int tx_mult;			/* buffer size multiplier (percent) */
 	/*-------------------------------- RX part */
 	u32 serv_read;			/* host service read index */
 	struct atm_vcc *fast,*last_fast;/* queues of VCCs with pending PDUs */
@@ -82,6 +87,7 @@
 	struct atm_vcc **rx_map;	/* for fast lookups */
 	struct sk_buff_head rx_queue;	/* PDUs currently being RX-DMAed */
 	wait_queue_head_t rx_wait;	/* for close */
+	int rx_mult;			/* buffer size multiplier (percent) */
 	/*-------------------------------- statistics */
 	unsigned long lost;		/* number of lost cells (RX) */
 	/*-------------------------------- memory management */
@@ -94,7 +100,7 @@
 	/*-------------------------------- general information */
 	int mem;			/* RAM on board (in bytes) */
 	int asic;			/* PCI interface type, 0 for FPGA */
-	unsigned char irq;		/* IRQ */
+	unsigned int irq;		/* IRQ */
 	struct pci_dev *pci_dev;	/* PCI stuff */
 };
 
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/horizon.c linux/drivers/atm/horizon.c
--- v2.3.42/linux/drivers/atm/horizon.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/atm/horizon.c	Tue Feb  8 18:23:13 2000
@@ -2623,12 +2623,10 @@
   switch (level) {
     case SOL_SOCKET:
       switch (optname) {
-	case SO_BCTXOPT:
-	  // return the right thing
-	  break;
-	case SO_BCRXOPT:
-	  // return the right thing
-	  break;
+//	case SO_BCTXOPT:
+//	  break;
+//	case SO_BCRXOPT:
+//	  break;
 	default:
 	  return -ENOPROTOOPT;
 	  break;
@@ -2645,12 +2643,10 @@
   switch (level) {
     case SOL_SOCKET:
       switch (optname) {
-	case SO_BCTXOPT:
-	  // not settable
-	  break;
-	case SO_BCRXOPT:
-	  // not settable
-	  break;
+//	case SO_BCTXOPT:
+//	  break;
+//	case SO_BCRXOPT:
+//	  break;
 	default:
 	  return -ENOPROTOOPT;
 	  break;
@@ -2743,21 +2739,11 @@
 }
 
 static const struct atmdev_ops hrz_ops = {
-  NULL,          // no hrz_dev_close
-  hrz_open,
-  hrz_close,
-  NULL,          // no hrz_ioctl
-  NULL,          // hrz_getsockopt,
-  NULL,          // hrz_setsockopt,
-  hrz_send,
-  hrz_sg_send,
-  NULL,          // no send_oam    - not in fact used yet
-  NULL,          // no hrz_phy_put - not needed in this driver 
-  NULL,          // no hrz_phy_get - not needed in this driver 
-  NULL,          // no feedback    - feedback to the driver!
-  NULL,          // no hrz_change_qos
-  NULL,          // no free_rx_skb
-  hrz_proc_read
+  open:		hrz_open,
+  close:	hrz_close,
+  send:		hrz_send,
+  sg_send:	hrz_sg_send,
+  proc_read:	hrz_proc_read
 };
 
 static int __init hrz_probe (void) {
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/idt77105.c linux/drivers/atm/idt77105.c
--- v2.3.42/linux/drivers/atm/idt77105.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/atm/idt77105.c	Tue Feb  8 18:23:13 2000
@@ -0,0 +1,385 @@
+/* drivers/atm/idt77105.c - IDT77105 (PHY) driver */
+ 
+/* Written 1999 by Greg Banks, NEC Australia <gnb@linuxfan.com>. Based on suni.c */
+
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/atmdev.h>
+#include <linux/sonet.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/atm_idt77105.h>
+#include <asm/system.h>
+#include <asm/param.h>
+#include <asm/uaccess.h>
+
+#include "idt77105.h"
+
+#undef GENERAL_DEBUG
+
+#ifdef GENERAL_DEBUG
+#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
+#else
+#define DPRINTK(format,args...)
+#endif
+
+
+struct idt77105_priv {
+	struct idt77105_stats stats;    /* link diagnostics */
+	struct atm_dev *dev;		/* device back-pointer */
+	struct idt77105_priv *next;
+        int loop_mode;
+        unsigned char old_mcr;          /* storage of MCR reg while signal lost */
+};
+
+
+#define PRIV(dev) ((struct idt77105_priv *) dev->phy_data)
+
+#define PUT(val,reg) dev->ops->phy_put(dev,val,IDT77105_##reg)
+#define GET(reg) dev->ops->phy_get(dev,IDT77105_##reg)
+
+static void idt77105_stats_timer_func(unsigned long);
+static void idt77105_restart_timer_func(unsigned long);
+
+
+static struct timer_list stats_timer = { NULL, NULL, 0L, 0L,
+                                         &idt77105_stats_timer_func };
+static struct timer_list restart_timer = { NULL, NULL, 0L, 0L, 
+                                           &idt77105_restart_timer_func };
+static int start_timer = 1;
+static struct idt77105_priv *idt77105_all = NULL;
+
+/*
+ * Retrieve the value of one of the IDT77105's counters.
+ * `counter' is one of the IDT77105_CTRSEL_* constants.
+ */
+static u16 get_counter(struct atm_dev *dev, int counter)
+{
+        u16 val;
+        
+        /* write the counter bit into PHY register 6 */
+        PUT(counter, CTRSEL);
+        /* read the low 8 bits from register 4 */
+        val = GET(CTRLO);
+        /* read the high 8 bits from register 5 */
+        val |= GET(CTRHI)<<8;
+        
+        return val;
+}
+
+/*
+ * Timer function called every second to gather statistics
+ * from the 77105. This is done because the h/w registers
+ * will overflow if not read at least once per second. The
+ * kernel's stats are much higher precision. Also, having
+ * a separate copy of the stats allows implementation of
+ * an ioctl which gathers the stats *without* zero'ing them.
+ */
+static void idt77105_stats_timer_func(unsigned long dummy)
+{
+	struct idt77105_priv *walk;
+	struct atm_dev *dev;
+	struct idt77105_stats *stats;
+
+        DPRINTK("IDT77105 gathering statistics\n");
+	for (walk = idt77105_all; walk; walk = walk->next) {
+		dev = walk->dev;
+                
+		stats = &walk->stats;
+                stats->symbol_errors += get_counter(dev, IDT77105_CTRSEL_SEC);
+                stats->tx_cells += get_counter(dev, IDT77105_CTRSEL_TCC);
+                stats->rx_cells += get_counter(dev, IDT77105_CTRSEL_RCC);
+                stats->rx_hec_errors += get_counter(dev, IDT77105_CTRSEL_RHEC);
+	}
+        if (!start_timer) mod_timer(&stats_timer,jiffies+IDT77105_STATS_TIMER_PERIOD);
+}
+
+
+/*
+ * A separate timer func which handles restarting PHY chips which
+ * have had the cable re-inserted after being pulled out. This is
+ * done by polling the Good Signal Bit in the Interrupt Status
+ * register every 5 seconds. The other technique (checking Good
+ * Signal Bit in the interrupt handler) cannot be used because PHY
+ * interrupts need to be disabled when the cable is pulled out
+ * to avoid lots of spurious cell error interrupts.
+ */
+static void idt77105_restart_timer_func(unsigned long dummy)
+{
+	struct idt77105_priv *walk;
+	struct atm_dev *dev;
+        unsigned char istat;
+
+        DPRINTK("IDT77105 checking for cable re-insertion\n");
+	for (walk = idt77105_all; walk; walk = walk->next) {
+		dev = walk->dev;
+                
+                if (dev->signal != ATM_PHY_SIG_LOST)
+                    continue;
+                    
+                istat = GET(ISTAT); /* side effect: clears all interrupt status bits */
+                if (istat & IDT77105_ISTAT_GOODSIG) {
+                    /* Found signal again */
+                    dev->signal = ATM_PHY_SIG_FOUND;
+	            printk(KERN_NOTICE "%s(itf %d): signal detected again\n",
+                        dev->type,dev->number);
+                    /* flush the receive FIFO */
+                    PUT( GET(DIAG) | IDT77105_DIAG_RFLUSH, DIAG);
+                    /* re-enable interrupts */
+	            PUT( walk->old_mcr ,MCR);
+                }
+	}
+        if (!start_timer) mod_timer(&restart_timer,jiffies+IDT77105_RESTART_TIMER_PERIOD);
+}
+
+
+static int fetch_stats(struct atm_dev *dev,struct idt77105_stats *arg,int zero)
+{
+	unsigned long flags;
+	int error;
+
+	error = 0;
+	save_flags(flags);
+	cli();
+	if (arg)
+		error = copy_to_user(arg,&PRIV(dev)->stats,
+		    sizeof(struct idt77105_stats));
+	if (zero && !error)
+		memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats));
+	restore_flags(flags);
+	return error ? -EFAULT : sizeof(struct idt77105_stats);
+}
+
+
+
+static int idt77105_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
+{
+        printk(KERN_NOTICE "%s(%d) idt77105_ioctl() called\n",dev->type,dev->number);
+	switch (cmd) {
+		case IDT77105_GETSTATZ:
+		case IDT77105_GETSTAT:
+			return fetch_stats(dev,(struct idt77105_stats *) arg,
+			    cmd == IDT77105_GETSTATZ);
+		case IDT77105_SETLOOP:
+			if (!capable(CAP_NET_ADMIN)) return -EPERM;
+			if ((int) arg < 0 || (int) arg > IDT77105_LM_LOOP)
+				return -EINVAL;
+			PUT((GET(DIAG) & ~IDT77105_DIAG_LCMASK) |
+			    ((int) arg == IDT77105_LM_NONE ? IDT77105_DIAG_LC_NORMAL : 0) |
+			    ((int) arg == IDT77105_LM_DIAG ? IDT77105_DIAG_LC_PHY_LOOPBACK : 0) |
+			    ((int) arg == IDT77105_LM_LOOP ? IDT77105_DIAG_LC_LINE_LOOPBACK : 0),
+                            DIAG);
+                        printk(KERN_NOTICE "%s(%d) Loopback mode is: %s\n",
+                            dev->type, dev->number,
+                            ((int) arg == IDT77105_LM_NONE ? "NONE" : 
+                                ((int) arg == IDT77105_LM_DIAG ? "DIAG (local)" :
+			            ((int) arg == IDT77105_LM_LOOP ? "LOOP (remote)" :
+                                        "unknown")))
+                            );
+			PRIV(dev)->loop_mode = (int) arg;
+			return 0;
+		case IDT77105_GETLOOP:
+			return put_user(PRIV(dev)->loop_mode,(int *) arg) ?
+			    -EFAULT : sizeof(int);
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+
+
+static void idt77105_int(struct atm_dev *dev)
+{
+        unsigned char istat;
+        
+        istat = GET(ISTAT); /* side effect: clears all interrupt status bits */
+     
+        DPRINTK("IDT77105 generated an interrupt, istat=%02x\n", (unsigned)istat);
+                
+        if (istat & IDT77105_ISTAT_RSCC) {
+            /* Rx Signal Condition Change - line went up or down */
+            if (istat & IDT77105_ISTAT_GOODSIG) {   /* signal detected again */
+                /* This should not happen (restart timer does it) but JIC */
+                dev->signal = ATM_PHY_SIG_FOUND;
+            } else {    /* signal lost */
+                /*
+                 * Disable interrupts and stop all transmission and
+                 * reception - the restart timer will restore these.
+                 */
+                PRIV(dev)->old_mcr = GET(MCR);
+	        PUT(
+                    (PRIV(dev)->old_mcr|
+                    IDT77105_MCR_DREC|
+                    IDT77105_MCR_DRIC|
+                    IDT77105_MCR_HALTTX
+                    ) & ~IDT77105_MCR_EIP, MCR);
+                dev->signal = ATM_PHY_SIG_LOST;
+	        printk(KERN_NOTICE "%s(itf %d): signal lost\n",
+                    dev->type,dev->number);
+            }
+        }
+        
+        if (istat & IDT77105_ISTAT_RFO) {
+            /* Rx FIFO Overrun -- perform a FIFO flush */
+            PUT( GET(DIAG) | IDT77105_DIAG_RFLUSH, DIAG);
+	    printk(KERN_NOTICE "%s(itf %d): receive FIFO overrun\n",
+                dev->type,dev->number);
+        }
+#ifdef GENERAL_DEBUG
+        if (istat & (IDT77105_ISTAT_HECERR | IDT77105_ISTAT_SCR |
+                     IDT77105_ISTAT_RSE)) {
+            /* normally don't care - just report in stats */
+	    printk(KERN_NOTICE "%s(itf %d): received cell with error\n",
+                dev->type,dev->number);
+        }
+#endif
+}
+
+
+static int idt77105_start(struct atm_dev *dev)
+{
+	unsigned long flags;
+
+	if (!(PRIV(dev) = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
+		return -ENOMEM;
+	PRIV(dev)->dev = dev;
+	save_flags(flags);
+	cli();
+	PRIV(dev)->next = idt77105_all;
+	idt77105_all = PRIV(dev);
+	restore_flags(flags);
+	memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats));
+        
+        /* initialise dev->signal from Good Signal Bit */
+        dev->signal = GET(ISTAT) & IDT77105_ISTAT_GOODSIG ? ATM_PHY_SIG_FOUND :
+	  ATM_PHY_SIG_LOST;
+	if (dev->signal == ATM_PHY_SIG_LOST)
+		printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type,
+		    dev->number);
+
+        /* initialise loop mode from hardware */
+        switch ( GET(DIAG) & IDT77105_DIAG_LCMASK ) {
+        case IDT77105_DIAG_LC_NORMAL:
+            PRIV(dev)->loop_mode = IDT77105_LM_NONE;
+            break;
+        case IDT77105_DIAG_LC_PHY_LOOPBACK:
+            PRIV(dev)->loop_mode = IDT77105_LM_DIAG;
+            break;
+        case IDT77105_DIAG_LC_LINE_LOOPBACK:
+            PRIV(dev)->loop_mode = IDT77105_LM_LOOP;
+            break;
+        }
+        
+        /* enable interrupts, e.g. on loss of signal */
+        PRIV(dev)->old_mcr = GET(MCR);
+        if (dev->signal == ATM_PHY_SIG_FOUND) {
+            PRIV(dev)->old_mcr |= IDT77105_MCR_EIP;
+	    PUT(PRIV(dev)->old_mcr, MCR);
+        }
+
+                    
+	idt77105_stats_timer_func(0); /* clear 77105 counters */
+	(void) fetch_stats(dev,NULL,1); /* clear kernel counters */
+        
+	cli();
+	if (!start_timer) restore_flags(flags);
+	else {
+		start_timer = 0;
+		restore_flags(flags);
+                
+		init_timer(&stats_timer);
+		stats_timer.expires = jiffies+IDT77105_STATS_TIMER_PERIOD;
+		stats_timer.function = idt77105_stats_timer_func;
+		add_timer(&stats_timer);
+                
+		init_timer(&restart_timer);
+		restart_timer.expires = jiffies+IDT77105_RESTART_TIMER_PERIOD;
+		restart_timer.function = idt77105_restart_timer_func;
+		add_timer(&restart_timer);
+	}
+	return 0;
+}
+
+
+static const struct atmphy_ops idt77105_ops = {
+	idt77105_start,
+	idt77105_ioctl,
+	idt77105_int
+};
+
+
+int __init idt77105_init(struct atm_dev *dev)
+{
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif /* MODULE */
+
+	dev->phy = &idt77105_ops;
+	return 0;
+}
+
+
+/*
+ * TODO: this function should be called through phy_ops
+ * but that will not be possible for some time as there is
+ * currently a freeze on modifying that structure
+ * -- Greg Banks, 13 Sep 1999
+ */
+int idt77105_stop(struct atm_dev *dev)
+{
+	struct idt77105_priv *walk, *prev;
+
+        DPRINTK("%s(itf %d): stopping IDT77105\n",dev->type,dev->number);
+        
+        /* disable interrupts */
+	PUT( GET(MCR) & ~IDT77105_MCR_EIP, MCR );
+        
+        /* detach private struct from atm_dev & free */
+	for (prev = NULL, walk = idt77105_all ;
+             walk != NULL;
+             prev = walk, walk = walk->next) {
+            if (walk->dev == dev) {
+                if (prev != NULL)
+                    prev->next = walk->next;
+                else
+                    idt77105_all = walk->next;
+	        dev->phy = NULL;
+                PRIV(dev) = NULL;
+                kfree(walk);
+                break;
+            }
+        }
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif /* MODULE */
+	return 0;
+}
+
+
+
+EXPORT_SYMBOL(idt77105_init);
+EXPORT_SYMBOL(idt77105_stop);
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	return 0;
+}
+
+
+void cleanup_module(void)
+{
+        /* turn off timers */
+        del_timer(&stats_timer);
+        del_timer(&restart_timer);
+}
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/idt77105.h linux/drivers/atm/idt77105.h
--- v2.3.42/linux/drivers/atm/idt77105.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/atm/idt77105.h	Tue Feb  8 18:23:13 2000
@@ -0,0 +1,92 @@
+/* drivers/atm/idt77105.h - IDT77105 (PHY) declarations */
+ 
+/* Written 1999 by Greg Banks, NEC Australia <gnb@linuxfan.com>. Based on suni.h */
+ 
+
+#ifndef DRIVER_ATM_IDT77105_H
+#define DRIVER_ATM_IDT77105_H
+
+#include <linux/atmdev.h>
+#include <linux/atmioc.h>
+
+
+/* IDT77105 registers */
+
+#define IDT77105_MCR		0x0	/* Master Control Register */
+#define IDT77105_ISTAT	        0x1	/* Interrupt Status */
+#define IDT77105_DIAG   	0x2	/* Diagnostic Control */
+#define IDT77105_LEDHEC		0x3	/* LED Driver & HEC Status/Control */
+#define IDT77105_CTRLO		0x4	/* Low Byte Counter Register */
+#define IDT77105_CTRHI		0x5	/* High Byte Counter Register */
+#define IDT77105_CTRSEL		0x6	/* Counter Register Read Select */
+
+/* IDT77105 register values */
+
+/* MCR */
+#define IDT77105_MCR_UPLO	0x80	/* R/W, User Prog'le Output Latch */
+#define IDT77105_MCR_DREC	0x40	/* R/W, Discard Receive Error Cells */
+#define IDT77105_MCR_ECEIO	0x20	/* R/W, Enable Cell Error Interrupts
+                                         * Only */
+#define IDT77105_MCR_TDPC	0x10	/* R/W, Transmit Data Parity Check */
+#define IDT77105_MCR_DRIC	0x08	/* R/W, Discard Received Idle Cells */
+#define IDT77105_MCR_HALTTX	0x04	/* R/W, Halt Tx */
+#define IDT77105_MCR_UMODE	0x02	/* R/W, Utopia (cell/byte) Mode */
+#define IDT77105_MCR_EIP	0x01	/* R/W, Enable Interrupt Pin */
+
+/* ISTAT */
+#define IDT77105_ISTAT_GOODSIG	0x40	/* R, Good Signal Bit */
+#define IDT77105_ISTAT_HECERR	0x20	/* sticky, HEC Error*/
+#define IDT77105_ISTAT_SCR	0x10	/* sticky, Short Cell Received */
+#define IDT77105_ISTAT_TPE	0x08	/* sticky, Transmit Parity Error */
+#define IDT77105_ISTAT_RSCC	0x04	/* sticky, Rx Signal Condition Change */
+#define IDT77105_ISTAT_RSE	0x02	/* sticky, Rx Symbol Error */
+#define IDT77105_ISTAT_RFO	0x01	/* sticky, Rx FIFO Overrun */
+
+/* DIAG */
+#define IDT77105_DIAG_FTD	0x80	/* R/W, Force TxClav deassert */
+#define IDT77105_DIAG_ROS	0x40	/* R/W, RxClav operation select */
+#define IDT77105_DIAG_MPCS	0x20	/* R/W, Multi-PHY config'n select */
+#define IDT77105_DIAG_RFLUSH	0x10	/* R/W, clear receive FIFO */
+#define IDT77105_DIAG_ITPE	0x08	/* R/W, Insert Tx payload error */
+#define IDT77105_DIAG_ITHE	0x04	/* R/W, Insert Tx HEC error */
+#define IDT77105_DIAG_UMODE	0x02	/* R/W, Utopia (cell/byte) Mode */
+#define IDT77105_DIAG_LCMASK	0x03	/* R/W, Loopback Control */
+
+#define IDT77105_DIAG_LC_NORMAL         0x00	/* Receive from network */
+#define IDT77105_DIAG_LC_PHY_LOOPBACK	0x02
+#define IDT77105_DIAG_LC_LINE_LOOPBACK	0x03
+
+/* LEDHEC */
+#define IDT77105_LEDHEC_DRHC	0x40	/* R/W, Disable Rx HEC check */
+#define IDT77105_LEDHEC_DTHC	0x20	/* R/W, Disable Tx HEC calculation */
+#define IDT77105_LEDHEC_RPWMASK	0x18	/* R/W, RxRef pulse width select */
+#define IDT77105_LEDHEC_TFS	0x04	/* R, Tx FIFO Status (1=empty) */
+#define IDT77105_LEDHEC_TLS	0x02	/* R, Tx LED Status (1=lit) */
+#define IDT77105_LEDHEC_RLS	0x01	/* R, Rx LED Status (1=lit) */
+
+#define IDT77105_LEDHEC_RPW_1	0x00	/* RxRef active for 1 RxClk cycle */
+#define IDT77105_LEDHEC_RPW_2	0x08	/* RxRef active for 2 RxClk cycle */
+#define IDT77105_LEDHEC_RPW_4	0x10	/* RxRef active for 4 RxClk cycle */
+#define IDT77105_LEDHEC_RPW_8	0x18	/* RxRef active for 8 RxClk cycle */
+
+/* CTRSEL */
+#define IDT77105_CTRSEL_SEC	0x08	/* W, Symbol Error Counter */
+#define IDT77105_CTRSEL_TCC	0x04	/* W, Tx Cell Counter */
+#define IDT77105_CTRSEL_RCC	0x02	/* W, Rx Cell Counter */
+#define IDT77105_CTRSEL_RHEC	0x01	/* W, Rx HEC Error Counter */
+
+#ifdef __KERNEL__
+int idt77105_init(struct atm_dev *dev) __init;
+int idt77105_stop(struct atm_dev *dev);
+#endif
+
+/*
+ * Tunable parameters
+ */
+ 
+/* Time between samples of the hardware cell counters. Should be <= 1 sec */
+#define IDT77105_STATS_TIMER_PERIOD     (HZ) 
+/* Time between checks to see if the signal has been found again */
+#define IDT77105_RESTART_TIMER_PERIOD   (5 * HZ)
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/iphase.c linux/drivers/atm/iphase.c
--- v2.3.42/linux/drivers/atm/iphase.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/atm/iphase.c	Tue Feb  8 22:27:11 2000
@@ -0,0 +1,3313 @@
+/******************************************************************************
+         iphase.c: Device driver for Interphase ATM PCI adapter cards 
+                    Author: Peter Wang  <pwang@iphase.com>            
+                   Interphase Corporation  <www.iphase.com>           
+                               Version: 1.0                           
+*******************************************************************************
+      
+      This software may be used and distributed according to the terms
+      of the GNU Public License (GPL), incorporated herein by reference.
+      Drivers based on this skeleton fall under the GPL and must retain
+      the authorship (implicit copyright) notice.
+
+      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.
+      
+      Modified from an incomplete driver for Interphase 5575 1KVC 1M card which 
+      was originally written by Monalisa Agrawal at UNH. Now this driver 
+      supports a variety of varients of Interphase ATM PCI (i)Chip adapter 
+      card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM) 
+      in terms of PHY type, the size of control memory and the size of 
+      packet memory. The followings are the change log and history:
+     
+          Bugfix the Mona's UBR driver.
+          Modify the basic memory allocation and dma logic.
+          Port the driver to the latest kernel from 2.0.46.
+          Complete the ABR logic of the driver, and added the ABR work-
+              around for the hardware anormalies.
+          Add the CBR support.
+	  Add the flow control logic to the driver to allow rate-limit VC.
+          Add 4K VC support to the board with 512K control memory.
+          Add the support of all the variants of the Interphase ATM PCI 
+          (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525
+          (25M UTP25) and x531 (DS3 and E3).
+          Add SMP support.
+
+      Support and updates available at: ftp://ftp.iphase.com/pub/atm
+
+*******************************************************************************/
+
+#ifdef IA_MODULE
+#define MODULE
+#endif
+#include <linux/version.h>
+#include <linux/module.h>  
+#include <linux/kernel.h>  
+#include <linux/mm.h>  
+#include <linux/pci.h>  
+#include <linux/errno.h>  
+#include <linux/atm.h>  
+#include <linux/atmdev.h>  
+#include <linux/sonet.h>  
+#include <linux/skbuff.h>  
+#include <linux/time.h>  
+#include <linux/sched.h> /* for xtime */  
+#include <linux/delay.h>  
+#include <linux/uio.h>  
+#include <linux/init.h>  
+#include <asm/system.h>  
+#include <asm/io.h>  
+#include <asm/uaccess.h>  
+#include <asm/string.h>  
+#include <asm/byteorder.h>  
+#include <math.h>  
+#include <linux/vmalloc.h>  
+#include "iphase.h"		  
+#include "suni.h"		  
+#define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))  
+struct suni_priv {
+        struct sonet_stats sonet_stats; /* link diagnostics */
+        unsigned char loop_mode;        /* loopback mode */
+        struct atm_dev *dev;            /* device back-pointer */
+        struct suni_priv *next;         /* next SUNI */
+}; 
+#define PRIV(dev) ((struct suni_priv *) dev->phy_data)
+
+static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr);
+
+static IADEV *ia_dev[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+static struct atm_dev *_ia_dev[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+static int iadev_count = 0;
+static struct timer_list ia_timer;
+struct atm_vcc *vcc_close_que[100];
+static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
+static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;
+static u32 IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER
+            |IF_IADBG_ABR | IF_IADBG_EVENT*/ 0; 
+
+#ifdef MODULE
+MODULE_PARM(IA_TX_BUF, "i");
+MODULE_PARM(IA_TX_BUF_SZ, "i");
+MODULE_PARM(IA_RX_BUF, "i");
+MODULE_PARM(IA_RX_BUF_SZ, "i");
+MODULE_PARM(IADebugFlag, "i");
+#endif
+
+/**************************** IA_LIB **********************************/
+
+static void ia_init_rtn_q (IARTN_Q *que) 
+{ 
+   que->next = NULL; 
+   que->tail = NULL; 
+}
+
+static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data) 
+{
+   data->next = NULL;
+   if (que->next == NULL) 
+      que->next = que->tail = data;
+   else {
+      data->next = que->next;
+      que->next = data;
+   } 
+   return;
+}
+
+static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) {
+   IARTN_Q *entry;
+   entry = (IARTN_Q *)kmalloc(sizeof(IARTN_Q), GFP_KERNEL);
+   if (!entry) return -1;
+   entry->data = data;
+   entry->next = NULL;
+   if (que->next == NULL) 
+      que->next = que->tail = entry;
+   else {
+      que->tail->next = entry;
+      que->tail = que->tail->next;
+   }      
+   return 1;
+}
+
+static IARTN_Q * ia_deque_rtn_q (IARTN_Q *que) {
+   IARTN_Q *tmpdata;
+   if (que->next == NULL)
+      return NULL;
+   tmpdata = que->next;
+   if ( que->next == que->tail)  
+      que->next = que->tail = NULL;
+   else 
+      que->next = que->next->next;
+   return tmpdata;
+}
+
+static void ia_hack_tcq(IADEV *dev) {
+
+  u_short 		desc1;
+  u_short		tcq_wr;
+  struct ia_vcc         *iavcc_r = NULL; 
+  extern void desc_dbg(IADEV *iadev);
+
+  tcq_wr = readl(dev->seg_reg+TCQ_WR_PTR) & 0xffff;
+  while (dev->host_tcq_wr != tcq_wr) {
+     desc1 = *(u_short *)(dev->seg_ram + dev->host_tcq_wr);
+     if (!desc1) ;
+     else if (!dev->desc_tbl[desc1 -1].timestamp) {
+        IF_ABR(printk(" Desc %d is reset at %ld\n", desc1 -1, jiffies);)
+        *(u_short *) (dev->seg_ram + dev->host_tcq_wr) = 0;
+     }                                 
+     else if (dev->desc_tbl[desc1 -1].timestamp) {
+        if (!(iavcc_r = dev->desc_tbl[desc1 -1].iavcc)) { 
+           printk("IA: Fatal err in get_desc\n");
+           continue;
+        }
+        iavcc_r->vc_desc_cnt--;
+        dev->desc_tbl[desc1 -1].timestamp = 0;
+        IF_EVENT(printk("ia_hack: return_q skb = 0x%x desc = %d\n", 
+                                   (u32)dev->desc_tbl[desc1 -1].txskb, desc1);)
+        if (iavcc_r->pcr < dev->rate_limit) {
+           IA_SKB_STATE (dev->desc_tbl[desc1-1].txskb) |= IA_TX_DONE;
+           if (ia_enque_rtn_q(&dev->tx_return_q, dev->desc_tbl[desc1 -1]) < 0)
+              printk("ia_hack_tcq: No memory available\n");
+        } 
+        dev->desc_tbl[desc1 -1].iavcc = NULL;
+        dev->desc_tbl[desc1 -1].txskb = NULL;
+     }
+     dev->host_tcq_wr += 2;
+     if (dev->host_tcq_wr > dev->ffL.tcq_ed) 
+        dev->host_tcq_wr = dev->ffL.tcq_st;
+  }
+} /* ia_hack_tcq */
+
+static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
+  u_short 		desc_num, i;
+  struct sk_buff        *skb;
+  struct ia_vcc         *iavcc_r = NULL; 
+  unsigned long delta;
+  static unsigned long timer = 0;
+  int ltimeout;
+  extern void desc_dbg(IADEV *iadev);
+
+  ia_hack_tcq (dev);
+  if(((jiffies - timer)>50)||((dev->ffL.tcq_rd==dev->host_tcq_wr))){      
+     timer = jiffies; 
+     i=0;
+     while (i < dev->num_tx_desc) {
+        if (!dev->desc_tbl[i].timestamp) {
+           i++;
+           continue;
+        }
+        ltimeout = dev->desc_tbl[i].iavcc->ltimeout; 
+        delta = jiffies - dev->desc_tbl[i].timestamp;
+        if (delta >= ltimeout) {
+           IF_ABR(printk("RECOVER run!! desc_tbl %d = %d  delta = %ld, 
+               time = %ld\n", i,dev->desc_tbl[i].timestamp, delta, jiffies);)
+           if (dev->ffL.tcq_rd == dev->ffL.tcq_st) 
+              dev->ffL.tcq_rd =  dev->ffL.tcq_ed;
+           else 
+              dev->ffL.tcq_rd -= 2;
+           *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd) = i+1;
+           if (!(skb = dev->desc_tbl[i].txskb) || 
+                          !(iavcc_r = dev->desc_tbl[i].iavcc))
+              printk("Fatal err, desc table vcc or skb is NULL\n");
+           else 
+              iavcc_r->vc_desc_cnt--;
+           dev->desc_tbl[i].timestamp = 0;
+           dev->desc_tbl[i].iavcc = NULL;
+           dev->desc_tbl[i].txskb = NULL;
+        }
+        i++;
+     } /* while */
+  }
+  if (dev->ffL.tcq_rd == dev->host_tcq_wr) 
+     return 0xFFFF;
+    
+  /* Get the next available descriptor number from TCQ */
+  desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
+
+  while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) {
+     dev->ffL.tcq_rd += 2;
+     if (dev->ffL.tcq_rd > dev->ffL.tcq_ed) 
+     dev->ffL.tcq_rd = dev->ffL.tcq_st;
+     if (dev->ffL.tcq_rd == dev->host_tcq_wr) 
+        return 0xFFFF; 
+     desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
+  }
+
+  /* get system time */
+  dev->desc_tbl[desc_num -1].timestamp = jiffies;
+  return desc_num;
+}
+
+static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) {
+  u_char          	foundLockUp;
+  vcstatus_t		*vcstatus;
+  u_short               *shd_tbl;
+  u_short               tempCellSlot, tempFract;
+  struct main_vc *abr_vc = (struct main_vc *)dev->MAIN_VC_TABLE_ADDR;
+  struct ext_vc *eabr_vc = (struct ext_vc *)dev->EXT_VC_TABLE_ADDR;
+  u_int  i;
+
+  if (vcc->qos.txtp.traffic_class == ATM_ABR) {
+     vcstatus = (vcstatus_t *) &(dev->testTable[vcc->vci]->vc_status);
+     vcstatus->cnt++;
+     foundLockUp = 0;
+     if( vcstatus->cnt == 0x05 ) {
+        abr_vc += vcc->vci;
+	eabr_vc += vcc->vci;
+	if( eabr_vc->last_desc ) {
+	   if( (abr_vc->status & 0x07) == ABR_STATE /* 0x2 */ ) {
+              /* Wait for 10 Micro sec */
+              udelay(10);
+	      if ((eabr_vc->last_desc)&&((abr_vc->status & 0x07)==ABR_STATE))
+		 foundLockUp = 1;
+           }
+	   else {
+	      tempCellSlot = abr_vc->last_cell_slot;
+              tempFract    = abr_vc->fraction;
+              if((tempCellSlot == dev->testTable[vcc->vci]->lastTime)
+                         && (tempFract == dev->testTable[vcc->vci]->fract))
+	         foundLockUp = 1; 		    
+              dev->testTable[vcc->vci]->lastTime = tempCellSlot;   
+              dev->testTable[vcc->vci]->fract = tempFract; 
+	   } 	    
+        } /* last descriptor */	 	   
+        vcstatus->cnt = 0;     	
+     } /* vcstatus->cnt */
+	
+     if (foundLockUp) {
+        IF_ABR(printk("LOCK UP found\n");) 
+	writew(0xFFFD, dev->seg_reg+MODE_REG_0);
+        /* Wait for 10 Micro sec */
+        udelay(10); 
+        abr_vc->status &= 0xFFF8;
+        abr_vc->status |= 0x0001;  /* state is idle */
+	shd_tbl = (u_short *)dev->ABR_SCHED_TABLE_ADDR;                
+	for( i = 0; ((i < dev->num_vc) && (shd_tbl[i])); i++ );
+	if (i < dev->num_vc)
+           shd_tbl[i] = vcc->vci;
+        else
+           IF_ERR(printk("ABR Seg. may not continue on VC %x\n",vcc->vci);)
+        writew(T_ONLINE, dev->seg_reg+MODE_REG_0);
+        writew(~(TRANSMIT_DONE|TCQ_NOT_EMPTY), dev->seg_reg+SEG_MASK_REG);
+        writew(TRANSMIT_DONE, dev->seg_reg+SEG_INTR_STATUS_REG);       
+	vcstatus->cnt = 0;
+     } /* foundLockUp */
+
+  } /* if an ABR VC */
+
+
+}
+ 
+/*
+** Conversion of 24-bit cellrate (cells/sec) to 16-bit floating point format.
+**
+**  +----+----+------------------+-------------------------------+
+**  |  R | NZ |  5-bit exponent  |        9-bit mantissa         |
+**  +----+----+------------------+-------------------------------+
+** 
+**    R = reserverd (written as 0)
+**    NZ = 0 if 0 cells/sec; 1 otherwise
+**
+**    if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec
+*/
+static u16
+cellrate_to_float(u32 cr)
+{
+
+#define	NZ 		0x4000
+#define	M_BITS		9		/* Number of bits in mantissa */
+#define	E_BITS		5		/* Number of bits in exponent */
+#define	M_MASK		0x1ff		
+#define	E_MASK		0x1f
+  u16   flot;
+  u32	tmp = cr & 0x00ffffff;
+  int 	i   = 0;
+  if (cr == 0)
+     return 0;
+  while (tmp != 1) {
+     tmp >>= 1;
+     i++;
+  }
+  if (i == M_BITS)
+     flot = NZ | (i << M_BITS) | (cr & M_MASK);
+  else if (i < M_BITS)
+     flot = NZ | (i << M_BITS) | ((cr << (M_BITS - i)) & M_MASK);
+  else
+     flot = NZ | (i << M_BITS) | ((cr >> (i - M_BITS)) & M_MASK);
+  return flot;
+}
+
+#if 0
+/*
+** Conversion of 16-bit floating point format to 24-bit cellrate (cells/sec).
+*/
+static u32
+float_to_cellrate(u16 rate)
+{
+  u32   exp, mantissa, cps;
+  if ((rate & NZ) == 0)
+     return 0;
+  exp = (rate >> M_BITS) & E_MASK;
+  mantissa = rate & M_MASK;
+  if (exp == 0)
+     return 1;
+  cps = (1 << M_BITS) | mantissa;
+  if (exp == M_BITS)
+     cps = cps;
+  else if (exp > M_BITS)
+     cps <<= (exp - M_BITS);
+  else
+     cps >>= (M_BITS - exp);
+  return cps;
+}
+#endif 
+
+static void init_abr_vc (IADEV *dev, srv_cls_param_t *srv_p) {
+  srv_p->class_type = ATM_ABR;
+  srv_p->pcr        = dev->LineRate;
+  srv_p->mcr        = 0;
+  srv_p->icr        = 0x055cb7;
+  srv_p->tbe        = 0xffffff;
+  srv_p->frtt       = 0x3a;
+  srv_p->rif        = 0xf;
+  srv_p->rdf        = 0xb;
+  srv_p->nrm        = 0x4;
+  srv_p->trm        = 0x7;
+  srv_p->cdf        = 0x3;
+  srv_p->adtf       = 50;
+}
+
+static int
+ia_open_abr_vc(IADEV *dev, srv_cls_param_t *srv_p, 
+                                                struct atm_vcc *vcc, u8 flag)
+{
+  f_vc_abr_entry  *f_abr_vc;
+  r_vc_abr_entry  *r_abr_vc;
+  u32		icr;
+  u8		trm, nrm, crm;
+  u16		adtf, air, *ptr16;	
+  f_abr_vc =(f_vc_abr_entry *)dev->MAIN_VC_TABLE_ADDR;
+  f_abr_vc += vcc->vci;       
+  switch (flag) {
+     case 1: /* FFRED initialization */
+#if 0  /* sanity check */
+       if (srv_p->pcr == 0)
+          return INVALID_PCR;
+       if (srv_p->pcr > dev->LineRate)
+          srv_p->pcr = dev->LineRate;
+       if ((srv_p->mcr + dev->sum_mcr) > dev->LineRate)
+	  return MCR_UNAVAILABLE;
+       if (srv_p->mcr > srv_p->pcr)
+	  return INVALID_MCR;
+       if (!(srv_p->icr))
+	  srv_p->icr = srv_p->pcr;
+       if ((srv_p->icr < srv_p->mcr) || (srv_p->icr > srv_p->pcr))
+	  return INVALID_ICR;
+       if ((srv_p->tbe < MIN_TBE) || (srv_p->tbe > MAX_TBE))
+	  return INVALID_TBE;
+       if ((srv_p->frtt < MIN_FRTT) || (srv_p->frtt > MAX_FRTT))
+	  return INVALID_FRTT;
+       if (srv_p->nrm > MAX_NRM)
+	  return INVALID_NRM;
+       if (srv_p->trm > MAX_TRM)
+	  return INVALID_TRM;
+       if (srv_p->adtf > MAX_ADTF)
+          return INVALID_ADTF;
+       else if (srv_p->adtf == 0)
+	  srv_p->adtf = 1;
+       if (srv_p->cdf > MAX_CDF)
+	  return INVALID_CDF;
+       if (srv_p->rif > MAX_RIF)
+	  return INVALID_RIF;
+       if (srv_p->rdf > MAX_RDF)
+	  return INVALID_RDF;
+#endif
+       memset ((caddr_t)f_abr_vc, 0, sizeof(f_vc_abr_entry));
+       f_abr_vc->f_vc_type = ABR;
+       nrm = 2 << srv_p->nrm;     /* (2 ** (srv_p->nrm +1)) */
+			          /* i.e 2**n = 2 << (n-1) */
+       f_abr_vc->f_nrm = nrm << 8 | nrm;
+       trm = 100000/(2 << (16 - srv_p->trm));
+       if ( trm == 0) trm = 1;
+       f_abr_vc->f_nrmexp =(((srv_p->nrm +1) & 0x0f) << 12)|(MRM << 8) | trm;
+       crm = srv_p->tbe / nrm;
+       if (crm == 0) crm = 1;
+       f_abr_vc->f_crm = crm & 0xff;
+       f_abr_vc->f_pcr = cellrate_to_float(srv_p->pcr);
+       icr = MIN( srv_p->icr, (srv_p->tbe > srv_p->frtt) ?
+				((srv_p->tbe/srv_p->frtt)*1000000) :
+				(1000000/(srv_p->frtt/srv_p->tbe)));
+       f_abr_vc->f_icr = cellrate_to_float(icr);
+       adtf = (10000 * srv_p->adtf)/8192;
+       if (adtf == 0) adtf = 1; 
+       f_abr_vc->f_cdf = ((7 - srv_p->cdf) << 12 | adtf) & 0xfff;
+       f_abr_vc->f_mcr = cellrate_to_float(srv_p->mcr);
+       f_abr_vc->f_acr = f_abr_vc->f_icr;
+       f_abr_vc->f_status = 0x0042;
+       break;
+    case 0: /* RFRED initialization */	
+       ptr16 = (u_short *)(dev->reass_ram + REASS_TABLE*dev->memSize); 
+       *(ptr16 + vcc->vci) = NO_AAL5_PKT | REASS_ABR;
+       r_abr_vc = (r_vc_abr_entry*)(dev->reass_ram+ABR_VC_TABLE*dev->memSize);
+       r_abr_vc += vcc->vci;
+       r_abr_vc->r_status_rdf = (15 - srv_p->rdf) & 0x000f;
+       air = srv_p->pcr << (15 - srv_p->rif);
+       if (air == 0) air = 1;
+       r_abr_vc->r_air = cellrate_to_float(air);
+       dev->testTable[vcc->vci]->vc_status = VC_ACTIVE | VC_ABR;
+       dev->sum_mcr	   += srv_p->mcr;
+       dev->n_abr++;
+       break;
+    default:
+       break;
+  }
+  return	0;
+}
+static int ia_cbr_setup (IADEV *dev, struct atm_vcc *vcc) {
+   u32 rateLow=0, rateHigh, rate;
+   int entries;
+   struct ia_vcc *ia_vcc;
+
+   int   idealSlot =0, testSlot, toBeAssigned, inc;
+   u32   spacing;
+   u16  *SchedTbl, *TstSchedTbl;
+   u16  cbrVC, vcIndex;
+   u32   fracSlot    = 0;
+   u32   sp_mod      = 0;
+   u32   sp_mod2     = 0;
+
+   /* IpAdjustTrafficParams */
+   if (vcc->qos.txtp.max_pcr <= 0) {
+      IF_ERR(printk("PCR for CBR not defined\n");)
+      return -1;
+   }
+   rate = vcc->qos.txtp.max_pcr;
+   entries = rate / dev->Granularity;
+   IF_CBR(printk("CBR: CBR entries=0x%x for rate=0x%x & Gran=0x%x\n",
+                                entries, rate, dev->Granularity);)
+   if (entries < 1)
+      IF_CBR(printk("CBR: Bandwidth smaller than granularity of CBR table\n");) 
+   rateLow  =  entries * dev->Granularity;
+   rateHigh = (entries + 1) * dev->Granularity;
+   if (3*(rate - rateLow) > (rateHigh - rate))
+      entries++;
+   if (entries > dev->CbrRemEntries) {
+      IF_CBR(printk("CBR: Not enough bandwidth to support this PCR.\n");)
+      IF_CBR(printk("Entries = 0x%x, CbrRemEntries = 0x%x.\n",
+                                       entries, dev->CbrRemEntries);)
+      return -EBUSY;
+   }   
+
+   ia_vcc = INPH_IA_VCC(vcc);
+   ia_vcc->NumCbrEntry = entries; 
+   dev->sum_mcr += entries * dev->Granularity; 
+   /* IaFFrednInsertCbrSched */
+   // Starting at an arbitrary location, place the entries into the table
+   // as smoothly as possible
+   cbrVC   = 0;
+   spacing = dev->CbrTotEntries / entries;
+   sp_mod  = dev->CbrTotEntries % entries; // get modulo
+   toBeAssigned = entries;
+   fracSlot = 0;
+   vcIndex  = vcc->vci;
+   IF_CBR(printk("Vci=0x%x,Spacing=0x%x,Sp_mod=0x%x\n",vcIndex,spacing,sp_mod);)
+   while (toBeAssigned)
+   {
+      // If this is the first time, start the table loading for this connection
+      // as close to entryPoint as possible.
+      if (toBeAssigned == entries)
+      {
+         idealSlot = dev->CbrEntryPt;
+         dev->CbrEntryPt += 2;    // Adding 2 helps to prevent clumping
+         if (dev->CbrEntryPt >= dev->CbrTotEntries) 
+            dev->CbrEntryPt -= dev->CbrTotEntries;// Wrap if necessary
+      } else {
+         idealSlot += (u32)(spacing + fracSlot); // Point to the next location
+         // in the table that would be  smoothest
+         fracSlot = ((sp_mod + sp_mod2) / entries);  // get new integer part
+         sp_mod2  = ((sp_mod + sp_mod2) % entries);  // calc new fractional part
+      }
+      if (idealSlot >= (int)dev->CbrTotEntries) 
+         idealSlot -= dev->CbrTotEntries;  
+      // Continuously check around this ideal value until a null
+      // location is encountered.
+      SchedTbl = (u16*)(dev->seg_ram+CBR_SCHED_TABLE*dev->memSize); 
+      inc = 0;
+      testSlot = idealSlot;
+      TstSchedTbl = (u16*)(SchedTbl+testSlot);  //set index and read in value
+      IF_CBR(printk("CBR Testslot 0x%x AT Location 0x%x, NumToAssign=%d\n",
+                                testSlot, (u32)TstSchedTbl,toBeAssigned);) 
+      memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(u16));
+      while (cbrVC)  // If another VC at this location, we have to keep looking
+      {
+          inc++;
+          testSlot = idealSlot - inc;
+          if (testSlot < 0) { // Wrap if necessary
+             testSlot += dev->CbrTotEntries;
+             IF_CBR(printk("Testslot Wrap. STable Start=0x%x,Testslot=%d\n",
+                                                       (u32)SchedTbl,testSlot);)
+          }
+          TstSchedTbl = (u16 *)(SchedTbl + testSlot);  // set table index
+          memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(u16)); 
+          if (!cbrVC)
+             break;
+          testSlot = idealSlot + inc;
+          if (testSlot >= (int)dev->CbrTotEntries) { // Wrap if necessary
+             testSlot -= dev->CbrTotEntries;
+             IF_CBR(printk("TotCbrEntries=%d",dev->CbrTotEntries);)
+             IF_CBR(printk(" Testslot=0x%x ToBeAssgned=%d\n", 
+                                            testSlot, toBeAssigned);)
+          } 
+          // set table index and read in value
+          TstSchedTbl = (u16*)(SchedTbl + testSlot);
+          IF_CBR(printk("Reading CBR Tbl from 0x%x, CbrVal=0x%x Iteration %d\n",
+                          (u32)TstSchedTbl,cbrVC,inc);) 
+          memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(u16));
+       } /* while */
+       // Move this VCI number into this location of the CBR Sched table.
+       memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex,sizeof(u16));
+       dev->CbrRemEntries--;
+       toBeAssigned--;
+   } /* while */ 
+
+   /* IaFFrednCbrEnable */
+   dev->NumEnabledCBR++;
+   if (dev->NumEnabledCBR == 1) {
+       writew((CBR_EN | UBR_EN | ABR_EN | (0x23 << 2)), dev->seg_reg+STPARMS);
+       IF_CBR(printk("CBR is enabled\n");)
+   }
+   return 0;
+}
+static void ia_cbrVc_close (struct atm_vcc *vcc) {
+   IADEV *iadev;
+   u16 *SchedTbl, NullVci = 0;
+   u32 i, NumFound;
+
+   iadev = INPH_IA_DEV(vcc->dev);
+   iadev->NumEnabledCBR--;
+   SchedTbl = (u16*)(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize);
+   if (iadev->NumEnabledCBR == 0) {
+      writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);
+      IF_CBR (printk("CBR support disabled\n");)
+   }
+   NumFound = 0;
+   for (i=0; i < iadev->CbrTotEntries; i++)
+   {
+      if (*SchedTbl == vcc->vci) {
+         iadev->CbrRemEntries++;
+         *SchedTbl = NullVci;
+         IF_CBR(NumFound++;)
+      }
+      SchedTbl++;   
+   } 
+   IF_CBR(printk("Exit ia_cbrVc_close, NumRemoved=%d\n",NumFound);)
+}
+
+static int ia_avail_descs(IADEV *iadev) {
+   int tmp = 0;
+   ia_hack_tcq(iadev);
+   if (iadev->host_tcq_wr >= iadev->ffL.tcq_rd)
+      tmp = (iadev->host_tcq_wr - iadev->ffL.tcq_rd) / 2;
+   else
+      tmp = (iadev->ffL.tcq_ed - iadev->ffL.tcq_rd + 2 + iadev->host_tcq_wr -
+                   iadev->ffL.tcq_st) / 2;
+   return tmp;
+}    
+
+static int ia_que_tx (IADEV *iadev) { 
+   struct sk_buff *skb;
+   int num_desc;
+   struct atm_vcc *vcc;
+   struct ia_vcc *iavcc;
+   static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb);
+   num_desc = ia_avail_descs(iadev);
+   while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) {
+      if (!(vcc = ATM_SKB(skb)->vcc)) {
+         dev_kfree_skb(skb);
+         printk("ia_que_tx: Null vcc\n");
+         break;
+      }
+      if ((vcc->flags & ATM_VF_READY) == 0 ) {
+         dev_kfree_skb(skb);
+         printk("Free the SKB on closed vci %d \n", vcc->vci);
+         break;
+      }
+      iavcc = INPH_IA_VCC(vcc);
+      if (ia_pkt_tx (vcc, skb)) {
+         skb_queue_head(&iadev->tx_backlog, skb);
+      }
+      num_desc--;
+   }
+   return 0;
+}
+void ia_tx_poll (IADEV *iadev) {
+   struct atm_vcc *vcc = NULL;
+   struct sk_buff *skb = NULL, *skb1 = NULL;
+   struct ia_vcc *iavcc;
+   IARTN_Q *  rtne;
+
+   ia_hack_tcq(iadev);
+   while ( (rtne = ia_deque_rtn_q(&iadev->tx_return_q))) {
+       skb = rtne->data.txskb;
+       if (!skb) {
+           printk("ia_tx_poll: skb is null\n");
+           return;
+       }
+       vcc = ATM_SKB(skb)->vcc;
+       if (!vcc) {
+           printk("ia_tx_poll: vcc is null\n");
+           dev_kfree_skb(skb);
+           return;
+       }
+
+       iavcc = INPH_IA_VCC(vcc);
+       if (!iavcc) {
+           printk("ia_tx_poll: iavcc is null\n");
+           dev_kfree_skb(skb);
+           return;
+       }
+
+       skb1 = skb_dequeue(&iavcc->txing_skb);
+       while (skb1 && (skb1 != skb)) {
+          if (!(IA_SKB_STATE(skb1) & IA_TX_DONE)) {
+             printk("IA_tx_intr: Vci %d lost pkt!!!\n", vcc->vci);
+          }
+          IF_ERR(printk("Release the SKB not match\n");)
+          if (vcc && (vcc->pop) && (skb1->len != 0))
+          {
+             vcc->pop(vcc, skb1);
+             IF_EVENT(printk("Tansmit Done - skb 0x%lx return\n",
+                                                          (long)skb1);)
+          }
+          else 
+             dev_kfree_skb(skb1);
+          skb1 = skb_dequeue(&iavcc->txing_skb);
+       }                                                        
+       if (!skb1) {
+          IF_EVENT(printk("IA: Vci %d - skb not found requed\n",vcc->vci);)
+          ia_enque_head_rtn_q (&iadev->tx_return_q, rtne);
+          break;
+       }
+       if (vcc && (vcc->pop) && (skb->len != 0))
+       {
+          vcc->pop(vcc, skb);
+          IF_EVENT(printk("Tx Done - skb 0x%lx return\n",(long)skb);)
+       }
+       else 
+          dev_kfree_skb(skb);
+       kfree(rtne);
+    }
+    ia_que_tx(iadev);
+    return;
+}
+#if 0
+static void ia_eeprom_put (IADEV *iadev, u32 addr, u_short val)
+{
+        u32	t;
+	int	i;
+	/*
+	 * Issue a command to enable writes to the NOVRAM
+	 */
+	NVRAM_CMD (EXTEND + EWEN);
+	NVRAM_CLR_CE;
+	/*
+	 * issue the write command
+	 */
+	NVRAM_CMD(IAWRITE + addr);
+	/* 
+	 * Send the data, starting with D15, then D14, and so on for 16 bits
+	 */
+	for (i=15; i>=0; i--) {
+		NVRAM_CLKOUT (val & 0x8000);
+		val <<= 1;
+	}
+	NVRAM_CLR_CE;
+	CFG_OR(NVCE);
+	t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); 
+	while (!(t & NVDO))
+		t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); 
+
+	NVRAM_CLR_CE;
+	/*
+	 * disable writes again
+	 */
+	NVRAM_CMD(EXTEND + EWDS)
+	NVRAM_CLR_CE;
+	CFG_AND(~NVDI);
+}
+#endif
+
+static u16 ia_eeprom_get (IADEV *iadev, u32 addr)
+{
+	u_short	val;
+        u32	t;
+	int	i;
+	/*
+	 * Read the first bit that was clocked with the falling edge of the
+	 * the last command data clock
+	 */
+	NVRAM_CMD(IAREAD + addr);
+	/*
+	 * Now read the rest of the bits, the next bit read is D14, then D13,
+	 * and so on.
+	 */
+	val = 0;
+	for (i=15; i>=0; i--) {
+		NVRAM_CLKIN(t);
+		val |= (t << i);
+	}
+	NVRAM_CLR_CE;
+	CFG_AND(~NVDI);
+	return val;
+}
+
+static void ia_hw_type(IADEV *iadev) {
+   u_short memType = ia_eeprom_get(iadev, 25);   
+   iadev->memType = memType;
+   if ((memType & MEM_SIZE_MASK) == MEM_SIZE_1M) {
+      iadev->num_tx_desc = IA_TX_BUF;
+      iadev->tx_buf_sz = IA_TX_BUF_SZ;
+      iadev->num_rx_desc = IA_RX_BUF;
+      iadev->rx_buf_sz = IA_RX_BUF_SZ; 
+   } else if ((memType & MEM_SIZE_MASK) == MEM_SIZE_512K) {
+      if (IA_TX_BUF == DFL_TX_BUFFERS)
+        iadev->num_tx_desc = IA_TX_BUF / 2;
+      else 
+        iadev->num_tx_desc = IA_TX_BUF;
+      iadev->tx_buf_sz = IA_TX_BUF_SZ;
+      if (IA_RX_BUF == DFL_RX_BUFFERS)
+        iadev->num_rx_desc = IA_RX_BUF / 2;
+      else
+        iadev->num_rx_desc = IA_RX_BUF;
+      iadev->rx_buf_sz = IA_RX_BUF_SZ;
+   }
+   else {
+      if (IA_TX_BUF == DFL_TX_BUFFERS) 
+        iadev->num_tx_desc = IA_TX_BUF / 8;
+      else
+        iadev->num_tx_desc = IA_TX_BUF;
+      iadev->tx_buf_sz = IA_TX_BUF_SZ;
+      if (IA_RX_BUF == DFL_RX_BUFFERS)
+        iadev->num_rx_desc = IA_RX_BUF / 8;
+      else
+        iadev->num_rx_desc = IA_RX_BUF;
+      iadev->rx_buf_sz = IA_RX_BUF_SZ; 
+   } 
+   iadev->rx_pkt_ram = TX_PACKET_RAM + (iadev->num_tx_desc * iadev->tx_buf_sz); 
+   IF_INIT(printk("BUF: tx=%d,sz=%d rx=%d sz= %d rx_pkt_ram=%d\n",
+         iadev->num_tx_desc, iadev->tx_buf_sz, iadev->num_rx_desc,
+         iadev->rx_buf_sz, iadev->rx_pkt_ram);)
+
+#if 0
+   if ((memType & FE_MASK) == FE_SINGLE_MODE) {
+      iadev->phy_type = PHY_OC3C_S;
+   else if ((memType & FE_MASK) == FE_UTP_OPTION)
+      iadev->phy_type = PHY_UTP155;
+   else
+     iadev->phy_type = PHY_OC3C_M;
+#endif
+   
+   iadev->phy_type = memType & FE_MASK;
+   IF_INIT(printk("memType = 0x%x iadev->phy_type = 0x%x\n", 
+                                         memType,iadev->phy_type);)
+   if (iadev->phy_type == FE_25MBIT_PHY) 
+      iadev->LineRate = (u32)(((25600000/8)*26)/(27*53));
+   else if (iadev->phy_type == FE_DS3_PHY)
+      iadev->LineRate = (u32)(((44736000/8)*26)/(27*53));
+   else if (iadev->phy_type == FE_E3_PHY) 
+      iadev->LineRate = (u32)(((34368000/8)*26)/(27*53));
+   else
+       iadev->LineRate = (u32)(ATM_OC3_PCR);
+   IF_INIT(printk("iadev->LineRate = %d \n", iadev->LineRate);)
+
+}
+
+static void IaFrontEndIntr(IADEV *iadev) {
+  volatile IA_SUNI *suni;
+  volatile ia_mb25_t *mb25;
+  volatile suni_pm7345_t *suni_pm7345;
+  u32 intr_status;
+  u_int frmr_intr;
+
+  if(iadev->phy_type & FE_25MBIT_PHY) {
+     mb25 = (ia_mb25_t*)iadev->phy;
+     iadev->carrier_detect =  Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
+  } else if (iadev->phy_type & FE_DS3_PHY) {
+     suni_pm7345 = (suni_pm7345_t *)iadev->phy;
+     /* clear FRMR interrupts */
+     frmr_intr   = suni_pm7345->suni_ds3_frm_intr_stat; 
+     iadev->carrier_detect =  
+           Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV));
+  } else if (iadev->phy_type & FE_E3_PHY ) {
+     suni_pm7345 = (suni_pm7345_t *)iadev->phy;
+     frmr_intr   = suni_pm7345->suni_e3_frm_maint_intr_ind;
+     iadev->carrier_detect =
+           Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS));
+  }
+  else { 
+     suni = (IA_SUNI *)iadev->phy;
+     intr_status = suni->suni_rsop_status & 0xff;
+     iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV));
+  }
+  if (iadev->carrier_detect)
+    printk("IA: SUNI carrier detected\n");
+  else
+    printk("IA: SUNI carrier lost signal\n"); 
+  return;
+}
+
+void ia_mb25_init (IADEV *iadev)
+{
+   volatile ia_mb25_t  *mb25 = (ia_mb25_t*)iadev->phy;
+#if 0
+   mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED;
+#endif
+   mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC;
+   mb25->mb25_diag_control = 0;
+   /*
+    * Initialize carrier detect state
+    */
+   iadev->carrier_detect =  Boolean(mb25->mb25_intr_status & MB25_IS_GSB);
+   return;
+}                   
+
+void ia_suni_pm7345_init (IADEV *iadev)
+{
+   volatile suni_pm7345_t *suni_pm7345 = (suni_pm7345_t *)iadev->phy;
+   if (iadev->phy_type & FE_DS3_PHY)
+   {
+      iadev->carrier_detect = 
+          Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV)); 
+      suni_pm7345->suni_ds3_frm_intr_enbl = 0x17;
+      suni_pm7345->suni_ds3_frm_cfg = 1;
+      suni_pm7345->suni_ds3_tran_cfg = 1;
+      suni_pm7345->suni_config = 0;
+      suni_pm7345->suni_splr_cfg = 0;
+      suni_pm7345->suni_splt_cfg = 0;
+   }
+   else 
+   {
+      iadev->carrier_detect = 
+          Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat & SUNI_E3_LOS));
+      suni_pm7345->suni_e3_frm_fram_options = 0x4;
+      suni_pm7345->suni_e3_frm_maint_options = 0x20;
+      suni_pm7345->suni_e3_frm_fram_intr_enbl = 0x1d;
+      suni_pm7345->suni_e3_frm_maint_intr_enbl = 0x30;
+      suni_pm7345->suni_e3_tran_stat_diag_options = 0x0;
+      suni_pm7345->suni_e3_tran_fram_options = 0x1;
+      suni_pm7345->suni_config = SUNI_PM7345_E3ENBL;
+      suni_pm7345->suni_splr_cfg = 0x41;
+      suni_pm7345->suni_splt_cfg = 0x41;
+   } 
+   /*
+    * Enable RSOP loss of signal interrupt.
+    */
+   suni_pm7345->suni_intr_enbl = 0x28;
+ 
+   /*
+    * Clear error counters
+    */
+   suni_pm7345->suni_id_reset = 0;
+
+   /*
+    * Clear "PMCTST" in master test register.
+    */
+   suni_pm7345->suni_master_test = 0;
+
+   suni_pm7345->suni_rxcp_ctrl = 0x2c;
+   suni_pm7345->suni_rxcp_fctrl = 0x81;
+ 
+   suni_pm7345->suni_rxcp_idle_pat_h1 = 0;
+   suni_pm7345->suni_rxcp_idle_pat_h2 = 0;
+   suni_pm7345->suni_rxcp_idle_pat_h3 = 0;
+   suni_pm7345->suni_rxcp_idle_pat_h4 = 1;
+ 
+   suni_pm7345->suni_rxcp_idle_mask_h1 = 0xff;
+   suni_pm7345->suni_rxcp_idle_mask_h2 = 0xff;
+   suni_pm7345->suni_rxcp_idle_mask_h3 = 0xff;
+   suni_pm7345->suni_rxcp_idle_mask_h4 = 0xfe;
+ 
+   suni_pm7345->suni_rxcp_cell_pat_h1 = 0;
+   suni_pm7345->suni_rxcp_cell_pat_h2 = 0;
+   suni_pm7345->suni_rxcp_cell_pat_h3 = 0;
+   suni_pm7345->suni_rxcp_cell_pat_h4 = 1;
+ 
+   suni_pm7345->suni_rxcp_cell_mask_h1 = 0xff;
+   suni_pm7345->suni_rxcp_cell_mask_h2 = 0xff;
+   suni_pm7345->suni_rxcp_cell_mask_h3 = 0xff;
+   suni_pm7345->suni_rxcp_cell_mask_h4 = 0xff;
+ 
+   suni_pm7345->suni_txcp_ctrl = 0xa4;
+   suni_pm7345->suni_txcp_intr_en_sts = 0x10;
+   suni_pm7345->suni_txcp_idle_pat_h5 = 0x55;
+ 
+   suni_pm7345->suni_config &= ~(SUNI_PM7345_LLB |
+                                 SUNI_PM7345_CLB |
+                                 SUNI_PM7345_DLB |
+                                  SUNI_PM7345_PLB);
+#ifdef __SNMP__
+   suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE;
+#endif __SNMP__
+   return;
+}
+
+
+/***************************** IA_LIB END *****************************/
+    
+/* pwang_test debug utility */
+int tcnter = 0, rcnter = 0;
+void xdump( u_char*  cp, int  length, char*  prefix )
+{
+    int col, count;
+    u_char prntBuf[120];
+    u_char*  pBuf = prntBuf;
+    count = 0;
+    while(count < length){
+        pBuf += sprintf( pBuf, "%s", prefix );
+        for(col = 0;count + col < length && col < 16; col++){
+            if (col != 0 && (col % 4) == 0)
+                pBuf += sprintf( pBuf, " " );
+            pBuf += sprintf( pBuf, "%02X ", cp[count + col] );
+        }
+        while(col++ < 16){      /* pad end of buffer with blanks */
+            if ((col % 4) == 0)
+                sprintf( pBuf, " " );
+            pBuf += sprintf( pBuf, "   " );
+        }
+        pBuf += sprintf( pBuf, "  " );
+        for(col = 0;count + col < length && col < 16; col++){
+            if (isprint((int)cp[count + col]))
+                pBuf += sprintf( pBuf, "%c", cp[count + col] );
+            else
+                pBuf += sprintf( pBuf, "." );
+                }
+        sprintf( pBuf, "\n" );
+        // SPrint(prntBuf);
+        printk(prntBuf);
+        count += col;
+        pBuf = prntBuf;
+    }
+
+}  /* close xdump(... */
+
+  
+static struct atm_dev *ia_boards = NULL;  
+  
+#define ACTUAL_RAM_BASE \
+	RAM_BASE*((iadev->mem)/(128 * 1024))  
+#define ACTUAL_SEG_RAM_BASE \
+	IPHASE5575_FRAG_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024))  
+#define ACTUAL_REASS_RAM_BASE \
+	IPHASE5575_REASS_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024))  
+  
+  
+/*-- some utilities and memory allocation stuff will come here -------------*/  
+  
+void desc_dbg(IADEV *iadev) {
+
+  u_short tcq_wr_ptr, tcq_st_ptr, tcq_ed_ptr;
+  u32 tmp, i;
+  // regval = readl((u32)ia_cmds->maddr);
+  tcq_wr_ptr =  readw(iadev->seg_reg+TCQ_WR_PTR);
+  printk("B_tcq_wr = 0x%x desc = %d last desc = %d\n",
+                     tcq_wr_ptr, readw(iadev->seg_ram+tcq_wr_ptr),
+                     readw(iadev->seg_ram+tcq_wr_ptr-2));
+  printk(" host_tcq_wr = 0x%x  host_tcq_rd = 0x%x \n",  iadev->host_tcq_wr, 
+                   iadev->ffL.tcq_rd);
+  tcq_st_ptr =  readw(iadev->seg_reg+TCQ_ST_ADR);
+  tcq_ed_ptr =  readw(iadev->seg_reg+TCQ_ED_ADR);
+  printk("tcq_st_ptr = 0x%x    tcq_ed_ptr = 0x%x \n", tcq_st_ptr, tcq_ed_ptr);
+  i = 0;
+  while (tcq_st_ptr != tcq_ed_ptr) {
+      tmp = iadev->seg_ram+tcq_st_ptr;
+      printk("TCQ slot %d desc = %d  Addr = 0x%x\n", i++, readw(tmp), tmp);
+      tcq_st_ptr += 2;
+  }
+  for(i=0; i <iadev->num_tx_desc; i++)
+      printk("Desc_tbl[%d] = %d \n", i, iadev->desc_tbl[i].timestamp);
+} 
+  
+  
+/*----------------------------- Recieving side stuff --------------------------*/  
+ 
+static void rx_excp_rcvd(struct atm_dev *dev)  
+{  
+#if 0 /* closing the receiving size will cause too many excp int */  
+  IADEV *iadev;  
+  u_short state;  
+  u_short excpq_rd_ptr;  
+  //u_short *ptr;  
+  int vci, error = 1;  
+  iadev = INPH_IA_DEV(dev);  
+  state = readl(iadev->reass_reg + STATE_REG) & 0xffff;  
+  while((state & EXCPQ_EMPTY) != EXCPQ_EMPTY)  
+  { printk("state = %x \n", state); 
+        excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_RD_PTR) & 0xffff;  
+ printk("state = %x excpq_rd_ptr = %x \n", state, excpq_rd_ptr); 
+        if (excpq_rd_ptr == *(u16*)(iadev->reass_reg + EXCP_Q_WR_PTR))
+            IF_ERR(printk("excpq_rd_ptr is wrong!!!\n");)
+        // TODO: update exception stat
+	vci = readw(iadev->reass_ram+excpq_rd_ptr);  
+	error = readw(iadev->reass_ram+excpq_rd_ptr+2) & 0x0007;  
+        // pwang_test
+	excpq_rd_ptr += 4;  
+	if (excpq_rd_ptr > (readw(iadev->reass_reg + EXCP_Q_ED_ADR)& 0xffff))  
+ 	    excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_ST_ADR)& 0xffff;
+	writew( excpq_rd_ptr, iadev->reass_reg + EXCP_Q_RD_PTR);  
+        state = readl(iadev->reass_reg + STATE_REG) & 0xffff;  
+  }  
+#endif
+}  
+  
+static void free_desc(struct atm_dev *dev, int desc)  
+{  
+	IADEV *iadev;  
+	iadev = INPH_IA_DEV(dev);  
+        writew(desc, iadev->reass_ram+iadev->rfL.fdq_wr); 
+	iadev->rfL.fdq_wr +=2;
+	if (iadev->rfL.fdq_wr > iadev->rfL.fdq_ed)
+		iadev->rfL.fdq_wr =  iadev->rfL.fdq_st;  
+	writew(iadev->rfL.fdq_wr, iadev->reass_reg+FREEQ_WR_PTR);  
+}  
+  
+  
+static int rx_pkt(struct atm_dev *dev)  
+{  
+	IADEV *iadev;  
+	struct atm_vcc *vcc;  
+	unsigned short status;  
+	struct rx_buf_desc *buf_desc_ptr;  
+	int desc;   
+	struct dle* wr_ptr;  
+	int len;  
+	struct sk_buff *skb;  
+	u_int buf_addr, dma_addr;  
+	iadev = INPH_IA_DEV(dev);  
+	if (iadev->rfL.pcq_rd == (readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff)) 
+	{  
+   	    printk(KERN_ERR DEV_LABEL "(itf %d) Receive queue empty\n", dev->number);  
+	    return -EINVAL;  
+	}  
+	/* mask 1st 3 bits to get the actual descno. */  
+	desc = readw(iadev->reass_ram+iadev->rfL.pcq_rd) & 0x1fff;  
+        IF_RX(printk("reass_ram = 0x%x iadev->rfL.pcq_rd = 0x%x desc = %d\n", 
+                                    iadev->reass_ram, iadev->rfL.pcq_rd, desc);
+              printk(" pcq_wr_ptr = 0x%x\n",
+                               readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff);)
+	/* update the read pointer  - maybe we shud do this in the end*/  
+	if ( iadev->rfL.pcq_rd== iadev->rfL.pcq_ed) 
+		iadev->rfL.pcq_rd = iadev->rfL.pcq_st;  
+	else  
+		iadev->rfL.pcq_rd += 2;
+	writew(iadev->rfL.pcq_rd, iadev->reass_reg+PCQ_RD_PTR);  
+  
+	/* get the buffer desc entry.  
+		update stuff. - doesn't seem to be any update necessary  
+	*/  
+	buf_desc_ptr = (struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR;
+	/* make the ptr point to the corresponding buffer desc entry */  
+	buf_desc_ptr += desc;	  
+        if (!desc || (desc > iadev->num_rx_desc) || 
+                      ((buf_desc_ptr->vc_index & 0xffff) > iadev->num_vc)) { 
+            free_desc(dev, desc);
+            IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
+            return -1;
+        }
+	vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];  
+	if (!vcc)  
+	{      
+                free_desc(dev, desc); 
+		printk("IA: null vcc, drop PDU\n");  
+		return -1;  
+	}  
+	  
+  
+	/* might want to check the status bits for errors */  
+	status = (u_short) (buf_desc_ptr->desc_mode);  
+	if (status & (RX_CER | RX_PTE | RX_OFL))  
+	{  
+                vcc->stats->rx_err++;
+		IF_ERR(printk("IA: bad packet, dropping it");)  
+                if (status & RX_CER) { 
+                    IF_ERR(printk(" cause: packet CRC error\n");)
+                }
+                else if (status & RX_PTE) {
+                    IF_ERR(printk(" cause: packet time out\n");)
+                }
+                else {
+                    IF_ERR(printk(" cause: buffer over flow\n");)
+                }
+		free_desc(dev, desc);  
+		return 0;  
+	}  
+  
+	/*  
+		build DLE.	  
+	*/  
+  
+	buf_addr = (buf_desc_ptr->buf_start_hi << 16) | buf_desc_ptr->buf_start_lo;  
+	dma_addr = (buf_desc_ptr->dma_start_hi << 16) | buf_desc_ptr->dma_start_lo;  
+	len = dma_addr - buf_addr;  
+        if (len > iadev->rx_buf_sz) {
+           printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz);
+           vcc->stats->rx_err++;
+           free_desc(dev, desc); 
+           return 0;
+        }
+		  
+#if LINUX_VERSION_CODE >= 0x20312
+        if (!(skb = atm_alloc_charge(vcc, len, GFP_ATOMIC))) {
+#else
+        if (atm_charge(vcc, atm_pdu2truesize(len))) {
+	   /* lets allocate an skb for now */  
+	   skb = alloc_skb(len, GFP_ATOMIC);  
+	   if (!skb)  
+	   {  
+              IF_ERR(printk("can't allocate memory for recv, drop pkt!\n");)  
+              vcc->stats->rx_drop++;
+              atm_return(vcc, atm_pdu2truesize(len));
+              free_desc(dev, desc); 
+	      return 0;  
+	   }  
+        }
+        else {
+           IF_EVENT(printk("IA: Rx over the rx_quota %ld\n", vcc->rx_quota);)
+#endif
+           if (vcc->vci < 32)
+              printk("Drop control packets\n");
+           free_desc(dev, desc);
+           return 0;
+        }
+	skb_put(skb,len);  
+        // pwang_test
+        ATM_SKB(skb)->vcc = vcc;
+        ATM_SKB(skb)->iovcnt = 0;
+        ATM_DESC(skb) = desc;        
+	skb_queue_tail(&iadev->rx_dma_q, skb);  
+
+	/* Build the DLE structure */  
+	wr_ptr = iadev->rx_dle_q.write;  
+	wr_ptr->sys_pkt_addr = virt_to_bus(skb->data);	  
+	wr_ptr->local_pkt_addr = buf_addr;  
+	wr_ptr->bytes = len;	/* We don't know this do we ?? */  
+	wr_ptr->mode = DMA_INT_ENABLE;  
+  
+	/* shud take care of wrap around here too. */  
+        if(++wr_ptr == iadev->rx_dle_q.end)
+             wr_ptr = iadev->rx_dle_q.start;
+	iadev->rx_dle_q.write = wr_ptr;  
+	udelay(1);  
+	/* Increment transaction counter */  
+	writel(1, iadev->dma+IPHASE5575_RX_COUNTER);   
+	return 0;  
+}  
+  
+static void rx_intr(struct atm_dev *dev)  
+{  
+  IADEV *iadev;  
+  u_short status;  
+  u_short state, i;  
+  
+  iadev = INPH_IA_DEV(dev);  
+  status = readl(iadev->reass_reg+REASS_INTR_STATUS_REG) & 0xffff;  
+  IF_EVENT(printk("rx_intr: status = 0x%x\n", status);)
+  if (status & RX_PKT_RCVD)  
+  {  
+	/* do something */  
+	/* Basically recvd an interrupt for receving a packet.  
+	A descriptor would have been written to the packet complete   
+	queue. Get all the descriptors and set up dma to move the   
+	packets till the packet complete queue is empty..  
+	*/  
+	state = readl(iadev->reass_reg + STATE_REG) & 0xffff;  
+        IF_EVENT(printk("Rx intr status: RX_PKT_RCVD %08x\n", status);) 
+	while(!(state & PCQ_EMPTY))  
+	{  
+             rx_pkt(dev);  
+	     state = readl(iadev->reass_reg + STATE_REG) & 0xffff;  
+	}  
+        iadev->rxing = 1;
+  }  
+  if (status & RX_FREEQ_EMPT)  
+  {   
+     if (iadev->rxing) {
+        iadev->rx_tmp_cnt = iadev->rx_pkt_cnt;
+        iadev->rx_tmp_jif = jiffies; 
+        iadev->rxing = 0;
+     } 
+     else if (((jiffies - iadev->rx_tmp_jif) > 50) && 
+               ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) {
+        for (i = 1; i <= iadev->num_rx_desc; i++)
+               free_desc(dev, i);
+printk("Test logic RUN!!!!\n");
+        writew( ~(RX_FREEQ_EMPT|RX_EXCP_RCVD),iadev->reass_reg+REASS_MASK_REG);
+        iadev->rxing = 1;
+     }
+     IF_EVENT(printk("Rx intr status: RX_FREEQ_EMPT %08x\n", status);)  
+  }  
+
+  if (status & RX_EXCP_RCVD)  
+  {  
+	/* probably need to handle the exception queue also. */  
+	IF_EVENT(printk("Rx intr status: RX_EXCP_RCVD %08x\n", status);)  
+	rx_excp_rcvd(dev);  
+  }  
+
+
+  if (status & RX_RAW_RCVD)  
+  {  
+	/* need to handle the raw incoming cells. This deepnds on   
+	whether we have programmed to receive the raw cells or not.  
+	Else ignore. */  
+	IF_EVENT(printk("Rx intr status:  RX_RAW_RCVD %08x\n", status);)  
+  }  
+}  
+  
+  
+static void rx_dle_intr(struct atm_dev *dev)  
+{  
+  IADEV *iadev;  
+  struct atm_vcc *vcc;   
+  struct sk_buff *skb;  
+  int desc;  
+  u_short state;   
+  struct dle *dle, *cur_dle;  
+  u_int dle_lp;  
+  iadev = INPH_IA_DEV(dev);  
+ 
+  /* free all the dles done, that is just update our own dle read pointer   
+	- do we really need to do this. Think not. */  
+  /* DMA is done, just get all the recevie buffers from the rx dma queue  
+	and push them up to the higher layer protocol. Also free the desc  
+	associated with the buffer. */  
+  dle = iadev->rx_dle_q.read;  
+  dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1);  
+  cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4));  
+  while(dle != cur_dle)  
+  {  
+      /* free the DMAed skb */  
+      skb = skb_dequeue(&iadev->rx_dma_q);  
+      if (!skb)  
+         goto INCR_DLE;
+      desc = ATM_DESC(skb);
+      free_desc(dev, desc);  
+               
+      if (!skb->len)  
+      {  
+          printk("rx_dle_intr: skb len 0\n");  
+	  dev_kfree_skb(skb);  
+      }  
+      else  
+      {  
+          struct cpcs_trailer *trailer;
+          u_short length;
+          struct ia_vcc *ia_vcc;
+          /* no VCC related housekeeping done as yet. lets see */  
+          vcc = ATM_SKB(skb)->vcc;
+	  if (!vcc) {
+	      printk("IA: null vcc\n");  
+              vcc->stats->rx_err++;
+              dev_kfree_skb(skb);
+              goto INCR_DLE;
+          }
+          ia_vcc = INPH_IA_VCC(vcc);
+          if (ia_vcc == NULL)
+          {
+             vcc->stats->rx_err++;
+             dev_kfree_skb(skb);
+#if LINUX_VERSION_CODE >= 0x20312
+             atm_return(vcc, atm_guess_pdu2truesize(skb->len));
+#else
+             atm_return(vcc, atm_pdu2truesize(skb->len));
+#endif
+             goto INCR_DLE;
+           }
+          // get real pkt length  pwang_test
+          trailer = (struct cpcs_trailer*)((u_char *)skb->data +
+                                 skb->len - sizeof(struct cpcs_trailer));
+          length =  swap(trailer->length);
+          if ((length > iadev->rx_buf_sz) || (length > 
+                              (skb->len - sizeof(struct cpcs_trailer))))
+          {
+             vcc->stats->rx_err++;
+             dev_kfree_skb(skb);
+             IF_ERR(printk("rx_dle_intr: Bad  AAL5 trailer %d (skb len %d)", 
+                                                            length, skb->len);)
+#if LINUX_VERSION_CODE >= 0x20312
+             atm_return(vcc, atm_guess_pdu2truesize(skb->len));
+#else
+             atm_return(vcc, atm_pdu2truesize(skb->len));
+#endif 
+             goto INCR_DLE;
+          }
+          skb_trim(skb, length);
+          
+	  /* Display the packet */  
+	  IF_RXPKT(printk("\nDmad Recvd data: len = %d \n", skb->len);  
+          xdump(skb->data, skb->len, "RX: ");
+          printk("\n");)
+
+	  IF_RX(printk("rx_dle_intr: skb push");)  
+	  vcc->push(vcc,skb);  
+	  vcc->stats->rx++;   
+          iadev->rx_pkt_cnt++;
+      }  
+INCR_DLE:
+      if (++dle == iadev->rx_dle_q.end)  
+    	  dle = iadev->rx_dle_q.start;  
+  }  
+  iadev->rx_dle_q.read = dle;  
+  
+  /* if the interrupts are masked because there were no free desc available,  
+		unmask them now. */ 
+  if (!iadev->rxing) {
+     state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
+     if (!(state & FREEQ_EMPTY)) {
+        state = readl(iadev->reass_reg + REASS_MASK_REG) & 0xffff;
+        writel(state & ~(RX_FREEQ_EMPT |/* RX_EXCP_RCVD |*/ RX_PKT_RCVD),
+                                      iadev->reass_reg+REASS_MASK_REG);
+        iadev->rxing++; 
+     }
+  }
+}  
+  
+  
+static int open_rx(struct atm_vcc *vcc)  
+{  
+	IADEV *iadev;  
+	u_short *vc_table;  
+	u_short *reass_ptr;  
+	IF_EVENT(printk("iadev: open_rx %d.%d\n", vcc->vpi, vcc->vci);)
+
+	if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0;    
+	iadev = INPH_IA_DEV(vcc->dev);  
+        if (vcc->qos.rxtp.traffic_class == ATM_ABR) {  
+           if (iadev->phy_type & FE_25MBIT_PHY) {
+               printk("IA:  ABR not support\n");
+               return -EINVAL; 
+           }
+        }
+	/* Make only this VCI in the vc table valid and let all   
+		others be invalid entries */  
+	vc_table = (u_short *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);  
+	vc_table += vcc->vci;  
+	/* mask the last 6 bits and OR it with 3 for 1K VCs */  
+
+        *vc_table = vcc->vci << 6;
+	/* Also keep a list of open rx vcs so that we can attach them with  
+		incoming PDUs later. */  
+	if ((vcc->qos.rxtp.traffic_class == ATM_ABR) || 
+                                (vcc->qos.txtp.traffic_class == ATM_ABR))  
+	{  
+                srv_cls_param_t srv_p;
+                init_abr_vc(iadev, &srv_p);
+                ia_open_abr_vc(iadev, &srv_p, vcc, 0);
+	} 
+       	else {  /* for UBR  later may need to add CBR logic */
+        	reass_ptr = (u_short *)
+                           (iadev->reass_ram+REASS_TABLE*iadev->memSize);
+           	reass_ptr += vcc->vci;  
+           	*reass_ptr = NO_AAL5_PKT;
+       	}
+	
+	if (iadev->rx_open[vcc->vci])  
+		printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d already open\n",  
+			vcc->dev->number, vcc->vci);  
+	iadev->rx_open[vcc->vci] = vcc;  
+	return 0;  
+}  
+  
+static int rx_init(struct atm_dev *dev)  
+{  
+	IADEV *iadev;  
+	struct rx_buf_desc *buf_desc_ptr;  
+	unsigned long rx_pkt_start = 0;  
+	u32 *dle_addr;  
+	struct abr_vc_table  *abr_vc_table; 
+	u16 *vc_table;  
+	u16 *reass_table;  
+        u16 *ptr16;
+	int i,j, vcsize_sel;  
+	u_short freeq_st_adr;  
+	u_short *freeq_start;  
+  
+	iadev = INPH_IA_DEV(dev);  
+  //    spin_lock_init(&iadev->rx_lock); 
+	/* I need to initialize the DLEs somewhere. Lets see what I   
+		need to do for this, hmmm...  
+		- allocate memory for 256 DLEs. make sure that it starts  
+		on a 4k byte address boundary. Program the start address   
+		in Receive List address register.  ..... to do for TX also  
+	   To make sure that it is a 4k byte boundary - allocate 8k and find   
+		4k byte boundary within.  
+		( (addr + (4k-1)) & ~(4k-1) )  
+	*/   
+  
+	/* allocate 8k bytes */  
+	dle_addr = (u32*)kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL);  
+	if (!dle_addr)  
+	{  
+		printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");  
+	}  
+	/* find 4k byte boundary within the 8k allocated */  
+	dle_addr = (u32*)( ((u32)dle_addr+(4096-1)) & ~(4096-1) );  
+	iadev->rx_dle_q.start = (struct dle*)dle_addr;  
+	iadev->rx_dle_q.read = iadev->rx_dle_q.start;  
+	iadev->rx_dle_q.write = iadev->rx_dle_q.start;  
+	iadev->rx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES);  
+	/* the end of the dle q points to the entry after the last  
+	DLE that can be used. */  
+  
+	/* write the upper 20 bits of the start address to rx list address register */  
+	writel(virt_to_bus(dle_addr) & 0xfffff000, iadev->dma+IPHASE5575_RX_LIST_ADDR);  
+	IF_INIT(printk("Tx Dle list addr: 0x%08x value: 0x%0x\n", 
+                      (u32)(iadev->dma+IPHASE5575_TX_LIST_ADDR), 
+                      *(u32*)(iadev->dma+IPHASE5575_TX_LIST_ADDR));  
+	printk("Rx Dle list addr: 0x%08x value: 0x%0x\n", 
+                      (u32)(iadev->dma+IPHASE5575_RX_LIST_ADDR), 
+                      *(u32*)(iadev->dma+IPHASE5575_RX_LIST_ADDR));)  
+  
+	writew(0xffff, iadev->reass_reg+REASS_MASK_REG);  
+	writew(0, iadev->reass_reg+MODE_REG);  
+	writew(RESET_REASS, iadev->reass_reg+REASS_COMMAND_REG);  
+  
+	/* Receive side control memory map  
+	   -------------------------------  
+  
+		Buffer descr	0x0000 (736 - 23K)  
+		VP Table	0x5c00 (256 - 512)  
+		Except q	0x5e00 (128 - 512)  
+		Free buffer q	0x6000 (1K - 2K)  
+		Packet comp q	0x6800 (1K - 2K)  
+		Reass Table	0x7000 (1K - 2K)  
+		VC Table	0x7800 (1K - 2K)  
+		ABR VC Table	0x8000 (1K - 32K)  
+	*/  
+	  
+	/* Base address for Buffer Descriptor Table */  
+	writew(RX_DESC_BASE >> 16, iadev->reass_reg+REASS_DESC_BASE);  
+	/* Set the buffer size register */  
+	writew(iadev->rx_buf_sz, iadev->reass_reg+BUF_SIZE);  
+  
+	/* Initialize each entry in the Buffer Descriptor Table */  
+        iadev->RX_DESC_BASE_ADDR = iadev->reass_ram+RX_DESC_BASE*iadev->memSize;
+	buf_desc_ptr =(struct rx_buf_desc *)iadev->RX_DESC_BASE_ADDR;
+	memset((caddr_t)buf_desc_ptr, 0, sizeof(struct rx_buf_desc));  
+	buf_desc_ptr++;  
+	rx_pkt_start = iadev->rx_pkt_ram;  
+	for(i=1; i<=iadev->num_rx_desc; i++)  
+	{  
+		memset((caddr_t)buf_desc_ptr, 0, sizeof(struct rx_buf_desc));  
+		buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16;  
+		buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff;  
+		buf_desc_ptr++;		  
+		rx_pkt_start += iadev->rx_buf_sz;  
+	}  
+	IF_INIT(printk("Rx Buffer desc ptr: 0x%0x\n", (u32)(buf_desc_ptr));)  
+        i = FREE_BUF_DESC_Q*iadev->memSize; 
+	writew(i >> 16,  iadev->reass_reg+REASS_QUEUE_BASE); 
+        writew(i, iadev->reass_reg+FREEQ_ST_ADR);
+        writew(i+iadev->num_rx_desc*sizeof(u_short), 
+                                         iadev->reass_reg+FREEQ_ED_ADR);
+        writew(i, iadev->reass_reg+FREEQ_RD_PTR);
+        writew(i+iadev->num_rx_desc*sizeof(u_short), 
+                                        iadev->reass_reg+FREEQ_WR_PTR);    
+	/* Fill the FREEQ with all the free descriptors. */  
+	freeq_st_adr = readw(iadev->reass_reg+FREEQ_ST_ADR);  
+	freeq_start = (u_short *)(iadev->reass_ram+freeq_st_adr);  
+	for(i=1; i<=iadev->num_rx_desc; i++)  
+	{  
+		*freeq_start = (u_short)i;  
+		freeq_start++;  
+	}  
+	IF_INIT(printk("freeq_start: 0x%0x\n", (u32)freeq_start);)  
+        /* Packet Complete Queue */
+        i = (PKT_COMP_Q * iadev->memSize) & 0xffff;
+        writew(i, iadev->reass_reg+PCQ_ST_ADR);
+        writew(i+iadev->num_vc*sizeof(u_short), iadev->reass_reg+PCQ_ED_ADR);
+        writew(i, iadev->reass_reg+PCQ_RD_PTR);
+        writew(i, iadev->reass_reg+PCQ_WR_PTR);
+
+        /* Exception Queue */
+        i = (EXCEPTION_Q * iadev->memSize) & 0xffff;
+        writew(i, iadev->reass_reg+EXCP_Q_ST_ADR);
+        writew(i + NUM_RX_EXCP * sizeof(RX_ERROR_Q), 
+                                             iadev->reass_reg+EXCP_Q_ED_ADR);
+        writew(i, iadev->reass_reg+EXCP_Q_RD_PTR);
+        writew(i, iadev->reass_reg+EXCP_Q_WR_PTR); 
+ 
+    	/* Load local copy of FREEQ and PCQ ptrs */
+        iadev->rfL.fdq_st = readw(iadev->reass_reg+FREEQ_ST_ADR) & 0xffff;
+       	iadev->rfL.fdq_ed = readw(iadev->reass_reg+FREEQ_ED_ADR) & 0xffff ;
+	iadev->rfL.fdq_rd = readw(iadev->reass_reg+FREEQ_RD_PTR) & 0xffff;
+	iadev->rfL.fdq_wr = readw(iadev->reass_reg+FREEQ_WR_PTR) & 0xffff;
+        iadev->rfL.pcq_st = readw(iadev->reass_reg+PCQ_ST_ADR) & 0xffff;
+	iadev->rfL.pcq_ed = readw(iadev->reass_reg+PCQ_ED_ADR) & 0xffff;
+	iadev->rfL.pcq_rd = readw(iadev->reass_reg+PCQ_RD_PTR) & 0xffff;
+	iadev->rfL.pcq_wr = readw(iadev->reass_reg+PCQ_WR_PTR) & 0xffff;
+	
+        IF_INIT(printk("INIT:pcq_st:0x%x pcq_ed:0x%x pcq_rd:0x%x pcq_wr:0x%x", 
+              iadev->rfL.pcq_st, iadev->rfL.pcq_ed, iadev->rfL.pcq_rd, 
+              iadev->rfL.pcq_wr);)		  
+	/* just for check - no VP TBL */  
+	/* VP Table */  
+	/* writew(0x0b80, iadev->reass_reg+VP_LKUP_BASE); */  
+	/* initialize VP Table for invalid VPIs  
+		- I guess we can write all 1s or 0x000f in the entire memory  
+		  space or something similar.  
+	*/  
+  
+	/* This seems to work and looks right to me too !!! */  
+        i =  REASS_TABLE * iadev->memSize;
+	writew((i >> 3), iadev->reass_reg+REASS_TABLE_BASE);   
+ 	/* initialize Reassembly table to I don't know what ???? */  
+	reass_table = (u16 *)(iadev->reass_ram+i);  
+        j = REASS_TABLE_SZ * iadev->memSize;
+	for(i=0; i < j; i++)  
+		*reass_table++ = NO_AAL5_PKT;  
+       i = 8*1024;
+       vcsize_sel =  0;
+       while (i != iadev->num_vc) {
+          i /= 2;
+          vcsize_sel++;
+       }
+       i = RX_VC_TABLE * iadev->memSize;
+       writew(((i>>3) & 0xfff8) | vcsize_sel, iadev->reass_reg+VC_LKUP_BASE);
+       vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);  
+        j = RX_VC_TABLE_SZ * iadev->memSize;
+	for(i = 0; i < j; i++)  
+	{  
+		/* shift the reassembly pointer by 3 + lower 3 bits of   
+		vc_lkup_base register (=3 for 1K VCs) and the last byte   
+		is those low 3 bits.   
+		Shall program this later.  
+		*/  
+		*vc_table = (i << 6) | 15;	/* for invalid VCI */  
+		vc_table++;  
+	}  
+        /* ABR VC table */
+        i =  ABR_VC_TABLE * iadev->memSize;
+        writew(i >> 3, iadev->reass_reg+ABR_LKUP_BASE);
+                   
+        i = ABR_VC_TABLE * iadev->memSize;
+	abr_vc_table = (struct abr_vc_table *)(iadev->reass_ram+i);  
+        j = REASS_TABLE_SZ * iadev->memSize;
+        memset ((char*)abr_vc_table, 0, j * sizeof(struct abr_vc_table ) );
+    	for(i = 0; i < j; i++) {   		
+		abr_vc_table->rdf = 0x0003;
+             	abr_vc_table->air = 0x5eb1;
+	       	abr_vc_table++;   	
+        }  
+
+	/* Initialize other registers */  
+  
+	/* VP Filter Register set for VC Reassembly only */  
+	writew(0xff00, iadev->reass_reg+VP_FILTER);  
+        writew(0, iadev->reass_reg+XTRA_RM_OFFSET);
+	writew(0x1,  iadev->reass_reg+PROTOCOL_ID);
+
+	/* Packet Timeout Count  related Registers : 
+	   Set packet timeout to occur in about 3 seconds
+	   Set Packet Aging Interval count register to overflow in about 4 us
+ 	*/  
+        writew(0xF6F8, iadev->reass_reg+PKT_TM_CNT );
+        ptr16 = (u16*)j;
+        i = ((u32)ptr16 >> 6) & 0xff;
+	ptr16  += j - 1;
+	i |=(((u32)ptr16 << 2) & 0xff00);
+        writew(i, iadev->reass_reg+TMOUT_RANGE);
+        /* initiate the desc_tble */
+        for(i=0; i<iadev->num_tx_desc;i++)
+            iadev->desc_tbl[i].timestamp = 0;
+
+	/* to clear the interrupt status register - read it */  
+	readw(iadev->reass_reg+REASS_INTR_STATUS_REG);   
+  
+	/* Mask Register - clear it */  
+	writew(~(RX_FREEQ_EMPT|RX_PKT_RCVD), iadev->reass_reg+REASS_MASK_REG);  
+  
+	skb_queue_head_init(&iadev->rx_dma_q);  
+	iadev->rx_free_desc_qhead = NULL;   
+	iadev->rx_open =(struct atm_vcc **)kmalloc(4*iadev->num_vc,GFP_KERNEL);
+	if (!iadev->rx_open)  
+	{  
+		printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n",
+		dev->number);  
+		return -ENOMEM;  
+	}  
+	memset(iadev->rx_open, 0, 4*iadev->num_vc);  
+        iadev->rxing = 1;
+        iadev->rx_pkt_cnt = 0;
+	/* Mode Register */  
+	writew(R_ONLINE, iadev->reass_reg+MODE_REG);  
+	return 0;  
+}  
+  
+
+/*  
+	The memory map suggested in appendix A and the coding for it.   
+	Keeping it around just in case we change our mind later.  
+  
+		Buffer descr	0x0000 (128 - 4K)  
+		UBR sched	0x1000 (1K - 4K)  
+		UBR Wait q	0x2000 (1K - 4K)  
+		Commn queues	0x3000 Packet Ready, Trasmit comp(0x3100)  
+					(128 - 256) each  
+		extended VC	0x4000 (1K - 8K)  
+		ABR sched	0x6000	and ABR wait queue (1K - 2K) each  
+		CBR sched	0x7000 (as needed)  
+		VC table	0x8000 (1K - 32K)  
+*/  
+  
+static void tx_intr(struct atm_dev *dev)  
+{  
+	IADEV *iadev;  
+	unsigned short status;  
+        unsigned long flags;
+
+	iadev = INPH_IA_DEV(dev);  
+  
+	status = readl(iadev->seg_reg+SEG_INTR_STATUS_REG);  
+        if (status & TRANSMIT_DONE){
+
+           IF_EVENT(printk("Tansmit Done Intr logic run\n");)
+           spin_lock_irqsave(&iadev->tx_lock, flags);
+           ia_tx_poll(iadev);
+           spin_unlock_irqrestore(&iadev->tx_lock, flags);
+           writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
+           if (iadev->close_pending)  
+               wake_up(&iadev->close_wait);
+        }     	  
+	if (status & TCQ_NOT_EMPTY)  
+	{  
+	    IF_EVENT(printk("TCQ_NOT_EMPTY int received\n");)  
+	}  
+}  
+  
+static void tx_dle_intr(struct atm_dev *dev)
+{
+        IADEV *iadev;
+        struct dle *dle, *cur_dle; 
+        struct sk_buff *skb;
+        struct atm_vcc *vcc;
+        struct ia_vcc  *iavcc;
+        u_int dle_lp;
+        unsigned long flags;
+
+        iadev = INPH_IA_DEV(dev);
+        spin_lock_irqsave(&iadev->tx_lock, flags);   
+        dle = iadev->tx_dle_q.read;
+        dle_lp = readl(iadev->dma+IPHASE5575_TX_LIST_ADDR) & 
+                                        (sizeof(struct dle)*DLE_ENTRIES - 1);
+        cur_dle = (struct dle*)(iadev->tx_dle_q.start + (dle_lp >> 4));
+        while (dle != cur_dle)
+        {
+            /* free the DMAed skb */ 
+            skb = skb_dequeue(&iadev->tx_dma_q); 
+            if (!skb) break;
+            vcc = ATM_SKB(skb)->vcc;
+            if (!vcc) {
+                  printk("tx_dle_intr: vcc is null\n");
+                  dev_kfree_skb(skb);
+                  return;
+            }
+            iavcc = INPH_IA_VCC(vcc);
+            if (!iavcc) {
+                  printk("tx_dle_intr: iavcc is null\n");
+                  dev_kfree_skb(skb);
+                  return;
+            }
+            if (vcc->qos.txtp.pcr >= iadev->rate_limit) {
+               if ((vcc->pop) && (skb->len != 0))
+               {     
+                 vcc->pop(vcc, skb);
+               } 
+               else {
+                 dev_kfree_skb(skb);
+               }
+            }
+            else { /* Hold the rate-limited skb for flow control */
+               IA_SKB_STATE(skb) |= IA_DLED;
+               skb_queue_tail(&iavcc->txing_skb, skb);
+            }
+            IF_EVENT(printk("tx_dle_intr: enque skb = 0x%x \n", (u32)skb);)
+            if (++dle == iadev->tx_dle_q.end)
+                 dle = iadev->tx_dle_q.start;
+        }
+        iadev->tx_dle_q.read = dle;
+        spin_unlock_irqrestore(&iadev->tx_lock, flags);
+}
+  
+static int open_tx(struct atm_vcc *vcc)  
+{  
+	struct ia_vcc *ia_vcc;  
+	IADEV *iadev;  
+	struct main_vc *vc;  
+	struct ext_vc *evc;  
+        int ret;
+	IF_EVENT(printk("iadev: open_tx entered vcc->vci = %d\n", vcc->vci);)  
+	if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;  
+	iadev = INPH_IA_DEV(vcc->dev);  
+        
+        if (iadev->phy_type & FE_25MBIT_PHY) {
+           if (vcc->qos.txtp.traffic_class == ATM_ABR) {
+               printk("IA:  ABR not support\n");
+               return -EINVAL; 
+           }
+	  if (vcc->qos.txtp.traffic_class == ATM_CBR) {
+               printk("IA:  CBR not support\n");
+               return -EINVAL; 
+          }
+        }
+        ia_vcc =  INPH_IA_VCC(vcc);
+        memset((caddr_t)ia_vcc, 0, sizeof(struct ia_vcc));
+        if (vcc->qos.txtp.max_sdu > 
+                         (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){
+           printk("IA:  SDU size over the configured SDU size %d\n",
+                                                          iadev->tx_buf_sz);
+           kfree(ia_vcc);
+           return -EINVAL; 
+        }
+	ia_vcc->vc_desc_cnt = 0;
+        ia_vcc->txing = 1;
+
+        /* find pcr */
+        if (vcc->qos.txtp.max_pcr == ATM_MAX_PCR) 
+           vcc->qos.txtp.pcr = iadev->LineRate;
+        else if ((vcc->qos.txtp.max_pcr == 0)&&( vcc->qos.txtp.pcr <= 0))
+           vcc->qos.txtp.pcr = iadev->LineRate;
+        else if ((vcc->qos.txtp.max_pcr > vcc->qos.txtp.pcr) && (vcc->qos.txtp.max_pcr> 0)) 
+           vcc->qos.txtp.pcr = vcc->qos.txtp.max_pcr;
+        if (vcc->qos.txtp.pcr > iadev->LineRate)
+             vcc->qos.txtp.pcr = iadev->LineRate;
+        ia_vcc->pcr = vcc->qos.txtp.pcr;
+
+        if (ia_vcc->pcr > (iadev->LineRate / 6) ) ia_vcc->ltimeout = HZ / 10;
+        else if (ia_vcc->pcr > (iadev->LineRate / 130)) ia_vcc->ltimeout = HZ;
+        else if (ia_vcc->pcr <= 170) ia_vcc->ltimeout = 16 * HZ;
+        else ia_vcc->ltimeout = 2700 * HZ  / ia_vcc->pcr;
+        if (ia_vcc->pcr < iadev->rate_limit)
+           skb_queue_head_init (&ia_vcc->txing_skb);
+        if (ia_vcc->pcr < iadev->rate_limit) {
+           if (vcc->qos.txtp.max_sdu != 0) {
+               if (ia_vcc->pcr > 60000)
+                  vcc->sk->sndbuf = vcc->qos.txtp.max_sdu * 5;
+               else if (ia_vcc->pcr > 2000)
+                  vcc->sk->sndbuf = vcc->qos.txtp.max_sdu * 4;
+               else
+                 vcc->sk->sndbuf = 3*vcc->qos.txtp.max_sdu;
+           }
+           else
+             vcc->sk->sndbuf = 24576;
+        }
+           
+	vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;  
+	evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR;  
+	vc += vcc->vci;  
+	evc += vcc->vci;  
+	memset((caddr_t)vc, 0, sizeof(struct main_vc));  
+	memset((caddr_t)evc, 0, sizeof(struct ext_vc));  
+	  
+	/* store the most significant 4 bits of vci as the last 4 bits   
+		of first part of atm header.  
+	   store the last 12 bits of vci as first 12 bits of the second  
+		part of the atm header.  
+	*/  
+	evc->atm_hdr1 = (vcc->vci >> 12) & 0x000f;  
+	evc->atm_hdr2 = (vcc->vci & 0x0fff) << 4;  
+ 
+	/* check the following for different traffic classes */  
+	if (vcc->qos.txtp.traffic_class == ATM_UBR)  
+	{  
+		vc->type = UBR;  
+                vc->status = CRC_APPEND;
+		vc->acr = cellrate_to_float(iadev->LineRate);  
+                if (vcc->qos.txtp.pcr > 0) 
+                   vc->acr = cellrate_to_float(vcc->qos.txtp.pcr);  
+                IF_UBR(printk("UBR: txtp.pcr = 0x%d f_rate = 0x%x\n", 
+                                             vcc->qos.txtp.max_pcr,vc->acr);)
+	}  
+	else if (vcc->qos.txtp.traffic_class == ATM_ABR)  
+	{       srv_cls_param_t srv_p;
+		IF_ABR(printk("Tx ABR VCC\n");)  
+                init_abr_vc(iadev, &srv_p);
+                if (vcc->qos.txtp.pcr > 0) 
+                   srv_p.pcr = vcc->qos.txtp.pcr;
+                if (vcc->qos.txtp.min_pcr > 0) {
+                   int tmpsum = iadev->sum_mcr+iadev->sum_cbr+vcc->qos.txtp.min_pcr;
+                   if (tmpsum > iadev->LineRate)
+                       return -EBUSY;
+                   srv_p.mcr = vcc->qos.txtp.min_pcr;
+                   iadev->sum_mcr += vcc->qos.txtp.min_pcr;
+                } 
+                else srv_p.mcr = 0;
+                if (vcc->qos.txtp.icr)
+                   srv_p.icr = vcc->qos.txtp.icr;
+                if (vcc->qos.txtp.tbe)
+                   srv_p.tbe = vcc->qos.txtp.tbe;
+                if (vcc->qos.txtp.frtt)
+                   srv_p.frtt = vcc->qos.txtp.frtt;
+                if (vcc->qos.txtp.rif)
+                   srv_p.rif = vcc->qos.txtp.rif;
+                if (vcc->qos.txtp.rdf)
+                   srv_p.rdf = vcc->qos.txtp.rdf;
+                if (vcc->qos.txtp.nrm_pres)
+                   srv_p.nrm = vcc->qos.txtp.nrm;
+                if (vcc->qos.txtp.trm_pres)
+                   srv_p.trm = vcc->qos.txtp.trm;
+                if (vcc->qos.txtp.adtf_pres)
+                   srv_p.adtf = vcc->qos.txtp.adtf;
+                if (vcc->qos.txtp.cdf_pres)
+                   srv_p.cdf = vcc->qos.txtp.cdf;    
+                if (srv_p.icr > srv_p.pcr)
+                   srv_p.icr = srv_p.pcr;    
+                IF_ABR(printk("ABR:vcc->qos.txtp.max_pcr = %d  mcr = %d\n", 
+                                                      srv_p.pcr, srv_p.mcr);)
+		ia_open_abr_vc(iadev, &srv_p, vcc, 1);
+	} else if (vcc->qos.txtp.traffic_class == ATM_CBR) {
+                if (iadev->phy_type & FE_25MBIT_PHY) {
+                    printk("IA:  CBR not support\n");
+                    return -EINVAL; 
+                }
+                if (vcc->qos.txtp.max_pcr > iadev->LineRate) {
+                   IF_CBR(printk("PCR is not availble\n");)
+                   return -1;
+                }
+                vc->type = CBR;
+                vc->status = CRC_APPEND;
+                if ((ret = ia_cbr_setup (iadev, vcc)) < 0) {     
+                    return ret;
+                }
+       } 
+	else  
+           printk("iadev:  Non UBR, ABR and CBR traffic not supportedn"); 
+        
+        iadev->testTable[vcc->vci]->vc_status |= VC_ACTIVE;
+	IF_EVENT(printk("ia open_tx returning \n");)  
+	return 0;  
+}  
+  
+  
+static int tx_init(struct atm_dev *dev)  
+{  
+	IADEV *iadev;  
+	struct tx_buf_desc *buf_desc_ptr;
+	unsigned int tx_pkt_start;  
+	u32 *dle_addr;  
+	int i;  
+	u_short tcq_st_adr;  
+	u_short *tcq_start;  
+	u_short prq_st_adr;  
+	u_short *prq_start;  
+	struct main_vc *vc;  
+	struct ext_vc *evc;   
+        u_short tmp16;
+        u32 vcsize_sel;
+ 
+	iadev = INPH_IA_DEV(dev);  
+        spin_lock_init(&iadev->tx_lock);
+ 
+	IF_INIT(printk("Tx MASK REG: 0x%0x\n", 
+                                readw(iadev->seg_reg+SEG_MASK_REG));)  
+	/*---------- Initializing Transmit DLEs ----------*/  
+	/* allocating 8k memory for transmit DLEs */  
+	dle_addr = (u32*)kmalloc(2*sizeof(struct dle)*DLE_ENTRIES, GFP_KERNEL);  
+	if (!dle_addr)  
+	{  
+		printk(KERN_ERR DEV_LABEL "can't allocate TX DLEs\n");  
+	}  
+  
+	/* find 4k byte boundary within the 8k allocated */  
+	dle_addr = (u32*)(((u32)dle_addr+(4096-1)) & ~(4096-1));  
+	iadev->tx_dle_q.start = (struct dle*)dle_addr;  
+	iadev->tx_dle_q.read = iadev->tx_dle_q.start;  
+	iadev->tx_dle_q.write = iadev->tx_dle_q.start;  
+	iadev->tx_dle_q.end = (struct dle*)((u32)dle_addr+sizeof(struct dle)*DLE_ENTRIES);  
+
+	/* write the upper 20 bits of the start address to tx list address register */  
+	writel(virt_to_bus(dle_addr) & 0xfffff000, iadev->dma+IPHASE5575_TX_LIST_ADDR);  
+	writew(0xffff, iadev->seg_reg+SEG_MASK_REG);  
+	writew(0, iadev->seg_reg+MODE_REG_0);  
+	writew(RESET_SEG, iadev->seg_reg+SEG_COMMAND_REG);  
+        iadev->MAIN_VC_TABLE_ADDR = iadev->seg_ram+MAIN_VC_TABLE*iadev->memSize;
+        iadev->EXT_VC_TABLE_ADDR = iadev->seg_ram+EXT_VC_TABLE*iadev->memSize;
+        iadev->ABR_SCHED_TABLE_ADDR=iadev->seg_ram+ABR_SCHED_TABLE*iadev->memSize;
+  
+	/*  
+	   Transmit side control memory map  
+	   --------------------------------    
+	 Buffer descr 	0x0000 (128 - 4K)  
+	 Commn queues	0x1000	Transmit comp, Packet ready(0x1400)   
+					(512 - 1K) each  
+					TCQ - 4K, PRQ - 5K  
+	 CBR Table 	0x1800 (as needed) - 6K  
+	 UBR Table	0x3000 (1K - 4K) - 12K  
+	 UBR Wait queue	0x4000 (1K - 4K) - 16K  
+	 ABR sched	0x5000	and ABR wait queue (1K - 2K) each  
+				ABR Tbl - 20K, ABR Wq - 22K   
+	 extended VC	0x6000 (1K - 8K) - 24K  
+	 VC Table	0x8000 (1K - 32K) - 32K  
+	  
+	Between 0x2000 (8K) and 0x3000 (12K) there is 4K space left for VBR Tbl  
+	and Wait q, which can be allotted later.  
+	*/  
+     
+	/* Buffer Descriptor Table Base address */  
+	writew(TX_DESC_BASE, iadev->seg_reg+SEG_DESC_BASE);  
+  
+	/* initialize each entry in the buffer descriptor table */  
+	buf_desc_ptr =(struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE);  
+	memset((caddr_t)buf_desc_ptr, 0, sizeof(struct tx_buf_desc));  
+	buf_desc_ptr++;  
+	tx_pkt_start = TX_PACKET_RAM;  
+	for(i=1; i<=iadev->num_tx_desc; i++)  
+	{  
+		memset((caddr_t)buf_desc_ptr, 0, sizeof(struct tx_buf_desc));  
+		buf_desc_ptr->desc_mode = AAL5;  
+		buf_desc_ptr->buf_start_hi = tx_pkt_start >> 16;  
+		buf_desc_ptr->buf_start_lo = tx_pkt_start & 0x0000ffff;  
+		buf_desc_ptr++;		  
+		tx_pkt_start += iadev->tx_buf_sz;  
+	}  
+        iadev->tx_buf= (caddr_t*)kmalloc(iadev->num_tx_desc*sizeof(caddr_t), 
+                                                                   GFP_KERNEL);
+        if (!iadev->tx_buf) {
+            printk(KERN_ERR DEV_LABEL " couldn't get mem\n");
+            return -EAGAIN;
+        }
+       	for (i= 0; i< iadev->num_tx_desc; i++)
+       	{
+ 
+       	    iadev->tx_buf[i] =(caddr_t)kmalloc(sizeof(struct cpcs_trailer),
+                                                           GFP_KERNEL|GFP_DMA);
+            if(!iadev->tx_buf[i]) {                
+		printk(KERN_ERR DEV_LABEL " couldn't get freepage\n"); 
+         	return -EAGAIN;
+            }
+        }
+        iadev->desc_tbl = (struct desc_tbl_t *)kmalloc(iadev->num_tx_desc *
+                                   sizeof(struct desc_tbl_t), GFP_KERNEL);
+  
+	/* Communication Queues base address */  
+        i = TX_COMP_Q * iadev->memSize;
+	writew(i >> 16, iadev->seg_reg+SEG_QUEUE_BASE);  
+  
+	/* Transmit Complete Queue */  
+	writew(i, iadev->seg_reg+TCQ_ST_ADR);  
+	writew(i, iadev->seg_reg+TCQ_RD_PTR);  
+	writew(i+iadev->num_tx_desc*sizeof(u_short),iadev->seg_reg+TCQ_WR_PTR); 
+	iadev->host_tcq_wr = i + iadev->num_tx_desc*sizeof(u_short);
+        writew(i+2 * iadev->num_tx_desc * sizeof(u_short), 
+                                              iadev->seg_reg+TCQ_ED_ADR); 
+	/* Fill the TCQ with all the free descriptors. */  
+	tcq_st_adr = readw(iadev->seg_reg+TCQ_ST_ADR);  
+	tcq_start = (u_short *)(iadev->seg_ram+tcq_st_adr);  
+	for(i=1; i<=iadev->num_tx_desc; i++)  
+	{  
+		*tcq_start = (u_short)i;  
+		tcq_start++;  
+	}  
+  
+	/* Packet Ready Queue */  
+        i = PKT_RDY_Q * iadev->memSize; 
+	writew(i, iadev->seg_reg+PRQ_ST_ADR);  
+	writew(i+2 * iadev->num_tx_desc * sizeof(u_short), 
+                                              iadev->seg_reg+PRQ_ED_ADR);
+	writew(i, iadev->seg_reg+PRQ_RD_PTR);  
+	writew(i, iadev->seg_reg+PRQ_WR_PTR);  
+	 
+        /* Load local copy of PRQ and TCQ ptrs */
+        iadev->ffL.prq_st = readw(iadev->seg_reg+PRQ_ST_ADR) & 0xffff;
+	iadev->ffL.prq_ed = readw(iadev->seg_reg+PRQ_ED_ADR) & 0xffff;
+ 	iadev->ffL.prq_wr = readw(iadev->seg_reg+PRQ_WR_PTR) & 0xffff;
+
+	iadev->ffL.tcq_st = readw(iadev->seg_reg+TCQ_ST_ADR) & 0xffff;
+	iadev->ffL.tcq_ed = readw(iadev->seg_reg+TCQ_ED_ADR) & 0xffff;
+	iadev->ffL.tcq_rd = readw(iadev->seg_reg+TCQ_RD_PTR) & 0xffff;
+
+	/* Just for safety initializing the queue to have desc 1 always */  
+	/* Fill the PRQ with all the free descriptors. */  
+	prq_st_adr = readw(iadev->seg_reg+PRQ_ST_ADR);  
+	prq_start = (u_short *)(iadev->seg_ram+prq_st_adr);  
+	for(i=1; i<=iadev->num_tx_desc; i++)  
+	{  
+		*prq_start = (u_short)0;	/* desc 1 in all entries */  
+		prq_start++;  
+	}  
+	/* CBR Table */  
+        IF_INIT(printk("Start CBR Init\n");)
+#if 1  /* for 1K VC board, CBR_PTR_BASE is 0 */
+        writew(0,iadev->seg_reg+CBR_PTR_BASE);
+#else /* Charlie's logic is wrong ? */
+        tmp16 = (iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize)>>17;
+        IF_INIT(printk("cbr_ptr_base = 0x%x ", tmp16);)
+        writew(tmp16,iadev->seg_reg+CBR_PTR_BASE);
+#endif
+
+        IF_INIT(printk("value in register = 0x%x\n",
+                                   readw(iadev->seg_reg+CBR_PTR_BASE));)
+        tmp16 = (CBR_SCHED_TABLE*iadev->memSize) >> 1;
+        writew(tmp16, iadev->seg_reg+CBR_TAB_BEG);
+        IF_INIT(printk("cbr_tab_beg = 0x%x in reg = 0x%x \n", tmp16,
+                                        readw(iadev->seg_reg+CBR_TAB_BEG));)
+        writew(tmp16, iadev->seg_reg+CBR_TAB_END+1); // CBR_PTR;
+        tmp16 = (CBR_SCHED_TABLE*iadev->memSize + iadev->num_vc*6 - 2) >> 1;
+        writew(tmp16, iadev->seg_reg+CBR_TAB_END);
+        IF_INIT(printk("iadev->seg_reg = 0x%x CBR_PTR_BASE = 0x%x\n",
+               (u32)iadev->seg_reg, readw(iadev->seg_reg+CBR_PTR_BASE));)
+        IF_INIT(printk("CBR_TAB_BEG = 0x%x, CBR_TAB_END = 0x%x, CBR_PTR = 0x%x\n",
+          readw(iadev->seg_reg+CBR_TAB_BEG), readw(iadev->seg_reg+CBR_TAB_END),
+          readw(iadev->seg_reg+CBR_TAB_END+1));)
+        tmp16 = (iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize);
+
+        /* Initialize the CBR Schedualing Table */
+        memset((caddr_t)(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize), 
+                                                          0, iadev->num_vc*6); 
+        iadev->CbrRemEntries = iadev->CbrTotEntries = iadev->num_vc*3;
+        iadev->CbrEntryPt = 0;
+        iadev->Granularity = MAX_ATM_155 / iadev->CbrTotEntries;
+        iadev->NumEnabledCBR = 0;
+
+	/* UBR scheduling Table and wait queue */  
+	/* initialize all bytes of UBR scheduler table and wait queue to 0   
+		- SCHEDSZ is 1K (# of entries).  
+		- UBR Table size is 4K  
+		- UBR wait queue is 4K  
+	   since the table and wait queues are contiguous, all the bytes   
+	   can be intialized by one memeset.  
+	*/  
+        
+        vcsize_sel = 0;
+        i = 8*1024;
+        while (i != iadev->num_vc) {
+          i /= 2;
+          vcsize_sel++;
+        }
+ 
+        i = MAIN_VC_TABLE * iadev->memSize;
+        writew(vcsize_sel | ((i >> 8) & 0xfff8),iadev->seg_reg+VCT_BASE);
+        i =  EXT_VC_TABLE * iadev->memSize;
+        writew((i >> 8) & 0xfffe, iadev->seg_reg+VCTE_BASE);
+        i = UBR_SCHED_TABLE * iadev->memSize;
+        writew((i & 0xffff) >> 11,  iadev->seg_reg+UBR_SBPTR_BASE);
+        i = UBR_WAIT_Q * iadev->memSize; 
+        writew((i >> 7) & 0xffff,  iadev->seg_reg+UBRWQ_BASE);
+ 	memset((caddr_t)(iadev->seg_ram+UBR_SCHED_TABLE*iadev->memSize),
+                                                       0, iadev->num_vc*8);
+	/* ABR scheduling Table(0x5000-0x57ff) and wait queue(0x5800-0x5fff)*/  
+	/* initialize all bytes of ABR scheduler table and wait queue to 0   
+		- SCHEDSZ is 1K (# of entries).  
+		- ABR Table size is 2K  
+		- ABR wait queue is 2K  
+	   since the table and wait queues are contiguous, all the bytes   
+	   can be intialized by one memeset.  
+	*/  
+        i = ABR_SCHED_TABLE * iadev->memSize;
+        writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE);
+        i = ABR_WAIT_Q * iadev->memSize;
+        writew((i >> 7) & 0xffff, iadev->seg_reg+ABRWQ_BASE);
+ 
+        i = ABR_SCHED_TABLE*iadev->memSize;
+	memset((caddr_t)(iadev->seg_ram+i),  0, iadev->num_vc*4);
+	vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;  
+	evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR;  
+        iadev->testTable = (struct testTable_t **)
+                          kmalloc(sizeof(long)*iadev->num_vc, GFP_KERNEL); 
+        if (!iadev->testTable) {
+           printk("Get freepage  failed\n");
+           return -EAGAIN; 
+        }
+	for(i=0; i<iadev->num_vc; i++)  
+	{  
+		memset((caddr_t)vc, 0, sizeof(struct main_vc));  
+		memset((caddr_t)evc, 0, sizeof(struct ext_vc));  
+                iadev->testTable[i] = (struct testTable_t *)
+                            kmalloc(sizeof(struct testTable_t), GFP_KERNEL);
+              	iadev->testTable[i]->lastTime = 0;
+ 		iadev->testTable[i]->fract = 0;
+                iadev->testTable[i]->vc_status = VC_UBR;
+		vc++;  
+		evc++;  
+	}  
+  
+	/* Other Initialization */  
+	  
+	/* Max Rate Register */  
+        if (iadev->phy_type & FE_25MBIT_PHY) {
+	   writew(RATE25, iadev->seg_reg+MAXRATE);  
+	   writew((UBR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);  
+        }
+        else {
+	   writew(cellrate_to_float(iadev->LineRate),iadev->seg_reg+MAXRATE);
+	   writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);  
+        }
+	/* Set Idle Header Reigisters to be sure */  
+	writew(0, iadev->seg_reg+IDLEHEADHI);  
+	writew(0, iadev->seg_reg+IDLEHEADLO);  
+  
+	/* Program ABR UBR Priority Register  as  PRI_ABR_UBR_EQUAL */
+        writew(0xaa00, iadev->seg_reg+ABRUBR_ARB); 
+
+        iadev->close_pending = 0;
+#if LINUX_VERSION_CODE >= 0x20303
+        init_waitqueue_head(&iadev->close_wait);
+        init_waitqueue_head(&iadev->timeout_wait);
+#else
+        iadev->close_wait = NULL;
+        iadev->timeout_wait = NULL;
+#endif 
+	skb_queue_head_init(&iadev->tx_dma_q);  
+	ia_init_rtn_q(&iadev->tx_return_q);  
+
+	/* RM Cell Protocol ID and Message Type */  
+	writew(RM_TYPE_4_0, iadev->seg_reg+RM_TYPE);  
+        skb_queue_head_init (&iadev->tx_backlog);
+  
+	/* Mode Register 1 */  
+	writew(MODE_REG_1_VAL, iadev->seg_reg+MODE_REG_1);  
+  
+	/* Mode Register 0 */  
+	writew(T_ONLINE, iadev->seg_reg+MODE_REG_0);  
+  
+	/* Interrupt Status Register - read to clear */  
+	readw(iadev->seg_reg+SEG_INTR_STATUS_REG);  
+  
+	/* Interrupt Mask Reg- don't mask TCQ_NOT_EMPTY interrupt generation */  
+        writew(~(TRANSMIT_DONE | TCQ_NOT_EMPTY), iadev->seg_reg+SEG_MASK_REG);
+        writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);  
+        iadev->tx_pkt_cnt = 0;
+        iadev->rate_limit = iadev->LineRate / 3;
+  
+	return 0;  
+}   
+   
+static void ia_int(int irq, void *dev_id, struct pt_regs *regs)  
+{  
+   struct atm_dev *dev;  
+   IADEV *iadev;  
+   unsigned int status;  
+
+   dev = dev_id;  
+   iadev = INPH_IA_DEV(dev);  
+   while( (status = readl(iadev->reg+IPHASE5575_BUS_STATUS_REG) & 0x7f))  
+   { 
+        IF_EVENT(printk("ia_int: status = 0x%x\n", status);) 
+	if (status & STAT_REASSINT)  
+	{  
+	   /* do something */  
+	   IF_EVENT(printk("REASSINT Bus status reg: %08x\n", status);) 
+	   rx_intr(dev);  
+	}  
+	if (status & STAT_DLERINT)  
+	{  
+	   /* Clear this bit by writing a 1 to it. */  
+	   *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLERINT;
+	   rx_dle_intr(dev);  
+	}  
+	if (status & STAT_SEGINT)  
+	{  
+	   /* do something */ 
+           IF_EVENT(printk("IA: tx_intr \n");) 
+	   tx_intr(dev);  
+	}  
+	if (status & STAT_DLETINT)  
+	{  
+	   *(u_int *)(iadev->reg+IPHASE5575_BUS_STATUS_REG) = STAT_DLETINT;  
+	   tx_dle_intr(dev);  
+	}  
+	if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT))  
+	{  
+           if (status & STAT_FEINT) 
+               IaFrontEndIntr(iadev);
+	}  
+   }  
+}  
+	  
+	  
+	  
+/*----------------------------- entries --------------------------------*/  
+static int get_esi(struct atm_dev *dev)  
+{  
+	IADEV *iadev;  
+	int i;  
+	u32 mac1;  
+	u16 mac2;  
+	  
+	iadev = INPH_IA_DEV(dev);  
+	mac1 = cpu_to_be32(le32_to_cpu(readl(  
+				iadev->reg+IPHASE5575_MAC1)));  
+	mac2 = cpu_to_be16(le16_to_cpu(readl(iadev->reg+IPHASE5575_MAC2)));  
+	IF_INIT(printk("ESI: 0x%08x%04x\n", mac1, mac2);)  
+	for (i=0; i<MAC1_LEN; i++)  
+		dev->esi[i] = mac1 >>(8*(MAC1_LEN-1-i));  
+	  
+	for (i=0; i<MAC2_LEN; i++)  
+		dev->esi[i+MAC1_LEN] = mac2 >>(8*(MAC2_LEN - 1 -i));  
+	return 0;  
+}  
+	  
+static int reset_sar(struct atm_dev *dev)  
+{  
+	IADEV *iadev;  
+	int i, error = 1;  
+	unsigned int pci[64];  
+	  
+	iadev = INPH_IA_DEV(dev);  
+	for(i=0; i<64; i++)  
+	  if ((error = pci_read_config_dword(iadev->pci,  
+				i*4, &pci[i])) != PCIBIOS_SUCCESSFUL)  
+  	      return error;  
+	writel(0, iadev->reg+IPHASE5575_EXT_RESET);  
+	for(i=0; i<64; i++)  
+	  if ((error = pci_write_config_dword(iadev->pci,  
+					i*4, pci[i])) != PCIBIOS_SUCCESSFUL)  
+	    return error;  
+	udelay(5);  
+	return 0;  
+}  
+	  
+	  
+#if LINUX_VERSION_CODE >= 0x20312
+static int __init ia_init(struct atm_dev *dev)
+#else
+__initfunc(static int ia_init(struct atm_dev *dev))
+#endif  
+{  
+	IADEV *iadev;  
+	unsigned int real_base, base;  
+	unsigned short command;  
+	unsigned char revision;  
+	int error, i; 
+	  
+	/* The device has been identified and registered. Now we read   
+	   necessary configuration info like memory base address,   
+	   interrupt number etc */  
+	  
+	IF_INIT(printk(">ia_init\n");)  
+	dev->ci_range.vpi_bits = 0;  
+	dev->ci_range.vci_bits = NR_VCI_LD;  
+
+	iadev = INPH_IA_DEV(dev);  
+		  
+	if ((error = pci_read_config_word(iadev->pci, PCI_COMMAND,&command))   
+		    || (error = pci_read_config_dword(iadev->pci,   
+				PCI_BASE_ADDRESS_0,&real_base))   
+		    || (error = pci_read_config_byte(iadev->pci,   
+				PCI_INTERRUPT_LINE,&iadev->irq))   
+		    || (error = pci_read_config_byte(iadev->pci,   
+				PCI_REVISION_ID,&revision)))   
+	{  
+		printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%x\n",  
+				dev->number,error);  
+		return -EINVAL;  
+	}  
+	IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%x,irq=%d\n",  
+			dev->number, revision, real_base, iadev->irq);)  
+	  
+	/* find mapping size of board */  
+	  
+	/* write all 1's into the base address register.  
+	   read the register whic returns us 0's in the don't care bits.  
+	   size is calculated as ~(don't cre bits) + 1 */  
+	  
+	if (pci_write_config_dword(iadev->pci,   
+			PCI_BASE_ADDRESS_0, 0xffffffff)!=PCIBIOS_SUCCESSFUL)  
+	{  
+		printk(DEV_LABEL "(itf %d): init error 0x%x\n",dev->number,  
+			    error);  
+		return -EINVAL;  
+	}  
+	if(pci_read_config_dword(iadev->pci, PCI_BASE_ADDRESS_0,   
+				&(iadev->pci_map_size)) !=PCIBIOS_SUCCESSFUL)   
+	{  
+		printk(DEV_LABEL "(itf %d): init error 0x%x\n",dev->number,  
+			    error);  
+		return -EINVAL;  
+	}  
+	iadev->pci_map_size &= PCI_BASE_ADDRESS_MEM_MASK;  
+	iadev->pci_map_size = ~iadev->pci_map_size + 1;  
+        if (iadev->pci_map_size == 0x100000){
+          iadev->num_vc = 4096;
+	  dev->ci_range.vci_bits = NR_VCI_4K_LD;  
+          iadev->memSize = 4;
+        }
+        else if (iadev->pci_map_size == 0x40000) {
+          iadev->num_vc = 1024;
+          iadev->memSize = 1;
+        }
+        else {
+           printk("Unknown pci_map_size = 0x%x\n", iadev->pci_map_size);
+           return -EINVAL;
+        }
+	IF_INIT(printk (DEV_LABEL "map size: %i\n", iadev->pci_map_size);)  
+	if(pci_write_config_dword(iadev->pci, PCI_BASE_ADDRESS_0,  
+				real_base)!=PCIBIOS_SUCCESSFUL)  
+	{  
+		printk(DEV_LABEL "(itf %d): init error 0x%x\n",dev->number,  
+			    error);  
+		return -EINVAL;  
+	}  
+	  
+	/* strip flags (last 4 bits )  ---> mask with 0xfffffff0 */  
+	real_base &= MEM_VALID;   
+	/* enabling the responses in memory space */  
+	command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);  
+	if ((error = pci_write_config_word(iadev->pci,  
+				       PCI_COMMAND,  command)))  
+	{  
+		printk(DEV_LABEL "(itf %d): can't enable memory (0x%x)\n",  
+		    dev->number,error);  
+		return error;  
+	}  
+	/*  
+	 * Delay at least 1us before doing any mem accesses (how 'bout 10?)  
+	 */  
+	udelay(10);  
+	  
+	/* mapping the physical address to a virtual address in address space */  
+	base=(unsigned long)ioremap((unsigned long)real_base,iadev->pci_map_size);  /* ioremap is not resolved ??? */  
+	  
+	if (!base)  
+	{  
+		printk(DEV_LABEL " (itf %d): can't set up page mapping\n",  
+			    dev->number);  
+		return error;  
+	}  
+	IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=0x%x,irq=%d\n",  
+			dev->number, revision, base, iadev->irq);)  
+	  
+	/* filling the iphase dev structure */  
+	iadev->mem = iadev->pci_map_size /2;  
+	iadev->base_diff = real_base - base;  
+	iadev->real_base = real_base;  
+	iadev->base = base;  
+		  
+	/* Bus Interface Control Registers */  
+	iadev->reg = (u32 *) (base + REG_BASE);  
+	/* Segmentation Control Registers */  
+	iadev->seg_reg = (u32 *) (base + SEG_BASE);  
+	/* Reassembly Control Registers */  
+	iadev->reass_reg = (u32 *) (base + REASS_BASE);  
+	/* Front end/ DMA control registers */  
+	iadev->phy = (u32 *) (base + PHY_BASE);  
+	iadev->dma = (u32 *) (base + PHY_BASE);  
+	/* RAM - Segmentation RAm and Reassembly RAM */  
+	iadev->ram = (u32 *) (base + ACTUAL_RAM_BASE);  
+	iadev->seg_ram =  (base + ACTUAL_SEG_RAM_BASE);  
+	iadev->reass_ram = (base + ACTUAL_REASS_RAM_BASE);  
+  
+	/* lets print out the above */  
+	IF_INIT(printk("Base addrs: %08x %08x %08x \n %08x %08x %08x %08x\n", 
+          (u32)iadev->reg,(u32)iadev->seg_reg,(u32)iadev->reass_reg, 
+          (u32)iadev->phy, (u32)iadev->ram, (u32)iadev->seg_ram, 
+          (u32)iadev->reass_ram);) 
+	  
+	/* lets try reading the MAC address */  
+	error = get_esi(dev);  
+	if (error) return error;  
+        printk("IA: ");
+	for (i=0; i < ESI_LEN; i++)  
+                printk("%s%02X",i ? "-" : "",dev->esi[i]);  
+        printk("\n");  
+  
+        /* reset SAR */  
+        if (reset_sar(dev)) {
+           printk("IA: reset SAR fail, please try again\n");
+           return 1;
+        }
+	return 0;  
+}  
+
+static void ia_update_stats(IADEV *iadev) {
+    if (!iadev->carrier_detect)
+        return;
+    iadev->rx_cell_cnt += readw(iadev->reass_reg+CELL_CTR0)&0xffff;
+    iadev->rx_cell_cnt += (readw(iadev->reass_reg+CELL_CTR1) & 0xffff) << 16;
+    iadev->drop_rxpkt +=  readw(iadev->reass_reg + DRP_PKT_CNTR ) & 0xffff;
+    iadev->drop_rxcell += readw(iadev->reass_reg + ERR_CNTR) & 0xffff;
+    iadev->tx_cell_cnt += readw(iadev->seg_reg + CELL_CTR_LO_AUTO)&0xffff;
+    iadev->tx_cell_cnt += (readw(iadev->seg_reg+CELL_CTR_HIGH_AUTO)&0xffff)<<16;
+    return;
+}
+  
+static void ia_led_timer(unsigned long arg) {
+ 	unsigned long flags;
+  	static u_char blinking[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+        u_char i;
+        static u32 ctrl_reg; 
+        for (i = 0; i < iadev_count; i++) {
+           if (ia_dev[i]) {
+	      ctrl_reg = readl(ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
+	      if (blinking[i] == 0) {
+		 blinking[i]++;
+                 ctrl_reg &= (~CTRL_LED);
+                 writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
+                 ia_update_stats(ia_dev[i]);
+              }
+              else {
+		 blinking[i] = 0;
+		 ctrl_reg |= CTRL_LED;
+                 writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
+                 spin_lock_irqsave(&ia_dev[i]->tx_lock, flags);
+                 if (ia_dev[i]->close_pending)  
+                    wake_up(&ia_dev[i]->close_wait);
+                 ia_tx_poll(ia_dev[i]);
+                 spin_unlock_irqrestore(&ia_dev[i]->tx_lock, flags);
+              }
+           }
+        }
+	mod_timer(&ia_timer, jiffies + HZ / 4);
+ 	return;
+}
+
+static void ia_phy_put(struct atm_dev *dev, unsigned char value,   
+	unsigned long addr)  
+{  
+	writel(value, INPH_IA_DEV(dev)->phy+addr);  
+}  
+  
+static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr)  
+{  
+	return readl(INPH_IA_DEV(dev)->phy+addr);  
+}  
+
+#if LINUX_VERSION_CODE >= 0x20312
+static int __init ia_start(struct atm_dev *dev)
+#else
+__initfunc(static int ia_start(struct atm_dev *dev))
+#endif  
+{  
+	IADEV *iadev;  
+	int error = 1;  
+	unsigned char phy;  
+	u32 ctrl_reg;  
+	IF_EVENT(printk(">ia_start\n");)  
+	iadev = INPH_IA_DEV(dev);  
+        if (request_irq(iadev->irq, &ia_int, SA_SHIRQ, DEV_LABEL, dev)) {  
+                printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",  
+                    dev->number, iadev->irq);  
+                return -EAGAIN;  
+        }  
+        /* @@@ should release IRQ on error */  
+	/* enabling memory + master */  
+        if ((error = pci_write_config_word(iadev->pci,   
+				PCI_COMMAND,   
+				PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER )))   
+	{  
+                printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"  
+                    "master (0x%x)\n",dev->number, error);  
+                free_irq(iadev->irq, dev); 
+                return error;  
+        }  
+	udelay(10);  
+  
+	/* Maybe we should reset the front end, initialize Bus Interface Control   
+		Registers and see. */  
+  
+	IF_INIT(printk("Bus ctrl reg: %08x\n", 
+                            readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));)  
+	ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG);  
+	ctrl_reg = (ctrl_reg & (CTRL_LED | CTRL_FE_RST))  
+			| CTRL_B8  
+			| CTRL_B16  
+			| CTRL_B32  
+			| CTRL_B48  
+			| CTRL_B64  
+			| CTRL_B128  
+			| CTRL_ERRMASK  
+			| CTRL_DLETMASK		/* shud be removed l8r */  
+			| CTRL_DLERMASK  
+			| CTRL_SEGMASK  
+			| CTRL_REASSMASK 	  
+			| CTRL_FEMASK  
+			| CTRL_CSPREEMPT;  
+  
+       writel(ctrl_reg, iadev->reg+IPHASE5575_BUS_CONTROL_REG);   
+  
+	IF_INIT(printk("Bus ctrl reg after initializing: %08x\n", 
+                           readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));  
+	   printk("Bus status reg after init: %08x\n", 
+                            readl(iadev->reg+IPHASE5575_BUS_STATUS_REG));)  
+    
+        ia_hw_type(iadev); 
+	error = tx_init(dev);  
+	if (error) {
+           free_irq(iadev->irq, dev);  
+           return error;
+        }  
+	error = rx_init(dev);  
+	if (error) {
+          free_irq(iadev->irq, dev); 
+          return error;  
+        }
+  
+	ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG);  
+       	writel(ctrl_reg | CTRL_FE_RST, iadev->reg+IPHASE5575_BUS_CONTROL_REG);   
+	IF_INIT(printk("Bus ctrl reg after initializing: %08x\n", 
+                               readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));)  
+        phy = 0; /* resolve compiler complaint */
+        IF_INIT ( 
+	if ((phy=ia_phy_get(dev,0)) == 0x30)  
+		printk("IA: pm5346,rev.%d\n",phy&0x0f);  
+	else  
+		printk("IA: utopia,rev.%0x\n",phy);) 
+
+        if (iadev->phy_type &  FE_25MBIT_PHY) {
+           ia_mb25_init(iadev);
+           return 0;
+        }
+        if (iadev->phy_type & (FE_DS3_PHY | FE_E3_PHY)) {
+           ia_suni_pm7345_init(iadev);
+           return 0;
+        }
+
+	error = suni_init(dev);  
+	if (error) {
+          free_irq(iadev->irq, dev); 
+          return error;  
+        }
+
+        /* Enable interrupt on loss of signal SUNI_RSOP_CIE 0x10
+           SUNI_RSOP_CIE_LOSE - 0x04
+        */
+        ia_phy_put(dev, ia_phy_get(dev,0x10) | 0x04, 0x10);         
+#ifndef MODULE
+	error = dev->phy->start(dev);  
+	if (error) {
+          free_irq(iadev->irq, dev);
+          return error;
+        }   
+#endif
+        /* Get iadev->carrier_detect status */
+        IaFrontEndIntr(iadev);
+	return 0;  
+}  
+  
+static void ia_close(struct atm_vcc *vcc)  
+{  
+        u16 *vc_table;
+        IADEV *iadev;
+        struct ia_vcc *ia_vcc;
+        struct sk_buff *skb = NULL;
+        struct sk_buff_head tmp_tx_backlog, tmp_vcc_backlog;
+        unsigned long closetime, flags;
+        int ctimeout;
+
+        iadev = INPH_IA_DEV(vcc->dev);
+        ia_vcc = INPH_IA_VCC(vcc);
+	if (!ia_vcc) return;  
+
+        IF_EVENT(printk("ia_close: ia_vcc->vc_desc_cnt = %d  vci = %d\n", 
+                                              ia_vcc->vc_desc_cnt,vcc->vci);)
+	vcc->flags &= ~ATM_VF_READY;  
+        skb_queue_head_init (&tmp_tx_backlog);
+        skb_queue_head_init (&tmp_vcc_backlog); 
+        if (vcc->qos.txtp.traffic_class != ATM_NONE) {
+           iadev->close_pending++;
+           sleep_on_timeout(&iadev->timeout_wait, 50);
+           spin_lock_irqsave(&iadev->tx_lock, flags); 
+           while((skb = skb_dequeue(&iadev->tx_backlog))) {
+              if (ATM_SKB(skb)->vcc == vcc){ 
+                 if (vcc->pop) vcc->pop(vcc, skb);
+                 else dev_kfree_skb(skb);
+              }
+              else 
+                 skb_queue_tail(&tmp_tx_backlog, skb);
+           } 
+           while((skb = skb_dequeue(&tmp_tx_backlog))) 
+             skb_queue_tail(&iadev->tx_backlog, skb);
+           IF_EVENT(printk("IA TX Done decs_cnt = %d\n", ia_vcc->vc_desc_cnt);) 
+           closetime = jiffies;
+           ctimeout = 300000 / ia_vcc->pcr;
+           if (ctimeout == 0)
+              ctimeout = 1;
+           while (ia_vcc->vc_desc_cnt > 0){
+              if ((jiffies - closetime) >= ctimeout) 
+                 break;
+              spin_unlock_irqrestore(&iadev->tx_lock, flags);
+              sleep_on(&iadev->close_wait);
+              spin_lock_irqsave(&iadev->tx_lock, flags);
+           }    
+           iadev->close_pending--;
+           iadev->testTable[vcc->vci]->lastTime = 0;
+           iadev->testTable[vcc->vci]->fract = 0; 
+           iadev->testTable[vcc->vci]->vc_status = VC_UBR; 
+           if (vcc->qos.txtp.traffic_class == ATM_ABR) {
+              if (vcc->qos.txtp.min_pcr > 0)
+                 iadev->sum_mcr -= vcc->qos.txtp.min_pcr;
+           }
+           if (vcc->qos.txtp.traffic_class == ATM_CBR) {
+              ia_vcc = INPH_IA_VCC(vcc); 
+              iadev->sum_mcr -= ia_vcc->NumCbrEntry*iadev->Granularity;
+              ia_cbrVc_close (vcc);
+           }
+           spin_unlock_irqrestore(&iadev->tx_lock, flags);
+        }
+        
+        if (vcc->qos.rxtp.traffic_class != ATM_NONE) {   
+           // reset reass table
+           vc_table = (u16 *)(iadev->reass_ram+REASS_TABLE*iadev->memSize);
+           vc_table += vcc->vci; 
+           *vc_table = NO_AAL5_PKT;
+           // reset vc table
+           vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);
+           vc_table += vcc->vci;
+           *vc_table = (vcc->vci << 6) | 15;
+           if (vcc->qos.rxtp.traffic_class == ATM_ABR) {
+              struct abr_vc_table *abr_vc_table = (struct abr_vc_table *)
+                                (iadev->reass_ram+ABR_VC_TABLE*iadev->memSize);
+              abr_vc_table +=  vcc->vci;
+              abr_vc_table->rdf = 0x0003;
+              abr_vc_table->air = 0x5eb1;
+           }                                 
+           // Drain the packets
+           rx_dle_intr(vcc->dev); 
+           iadev->rx_open[vcc->vci] = 0;
+        }
+	kfree(INPH_IA_VCC(vcc));  
+        ia_vcc = NULL;
+        INPH_IA_VCC(vcc) = NULL;  
+        vcc->flags &= ~ATM_VF_ADDR;  
+        return;        
+}  
+  
+static int ia_open(struct atm_vcc *vcc, short vpi, int vci)  
+{  
+	IADEV *iadev;  
+	struct ia_vcc *ia_vcc;  
+	int error;  
+	if (!(vcc->flags & ATM_VF_PARTIAL))  
+	{  
+		IF_EVENT(printk("ia: not partially allocated resources\n");)  
+		INPH_IA_VCC(vcc) = NULL;  
+	}  
+	iadev = INPH_IA_DEV(vcc->dev);  
+	error = atm_find_ci(vcc, &vpi, &vci);  
+	if (error)   
+	{  
+	    printk("iadev: atm_find_ci returned error %d\n", error);  
+	    return error;  
+	}  
+	vcc->vpi = vpi;  
+	vcc->vci = vci;  
+	if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)  
+	{  
+		IF_EVENT(printk("iphase open: unspec part\n");)  
+		vcc->flags |= ATM_VF_ADDR;  
+	}  
+	if (vcc->qos.aal != ATM_AAL5)  
+		return -EINVAL;  
+	IF_EVENT(printk(DEV_LABEL "(itf %d): open %d.%d\n", 
+                                 vcc->dev->number, vcc->vpi, vcc->vci);)  
+  
+	/* Device dependent initialization */  
+	ia_vcc = kmalloc(sizeof(struct ia_vcc), GFP_KERNEL);  
+	if (!ia_vcc) return -ENOMEM;  
+	INPH_IA_VCC(vcc) = ia_vcc;  
+  
+	if ((error = open_rx(vcc)))  
+	{  
+		IF_EVENT(printk("iadev: error in open_rx, closing\n");)  
+		ia_close(vcc);  
+		return error;  
+	}  
+  
+	if ((error = open_tx(vcc)))  
+	{  
+		IF_EVENT(printk("iadev: error in open_tx, closing\n");)  
+		ia_close(vcc);  
+		return error;  
+	}  
+  
+	vcc->flags |= ATM_VF_READY;  
+
+#ifndef MODULE
+        {
+           static u8 first = 1; 
+           if (first) {
+              ia_timer.next = NULL;
+              ia_timer.prev = NULL;
+              ia_timer.expires = jiffies + 3*HZ;
+              ia_timer.data = 0UL;
+              ia_timer.function = ia_led_timer;
+              add_timer(&ia_timer);
+              first = 0;
+           }           
+        }
+#endif
+	IF_EVENT(printk("ia open returning\n");)  
+	return 0;  
+}  
+  
+static int ia_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)  
+{  
+	IF_EVENT(printk(">ia_change_qos\n");)  
+	return 0;  
+}  
+  
+static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg)  
+{  
+   PIA_CMDBUF ia_cmds;
+   IADEV *iadev;
+   int i, board;
+   u16 *tmps;
+   IF_EVENT(printk(">ia_ioctl\n");)  
+   if (cmd != IA_CMD) {
+      if (!dev->phy->ioctl) return -EINVAL;
+      return dev->phy->ioctl(dev,cmd,arg);
+   } 
+   ia_cmds	= (PIA_CMDBUF)arg;
+   board = ia_cmds->status;
+   if ((board < 0) || (board > iadev_count))
+         board = 0;    
+   iadev = ia_dev[board];
+   switch (ia_cmds->cmd) {
+   case MEMDUMP:
+   {
+	switch (ia_cmds->sub_cmd) {
+       	  case MEMDUMP_DEV:     
+             memcpy((char*)ia_cmds->buf, (char*)iadev,
+                          			sizeof(IADEV));
+             ia_cmds->status = 0;
+             break;
+          case MEMDUMP_SEGREG:
+             tmps = (u16 *)ia_cmds->buf;
+             for(i=0; i<0x80; i+=2, tmps++)
+                *tmps = *(u16*)(iadev->seg_reg+i);
+             ia_cmds->status = 0;
+             ia_cmds->len = 0x80;
+             break;
+          case MEMDUMP_REASSREG:
+             tmps = (u16 *)ia_cmds->buf;
+             for(i=0; i<0x80; i+=2, tmps++)
+                *tmps = *(u16*)(iadev->reass_reg+i);
+             ia_cmds->status = 0;
+             ia_cmds->len = 0x80;
+             break;
+          case MEMDUMP_FFL:
+          {  
+             ia_regs_t       regs_local;
+             ffredn_t        *ffL = &regs_local.ffredn;
+             rfredn_t        *rfL = &regs_local.rfredn;
+                     
+             /* Copy real rfred registers into the local copy */
+ 	     for (i=0; i<(sizeof (rfredn_t))/4; i++)
+                ((u_int *)rfL)[i] = ((u_int *)iadev->reass_reg)[i] & 0xffff;
+             	/* Copy real ffred registers into the local copy */
+	     for (i=0; i<(sizeof (ffredn_t))/4; i++)
+                ((u_int *)ffL)[i] = ((u_int *)iadev->seg_reg)[i] & 0xffff;
+
+             memcpy((char*)ia_cmds->buf,(char*)&regs_local,sizeof(ia_regs_t));
+             printk("Board %d registers dumped\n", board);
+             ia_cmds->status = 0;                  
+	 }	
+    	     break;        
+         case READ_REG:
+         {  
+             desc_dbg(iadev); 
+             ia_cmds->status = 0; 
+         }
+             break;
+         case 0x6:
+         {  
+             ia_cmds->status = 0; 
+             printk("skb = 0x%lx\n", (long)skb_peek(&iadev->tx_backlog));
+             printk("rtn_q: 0x%lx\n",(long)ia_deque_rtn_q(&iadev->tx_return_q));
+         }
+             break;
+         case 0x8:
+         {
+             struct sonet_stats *stats;
+             stats = &PRIV(_ia_dev[board])->sonet_stats;
+             printk("section_bip: %d\n", stats->section_bip);
+             printk("line_bip   : %d\n", stats->line_bip);
+             printk("path_bip   : %d\n", stats->path_bip);
+             printk("line_febe  : %d\n", stats->line_febe);
+             printk("path_febe  : %d\n", stats->path_febe);
+             printk("corr_hcs   : %d\n", stats->corr_hcs);
+             printk("uncorr_hcs : %d\n", stats->uncorr_hcs);
+             printk("tx_cells   : %d\n", stats->tx_cells);
+             printk("rx_cells   : %d\n", stats->rx_cells);
+         }
+            ia_cmds->status = 0;
+            break;
+         case 0x9:
+            for (i = 1; i <= iadev->num_rx_desc; i++)
+               free_desc(_ia_dev[board], i);
+            writew( ~(RX_FREEQ_EMPT | RX_EXCP_RCVD), 
+                                            iadev->reass_reg+REASS_MASK_REG);
+            iadev->rxing = 1;
+            
+            ia_cmds->status = 0;
+            break;
+
+         case 0xb:
+            IaFrontEndIntr(iadev);
+            break;
+         case 0xa:
+         {  
+             ia_cmds->status = 0; 
+             IADebugFlag = ia_cmds->maddr;
+             printk("New debug option loaded\n");
+         }
+             break;
+         default:
+             memcpy((char*)ia_cmds->buf, (char*)ia_cmds->maddr, ia_cmds->len);
+             ia_cmds->status = 0;
+             break;
+      }	
+   }
+      break;
+   default:
+      break;
+
+   }	
+   return 0;  
+}  
+  
+static int ia_getsockopt(struct atm_vcc *vcc, int level, int optname,   
+	void *optval, int optlen)  
+{  
+	IF_EVENT(printk(">ia_getsockopt\n");)  
+	return -EINVAL;  
+}  
+  
+static int ia_setsockopt(struct atm_vcc *vcc, int level, int optname,   
+	void *optval, int optlen)  
+{  
+	IF_EVENT(printk(">ia_setsockopt\n");)  
+	return -EINVAL;  
+}  
+  
+static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
+        IADEV *iadev;
+        struct dle *wr_ptr;
+        struct tx_buf_desc *buf_desc_ptr;
+        int desc;
+        int comp_code;
+        unsigned int addr;
+        int total_len, pad, last;
+        struct cpcs_trailer *trailer;
+        struct ia_vcc *iavcc;
+        iadev = INPH_IA_DEV(vcc->dev);  
+        iavcc = INPH_IA_VCC(vcc);
+        if (!iavcc->txing) {
+           printk("discard packet on closed VC\n");
+           if (vcc->pop) vcc->pop(vcc, skb);
+           else dev_kfree_skb(skb);
+        }
+
+        if (skb->len > iadev->tx_buf_sz - 8) {
+           printk("Transmit size over tx buffer size\n");
+           if (vcc->pop)
+                 vcc->pop(vcc, skb);
+           else
+                 dev_kfree_skb(skb);
+          return 0;
+        }
+        if ((u32)skb->data & 3) {
+           printk("Misaligned SKB\n");
+           if (vcc->pop)
+                 vcc->pop(vcc, skb);
+           else
+                 dev_kfree_skb(skb);
+           return 0;
+        }       
+	/* Get a descriptor number from our free descriptor queue  
+	   We get the descr number from the TCQ now, since I am using  
+	   the TCQ as a free buffer queue. Initially TCQ will be   
+	   initialized with all the descriptors and is hence, full.  
+	*/
+	desc = get_desc (iadev, iavcc);
+	if (desc == 0xffff) 
+	    return 1;
+	comp_code = desc >> 13;  
+	desc &= 0x1fff;  
+  
+	if ((desc == 0) || (desc > iadev->num_tx_desc))  
+	{  
+		IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);) 
+                vcc->stats->tx++;
+		if (vcc->pop)   
+		    vcc->pop(vcc, skb);   
+		else  
+		    dev_kfree_skb(skb);
+		return 0;   /* return SUCCESS */
+	}  
+  
+	if (comp_code)  
+	{  
+	    IF_ERR(printk(DEV_LABEL "send desc:%d completion code %d error\n", 
+                                                            desc, comp_code);)  
+	}  
+       
+        /* remember the desc and vcc mapping */
+        iavcc->vc_desc_cnt++;
+        iadev->desc_tbl[desc-1].iavcc = iavcc;
+        iadev->desc_tbl[desc-1].txskb = skb;
+        IA_SKB_STATE(skb) = 0;
+
+        iadev->ffL.tcq_rd += 2;
+        if (iadev->ffL.tcq_rd > iadev->ffL.tcq_ed)
+	  	iadev->ffL.tcq_rd  = iadev->ffL.tcq_st;
+	writew(iadev->ffL.tcq_rd, iadev->seg_reg+TCQ_RD_PTR);
+  
+	/* Put the descriptor number in the packet ready queue  
+		and put the updated write pointer in the DLE field   
+	*/   
+	*(u16*)(iadev->seg_ram+iadev->ffL.prq_wr) = desc; 
+
+ 	iadev->ffL.prq_wr += 2;
+        if (iadev->ffL.prq_wr > iadev->ffL.prq_ed)
+                iadev->ffL.prq_wr = iadev->ffL.prq_st;
+	  
+	/* Figure out the exact length of the packet and padding required to 
+           make it  aligned on a 48 byte boundary.  */
+	total_len = skb->len + sizeof(struct cpcs_trailer);  
+	last = total_len - (total_len/48)*48;  
+	pad = 48 - last;  
+	total_len = pad + total_len;  
+	IF_TX(printk("ia packet len:%d padding:%d\n", total_len, pad);)  
+ 
+	/* Put the packet in a tx buffer */   
+	if (!iadev->tx_buf[desc-1])  
+		printk("couldn't get free page\n");  
+
+        IF_TX(printk("Sent: skb = 0x%x skb->data: 0x%x len: %d, desc: %d\n",
+                  (u32)skb, (u32)skb->data, skb->len, desc);)
+        addr = virt_to_bus(skb->data);
+	trailer = (struct cpcs_trailer*)iadev->tx_buf[desc-1];  
+	trailer->control = 0; 
+        /*big endian*/ 
+	trailer->length = ((skb->len & 0xff) << 8) | ((skb->len & 0xff00) >> 8);
+	trailer->crc32 = 0;	/* not needed - dummy bytes */  
+
+	/* Display the packet */  
+	IF_TXPKT(printk("Sent data: len = %d MsgNum = %d\n", 
+                                                        skb->len, tcnter++);  
+        xdump(skb->data, skb->len, "TX: ");
+        printk("\n");)
+
+	/* Build the buffer descriptor */  
+	buf_desc_ptr = (struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE);  
+	buf_desc_ptr += desc;	/* points to the corresponding entry */  
+	buf_desc_ptr->desc_mode = AAL5 | EOM_EN | APP_CRC32 | CMPL_INT;   
+        writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
+	buf_desc_ptr->vc_index = vcc->vci;
+	buf_desc_ptr->bytes = total_len;  
+
+        if (vcc->qos.txtp.traffic_class == ATM_ABR)  
+	   clear_lockup (vcc, iadev);
+
+	/* Build the DLE structure */  
+	wr_ptr = iadev->tx_dle_q.write;  
+	memset((caddr_t)wr_ptr, 0, sizeof(struct dle));  
+	wr_ptr->sys_pkt_addr = addr;  
+	wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) | 
+                                                  buf_desc_ptr->buf_start_lo;  
+	/* wr_ptr->bytes = swap(total_len);	didn't seem to affect ?? */  
+	wr_ptr->bytes = skb->len;  
+
+        /* hw bug - DLEs of 0x2d, 0x2e, 0x2f cause DMA lockup */
+        if ((wr_ptr->bytes >> 2) == 0xb)
+           wr_ptr->bytes = 0x30;
+
+	wr_ptr->mode = TX_DLE_PSI; 
+	wr_ptr->prq_wr_ptr_data = 0;
+  
+	/* end is not to be used for the DLE q */  
+	if (++wr_ptr == iadev->tx_dle_q.end)  
+		wr_ptr = iadev->tx_dle_q.start;  
+        
+        /* Build trailer dle */
+        wr_ptr->sys_pkt_addr = virt_to_bus(iadev->tx_buf[desc-1]);
+        wr_ptr->local_pkt_addr = ((buf_desc_ptr->buf_start_hi << 16) | 
+          buf_desc_ptr->buf_start_lo) + total_len - sizeof(struct cpcs_trailer);
+
+        wr_ptr->bytes = sizeof(struct cpcs_trailer);
+        wr_ptr->mode = DMA_INT_ENABLE; 
+        wr_ptr->prq_wr_ptr_data = iadev->ffL.prq_wr;
+        
+        /* end is not to be used for the DLE q */
+        if (++wr_ptr == iadev->tx_dle_q.end)  
+                wr_ptr = iadev->tx_dle_q.start;
+
+	iadev->tx_dle_q.write = wr_ptr;  
+        ATM_DESC(skb) = vcc->vci;
+        skb_queue_tail(&iadev->tx_dma_q, skb);
+
+        vcc->stats->tx++;
+        iadev->tx_pkt_cnt++;
+	/* Increment transaction counter */  
+	writel(2, iadev->dma+IPHASE5575_TX_COUNTER);  
+        
+#if 0        
+        /* add flow control logic */ 
+        if (vcc->stats->tx % 20 == 0) {
+          if (iavcc->vc_desc_cnt > 10) {
+             vcc->tx_quota =  vcc->tx_quota * 3 / 4;
+            printk("Tx1:  vcc->tx_quota = %d \n", (u32)vcc->tx_quota );
+              iavcc->flow_inc = -1;
+              iavcc->saved_tx_quota = vcc->tx_quota;
+           } else if ((iavcc->flow_inc < 0) && (iavcc->vc_desc_cnt < 3)) {
+             // vcc->tx_quota = 3 * iavcc->saved_tx_quota / 4;
+             printk("Tx2:  vcc->tx_quota = %d \n", (u32)vcc->tx_quota ); 
+              iavcc->flow_inc = 0;
+           }
+        }
+#endif
+	IF_TX(printk("ia send done\n");)  
+	return 0;  
+}  
+
+static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+        IADEV *iadev; 
+        struct ia_vcc *iavcc;
+        unsigned long flags;
+
+        iadev = INPH_IA_DEV(vcc->dev);
+        iavcc = INPH_IA_VCC(vcc); 
+        if ((!skb)||(skb->len>(iadev->tx_buf_sz-sizeof(struct cpcs_trailer))))
+        {
+            if (!skb)
+                printk(KERN_CRIT "null skb in ia_send\n");
+            dev_kfree_skb(skb);
+            return -EINVAL;
+        }                         
+        spin_lock_irqsave(&iadev->tx_lock, flags); 
+        if ((vcc->flags & ATM_VF_READY) == 0){ 
+            dev_kfree_skb(skb);
+            spin_unlock_irqrestore(&iadev->tx_lock, flags);
+            return -EINVAL; 
+        }
+        ATM_SKB(skb)->vcc = vcc;
+ 
+        if (skb_peek(&iadev->tx_backlog)) {
+           skb_queue_tail(&iadev->tx_backlog, skb);
+        }
+        else {
+           if (ia_pkt_tx (vcc, skb)) {
+              skb_queue_tail(&iadev->tx_backlog, skb);
+           }
+        }
+        spin_unlock_irqrestore(&iadev->tx_lock, flags);
+        return 0;
+
+}
+
+static int ia_sg_send(struct atm_vcc *vcc, unsigned long start,   
+	unsigned long size)  
+{  
+	IF_EVENT(printk(">ia_sg_send\n");)  
+	return 0;  
+}  
+  
+  
+static int ia_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
+{ 
+  int   left = *pos, n;   
+  char  *tmpPtr;
+  IADEV *iadev = INPH_IA_DEV(dev);
+  if(!left--) {
+     if (iadev->phy_type == FE_25MBIT_PHY) {
+       n = sprintf(page, "  Board Type         :  Iphase5525-1KVC-128K\n");
+       return n;
+     }
+     if (iadev->phy_type == FE_DS3_PHY)
+        n = sprintf(page, "  Board Type         :  Iphase-ATM-DS3");
+     else if (iadev->phy_type == FE_E3_PHY)
+        n = sprintf(page, "  Board Type         :  Iphase-ATM-E3");
+     else if (iadev->phy_type == FE_UTP_OPTION)
+         n = sprintf(page, "  Board Type         :  Iphase-ATM-UTP155"); 
+     else
+        n = sprintf(page, "  Board Type         :  Iphase-ATM-OC3");
+     tmpPtr = page + n;
+     if (iadev->pci_map_size == 0x40000)
+        n += sprintf(tmpPtr, "-1KVC-");
+     else
+        n += sprintf(tmpPtr, "-4KVC-");  
+     tmpPtr = page + n; 
+     if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_1M)
+        n += sprintf(tmpPtr, "1M  \n");
+     else if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_512K)
+        n += sprintf(tmpPtr, "512K\n");
+     else
+       n += sprintf(tmpPtr, "128K\n");
+     return n;
+  }
+  if (!left) {
+     return  sprintf(page, "  Number of Tx Buffer:  %u\n"
+                           "  Size of Tx Buffer  :  %u\n"
+                           "  Number of Rx Buffer:  %u\n"
+                           "  Size of Rx Buffer  :  %u\n"
+                           "  Packets Receiverd  :  %u\n"
+                           "  Packets Transmitted:  %u\n"
+                           "  Cells Received     :  %u\n"
+                           "  Cells Transmitted  :  %u\n"
+                           "  Board Dropped Cells:  %u\n"
+                           "  Board Dropped Pkts :  %u\n",
+                           iadev->num_tx_desc,  iadev->tx_buf_sz,
+                           iadev->num_rx_desc,  iadev->rx_buf_sz,
+                           iadev->rx_pkt_cnt,   iadev->tx_pkt_cnt,
+                           iadev->rx_cell_cnt, iadev->tx_cell_cnt,
+                           iadev->drop_rxcell, iadev->drop_rxpkt);                        
+  }
+  return 0;
+}
+  
+static const struct atmdev_ops ops = {  
+	open:		ia_open,  
+	close:		ia_close,  
+	ioctl:		ia_ioctl,  
+	getsockopt:	ia_getsockopt,  
+	setsockopt:	ia_setsockopt,  
+	send:		ia_send,  
+	sg_send:	ia_sg_send,  
+	phy_put:	ia_phy_put,  
+	phy_get:	ia_phy_get,  
+	change_qos:	ia_change_qos,  
+        proc_read:	ia_proc_read
+};  
+	  
+  
+#if LINUX_VERSION_CODE >= 0x20312
+int __init ia_detect(void)
+#else
+__initfunc(int ia_detect(void)) 
+#endif 
+{  
+	struct atm_dev *dev;  
+	IADEV *iadev;  
+        unsigned long flags;
+        int index = 0;  
+	struct pci_dev *prev_dev;       
+	if (!pci_present()) {  
+		printk(KERN_ERR DEV_LABEL " driver but no PCI BIOS ?\n");  
+		return 0;  
+	}  
+	iadev = (IADEV *)kmalloc(sizeof(IADEV), GFP_KERNEL); 
+	if (!iadev) return -ENOMEM;  
+        memset((char*)iadev, 0, sizeof(IADEV));
+	prev_dev = NULL;  
+	while((iadev->pci = pci_find_device(PCI_VENDOR_ID_IPHASE,  
+		PCI_DEVICE_ID_IPHASE_5575,  prev_dev))) {  
+		IF_INIT(printk("ia detected at bus:%d dev: %d function:%d\n",
+                     iadev->pci->bus->number, PCI_SLOT(iadev->pci->devfn), 
+                                                 PCI_FUNC(iadev->pci->devfn));)  
+		dev = atm_dev_register(DEV_LABEL, &ops, -1, 0);   
+		if (!dev) break;  
+		IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", 
+                                                             dev->number);)  
+		INPH_IA_DEV(dev) = iadev; 
+                // TODO: multi_board using ia_boards logic in cleanup_module
+		ia_dev[index] = iadev;
+		_ia_dev[index] = dev;
+                IF_INIT(printk("dev_id = 0x%x iadev->LineRate = %d \n", 
+                                        (u32)dev, iadev->LineRate);)
+                iadev_count++;
+                spin_lock_init(&iadev->misc_lock);
+                spin_lock_irqsave(&iadev->misc_lock, flags); 
+		if (ia_init(dev) || ia_start(dev)) {  
+			atm_dev_deregister(dev);  
+                        IF_INIT(printk("IA register failed!\n");)
+                        ia_dev[index] = NULL;
+                        _ia_dev[index] = NULL;
+                        iadev_count--;
+                        spin_unlock_irqrestore(&iadev->misc_lock, flags); 
+			return -EINVAL;  
+		}  
+                spin_unlock_irqrestore(&iadev->misc_lock, flags);
+                IF_EVENT(printk("iadev_count = %d\n", iadev_count);)
+		prev_dev = iadev->pci;  
+		iadev->next_board = ia_boards;  
+		ia_boards = dev;  
+		iadev = (IADEV *)kmalloc(   
+				sizeof(IADEV), GFP_KERNEL);  
+		if (!iadev) break;   
+                memset((char*)iadev, 0, sizeof(IADEV)); 
+		index++;  
+                dev = NULL;
+	}  
+	return index;  
+}  
+  
+
+#ifdef MODULE  
+  
+int init_module(void)  
+{  
+	IF_EVENT(printk(">ia init_module\n");)  
+	if (!ia_detect()) {  
+		printk(KERN_ERR DEV_LABEL ": no adapter found\n");  
+		return -ENXIO;  
+	}  
+	// MOD_INC_USE_COUNT; 
+        ia_timer.next = NULL;
+       	ia_timer.prev = NULL;
+   	ia_timer.expires = jiffies + 3*HZ;
+   	ia_timer.data = 0UL;
+   	ia_timer.function = ia_led_timer;
+   	add_timer(&ia_timer); 
+   
+	return 0;  
+}  
+  
+  
+void cleanup_module(void)  
+{  
+	struct atm_dev *dev;  
+	IADEV *iadev;  
+	unsigned short command;  
+        int i, j= 0;
+ 
+	IF_EVENT(printk(">ia cleanup_module\n");)  
+        // MOD_DEC_USE_COUNT;
+	if (MOD_IN_USE)  
+		printk("ia: module in use\n");  
+        del_timer(&ia_timer);
+	while(ia_dev[j])  
+	{  
+		dev = ia_boards;  
+		iadev = INPH_IA_DEV(dev);  
+		ia_boards = iadev->next_board;  
+                
+        	/* disable interrupt of lost signal */
+        	ia_phy_put(dev, ia_phy_get(dev,0x10) & ~(0x4), 0x10); 
+        	udelay(1);
+
+      		/* De-register device */  
+      		atm_dev_deregister(dev);  
+		IF_EVENT(printk("iav deregistered at (itf:%d)\n", dev->number);)
+		for (i= 0; i< iadev->num_tx_desc; i++)
+                        kfree(iadev->tx_buf[i]);
+                kfree(iadev->tx_buf);
+      		/* Disable memory mapping and busmastering */  
+		if (pci_read_config_word(iadev->pci,  
+					     PCI_COMMAND, &command) != 0)  
+      		{  
+         		printk("ia: can't read PCI_COMMAND.\n");  
+      		}  
+      		command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);  
+      		if (pci_write_config_word(iadev->pci,  
+					      PCI_COMMAND, command) != 0)  
+      		{  
+         		printk("ia: can't write PCI_COMMAND.\n");  
+      		}  
+      		free_irq(iadev->irq, dev);  
+      		iounmap((void *) iadev->base);  
+      		kfree(iadev);  
+                j++;
+	}  
+	/* and voila whatever we tried seems to work. I don't know if it will  
+		fix suni errors though. Really doubt that. */  
+        for (i = 0; i<8; i++) {
+               ia_dev[i] =  NULL;
+              _ia_dev[i] = NULL;
+        }
+}  
+
+#endif  
+  
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/iphase.h linux/drivers/atm/iphase.h
--- v2.3.42/linux/drivers/atm/iphase.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/atm/iphase.h	Tue Feb  8 18:48:22 2000
@@ -0,0 +1,1467 @@
+/******************************************************************************
+             Device driver for Interphase ATM PCI adapter cards 
+                    Author: Peter Wang  <pwang@iphase.com>            
+                   Interphase Corporation  <www.iphase.com>           
+                               Version: 1.0   
+               iphase.h:  This is the header file for iphase.c. 
+*******************************************************************************
+      
+      This software may be used and distributed according to the terms
+      of the GNU Public License (GPL), incorporated herein by reference.
+      Drivers based on this skeleton fall under the GPL and must retain
+      the authorship (implicit copyright) notice.
+
+      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.
+      
+      Modified from an incomplete driver for Interphase 5575 1KVC 1M card which 
+      was originally written by Monalisa Agrawal at UNH. Now this driver 
+      supports a variety of varients of Interphase ATM PCI (i)Chip adapter 
+      card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM) 
+      in terms of PHY type, the size of control memory and the size of 
+      packet memory. The followings are the change log and history:
+     
+          Bugfix the Mona's UBR driver.
+          Modify the basic memory allocation and dma logic.
+          Port the driver to the latest kernel from 2.0.46.
+          Complete the ABR logic of the driver, and added the ABR work-
+              around for the hardware anormalies.
+          Add the CBR support.
+	  Add the flow control logic to the driver to allow rate-limit VC.
+          Add 4K VC support to the board with 512K control memory.
+          Add the support of all the variants of the Interphase ATM PCI 
+          (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525
+          (25M UTP25) and x531 (DS3 and E3).
+          Add SMP support.
+
+      Support and updates available at: ftp://ftp.iphase.com/pub/atm
+
+*******************************************************************************/
+  
+#ifndef IPHASE_H  
+#define IPHASE_H  
+
+#include <linux/config.h>
+
+/************************ IADBG DEFINE *********************************/
+/* IADebugFlag Bit Map */ 
+#define IF_IADBG_INIT_ADAPTER   0x00000001        // init adapter info
+#define IF_IADBG_TX             0x00000002        // debug TX
+#define IF_IADBG_RX             0x00000004        // debug RX
+#define IF_IADBG_QUERY_INFO     0x00000008        // debug Request call
+#define IF_IADBG_SHUTDOWN       0x00000010        // debug shutdown event
+#define IF_IADBG_INTR           0x00000020        // debug interrupt DPC
+#define IF_IADBG_TXPKT          0x00000040  	  // debug TX PKT
+#define IF_IADBG_RXPKT          0x00000080  	  // debug RX PKT
+#define IF_IADBG_ERR            0x00000100        // debug system error
+#define IF_IADBG_EVENT          0x00000200        // debug event
+#define IF_IADBG_DIS_INTR       0x00001000        // debug disable interrupt
+#define IF_IADBG_EN_INTR        0x00002000        // debug enable interrupt
+#define IF_IADBG_LOUD           0x00004000        // debugging info
+#define IF_IADBG_VERY_LOUD      0x00008000        // excessive debugging info
+#define IF_IADBG_CBR            0x00100000  	  //
+#define IF_IADBG_UBR            0x00200000  	  //
+#define IF_IADBG_ABR            0x00400000        //
+#define IF_IADBG_DESC           0x01000000        //
+#define IF_IADBG_SUNI_STAT      0x02000000        // suni statistics
+#define IF_IADBG_RESET          0x04000000        
+
+extern	unsigned int	IADebugFlag;
+
+#define IF_IADBG(f) if (IADebugFlag & (f))
+
+#ifdef  CONFIG_ATM_IA_DEBUG   /* Debug build */
+
+#define IF_LOUD(A) IF_IADBG(IF_IADBG_LOUD) { A }
+#define IF_ERR(A) IF_IADBG(IF_IADBG_ERR) { A }
+#define IF_VERY_LOUD(A) IF_IADBG( IF_IADBG_VERY_LOUD ) { A }
+
+#define IF_INIT_ADAPTER(A) IF_IADBG( IF_IADBG_INIT_ADAPTER ) { A }
+#define IF_INIT(A) IF_IADBG( IF_IADBG_INIT_ADAPTER ) { A }
+#define IF_SUNI_STAT(A) IF_IADBG( IF_IADBG_SUNI_STAT ) { A }
+#define IF_QUERY_INFO(A) IF_IADBG( IF_IADBG_QUERY_INFO ) { A }
+#define IF_COPY_OVER(A) IF_IADBG( IF_IADBG_COPY_OVER ) { A }
+
+#define IF_INTR(A) IF_IADBG( IF_IADBG_INTR ) { A }
+#define IF_DIS_INTR(A) IF_IADBG( IF_IADBG_DIS_INTR ) { A }
+#define IF_EN_INTR(A) IF_IADBG( IF_IADBG_EN_INTR ) { A }
+
+#define IF_TX(A) IF_IADBG( IF_IADBG_TX ) { A }
+#define IF_RX(A) IF_IADBG( IF_IADBG_RX ) { A }
+#define IF_TXPKT(A) IF_IADBG( IF_IADBG_TXPKT ) { A }
+#define IF_RXPKT(A) IF_IADBG( IF_IADBG_RXPKT ) { A }
+
+#define IF_SHUTDOWN(A) IF_IADBG(IF_IADBG_SHUTDOWN) { A }
+#define IF_CBR(A) IF_IADBG( IF_IADBG_CBR ) { A }
+#define IF_UBR(A) IF_IADBG( IF_IADBG_UBR ) { A }
+#define IF_ABR(A) IF_IADBG( IF_IADBG_ABR ) { A }
+#define IF_EVENT(A) IF_IADBG( IF_IADBG_EVENT) { A }
+
+#else /* free build */
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+#define IF_INIT_ADAPTER(A)
+#define IF_INIT(A)
+#define IF_SUNI_STAT(A)
+#define IF_PVC_CHKPKT(A)
+#define IF_QUERY_INFO(A)
+#define IF_COPY_OVER(A)
+#define IF_HANG(A)
+#define IF_INTR(A)
+#define IF_DIS_INTR(A)
+#define IF_EN_INTR(A)
+#define IF_TX(A)
+#define IF_RX(A)
+#define IF_TXDEBUG(A)
+#define IF_VC(A)
+#define IF_ERR(A) 
+#define IF_CBR(A)
+#define IF_UBR(A)
+#define IF_ABR(A)
+#define IF_SHUTDOWN(A)
+#define DbgPrint(A)
+#define IF_EVENT(A)
+#define IF_TXPKT(A) 
+#define IF_RXPKT(A)
+#endif /* CONFIG_ATM_IA_DEBUG */ 
+
+#define isprint(a) ((a >=' ')&&(a <= '~'))  
+#define ATM_DESC(skb) (skb->protocol)
+#define IA_SKB_STATE(skb) (skb->protocol)
+#define IA_DLED   1
+#define IA_TX_DONE 2
+
+/* iadbg defines */
+#define IA_CMD   0x7749
+typedef struct {
+	int cmd;
+        int sub_cmd;
+        int len;
+        u32 maddr;
+        int status;
+        void *buf;
+} IA_CMDBUF, *PIA_CMDBUF;
+
+/* cmds */
+#define MEMDUMP     		0x01
+
+/* sub_cmds */
+#define MEMDUMP_SEGREG          0x2
+#define MEMDUMP_DEV  		0x1
+#define MEMDUMP_REASSREG        0x3
+#define MEMDUMP_FFL             0x4
+#define READ_REG                0x5
+#define WAKE_DBG_WAIT           0x6
+
+/************************ IADBG DEFINE END ***************************/
+
+#define Boolean(x)    	((x) ? 1 : 0)
+#define NR_VCI 1024		/* number of VCIs */  
+#define NR_VCI_LD 10		/* log2(NR_VCI) */  
+#define NR_VCI_4K 4096 		/* number of VCIs */  
+#define NR_VCI_4K_LD 12		/* log2(NR_VCI) */  
+#define MEM_VALID 0xfffffff0	/* mask base address with this */  
+  
+#ifndef PCI_VENDOR_ID_IPHASE  
+#define PCI_VENDOR_ID_IPHASE 0x107e  
+#endif  
+#ifndef PCI_DEVICE_ID_IPHASE_5575  
+#define PCI_DEVICE_ID_IPHASE_5575 0x0008  
+#endif  
+#define DEV_LABEL 	"ia"  
+#define PCR	207692  
+#define ICR	100000  
+#define MCR	0  
+#define TBE	1000  
+#define FRTT	1  
+#define RIF	2		  
+#define RDF	4  
+#define NRMCODE 5	/* 0 - 7 */  
+#define TRMCODE	3	/* 0 - 7 */  
+#define CDFCODE	6  
+#define ATDFCODE 2	/* 0 - 15 */  
+  
+/*---------------------- Packet/Cell Memory ------------------------*/  
+#define TX_PACKET_RAM 	0x00000 /* start of Trasnmit Packet memory - 0 */  
+#define DFL_TX_BUF_SZ	10240	/* 10 K buffers */  
+#define DFL_TX_BUFFERS     50 	/* number of packet buffers for Tx   
+					- descriptor 0 unused */  
+#define REASS_RAM_SIZE 0x10000  /* for 64K 1K VC board */  
+#define RX_PACKET_RAM 	0x80000 /* start of Receive Packet memory - 512K */  
+#define DFL_RX_BUF_SZ	10240	/* 10k buffers */  
+#define DFL_RX_BUFFERS      50	/* number of packet buffers for Rx   
+					- descriptor 0 unused */  
+  
+struct cpcs_trailer 
+{  
+	u_short control;  
+	u_short length;  
+	u_int	crc32;  
+};  
+  
+struct ia_vcc 
+{ 
+	int rxing;	 
+	int txing;		 
+        int NumCbrEntry;
+        u32 pcr;
+        u32 saved_tx_quota;
+        int flow_inc;
+        struct sk_buff_head txing_skb; 
+        int  ltimeout;                  
+        u8  vc_desc_cnt;                
+                
+};  
+  
+struct abr_vc_table 
+{  
+	u_char status;  
+	u_char rdf;  
+	u_short air;  
+	u_int res[3];  
+	u_int req_rm_cell_data1;  
+	u_int req_rm_cell_data2;  
+	u_int add_rm_cell_data1;  
+	u_int add_rm_cell_data2;  
+};  
+    
+/* 32 byte entries */  
+struct main_vc 
+{  
+	u_short 	type;  
+#define ABR	0x8000  
+#define UBR 	0xc000  
+#define CBR	0x0000  
+	/* ABR fields */  
+	u_short 	nrm;	 
+ 	u_short 	trm;	   
+	u_short 	rm_timestamp_hi;  
+	u_short 	rm_timestamp_lo:8,  
+			crm:8;		  
+	u_short 	remainder; 	/* ABR and UBR fields - last 10 bits*/  
+	u_short 	next_vc_sched;  
+	u_short 	present_desc;	/* all classes */  
+	u_short 	last_cell_slot;	/* ABR and UBR */  
+	u_short 	pcr;  
+	u_short 	fraction;  
+	u_short 	icr;  
+	u_short 	atdf;  
+	u_short 	mcr;  
+	u_short 	acr;		 
+	u_short 	unack:8,  
+			status:8;	/* all classes */  
+#define UIOLI 0x80  
+#define CRC_APPEND 0x40			/* for status field - CRC-32 append */  
+#define ABR_STATE 0x02  
+  
+};  
+  
+  
+/* 8 byte entries */  
+struct ext_vc 
+{  
+	u_short 	atm_hdr1;  
+	u_short 	atm_hdr2;  
+	u_short 	last_desc;  
+      	u_short 	out_of_rate_link;   /* reserved for UBR and CBR */  
+};  
+  
+  
+#define DLE_ENTRIES 256  
+#define DMA_INT_ENABLE 0x0002	/* use for both Tx and Rx */  
+#define TX_DLE_PSI 0x0001  
+  
+/* Descriptor List Entries (DLE) */  
+struct dle 
+{  
+	u32 	sys_pkt_addr;  
+	u32 	local_pkt_addr;  
+	u32 	bytes;  
+	u16 	prq_wr_ptr_data;  
+	u16 	mode;  
+};  
+  
+struct dle_q 
+{  
+	struct dle 	*start;  
+	struct dle 	*end;  
+	struct dle 	*read;  
+	struct dle 	*write;  
+};  
+  
+struct free_desc_q 
+{  
+	int 	desc;	/* Descriptor number */  
+	struct free_desc_q *next;  
+};  
+  
+struct tx_buf_desc {  
+	unsigned short desc_mode;  
+	unsigned short vc_index;  
+	unsigned short res1;		/* reserved field */  
+	unsigned short bytes;  
+	unsigned short buf_start_hi;  
+	unsigned short buf_start_lo;  
+	unsigned short res2[10];	/* reserved field */  
+};  
+	  
+  
+struct rx_buf_desc { 
+	unsigned short desc_mode;
+	unsigned short vc_index;
+	unsigned short vpi; 
+	unsigned short bytes; 
+	unsigned short buf_start_hi;  
+	unsigned short buf_start_lo;  
+	unsigned short dma_start_hi;  
+	unsigned short dma_start_lo;  
+	unsigned short crc_upper;  
+	unsigned short crc_lower;  
+	unsigned short res:8, timeout:8;  
+	unsigned short res2[5];	/* reserved field */  
+};  
+  
+/*--------SAR stuff ---------------------*/  
+  
+#define EPROM_SIZE 0x40000	/* says 64K in the docs ??? */  
+#define MAC1_LEN	4	   					  
+#define MAC2_LEN	2  
+   
+/*------------ PCI Memory Space Map, 128K SAR memory ----------------*/  
+#define IPHASE5575_PCI_CONFIG_REG_BASE	0x0000  
+#define IPHASE5575_BUS_CONTROL_REG_BASE 0x1000	/* offsets 0x00 - 0x3c */  
+#define IPHASE5575_FRAG_CONTROL_REG_BASE 0x2000  
+#define IPHASE5575_REASS_CONTROL_REG_BASE 0x3000  
+#define IPHASE5575_DMA_CONTROL_REG_BASE	0x4000  
+#define IPHASE5575_FRONT_END_REG_BASE IPHASE5575_DMA_CONTROL_REG_BASE  
+#define IPHASE5575_FRAG_CONTROL_RAM_BASE 0x10000  
+#define IPHASE5575_REASS_CONTROL_RAM_BASE 0x20000  
+  
+/*------------ Bus interface control registers -----------------*/  
+#define IPHASE5575_BUS_CONTROL_REG	0x00  
+#define IPHASE5575_BUS_STATUS_REG	0x01	/* actual offset 0x04 */  
+#define IPHASE5575_MAC1			0x02  
+#define IPHASE5575_REV			0x03  
+#define IPHASE5575_MAC2			0x03	/*actual offset 0x0e-reg 0x0c*/  
+#define IPHASE5575_EXT_RESET		0x04  
+#define IPHASE5575_INT_RESET		0x05	/* addr 1c ?? reg 0x06 */  
+#define IPHASE5575_PCI_ADDR_PAGE	0x07	/* reg 0x08, 0x09 ?? */  
+#define IPHASE5575_EEPROM_ACCESS	0x0a	/* actual offset 0x28 */  
+#define IPHASE5575_CELL_FIFO_QUEUE_SZ	0x0b  
+#define IPHASE5575_CELL_FIFO_MARK_STATE	0x0c  
+#define IPHASE5575_CELL_FIFO_READ_PTR	0x0d  
+#define IPHASE5575_CELL_FIFO_WRITE_PTR	0x0e  
+#define IPHASE5575_CELL_FIFO_CELLS_AVL	0x0f	/* actual offset 0x3c */  
+  
+/* Bus Interface Control Register bits */  
+#define CTRL_FE_RST	0x80000000  
+#define CTRL_LED	0x40000000  
+#define CTRL_25MBPHY	0x10000000  
+#define CTRL_ENCMBMEM	0x08000000  
+#define CTRL_ENOFFSEG	0x01000000  
+#define CTRL_ERRMASK	0x00400000  
+#define CTRL_DLETMASK	0x00100000  
+#define CTRL_DLERMASK	0x00080000  
+#define CTRL_FEMASK	0x00040000  
+#define CTRL_SEGMASK	0x00020000  
+#define CTRL_REASSMASK	0x00010000  
+#define CTRL_CSPREEMPT	0x00002000  
+#define CTRL_B128	0x00000200  
+#define CTRL_B64	0x00000100  
+#define CTRL_B48	0x00000080  
+#define CTRL_B32	0x00000040  
+#define CTRL_B16	0x00000020  
+#define CTRL_B8		0x00000010  
+  
+/* Bus Interface Status Register bits */  
+#define STAT_CMEMSIZ	0xc0000000  
+#define STAT_ADPARCK	0x20000000  
+#define STAT_RESVD	0x1fffff80  
+#define STAT_ERRINT	0x00000040  
+#define STAT_MARKINT	0x00000020  
+#define STAT_DLETINT	0x00000010  
+#define STAT_DLERINT	0x00000008  
+#define STAT_FEINT	0x00000004  
+#define STAT_SEGINT	0x00000002  
+#define STAT_REASSINT	0x00000001  
+  
+  
+/*--------------- Segmentation control registers -----------------*/  
+/* The segmentation registers are 16 bits access and the addresses  
+	are defined as such so the addresses are the actual "offsets" */  
+#define IDLEHEADHI	0x00  
+#define IDLEHEADLO	0x01  
+#define MAXRATE		0x02  
+/* Values for MAXRATE register for 155Mbps and 25.6 Mbps operation */  
+#define RATE155		0x64b1 // 16 bits float format 
+#define MAX_ATM_155     352768 // Cells/second p.118
+#define RATE25		0x5f9d  
+  
+#define STPARMS		0x03  
+#define STPARMS_1K	0x008c  
+#define STPARMS_2K	0x0049  
+#define STPARMS_4K	0x0026  
+#define COMP_EN		0x4000  
+#define CBR_EN		0x2000  
+#define ABR_EN		0x0800  
+#define UBR_EN		0x0400  
+  
+#define ABRUBR_ARB	0x04  
+#define RM_TYPE		0x05  
+/*Value for RM_TYPE register for ATM Forum Traffic Mangement4.0 support*/  
+#define RM_TYPE_4_0	0x0100  
+  
+#define SEG_COMMAND_REG		0x17  
+/* Values for the command register */  
+#define RESET_SEG 0x0055  
+#define RESET_SEG_STATE	0x00aa  
+#define RESET_TX_CELL_CTR 0x00cc  
+  
+#define CBR_PTR_BASE	0x20  
+#define ABR_SBPTR_BASE	0x22  
+#define UBR_SBPTR_BASE  0x23  
+#define ABRWQ_BASE	0x26  
+#define UBRWQ_BASE	0x27  
+#define VCT_BASE	0x28  
+#define VCTE_BASE	0x29  
+#define CBR_TAB_BEG	0x2c  
+#define CBR_TAB_END	0x2d  
+#define PRQ_ST_ADR	0x30  
+#define PRQ_ED_ADR	0x31  
+#define PRQ_RD_PTR	0x32  
+#define PRQ_WR_PTR	0x33  
+#define TCQ_ST_ADR	0x34  
+#define TCQ_ED_ADR 	0x35  
+#define TCQ_RD_PTR	0x36  
+#define TCQ_WR_PTR	0x37  
+#define SEG_QUEUE_BASE	0x40  
+#define SEG_DESC_BASE	0x41  
+#define MODE_REG_0	0x45  
+#define T_ONLINE	0x0002		/* (i)chipSAR is online */  
+  
+#define MODE_REG_1	0x46  
+#define MODE_REG_1_VAL	0x0400		/*for propoer device operation*/  
+  
+#define SEG_INTR_STATUS_REG 0x47  
+#define SEG_MASK_REG	0x48  
+#define TRANSMIT_DONE 0x0200
+#define TCQ_NOT_EMPTY 0x1000	/* this can be used for both the interrupt   
+				status registers as well as the mask register */  
+  
+#define CELL_CTR_HIGH_AUTO 0x49  
+#define CELL_CTR_HIGH_NOAUTO 0xc9  
+#define CELL_CTR_LO_AUTO 0x4a  
+#define CELL_CTR_LO_NOAUTO 0xca  
+  
+/* Diagnostic registers */  
+#define NEXTDESC 	0x59  
+#define NEXTVC		0x5a  
+#define PSLOTCNT	0x5d  
+#define NEWDN		0x6a  
+#define NEWVC		0x6b  
+#define SBPTR		0x6c  
+#define ABRWQ_WRPTR	0x6f  
+#define ABRWQ_RDPTR	0x70  
+#define UBRWQ_WRPTR	0x71  
+#define UBRWQ_RDPTR	0x72  
+#define CBR_VC		0x73  
+#define ABR_SBVC	0x75  
+#define UBR_SBVC	0x76  
+#define ABRNEXTLINK	0x78  
+#define UBRNEXTLINK	0x79  
+  
+  
+/*----------------- Reassembly control registers ---------------------*/  
+/* The reassembly registers are 16 bits access and the addresses  
+	are defined as such so the addresses are the actual "offsets" */  
+#define MODE_REG	0x00  
+#define R_ONLINE	0x0002		/* (i)chip is online */  
+#define IGN_RAW_FL     	0x0004
+  
+#define PROTOCOL_ID	0x01  
+#define REASS_MASK_REG	0x02  
+#define REASS_INTR_STATUS_REG	0x03  
+/* Interrupt Status register bits */  
+#define RX_PKT_CTR_OF	0x8000  
+#define RX_ERR_CTR_OF	0x4000  
+#define RX_CELL_CTR_OF	0x1000  
+#define RX_FREEQ_EMPT	0x0200  
+#define RX_EXCPQ_FL	0x0080  
+#define	RX_RAWQ_FL	0x0010  
+#define RX_EXCP_RCVD	0x0008  
+#define RX_PKT_RCVD	0x0004  
+#define RX_RAW_RCVD	0x0001  
+  
+#define DRP_PKT_CNTR	0x04  
+#define ERR_CNTR	0x05  
+#define RAW_BASE_ADR	0x08  
+#define CELL_CTR0	0x0c  
+#define CELL_CTR1	0x0d  
+#define REASS_COMMAND_REG	0x0f  
+/* Values for command register */  
+#define RESET_REASS	0x0055  
+#define RESET_REASS_STATE 0x00aa  
+#define RESET_DRP_PKT_CNTR 0x00f1  
+#define RESET_ERR_CNTR	0x00f2  
+#define RESET_CELL_CNTR 0x00f8  
+#define RESET_REASS_ALL_REGS 0x00ff  
+  
+#define REASS_DESC_BASE	0x10  
+#define VC_LKUP_BASE	0x11  
+#define REASS_TABLE_BASE 0x12  
+#define REASS_QUEUE_BASE 0x13  
+#define PKT_TM_CNT	0x16  
+#define TMOUT_RANGE	0x17  
+#define INTRVL_CNTR	0x18  
+#define TMOUT_INDX	0x19  
+#define VP_LKUP_BASE	0x1c  
+#define VP_FILTER	0x1d  
+#define ABR_LKUP_BASE	0x1e  
+#define FREEQ_ST_ADR	0x24  
+#define FREEQ_ED_ADR	0x25  
+#define FREEQ_RD_PTR	0x26  
+#define FREEQ_WR_PTR	0x27  
+#define PCQ_ST_ADR	0x28  
+#define PCQ_ED_ADR	0x29  
+#define PCQ_RD_PTR	0x2a  
+#define PCQ_WR_PTR	0x2b  
+#define EXCP_Q_ST_ADR	0x2c  
+#define EXCP_Q_ED_ADR	0x2d  
+#define EXCP_Q_RD_PTR	0x2e  
+#define EXCP_Q_WR_PTR	0x2f  
+#define CC_FIFO_ST_ADR	0x34  
+#define CC_FIFO_ED_ADR	0x35  
+#define CC_FIFO_RD_PTR	0x36  
+#define CC_FIFO_WR_PTR	0x37  
+#define STATE_REG	0x38  
+#define BUF_SIZE	0x42  
+#define XTRA_RM_OFFSET	0x44  
+#define DRP_PKT_CNTR_NC	0x84  
+#define ERR_CNTR_NC	0x85  
+#define CELL_CNTR0_NC	0x8c  
+#define CELL_CNTR1_NC	0x8d  
+  
+/* State Register bits */  
+#define EXCPQ_EMPTY	0x0040  
+#define PCQ_EMPTY	0x0010  
+#define FREEQ_EMPTY	0x0004  
+  
+  
+/*----------------- Front End registers/ DMA control --------------*/  
+/* There is a lot of documentation error regarding these offsets ???   
+	eg:- 2 offsets given 800, a00 for rx counter  
+	similarly many others  
+   Remember again that the offsets are to be 4*register number, so  
+	correct the #defines here   
+*/  
+#define IPHASE5575_TX_COUNTER		0x200	/* offset - 0x800 */  
+#define IPHASE5575_RX_COUNTER		0x280	/* offset - 0xa00 */  
+#define IPHASE5575_TX_LIST_ADDR		0x300	/* offset - 0xc00 */  
+#define IPHASE5575_RX_LIST_ADDR		0x380	/* offset - 0xe00 */  
+  
+/*--------------------------- RAM ---------------------------*/  
+/* These memory maps are actually offsets from the segmentation and reassembly  RAM base addresses */  
+  
+/* Segmentation Control Memory map */  
+#define TX_DESC_BASE	0x0000	/* Buffer Decriptor Table */  
+#define TX_COMP_Q	0x1000	/* Transmit Complete Queue */  
+#define PKT_RDY_Q	0x1400	/* Packet Ready Queue */  
+#define CBR_SCHED_TABLE	0x1800	/* CBR Table */  
+#define UBR_SCHED_TABLE	0x3000	/* UBR Table */  
+#define UBR_WAIT_Q	0x4000	/* UBR Wait Queue */  
+#define ABR_SCHED_TABLE	0x5000	/* ABR Table */  
+#define ABR_WAIT_Q	0x5800	/* ABR Wait Queue */  
+#define EXT_VC_TABLE	0x6000	/* Extended VC Table */  
+#define MAIN_VC_TABLE	0x8000	/* Main VC Table */  
+#define SCHEDSZ		1024	/* ABR and UBR Scheduling Table size */  
+#define TX_DESC_TABLE_SZ 128	/* Number of entries in the Transmit   
+					Buffer Descriptor Table */  
+  
+/* These are used as table offsets in Descriptor Table address generation */  
+#define DESC_MODE	0x0  
+#define VC_INDEX	0x1  
+#define BYTE_CNT	0x3  
+#define PKT_START_HI	0x4  
+#define PKT_START_LO	0x5  
+  
+/* Descriptor Mode Word Bits */  
+#define EOM_EN	0x0800  
+#define AAL5	0x0100  
+#define APP_CRC32 0x0400  
+#define CMPL_INT  0x1000
+  
+#define TABLE_ADDRESS(db, dn, to) \
+	(((unsigned long)(db & 0x04)) << 16) | (dn << 5) | (to << 1)  
+  
+/* Reassembly Control Memory Map */  
+#define RX_DESC_BASE	0x0000	/* Buffer Descriptor Table */  
+#define VP_TABLE	0x5c00	/* VP Table */  
+#define EXCEPTION_Q	0x5e00	/* Exception Queue */  
+#define FREE_BUF_DESC_Q	0x6000	/* Free Buffer Descriptor Queue */  
+#define PKT_COMP_Q	0x6800	/* Packet Complete Queue */  
+#define REASS_TABLE	0x7000	/* Reassembly Table */  
+#define RX_VC_TABLE	0x7800	/* VC Table */  
+#define ABR_VC_TABLE	0x8000	/* ABR VC Table */  
+#define RX_DESC_TABLE_SZ 736	/* Number of entries in the Receive   
+					Buffer Descriptor Table */  
+#define VP_TABLE_SZ	256	 /* Number of entries in VPTable */   
+#define RX_VC_TABLE_SZ 	1024	/* Number of entries in VC Table */   
+#define REASS_TABLE_SZ 	1024	/* Number of entries in Reassembly Table */  
+ /* Buffer Descriptor Table */  
+#define RX_ACT	0x8000  
+#define RX_VPVC	0x4000  
+#define RX_CNG	0x0040  
+#define RX_CER	0x0008  
+#define RX_PTE	0x0004  
+#define RX_OFL	0x0002  
+#define NUM_RX_EXCP   32
+
+/* Reassembly Table */  
+#define NO_AAL5_PKT	0x0000  
+#define AAL5_PKT_REASSEMBLED 0x4000  
+#define AAL5_PKT_TERMINATED 0x8000  
+#define RAW_PKT		0xc000  
+#define REASS_ABR	0x2000  
+  
+/*-------------------- Base Registers --------------------*/  
+#define REG_BASE IPHASE5575_BUS_CONTROL_REG_BASE  
+#define RAM_BASE IPHASE5575_FRAG_CONTROL_RAM_BASE  
+#define PHY_BASE IPHASE5575_FRONT_END_REG_BASE  
+#define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE  
+#define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE  
+
+typedef volatile u_int  freg_t;
+typedef u_int   rreg_t;
+
+typedef struct _ffredn_t {
+        freg_t  idlehead_high;  /* Idle cell header (high)              */
+        freg_t  idlehead_low;   /* Idle cell header (low)               */
+        freg_t  maxrate;        /* Maximum rate                         */
+        freg_t  stparms;        /* Traffic Management Parameters        */
+        freg_t  abrubr_abr;     /* ABRUBR Priority Byte 1, TCR Byte 0   */
+        freg_t  rm_type;        /*                                      */
+        u_int   filler5[0x17 - 0x06];
+        freg_t  cmd_reg;        /* Command register                     */
+        u_int   filler18[0x20 - 0x18];
+        freg_t  cbr_base;       /* CBR Pointer Base                     */
+        freg_t  vbr_base;       /* VBR Pointer Base                     */
+        freg_t  abr_base;       /* ABR Pointer Base                     */
+        freg_t  ubr_base;       /* UBR Pointer Base                     */
+        u_int   filler24;
+        freg_t  vbrwq_base;     /* VBR Wait Queue Base                  */
+        freg_t  abrwq_base;     /* ABR Wait Queue Base                  */
+        freg_t  ubrwq_base;     /* UBR Wait Queue Base                  */
+        freg_t  vct_base;       /* Main VC Table Base                   */
+        freg_t  vcte_base;      /* Extended Main VC Table Base          */
+        u_int   filler2a[0x2C - 0x2A];
+        freg_t  cbr_tab_beg;    /* CBR Table Begin                      */
+        freg_t  cbr_tab_end;    /* CBR Table End                        */
+        freg_t  cbr_pointer;    /* CBR Pointer                          */
+        u_int   filler2f[0x30 - 0x2F];
+        freg_t  prq_st_adr;     /* Packet Ready Queue Start Address     */
+        freg_t  prq_ed_adr;     /* Packet Ready Queue End Address       */
+        freg_t  prq_rd_ptr;     /* Packet Ready Queue read pointer      */
+        freg_t  prq_wr_ptr;     /* Packet Ready Queue write pointer     */
+        freg_t  tcq_st_adr;     /* Transmit Complete Queue Start Address*/
+        freg_t  tcq_ed_adr;     /* Transmit Complete Queue End Address  */
+        freg_t  tcq_rd_ptr;     /* Transmit Complete Queue read pointer */
+        freg_t  tcq_wr_ptr;     /* Transmit Complete Queue write pointer*/
+        u_int   filler38[0x40 - 0x38];
+        freg_t  queue_base;     /* Base address for PRQ and TCQ         */
+        freg_t  desc_base;      /* Base address of descriptor table     */
+        u_int   filler42[0x45 - 0x42];
+        freg_t  mode_reg_0;     /* Mode register 0                      */
+        freg_t  mode_reg_1;     /* Mode register 1                      */
+        freg_t  intr_status_reg;/* Interrupt Status register            */
+        freg_t  mask_reg;       /* Mask Register                        */
+        freg_t  cell_ctr_high1; /* Total cell transfer count (high)     */
+        freg_t  cell_ctr_lo1;   /* Total cell transfer count (low)      */
+        freg_t  state_reg;      /* Status register                      */
+        u_int   filler4c[0x58 - 0x4c];
+        freg_t  curr_desc_num;  /* Contains the current descriptor num  */
+        freg_t  next_desc;      /* Next descriptor                      */
+        freg_t  next_vc;        /* Next VC                              */
+        u_int   filler5b[0x5d - 0x5b];
+        freg_t  present_slot_cnt;/* Present slot count                  */
+        u_int   filler5e[0x6a - 0x5e];
+        freg_t  new_desc_num;   /* New descriptor number                */
+        freg_t  new_vc;         /* New VC                               */
+        freg_t  sched_tbl_ptr;  /* Schedule table pointer               */
+        freg_t  vbrwq_wptr;     /* VBR wait queue write pointer         */
+        freg_t  vbrwq_rptr;     /* VBR wait queue read pointer          */
+        freg_t  abrwq_wptr;     /* ABR wait queue write pointer         */
+        freg_t  abrwq_rptr;     /* ABR wait queue read pointer          */
+        freg_t  ubrwq_wptr;     /* UBR wait queue write pointer         */
+        freg_t  ubrwq_rptr;     /* UBR wait queue read pointer          */
+        freg_t  cbr_vc;         /* CBR VC                               */
+        freg_t  vbr_sb_vc;      /* VBR SB VC                            */
+        freg_t  abr_sb_vc;      /* ABR SB VC                            */
+        freg_t  ubr_sb_vc;      /* UBR SB VC                            */
+        freg_t  vbr_next_link;  /* VBR next link                        */
+        freg_t  abr_next_link;  /* ABR next link                        */
+        freg_t  ubr_next_link;  /* UBR next link                        */
+        u_int   filler7a[0x7c-0x7a];
+        freg_t  out_rate_head;  /* Out of rate head                     */
+        u_int   filler7d[0xca-0x7d]; /* pad out to full address space   */
+        freg_t  cell_ctr_high1_nc;/* Total cell transfer count (high)   */
+        freg_t  cell_ctr_lo1_nc;/* Total cell transfer count (low)      */
+        u_int   fillercc[0x100-0xcc]; /* pad out to full address space   */
+} ffredn_t;
+
+typedef struct _rfredn_t {
+        rreg_t  mode_reg_0;     /* Mode register 0                      */
+        rreg_t  protocol_id;    /* Protocol ID                          */
+        rreg_t  mask_reg;       /* Mask Register                        */
+        rreg_t  intr_status_reg;/* Interrupt status register            */
+        rreg_t  drp_pkt_cntr;   /* Dropped packet cntr (clear on read)  */
+        rreg_t  err_cntr;       /* Error Counter (cleared on read)      */
+        u_int   filler6[0x08 - 0x06];
+        rreg_t  raw_base_adr;   /* Base addr for raw cell Q             */
+        u_int   filler2[0x0c - 0x09];
+        rreg_t  cell_ctr0;      /* Cell Counter 0 (cleared when read)   */
+        rreg_t  cell_ctr1;      /* Cell Counter 1 (cleared when read)   */
+        u_int   filler3[0x0f - 0x0e];
+        rreg_t  cmd_reg;        /* Command register                     */
+        rreg_t  desc_base;      /* Base address for description table   */
+        rreg_t  vc_lkup_base;   /* Base address for VC lookup table     */
+        rreg_t  reass_base;     /* Base address for reassembler table   */
+        rreg_t  queue_base;     /* Base address for Communication queue */
+        u_int   filler14[0x16 - 0x14];
+        rreg_t  pkt_tm_cnt;     /* Packet Timeout and count register    */
+        rreg_t  tmout_range;    /* Range of reassembley IDs for timeout */
+        rreg_t  intrvl_cntr;    /* Packet aging interval counter        */
+        rreg_t  tmout_indx;     /* index of pkt being tested for aging  */
+        u_int   filler1a[0x1c - 0x1a];
+        rreg_t  vp_lkup_base;   /* Base address for VP lookup table     */
+        rreg_t  vp_filter;      /* VP filter register                   */
+        rreg_t  abr_lkup_base;  /* Base address of ABR VC Table         */
+        u_int   filler1f[0x24 - 0x1f];
+        rreg_t  fdq_st_adr;     /* Free desc queue start address        */
+        rreg_t  fdq_ed_adr;     /* Free desc queue end address          */
+        rreg_t  fdq_rd_ptr;     /* Free desc queue read pointer         */
+        rreg_t  fdq_wr_ptr;     /* Free desc queue write pointer        */
+        rreg_t  pcq_st_adr;     /* Packet Complete queue start address  */
+        rreg_t  pcq_ed_adr;     /* Packet Complete queue end address    */
+        rreg_t  pcq_rd_ptr;     /* Packet Complete queue read pointer   */
+        rreg_t  pcq_wr_ptr;     /* Packet Complete queue write pointer  */
+        rreg_t  excp_st_adr;    /* Exception queue start address        */
+        rreg_t  excp_ed_adr;    /* Exception queue end address          */
+        rreg_t  excp_rd_ptr;    /* Exception queue read pointer         */
+        rreg_t  excp_wr_ptr;    /* Exception queue write pointer        */
+        u_int   filler30[0x34 - 0x30];
+        rreg_t  raw_st_adr;     /* Raw Cell start address               */
+        rreg_t  raw_ed_adr;     /* Raw Cell end address                 */
+        rreg_t  raw_rd_ptr;     /* Raw Cell read pointer                */
+        rreg_t  raw_wr_ptr;     /* Raw Cell write pointer               */
+        rreg_t  state_reg;      /* State Register                       */
+        u_int   filler39[0x42 - 0x39];
+        rreg_t  buf_size;       /* Buffer size                          */
+        u_int   filler43;
+        rreg_t  xtra_rm_offset; /* Offset of the additional turnaround RM */
+        u_int   filler45[0x84 - 0x45];
+        rreg_t  drp_pkt_cntr_nc;/* Dropped Packet cntr, Not clear on rd */
+        rreg_t  err_cntr_nc;    /* Error Counter, Not clear on read     */
+        u_int   filler86[0x8c - 0x86];
+        rreg_t  cell_ctr0_nc;   /* Cell Counter 0,  Not clear on read   */
+        rreg_t  cell_ctr1_nc;   /* Cell Counter 1, Not clear on read    */
+        u_int   filler8e[0x100-0x8e]; /* pad out to full address space   */
+} rfredn_t;
+
+typedef struct {
+        /* Atlantic */
+        ffredn_t        ffredn;         /* F FRED                       */
+        rfredn_t        rfredn;         /* R FRED                       */
+} ia_regs_t;
+
+typedef struct {
+	u_short		f_vc_type;	/* VC type              */
+	u_short		f_nrm;		/* Nrm			*/
+	u_short		f_nrmexp;	/* Nrm Exp              */
+	u_short		reserved6;	/* 			*/
+	u_short		f_crm;		/* Crm			*/
+	u_short		reserved10;	/* Reserved		*/
+	u_short		reserved12;	/* Reserved		*/
+	u_short		reserved14;	/* Reserved		*/
+	u_short		last_cell_slot;	/* last_cell_slot_count	*/
+	u_short		f_pcr;		/* Peak Cell Rate	*/
+	u_short		fraction;	/* fraction		*/
+	u_short		f_icr;		/* Initial Cell Rate	*/
+	u_short		f_cdf;		/* */
+	u_short		f_mcr;		/* Minimum Cell Rate	*/
+	u_short		f_acr;		/* Allowed Cell Rate	*/
+	u_short		f_status;	/* */
+} f_vc_abr_entry;
+
+typedef struct {
+        u_short         r_status_rdf;   /* status + RDF         */
+        u_short         r_air;          /* AIR                  */
+        u_short         reserved4[14];  /* Reserved             */
+} r_vc_abr_entry;   
+
+#define MRM 3
+#define MIN(x,y)	((x) < (y)) ? (x) : (y)
+
+typedef struct srv_cls_param {
+        u32 class_type;         /* CBR/VBR/ABR/UBR; use the enum above */
+        u32 pcr;                /* Peak Cell Rate (24-bit) */ 
+        /* VBR parameters */
+        u32 scr;                /* sustainable cell rate */
+        u32 max_burst_size;     /* ?? cell rate or data rate */
+ 
+        /* ABR only UNI 4.0 Parameters */
+        u32 mcr;                /* Min Cell Rate (24-bit) */
+        u32 icr;                /* Initial Cell Rate (24-bit) */
+        u32 tbe;                /* Transient Buffer Exposure (24-bit) */
+        u32 frtt;               /* Fixed Round Trip Time (24-bit) */
+ 
+#if 0   /* Additional Parameters of TM 4.0 */
+bits  31          30           29          28       27-25 24-22 21-19  18-9
+-----------------------------------------------------------------------------
+| NRM present | TRM prsnt | CDF prsnt | ADTF prsnt | NRM | TRM | CDF | ADTF |
+-----------------------------------------------------------------------------
+#endif /* 0 */
+ 
+        u8 nrm;                 /* Max # of Cells for each forward RM
+                                        cell (3-bit) */
+        u8 trm;                 /* Time between forward RM cells (3-bit) */
+        u16 adtf;               /* ACR Decrease Time Factor (10-bit) */
+        u8 cdf;                 /* Cutoff Decrease Factor (3-bit) */
+        u8 rif;                 /* Rate Increment Factor (4-bit) */
+        u8 rdf;                 /* Rate Decrease Factor (4-bit) */
+        u8 reserved;            /* 8 bits to keep structure word aligned */
+} srv_cls_param_t;
+
+struct testTable_t {
+	u16 lastTime; 
+	u16 fract; 
+	u8 vc_status;
+}; 
+
+typedef struct {
+	u16 vci;
+	u16 error;
+} RX_ERROR_Q;
+
+typedef struct {
+	u8 active: 1; 
+	u8 abr: 1; 
+	u8 ubr: 1; 
+	u8 cnt: 5;
+#define VC_ACTIVE 	0x01
+#define VC_ABR		0x02
+#define VC_UBR		0x04
+} vcstatus_t;
+  
+struct ia_rfL_t {
+    	u32  fdq_st;     /* Free desc queue start address        */
+        u32  fdq_ed;     /* Free desc queue end address          */
+        u32  fdq_rd;     /* Free desc queue read pointer         */
+        u32  fdq_wr;     /* Free desc queue write pointer        */
+        u32  pcq_st;     /* Packet Complete queue start address  */
+        u32  pcq_ed;     /* Packet Complete queue end address    */
+        u32  pcq_rd;     /* Packet Complete queue read pointer   */
+        u32  pcq_wr;     /* Packet Complete queue write pointer  */ 
+};
+
+struct ia_ffL_t {
+	u32  prq_st;     /* Packet Ready Queue Start Address     */
+        u32  prq_ed;     /* Packet Ready Queue End Address       */
+        u32  prq_wr;     /* Packet Ready Queue write pointer     */
+        u32  tcq_st;     /* Transmit Complete Queue Start Address*/
+        u32  tcq_ed;     /* Transmit Complete Queue End Address  */
+        u32  tcq_rd;     /* Transmit Complete Queue read pointer */
+};
+
+struct desc_tbl_t {
+        u32 timestamp;
+        struct ia_vcc *iavcc;
+        struct sk_buff *txskb;
+}; 
+
+typedef struct ia_rtn_q {
+   struct desc_tbl_t data;
+   struct ia_rtn_q *next, *tail;
+} IARTN_Q;
+
+#define SUNI_LOSV   	0x04
+typedef struct {
+        u32   suni_master_reset;      /* SUNI Master Reset and Identity     */
+        u32   suni_master_config;     /* SUNI Master Configuration          */
+        u32   suni_master_intr_stat;  /* SUNI Master Interrupt Status       */
+        u32   suni_reserved1;         /* Reserved                           */
+        u32   suni_master_clk_monitor;/* SUNI Master Clock Monitor          */
+        u32   suni_master_control;    /* SUNI Master Clock Monitor          */
+        u32   suni_reserved2[10];     /* Reserved                           */
+
+        u32   suni_rsop_control;      /* RSOP Control/Interrupt Enable      */
+        u32   suni_rsop_status;       /* RSOP Status/Interrupt States       */
+        u32   suni_rsop_section_bip8l;/* RSOP Section BIP-8 LSB             */
+        u32   suni_rsop_section_bip8m;/* RSOP Section BIP-8 MSB             */
+
+        u32   suni_tsop_control;      /* TSOP Control                       */
+        u32   suni_tsop_diag;         /* TSOP Disgnostics                   */
+        u32   suni_tsop_reserved[2];  /* TSOP Reserved                      */
+
+        u32   suni_rlop_cs;           /* RLOP Control/Status                */
+        u32   suni_rlop_intr;         /* RLOP Interrupt Enable/Status       */
+        u32   suni_rlop_line_bip24l;  /* RLOP Line BIP-24 LSB               */
+        u32   suni_rlop_line_bip24;   /* RLOP Line BIP-24                   */
+        u32   suni_rlop_line_bip24m;  /* RLOP Line BIP-24 MSB               */
+        u32   suni_rlop_line_febel;   /* RLOP Line FEBE LSB                 */
+        u32   suni_rlop_line_febe;    /* RLOP Line FEBE                     */
+        u32   suni_rlop_line_febem;   /* RLOP Line FEBE MSB                 */
+
+        u32   suni_tlop_control;      /* TLOP Control                       */
+        u32   suni_tlop_disg;         /* TLOP Disgnostics                   */
+        u32   suni_tlop_reserved[14]; /* TLOP Reserved                      */
+
+        u32   suni_rpop_cs;           /* RPOP Status/Control                */
+        u32   suni_rpop_intr;         /* RPOP Interrupt/Status              */
+        u32   suni_rpop_reserved;     /* RPOP Reserved                      */
+        u32   suni_rpop_intr_ena;     /* RPOP Interrupt Enable              */
+        u32   suni_rpop_reserved1[3]; /* RPOP Reserved                      */
+        u32   suni_rpop_path_sig;     /* RPOP Path Signal Label             */
+        u32   suni_rpop_bip8l;        /* RPOP Path BIP-8 LSB                */
+        u32   suni_rpop_bip8m;        /* RPOP Path BIP-8 MSB                */
+        u32   suni_rpop_febel;        /* RPOP Path FEBE LSB                 */
+        u32   suni_rpop_febem;        /* RPOP Path FEBE MSB                 */
+        u32   suni_rpop_reserved2[4]; /* RPOP Reserved                      */
+
+        u32   suni_tpop_cntrl_daig;   /* TPOP Control/Disgnostics           */
+        u32   suni_tpop_pointer_ctrl; /* TPOP Pointer Control               */
+        u32   suni_tpop_sourcer_ctrl; /* TPOP Source Control                */
+        u32   suni_tpop_reserved1[2]; /* TPOP Reserved                      */
+        u32   suni_tpop_arb_prtl;     /* TPOP Arbitrary Pointer LSB         */
+        u32   suni_tpop_arb_prtm;     /* TPOP Arbitrary Pointer MSB         */
+        u32   suni_tpop_reserved2;    /* TPOP Reserved                      */
+        u32   suni_tpop_path_sig;     /* TPOP Path Signal Lable             */
+        u32   suni_tpop_path_status;  /* TPOP Path Status                   */
+        u32   suni_tpop_reserved3[6]; /* TPOP Reserved                      */              
+
+        u32   suni_racp_cs;           /* RACP Control/Status                */
+        u32   suni_racp_intr;         /* RACP Interrupt Enable/Status       */
+        u32   suni_racp_hdr_pattern;  /* RACP Match Header Pattern          */
+        u32   suni_racp_hdr_mask;     /* RACP Match Header Mask             */
+        u32   suni_racp_corr_hcs;     /* RACP Correctable HCS Error Count   */
+        u32   suni_racp_uncorr_hcs;   /* RACP Uncorrectable HCS Error Count */
+        u32   suni_racp_reserved[10]; /* RACP Reserved                      */
+
+        u32   suni_tacp_control;      /* TACP Control                       */
+        u32   suni_tacp_idle_hdr_pat; /* TACP Idle Cell Header Pattern      */
+        u32   suni_tacp_idle_pay_pay; /* TACP Idle Cell Payld Octet Pattern */
+        u32   suni_tacp_reserved[5];  /* TACP Reserved                      */
+
+        u32   suni_reserved3[24];     /* Reserved                           */
+
+        u32   suni_master_test;       /* SUNI Master Test                   */
+        u32   suni_reserved_test;     /* SUNI Reserved for Test             */
+} IA_SUNI;
+
+
+typedef struct _SUNI_STATS_
+{
+   u32 valid;                       // 1 = oc3 PHY card
+   u32 carrier_detect;              // GPIN input
+   // RSOP: receive section overhead processor
+   u16 rsop_oof_state;              // 1 = out of frame
+   u16 rsop_lof_state;              // 1 = loss of frame
+   u16 rsop_los_state;              // 1 = loss of signal
+   u32 rsop_los_count;              // loss of signal count
+   u32 rsop_bse_count;              // section BIP-8 error count
+   // RLOP: receive line overhead processor
+   u16 rlop_ferf_state;             // 1 = far end receive failure
+   u16 rlop_lais_state;             // 1 = line AIS
+   u32 rlop_lbe_count;              // BIP-24 count
+   u32 rlop_febe_count;             // FEBE count;
+   // RPOP: receive path overhead processor
+   u16 rpop_lop_state;              // 1 = LOP
+   u16 rpop_pais_state;             // 1 = path AIS
+   u16 rpop_pyel_state;             // 1 = path yellow alert
+   u32 rpop_bip_count;              // path BIP-8 error count
+   u32 rpop_febe_count;             // path FEBE error count
+   u16 rpop_psig;                   // path signal label value
+   // RACP: receive ATM cell processor
+   u16 racp_hp_state;               // hunt/presync state
+   u32 racp_fu_count;               // FIFO underrun count
+   u32 racp_fo_count;               // FIFO overrun count
+   u32 racp_chcs_count;             // correctable HCS error count
+   u32 racp_uchcs_count;            // uncorrectable HCS error count
+} IA_SUNI_STATS; 
+
+typedef struct iadev_t {  
+	/*-----base pointers into (i)chipSAR+ address space */   
+	u32 *phy;			/* base pointer into phy(SUNI) */  
+	u32 *dma;			/* base pointer into DMA control   
+						registers */  
+	u32 *reg;			/* base pointer to SAR registers  
+					   - Bus Interface Control Regs */  
+	u32 *seg_reg;			/* base pointer to segmentation engine  
+						internal registers */  
+	u32 *reass_reg;			/* base pointer to reassemble engine  
+						internal registers */  
+	u32 *ram;			/* base pointer to SAR RAM */  
+	unsigned int seg_ram;  
+	unsigned int reass_ram;  
+	struct dle_q tx_dle_q;  
+	struct free_desc_q *tx_free_desc_qhead;  
+	struct sk_buff_head tx_dma_q, tx_backlog;  
+        spinlock_t            tx_lock;
+        IARTN_Q               tx_return_q;
+        u32                   close_pending;
+#if LINUX_VERSION_CODE >= 0x20303
+        wait_queue_head_t    close_wait;
+        wait_queue_head_t    timeout_wait;
+#else
+        struct wait_queue     *close_wait;
+        struct wait_queue     *timeout_wait;
+#endif
+	caddr_t *tx_buf;  
+        u16 num_tx_desc, tx_buf_sz, rate_limit;
+        u32 tx_cell_cnt, tx_pkt_cnt;
+        u32 MAIN_VC_TABLE_ADDR, EXT_VC_TABLE_ADDR, ABR_SCHED_TABLE_ADDR;
+	struct dle_q rx_dle_q;  
+	struct free_desc_q *rx_free_desc_qhead;  
+	struct sk_buff_head rx_dma_q;  
+        spinlock_t rx_lock, misc_lock;
+	struct atm_vcc **rx_open;	/* list of all open VCs */  
+        u16 num_rx_desc, rx_buf_sz, rxing;
+        u32 rx_pkt_ram, rx_tmp_cnt, rx_tmp_jif;
+        u32 RX_DESC_BASE_ADDR;
+        u32 drop_rxpkt, drop_rxcell, rx_cell_cnt, rx_pkt_cnt;
+	struct atm_dev *next_board;	/* other iphase devices */  
+	struct pci_dev *pci;  
+	int mem;  
+	unsigned long base_diff;	/* virtual - real base address */  
+	unsigned int real_base, base;	/* real and virtual base address */  
+	unsigned int pci_map_size;	/*pci map size of board */  
+	unsigned char irq;  
+	unsigned char bus;  
+	unsigned char dev_fn;  
+        u_short  phy_type;
+        u_short  num_vc, memSize, memType;
+        struct ia_ffL_t ffL;
+        struct ia_rfL_t rfL;
+        /* Suni stat */
+        // IA_SUNI_STATS suni_stats;
+        unsigned char carrier_detect;
+        /* CBR related */
+        // transmit DMA & Receive
+        unsigned int tx_dma_cnt;     // number of elements on dma queue
+        unsigned int rx_dma_cnt;     // number of elements on rx dma queue
+        unsigned int NumEnabledCBR;  // number of CBR VCI's enabled.     CBR
+        // receive MARK  for Cell FIFO
+        unsigned int rx_mark_cnt;    // number of elements on mark queue
+        unsigned int CbrTotEntries;  // Total CBR Entries in Scheduling Table.
+        unsigned int CbrRemEntries;  // Remaining CBR Entries in Scheduling Table.
+        unsigned int CbrEntryPt;     // CBR Sched Table Entry Point.
+        unsigned int Granularity;    // CBR Granularity given Table Size.
+        /* ABR related */
+	unsigned int  sum_mcr, sum_cbr, LineRate;
+	unsigned int  n_abr;
+        struct desc_tbl_t *desc_tbl;
+        u_short host_tcq_wr;
+        struct testTable_t **testTable;
+} IADEV;  
+  
+  
+#define INPH_IA_DEV(d) ((IADEV *) (d)->dev_data)  
+#define INPH_IA_VCC(v) ((struct ia_vcc *) (v)->dev_data)  
+
+/******************* IDT77105 25MB/s PHY DEFINE *****************************/
+typedef struct {
+	u_int	mb25_master_ctrl;	/* Master control		     */
+	u_int	mb25_intr_status;	/* Interrupt status		     */
+	u_int	mb25_diag_control;	/* Diagnostic control		     */
+	u_int	mb25_led_hec;		/* LED driver and HEC status/control */
+	u_int	mb25_low_byte_counter;	/* Low byte counter		     */
+	u_int	mb25_high_byte_counter;	/* High byte counter		     */
+} ia_mb25_t;
+
+/*
+ * Master Control
+ */
+#define	MB25_MC_UPLO	0x80		/* UPLO				     */
+#define	MB25_MC_DREC	0x40		/* Discard receive cell errors	     */
+#define	MB25_MC_ECEIO	0x20		/* Enable Cell Error Interrupts Only */
+#define	MB25_MC_TDPC	0x10		/* Transmit data parity check	     */
+#define	MB25_MC_DRIC	0x08		/* Discard receive idle cells	     */
+#define	MB25_MC_HALTTX	0x04		/* Halt Tx			     */
+#define	MB25_MC_UMS	0x02		/* UTOPIA mode select		     */
+#define	MB25_MC_ENABLED	0x01		/* Enable interrupt		     */
+
+/*
+ * Interrupt Status
+ */
+#define	MB25_IS_GSB	0x40		/* GOOD Symbol Bit		     */	
+#define	MB25_IS_HECECR	0x20		/* HEC error cell received	     */
+#define	MB25_IS_SCR	0x10		/* "Short Cell" Received	     */
+#define	MB25_IS_TPE	0x08		/* Trnamsit Parity Error	     */
+#define	MB25_IS_RSCC	0x04		/* Receive Signal Condition change   */
+#define	MB25_IS_RCSE	0x02		/* Received Cell Symbol Error	     */
+#define	MB25_IS_RFIFOO	0x01		/* Received FIFO Overrun	     */
+
+/*
+ * Diagnostic Control
+ */
+#define	MB25_DC_FTXCD	0x80		/* Force TxClav deassert	     */	
+#define	MB25_DC_RXCOS	0x40		/* RxClav operation select	     */
+#define	MB25_DC_ECEIO	0x20		/* Single/Multi-PHY config select    */
+#define	MB25_DC_RLFLUSH	0x10		/* Clear receive FIFO		     */
+#define	MB25_DC_IXPE	0x08		/* Insert xmit payload error	     */
+#define	MB25_DC_IXHECE	0x04		/* Insert Xmit HEC Error	     */
+#define	MB25_DC_LB_MASK	0x03		/* Loopback control mask	     */
+
+#define	MB25_DC_LL	0x03		/* Line Loopback		     */
+#define	MB25_DC_PL	0x02		/* PHY Loopback			     */
+#define	MB25_DC_NM	0x00		
+
+#define FE_MASK 	0x00F0
+#define FE_MULTI_MODE	0x0000
+#define FE_SINGLE_MODE  0x0010 
+#define FE_UTP_OPTION  	0x0020
+#define FE_25MBIT_PHY	0x0040
+#define FE_DS3_PHY      0x0080          /* DS3 */
+#define FE_E3_PHY       0x0090          /* E3 */
+		     
+extern void ia_mb25_init (IADEV *);
+
+/*********************** SUNI_PM7345 PHY DEFINE HERE *********************/
+typedef struct _suni_pm7345_t
+{
+    u_int suni_config;     /* SUNI Configuration */
+    u_int suni_intr_enbl;  /* SUNI Interrupt Enable */
+    u_int suni_intr_stat;  /* SUNI Interrupt Status */
+    u_int suni_control;    /* SUNI Control */
+    u_int suni_id_reset;   /* SUNI Reset and Identity */
+    u_int suni_data_link_ctrl;
+    u_int suni_rboc_conf_intr_enbl;
+    u_int suni_rboc_stat;
+    u_int suni_ds3_frm_cfg;
+    u_int suni_ds3_frm_intr_enbl;
+    u_int suni_ds3_frm_intr_stat;
+    u_int suni_ds3_frm_stat;
+    u_int suni_rfdl_cfg;
+    u_int suni_rfdl_enbl_stat;
+    u_int suni_rfdl_stat;
+    u_int suni_rfdl_data;
+    u_int suni_pmon_chng;
+    u_int suni_pmon_intr_enbl_stat;
+    u_int suni_reserved1[0x13-0x11];
+    u_int suni_pmon_lcv_evt_cnt_lsb;
+    u_int suni_pmon_lcv_evt_cnt_msb;
+    u_int suni_pmon_fbe_evt_cnt_lsb;
+    u_int suni_pmon_fbe_evt_cnt_msb;
+    u_int suni_pmon_sez_det_cnt_lsb;
+    u_int suni_pmon_sez_det_cnt_msb;
+    u_int suni_pmon_pe_evt_cnt_lsb;
+    u_int suni_pmon_pe_evt_cnt_msb;
+    u_int suni_pmon_ppe_evt_cnt_lsb;
+    u_int suni_pmon_ppe_evt_cnt_msb;
+    u_int suni_pmon_febe_evt_cnt_lsb;
+    u_int suni_pmon_febe_evt_cnt_msb;
+    u_int suni_ds3_tran_cfg;
+    u_int suni_ds3_tran_diag;
+    u_int suni_reserved2[0x23-0x21];
+    u_int suni_xfdl_cfg;
+    u_int suni_xfdl_intr_st;
+    u_int suni_xfdl_xmit_data;
+    u_int suni_xboc_code;
+    u_int suni_splr_cfg;
+    u_int suni_splr_intr_en;
+    u_int suni_splr_intr_st;
+    u_int suni_splr_status;
+    u_int suni_splt_cfg;
+    u_int suni_splt_cntl;
+    u_int suni_splt_diag_g1;
+    u_int suni_splt_f1;
+    u_int suni_cppm_loc_meters;
+    u_int suni_cppm_chng_of_cppm_perf_meter;
+    u_int suni_cppm_b1_err_cnt_lsb;
+    u_int suni_cppm_b1_err_cnt_msb;
+    u_int suni_cppm_framing_err_cnt_lsb;
+    u_int suni_cppm_framing_err_cnt_msb;
+    u_int suni_cppm_febe_cnt_lsb;
+    u_int suni_cppm_febe_cnt_msb;
+    u_int suni_cppm_hcs_err_cnt_lsb;
+    u_int suni_cppm_hcs_err_cnt_msb;
+    u_int suni_cppm_idle_un_cell_cnt_lsb;
+    u_int suni_cppm_idle_un_cell_cnt_msb;
+    u_int suni_cppm_rcv_cell_cnt_lsb;
+    u_int suni_cppm_rcv_cell_cnt_msb;
+    u_int suni_cppm_xmit_cell_cnt_lsb;
+    u_int suni_cppm_xmit_cell_cnt_msb;
+    u_int suni_rxcp_ctrl;
+    u_int suni_rxcp_fctrl;
+    u_int suni_rxcp_intr_en_sts;
+    u_int suni_rxcp_idle_pat_h1;
+    u_int suni_rxcp_idle_pat_h2;
+    u_int suni_rxcp_idle_pat_h3;
+    u_int suni_rxcp_idle_pat_h4;
+    u_int suni_rxcp_idle_mask_h1;
+    u_int suni_rxcp_idle_mask_h2;
+    u_int suni_rxcp_idle_mask_h3;
+    u_int suni_rxcp_idle_mask_h4;
+    u_int suni_rxcp_cell_pat_h1;
+    u_int suni_rxcp_cell_pat_h2;
+    u_int suni_rxcp_cell_pat_h3;
+    u_int suni_rxcp_cell_pat_h4;
+    u_int suni_rxcp_cell_mask_h1;
+    u_int suni_rxcp_cell_mask_h2;
+    u_int suni_rxcp_cell_mask_h3;
+    u_int suni_rxcp_cell_mask_h4;
+    u_int suni_rxcp_hcs_cs;
+    u_int suni_rxcp_lcd_cnt_threshold;
+    u_int suni_reserved3[0x57-0x54];
+    u_int suni_txcp_ctrl;
+    u_int suni_txcp_intr_en_sts;
+    u_int suni_txcp_idle_pat_h1;
+    u_int suni_txcp_idle_pat_h2;
+    u_int suni_txcp_idle_pat_h3;
+    u_int suni_txcp_idle_pat_h4;
+    u_int suni_txcp_idle_pat_h5;
+    u_int suni_txcp_idle_payload;
+    u_int suni_e3_frm_fram_options;
+    u_int suni_e3_frm_maint_options;
+    u_int suni_e3_frm_fram_intr_enbl;
+    u_int suni_e3_frm_fram_intr_ind_stat;
+    u_int suni_e3_frm_maint_intr_enbl;
+    u_int suni_e3_frm_maint_intr_ind;
+    u_int suni_e3_frm_maint_stat;
+    u_int suni_reserved4;
+    u_int suni_e3_tran_fram_options;
+    u_int suni_e3_tran_stat_diag_options;
+    u_int suni_e3_tran_bip_8_err_mask;
+    u_int suni_e3_tran_maint_adapt_options;
+    u_int suni_ttb_ctrl;
+    u_int suni_ttb_trail_trace_id_stat;
+    u_int suni_ttb_ind_addr;
+    u_int suni_ttb_ind_data;
+    u_int suni_ttb_exp_payload_type;
+    u_int suni_ttb_payload_type_ctrl_stat;
+    u_int suni_pad5[0x7f-0x71];
+    u_int suni_master_test;
+    u_int suni_pad6[0xff-0x80];
+}suni_pm7345_t;
+
+#define SUNI_PM7345_T suni_pm7345_t
+#define SUNI_PM7345     0x20            /* Suni chip type */
+#define SUNI_PM5346     0x30            /* Suni chip type */
+/*
+ * SUNI_PM7345 Configuration
+ */
+#define SUNI_PM7345_CLB         0x01    /* Cell loopback        */
+#define SUNI_PM7345_PLB         0x02    /* Payload loopback     */
+#define SUNI_PM7345_DLB         0x04    /* Diagnostic loopback  */
+#define SUNI_PM7345_LLB         0x80    /* Line loopback        */
+#define SUNI_PM7345_E3ENBL      0x40    /* E3 enable bit        */
+#define SUNI_PM7345_LOOPT       0x10    /* LOOPT enable bit     */
+#define SUNI_PM7345_FIFOBP      0x20    /* FIFO bypass          */
+#define SUNI_PM7345_FRMRBP      0x08    /* Framer bypass        */
+/*
+ * DS3 FRMR Interrupt Enable
+ */
+#define SUNI_DS3_COFAE  0x80            /* Enable change of frame align */
+#define SUNI_DS3_REDE   0x40            /* Enable DS3 RED state intr    */
+#define SUNI_DS3_CBITE  0x20            /* Enable Appl ID channel intr  */
+#define SUNI_DS3_FERFE  0x10            /* Enable Far End Receive Failure intr*/
+#define SUNI_DS3_IDLE   0x08            /* Enable Idle signal intr      */
+#define SUNI_DS3_AISE   0x04            /* Enable Alarm Indication signal intr*/
+#define SUNI_DS3_OOFE   0x02            /* Enable Out of frame intr     */
+#define SUNI_DS3_LOSE   0x01            /* Enable Loss of signal intr   */
+ 
+/*
+ * DS3 FRMR Status
+ */
+#define SUNI_DS3_ACE    0x80            /* Additional Configuration Reg */
+#define SUNI_DS3_REDV   0x40            /* DS3 RED state                */
+#define SUNI_DS3_CBITV  0x20            /* Application ID channel state */
+#define SUNI_DS3_FERFV  0x10            /* Far End Receive Failure state*/
+#define SUNI_DS3_IDLV   0x08            /* Idle signal state            */
+#define SUNI_DS3_AISV   0x04            /* Alarm Indication signal state*/
+#define SUNI_DS3_OOFV   0x02            /* Out of frame state           */
+#define SUNI_DS3_LOSV   0x01            /* Loss of signal state         */
+
+/*
+ * E3 FRMR Interrupt/Status
+ */
+#define SUNI_E3_CZDI    0x40            /* Consecutive Zeros indicator  */
+#define SUNI_E3_LOSI    0x20            /* Loss of signal intr status   */
+#define SUNI_E3_LCVI    0x10            /* Line code violation intr     */
+#define SUNI_E3_COFAI   0x08            /* Change of frame align intr   */
+#define SUNI_E3_OOFI    0x04            /* Out of frame intr status     */
+#define SUNI_E3_LOS     0x02            /* Loss of signal state         */
+#define SUNI_E3_OOF     0x01            /* Out of frame state           */
+
+/*
+ * E3 FRMR Maintenance Status
+ */
+#define SUNI_E3_AISD    0x80            /* Alarm Indication signal state*/
+#define SUNI_E3_FERF_RAI        0x40    /* FERF/RAI indicator           */
+#define SUNI_E3_FEBE    0x20            /* Far End Block Error indicator*/
+
+/*
+ * RXCP Control/Status
+ */
+#define SUNI_DS3_HCSPASS        0x80    /* Pass cell with HEC errors    */
+#define SUNI_DS3_HCSDQDB        0x40    /* Control octets in HCS calc   */
+#define SUNI_DS3_HCSADD         0x20    /* Add coset poly               */
+#define SUNI_DS3_HCK            0x10    /* Control FIFO data path integ chk*/
+#define SUNI_DS3_BLOCK          0x08    /* Enable cell filtering        */
+#define SUNI_DS3_DSCR           0x04    /* Disable payload descrambling */
+#define SUNI_DS3_OOCDV          0x02    /* Cell delineation state       */
+#define SUNI_DS3_FIFORST        0x01    /* Cell FIFO reset              */
+
+/*
+ * RXCP Interrupt Enable/Status
+ */
+#define SUNI_DS3_OOCDE  0x80            /* Intr enable, change in CDS   */
+#define SUNI_DS3_HCSE   0x40            /* Intr enable, corr HCS errors */
+#define SUNI_DS3_FIFOE  0x20            /* Intr enable, unco HCS errors */
+#define SUNI_DS3_OOCDI  0x10            /* SYNC state                   */
+#define SUNI_DS3_UHCSI  0x08            /* Uncorr. HCS errors detected  */
+#define SUNI_DS3_COCAI  0x04            /* Corr. HCS errors detected    */
+#define SUNI_DS3_FOVRI  0x02            /* FIFO overrun                 */
+#define SUNI_DS3_FUDRI  0x01            /* FIFO underrun                */
+
+extern void ia_suni_pm7345_init (IADEV *iadev);
+
+///////////////////SUNI_PM7345 PHY DEFINE END /////////////////////////////
+
+/* ia_eeprom define*/
+#define MEM_SIZE_MASK   0x000F          /* mask of 4 bits defining memory size*/
+#define MEM_SIZE_128K   0x0000          /* board has 128k buffer */
+#define MEM_SIZE_512K   0x0001          /* board has 512K of buffer */
+#define MEM_SIZE_1M     0x0002          /* board has 1M of buffer */
+                                        /* 0x3 to 0xF are reserved for future */
+
+#define FE_MASK         0x00F0          /* mask of 4 bits defining FE type */
+#define FE_MULTI_MODE   0x0000          /* 155 MBit multimode fiber */
+#define FE_SINGLE_MODE  0x0010          /* 155 MBit single mode laser */
+#define FE_UTP_OPTION   0x0020          /* 155 MBit UTP front end */
+
+#define	NOVRAM_SIZE	64
+#define	CMD_LEN		10
+
+/***********
+ *
+ *	Switches and defines for header files.
+ *
+ *	The following defines are used to turn on and off
+ *	various options in the header files. Primarily useful
+ *	for debugging.
+ *
+ ***********/
+
+/*
+ * a list of the commands that can be sent to the NOVRAM
+ */
+
+#define	EXTEND	0x100
+#define	IAWRITE	0x140
+#define	IAREAD	0x180
+#define	ERASE	0x1c0
+
+#define	EWDS	0x00
+#define	WRAL	0x10
+#define	ERAL	0x20
+#define	EWEN	0x30
+
+/*
+ * these bits duplicate the hw_flip.h register settings
+ * note: how the data in / out bits are defined in the flipper specification 
+ */
+
+#define	NVCE	0x02
+#define	NVSK	0x01
+#define	NVDO	0x08	
+#define NVDI	0x04
+/***********************
+ *
+ * This define ands the value and the current config register and puts
+ * the result in the config register
+ *
+ ***********************/
+
+#define	CFG_AND(val) { \
+		u32 t; \
+		t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \
+		t &= (val); \
+		writel(t, iadev->reg+IPHASE5575_EEPROM_ACCESS); \
+	}
+
+/***********************
+ *
+ * This define ors the value and the current config register and puts
+ * the result in the config register
+ *
+ ***********************/
+
+#define	CFG_OR(val) { \
+		u32 t; \
+		t =  readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \
+		t |= (val); \
+		writel(t, iadev->reg+IPHASE5575_EEPROM_ACCESS); \
+	}
+
+/***********************
+ *
+ * Send a command to the NOVRAM, the command is in cmd.
+ *
+ * clear CE and SK. Then assert CE.
+ * Clock each of the command bits out in the correct order with SK
+ * exit with CE still asserted
+ *
+ ***********************/
+
+#define	NVRAM_CMD(cmd) { \
+		int	i; \
+		u_short c = cmd; \
+		CFG_AND(~(NVCE|NVSK)); \
+		CFG_OR(NVCE); \
+		for (i=0; i<CMD_LEN; i++) { \
+			NVRAM_CLKOUT((c & (1 << (CMD_LEN - 1))) ? 1 : 0); \
+			c <<= 1; \
+		} \
+	}
+
+/***********************
+ *
+ * clear the CE, this must be used after each command is complete
+ *
+ ***********************/
+
+#define	NVRAM_CLR_CE	{CFG_AND(~NVCE)}
+
+/***********************
+ *
+ * clock the data bit in bitval out to the NOVRAM.  The bitval must be
+ * a 1 or 0, or the clockout operation is undefined
+ *
+ ***********************/
+
+#define	NVRAM_CLKOUT(bitval) { \
+		CFG_AND(~NVDI); \
+		CFG_OR((bitval) ? NVDI : 0); \
+		CFG_OR(NVSK); \
+		CFG_AND( ~NVSK); \
+	}
+
+/***********************
+ *
+ * clock the data bit in and return a 1 or 0, depending on the value
+ * that was received from the NOVRAM
+ *
+ ***********************/
+
+#define	NVRAM_CLKIN(value) { \
+		u32 _t; \
+		CFG_OR(NVSK); \
+		CFG_AND(~NVSK); \
+		_t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS); \
+		value = (_t & NVDO) ? 1 : 0; \
+	}
+
+
+#endif /* IPHASE_H */
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c
--- v2.3.42/linux/drivers/atm/nicstar.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/atm/nicstar.c	Tue Feb  8 18:23:13 2000
@@ -44,6 +44,9 @@
 #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
 #include "suni.h"
 #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */
+#ifdef CONFIG_ATM_NICSTAR_USE_IDT77105
+#include "idt77105.h"
+#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
 
 
 /* Additional code ************************************************************/
@@ -99,8 +102,10 @@
 
 #define NS_DELAY mdelay(1)
 
-#define ALIGN_ADDRESS(addr, alignment) \
+#define ALIGN_BUS_ADDR(addr, alignment) \
         ((((u32) (addr)) + (((u32) (alignment)) - 1)) & ~(((u32) (alignment)) - 1))
+#define ALIGN_ADDRESS(addr, alignment) \
+        bus_to_virt(ALIGN_BUS_ADDR(virt_to_bus(addr), alignment))
 
 #undef CEIL(d)
 
@@ -164,21 +169,13 @@
 static unsigned num_cards = 0;
 static struct atmdev_ops atm_ops =
 {
-   NULL,		/* dev_close */
-   ns_open,		/* open */
-   ns_close,		/* close */
-   ns_ioctl,		/* ioctl */
-   NULL,		/* getsockopt */
-   NULL,		/* setsockopt */
-   ns_send,		/* send */
-   NULL,		/* sg_send */
-   NULL,		/* send_oam */
-   ns_phy_put,		/* phy_put */
-   ns_phy_get,		/* phy_get */
-   NULL,		/* feedback */
-   NULL,		/* change_qos */
-   NULL,		/* free_rx_skb */
-   ns_proc_read		/* proc_read */
+   open:	ns_open,
+   close:	ns_close,
+   ioctl:	ns_ioctl,
+   send:	ns_send,
+   phy_put:	ns_phy_put,
+   phy_get:	ns_phy_get,
+   proc_read:	ns_proc_read
 };
 static struct timer_list ns_timer;
 static char *mac[NS_MAX_CARDS] = { NULL
@@ -286,6 +283,12 @@
 
       card = cards[i];
 
+#ifdef CONFIG_ATM_NICSTAR_USE_IDT77105
+      if (card->max_pcr == IDT_25_PCR) {
+        idt77105_stop(card->atmdev);
+      }
+#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
+
       /* Stop everything */
       writel(0x00000000, card->membase + CFG);
 
@@ -457,15 +460,16 @@
    cards[i] = card;
       
    card->index = i;
+   card->atmdev = NULL;
    card->pcidev = pcidev;
-   card->membase = (u32) pcidev->resource[1].start;
+   card->membase = pcidev->resource[1].start;
 #ifdef __powerpc__
    /* Compensate for different memory map between host CPU and PCI bus.
       Shouldn't we use a macro for this? */
    card->membase += KERNELBASE;
 #endif /* __powerpc__ */
-   card->membase = (u32) ioremap(card->membase, NS_IOREMAP_SIZE);
-   if (card->membase == (u32) (NULL))
+   card->membase = (unsigned long) ioremap(card->membase, NS_IOREMAP_SIZE);
+   if (card->membase == 0)
    {
       printk("nicstar%d: can't ioremap() membase.\n",i);
       error = 3;
@@ -497,6 +501,7 @@
       ns_init_card_error(card, error);
       return error;
    }
+#ifdef NS_PCI_LATENCY
    if (pci_latency < NS_PCI_LATENCY)
    {
       PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i, NS_PCI_LATENCY);
@@ -513,6 +518,7 @@
 	 return error;
       }
    }
+#endif /* NS_PCI_LATENCY */
       
    /* Clear timer overflow */
    data = readl(card->membase + STAT);
@@ -872,8 +878,8 @@
    card->atmdev->ci_range.vpi_bits = card->vpibits;
    card->atmdev->ci_range.vci_bits = card->vcibits;
    card->atmdev->link_rate = card->max_pcr;
-
    card->atmdev->phy = NULL;
+
 #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
    if (card->max_pcr == ATM_OC3_PCR) {
       suni_init(card->atmdev);
@@ -883,6 +889,17 @@
 #endif /* MODULE */
    }
 #endif /* CONFIG_ATM_NICSTAR_USE_SUNI */
+
+#ifdef CONFIG_ATM_NICSTAR_USE_IDT77105
+   if (card->max_pcr == IDT_25_PCR) {
+      idt77105_init(card->atmdev);
+      /* Note that for the IDT77105 PHY we don't need the awful
+       * module count hack that the SUNI needs because we can
+       * stop the '105 when the nicstar module is cleaned up.
+       */
+   }
+#endif /* CONFIG_ATM_NICSTAR_USE_IDT77105 */
+
    if (card->atmdev->phy && card->atmdev->phy->start)
       card->atmdev->phy->start(card->atmdev);
 
@@ -1798,8 +1815,8 @@
       flags = NS_TBD_AAL5;
       scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data));
       scqe.word_3 = cpu_to_le32((u32) skb->len);
-      scqe.word_4 = cpu_to_le32(((u32) vcc->vpi) << NS_TBD_VPI_SHIFT |
-                                ((u32) vcc->vci) << NS_TBD_VCI_SHIFT);
+      scqe.word_4 = ns_tbd_mkword_4(0, (u32) vcc->vpi, (u32) vcc->vci, 0,
+                           ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? 1 : 0);
       flags |= NS_TBD_EOPDU;
    }
    else /* (vcc->qos.aal == ATM_AAL0) */
@@ -1950,7 +1967,7 @@
 {
    u32 scdi;
    scq_info *scq;
-   ns_tsi *previous, *one_ahead, *two_ahead;
+   ns_tsi *previous = NULL, *one_ahead, *two_ahead;
    int serviced_entries;   /* flag indicating at least on entry was serviced */
    
    serviced_entries = 0;
@@ -2679,7 +2696,10 @@
       card->intcnt = 0;
       return retval;
    }
+#if 0
    /* Dump 25.6 Mbps PHY registers */
+   /* Now there's a 25.6 Mbps PHY driver this code isn't needed. I left it
+      here just in case it's needed for debugging. */
    if (card->max_pcr == IDT_25_PCR && !left--)
    {
       u32 phy_regs[4];
@@ -2696,6 +2716,7 @@
       return sprintf(page, "PHY regs: 0x%02X 0x%02X 0x%02X 0x%02X \n",
                      phy_regs[0], phy_regs[1], phy_regs[2], phy_regs[3]);
    }
+#endif /* 0 - Dump 25.6 Mbps PHY registers */
 #if 0
    /* Dump TST */
    if (left-- < NS_TST_NUM_ENTRIES)
@@ -2757,7 +2778,7 @@
 	       break;
 
             default:
-	       return -EINVAL;
+	       return -ENOIOCTLCMD;
 
 	 }
          if (!copy_to_user((pool_levels *) arg, &pl, sizeof(pl)))
@@ -2921,7 +2942,7 @@
          else {
             printk("nicstar%d: %s == NULL \n", card->index,
                    dev->phy ? "dev->phy->ioctl" : "dev->phy");
-            return -EINVAL;
+            return -ENOIOCTLCMD;
          }
    }
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/nicstar.h linux/drivers/atm/nicstar.h
--- v2.3.42/linux/drivers/atm/nicstar.h	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/nicstar.h	Tue Feb  8 18:23:13 2000
@@ -51,7 +51,7 @@
 				   128K x 32bit SRAM will limit the maximum
 				   VCI. */
 
-#define NS_PCI_LATENCY 64	/* Must be a multiple of 32 */
+/*#define NS_PCI_LATENCY 64*/	/* Must be a multiple of 32 */
 
 	/* Number of buffers initially allocated */
 #define NUM_SB 32	/* Must be even */
@@ -240,13 +240,13 @@
 #define NS_TBD_VCI_SHIFT 4
 
 #define ns_tbd_mkword_1(flags, m, n, buflen) \
-        (cpu_to_le32(flags | m << 23 | n << 16 | buflen))
+      (cpu_to_le32((flags) | (m) << 23 | (n) << 16 | (buflen)))
 #define ns_tbd_mkword_1_novbr(flags, buflen) \
-        (cpu_to_le32(flags | buflen | 0x00810000))
+      (cpu_to_le32((flags) | (buflen) | 0x00810000))
 #define ns_tbd_mkword_3(control, pdulen) \
-        (cpu_to_le32(control << 16 | pdulen))
+      (cpu_to_le32((control) << 16 | (pdulen)))
 #define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) \
-        (cpu_to_le32(gfc << 28 | vpi << 20 | vci << 4 | pt << 1 | clp)))
+      (cpu_to_le32((gfc) << 28 | (vpi) << 20 | (vci) << 4 | (pt) << 1 | (clp)))
 
 
 #define NS_TSR_INTENABLE 0x20000000
@@ -455,41 +455,59 @@
 /* NISCtAR operation registers ************************************************/
 
 
+/* See Section 3.4 of `IDT77211 NICStAR User Manual' from www.idt.com */
+
 enum ns_regs
 {
-   DR0 = 0x00,
-   DR1 = 0x04,
-   DR2 = 0x08,
-   DR3 = 0x0C,
-   CMD = 0x10,
-   CFG = 0x14,
-   STAT = 0x18,
-   RSQB = 0x1C,
-   RSQT = 0x20,
-   RSQH = 0x24,
-   CDC = 0x28,
-   VPEC = 0x2C,
-   ICC = 0x30,
-   RAWCT = 0x34,
-   TMR = 0x38,
-   TSTB = 0x3C,
-   TSQB = 0x40,
-   TSQT = 0x44,
-   TSQH = 0x48,
-   GP = 0x4C,
-   VPM = 0x50
+   DR0   = 0x00,      /* Data Register 0 R/W*/
+   DR1   = 0x04,      /* Data Register 1 W */
+   DR2   = 0x08,      /* Data Register 2 W */
+   DR3   = 0x0C,      /* Data Register 3 W */
+   CMD   = 0x10,      /* Command W */
+   CFG   = 0x14,      /* Configuration R/W */
+   STAT  = 0x18,      /* Status R/W */
+   RSQB  = 0x1C,      /* Receive Status Queue Base W */
+   RSQT  = 0x20,      /* Receive Status Queue Tail R */
+   RSQH  = 0x24,      /* Receive Status Queue Head W */
+   CDC   = 0x28,      /* Cell Drop Counter R/clear */
+   VPEC  = 0x2C,      /* VPI/VCI Lookup Error Count R/clear */
+   ICC   = 0x30,      /* Invalid Cell Count R/clear */
+   RAWCT = 0x34,      /* Raw Cell Tail R */
+   TMR   = 0x38,      /* Timer R */
+   TSTB  = 0x3C,      /* Transmit Schedule Table Base R/W */
+   TSQB  = 0x40,      /* Transmit Status Queue Base W */
+   TSQT  = 0x44,      /* Transmit Status Queue Tail R */
+   TSQH  = 0x48,      /* Transmit Status Queue Head W */
+   GP    = 0x4C,      /* General Purpose R/W */
+   VPM   = 0x50       /* VPI/VCI Mask W */
 };
 
 
 /* NICStAR commands issued to the CMD register ********************************/
 
+
+/* Top 4 bits are command opcode, lower 28 are parameters. */
+
 #define NS_CMD_NO_OPERATION         0x00000000
+        /* params always 0 */
+
 #define NS_CMD_OPENCLOSE_CONNECTION 0x20000000
+        /* b19{1=open,0=close} b18-2{SRAM addr} */
+
 #define NS_CMD_WRITE_SRAM           0x40000000
+        /* b18-2{SRAM addr} b1-0{burst size} */
+
 #define NS_CMD_READ_SRAM            0x50000000
+        /* b18-2{SRAM addr} */
+
 #define NS_CMD_WRITE_FREEBUFQ       0x60000000
+        /* b0{large buf indicator} */
+
 #define NS_CMD_READ_UTILITY         0x80000000
+        /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */
+
 #define NS_CMD_WRITE_UTILITY        0x90000000
+        /* b8{1=select UTL_CS1} b9{1=select UTL_CS0} b7-0{bus addr} */
 
 #define NS_CMD_OPEN_CONNECTION (NS_CMD_OPENCLOSE_CONNECTION | 0x00080000)
 #define NS_CMD_CLOSE_CONNECTION NS_CMD_OPENCLOSE_CONNECTION
@@ -497,28 +515,35 @@
 
 /* NICStAR configuration bits *************************************************/
 
-#define NS_CFG_SWRST          0x80000000
-#define NS_CFG_RXPATH         0x20000000
-#define NS_CFG_SMBUFSIZE_MASK 0x18000000
-#define NS_CFG_LGBUFSIZE_MASK 0x06000000
-#define NS_CFG_EFBIE          0x01000000
-#define NS_CFG_RSQSIZE_MASK   0x00C00000
-#define NS_CFG_ICACCEPT       0x00200000
-#define NS_CFG_IGNOREGFC      0x00100000
-#define NS_CFG_VPIBITS_MASK   0x000C0000
-#define NS_CFG_RCTSIZE_MASK   0x00030000
-#define NS_CFG_VCERRACCEPT    0x00008000
-#define NS_CFG_RXINT_MASK     0x00007000
-#define NS_CFG_RAWIE          0x00000800
-#define NS_CFG_RSQAFIE        0x00000400
-#define NS_CFG_RXRM           0x00000200
-#define NS_CFG_TMRROIE        0x00000080
-#define NS_CFG_TXEN           0x00000020
-#define NS_CFG_TXIE           0x00000010
-#define NS_CFG_TXURIE         0x00000008
-#define NS_CFG_UMODE          0x00000004
-#define NS_CFG_TSQFIE         0x00000002
-#define NS_CFG_PHYIE          0x00000001
+#define NS_CFG_SWRST          0x80000000    /* Software Reset */
+#define NS_CFG_RXPATH         0x20000000    /* Receive Path Enable */
+#define NS_CFG_SMBUFSIZE_MASK 0x18000000    /* Small Receive Buffer Size */
+#define NS_CFG_LGBUFSIZE_MASK 0x06000000    /* Large Receive Buffer Size */
+#define NS_CFG_EFBIE          0x01000000    /* Empty Free Buffer Queue
+                                               Interrupt Enable */
+#define NS_CFG_RSQSIZE_MASK   0x00C00000    /* Receive Status Queue Size */
+#define NS_CFG_ICACCEPT       0x00200000    /* Invalid Cell Accept */
+#define NS_CFG_IGNOREGFC      0x00100000    /* Ignore General Flow Control */
+#define NS_CFG_VPIBITS_MASK   0x000C0000    /* VPI/VCI Bits Size Select */
+#define NS_CFG_RCTSIZE_MASK   0x00030000    /* Receive Connection Table Size */
+#define NS_CFG_VCERRACCEPT    0x00008000    /* VPI/VCI Error Cell Accept */
+#define NS_CFG_RXINT_MASK     0x00007000    /* End of Receive PDU Interrupt
+                                               Handling */
+#define NS_CFG_RAWIE          0x00000800    /* Raw Cell Qu' Interrupt Enable */
+#define NS_CFG_RSQAFIE        0x00000400    /* Receive Queue Almost Full
+                                               Interrupt Enable */
+#define NS_CFG_RXRM           0x00000200    /* Receive RM Cells */
+#define NS_CFG_TMRROIE        0x00000080    /* Timer Roll Over Interrupt
+                                               Enable */
+#define NS_CFG_TXEN           0x00000020    /* Transmit Operation Enable */
+#define NS_CFG_TXIE           0x00000010    /* Transmit Status Interrupt
+                                               Enable */
+#define NS_CFG_TXURIE         0x00000008    /* Transmit Under-run Interrupt
+                                               Enable */
+#define NS_CFG_UMODE          0x00000004    /* Utopia Mode (cell/byte) Select */
+#define NS_CFG_TSQFIE         0x00000002    /* Transmit Status Queue Full
+                                               Interrupt Enable */
+#define NS_CFG_PHYIE          0x00000001    /* PHY Interrupt Enable */
 
 #define NS_CFG_SMBUFSIZE_48    0x00000000
 #define NS_CFG_SMBUFSIZE_96    0x08000000
@@ -552,22 +577,22 @@
 
 /* NICStAR STATus bits ********************************************************/
 
-#define NS_STAT_SFBQC_MASK 0xFF000000
-#define NS_STAT_LFBQC_MASK 0x00FF0000
-#define NS_STAT_TSIF       0x00008000
-#define NS_STAT_TXICP      0x00004000
-#define NS_STAT_TSQF       0x00001000
-#define NS_STAT_TMROF      0x00000800
-#define NS_STAT_PHYI       0x00000400
-#define NS_STAT_CMDBZ      0x00000200
-#define NS_STAT_SFBQF      0x00000100
-#define NS_STAT_LFBQF      0x00000080
-#define NS_STAT_RSQF       0x00000040
-#define NS_STAT_EOPDU      0x00000020
-#define NS_STAT_RAWCF      0x00000010
-#define NS_STAT_SFBQE      0x00000008
-#define NS_STAT_LFBQE      0x00000004
-#define NS_STAT_RSQAF      0x00000002
+#define NS_STAT_SFBQC_MASK 0xFF000000   /* hi 8 bits Small Buffer Queue Count */
+#define NS_STAT_LFBQC_MASK 0x00FF0000   /* hi 8 bits Large Buffer Queue Count */
+#define NS_STAT_TSIF       0x00008000   /* Transmit Status Queue Indicator */
+#define NS_STAT_TXICP      0x00004000   /* Transmit Incomplete PDU */
+#define NS_STAT_TSQF       0x00001000   /* Transmit Status Queue Full */
+#define NS_STAT_TMROF      0x00000800   /* Timer Overflow */
+#define NS_STAT_PHYI       0x00000400   /* PHY Device Interrupt */
+#define NS_STAT_CMDBZ      0x00000200   /* Command Busy */
+#define NS_STAT_SFBQF      0x00000100   /* Small Buffer Queue Full */
+#define NS_STAT_LFBQF      0x00000080   /* Large Buffer Queue Full */
+#define NS_STAT_RSQF       0x00000040   /* Receive Status Queue Full */
+#define NS_STAT_EOPDU      0x00000020   /* End of PDU */
+#define NS_STAT_RAWCF      0x00000010   /* Raw Cell Flag */
+#define NS_STAT_SFBQE      0x00000008   /* Small Buffer Queue Empty */
+#define NS_STAT_LFBQE      0x00000004   /* Large Buffer Queue Empty */
+#define NS_STAT_RSQAF      0x00000002   /* Receive Status Queue Almost Full */
 
 #define ns_stat_sfbqc_get(stat) (((stat) & NS_STAT_SFBQC_MASK) >> 23)
 #define ns_stat_lfbqc_get(stat) (((stat) & NS_STAT_LFBQC_MASK) >> 15)
@@ -723,7 +748,7 @@
 {
    int index;				/* Card ID to the device driver */
    int sram_size;			/* In k x 32bit words. 32 or 128 */
-   u32 membase;				/* Card's memory base address */
+   unsigned long membase;			/* Card's memory base address */
    unsigned long max_pcr;
    int rct_size;			/* Number of entries */
    int vpibits;
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/suni.c linux/drivers/atm/suni.c
--- v2.3.42/linux/drivers/atm/suni.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/atm/suni.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* drivers/atm/suni.c - PMC SUNI (PHY) driver */
  
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/module.h>
@@ -181,19 +181,24 @@
 		case SONET_GETFRSENSE:
 			return -EINVAL;
 		case SUNI_SETLOOP:
-			if (!capable(CAP_NET_ADMIN)) return -EPERM;
-			if ((int) arg < 0 || (int) arg > SUNI_LM_LOOP)
-				return -EINVAL;
-			PUT((GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE)) |
-			    ((int) arg == SUNI_LM_DIAG ? SUNI_MCT_DLE : 0) |
-			    ((int) arg == SUNI_LM_LOOP ? SUNI_MCT_LLE : 0),MCT);
-			PRIV(dev)->loop_mode = (int) arg;
-			return 0;
+			{
+				int int_arg = (int) (long) arg;
+
+				if (!capable(CAP_NET_ADMIN)) return -EPERM;
+				if (int_arg < 0 || int_arg > SUNI_LM_LOOP)
+					return -EINVAL;
+				PUT((GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE))
+				    | (int_arg == SUNI_LM_DIAG ? SUNI_MCT_DLE :
+				    0) | (int_arg == SUNI_LM_LOOP ?
+				    SUNI_MCT_LLE : 0),MCT);
+				PRIV(dev)->loop_mode = int_arg;
+				return 0;
+			}
 		case SUNI_GETLOOP:
 			return put_user(PRIV(dev)->loop_mode,(int *) arg) ?
 			    -EFAULT : 0;
 		default:
-			return -EINVAL;
+			return -ENOIOCTLCMD;
 	}
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/uPD98402.c linux/drivers/atm/uPD98402.c
--- v2.3.42/linux/drivers/atm/uPD98402.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/atm/uPD98402.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  
 
 #include <linux/module.h>
@@ -118,7 +118,7 @@
 		case SONET_GETFRSENSE:
 			return get_sense(dev,arg);
 		default:
-		    return -EINVAL;
+		    return -ENOIOCTLCMD;
 	}
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/atm/zatm.c linux/drivers/atm/zatm.c
--- v2.3.42/linux/drivers/atm/zatm.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/atm/zatm.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* drivers/atm/zatm.c - ZeitNet ZN122x device driver */
  
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/config.h>
@@ -729,9 +729,6 @@
 	zpokel(zatm_dev,(zpeekl(zatm_dev,pos) & ~(0xffff << shift)) |
 	    ((zatm_vcc->rx_chan | uPD98401_RXLT_ENBL) << shift),pos);
 	restore_flags(flags);
-/* Ugly hack to ensure that ttcp_atm will work with the current allocation
-   scheme. @@@ */
-if (vcc->rx_quota < 200000) vcc->rx_quota = 200000;
 	return 0;
 }
 
@@ -1701,7 +1698,7 @@
 			}
 #endif
 		default:
-        		if (!dev->phy->ioctl) return -EINVAL;
+        		if (!dev->phy->ioctl) return -ENOIOCTLCMD;
 		        return dev->phy->ioctl(dev,cmd,arg);
 	}
 }
@@ -1710,21 +1707,6 @@
 static int zatm_getsockopt(struct atm_vcc *vcc,int level,int optname,
     void *optval,int optlen)
 {
-#ifdef CONFIG_MMU_HACKS
-
-static const struct atm_buffconst bctx = { PAGE_SIZE,0,PAGE_SIZE,0,0,0 };
-static const struct atm_buffconst bcrx = { PAGE_SIZE,0,PAGE_SIZE,0,0,0 };
-
-#else
-
-static const struct atm_buffconst bctx = { 4,0,4,0,0,0 };
-static const struct atm_buffconst bcrx = { 4,0,4,0,0,0 };
-
-#endif
-	if (level == SOL_AAL && (optname == SO_BCTXOPT ||
-	    optname == SO_BCRXOPT))
-		return copy_to_user(optval,optname == SO_BCTXOPT ? &bctx :
-		    &bcrx,sizeof(struct atm_buffconst)) ? -EFAULT : 0;
 	return -EINVAL;
 }
 
@@ -1797,21 +1779,17 @@
 
 
 static const struct atmdev_ops ops = {
-	NULL,			/* no dev_close */
-	zatm_open,
-	zatm_close,
-	zatm_ioctl,
-	zatm_getsockopt,
-	zatm_setsockopt,
-	zatm_send,
-	NULL /*zatm_sg_send*/,
-	NULL,			/* no send_oam */
-	zatm_phy_put,
-	zatm_phy_get,
-	zatm_feedback,
-	zatm_change_qos,
-	NULL,			/* no free_rx_skb */
-	NULL			/* no proc_read */
+	open:		zatm_open,
+	close:		zatm_close,
+	ioctl:		zatm_ioctl,
+	getsockopt:	zatm_getsockopt,
+	setsockopt:	zatm_setsockopt,
+	send:		zatm_send,
+	/*zatm_sg_send*/
+	phy_put:	zatm_phy_put,
+	phy_get:	zatm_phy_get,
+	feedback:	zatm_feedback,
+	change_qos:	zatm_change_qos,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.3.42/linux/drivers/block/Config.in	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/Config.in	Wed Feb  9 18:48:03 2000
@@ -79,8 +79,8 @@
 	       fi
 	       bool '    HPT366 chipset support' CONFIG_BLK_DEV_HPT366
 	       if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT366" = "y" ]; then
-		  bool '      HPT366 Fast Interrupt support (EXPERIMENTAL) (WIP)' HPT366_FAST_IRQ_PREDICTION
-		  bool '      HPT366 mode three unsupported (EXPERIMENTAL) (WIP)' HPT366_MODE3
+		  bool '      HPT366 Fast Interrupt support (EXPERIMENTAL) (WIP)' CONFIG_HPT366_FAST_IRQ_PREDICTION
+		  bool '      HPT366 mode three unsupported (EXPERIMENTAL) (WIP)' CONFIG_HPT366_MODE3
 	       fi
 	       if [ "$CONFIG_X86" = "y" ]; then
 		  bool '    Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
@@ -106,6 +106,7 @@
   	       if [ "$CONFIG_X86" = "y" ]; then
 	          bool '    SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513
 	       fi
+	       bool '    Cyrix CS5530 MediaGX chipset support' CONFIG_BLK_DEV_CS5530
 	    fi
 	    if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
 	       bool '    Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
@@ -239,6 +240,7 @@
      "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \
      "$CONFIG_BLK_DEV_PIIX" = "y" -o \
      "$CONFIG_BLK_DEV_SIS5513" = "y" -o \
+     "$CONFIG_BLK_DEV_CS5530" = "y" -o \
      "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then
    define_bool CONFIG_BLK_DEV_IDE_MODES y
 else
diff -u --recursive --new-file v2.3.42/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.3.42/linux/drivers/block/Makefile	Fri Jan 21 18:19:16 2000
+++ linux/drivers/block/Makefile	Tue Feb  8 11:39:00 2000
@@ -198,6 +198,10 @@
 IDE_OBJS += pdc202xx.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_CS5530),y)
+IDE_OBJS += cs5530.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_PDC4030),y)
 IDE_OBJS += pdc4030.o
 endif
@@ -350,10 +354,30 @@
 endif
 
 ifeq ($(CONFIG_MD_RAID5),y)
+LX_OBJS += xor.o
+CFLAGS_xor.o := $(PROFILING) -fomit-frame-pointer
 L_OBJS += raid5.o
 else
   ifeq ($(CONFIG_MD_RAID5),m)
+  LX_OBJS += xor.o
+  CFLAGS_xor.o := $(PROFILING) -fomit-frame-pointer
   M_OBJS += raid5.o
+  endif
+endif
+
+ifeq ($(CONFIG_MD_TRANSLUCENT),y)
+L_OBJS += translucent.o
+else
+  ifeq ($(CONFIG_MD_TRANSLUCENT),m)
+  M_OBJS += translucent.o
+  endif
+endif
+
+ifeq ($(CONFIG_MD_HSM),y)
+L_OBJS += hsm.o
+else
+  ifeq ($(CONFIG_MD_HSM),m)
+  M_OBJS += hsm.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.42/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c
--- v2.3.42/linux/drivers/block/acsi_slm.c	Mon Aug  9 12:32:28 1999
+++ linux/drivers/block/acsi_slm.c	Wed Feb  9 11:42:35 2000
@@ -271,17 +271,11 @@
 static struct timer_list slm_timer = { NULL, NULL, 0, 0, slm_test_ready };
 
 static struct file_operations slm_fops = {
-	NULL,			/* lseek - default */
-	slm_read,		/* read - status reading */
-	slm_write,		/* write - printing data write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	slm_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	slm_open,		/* open */
-	NULL,			/* flush */
-	slm_release,		/* release */
-	NULL			/* fsync */
+	read:		slm_read,
+	write:		slm_write,
+	ioctl:		slm_ioctl,
+	open:		slm_open,
+	release:	slm_release,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/block/blkpg.c linux/drivers/block/blkpg.c
--- v2.3.42/linux/drivers/block/blkpg.c	Wed May 26 09:30:31 1999
+++ linux/drivers/block/blkpg.c	Tue Feb  8 11:37:29 2000
@@ -65,20 +65,6 @@
 	return g;
 }
 
-/* moved here from md.c - will be discarded later */
-char *partition_name (kdev_t dev) {
-	static char name[40];		/* kdevname returns 32 bytes */
-					/* disk_name requires 32 bytes */
-	struct gendisk *hd = get_gendisk (dev);
-
-	if (!hd) {
-		sprintf (name, "[dev %s]", kdevname(dev));
-		return (name);
-	}
-
-	return disk_name (hd, MINOR(dev), name);  /* routine in genhd.c */
-}
-
 /*
  * Add a partition.
  *
diff -u --recursive --new-file v2.3.42/linux/drivers/block/cs5530.c linux/drivers/block/cs5530.c
--- v2.3.42/linux/drivers/block/cs5530.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/cs5530.c	Mon Feb  7 10:00:41 2000
@@ -0,0 +1,420 @@
+/*
+ * linux/drivers/block/cs5530.c		Version 0.2	Jan 30, 2000
+ *
+ * Copyright (C) 2000			Mark Lord <mlord@pobox.com>
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * Development of this chipset driver was funded
+ * by the nice folks at National Semiconductor.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include "ide_modes.h"
+
+/*
+ * Return the mode name for a drive transfer mode value:
+ */
+static const char *strmode (byte mode)
+{
+	switch (mode) {
+		case XFER_UDMA_4:	return("UDMA4");
+		case XFER_UDMA_3:	return("UDMA3");
+		case XFER_UDMA_2:	return("UDMA2");
+		case XFER_UDMA_1:	return("UDMA1");
+		case XFER_UDMA_0:	return("UDMA0");
+		case XFER_MW_DMA_2:	return("MDMA2");
+		case XFER_MW_DMA_1:	return("MDMA1");
+		case XFER_MW_DMA_0:	return("MDMA0");
+		case XFER_SW_DMA_2:	return("SDMA2");
+		case XFER_SW_DMA_1:	return("SDMA1");
+		case XFER_SW_DMA_0:	return("SDMA0");
+		case XFER_PIO_4:	return("PIO4");
+		case XFER_PIO_3:	return("PIO3");
+		case XFER_PIO_2:	return("PIO2");
+		case XFER_PIO_1:	return("PIO1");
+		case XFER_PIO_0:	return("PIO0");
+		default:		return("???");
+	}
+}
+
+/*
+ * Set a new transfer mode at the drive
+ */
+int cs5530_set_xfer_mode (ide_drive_t *drive, byte mode)
+{
+	int		i, error = 1;
+	byte		stat;
+	ide_hwif_t	*hwif = HWIF(drive);
+
+	printk("%s: cs5530_set_xfer_mode(%s)\n", drive->name, strmode(mode));
+	/*
+	 * If this is a DMA mode setting, then turn off all DMA bits.
+	 * We will set one of them back on afterwards, if all goes well.
+	 *
+	 * Not sure why this is needed (it looks very silly),
+	 * but other IDE chipset drivers also do this fiddling.  ???? -ml
+ 	 */
+	switch (mode) {
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:
+		case XFER_MW_DMA_0:
+		case XFER_SW_DMA_2:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+	}
+
+	/*
+	 * Select the drive, and issue the SETFEATURES command
+	 */
+	disable_irq(hwif->irq);
+	udelay(1);
+	SELECT_DRIVE(HWIF(drive), drive);
+	udelay(1);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+	OUT_BYTE(mode, IDE_NSECTOR_REG);
+	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
+	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
+	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */
+
+	/*
+	 * Wait for drive to become non-BUSY
+	 */
+	if ((stat = GET_STAT()) & BUSY_STAT) {
+		unsigned long flags, timeout;
+		__save_flags(flags);	/* local CPU only */
+		ide__sti();		/* local CPU only -- for jiffies */
+		timeout = jiffies + WAIT_CMD;
+		while ((stat = GET_STAT()) & BUSY_STAT) {
+			if (0 < (signed long)(jiffies - timeout))
+				break;
+		}
+		__restore_flags(flags); /* local CPU only */
+	}
+
+	/*
+	 * Allow status to settle, then read it again.
+	 * A few rare drives vastly violate the 400ns spec here,
+	 * so we'll wait up to 10usec for a "good" status
+	 * rather than expensively fail things immediately.
+	 */
+	for (i = 0; i < 10; i++) {
+		udelay(1);
+		if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) {
+			error = 0;
+			break;
+		}
+	}
+	enable_irq(hwif->irq);
+
+	/*
+	 * Turn dma bit on if all is okay
+	 */
+	if (error) {
+		(void) ide_dump_status(drive, "cs5530_set_xfer_mode", stat);
+	} else {
+		switch (mode) {
+			case XFER_UDMA_4:   drive->id->dma_ultra |= 0x1010; break;
+			case XFER_UDMA_3:   drive->id->dma_ultra |= 0x0808; break;
+			case XFER_UDMA_2:   drive->id->dma_ultra |= 0x0404; break;
+			case XFER_UDMA_1:   drive->id->dma_ultra |= 0x0202; break;
+			case XFER_UDMA_0:   drive->id->dma_ultra |= 0x0101; break;
+			case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
+			case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
+			case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
+			case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
+			case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
+			case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
+		}
+	}
+	return error;
+}
+
+/*
+ * Here are the standard PIO mode 0-4 timings for each "format".
+ * Format-0 uses fast data reg timings, with slower command reg timings.
+ * Format-1 uses fast timings for all registers, but won't work with all drives.
+ */
+static unsigned int cs5530_pio_timings[2][5] =
+	{{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
+	 {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}};
+
+/*
+ * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
+ */
+#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
+#define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
+
+/*
+ * cs5530_tuneproc() handles selection/setting of PIO modes
+ * for both the chipset and drive.
+ *
+ * The ide_init_cs5530() routine guarantees that all drives
+ * will have valid default PIO timings set up before we get here.
+ */
+static void cs5530_tuneproc (ide_drive_t *drive, byte pio)	/* pio=255 means "autotune" */
+{
+	ide_hwif_t	*hwif = HWIF(drive);
+	unsigned int	format, basereg = CS5530_BASEREG(hwif);
+	static byte	modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
+
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	if (!cs5530_set_xfer_mode(drive, modes[pio])) {
+		format = (inl(basereg+4) >> 31) & 1;
+		outl(cs5530_pio_timings[format][pio], basereg+(drive->select.b.unit<<3));
+	}
+}
+
+/*
+ * cs5530_config_dma() handles selection/setting of DMA/UDMA modes
+ * for both the chipset and drive.
+ */
+static int cs5530_config_dma (ide_drive_t *drive)
+{
+	int			udma_ok = 1, mode = 0;
+	ide_hwif_t		*hwif = HWIF(drive);
+	int			unit = drive->select.b.unit;
+	ide_drive_t		*mate = &hwif->drives[unit^1];
+	struct hd_driveid	*id = drive->id;
+	unsigned int		basereg, reg, timings;
+
+
+	/*
+	 * Default to DMA-off in case we run into trouble here.
+	 */
+	(void)hwif->dmaproc(ide_dma_off_quietly, drive);	/* turn off DMA while we fiddle */
+	outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
+
+	/*
+	 * The CS5530 specifies that two drives sharing a cable cannot
+	 * mix UDMA/MDMA.  It has to be one or the other, for the pair,
+	 * though different timings can still be chosen for each drive.
+	 * We could set the appropriate timing bits on the fly,
+	 * but that might be a bit confusing.  So, for now we statically
+	 * handle this requirement by looking at our mate drive to see
+	 * what it is capable of, before choosing a mode for our own drive.
+	 */
+	if (mate->present) {
+		struct hd_driveid *mateid = mate->id;
+		if (mateid && (mateid->capability & 1) && !hwif->dmaproc(ide_dma_bad_drive, mate)) {
+			if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
+				udma_ok = 1;
+			else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
+				udma_ok = 0;
+			else
+				udma_ok = 1;
+		}
+	}
+
+	/*
+	 * Now see what the current drive is capable of,
+	 * selecting UDMA only if the mate said it was ok.
+	 */
+	if (id && (id->capability & 1) && hwif->autodma && !hwif->dmaproc(ide_dma_bad_drive, drive)) {
+		if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
+			if      (id->dma_ultra & 4)
+				mode = XFER_UDMA_2;
+			else if (id->dma_ultra & 2)
+				mode = XFER_UDMA_1;
+			else if (id->dma_ultra & 1)
+				mode = XFER_UDMA_0;
+		}
+		if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
+			if      (id->dma_mword & 4)
+				mode = XFER_MW_DMA_2;
+			else if (id->dma_mword & 2)
+				mode = XFER_MW_DMA_1;
+			else if (id->dma_mword & 1)
+				mode = XFER_MW_DMA_0;
+		}
+	}
+
+	/*
+	 * Tell the drive to switch to the new mode; abort on failure.
+	 */
+	if (!mode || cs5530_set_xfer_mode(drive, mode))
+		return 1;	/* failure */
+
+	/*
+	 * Now tune the chipset to match the drive:
+	 */
+	switch (mode) {
+		case XFER_UDMA_0:	timings = 0x00921250; break;
+		case XFER_UDMA_1:	timings = 0x00911140; break;
+		case XFER_UDMA_2:	timings = 0x00911030; break;
+		case XFER_MW_DMA_0:	timings = 0x00077771; break;
+		case XFER_MW_DMA_1:	timings = 0x00012121; break;
+		case XFER_MW_DMA_2:	timings = 0x00002020; break;
+		default:
+			printk("%s: cs5530_config_dma: huh? mode=%02x\n", drive->name, mode);
+			return 1;	/* failure */
+	}
+	basereg = CS5530_BASEREG(hwif);
+	reg = inl(basereg+4);			/* get drive0 config register */
+	timings |= reg & 0x80000000;		/* preserve PIO format bit */
+	if (unit == 0) {			/* are we configuring drive0? */
+		outl(timings, basereg+4);	/* write drive0 config register */
+	} else {
+		if (timings & 0x00100000)
+			reg |=  0x00100000;	/* enable UDMA timings for both drives */
+		else
+			reg &= ~0x00100000;	/* disable UDMA timings for both drives */
+		outl(reg,     basereg+4);	/* write drive0 config register */
+		outl(timings, basereg+12);	/* write drive1 config register */
+	}
+	outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2);	/* set DMA_capable bit */
+
+	if (!strcmp(drive->name, "hdc"))	/* FIXME */
+		return 0;
+	/*
+	 * Finally, turn DMA on in software, and exit.
+	 */
+	return hwif->dmaproc(ide_dma_on, drive);	/* success */
+}
+
+/*
+ * This is a CS5530-specific wrapper for the standard ide_dmaproc().
+ * We need it for our custom "ide_dma_check" function.
+ * All other requests are forwarded to the standard ide_dmaproc().
+ */
+int cs5530_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			return cs5530_config_dma(drive);
+		default:
+			return ide_dmaproc(func, drive);
+	}
+}
+
+/*
+ * Initialize the cs5530 bridge for reliable IDE DMA operation.
+ */
+unsigned int __init pci_init_cs5530 (struct pci_dev *dev, const char *name)
+{
+	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
+	unsigned short pcicmd = 0;
+	unsigned long flags;
+
+	pci_for_each_dev (dev) {
+		if (dev->vendor == PCI_VENDOR_ID_CYRIX) {
+			switch (dev->device) {
+				case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
+					master_0 = dev;
+					break;
+				case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
+					cs5530_0 = dev;
+					break;
+			}
+		}
+	}
+	if (!master_0) {
+		printk("%s: unable to locate PCI MASTER function\n", name);
+		return 0;
+	}
+	if (!cs5530_0) {
+		printk("%s: unable to locate CS5530 LEGACY function\n", name);
+		return 0;
+	}
+
+	save_flags(flags);
+	cli();	/* all CPUs (there should only be one CPU with this chipset) */
+
+	/*
+	 * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
+	 * -->  OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
+	 */
+	pci_read_config_word (cs5530_0, PCI_COMMAND, &pcicmd);
+	pci_write_config_word(cs5530_0, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+
+	/*
+	 * Set PCI CacheLineSize to 16-bytes:
+	 * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
+	 */
+	pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04);
+
+	/*
+	 * Disable trapping of UDMA register accesses (Win98 hack):
+	 * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
+	 */
+	pci_write_config_word(cs5530_0, 0xd0, 0x5006);
+
+	/*
+	 * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus:
+	 * The other settings are what is necessary to get the register
+	 * into a sane state for IDE DMA operation.
+	 */
+	pci_write_config_byte(master_0, 0x40, 0x1e);
+
+	/* 
+	 * Set max PCI burst size (16-bytes seems to work best):
+	 *	   16bytes: set bit-1 at 0x41 (reg value of 0x16)
+	 *	all others: clear bit-1 at 0x41, and do:
+	 *	  128bytes: OR 0x00 at 0x41
+	 *	  256bytes: OR 0x04 at 0x41
+	 *	  512bytes: OR 0x08 at 0x41
+	 *	 1024bytes: OR 0x0c at 0x41
+	 */
+	pci_write_config_byte(master_0, 0x41, 0x14);
+
+	/*
+	 * These settings are necessary to get the chip
+	 * into a sane state for IDE DMA operation.
+	 */
+	pci_write_config_byte(master_0, 0x42, 0x00);
+	pci_write_config_byte(master_0, 0x43, 0xc1);
+
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * This gets invoked by the IDE driver once for each channel,
+ * and performs channel-specific pre-initialization before drive probing.
+ */
+void __init ide_init_cs5530 (ide_hwif_t *hwif)
+{
+	if (hwif->mate)
+		hwif->serialized = hwif->mate->serialized = 1;
+	if (!hwif->dma_base) {
+		hwif->autodma = 0;
+	} else {
+		unsigned int basereg, d0_timings;
+
+		hwif->dmaproc  = &cs5530_dmaproc;
+		hwif->tuneproc = &cs5530_tuneproc;
+		basereg = CS5530_BASEREG(hwif);
+		d0_timings = inl(basereg+0);
+		if (CS5530_BAD_PIO(d0_timings)) {	/* PIO timings not initialized? */
+			outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0);
+			if (!hwif->drives[0].autotune)
+				hwif->drives[0].autotune = 1;	/* needs autotuning later */
+		}
+		if (CS5530_BAD_PIO(inl(basereg+8))) {	/* PIO timings not initialized? */
+			outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8);
+			if (!hwif->drives[1].autotune)
+				hwif->drives[1].autotune = 1;	/* needs autotuning later */
+		}
+	}
+}
diff -u --recursive --new-file v2.3.42/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.42/linux/drivers/block/floppy.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/block/floppy.c	Wed Feb  9 20:08:09 2000
@@ -289,9 +289,6 @@
 
 #define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
 
-#define INT_OFF save_flags(flags); cli()
-#define INT_ON  restore_flags(flags)
-
 /* read/write */
 #define COMMAND raw_cmd->cmd[0]
 #define DR_SELECT raw_cmd->cmd[1]
@@ -471,7 +468,8 @@
 #define FD_COMMAND_ERROR 2
 #define FD_COMMAND_OKAY 3
 
-static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0;
+static volatile int command_status = FD_COMMAND_NONE;
+static unsigned long fdc_busy = 0;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
@@ -846,24 +844,36 @@
 /* locks the driver */
 static int lock_fdc(int drive, int interruptible)
 {
-	unsigned long flags;
-
 	if (!usage_count){
 		printk(KERN_ERR "Trying to lock fdc while usage count=0\n");
 		return -1;
 	}
 	if(floppy_grab_irq_and_dma()==-1)
 		return -EBUSY;
-	INT_OFF;
-	while (fdc_busy && NO_SIGNAL)
-		interruptible_sleep_on(&fdc_wait);
-	if (fdc_busy){
-		INT_ON;
-		return -EINTR;
+
+	if (test_and_set_bit(0, &fdc_busy)) {
+		DECLARE_WAITQUEUE(wait, current);
+		add_wait_queue(&fdc_wait, &wait);
+
+		for (;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (!test_and_set_bit(0, &fdc_busy))
+				break;
+
+			schedule();
+
+			if (!NO_SIGNAL) {
+				remove_wait_queue(&fdc_wait, &wait);
+				return -EINTR;
+			}
+		}
+
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&fdc_wait, &wait);
 	}
-	fdc_busy = 1;
-	INT_ON;
 	command_status = FD_COMMAND_NONE;
+
 	reschedule_timeout(drive, "lock fdc", 0);
 	set_fdc(drive);
 	return 0;
@@ -886,7 +896,7 @@
 	command_status = FD_COMMAND_NONE;
 	del_timer(&fd_timeout);
 	cont = NULL;
-	fdc_busy = 0;
+	clear_bit(0, &fdc_busy);
 	floppy_release_irq_and_dma();
 	wake_up(&fdc_wait);
 }
@@ -1031,39 +1041,39 @@
 	return 0;
 }
 
+static spinlock_t floppy_hlt_lock = SPIN_LOCK_UNLOCKED;
 static int hlt_disabled=0;
 static void floppy_disable_hlt(void)
 {
 	unsigned long flags;
 
-	INT_OFF;
-	if (!hlt_disabled){
+	spin_lock_irqsave(&floppy_hlt_lock, flags);
+	if (!hlt_disabled) {
 		hlt_disabled=1;
 #ifdef HAVE_DISABLE_HLT
 		disable_hlt();
 #endif
 	}
-	INT_ON;
+	spin_unlock_irqrestore(&floppy_hlt_lock, flags);
 }
 
 static void floppy_enable_hlt(void)
 {
 	unsigned long flags;
 
-	INT_OFF;
+	spin_lock_irqsave(&floppy_hlt_lock, flags);
 	if (hlt_disabled){
 		hlt_disabled=0;
 #ifdef HAVE_DISABLE_HLT
 		enable_hlt();
 #endif
 	}
-	INT_ON;
+	spin_unlock_irqrestore(&floppy_hlt_lock, flags);
 }
 
 
 static void setup_DMA(void)
 {
-	unsigned long flags;
 	unsigned long f;
 
 #ifdef FLOPPY_SANITY_CHECK
@@ -1085,7 +1095,6 @@
 		return;
 	}
 #endif
-	INT_OFF;
 	f=claim_dma_lock();
 	fd_disable_dma();
 #ifdef fd_dma_setup
@@ -1094,7 +1103,6 @@
 			DMA_MODE_READ : DMA_MODE_WRITE,
 			FDCS->address) < 0) {
 		release_dma_lock(f);
-		INT_ON;
 		cont->done(0);
 		FDCS->reset=1;
 		return;
@@ -1111,7 +1119,6 @@
 	fd_enable_dma();
 	release_dma_lock(f);
 #endif
-	INT_ON;
 	floppy_disable_hlt();
 }
 
@@ -1759,14 +1766,7 @@
 		} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 && max_sensei);
 	}
 	if (handler) {
-		int cpu = smp_processor_id();
-		if(softirq_trylock(cpu)) {
-			/* got the lock, call the handler immediately */
-			handler();
-			softirq_endlock(cpu);
-		} else
-			/* we interrupted a bottom half. Defer handler */
-			schedule_bh( (void *)(void *) handler);
+		schedule_bh( (void *)(void *) handler);
 	} else
 		FDCS->reset = 1;
 	is_alive("normal interrupt end");
@@ -1854,7 +1854,7 @@
 #endif
 
 	printk("status=%x\n", fd_inb(FD_STATUS));
-	printk("fdc_busy=%d\n", fdc_busy);
+	printk("fdc_busy=%lu\n", fdc_busy);
 	if (DEVICE_INTR)
 		printk("DEVICE_INTR=%p\n", DEVICE_INTR);
 	if (floppy_tq.sync)
@@ -2025,25 +2025,36 @@
 static int wait_til_done(void (*handler)(void), int interruptible)
 {
 	int ret;
-	unsigned long flags;
 
 	schedule_bh((void *)(void *)handler);
-	INT_OFF;
-	while(command_status < 2 && NO_SIGNAL){
-		is_alive("wait_til_done");
-		if (interruptible)
-			interruptible_sleep_on(&command_done);
-		else
-			sleep_on(&command_done);
+
+	if (command_status < 2 && NO_SIGNAL) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		add_wait_queue(&command_done, &wait);
+		for (;;) {
+			set_current_state(interruptible?
+					  TASK_INTERRUPTIBLE:
+					  TASK_UNINTERRUPTIBLE);
+
+			if (command_status >= 2 || !NO_SIGNAL)
+				break;
+
+			is_alive("wait_til_done");
+
+			schedule();
+		}
+
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&command_done, &wait);
 	}
+
 	if (command_status < 2){
 		cancel_activity();
 		cont = &intr_cont;
 		reset_fdc();
-		INT_ON;
 		return -EINTR;
 	}
-	INT_ON;
 
 	if (FDCS->reset)
 		command_status = FD_COMMAND_ERROR;
@@ -4177,22 +4188,26 @@
 	return have_no_fdc;
 }
 
+static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED;
+
 static int floppy_grab_irq_and_dma(void)
 {
 	unsigned long flags;
 
-	INT_OFF;
+	spin_lock_irqsave(&floppy_usage_lock, flags);
 	if (usage_count++){
-		INT_ON;
+		spin_unlock_irqrestore(&floppy_usage_lock, flags);
 		return 0;
 	}
-	INT_ON;
+	spin_unlock_irqrestore(&floppy_usage_lock, flags);
 	MOD_INC_USE_COUNT;
 	if (fd_request_irq()) {
 		DPRINT("Unable to grab IRQ%d for the floppy driver\n",
 			FLOPPY_IRQ);
 		MOD_DEC_USE_COUNT;
+		spin_lock_irqsave(&floppy_usage_lock, flags);
 		usage_count--;
+		spin_unlock_irqrestore(&floppy_usage_lock, flags);
 		return -1;
 	}
 	if (fd_request_dma()) {
@@ -4200,7 +4215,9 @@
 			FLOPPY_DMA);
 		fd_free_irq();
 		MOD_DEC_USE_COUNT;
+		spin_lock_irqsave(&floppy_usage_lock, flags);
 		usage_count--;
+		spin_unlock_irqrestore(&floppy_usage_lock, flags);
 		return -1;
 	}
 
@@ -4216,7 +4233,9 @@
 					release_region(FDCS->address+7, 1);
 				}
 				MOD_DEC_USE_COUNT;
+				spin_lock_irqsave(&floppy_usage_lock, flags);
 				usage_count--;
+				spin_unlock_irqrestore(&floppy_usage_lock, flags);
 				return -1;
 			}
 			request_region(FDCS->address, 6, "floppy");
@@ -4258,12 +4277,12 @@
 	unsigned long tmpaddr;
 	unsigned long flags;
 
-	INT_OFF;
+	spin_lock_irqsave(&floppy_usage_lock, flags);
 	if (--usage_count){
-		INT_ON;
+		spin_unlock_irqrestore(&floppy_usage_lock, flags);
 		return;
 	}
-	INT_ON;
+	spin_unlock_irqrestore(&floppy_usage_lock, flags);
 	if(irqdma_allocated)
 	{
 		fd_disable_dma();
diff -u --recursive --new-file v2.3.42/linux/drivers/block/hpt366.c linux/drivers/block/hpt366.c
--- v2.3.42/linux/drivers/block/hpt366.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/hpt366.c	Thu Feb 10 12:37:22 2000
@@ -10,6 +10,7 @@
  * development and support.
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -262,20 +263,20 @@
 
 	pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, &reg51h);
 
-#ifdef HPT366_FAST_IRQ_PREDICTION
+#ifdef CONFIG_HPT366_FAST_IRQ_PREDICTION
 	/*
 	 * Some drives prefer/allow for the method of handling interrupts.
 	 */
 	if (!(reg51h & 0x80))
 		pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h|0x80);
-#else /* ! HPT366_FAST_IRQ_PREDICTION */
+#else /* ! CONFIG_HPT366_FAST_IRQ_PREDICTION */
 	/*
 	 * Disable the "fast interrupt" prediction.
 	 * Instead, always wait for the real interrupt from the drive!
 	 */
 	if (reg51h & 0x80)
 		pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80);
-#endif /* HPT366_FAST_IRQ_PREDICTION */
+#endif /* CONFIG_HPT366_FAST_IRQ_PREDICTION */
 
 	/*
 	 * Preserve existing PIO settings:
diff -u --recursive --new-file v2.3.42/linux/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c
--- v2.3.42/linux/drivers/block/ide-floppy.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/ide-floppy.c	Wed Feb  9 19:43:53 2000
@@ -1397,6 +1397,13 @@
 
 	*((unsigned short *) &gcw) = id->config;
 
+#ifdef CONFIG_PPC
+	/* kludge for Apple PowerBook internal zip */
+	if ((gcw.device_type == 5) && !strstr(id->model, "CD-ROM")
+	    && strstr(id->model, "ZIP"))
+		gcw.device_type = 0;			
+#endif
+
 #if IDEFLOPPY_DEBUG_INFO
 	printk (KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n");
 	switch (gcw.protocol) {
diff -u --recursive --new-file v2.3.42/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.3.42/linux/drivers/block/ide-pci.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/ide-pci.c	Wed Feb  9 18:48:03 2000
@@ -60,7 +60,7 @@
 #define DEVID_ALI15X3	((ide_pci_devid_t){PCI_VENDOR_ID_AL,      PCI_DEVICE_ID_AL_M5229})
 #define DEVID_CY82C693	((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ,  PCI_DEVICE_ID_CONTAQ_82C693})
 #define DEVID_HINT	((ide_pci_devid_t){0x3388,                0x8013})
-#define DEVID_CX5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
+#define DEVID_CS5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
 #define DEVID_AMD7409	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7409})
 
 #define	IDE_IGNORE	((void *)-1)
@@ -132,7 +132,15 @@
 #define INIT_CY82C693	NULL
 #endif
 
-#define INIT_CX5530	NULL
+#ifdef CONFIG_BLK_DEV_CS5530
+extern unsigned int pci_init_cs5530(struct pci_dev *, const char *);
+extern void ide_init_cs5530(ide_hwif_t *);
+#define INIT_CS5530	&ide_init_cs5530
+#define PCI_CS5530	&pci_init_cs5530
+#else
+#define INIT_CS5530	NULL
+#define PCI_CS5530	NULL
+#endif
 
 #ifdef CONFIG_BLK_DEV_HPT34X
 extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *);
@@ -309,7 +317,7 @@
 	{DEVID_ALI15X3,	"ALI15X3",	PCI_ALI15X3,	ATA66_ALI15X3,	INIT_ALI15X3,	DMA_ALI15X3,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_CY82C693,"CY82C693",	PCI_CY82C693,	NULL,		INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_HINT,	"HINT_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
-	{DEVID_CX5530,	"CX5530",	NULL,		NULL,		INIT_CX5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CS5530,	"CS5530",	PCI_CS5530,	NULL,		INIT_CS5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_AMD7409,	"AMD7409",	NULL,		ATA66_AMD7409,	INIT_AMD7409,	NULL,		{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
 	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
 
@@ -614,6 +622,7 @@
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
 #endif /* CONFIG_BLK_DEV_HPT34X */
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) ||
 		    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
 			unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
@@ -682,12 +691,12 @@
 	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
 	if (hpt363_shared_pin && !hpt363_shared_irq) {
 		printk("%s: IDE controller run unsupported mode three!!!\n", d2->name);
-#ifndef HPT366_MODE3
+#ifndef CONFIG_HPT366_MODE3
 		printk("%s: IDE controller report to <andre@suse.com>\n", d->name);
 		return;
-#else /* HPT366_MODE3 */
+#else /* CONFIG_HPT366_MODE3 */
 		printk("%s: OVERRIDE IDE controller not advisable this mode!!!\n", d2->name);
-#endif /* HPT366_MODE3 */
+#endif /* CONFIG_HPT366_MODE3 */
 	}
 	ide_setup_pci_device(dev2, d2);
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
--- v2.3.42/linux/drivers/block/ide-pmac.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/ide-pmac.c	Wed Feb  9 19:43:53 2000
@@ -14,6 +14,12 @@
  *
  *  Copyright (c) 1995-1998  Mark Lord
  *
+ * BenH: I began adding more complete timing setup code, mostly because DMA
+ *       won't work on new machines unless timings are setup correctly. This
+ *       code was mainly stolen from Cmd646 driver and should be completed to
+ *       include real timing calc. instead of hard coded values. The format of
+ *       the timing register can be found in Darwin's source code, except for
+ *       Keylargo ATA-4 controller.
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -36,29 +42,92 @@
 #endif
 #include "ide_modes.h"
 
-int pmac_ide_ports_known;
-ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
-int pmac_ide_irq[MAX_HWIFS];
-int pmac_ide_count;
-struct device_node *pmac_ide_node[MAX_HWIFS];
+#undef IDE_PMAC_DEBUG
 
+#define IDE_SYSCLK_NS	30
+
+struct pmac_ide_hwif {
+	ide_ioreg_t			regbase;
+	int				irq;
+	int				kind;
+	struct device_node*		node;
+	u32				timings[2];
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+	volatile struct dbdma_regs*	dma_regs;
+	struct dbdma_cmd*		dma_table;
+#endif
+	
+} pmac_ide[MAX_HWIFS];
+
+static int pmac_ide_count;
+
+enum {
+	controller_ohare,	/* OHare based */
+	controller_heathrow,	/* Heathrow/Paddington */
+	controller_kl_ata3,	/* KeyLargo ATA-3 */
+	controller_kl_ata4	/* KeyLargo ATA-4 */
+};
+
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+
+typedef struct {
+	int	accessTime;
+	int	cycleTime;
+} pmac_ide_timing;
+
+/* Multiword DMA timings */
+static pmac_ide_timing mdma_timings[] =
+{
+    { 215,    480 },	/* Mode 0 */
+    {  80,    150 },	/*      1 */
+    {  70,    120 }	/*      2 */
+};
+
+/* Ultra DMA timings (for use when I know how to calculate them */
+static pmac_ide_timing udma_timings[] =
+{
+    {   0,    114 },	/* Mode 0 */
+    {   0,     73 },	/*      1 */
+    {   0,     54 },	/*      2 */
+    {   0,     39 },	/*      3 */
+    {   0,     25 }	/*      4 */
+};
+
 #define MAX_DCMDS	256	/* allow up to 256 DBDMA commands per xfer */
 
-static void pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif);
+static void pmac_ide_setup_dma(struct device_node *np, int ix);
 static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
-static int pmac_ide_build_dmatable(ide_drive_t *drive, int wr);
+static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr);
+static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio);
+static void pmac_ide_selectproc(ide_drive_t *drive);
+
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 #ifdef CONFIG_PMAC_PBOOK
-static int idepmac_notify(struct pmu_sleep_notifier *self, int when);
+static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when);
 struct pmu_sleep_notifier idepmac_sleep_notifier = {
-	idepmac_notify, SLEEP_LEVEL_BLOCK,
+	idepmac_notify_sleep, SLEEP_LEVEL_BLOCK,
 };
 #endif /* CONFIG_PMAC_PBOOK */
 
+static int
+pmac_ide_find(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	ide_ioreg_t base;
+	int i;
+	
+	for (i=0; i<pmac_ide_count; i++) {
+		base = pmac_ide[i].regbase;
+		if (base && base == hwif->io_ports[0])
+			return i;
+	}
+	return -1;
+}
+
 /*
- * N.B. this can't be an __init, because the media-bay task can
+ * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
 void pmac_ide_init_hwif_ports(hw_regs_t *hw,
@@ -71,7 +140,7 @@
 		return;
 
 	for (ix = 0; ix < MAX_HWIFS; ++ix)
-		if (data_port == pmac_ide_regbase[ix])
+		if (data_port == pmac_ide[ix].regbase)
 			break;
 
 	if (ix >= MAX_HWIFS) {
@@ -98,27 +167,125 @@
 	hw->io_ports[8] = data_port + 0x160;
 
 	if (irq != NULL)
-		*irq = pmac_ide_irq[ix];
+		*irq = pmac_ide[ix].irq;
+
+	ide_hwifs[ix].tuneproc = pmac_ide_tuneproc;
+	ide_hwifs[ix].selectproc = pmac_ide_selectproc;
+	if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) {
+		ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
+#ifdef CONFIG_PMAC_IDEDMA_AUTO
+		ide_hwifs[ix].autodma = 1;
+#endif
+	}
 }
 
-void pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
+#if 0
+/* This one could be later extended to handle CMD IDE and be used by some kind
+ * of /proc interface. I want to be able to get the devicetree path of a block
+ * device for yaboot configuration
+ */
+struct device_node*
+pmac_ide_get_devnode(ide_drive_t *drive)
 {
-	ide_pio_data_t d;
+	int i = pmac_ide_find(drive);
+	if (i < 0)
+		return NULL;
+	return pmac_ide[i].node;
+}
+#endif
 
-	if (_machine != _MACH_Pmac)
+/* Setup timings for the selected drive (master/slave). I still need to verify if this
+ * is enough, I beleive selectproc will be called whenever an IDE command is started,
+ * but... */
+static void
+pmac_ide_selectproc(ide_drive_t *drive)
+{
+	int i = pmac_ide_find(drive);
+	if (i < 0)
 		return;
+			
+	if (drive->select.all & 0x10)
+		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]);
+	else
+		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]);
+}
+
+/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
+#define SYSCLK_TICKS(t)		(((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
+
+static void
+pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
+{
+	ide_pio_data_t d;
+	int i;
+	u32 *timings;
+	int accessTicks, recTicks;
+	
+	i = pmac_ide_find(drive);
+	if (i < 0)
+		return;
+		
+	/* The "ata-4" IDE controller of UMA machines is a bit different.
+	 * We don't do anything for PIO modes until we know how to do the
+	 * calculation.
+	 */
+	if (pmac_ide[i].kind == controller_kl_ata4)
+		return;
+		
 	pio = ide_get_best_pio_mode(drive, pio, 4, &d);
-	switch (pio) {
-	case 4:
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x211025);
-		break;
-	default:
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), 0x2f8526);
-		break;
+	accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time);
+	if (accessTicks < 4)
+		accessTicks = 4;
+	recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4;
+	if (recTicks < 1)
+		recTicks = 1;
+	if (drive->select.all & 0x10)
+		timings = &pmac_ide[i].timings[1];
+	else
+		timings = &pmac_ide[i].timings[0];
+	
+	*timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);	
+#ifdef IDE_PMAC_DEBUG
+	printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
+		pio,  *timings);
+#endif	
+		
+	if (drive->select.all == IN_BYTE(IDE_SELECT_REG))
+		pmac_ide_selectproc(drive);
+}
+
+ide_ioreg_t
+pmac_ide_get_base(int index)
+{
+	return pmac_ide[index].regbase;
+}
+
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+
+kdev_t __init
+pmac_find_ide_boot(char *bootdevice, int n)
+{
+	int i;
+	
+	/*
+	 * Look through the list of IDE interfaces for this one.
+	 */
+	for (i = 0; i < pmac_ide_count; ++i) {
+		char *name;
+		if (!pmac_ide[i].node || !pmac_ide[i].node->full_name)
+			continue;
+		name = pmac_ide[i].node->full_name;
+		if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+			/* XXX should cope with the 2nd drive as well... */
+			return MKDEV(ide_majors[i], 0);
+		}
 	}
+
+	return 0;
 }
 
-void __init pmac_ide_probe(void)
+void __init
+pmac_ide_probe(void)
 {
 	struct device_node *np;
 	int i;
@@ -196,27 +363,70 @@
 		} else {
 			irq = np->intrs[0].line;
 		}
-		pmac_ide_regbase[i] = base;
-		pmac_ide_irq[i] = irq;
-		pmac_ide_node[i] = np;
+		pmac_ide[i].regbase = base;
+		pmac_ide[i].irq = irq;
+		pmac_ide[i].node = np;
+		if (device_is_compatible(np, "keylargo-ata")) {
+			if (strcmp(np->name, "ata-4") == 0)
+				pmac_ide[i].kind = controller_kl_ata4;
+			else
+				pmac_ide[i].kind = controller_kl_ata3;
+		} else if (device_is_compatible(np, "heathrow-ata"))
+			pmac_ide[i].kind = controller_heathrow;
+		else
+			pmac_ide[i].kind = controller_ohare;
 
 		if (np->parent && np->parent->name
 		    && strcasecmp(np->parent->name, "media-bay") == 0) {
 			media_bay_set_ide_infos(np->parent,base,irq,i);
-		} else
-			feature_set(np, FEATURE_IDE_enable);
+		} else if (pmac_ide[i].kind == controller_ohare) {
+			/* The code below is having trouble on some ohare machines
+			 * (timing related ?). Until I can put my hand on one of these
+			 * units, I keep the old way
+			 */
+			 feature_set(np, FEATURE_IDE0_enable);
+		} else {
+			/* This is necessary to enable IDE when net-booting */
+			int *bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
+			int bid = bidp ? *bidp : 0;
+			printk("pmac_ide: enabling IDE bus ID %d\n", bid);
+			switch(bid) {
+			    case 0:
+				feature_set(np, FEATURE_IDE0_reset);
+				feature_set(np, FEATURE_IOBUS_enable);
+				mdelay(10);
+ 				feature_set(np, FEATURE_IDE0_enable);
+				mdelay(10);
+				feature_clear(np, FEATURE_IDE0_reset);
+				break;
+			    case 1:
+				feature_set(np, FEATURE_Mediabay_IDE_reset);
+				mdelay(10);
+ 				feature_set(np, FEATURE_Mediabay_IDE_enable);
+				mdelay(10);
+				feature_clear(np, FEATURE_Mediabay_IDE_reset);
+				break;
+			    case 2:
+			    	/* This one exists only for KL, I don't know about any
+			    	   enable bit */
+				feature_set(np, FEATURE_IDE2_reset);
+				mdelay(10);
+				feature_clear(np, FEATURE_IDE2_reset);
+				break;
+			}
+			mdelay(1000);
+		}
 
 		hwif = &ide_hwifs[i];
 		pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq);
 		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 		hwif->chipset = ide_generic;
 		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
-		hwif->tuneproc = pmac_ide_tuneproc;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 		if (np->n_addrs >= 2) {
 			/* has a DBDMA controller channel */
-			pmac_ide_setup_dma(np, hwif);
+			pmac_ide_setup_dma(np, i);
 		}
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
@@ -232,27 +442,28 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
 static void __init 
-pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif)
+pmac_ide_setup_dma(struct device_node *np, int ix)
 {
-	hwif->dma_base = (unsigned long) ioremap(np->addrs[1].address, 0x200);
+	pmac_ide[ix].dma_regs =
+		(volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200);
 
 	/*
 	 * Allocate space for the DBDMA commands.
 	 * The +2 is +1 for the stop command and +1 to allow for
 	 * aligning the start address to a multiple of 16 bytes.
 	 */
-	hwif->dmatable_cpu = (unsigned long *)
+	pmac_ide[ix].dma_table = (struct dbdma_cmd*)
 	       kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL);
-	if (hwif->dmatable_cpu == 0) {
+	if (pmac_ide[ix].dma_table == 0) {
 		printk(KERN_ERR "%s: unable to allocate DMA command list\n",
-		       hwif->name);
+		       ide_hwifs[ix].name);
 		return;
 	}
 
-	hwif->dmaproc = &pmac_ide_dmaproc;
-#ifdef CONFIG_IDEDMA_PMAC_AUTO
-	hwif->autodma = 1;
-#endif /* CONFIG_IDEDMA_PMAC_AUTO */
+	ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
+#ifdef CONFIG_PMAC_IDEDMA_AUTO
+	ide_hwifs[ix].autodma = 1;
+#endif
 }
 
 /*
@@ -260,19 +471,19 @@
  * for a transfer and sets the DBDMA channel to point to it.
  */
 static int
-pmac_ide_build_dmatable(ide_drive_t *drive, int wr)
+pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
 {
-	ide_hwif_t *hwif = HWIF(drive);
 	struct dbdma_cmd *table, *tstart;
 	int count = 0;
 	struct request *rq = HWGROUP(drive)->rq;
 	struct buffer_head *bh = rq->bh;
 	unsigned int size, addr;
-	volatile struct dbdma_regs *dma
-		= (volatile struct dbdma_regs *) hwif->dma_base;
+	volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs;
 
-	table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(hwif->dmatable_cpu);
+	table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table);
 	out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
+	while (in_le32(&dma->status) & RUN)
+		udelay(1);
 
 	do {
 		/*
@@ -335,30 +546,277 @@
 	return 1;
 }
 
+
+/* This is fun.  -DaveM */
+#define IDE_SETXFER		0x03
+#define IDE_SETFEATURE		0xef
+#define IDE_DMA2_ENABLE		0x22
+#define IDE_DMA1_ENABLE		0x21
+#define IDE_DMA0_ENABLE		0x20
+#define IDE_UDMA4_ENABLE	0x44
+#define IDE_UDMA3_ENABLE	0x43
+#define IDE_UDMA2_ENABLE	0x42
+#define IDE_UDMA1_ENABLE	0x41
+#define IDE_UDMA0_ENABLE	0x40
+
+static __inline__ unsigned char
+dma_bits_to_command(unsigned char bits)
+{
+	if(bits & 0x04)
+		return IDE_DMA2_ENABLE;
+	if(bits & 0x02)
+		return IDE_DMA1_ENABLE;
+	return IDE_DMA0_ENABLE;
+}
+
+static __inline__ unsigned char
+udma_bits_to_command(unsigned char bits)
+{
+	if(bits & 0x10)
+		return IDE_UDMA4_ENABLE;
+	if(bits & 0x08)
+		return IDE_UDMA3_ENABLE;
+	if(bits & 0x04)
+		return IDE_UDMA2_ENABLE;
+	if(bits & 0x02)
+		return IDE_UDMA1_ENABLE;
+	if(bits & 0x01)
+		return IDE_UDMA0_ENABLE;
+	return 0;
+}
+
+static __inline__ int
+wait_for_ready(ide_drive_t *drive)
+{
+	/* Timeout bumped for some powerbooks */
+	int timeout = 2000;
+	byte stat;
+
+	while(--timeout) {
+		stat = GET_STAT();
+		if(!(stat & BUSY_STAT)) {
+			if (drive->ready_stat == 0)
+				break;
+			else if((stat & drive->ready_stat) || (stat & ERR_STAT))
+				break;
+		}
+		mdelay(1);
+	}
+	if((stat & ERR_STAT) || timeout <= 0) {
+		if (stat & ERR_STAT) {
+			printk("ide_pmace: wait_for_ready, error status: %x\n", stat);
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static int
+pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
+{
+	unsigned long flags;
+	byte old_select;
+	int result = 1;
+
+	save_flags(flags);
+	cli();
+	old_select = IN_BYTE(IDE_SELECT_REG);
+	OUT_BYTE(drive->select.all, IDE_SELECT_REG);
+	udelay(10);
+	OUT_BYTE(IDE_SETXFER, IDE_FEATURE_REG);
+	OUT_BYTE(command, IDE_NSECTOR_REG);
+	if(wait_for_ready(drive)) {
+		printk("pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
+		goto out;
+	}
+	OUT_BYTE(IDE_SETFEATURE, IDE_COMMAND_REG);
+	result = wait_for_ready(drive);
+	if (result)
+		printk("pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
+out:
+	OUT_BYTE(old_select, IDE_SELECT_REG);
+	restore_flags(flags);
+	
+	return result;
+}
+
+static int
+pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
+{
+	byte bits = drive->id->dma_mword & 0x07;
+	byte feature = dma_bits_to_command(bits);
+	u32 *timings;
+	int cycleTime, accessTime;
+	int accessTicks, recTicks;
+	struct hd_driveid *id = drive->id;
+	
+	/* For now, we don't know these values */
+	if (pmac_ide[idx].kind == controller_kl_ata4 && feature != IDE_DMA2_ENABLE)
+		return 0;
+	if (pmac_ide[idx].kind != controller_kl_ata4 && feature == IDE_DMA0_ENABLE)
+		return 0;
+				
+	/* Set feature on drive */
+    	printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
+	if (pmac_ide_do_setfeature(drive, feature)) {
+	    	printk("%s: Failed !\n", drive->name);
+	    	return 0;
+	}
+	
+	/* which drive is it ? */
+	if (drive->select.all & 0x10)
+		timings = &pmac_ide[idx].timings[1];
+	else
+		timings = &pmac_ide[idx].timings[0];
+
+	/* Calculate accesstime and cycle time */
+	cycleTime = mdma_timings[feature & 0xf].cycleTime;
+	accessTime = mdma_timings[feature & 0xf].accessTime;
+	if ((id->field_valid & 2) && (id->eide_dma_time))
+		cycleTime = id->eide_dma_time;
+	if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150))
+		cycleTime = 150;
+
+	/* For ata-4 controller, we don't know the calculation */
+	if (pmac_ide[idx].kind == controller_kl_ata4) {
+		*timings = 0x00019465;	/* MDMA2 */
+	} else {
+		int halfTick = 0;
+		int origAccessTime = accessTime;
+		int origCycleTime = cycleTime;
+		
+		accessTicks = SYSCLK_TICKS(accessTime);
+		if (accessTicks < 1)
+			accessTicks = 1;
+		accessTime = accessTicks * IDE_SYSCLK_NS;
+		recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
+		if (recTicks < 1)
+			recTicks = 1;
+		cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
+
+		if ((accessTicks > 1) &&
+			((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
+			((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
+            			halfTick    = 1;
+				accessTicks--;
+		}
+		*timings = ((*timings) & 0x7FF) |
+			(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
+	}
+#ifdef IDE_PMAC_DEBUG
+	printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
+		feature & 0xf, *timings);
+#endif	
+	return 1;
+}
+
+static int
+pmac_ide_udma_enable(ide_drive_t *drive, int idx)
+{
+	byte bits = drive->id->dma_ultra & 0x1f;
+	byte feature = udma_bits_to_command(bits);
+	u32 timings;
+	
+	/* We support only those values */
+	if (feature != IDE_UDMA4_ENABLE && feature != IDE_UDMA2_ENABLE)
+		return 0;
+		
+	/* Set feature on drive */
+    	printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
+	if (pmac_ide_do_setfeature(drive, feature)) {
+		printk("%s: Failed !\n", drive->name);
+		return 0;
+	}
+
+	/* Put this channel into UDMA mode.
+	 * This value is set by MacOS on the iBook for U/DMA2
+	 */
+	switch(feature) {	
+		case IDE_UDMA4_ENABLE:
+			timings = 0x0cd00065;
+			break;
+		case IDE_UDMA2_ENABLE:
+			timings = 0x11100065;
+			break;
+	}
+	
+	if (drive->select.all & 0x10)
+		pmac_ide[idx].timings[1] = timings;
+	else
+		pmac_ide[idx].timings[0] = timings;
+	
+	return 1;
+}
+
+static int
+pmac_ide_dma_onoff(ide_drive_t *drive, int enable)
+{
+	int ata4, udma, idx;
+	struct hd_driveid *id = drive->id;
+
+	drive->using_dma = 0;
+	
+	idx = pmac_ide_find(drive);
+	if (idx < 0)
+		return 0;
+		
+	if (drive->media == ide_floppy)
+		enable = 0;
+	if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE))
+		enable = 0;
+	if (check_drive_lists(drive, BAD_DMA_DRIVE))
+		enable = 0;
+
+	udma = 0;
+	ata4 = (pmac_ide[idx].kind == controller_kl_ata4);
+			
+	if(enable) {
+		if (ata4 && (drive->media == ide_disk) &&
+		    (id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) {
+			/* UltraDMA modes. */
+			drive->using_dma = pmac_ide_udma_enable(drive, idx);
+		}
+		if (!drive->using_dma && (id->dma_mword & 0x0007)) {
+			/* Normal MultiWord DMA modes. */
+			drive->using_dma = pmac_ide_mdma_enable(drive, idx);
+		}
+		/* Without this, strange things will happen on Keylargo-based
+		 * machines
+		 */
+		OUT_BYTE(0, IDE_CONTROL_REG);
+		if (drive->select.all == IN_BYTE(IDE_SELECT_REG))
+			pmac_ide_selectproc(drive);
+	}
+	return 0;
+}
+
 int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	volatile struct dbdma_regs *dma
-		= (volatile struct dbdma_regs *) hwif->dma_base;
-	int dstat;
+	int ix, dstat;
+	volatile struct dbdma_regs *dma;
+
+	/* Can we stuff a pointer to our intf structure in config_data
+	 * or select_data in hwif ?
+	 */
+	ix = pmac_ide_find(drive);
+	if (ix < 0)
+		return 0;		
+	dma = pmac_ide[ix].dma_regs;
 
 	switch (func) {
 	case ide_dma_on:
-		/* ide-floppy DMA doesn't work yet... */
-		drive->using_dma = drive->media != ide_floppy;
-		break;
 	case ide_dma_off:
-		printk(KERN_INFO "%s: DMA disabled\n", drive->name);
 	case ide_dma_off_quietly:
-		drive->using_dma = 0;
+		pmac_ide_dma_onoff(drive, (func == ide_dma_on));
 		break;
 	case ide_dma_check:
-		/* ide-floppy DMA doesn't work yet... */
-		drive->using_dma = hwif->autodma && drive->media != ide_floppy;
+		if (hwif->autodma)
+			pmac_ide_dma_onoff(drive, 1);
 		break;
 	case ide_dma_read:
 	case ide_dma_write:
-		if (!pmac_ide_build_dmatable(drive, func==ide_dma_write))
+		if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write))
 			return 1;
 		drive->waiting_for_dma = 1;
 		if (drive->media != ide_disk)
@@ -387,11 +845,9 @@
 #ifdef CONFIG_PMAC_PBOOK
 static void idepmac_sleep_disk(int i, unsigned long base)
 {
+	struct device_node* np = pmac_ide[i].node;
 	int j;
 
-	/* Reset to PIO 0 */
-	out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
-
 	/* FIXME: We only handle the master IDE */
 	if (ide_hwifs[i].drives[0].media == ide_disk) {
 		/* Spin down the drive */
@@ -410,23 +866,30 @@
 				break;
 		}
 	}
+	feature_set(np, FEATURE_IDE0_reset);
+	feature_clear(np, FEATURE_IOBUS_enable);
+	feature_clear(np, FEATURE_IDE0_enable);
+	pmac_ide[i].timings[0] = 0;
+	pmac_ide[i].timings[1] = 0;
 }
 
 static void idepmac_wake_disk(int i, unsigned long base)
 {
+	struct device_node* np = pmac_ide[i].node;
 	int j;
 
 	/* Revive IDE disk and controller */
-	feature_set(pmac_ide_node[i], FEATURE_IDE_enable);
-	mdelay(1);
-	feature_set(pmac_ide_node[i], FEATURE_IDE_DiskPower);
-	mdelay(100);
-	feature_set(pmac_ide_node[i], FEATURE_IDE_Reset);
-	mdelay(1);
-	/* Make sure we are still PIO0 */
-	out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
+	feature_set(np, FEATURE_IOBUS_enable);
+	mdelay(10);
+	feature_set(np, FEATURE_IDE0_enable);
+	mdelay(10);
+	feature_clear(np, FEATURE_IDE0_reset);
 	mdelay(100);
 
+	/* Reset timings */
+	pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
+	mdelay(10);
+
 	/* Wait up to 10 seconds (enough for recent drives) */
 	for (j = 0; j < 100; j++) {
 		int status;
@@ -443,14 +906,22 @@
 {
 	int timeout;
 
-	timeout = 5000;
+	/* Reset timings */
+	pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
+	mdelay(10);
+
+	timeout = 10000;
 	while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
 		mdelay(1);
 		--timeout;
 	}
 }
 
-static int idepmac_notify(struct pmu_sleep_notifier *self, int when)
+/* Note: We support only master drives for now. This will have to be
+ * improved if we want to handle sleep on the iMacDV where the CD-ROM
+ * is a slave
+ */
+static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	int i, ret;
 	unsigned long base;
@@ -462,10 +933,10 @@
 		break;
 	case PBOOK_SLEEP_NOW:
 		for (i = 0; i < pmac_ide_count; ++i) {
-			if ((base = pmac_ide_regbase[i]) == 0)
+			if ((base = pmac_ide[i].regbase) == 0)
 				continue;
 			/* Disable irq during sleep */
-			disable_irq(pmac_ide_irq[i]);
+			disable_irq(pmac_ide[i].irq);
 			ret = check_media_bay_by_base(base, MB_CD);
 			if (ret == -ENODEV)
 				/* not media bay - put the disk to sleep */
@@ -474,15 +945,22 @@
 		break;
 	case PBOOK_WAKE:
 		for (i = 0; i < pmac_ide_count; ++i) {
-			if ((base = pmac_ide_regbase[i]) == 0)
+			ide_hwif_t *hwif;
+			if ((base = pmac_ide[i].regbase) == 0)
 				continue;
+			hwif = &ide_hwifs[i];
 		        /* We don't handle media bay devices this way */
 			ret = check_media_bay_by_base(base, MB_CD);
 			if (ret == -ENODEV)
 				idepmac_wake_disk(i, base);
 			else if (ret == 0)
 				idepmac_wake_bay(i, base);
-			enable_irq(pmac_ide_irq[i]);
+			enable_irq(pmac_ide[i].irq);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+			if (hwif->drives[0].present && hwif->drives[0].using_dma)
+				pmac_ide_dma_onoff(&hwif->drives[0], 1);
+#endif				
 		}
 		break;
 	}
diff -u --recursive --new-file v2.3.42/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- v2.3.42/linux/drivers/block/ide-probe.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/ide-probe.c	Wed Feb  9 19:43:53 2000
@@ -117,8 +117,16 @@
 				}
 				type = ide_cdrom;	/* Early cdrom models used zero */
 			case ide_cdrom:
-				printk ("CDROM");
 				drive->removable = 1;
+#ifdef CONFIG_PPC
+				/* kludge for Apple PowerBook internal zip */
+				if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
+					printk ("FLOPPY");
+					type = ide_floppy;
+					break;
+				}
+#endif
+				printk ("CDROM");
 				break;
 			case ide_tape:
 				printk ("TAPE");
diff -u --recursive --new-file v2.3.42/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v2.3.42/linux/drivers/block/ide-tape.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/ide-tape.c	Wed Feb  9 19:47:20 2000
@@ -4372,12 +4372,12 @@
 		return -ENXIO;
 	}
 	if (tape->onstream && (count != tape->tape_block_size)) {
-		printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%d used)\n", tape->name, tape->tape_block_size, count);
+		printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count);
 		return -EINVAL;
 	}
 #if IDETAPE_DEBUG_LOG
 	if (tape->debug_level >= 3)
-		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %d\n", count);
+		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (tape->chrdev_direction != idetape_direction_read) {
@@ -4552,12 +4552,12 @@
 		return -ENXIO;
 	}
 	if (tape->onstream && (count != tape->tape_block_size)) {
-		printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%d used)\n", tape->name, tape->tape_block_size, count);
+		printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count);
 		return -EINVAL;
 	}
 #if IDETAPE_DEBUG_LOG
 	if (tape->debug_level >= 3)
-		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_write, count %d\n", count);
+		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_write, count %Zd\n", count);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (tape->chrdev_direction != idetape_direction_write) {	/* Initialize write operation */
@@ -5839,18 +5839,11 @@
  *	Our character device supporting functions, passed to register_chrdev.
  */
 static struct file_operations idetape_fops = {
-	NULL,			/* lseek - default */
-	idetape_chrdev_read,	/* read  */
-	idetape_chrdev_write,	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll */
-	idetape_chrdev_ioctl,	/* ioctl */
-	NULL,			/* mmap */
-	idetape_chrdev_open,	/* open */
-	NULL,			/* flush */
-	idetape_chrdev_release,	/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
+	read:		idetape_chrdev_read,
+	write:		idetape_chrdev_write,
+	ioctl:		idetape_chrdev_ioctl,
+	open:		idetape_chrdev_open,
+	release:	idetape_chrdev_release,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.42/linux/drivers/block/ide.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/ide.c	Mon Feb  7 19:45:28 2000
@@ -861,7 +861,7 @@
 	if (drive->media != ide_disk)
 		return;
 	while (i > 0) {
-		unsigned long buffer[16];
+		u32 buffer[16];
 		unsigned int wcount = (i > 16) ? 16 : i;
 		i -= wcount;
 		ide_input_data (drive, buffer, wcount);
diff -u --recursive --new-file v2.3.42/linux/drivers/block/linear.c linux/drivers/block/linear.c
--- v2.3.42/linux/drivers/block/linear.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/block/linear.c	Tue Feb  8 11:39:00 2000
@@ -1,4 +1,3 @@
-
 /*
    linear.c : Multiple Devices driver for Linux
               Copyright (C) 1994-96 Marc ZYNGIER
@@ -19,186 +18,204 @@
 
 #include <linux/module.h>
 
-#include <linux/md.h>
+#include <linux/raid/md.h>
 #include <linux/malloc.h>
-#include <linux/init.h>
 
-#include "linear.h"
+#include <linux/raid/linear.h>
 
 #define MAJOR_NR MD_MAJOR
 #define MD_DRIVER
 #define MD_PERSONALITY
 
-static int linear_run (int minor, struct md_dev *mddev)
-{
-  int cur=0, i, size, dev0_size, nb_zone;
-  struct linear_data *data;
-
-  MOD_INC_USE_COUNT;
-
-  mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL);
-  data=(struct linear_data *) mddev->private;
-
-  /*
-     Find out the smallest device. This was previously done
-     at registry time, but since it violates modularity,
-     I moved it here... Any comment ? ;-)
-   */
-
-  data->smallest=mddev->devices;
-  for (i=1; i<mddev->nb_dev; i++)
-    if (data->smallest->size > mddev->devices[i].size)
-      data->smallest=mddev->devices+i;
-  
-  nb_zone=data->nr_zones=
-    md_size[minor]/data->smallest->size +
-    (md_size[minor]%data->smallest->size ? 1 : 0);
-  
-  data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL);
-
-  size=mddev->devices[cur].size;
-
-  i=0;
-  while (cur<mddev->nb_dev)
-  {
-    data->hash_table[i].dev0=mddev->devices+cur;
-
-    if (size>=data->smallest->size) /* If we completely fill the slot */
-    {
-      data->hash_table[i++].dev1=NULL;
-      size-=data->smallest->size;
-
-      if (!size)
-      {
-	if (++cur==mddev->nb_dev) continue;
-	size=mddev->devices[cur].size;
-      }
-
-      continue;
-    }
-
-    if (++cur==mddev->nb_dev) /* Last dev, set dev1 as NULL */
-    {
-      data->hash_table[i].dev1=NULL;
-      continue;
-    }
-
-    dev0_size=size;		/* Here, we use a 2nd dev to fill the slot */
-    size=mddev->devices[cur].size;
-    data->hash_table[i++].dev1=mddev->devices+cur;
-    size-=(data->smallest->size - dev0_size);
-  }
-
-  return 0;
-}
-
-static int linear_stop (int minor, struct md_dev *mddev)
-{
-  struct linear_data *data=(struct linear_data *) mddev->private;
-  
-  kfree (data->hash_table);
-  kfree (data);
-
-  MOD_DEC_USE_COUNT;
-
-  return 0;
-}
-
-
-static int linear_map (struct md_dev *mddev, kdev_t *rdev,
-		       unsigned long *rsector, unsigned long size)
+static int linear_run (mddev_t *mddev)
 {
-  struct linear_data *data=(struct linear_data *) mddev->private;
-  struct linear_hash *hash;
-  struct real_dev *tmp_dev;
-  long block;
-
-  block=*rsector >> 1;
-  hash=data->hash_table+(block/data->smallest->size);
-  
-  if (block >= (hash->dev0->size + hash->dev0->offset))
-  {
-    if (!hash->dev1)
-    {
-      printk ("linear_map : hash->dev1==NULL for block %ld\n", block);
-      return (-1);
-    }
+	linear_conf_t *conf;
+	struct linear_hash *table;
+	mdk_rdev_t *rdev;
+	int size, i, j, nb_zone;
+	unsigned int curr_offset;
+
+	MOD_INC_USE_COUNT;
+
+	conf = kmalloc (sizeof (*conf), GFP_KERNEL);
+	if (!conf)
+		goto out;
+	mddev->private = conf;
+
+	if (md_check_ordering(mddev)) {
+		printk("linear: disks are not ordered, aborting!\n");
+		goto out;
+	}
+	/*
+	 * Find the smallest device.
+	 */
+
+	conf->smallest = NULL;
+	curr_offset = 0;
+	ITERATE_RDEV_ORDERED(mddev,rdev,j) {
+		dev_info_t *disk = conf->disks + j;
+
+		disk->dev = rdev->dev;
+		disk->size = rdev->size;
+		disk->offset = curr_offset;
+
+		curr_offset += disk->size;
+
+		if (!conf->smallest || (disk->size < conf->smallest->size))
+			conf->smallest = disk;
+	}
+
+	nb_zone = conf->nr_zones =
+		md_size[mdidx(mddev)] / conf->smallest->size +
+		((md_size[mdidx(mddev)] % conf->smallest->size) ? 1 : 0);
+  
+	conf->hash_table = kmalloc (sizeof (struct linear_hash) * nb_zone,
+					GFP_KERNEL);
+	if (!conf->hash_table)
+		goto out;
+
+	/*
+	 * Here we generate the linear hash table
+	 */
+	table = conf->hash_table;
+	i = 0;
+	size = 0;
+	for (j = 0; j < mddev->nb_dev; j++) {
+		dev_info_t *disk = conf->disks + j;
+
+		if (size < 0) {
+			table->dev1 = disk;
+			table++;
+		}
+		size += disk->size;
+
+		while (size) {
+			table->dev0 = disk;
+			size -= conf->smallest->size;
+			if (size < 0)
+				break;
+			table->dev1 = NULL;
+			table++;
+		}
+	}
+	table->dev1 = NULL;
+
+	return 0;
+
+out:
+	if (conf)
+		kfree(conf);
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static int linear_stop (mddev_t *mddev)
+{
+	linear_conf_t *conf = mddev_to_conf(mddev);
+  
+	kfree(conf->hash_table);
+	kfree(conf);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static int linear_make_request (mddev_t *mddev, int rw, struct buffer_head * bh)
+{
+        linear_conf_t *conf = mddev_to_conf(mddev);
+        struct linear_hash *hash;
+        dev_info_t *tmp_dev;
+        long block;
+
+	block = bh->b_blocknr * (bh->b_size >> 10);
+	hash = conf->hash_table + (block / conf->smallest->size);
+  
+	if (block >= (hash->dev0->size + hash->dev0->offset)) {
+		if (!hash->dev1) {
+			printk ("linear_make_request : hash->dev1==NULL for block %ld\n",
+						block);
+			return -1;
+		}
+		tmp_dev = hash->dev1;
+	} else
+		tmp_dev = hash->dev0;
     
-    tmp_dev=hash->dev1;
-  }
-  else
-    tmp_dev=hash->dev0;
-    
-  if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset)
-    printk ("Block %ld out of bounds on dev %s size %d offset %d\n",
-	    block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
-  
-  *rdev=tmp_dev->dev;
-  *rsector=(block-(tmp_dev->offset)) << 1;
+	if (block >= (tmp_dev->size + tmp_dev->offset)
+				|| block < tmp_dev->offset) {
+		printk ("linear_make_request: Block %ld out of bounds on dev %s size %d offset %d\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
+		return -1;
+	}
+	bh->b_rdev = tmp_dev->dev;
+	bh->b_rsector = (block - tmp_dev->offset) << 1;
 
-  return (0);
+	generic_make_request(rw, bh);
+	return 0;
 }
 
-static int linear_status (char *page, int minor, struct md_dev *mddev)
+static int linear_status (char *page, mddev_t *mddev)
 {
-  int sz=0;
+	int sz = 0;
 
 #undef MD_DEBUG
 #ifdef MD_DEBUG
-  int j;
-  struct linear_data *data=(struct linear_data *) mddev->private;
+	int j;
+	linear_conf_t *conf = mddev_to_conf(mddev);
   
-  sz+=sprintf (page+sz, "      ");
-  for (j=0; j<data->nr_zones; j++)
-  {
-    sz+=sprintf (page+sz, "[%s",
-		 partition_name (data->hash_table[j].dev0->dev));
-
-    if (data->hash_table[j].dev1)
-      sz+=sprintf (page+sz, "/%s] ",
-		   partition_name(data->hash_table[j].dev1->dev));
-    else
-      sz+=sprintf (page+sz, "] ");
-  }
-
-  sz+=sprintf (page+sz, "\n");
+	sz += sprintf(page+sz, "      ");
+	for (j = 0; j < conf->nr_zones; j++)
+	{
+		sz += sprintf(page+sz, "[%s",
+			partition_name(conf->hash_table[j].dev0->dev));
+
+		if (conf->hash_table[j].dev1)
+			sz += sprintf(page+sz, "/%s] ",
+			  partition_name(conf->hash_table[j].dev1->dev));
+		else
+			sz += sprintf(page+sz, "] ");
+	}
+	sz += sprintf(page+sz, "\n");
 #endif
-  sz+=sprintf (page+sz, " %dk rounding", 1<<FACTOR_SHIFT(FACTOR(mddev)));
-  return sz;
+	sz += sprintf(page+sz, " %dk rounding", mddev->param.chunk_size/1024);
+	return sz;
 }
 
 
-static struct md_personality linear_personality=
+static mdk_personality_t linear_personality=
 {
-  "linear",
-  linear_map,
-  NULL,
-  NULL,
-  linear_run,
-  linear_stop,
-  linear_status,
-  NULL,				/* no ioctls */
-  0
+	"linear",
+	NULL,
+	linear_make_request,
+	NULL,
+	linear_run,
+	linear_stop,
+	linear_status,
+	NULL,
+	0,
+	NULL,
+	NULL,
+	NULL,
+	NULL
 };
 
-
 #ifndef MODULE
 
-void __init linear_init (void)
+void md__init linear_init (void)
 {
-  register_md_personality (LINEAR, &linear_personality);
+	register_md_personality (LINEAR, &linear_personality);
 }
 
 #else
 
 int init_module (void)
 {
-  return (register_md_personality (LINEAR, &linear_personality));
+	return (register_md_personality (LINEAR, &linear_personality));
 }
 
 void cleanup_module (void)
 {
-  unregister_md_personality (LINEAR);
+	unregister_md_personality (LINEAR);
 }
 
 #endif
+
diff -u --recursive --new-file v2.3.42/linux/drivers/block/linear.h linux/drivers/block/linear.h
--- v2.3.42/linux/drivers/block/linear.h	Fri Nov 22 06:07:23 1996
+++ linux/drivers/block/linear.h	Wed Dec 31 16:00:00 1969
@@ -1,16 +0,0 @@
-#ifndef _LINEAR_H
-#define _LINEAR_H
-
-struct linear_hash
-{
-  struct real_dev *dev0, *dev1;
-};
-
-struct linear_data
-{
-  struct linear_hash *hash_table; /* Dynamically allocated */
-  struct real_dev *smallest;
-  int nr_zones;
-};
-
-#endif
diff -u --recursive --new-file v2.3.42/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.42/linux/drivers/block/ll_rw_blk.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/block/ll_rw_blk.c	Wed Feb  9 19:34:53 2000
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <linux/blk.h>
 #include <linux/highmem.h>
+#include <linux/raid/md.h>
 
 #include <linux/module.h>
 
@@ -65,9 +66,9 @@
  */
 DECLARE_WAIT_QUEUE_HEAD(wait_for_request);
 
-/* This specifies how many sectors to read ahead on the disk.  */
+/* This specifies how many sectors to read ahead on the disk. */
 
-int read_ahead[MAX_BLKDEV] = {0, };
+int read_ahead[MAX_BLKDEV];
 
 /* blk_dev_struct is:
  *	*request_fn
@@ -83,7 +84,7 @@
  *
  * if (!blk_size[MAJOR]) then no minor size checking is done.
  */
-int * blk_size[MAX_BLKDEV] = { NULL, NULL, };
+int * blk_size[MAX_BLKDEV];
 
 /*
  * blksize_size contains the size of all block-devices:
@@ -92,7 +93,7 @@
  *
  * if (!blksize_size[MAJOR]) then 1024 bytes is assumed.
  */
-int * blksize_size[MAX_BLKDEV] = { NULL, NULL, };
+int * blksize_size[MAX_BLKDEV];
 
 /*
  * hardsect_size contains the size of the hardware sector of a device.
@@ -106,17 +107,17 @@
  * This is currently set by some scsi devices and read by the msdos fs driver.
  * Other uses may appear later.
  */
-int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
+int * hardsect_size[MAX_BLKDEV];
 
 /*
  * The following tunes the read-ahead algorithm in mm/filemap.c
  */
-int * max_readahead[MAX_BLKDEV] = { NULL, NULL, };
+int * max_readahead[MAX_BLKDEV];
 
 /*
  * Max number of sectors per request
  */
-int * max_sectors[MAX_BLKDEV] = { NULL, NULL, };
+int * max_sectors[MAX_BLKDEV];
 
 static inline int get_max_sectors(kdev_t dev)
 {
@@ -126,18 +127,24 @@
 }
 
 /*
- * Is called with the request spinlock aquired.
  * NOTE: the device-specific queue() functions
  * have to be atomic!
  */
-static inline request_queue_t *get_queue(kdev_t dev)
+request_queue_t * blk_get_queue (kdev_t dev)
 {
 	int major = MAJOR(dev);
 	struct blk_dev_struct *bdev = blk_dev + major;
+	unsigned long flags;
+	request_queue_t *ret;
 
+	spin_lock_irqsave(&io_request_lock,flags);
 	if (bdev->queue)
-		return bdev->queue(dev);
-	return &blk_dev[major].request_queue;
+		ret = bdev->queue(dev);
+	else
+		ret = &blk_dev[major].request_queue;
+	spin_unlock_irqrestore(&io_request_lock,flags);
+
+	return ret;
 }
 
 void blk_cleanup_queue(request_queue_t * q)
@@ -147,12 +154,17 @@
 
 void blk_queue_headactive(request_queue_t * q, int active)
 {
-	q->head_active     = active;
+	q->head_active = active;
+}
+
+void blk_queue_pluggable (request_queue_t * q, plug_device_fn *plug)
+{
+	q->plug_device_fn = plug;
 }
 
-void blk_queue_pluggable(request_queue_t * q, int use_plug)
+void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
 {
-	q->use_plug        = use_plug;
+	q->make_request_fn = mfn;
 }
 
 static int ll_merge_fn(request_queue_t *q, struct request *req, 
@@ -185,42 +197,23 @@
 
 void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
 {
-	q->request_fn		= rfn;
+	q->request_fn     	= rfn;
 	q->current_request	= NULL;
-	q->merge_fn		= ll_merge_fn;
+	q->merge_fn       	= ll_merge_fn;
 	q->merge_requests_fn	= ll_merge_requests_fn;
-	q->plug_tq.sync		= 0;
-	q->plug_tq.routine	= unplug_device;
-	q->plug_tq.data		= q;
-	q->plugged		= 0;
+	q->make_request_fn	= NULL;
+	q->plug_tq.sync   	= 0;
+	q->plug_tq.routine	= &generic_unplug_device;
+	q->plug_tq.data   	= q;
+	q->plugged        	= 0;
 	/*
 	 * These booleans describe the queue properties.  We set the
 	 * default (and most common) values here.  Other drivers can
 	 * use the appropriate functions to alter the queue properties.
 	 * as appropriate.
 	 */
-	q->use_plug		= 1;
-	q->head_active		= 1;
-}
-
-/*
- * remove the plug and let it rip..
- */
-void unplug_device(void * data)
-{
-	request_queue_t * q = (request_queue_t *) data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock,flags);
-	if( q->plugged )
-	{
-	        q->plugged = 0;
-		if( q->current_request != NULL )
-		{
-			(q->request_fn)(q);
-		}
-	}
-	spin_unlock_irqrestore(&io_request_lock,flags);
+	q->plug_device_fn 	= NULL;
+	q->head_active    	= 1;
 }
 
 /*
@@ -231,8 +224,12 @@
  * This is called with interrupts off and no requests on the queue.
  * (and with the request spinlock aquired)
  */
-static inline void plug_device(request_queue_t * q)
+inline void generic_plug_device (request_queue_t *q, kdev_t dev)
 {
+	if (MAJOR(dev) == MD_MAJOR) {
+		spin_unlock_irq(&io_request_lock);
+		BUG();
+	}
 	if (q->current_request)
 		return;
 
@@ -241,6 +238,23 @@
 }
 
 /*
+ * remove the plug and let it rip..
+ */
+void generic_unplug_device(void * data)
+{
+	request_queue_t * q = (request_queue_t *) data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock,flags);
+	if (q->plugged) {
+		q->plugged = 0;
+		if (q->current_request)
+			(q->request_fn)(q);
+	}
+	spin_unlock_irqrestore(&io_request_lock,flags);
+}
+
+/*
  * look for a free request in the first N entries.
  * NOTE: interrupts must be disabled on the way in (on SMP the request queue
  * spinlock has to be aquired), and will still be disabled on the way out.
@@ -337,7 +351,7 @@
 }
 
 static inline void drive_stat_acct(struct request *req,
-                                   unsigned long nr_sectors, int new_io)
+				unsigned long nr_sectors, int new_io)
 {
 	int major = MAJOR(req->rq_dev);
 	int minor = MINOR(req->rq_dev);
@@ -384,23 +398,17 @@
  * which is important for drive_stat_acct() above.
  */
 
-static void add_request(request_queue_t * q, struct request * req)
+static inline void __add_request(request_queue_t * q, struct request * req)
 {
 	int major = MAJOR(req->rq_dev);
 	struct request * tmp;
-	unsigned long flags;
 
 	drive_stat_acct(req, req->nr_sectors, 1);
 	req->next = NULL;
 
-	/*
-	 * We use the goto to reduce locking complexity
-	 */
-	spin_lock_irqsave(&io_request_lock,flags);
-
 	if (!(tmp = q->current_request)) {
 		q->current_request = req;
-		goto out;
+		return;
 	}
 	for ( ; tmp->next ; tmp = tmp->next) {
 		const int after_current = IN_ORDER(tmp,req);
@@ -420,7 +428,7 @@
 	/*
 	 * FIXME(eric) I don't understand why there is a need for this
 	 * special case code.  It clearly doesn't fit any more with
-	 * the new queueing architecture, and it got added in 2.3.10.  
+	 * the new queueing architecture, and it got added in 2.3.10.
 	 * I am leaving this in here until I hear back from the COMPAQ
 	 * people.
 	 */
@@ -433,16 +441,13 @@
 	{
 		(q->request_fn)(q);
 	}
-
-out:
-	spin_unlock_irqrestore(&io_request_lock,flags);
 }
 
 /*
  * Has to be called with the request spinlock aquired
  */
 static inline void attempt_merge (request_queue_t * q,
-				  struct request *req, 
+				  struct request *req,
 				  int max_sectors)
 {
 	struct request *next = req->next;
@@ -453,7 +458,6 @@
 		return;
 	if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors)
 		return;
-
 	/*
 	 * If we are not allowed to merge these requests, then
 	 * return.  If we are allowed to merge, then the count
@@ -471,11 +475,10 @@
 	wake_up (&wait_for_request);
 }
 
-static void __make_request(request_queue_t * q,
-			   int major,
-			   int rw, 
+static inline void __make_request(request_queue_t * q, int rw,
 			   struct buffer_head * bh)
 {
+	int major = MAJOR(bh->b_rdev);
 	unsigned int sector, count;
 	struct request * req;
 	int rw_ahead, max_req, max_sectors;
@@ -484,28 +487,22 @@
 	count = bh->b_size >> 9;
 	sector = bh->b_rsector;
 
-	/* It had better not be a new buffer by the time we see it */
-	if (buffer_new(bh))
-		BUG();
-
-	/* Only one thread can actually submit the I/O. */
-	if (test_and_set_bit(BH_Lock, &bh->b_state))
-		return;
-
 	if (blk_size[major]) {
 		unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1;
 
 		if (maxsector < count || maxsector - count < sector) {
 			bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);
-                        /* This may well happen - the kernel calls bread()
-                           without checking the size of the device, e.g.,
-                           when mounting a device. */
+			if (!blk_size[major][MINOR(bh->b_rdev)])
+				goto end_io;
+			/* This may well happen - the kernel calls bread()
+			   without checking the size of the device, e.g.,
+			   when mounting a device. */
 			printk(KERN_INFO
-                               "attempt to access beyond end of device\n");
+				"attempt to access beyond end of device\n");
 			printk(KERN_INFO "%s: rw=%d, want=%d, limit=%d\n",
-                               kdevname(bh->b_rdev), rw,
-                               (sector + count)>>1,
-                               blk_size[major][MINOR(bh->b_rdev)]);
+				kdevname(bh->b_rdev), rw,
+					(sector + count)>>1,
+					blk_size[major][MINOR(bh->b_rdev)]);
 			goto end_io;
 		}
 	}
@@ -539,8 +536,7 @@
 			max_req = (NR_REQUEST * 2) / 3;
 			break;
 		default:
-			printk(KERN_ERR "make_request: bad block dev cmd,"
-                               " must be R/W/RA/WA\n");
+			BUG();
 			goto end_io;
 	}
 
@@ -561,10 +557,12 @@
 #endif
 
 /* look for a free request. */
-       /* Loop uses two requests, 1 for loop and 1 for the real device.
-        * Cut max_req in half to avoid running out and deadlocking. */
+	/*
+	 * Loop uses two requests, 1 for loop and 1 for the real device.
+	 * Cut max_req in half to avoid running out and deadlocking.
+	 */
 	 if ((major == LOOP_MAJOR) || (major == NBD_MAJOR))
-	     max_req >>= 1;
+		max_req >>= 1;
 
 	/*
 	 * Try to coalesce the new request with old requests
@@ -579,10 +577,10 @@
 	req = q->current_request;
 	if (!req) {
 		/* MD and loop can't handle plugging without deadlocking */
-		if (major != MD_MAJOR && major != LOOP_MAJOR && 
-		    major != DDV_MAJOR && major != NBD_MAJOR
-		    && q->use_plug)
-			plug_device(q); /* is atomic */
+		if (q->plug_device_fn)
+			q->plug_device_fn(q, bh->b_rdev); /* is atomic */
+		else
+			generic_plug_device(q, bh->b_rdev); /* is atomic */
 		goto get_rq;
 	}
 
@@ -667,13 +665,34 @@
 get_rq:
 	req = get_request(max_req, bh->b_rdev);
 
-	spin_unlock_irqrestore(&io_request_lock,flags);
-
-/* if no request available: if rw_ahead, forget it; otherwise try again blocking.. */
+	/*
+	 * if no request available: if rw_ahead, forget it,
+	 * otherwise try again blocking..
+	 */
 	if (!req) {
+		spin_unlock_irqrestore(&io_request_lock,flags);
 		if (rw_ahead)
 			goto end_io;
 		req = __get_request_wait(max_req, bh->b_rdev);
+		spin_lock_irqsave(&io_request_lock,flags);
+	}
+	/*
+	 * Dont start the IO if the buffer has been
+	 * invalidated meanwhile. (we have to do this
+	 * within the io request lock and atomically
+	 * before adding the request, see buffer.c's
+	 * insert_into_queues_exclusive() function.
+	 */
+	if (!test_bit(BH_Req, &bh->b_state)) {
+		req->rq_status = RQ_INACTIVE;
+		spin_unlock_irqrestore(&io_request_lock,flags);
+		/*
+		 * A fake 'everything went ok' completion event.
+		 * The bh doesnt matter anymore, but we should not
+		 * signal errors to RAID levels.
+	 	 */
+		bh->b_end_io(bh, 1);
+		return;
 	}
 
 /* fill up the request-info, and add it to the queue */
@@ -689,52 +708,51 @@
 	req->bh = bh;
 	req->bhtail = bh;
 	req->next = NULL;
-	add_request(q, req);
+	__add_request(q, req);
+	spin_unlock_irqrestore(&io_request_lock, flags);
 	return;
 
 end_io:
 	bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
 }
 
-void make_request(int major,int rw,  struct buffer_head * bh)
+void generic_make_request(int rw, struct buffer_head * bh)
 {
 	request_queue_t * q;
 	unsigned long flags;
-	
-	q = get_queue(bh->b_dev);
 
-	__make_request(q, major, rw, bh);
+	q = blk_get_queue(bh->b_rdev);
+
+	__make_request(q, rw, bh);
 
 	spin_lock_irqsave(&io_request_lock,flags);
-	if( !q->plugged )
+	if (q && !q->plugged)
 		(q->request_fn)(q);
 	spin_unlock_irqrestore(&io_request_lock,flags);
 }
 
 
-
 /* This function can be used to request a number of buffers from a block
    device. Currently the only restriction is that all buffers must belong to
    the same device */
 
-void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
+static void __ll_rw_block(int rw, int nr, struct buffer_head * bh[],int haslock)
 {
 	unsigned int major;
 	int correct_size;
-	request_queue_t		* q;
-	unsigned long flags;
+	request_queue_t *q;
 	int i;
 
-
 	major = MAJOR(bh[0]->b_dev);
-	if (!(q = get_queue(bh[0]->b_dev))) {
+	q = blk_get_queue(bh[0]->b_dev);
+	if (!q) {
 		printk(KERN_ERR
 	"ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n",
 		kdevname(bh[0]->b_dev), bh[0]->b_blocknr);
 		goto sorry;
 	}
 
-	/* Determine correct block size for this device.  */
+	/* Determine correct block size for this device. */
 	correct_size = BLOCK_SIZE;
 	if (blksize_size[major]) {
 		i = blksize_size[major][MINOR(bh[0]->b_dev)];
@@ -742,7 +760,7 @@
 			correct_size = i;
 	}
 
-	/* Verify requested block sizes.  */
+	/* Verify requested block sizes. */
 	for (i = 0; i < nr; i++) {
 		if (bh[i]->b_size != correct_size) {
 			printk(KERN_NOTICE "ll_rw_block: device %s: "
@@ -751,19 +769,6 @@
 			       correct_size, bh[i]->b_size);
 			goto sorry;
 		}
-
-		/* Md remaps blocks now */
-		bh[i]->b_rdev = bh[i]->b_dev;
-		bh[i]->b_rsector=bh[i]->b_blocknr*(bh[i]->b_size >> 9);
-#ifdef CONFIG_BLK_DEV_MD
-		if (major==MD_MAJOR &&
-		    md_map (MINOR(bh[i]->b_dev), &bh[i]->b_rdev,
-			    &bh[i]->b_rsector, bh[i]->b_size >> 9)) {
-		        printk (KERN_ERR
-				"Bad md_map in ll_rw_block\n");
-		        goto sorry;
-		}
-#endif
 	}
 
 	if ((rw & WRITE) && is_read_only(bh[0]->b_dev)) {
@@ -773,25 +778,29 @@
 	}
 
 	for (i = 0; i < nr; i++) {
+		/* Only one thread can actually submit the I/O. */
+		if (haslock) {
+			if (!buffer_locked(bh[i]))
+				BUG();
+		} else {
+			if (test_and_set_bit(BH_Lock, &bh[i]->b_state))
+				continue;
+		}
 		set_bit(BH_Req, &bh[i]->b_state);
-#ifdef CONFIG_BLK_DEV_MD
-		if (MAJOR(bh[i]->b_dev) == MD_MAJOR) {
-			md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
-			continue;
+
+		if (q->make_request_fn)
+			q->make_request_fn(rw, bh[i]);
+		else {
+			bh[i]->b_rdev = bh[i]->b_dev;
+			bh[i]->b_rsector = bh[i]->b_blocknr*(bh[i]->b_size>>9);
+
+			generic_make_request(rw, bh[i]);
 		}
-#endif
-		__make_request(q, MAJOR(bh[i]->b_rdev), rw, bh[i]);
 	}
 
-	spin_lock_irqsave(&io_request_lock,flags);
-	if( !q->plugged )
-	{
-		(q->request_fn)(q);
-	}
-	spin_unlock_irqrestore(&io_request_lock,flags);
 	return;
 
-      sorry:
+sorry:
 	for (i = 0; i < nr; i++) {
 		mark_buffer_clean(bh[i]); /* remeber to refile it */
 		clear_bit(BH_Uptodate, &bh[i]->b_state);
@@ -800,8 +809,18 @@
 	return;
 }
 
+void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
+{
+	__ll_rw_block(rw, nr, bh, 0);
+}
+
+void ll_rw_block_locked(int rw, int nr, struct buffer_head * bh[])
+{
+	__ll_rw_block(rw, nr, bh, 1);
+}
+
 #ifdef CONFIG_STRAM_SWAP
-extern int stram_device_init( void );
+extern int stram_device_init (void);
 #endif
 
 /*
@@ -811,8 +830,7 @@
  * 1 means we are done
  */
 
-int 
-end_that_request_first( struct request *req, int uptodate, char *name ) 
+int end_that_request_first (struct request *req, int uptodate, char *name)
 {
 	struct buffer_head * bh;
 	int nsect;
@@ -847,8 +865,7 @@
 	return 0;
 }
 
-void
-end_that_request_last( struct request *req ) 
+void end_that_request_last(struct request *req)
 {
 	if (req->sem != NULL)
 		up(req->sem);
@@ -862,7 +879,7 @@
 	struct blk_dev_struct *dev;
 
 	for (dev = blk_dev + MAX_BLKDEV; dev-- != blk_dev;) {
-		dev->queue           = NULL;
+		dev->queue = NULL;
 		blk_init_queue(&dev->request_queue, NULL);
 	}
 
@@ -923,8 +940,8 @@
 	floppy_init();
 #else
 #if !defined (__mc68000__) && !defined(CONFIG_PPC) && !defined(__sparc__)\
-    && !defined(CONFIG_APUS) && !defined(__sh__)
-	outb_p(0xc, 0x3f2);
+    && !defined(CONFIG_APUS) && !defined(__sh__) && !defined(__ia64__)
+	outb_p(0xc, 0x3f2);	/* XXX do something with the floppy controller?? */
 #endif
 #endif
 #ifdef CONFIG_CDU31A
@@ -943,7 +960,7 @@
 	sbpcd_init();
 #endif CONFIG_SBPCD
 #ifdef CONFIG_AZTCD
-        aztcd_init();
+	aztcd_init();
 #endif CONFIG_AZTCD
 #ifdef CONFIG_CDU535
 	sony535_init();
@@ -981,3 +998,5 @@
 EXPORT_SYMBOL(blk_init_queue);
 EXPORT_SYMBOL(blk_cleanup_queue);
 EXPORT_SYMBOL(blk_queue_headactive);
+EXPORT_SYMBOL(blk_queue_pluggable);
+EXPORT_SYMBOL(generic_make_request);
diff -u --recursive --new-file v2.3.42/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.3.42/linux/drivers/block/loop.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/block/loop.c	Thu Feb 10 12:16:57 2000
@@ -342,8 +342,8 @@
 	set_fs(old_fs);
 
 	if (retval < 0) {
-		printk(KERN_WARNING "loop: cannot create block - FS write failed: code %d\n", 
-									retval);
+		printk(KERN_WARNING "loop: cannot create block - FS write failed: code %Zi\n",
+			retval);
 		return FALSE;
 	} else {
 		return TRUE;
@@ -386,7 +386,11 @@
 		   a file structure */
 		lo->lo_backing_file = NULL;
 	} else if (S_ISREG(inode->i_mode)) {
-		if (!inode->i_op->get_block) { 
+		/*
+		 * Total crap. We should just use pagecache instead of trying
+		 * to redirect on block level.
+		 */
+		if (!inode->i_mapping->a_ops->bmap) {
 			printk(KERN_ERR "loop: device has no block access/not implemented\n");
 			goto out_putf;
 		}
diff -u --recursive --new-file v2.3.42/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.3.42/linux/drivers/block/md.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/block/md.c	Tue Feb  8 18:44:57 2000
@@ -1,21 +1,17 @@
-
 /*
    md.c : Multiple Devices driver for Linux
-          Copyright (C) 1994-96 Marc ZYNGIER
-	  <zyngier@ufr-info-p7.ibp.fr> or
-	  <maz@gloups.fdn.fr>
+          Copyright (C) 1998, 1999, 2000 Ingo Molnar
 
-   A lot of inspiration came from hd.c ...
+     completely rewritten, based on the MD driver code from Marc Zyngier
 
-   kerneld support by Boris Tobotras <boris@xtalk.msk.su>
-   boot support for linear and striped mode by Harald Hoyer <HarryH@Royal.Net>
+   Changes:
 
-   RAID-1/RAID-5 extensions by:
-        Ingo Molnar, Miguel de Icaza, Gadi Oxman
+   - RAID-1/RAID-5 extensions by Miguel de Icaza, Gadi Oxman, Ingo Molnar
+   - boot support for linear and striped mode by Harald Hoyer <HarryH@Royal.Net>
+   - kerneld support by Boris Tobotras <boris@xtalk.msk.su>
+   - kmod support by: Cyrus Durgin
+   - RAID0 bugfixes: Mark Anthony Lisher <markal@iname.com>
 
-   Changes for kmod by:
-   	Cyrus Durgin
-   
    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, or (at your option)
@@ -26,731 +22,2857 @@
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
 
-/*
- * Current RAID-1,4,5 parallel reconstruction speed limit is 1024 KB/sec, so
- * the extra system load does not show up that much. Increase it if your
- * system can take more.
- */
-#define SPEED_LIMIT 1024
-
 #include <linux/config.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-#include <linux/md.h>
-#include <linux/hdreg.h>
-#include <linux/stat.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/blkdev.h>
-#include <linux/genhd.h>
-#include <linux/smp_lock.h>
+#include <linux/raid/md.h>
+
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
-#include <linux/errno.h>
-#include <linux/init.h>
 
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
 
+#include <asm/unaligned.h>
+
+extern asmlinkage int sys_sched_yield(void);
+extern asmlinkage int sys_setsid(void);
+
+extern unsigned long io_events[MAX_BLKDEV];
+
 #define MAJOR_NR MD_MAJOR
 #define MD_DRIVER
 
 #include <linux/blk.h>
-#include <linux/blkpg.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-#include <asm/atomic.h>
 
 #ifdef CONFIG_MD_BOOT
-extern kdev_t name_to_kdev_t(char *line) __init;
+extern kdev_t name_to_kdev_t(char *line) md__init;
+#endif
+
+#define DEBUG 0
+#if DEBUG
+# define dprintk(x...) printk(x)
+#else
+# define dprintk(x...) do { } while(0)
 #endif
 
-static struct hd_struct md_hd_struct[MAX_MD_DEV];
-static int md_blocksizes[MAX_MD_DEV];
-int md_maxreadahead[MAX_MD_DEV];
-#if SUPPORT_RECONSTRUCTION
-static struct md_thread *md_sync_thread = NULL;
-#endif /* SUPPORT_RECONSTRUCTION */
+static mdk_personality_t *pers[MAX_PERSONALITY] = {NULL, };
 
-int md_size[MAX_MD_DEV]={0, };
+/*
+ * these have to be allocated separately because external
+ * subsystems want to have a pre-defined structure
+ */
+struct hd_struct md_hd_struct[MAX_MD_DEVS];
+static int md_blocksizes[MAX_MD_DEVS];
+static int md_maxreadahead[MAX_MD_DEVS];
+static mdk_thread_t *md_recovery_thread = NULL;
+
+int md_size[MAX_MD_DEVS] = {0, };
 
 static struct gendisk md_gendisk=
 {
-  MD_MAJOR,
-  "md",
-  0,
-  1,
-  md_hd_struct,
-  md_size,
-  MAX_MD_DEV,
-  NULL,
-  NULL
+	MD_MAJOR,
+	"md",
+	0,
+	1,
+	md_hd_struct,
+	md_size,
+	MAX_MD_DEVS,
+	NULL,
+	NULL
 };
 
-static struct md_personality *pers[MAX_PERSONALITY]={NULL, };
-struct md_dev md_dev[MAX_MD_DEV];
+void md_plug_device (request_queue_t *mdqueue, kdev_t dev)
+{
+	mdk_rdev_t * rdev;
+	struct md_list_head *tmp;
+	request_queue_t *q;
+	mddev_t *mddev;
 
-int md_thread(void * arg);
+	if (!md_test_and_set_bit(0, (atomic_t *)&mdqueue->plugged)) {
+ 		mddev = kdev_to_mddev(dev);
+		ITERATE_RDEV(mddev,rdev,tmp) {
+			q = blk_get_queue(rdev->dev);
+			generic_unplug_device(q);
+		}
+		queue_task(&mdqueue->plug_tq, &tq_disk);
+	}
+}
 
-static int legacy_raid_sb (int minor, int pnum)
+static void md_unplug_device (void * data)
 {
-	int i, factor;
+	mdk_rdev_t * rdev;
+	struct md_list_head *tmp;
+	mddev_t *mddev = (mddev_t *)data;
+	request_queue_t *mdqueue = &mddev->queue, *q;
 
-	factor = 1 << FACTOR_SHIFT(FACTOR((md_dev+minor)));
+	clear_bit(0, (atomic_t *)&mdqueue->plugged);
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		q = blk_get_queue(rdev->dev);
+		generic_unplug_device(q);
+	}
+}
 
-	/*****
-	 * do size and offset calculations.
-	 */
-	for (i=0; i<md_dev[minor].nb_dev; i++) {
-		md_dev[minor].devices[i].size &= ~(factor - 1);
-		md_size[minor] += md_dev[minor].devices[i].size;
-		md_dev[minor].devices[i].offset=i ? (md_dev[minor].devices[i-1].offset + 
-							md_dev[minor].devices[i-1].size) : 0;
+/*
+ * Enables to iterate over all existing md arrays
+ */
+static MD_LIST_HEAD(all_mddevs);
+
+/*
+ * The mapping between kdev and mddev is not necessary a simple
+ * one! Eg. HSM uses several sub-devices to implement Logical
+ * Volumes. All these sub-devices map to the same mddev.
+ */
+dev_mapping_t mddev_map [MAX_MD_DEVS] = { {NULL, 0}, };
+
+void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data)
+{
+	unsigned int minor = MINOR(dev);
+
+	if (MAJOR(dev) != MD_MAJOR) {
+		MD_BUG();
+		return;
 	}
-	if (pnum == RAID0 >> PERSONALITY_SHIFT)
-		md_maxreadahead[minor] = MD_DEFAULT_DISK_READAHEAD * md_dev[minor].nb_dev;
-	return 0;
+	if (mddev_map[minor].mddev != NULL) {
+		MD_BUG();
+		return;
+	}
+	mddev_map[minor].mddev = mddev;
+	mddev_map[minor].data = data;
 }
 
-static void free_sb (struct md_dev *mddev)
+void del_mddev_mapping (mddev_t * mddev, kdev_t dev)
 {
-	int i;
-	struct real_dev *realdev;
+	unsigned int minor = MINOR(dev);
 
-	if (mddev->sb) {
-		free_page((unsigned long) mddev->sb);
-		mddev->sb = NULL;
+	if (MAJOR(dev) != MD_MAJOR) {
+		MD_BUG();
+		return;
 	}
-	for (i = 0; i <mddev->nb_dev; i++) {
-		realdev = mddev->devices + i;
-		if (realdev->sb) {
-			free_page((unsigned long) realdev->sb);
-			realdev->sb = NULL;
-		}
+	if (mddev_map[minor].mddev != mddev) {
+		MD_BUG();
+		return;
 	}
+	mddev_map[minor].mddev = NULL;
+	mddev_map[minor].data = NULL;
 }
 
-/*
- * Check one RAID superblock for generic plausibility
- */
+static request_queue_t *md_get_queue (kdev_t dev)
+{
+	mddev_t *mddev = kdev_to_mddev(dev);
 
-#define BAD_MAGIC KERN_ERR \
-"md: %s: invalid raid superblock magic (%x) on block %u\n"
+	if (!mddev)
+		return NULL;
+	return &mddev->queue;
+}
 
-#define OUT_OF_MEM KERN_ALERT \
-"md: out of memory.\n"
+static void do_md_request (request_queue_t * q)
+{
+	printk(KERN_ALERT "Got md request, not good...");
+	BUG();
+	return;
+}
 
-#define NO_DEVICE KERN_ERR \
-"md: disabled device %s\n"
+void md_make_request (int rw, struct buffer_head * bh)
+{
+	mddev_t *mddev = kdev_to_mddev(bh->b_dev);
 
-#define SUCCESS 0
-#define FAILURE -1
+	if (!mddev || !mddev->pers)
+		bh->b_end_io(bh, 0);
+	else {
+		if ((rw == READ || rw == READA) && buffer_uptodate(bh))
+			bh->b_end_io(bh, 1);
+		else
+			mddev->pers->make_request(mddev, rw, bh);
+	}
+}
 
-static int analyze_one_sb (struct real_dev * rdev)
+static mddev_t * alloc_mddev (kdev_t dev)
 {
-	int ret = FAILURE;
-	struct buffer_head *bh;
-	kdev_t dev = rdev->dev;
-	md_superblock_t *sb;
+	request_queue_t *q;
+	mddev_t *mddev;
+
+	if (MAJOR(dev) != MD_MAJOR) {
+		MD_BUG();
+		return 0;
+	}
+	mddev = (mddev_t *) kmalloc(sizeof(*mddev), GFP_KERNEL);
+	if (!mddev)
+		return NULL;
+		
+	memset(mddev, 0, sizeof(*mddev));
+
+	mddev->__minor = MINOR(dev);
+	init_MUTEX(&mddev->reconfig_sem);
+	init_MUTEX(&mddev->recovery_sem);
+	init_MUTEX(&mddev->resync_sem);
+	MD_INIT_LIST_HEAD(&mddev->disks);
+	MD_INIT_LIST_HEAD(&mddev->all_mddevs);
+
+	q = &mddev->queue;
+	blk_init_queue(q, DEVICE_REQUEST);
+	blk_queue_pluggable(q, md_plug_device);
+	blk_queue_make_request(q, md_make_request);
+	
+	q->plug_tq.sync = 0;
+        q->plug_tq.routine = &md_unplug_device;
+        q->plug_tq.data = mddev;
 
 	/*
-	 * Read the superblock, it's at the end of the disk
+	 * The 'base' mddev is the one with data NULL.
+	 * personalities can create additional mddevs 
+	 * if necessary.
 	 */
-	rdev->sb_offset = MD_NEW_SIZE_BLOCKS (blk_size[MAJOR(dev)][MINOR(dev)]);
-	set_blocksize (dev, MD_SB_BYTES);
-	bh = bread (dev, rdev->sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
+	add_mddev_mapping(mddev, dev, 0);
+	md_list_add(&mddev->all_mddevs, &all_mddevs);
 
-	if (bh) {
-		sb = (md_superblock_t *) bh->b_data;
-		if (sb->md_magic != MD_SB_MAGIC) {
-			printk (BAD_MAGIC, kdevname(dev),
-					 sb->md_magic, rdev->sb_offset);
-			goto abort;
-		}
-		rdev->sb = (md_superblock_t *) __get_free_page(GFP_KERNEL);
-		if (!rdev->sb) {
-			printk (OUT_OF_MEM);
-			goto abort;
-		}
-		memcpy (rdev->sb, bh->b_data, MD_SB_BYTES);
-
-		rdev->size = sb->size;
-	} else
-		printk (NO_DEVICE,kdevname(rdev->dev));
-	ret = SUCCESS;
-abort:
-	if (bh)
-		brelse (bh);
-	return ret;
+	return mddev;
 }
 
-#undef SUCCESS
-#undef FAILURE
+static void free_mddev (mddev_t *mddev)
+{
+	if (!mddev) {
+		MD_BUG();
+		return;
+	}
 
-#undef BAD_MAGIC
-#undef OUT_OF_MEM
-#undef NO_DEVICE
+	/*
+	 * Make sure nobody else is using this mddev
+	 * (careful, we rely on the global kernel lock here)
+	 */
+	while (md_atomic_read(&mddev->resync_sem.count) != 1)
+		schedule();
+	while (md_atomic_read(&mddev->recovery_sem.count) != 1)
+		schedule();
 
-/*
- * Check a full RAID array for plausibility
- */
+	del_mddev_mapping(mddev, MKDEV(MD_MAJOR, mdidx(mddev)));
+	md_list_del(&mddev->all_mddevs);
+	MD_INIT_LIST_HEAD(&mddev->all_mddevs);
+	kfree(mddev);
+}
 
-#define INCONSISTENT KERN_ERR \
-"md: superblock inconsistency -- run ckraid\n"
+struct gendisk * find_gendisk (kdev_t dev)
+{
+	struct gendisk *tmp = gendisk_head;
 
-#define OUT_OF_DATE KERN_ERR \
-"md: superblock update time inconsistenty -- using the most recent one\n"
+	while (tmp != NULL) {
+		if (tmp->major == MAJOR(dev))
+			return (tmp);
+		tmp = tmp->next;
+	}
+	return (NULL);
+}
 
-#define OLD_VERSION KERN_ALERT \
-"md: %s: unsupported raid array version %d.%d.%d\n"
+mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+{
+	mdk_rdev_t * rdev;
+	struct md_list_head *tmp;
+
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->desc_nr == nr)
+			return rdev;
+	}
+	return NULL;
+}
 
-#define NOT_CLEAN KERN_ERR \
-"md: %s: raid array is not clean -- run ckraid\n"
+mdk_rdev_t * find_rdev(mddev_t * mddev, kdev_t dev)
+{
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev;
 
-#define NOT_CLEAN_IGNORE KERN_ERR \
-"md: %s: raid array is not clean -- reconstructing parity\n"
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->dev == dev)
+			return rdev;
+	}
+	return NULL;
+}
 
-#define UNKNOWN_LEVEL KERN_ERR \
-"md: %s: unsupported raid level %d\n"
+static MD_LIST_HEAD(device_names);
 
-static int analyze_sbs (int minor, int pnum)
+char * partition_name (kdev_t dev)
 {
-	struct md_dev *mddev = md_dev + minor;
-	int i, N = mddev->nb_dev, out_of_date = 0;
-	struct real_dev * disks = mddev->devices;
-	md_superblock_t *sb, *freshest = NULL;
+	struct gendisk *hd;
+	static char nomem [] = "<nomem>";
+	dev_name_t *dname;
+	struct md_list_head *tmp = device_names.next;
 
+	while (tmp != &device_names) {
+		dname = md_list_entry(tmp, dev_name_t, list);
+		if (dname->dev == dev)
+			return dname->name;
+		tmp = tmp->next;
+	}
+
+	dname = (dev_name_t *) kmalloc(sizeof(*dname), GFP_KERNEL);
+
+	if (!dname)
+		return nomem;
 	/*
-	 * RAID-0 and linear don't use a RAID superblock
+	 * ok, add this new device name to the list
 	 */
-	if (pnum == RAID0 >> PERSONALITY_SHIFT ||
-		pnum == LINEAR >> PERSONALITY_SHIFT)
-			return legacy_raid_sb (minor, pnum);
+	hd = find_gendisk (dev);
+
+	if (!hd)
+		sprintf (dname->name, "[dev %s]", kdevname(dev));
+	else
+		disk_name (hd, MINOR(dev), dname->name);
+
+	dname->dev = dev;
+	MD_INIT_LIST_HEAD(&dname->list);
+	md_list_add(&dname->list, &device_names);
+
+	return dname->name;
+}
 
+static unsigned int calc_dev_sboffset (kdev_t dev, mddev_t *mddev,
+						int persistent)
+{
+	unsigned int size = 0;
+
+	if (blk_size[MAJOR(dev)])
+		size = blk_size[MAJOR(dev)][MINOR(dev)];
+	if (persistent)
+		size = MD_NEW_SIZE_BLOCKS(size);
+	return size;
+}
+
+static unsigned int calc_dev_size (kdev_t dev, mddev_t *mddev, int persistent)
+{
+	unsigned int size;
+
+	size = calc_dev_sboffset(dev, mddev, persistent);
+	if (!mddev->sb) {
+		MD_BUG();
+		return size;
+	}
+	if (mddev->sb->chunk_size)
+		size &= ~(mddev->sb->chunk_size/1024 - 1);
+	return size;
+}
+
+static unsigned int zoned_raid_size (mddev_t *mddev)
+{
+	unsigned int mask;
+	mdk_rdev_t * rdev;
+	struct md_list_head *tmp;
+
+	if (!mddev->sb) {
+		MD_BUG();
+		return -EINVAL;
+	}
 	/*
-	 * Verify the RAID superblock on each real device
+	 * do size and offset calculations.
 	 */
-	for (i = 0; i < N; i++)
-		if (analyze_one_sb(disks+i))
-			goto abort;
+	mask = ~(mddev->sb->chunk_size/1024 - 1);
+
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		rdev->size &= mask;
+		md_size[mdidx(mddev)] += rdev->size;
+	}
+	return 0;
+}
+
+/*
+ * We check wether all devices are numbered from 0 to nb_dev-1. The
+ * order is guaranteed even after device name changes.
+ *
+ * Some personalities (raid0, linear) use this. Personalities that
+ * provide data have to be able to deal with loss of individual
+ * disks, so they do their checking themselves.
+ */
+int md_check_ordering (mddev_t *mddev)
+{
+	int i, c;
+	mdk_rdev_t *rdev;
+	struct md_list_head *tmp;
 
 	/*
-	 * The superblock constant part has to be the same
-	 * for all disks in the array.
+	 * First, all devices must be fully functional
 	 */
-	sb = NULL;
-	for (i = 0; i < N; i++) {
-		if (!disks[i].sb)
-			continue;
-		if (!sb) {
-			sb = disks[i].sb;
-			continue;
-		}
-		if (memcmp(sb,
-			   disks[i].sb, MD_SB_GENERIC_CONSTANT_WORDS * 4)) {
-			printk (INCONSISTENT);
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->faulty) {
+			printk("md: md%d's device %s faulty, aborting.\n",
+				mdidx(mddev), partition_name(rdev->dev));
 			goto abort;
 		}
 	}
 
-	/*
-	 * OK, we have all disks and the array is ready to run. Let's
-	 * find the freshest superblock, that one will be the superblock
-	 * that represents the whole array.
-	 */
-	if ((sb = mddev->sb = (md_superblock_t *) __get_free_page (GFP_KERNEL)) == NULL)
+	c = 0;
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		c++;
+	}
+	if (c != mddev->nb_dev) {
+		MD_BUG();
 		goto abort;
-	freshest = NULL;
-	for (i = 0; i < N; i++) {
-		if (!disks[i].sb)
-			continue;
-		if (!freshest) {
-			freshest = disks[i].sb;
-			continue;
-		}
-		/*
-		 * Find the newest superblock version
-		 */
-		if (disks[i].sb->utime != freshest->utime) {
-			out_of_date = 1;
-			if (disks[i].sb->utime > freshest->utime)
-				freshest = disks[i].sb;
-		}
 	}
-	if (out_of_date)
-		printk(OUT_OF_DATE);
-	memcpy (sb, freshest, sizeof(*freshest));
-
-	/*
-	 * Check if we can support this RAID array
-	 */
-	if (sb->major_version != MD_MAJOR_VERSION ||
-			sb->minor_version > MD_MINOR_VERSION) {
-
-		printk (OLD_VERSION, kdevname(MKDEV(MD_MAJOR, minor)),
-				sb->major_version, sb->minor_version,
-				sb->patch_version);
+	if (mddev->nb_dev != mddev->sb->raid_disks) {
+		printk("md: md%d, array needs %d disks, has %d, aborting.\n",
+			mdidx(mddev), mddev->sb->raid_disks, mddev->nb_dev);
 		goto abort;
 	}
-
 	/*
-	 * We need to add this as a superblock option.
+	 * Now the numbering check
 	 */
-#if SUPPORT_RECONSTRUCTION
-	if (sb->state != (1 << MD_SB_CLEAN)) {
-		if (sb->level == 1) {
-			printk (NOT_CLEAN, kdevname(MKDEV(MD_MAJOR, minor)));
+	for (i = 0; i < mddev->nb_dev; i++) {
+		c = 0;
+		ITERATE_RDEV(mddev,rdev,tmp) {
+			if (rdev->desc_nr == i)
+				c++;
+		}
+		if (c == 0) {
+			printk("md: md%d, missing disk #%d, aborting.\n",
+				mdidx(mddev), i);
 			goto abort;
-		} else
-			printk (NOT_CLEAN_IGNORE, kdevname(MKDEV(MD_MAJOR, minor)));
-	}
-#else
-	if (sb->state != (1 << MD_SB_CLEAN)) {
-		printk (NOT_CLEAN, kdevname(MKDEV(MD_MAJOR, minor)));
-		goto abort;
-	}
-#endif /* SUPPORT_RECONSTRUCTION */
-
-	switch (sb->level) {
-		case 1:
-			md_size[minor] = sb->size;
-			md_maxreadahead[minor] = MD_DEFAULT_DISK_READAHEAD;
-			break;
-		case 4:
-		case 5:
-			md_size[minor] = sb->size * (sb->raid_disks - 1);
-			md_maxreadahead[minor] = MD_DEFAULT_DISK_READAHEAD * (sb->raid_disks - 1);
-			break;
-		default:
-			printk (UNKNOWN_LEVEL, kdevname(MKDEV(MD_MAJOR, minor)),
-					sb->level);
+		}
+		if (c > 1) {
+			printk("md: md%d, too many disks #%d, aborting.\n",
+				mdidx(mddev), i);
 			goto abort;
+		}
 	}
 	return 0;
 abort:
-	free_sb(mddev);
 	return 1;
 }
 
-#undef INCONSISTENT
-#undef OUT_OF_DATE
-#undef OLD_VERSION
-#undef NOT_CLEAN
-#undef OLD_LEVEL
-
-int md_update_sb(int minor)
+static void remove_descriptor (mdp_disk_t *disk, mdp_super_t *sb)
 {
-	struct md_dev *mddev = md_dev + minor;
-	struct buffer_head *bh;
-	md_superblock_t *sb = mddev->sb;
-	struct real_dev *realdev;
-	kdev_t dev;
-	int i;
-	u32 sb_offset;
+	if (disk_active(disk)) {
+		sb->working_disks--;
+	} else {
+		if (disk_spare(disk)) {
+			sb->spare_disks--;
+			sb->working_disks--;
+		} else	{
+			sb->failed_disks--;
+		}
+	}
+	sb->nr_disks--;
+	disk->major = 0;
+	disk->minor = 0;
+	mark_disk_removed(disk);
+}
 
-	sb->utime = CURRENT_TIME;
-	for (i = 0; i < mddev->nb_dev; i++) {
-		realdev = mddev->devices + i;
-		if (!realdev->sb)
-			continue;
-		dev = realdev->dev;
-		sb_offset = realdev->sb_offset;
-		set_blocksize(dev, MD_SB_BYTES);
-		printk("md: updating raid superblock on device %s, sb_offset == %u\n", kdevname(dev), sb_offset);
-		bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
-		if (bh) {
-			sb = (md_superblock_t *) bh->b_data;
-			memcpy(sb, mddev->sb, MD_SB_BYTES);
-			memcpy(&sb->descriptor, sb->disks + realdev->sb->descriptor.number, MD_SB_DESCRIPTOR_WORDS * 4);
-			mark_buffer_uptodate(bh, 1);
-			mark_buffer_dirty(bh, 1);
-			ll_rw_block(WRITE, 1, &bh);
-			wait_on_buffer(bh);
-			bforget(bh);
-			fsync_dev(dev);
-			invalidate_buffers(dev);
-		} else
-			printk(KERN_ERR "md: getblk failed for device %s\n", kdevname(dev));
+#define BAD_MAGIC KERN_ERR \
+"md: invalid raid superblock magic on %s\n"
+
+#define BAD_MINOR KERN_ERR \
+"md: %s: invalid raid minor (%x)\n"
+
+#define OUT_OF_MEM KERN_ALERT \
+"md: out of memory.\n"
+
+#define NO_SB KERN_ERR \
+"md: disabled device %s, could not read superblock.\n"
+
+#define BAD_CSUM KERN_WARNING \
+"md: invalid superblock checksum on %s\n"
+
+static int alloc_array_sb (mddev_t * mddev)
+{
+	if (mddev->sb) {
+		MD_BUG();
+		return 0;
 	}
+
+	mddev->sb = (mdp_super_t *) __get_free_page (GFP_KERNEL);
+	if (!mddev->sb)
+		return -ENOMEM;
+	md_clear_page((unsigned long)mddev->sb);
 	return 0;
 }
 
-static int do_md_run (int minor, int repart)
+static int alloc_disk_sb (mdk_rdev_t * rdev)
 {
-  int pnum, i, min, factor, err;
+	if (rdev->sb)
+		MD_BUG();
 
-  if (!md_dev[minor].nb_dev)
-    return -EINVAL;
-  
-  if (md_dev[minor].pers)
-    return -EBUSY;
-
-  md_dev[minor].repartition=repart;
-  
-  if ((pnum=PERSONALITY(&md_dev[minor]) >> (PERSONALITY_SHIFT))
-      >= MAX_PERSONALITY)
-    return -EINVAL;
-
-  /* Only RAID-1 and RAID-5 can have MD devices as underlying devices */
-  if (pnum != (RAID1 >> PERSONALITY_SHIFT) && pnum != (RAID5 >> PERSONALITY_SHIFT)){
-	  for (i = 0; i < md_dev [minor].nb_dev; i++)
-		  if (MAJOR (md_dev [minor].devices [i].dev) == MD_MAJOR)
-			  return -EINVAL;
-  }
-  if (!pers[pnum])
-  {
-#ifdef CONFIG_KMOD
-    char module_name[80];
-    sprintf (module_name, "md-personality-%d", pnum);
-    request_module (module_name);
-    if (!pers[pnum])
-#endif
-      return -EINVAL;
-  }
-  
-  factor = min = 1 << FACTOR_SHIFT(FACTOR((md_dev+minor)));
-  
-  for (i=0; i<md_dev[minor].nb_dev; i++)
-    if (md_dev[minor].devices[i].size<min)
-    {
-      printk ("Dev %s smaller than %dk, cannot shrink\n",
-	      partition_name (md_dev[minor].devices[i].dev), min);
-      return -EINVAL;
-    }
-
-  for (i=0; i<md_dev[minor].nb_dev; i++) {
-    fsync_dev(md_dev[minor].devices[i].dev);
-    invalidate_buffers(md_dev[minor].devices[i].dev);
-  }
-  
-  /* Resize devices according to the factor. It is used to align
-     partitions size on a given chunk size. */
-  md_size[minor]=0;
-
-  /*
-   * Analyze the raid superblock
-   */ 
-  if (analyze_sbs(minor, pnum))
-    return -EINVAL;
+	rdev->sb = (mdp_super_t *) __get_free_page(GFP_KERNEL);
+	if (!rdev->sb) {
+		printk (OUT_OF_MEM);
+		return -EINVAL;
+	}
+	md_clear_page((unsigned long)rdev->sb);
 
-  md_dev[minor].pers=pers[pnum];
-  
-  if ((err=md_dev[minor].pers->run (minor, md_dev+minor)))
-  {
-    md_dev[minor].pers=NULL;
-    free_sb(md_dev + minor);
-    return (err);
-  }
-
-  if (pnum != RAID0 >> PERSONALITY_SHIFT && pnum != LINEAR >> PERSONALITY_SHIFT)
-  {
-    md_dev[minor].sb->state &= ~(1 << MD_SB_CLEAN);
-    md_update_sb(minor);
-  }
-
-  /* FIXME : We assume here we have blocks
-     that are twice as large as sectors.
-     THIS MAY NOT BE TRUE !!! */
-  md_hd_struct[minor].start_sect=0;
-  md_hd_struct[minor].nr_sects=md_size[minor]<<1;
-  
-  read_ahead[MD_MAJOR] = 128;
-  return (0);
+	return 0;
 }
 
-static int do_md_stop (int minor, struct inode *inode)
+static void free_disk_sb (mdk_rdev_t * rdev)
 {
-	int i;
-  
-	if (inode->i_count>1 || md_dev[minor].busy>1) {
-		/*
-		 * ioctl : one open channel
-		 */
-		printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n",
-				minor, inode->i_count, md_dev[minor].busy);
-		return -EBUSY;
-	}
-  
-	if (md_dev[minor].pers) {
-		/*
-		 * It is safe to call stop here, it only frees private
-		 * data. Also, it tells us if a device is unstoppable
-		 * (eg. resyncing is in progress)
-		 */
-		if (md_dev[minor].pers->stop (minor, md_dev+minor))
-			return -EBUSY;
-		/*
-		 *  The device won't exist anymore -> flush it now
-		 */
-		fsync_dev (inode->i_rdev);
-		invalidate_buffers (inode->i_rdev);
-		if (md_dev[minor].sb) {
-			md_dev[minor].sb->state |= 1 << MD_SB_CLEAN;
-			md_update_sb(minor);
-		}
+	if (rdev->sb) {
+		free_page((unsigned long) rdev->sb);
+		rdev->sb = NULL;
+		rdev->sb_offset = 0;
+		rdev->size = 0;
+	} else {
+		if (!rdev->faulty)
+			MD_BUG();
 	}
-  
-	/* Remove locks. */
-	if (md_dev[minor].sb)
-	free_sb(md_dev + minor);
-	for (i=0; i<md_dev[minor].nb_dev; i++)
-		clear_inode (md_dev[minor].devices[i].inode);
-
-	md_dev[minor].nb_dev=md_size[minor]=0;
-	md_hd_struct[minor].nr_sects=0;
-	md_dev[minor].pers=NULL;
-  
-	read_ahead[MD_MAJOR] = 128;
-  
-	return (0);
 }
 
-static int do_md_add (int minor, kdev_t dev)
+static void mark_rdev_faulty (mdk_rdev_t * rdev)
 {
-	int i;
-	int hot_add=0;
-	struct real_dev *realdev;
+	if (!rdev) {
+		MD_BUG();
+		return;
+	}
+	free_disk_sb(rdev);
+	rdev->faulty = 1;
+}
 
-	if (md_dev[minor].nb_dev==MAX_REAL)
-		return -EINVAL;
+static int read_disk_sb (mdk_rdev_t * rdev)
+{
+	int ret = -EINVAL;
+	struct buffer_head *bh = NULL;
+	kdev_t dev = rdev->dev;
+	mdp_super_t *sb;
+	u32 sb_offset;
 
-	if (!fs_may_mount (dev))
+	if (!rdev->sb) {
+		MD_BUG();
+		goto abort;
+	}	
+	
+	/*
+	 * Calculate the position of the superblock,
+	 * it's at the end of the disk
+	 */
+	sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1);
+	rdev->sb_offset = sb_offset;
+	printk("(read) %s's sb offset: %d", partition_name(dev),
+							 sb_offset);
+	fsync_dev(dev);
+	set_blocksize (dev, MD_SB_BYTES);
+	bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
+
+	if (bh) {
+		sb = (mdp_super_t *) bh->b_data;
+		memcpy (rdev->sb, sb, MD_SB_BYTES);
+	} else {
+		printk (NO_SB,partition_name(rdev->dev));
+		goto abort;
+	}
+	printk(" [events: %08lx]\n", (unsigned long)get_unaligned(&rdev->sb->events));
+	ret = 0;
+abort:
+	if (bh)
+		brelse (bh);
+	return ret;
+}
+
+static unsigned int calc_sb_csum (mdp_super_t * sb)
+{
+	unsigned int disk_csum, csum;
+
+	disk_csum = sb->sb_csum;
+	sb->sb_csum = 0;
+	csum = csum_partial((void *)sb, MD_SB_BYTES, 0);
+	sb->sb_csum = disk_csum;
+	return csum;
+}
+
+/*
+ * Check one RAID superblock for generic plausibility
+ */
+
+static int check_disk_sb (mdk_rdev_t * rdev)
+{
+	mdp_super_t *sb;
+	int ret = -EINVAL;
+
+	sb = rdev->sb;
+	if (!sb) {
+		MD_BUG();
+		goto abort;
+	}
+
+	if (sb->md_magic != MD_SB_MAGIC) {
+		printk (BAD_MAGIC, partition_name(rdev->dev));
+		goto abort;
+	}
+
+	if (sb->md_minor >= MAX_MD_DEVS) {
+		printk (BAD_MINOR, partition_name(rdev->dev),
+							sb->md_minor);
+		goto abort;
+	}
+
+	if (calc_sb_csum(sb) != sb->sb_csum)
+		printk(BAD_CSUM, partition_name(rdev->dev));
+	ret = 0;
+abort:
+	return ret;
+}
+
+static kdev_t dev_unit(kdev_t dev)
+{
+	unsigned int mask;
+	struct gendisk *hd = find_gendisk(dev);
+
+	if (!hd)
+		return 0;
+	mask = ~((1 << hd->minor_shift) - 1);
+
+	return MKDEV(MAJOR(dev), MINOR(dev) & mask);
+}
+
+static mdk_rdev_t * match_dev_unit(mddev_t *mddev, kdev_t dev)
+{
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev;
+
+	ITERATE_RDEV(mddev,rdev,tmp)
+		if (dev_unit(rdev->dev) == dev_unit(dev))
+			return rdev;
+
+	return NULL;
+}
+
+static MD_LIST_HEAD(all_raid_disks);
+static MD_LIST_HEAD(pending_raid_disks);
+
+static void bind_rdev_to_array (mdk_rdev_t * rdev, mddev_t * mddev)
+{
+	mdk_rdev_t *same_pdev;
+
+	if (rdev->mddev) {
+		MD_BUG();
+		return;
+	}
+	same_pdev = match_dev_unit(mddev, rdev->dev);
+	if (same_pdev)
+		printk( KERN_WARNING
+"md%d: WARNING: %s appears to be on the same physical disk as %s. True\n"
+"     protection against single-disk failure might be compromised.\n",
+ 			mdidx(mddev), partition_name(rdev->dev),
+				partition_name(same_pdev->dev));
+		
+	md_list_add(&rdev->same_set, &mddev->disks);
+	rdev->mddev = mddev;
+	mddev->nb_dev++;
+	printk("bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev);
+}
+
+static void unbind_rdev_from_array (mdk_rdev_t * rdev)
+{
+	if (!rdev->mddev) {
+		MD_BUG();
+		return;
+	}
+	md_list_del(&rdev->same_set);
+	MD_INIT_LIST_HEAD(&rdev->same_set);
+	rdev->mddev->nb_dev--;
+	printk("unbind<%s,%d>\n", partition_name(rdev->dev),
+						 rdev->mddev->nb_dev);
+	rdev->mddev = NULL;
+}
+
+/*
+ * prevent the device from being mounted, repartitioned or
+ * otherwise reused by a RAID array (or any other kernel
+ * subsystem), by opening the device. [simply getting an
+ * inode is not enough, the SCSI module usage code needs
+ * an explicit open() on the device]
+ */
+static int lock_rdev (mdk_rdev_t *rdev)
+{
+	int err = 0;
+
+	/*
+	 * First insert a dummy inode.
+	 */
+	if (rdev->inode)
+		MD_BUG();
+	rdev->inode = get_empty_inode();
+	if (!rdev->inode)
+		return -ENOMEM;
+ 	/*
+	 * we dont care about any other fields
+	 */
+	rdev->inode->i_dev = rdev->inode->i_rdev = rdev->dev;
+	insert_inode_hash(rdev->inode);
+
+	memset(&rdev->filp, 0, sizeof(rdev->filp));
+	rdev->filp.f_mode = 3; /* read write */
+	return err;
+}
+
+static void unlock_rdev (mdk_rdev_t *rdev)
+{
+	if (!rdev->inode)
+		MD_BUG();
+	iput(rdev->inode);
+	rdev->inode = NULL;
+}
+
+static void export_rdev (mdk_rdev_t * rdev)
+{
+	printk("export_rdev(%s)\n",partition_name(rdev->dev));
+	if (rdev->mddev)
+		MD_BUG();
+	unlock_rdev(rdev);
+	free_disk_sb(rdev);
+	md_list_del(&rdev->all);
+	MD_INIT_LIST_HEAD(&rdev->all);
+	if (rdev->pending.next != &rdev->pending) {
+		printk("(%s was pending)\n",partition_name(rdev->dev));
+		md_list_del(&rdev->pending);
+		MD_INIT_LIST_HEAD(&rdev->pending);
+	}
+	rdev->dev = 0;
+	rdev->faulty = 0;
+	kfree(rdev);
+}
+
+static void kick_rdev_from_array (mdk_rdev_t * rdev)
+{
+	unbind_rdev_from_array(rdev);
+	export_rdev(rdev);
+}
+
+static void export_array (mddev_t *mddev)
+{
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev;
+	mdp_super_t *sb = mddev->sb;
+
+	if (mddev->sb) {
+		mddev->sb = NULL;
+		free_page((unsigned long) sb);
+	}
+
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (!rdev->mddev) {
+			MD_BUG();
+			continue;
+		}
+		kick_rdev_from_array(rdev);
+	}
+	if (mddev->nb_dev)
+		MD_BUG();
+}
+
+#undef BAD_CSUM
+#undef BAD_MAGIC
+#undef OUT_OF_MEM
+#undef NO_SB
+
+static void print_desc(mdp_disk_t *desc)
+{
+	printk(" DISK<N:%d,%s(%d,%d),R:%d,S:%d>\n", desc->number,
+		partition_name(MKDEV(desc->major,desc->minor)),
+		desc->major,desc->minor,desc->raid_disk,desc->state);
+}
+
+static void print_sb(mdp_super_t *sb)
+{
+	int i;
+
+	printk("  SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n",
+		sb->major_version, sb->minor_version, sb->patch_version,
+		sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3,
+		sb->ctime);
+	printk("     L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level,
+		sb->size, sb->nr_disks, sb->raid_disks, sb->md_minor,
+		sb->layout, sb->chunk_size);
+	printk("     UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n",
+		sb->utime, sb->state, sb->active_disks, sb->working_disks,
+		sb->failed_disks, sb->spare_disks,
+		sb->sb_csum, (unsigned long)get_unaligned(&sb->events));
+
+	for (i = 0; i < MD_SB_DISKS; i++) {
+		mdp_disk_t *desc;
+
+		desc = sb->disks + i;
+		printk("     D %2d: ", i);
+		print_desc(desc);
+	}
+	printk("     THIS: ");
+	print_desc(&sb->this_disk);
+
+}
+
+static void print_rdev(mdk_rdev_t *rdev)
+{
+	printk(" rdev %s: O:%s, SZ:%08d F:%d DN:%d ",
+		partition_name(rdev->dev), partition_name(rdev->old_dev),
+		rdev->size, rdev->faulty, rdev->desc_nr);
+	if (rdev->sb) {
+		printk("rdev superblock:\n");
+		print_sb(rdev->sb);
+	} else
+		printk("no rdev superblock!\n");
+}
+
+void md_print_devices (void)
+{
+	struct md_list_head *tmp, *tmp2;
+	mdk_rdev_t *rdev;
+	mddev_t *mddev;
+
+	printk("\n");
+	printk("       **********************************\n");
+	printk("       * <COMPLETE RAID STATE PRINTOUT> *\n");
+	printk("       **********************************\n");
+	ITERATE_MDDEV(mddev,tmp) {
+		printk("md%d: ", mdidx(mddev));
+
+		ITERATE_RDEV(mddev,rdev,tmp2)
+			printk("<%s>", partition_name(rdev->dev));
+
+		if (mddev->sb) {
+			printk(" array superblock:\n");
+			print_sb(mddev->sb);
+		} else
+			printk(" no array superblock.\n");
+
+		ITERATE_RDEV(mddev,rdev,tmp2)
+			print_rdev(rdev);
+	}
+	printk("       **********************************\n");
+	printk("\n");
+}
+
+static int sb_equal ( mdp_super_t *sb1, mdp_super_t *sb2)
+{
+	int ret;
+	mdp_super_t *tmp1, *tmp2;
+
+	tmp1 = kmalloc(sizeof(*tmp1),GFP_KERNEL);
+	tmp2 = kmalloc(sizeof(*tmp2),GFP_KERNEL);
+
+	if (!tmp1 || !tmp2) {
+		ret = 0;
+		goto abort;
+	}
+
+	*tmp1 = *sb1;
+	*tmp2 = *sb2;
+
+	/*
+	 * nr_disks is not constant
+	 */
+	tmp1->nr_disks = 0;
+	tmp2->nr_disks = 0;
+
+	if (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4))
+		ret = 0;
+	else
+		ret = 1;
+
+abort:
+	if (tmp1)
+		kfree(tmp1);
+	if (tmp2)
+		kfree(tmp2);
+
+	return ret;
+}
+
+static int uuid_equal(mdk_rdev_t *rdev1, mdk_rdev_t *rdev2)
+{
+	if (	(rdev1->sb->set_uuid0 == rdev2->sb->set_uuid0) &&
+		(rdev1->sb->set_uuid1 == rdev2->sb->set_uuid1) &&
+		(rdev1->sb->set_uuid2 == rdev2->sb->set_uuid2) &&
+		(rdev1->sb->set_uuid3 == rdev2->sb->set_uuid3))
+
+		return 1;
+
+	return 0;
+}
+
+static mdk_rdev_t * find_rdev_all (kdev_t dev)
+{
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev;
+
+	tmp = all_raid_disks.next;
+	while (tmp != &all_raid_disks) {
+		rdev = md_list_entry(tmp, mdk_rdev_t, all);
+		if (rdev->dev == dev)
+			return rdev;
+		tmp = tmp->next;
+	}
+	return NULL;
+}
+
+#define GETBLK_FAILED KERN_ERR \
+"md: getblk failed for device %s\n"
+
+static int write_disk_sb(mdk_rdev_t * rdev)
+{
+	struct buffer_head *bh;
+	kdev_t dev;
+	u32 sb_offset, size;
+	mdp_super_t *sb;
+
+	if (!rdev->sb) {
+		MD_BUG();
+		return -1;
+	}
+	if (rdev->faulty) {
+		MD_BUG();
+		return -1;
+	}
+	if (rdev->sb->md_magic != MD_SB_MAGIC) {
+		MD_BUG();
+		return -1;
+	}
+
+	dev = rdev->dev;
+	sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1);
+	if (rdev->sb_offset != sb_offset) {
+		printk("%s's sb offset has changed from %d to %d, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset);
+		goto skip;
+	}
+	/*
+	 * If the disk went offline meanwhile and it's just a spare, then
+	 * it's size has changed to zero silently, and the MD code does
+	 * not yet know that it's faulty.
+	 */
+	size = calc_dev_size(dev, rdev->mddev, 1);
+	if (size != rdev->size) {
+		printk("%s's size has changed from %d to %d since import, skipping\n", partition_name(dev), rdev->size, size);
+		goto skip;
+	}
+
+	printk("(write) %s's sb offset: %d\n", partition_name(dev), sb_offset);
+	fsync_dev(dev);
+	set_blocksize(dev, MD_SB_BYTES);
+	bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
+	if (!bh) {
+		printk(GETBLK_FAILED, partition_name(dev));
+		return 1;
+	}
+	memset(bh->b_data,0,bh->b_size);
+	sb = (mdp_super_t *) bh->b_data;
+	memcpy(sb, rdev->sb, MD_SB_BYTES);
+
+	mark_buffer_uptodate(bh, 1);
+	mark_buffer_dirty(bh, 1);
+	ll_rw_block(WRITE, 1, &bh);
+	wait_on_buffer(bh);
+	brelse(bh);
+	fsync_dev(dev);
+skip:
+	return 0;
+}
+#undef GETBLK_FAILED KERN_ERR
+
+static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	int i, ok = 0;
+	mdp_disk_t *desc;
+
+	for (i = 0; i < MD_SB_DISKS; i++) {
+		desc = mddev->sb->disks + i;
+#if 0
+		if (disk_faulty(desc)) {
+			if (MKDEV(desc->major,desc->minor) == rdev->dev)
+				ok = 1;
+			continue;
+		}
+#endif
+		if (MKDEV(desc->major,desc->minor) == rdev->dev) {
+			rdev->sb->this_disk = *desc;
+			rdev->desc_nr = desc->number;
+			ok = 1;
+			break;
+		}
+	}
+
+	if (!ok) {
+		MD_BUG();
+	}
+}
+
+static int sync_sbs(mddev_t * mddev)
+{
+	mdk_rdev_t *rdev;
+	mdp_super_t *sb;
+	struct md_list_head *tmp;
+
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->faulty)
+			continue;
+		sb = rdev->sb;
+		*sb = *mddev->sb;
+		set_this_disk(mddev, rdev);
+		sb->sb_csum = calc_sb_csum(sb);
+	}
+	return 0;
+}
+
+int md_update_sb(mddev_t * mddev)
+{
+	int first, err, count = 100;
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev;
+	__u64 ev;
+
+repeat:
+	mddev->sb->utime = CURRENT_TIME;
+	ev = get_unaligned(&mddev->sb->events);
+	++ev;
+	put_unaligned(ev,&mddev->sb->events);
+	if (ev == (__u64)0) {
+		/*
+		 * oops, this 64-bit counter should never wrap.
+		 * Either we are in around ~1 trillion A.C., assuming
+		 * 1 reboot per second, or we have a bug:
+		 */
+		MD_BUG();
+		--ev;
+		put_unaligned(ev,&mddev->sb->events);
+	}
+	sync_sbs(mddev);
+
+	/*
+	 * do not write anything to disk if using
+	 * nonpersistent superblocks
+	 */
+	if (mddev->sb->not_persistent)
+		return 0;
+
+	printk(KERN_INFO "md: updating md%d RAID superblock on device\n",
+					mdidx(mddev));
+
+	first = 1;
+	err = 0;
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (!first) {
+			first = 0;
+			printk(", ");
+		}
+		if (rdev->faulty)
+			printk("(skipping faulty ");
+		printk("%s ", partition_name(rdev->dev));
+		if (!rdev->faulty) {
+			printk("[events: %08lx]",
+			       (unsigned long)get_unaligned(&rdev->sb->events));
+			err += write_disk_sb(rdev);
+		} else
+			printk(")\n");
+	}
+	printk(".\n");
+	if (err) {
+		printk("errors occured during superblock update, repeating\n");
+		if (--count)
+			goto repeat;
+		printk("excessive errors occured during superblock update, exiting\n");
+	}
+	return 0;
+}
+
+/*
+ * Import a device. If 'on_disk', then sanity check the superblock
+ *
+ * mark the device faulty if:
+ *
+ *   - the device is nonexistent (zero size)
+ *   - the device has no valid superblock
+ *
+ * a faulty rdev _never_ has rdev->sb set.
+ */
+static int md_import_device (kdev_t newdev, int on_disk)
+{
+	int err;
+	mdk_rdev_t *rdev;
+	unsigned int size;
+
+	if (find_rdev_all(newdev))
+		return -EEXIST;
+
+	rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
+	if (!rdev) {
+		printk("could not alloc mem for %s!\n", partition_name(newdev));
+		return -ENOMEM;
+	}
+	memset(rdev, 0, sizeof(*rdev));
+
+	if (!fs_may_mount(newdev)) {
+		printk("md: can not import %s, has active inodes!\n",
+			partition_name(newdev));
+		err = -EBUSY;
+		goto abort_free;
+	}
+
+	if ((err = alloc_disk_sb(rdev)))
+		goto abort_free;
+
+	rdev->dev = newdev;
+	if (lock_rdev(rdev)) {
+		printk("md: could not lock %s, zero-size? Marking faulty.\n",
+			partition_name(newdev));
+		err = -EINVAL;
+		goto abort_free;
+	}
+	rdev->desc_nr = -1;
+	rdev->faulty = 0;
+
+	size = 0;
+	if (blk_size[MAJOR(newdev)])
+		size = blk_size[MAJOR(newdev)][MINOR(newdev)];
+	if (!size) {
+		printk("md: %s has zero size, marking faulty!\n",
+				partition_name(newdev));
+		err = -EINVAL;
+		goto abort_free;
+	}
+
+	if (on_disk) {
+		if ((err = read_disk_sb(rdev))) {
+			printk("md: could not read %s's sb, not importing!\n",
+					partition_name(newdev));
+			goto abort_free;
+		}
+		if ((err = check_disk_sb(rdev))) {
+			printk("md: %s has invalid sb, not importing!\n",
+					partition_name(newdev));
+			goto abort_free;
+		}
+
+		rdev->old_dev = MKDEV(rdev->sb->this_disk.major,
+					rdev->sb->this_disk.minor);
+		rdev->desc_nr = rdev->sb->this_disk.number;
+	}
+	md_list_add(&rdev->all, &all_raid_disks);
+	MD_INIT_LIST_HEAD(&rdev->pending);
+
+	if (rdev->faulty && rdev->sb)
+		free_disk_sb(rdev);
+	return 0;
+
+abort_free:
+	if (rdev->sb) {
+		if (rdev->inode)
+			unlock_rdev(rdev);
+		free_disk_sb(rdev);
+	}
+	kfree(rdev);
+	return err;
+}
+
+/*
+ * Check a full RAID array for plausibility
+ */
+
+#define INCONSISTENT KERN_ERR \
+"md: fatal superblock inconsistency in %s -- removing from array\n"
+
+#define OUT_OF_DATE KERN_ERR \
+"md: superblock update time inconsistency -- using the most recent one\n"
+
+#define OLD_VERSION KERN_ALERT \
+"md: md%d: unsupported raid array version %d.%d.%d\n"
+
+#define NOT_CLEAN_IGNORE KERN_ERR \
+"md: md%d: raid array is not clean -- starting background reconstruction\n"
+
+#define UNKNOWN_LEVEL KERN_ERR \
+"md: md%d: unsupported raid level %d\n"
+
+static int analyze_sbs (mddev_t * mddev)
+{
+	int out_of_date = 0, i;
+	struct md_list_head *tmp, *tmp2;
+	mdk_rdev_t *rdev, *rdev2, *freshest;
+	mdp_super_t *sb;
+
+	/*
+	 * Verify the RAID superblock on each real device
+	 */
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->faulty) {
+			MD_BUG();
+			goto abort;
+		}
+		if (!rdev->sb) {
+			MD_BUG();
+			goto abort;
+		}
+		if (check_disk_sb(rdev))
+			goto abort;
+	}
+
+	/*
+	 * The superblock constant part has to be the same
+	 * for all disks in the array.
+	 */
+	sb = NULL;
+
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (!sb) {
+			sb = rdev->sb;
+			continue;
+		}
+		if (!sb_equal(sb, rdev->sb)) {
+			printk (INCONSISTENT, partition_name(rdev->dev));
+			kick_rdev_from_array(rdev);
+			continue;
+		}
+	}
+
+	/*
+	 * OK, we have all disks and the array is ready to run. Let's
+	 * find the freshest superblock, that one will be the superblock
+	 * that represents the whole array.
+	 */
+	if (!mddev->sb)
+		if (alloc_array_sb(mddev))
+			goto abort;
+	sb = mddev->sb;
+	freshest = NULL;
+
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		__u64 ev1, ev2;
+		/*
+		 * if the checksum is invalid, use the superblock
+		 * only as a last resort. (decrease it's age by
+		 * one event)
+		 */
+		if (calc_sb_csum(rdev->sb) != rdev->sb->sb_csum) {
+			__u64 ev = get_unaligned(&rdev->sb->events);
+			if (ev != (__u64)0) {
+				--ev;
+				put_unaligned(ev,&rdev->sb->events);
+			}
+		}
+
+		printk("%s's event counter: %08lx\n", partition_name(rdev->dev),
+		       (unsigned long)get_unaligned(&rdev->sb->events));
+		if (!freshest) {
+			freshest = rdev;
+			continue;
+		}
+		/*
+		 * Find the newest superblock version
+		 */
+		ev1 = get_unaligned(&rdev->sb->events);
+		ev2 = get_unaligned(&freshest->sb->events);
+		if (ev1 != ev2) {
+			out_of_date = 1;
+			if (ev1 > ev2)
+				freshest = rdev;
+		}
+	}
+	if (out_of_date) {
+		printk(OUT_OF_DATE);
+		printk("freshest: %s\n", partition_name(freshest->dev));
+	}
+	memcpy (sb, freshest->sb, sizeof(*sb));
+
+	/*
+	 * at this point we have picked the 'best' superblock
+	 * from all available superblocks.
+	 * now we validate this superblock and kick out possibly
+	 * failed disks.
+	 */
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		/*
+		 * Kick all non-fresh devices faulty
+		 */
+		__u64 ev1, ev2;
+		ev1 = get_unaligned(&rdev->sb->events);
+		ev2 = get_unaligned(&sb->events);
+		++ev1;
+		if (ev1 < ev2) {
+			printk("md: kicking non-fresh %s from array!\n",
+						partition_name(rdev->dev));
+			kick_rdev_from_array(rdev);
+			continue;
+		}
+	}
+
+	/*
+	 * Fix up changed device names ... but only if this disk has a
+	 * recent update time. Use faulty checksum ones too.
+	 */
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		__u64 ev1, ev2, ev3;
+		if (rdev->faulty) { /* REMOVEME */
+			MD_BUG();
+			goto abort;
+		}
+		ev1 = get_unaligned(&rdev->sb->events);
+		ev2 = get_unaligned(&sb->events);
+		ev3 = ev2;
+		--ev3;
+		if ((rdev->dev != rdev->old_dev) &&
+		    ((ev1 == ev2) || (ev1 == ev3))) {
+			mdp_disk_t *desc;
+
+			printk("md: device name has changed from %s to %s since last import!\n", partition_name(rdev->old_dev), partition_name(rdev->dev));
+			if (rdev->desc_nr == -1) {
+				MD_BUG();
+				goto abort;
+			}
+			desc = &sb->disks[rdev->desc_nr];
+			if (rdev->old_dev != MKDEV(desc->major, desc->minor)) {
+				MD_BUG();
+				goto abort;
+			}
+			desc->major = MAJOR(rdev->dev);
+			desc->minor = MINOR(rdev->dev);
+			desc = &rdev->sb->this_disk;
+			desc->major = MAJOR(rdev->dev);
+			desc->minor = MINOR(rdev->dev);
+		}
+	}
+
+	/*
+	 * Remove unavailable and faulty devices ...
+	 *
+	 * note that if an array becomes completely unrunnable due to
+	 * missing devices, we do not write the superblock back, so the
+	 * administrator has a chance to fix things up. The removal thus
+	 * only happens if it's nonfatal to the contents of the array.
+	 */
+	for (i = 0; i < MD_SB_DISKS; i++) {
+		int found;
+		mdp_disk_t *desc;
+		kdev_t dev;
+
+		desc = sb->disks + i;
+		dev = MKDEV(desc->major, desc->minor);
+
+		/*
+		 * We kick faulty devices/descriptors immediately.
+		 */
+		if (disk_faulty(desc)) {
+			found = 0;
+			ITERATE_RDEV(mddev,rdev,tmp) {
+				if (rdev->desc_nr != desc->number)
+					continue;
+				printk("md%d: kicking faulty %s!\n",
+					mdidx(mddev),partition_name(rdev->dev));
+				kick_rdev_from_array(rdev);
+				found = 1;
+				break;
+			}
+			if (!found) {
+				if (dev == MKDEV(0,0))
+					continue;
+				printk("md%d: removing former faulty %s!\n",
+					mdidx(mddev), partition_name(dev));
+			}
+			remove_descriptor(desc, sb);
+			continue;
+		}
+
+		if (dev == MKDEV(0,0))
+			continue;
+		/*
+		 * Is this device present in the rdev ring?
+		 */
+		found = 0;
+		ITERATE_RDEV(mddev,rdev,tmp) {
+			if (rdev->desc_nr == desc->number) {
+				found = 1;
+				break;
+			}
+		}
+		if (found) 
+			continue;
+
+		printk("md%d: former device %s is unavailable, removing from array!\n", mdidx(mddev), partition_name(dev));
+		remove_descriptor(desc, sb);
+	}
+
+	/*
+	 * Double check wether all devices mentioned in the
+	 * superblock are in the rdev ring.
+	 */
+	for (i = 0; i < MD_SB_DISKS; i++) {
+		mdp_disk_t *desc;
+		kdev_t dev;
+
+		desc = sb->disks + i;
+		dev = MKDEV(desc->major, desc->minor);
+
+		if (dev == MKDEV(0,0))
+			continue;
+
+		if (disk_faulty(desc)) {
+			MD_BUG();
+			goto abort;
+		}
+
+		rdev = find_rdev(mddev, dev);
+		if (!rdev) {
+			MD_BUG();
+			goto abort;
+		}
+	}
+
+	/*
+	 * Do a final reality check.
+	 */
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->desc_nr == -1) {
+			MD_BUG();
+			goto abort;
+		}
+		/*
+		 * is the desc_nr unique?
+		 */
+		ITERATE_RDEV(mddev,rdev2,tmp2) {
+			if ((rdev2 != rdev) &&
+					(rdev2->desc_nr == rdev->desc_nr)) {
+				MD_BUG();
+				goto abort;
+			}
+		}
+		/*
+		 * is the device unique?
+		 */
+		ITERATE_RDEV(mddev,rdev2,tmp2) {
+			if ((rdev2 != rdev) &&
+					(rdev2->dev == rdev->dev)) {
+				MD_BUG();
+				goto abort;
+			}
+		}
+	}
+
+	/*
+	 * Check if we can support this RAID array
+	 */
+	if (sb->major_version != MD_MAJOR_VERSION ||
+			sb->minor_version > MD_MINOR_VERSION) {
+
+		printk (OLD_VERSION, mdidx(mddev), sb->major_version,
+				sb->minor_version, sb->patch_version);
+		goto abort;
+	}
+
+	if ((sb->state != (1 << MD_SB_CLEAN)) && ((sb->level == 1) ||
+			(sb->level == 4) || (sb->level == 5)))
+		printk (NOT_CLEAN_IGNORE, mdidx(mddev));
+
+	return 0;
+abort:
+	return 1;
+}
+
+#undef INCONSISTENT
+#undef OUT_OF_DATE
+#undef OLD_VERSION
+#undef OLD_LEVEL
+
+static int device_size_calculation (mddev_t * mddev)
+{
+	int data_disks = 0, persistent;
+	unsigned int readahead;
+	mdp_super_t *sb = mddev->sb;
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev;
+
+	/*
+	 * Do device size calculation. Bail out if too small.
+	 * (we have to do this after having validated chunk_size,
+	 * because device size has to be modulo chunk_size)
+	 */ 
+	persistent = !mddev->sb->not_persistent;
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->faulty)
+			continue;
+		if (rdev->size) {
+			MD_BUG();
+			continue;
+		}
+		rdev->size = calc_dev_size(rdev->dev, mddev, persistent);
+		if (rdev->size < sb->chunk_size / 1024) {
+			printk (KERN_WARNING
+				"Dev %s smaller than chunk_size: %dk < %dk\n",
+				partition_name(rdev->dev),
+				rdev->size, sb->chunk_size / 1024);
+			return -EINVAL;
+		}
+	}
+
+	switch (sb->level) {
+		case -3:
+			data_disks = 1;
+			break;
+		case -2:
+			data_disks = 1;
+			break;
+		case -1:
+			zoned_raid_size(mddev);
+			data_disks = 1;
+			break;
+		case 0:
+			zoned_raid_size(mddev);
+			data_disks = sb->raid_disks;
+			break;
+		case 1:
+			data_disks = 1;
+			break;
+		case 4:
+		case 5:
+			data_disks = sb->raid_disks-1;
+			break;
+		default:
+			printk (UNKNOWN_LEVEL, mdidx(mddev), sb->level);
+			goto abort;
+	}
+	if (!md_size[mdidx(mddev)])
+		md_size[mdidx(mddev)] = sb->size * data_disks;
+
+	readahead = MD_READAHEAD;
+	if ((sb->level == 0) || (sb->level == 4) || (sb->level == 5))
+		readahead = mddev->sb->chunk_size * 4 * data_disks;
+		if (readahead < data_disks * MAX_SECTORS*512*2) 
+			readahead = data_disks * MAX_SECTORS*512*2;
+	else {
+		if (sb->level == -3)
+			readahead = 0;
+	}
+	md_maxreadahead[mdidx(mddev)] = readahead;
+
+	printk(KERN_INFO "md%d: max total readahead window set to %dk\n",
+		mdidx(mddev), readahead/1024);
+
+	printk(KERN_INFO
+		"md%d: %d data-disks, max readahead per data-disk: %dk\n",
+			mdidx(mddev), data_disks, readahead/data_disks/1024);
+	return 0;
+abort:
+	return 1;
+}
+
+
+#define TOO_BIG_CHUNKSIZE KERN_ERR \
+"too big chunk_size: %d > %d\n"
+
+#define TOO_SMALL_CHUNKSIZE KERN_ERR \
+"too small chunk_size: %d < %ld\n"
+
+#define BAD_CHUNKSIZE KERN_ERR \
+"no chunksize specified, see 'man raidtab'\n"
+
+static int do_md_run (mddev_t * mddev)
+{
+	int pnum, err;
+	int chunk_size;
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev;
+
+
+	if (!mddev->nb_dev) {
+		MD_BUG();
+		return -EINVAL;
+	}
+  
+	if (mddev->pers)
+		return -EBUSY;
+
+	/*
+	 * Resize disks to align partitions size on a given
+	 * chunk size.
+	 */
+	md_size[mdidx(mddev)] = 0;
+
+	/*
+	 * Analyze all RAID superblock(s)
+	 */ 
+	if (analyze_sbs(mddev)) {
+		MD_BUG();
+		return -EINVAL;
+	}
+
+	chunk_size = mddev->sb->chunk_size;
+	pnum = level_to_pers(mddev->sb->level);
+
+	mddev->param.chunk_size = chunk_size;
+	mddev->param.personality = pnum;
+
+	if (chunk_size > MAX_CHUNK_SIZE) {
+		printk(TOO_BIG_CHUNKSIZE, chunk_size, MAX_CHUNK_SIZE);
+		return -EINVAL;
+	}
+	/*
+	 * chunk-size has to be a power of 2 and multiples of PAGE_SIZE
+	 */
+	if ( (1 << ffz(~chunk_size)) != chunk_size) {
+		MD_BUG();
+		return -EINVAL;
+	}
+	if (chunk_size < PAGE_SIZE) {
+		printk(TOO_SMALL_CHUNKSIZE, chunk_size, PAGE_SIZE);
+		return -EINVAL;
+	}
+
+	if (pnum >= MAX_PERSONALITY) {
+		MD_BUG();
+		return -EINVAL;
+	}
+
+	if ((pnum != RAID1) && (pnum != LINEAR) && !chunk_size) {
+		/*
+		 * 'default chunksize' in the old md code used to
+		 * be PAGE_SIZE, baaad.
+		 * we abort here to be on the safe side. We dont
+		 * want to continue the bad practice.
+		 */
+		printk(BAD_CHUNKSIZE);
+		return -EINVAL;
+	}
+
+	if (!pers[pnum])
+	{
+#ifdef CONFIG_KMOD
+		char module_name[80];
+		sprintf (module_name, "md-personality-%d", pnum);
+		request_module (module_name);
+		if (!pers[pnum])
+#endif
+			return -EINVAL;
+	}
+  
+	if (device_size_calculation(mddev))
+		return -EINVAL;
+
+	/*
+	 * Drop all container device buffers, from now on
+	 * the only valid external interface is through the md
+	 * device.
+	 */
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		if (rdev->faulty)
+			continue;
+		fsync_dev(rdev->dev);
+		invalidate_buffers(rdev->dev);
+	}
+  
+	mddev->pers = pers[pnum];
+  
+	err = mddev->pers->run(mddev);
+	if (err) {
+		printk("pers->run() failed ...\n");
+		mddev->pers = NULL;
+		return -EINVAL;
+	}
+
+	mddev->sb->state &= ~(1 << MD_SB_CLEAN);
+	md_update_sb(mddev);
+
+	/*
+	 * md_size has units of 1K blocks, which are
+	 * twice as large as sectors.
+	 */
+	md_hd_struct[mdidx(mddev)].start_sect = 0;
+	md_hd_struct[mdidx(mddev)].nr_sects = md_size[mdidx(mddev)] << 1;
+  
+	read_ahead[MD_MAJOR] = 1024;
+	return (0);
+}
+
+#undef TOO_BIG_CHUNKSIZE
+#undef BAD_CHUNKSIZE
+
+#define OUT(x) do { err = (x); goto out; } while (0)
+
+static int restart_array (mddev_t *mddev)
+{
+	int err = 0;
+ 
+	/*
+	 * Complain if it has no devices
+	 */
+	if (!mddev->nb_dev)
+		OUT(-ENXIO);
+
+	if (mddev->pers) {
+		if (!mddev->ro)
+			OUT(-EBUSY);
+
+		mddev->ro = 0;
+		set_device_ro(mddev_to_kdev(mddev), 0);
+
+		printk (KERN_INFO
+			"md%d switched to read-write mode.\n", mdidx(mddev));
+		/*
+		 * Kick recovery or resync if necessary
+		 */
+		md_recover_arrays();
+		if (mddev->pers->restart_resync)
+			mddev->pers->restart_resync(mddev);
+	} else
+		err = -EINVAL;
+ 
+out:
+	return err;
+}
+
+#define STILL_MOUNTED KERN_WARNING \
+"md: md%d still mounted.\n"
+
+static int do_md_stop (mddev_t * mddev, int ro)
+{
+	int err = 0, resync_interrupted = 0;
+	kdev_t dev = mddev_to_kdev(mddev);
+ 
+	if (!ro && !fs_may_mount (dev)) {
+		printk (STILL_MOUNTED, mdidx(mddev));
+		OUT(-EBUSY);
+	}
+  
+	/*
+	 * complain if it's already stopped
+	 */
+	if (!mddev->nb_dev)
+		OUT(-ENXIO);
+
+	if (mddev->pers) {
+		/*
+		 * It is safe to call stop here, it only frees private
+		 * data. Also, it tells us if a device is unstoppable
+		 * (eg. resyncing is in progress)
+		 */
+		if (mddev->pers->stop_resync)
+			if (mddev->pers->stop_resync(mddev))
+				resync_interrupted = 1;
+
+		if (mddev->recovery_running)
+			md_interrupt_thread(md_recovery_thread);
+
+		/*
+		 * This synchronizes with signal delivery to the
+		 * resync or reconstruction thread. It also nicely
+		 * hangs the process if some reconstruction has not
+		 * finished.
+		 */
+		down(&mddev->recovery_sem);
+		up(&mddev->recovery_sem);
+
+		/*
+		 *  sync and invalidate buffers because we cannot kill the
+		 *  main thread with valid IO transfers still around.
+		 *  the kernel lock protects us from new requests being
+		 *  added after invalidate_buffers().
+		 */
+		fsync_dev (mddev_to_kdev(mddev));
+		fsync_dev (dev);
+		invalidate_buffers (dev);
+
+		if (ro) {
+			if (mddev->ro)
+				OUT(-ENXIO);
+			mddev->ro = 1;
+		} else {
+			if (mddev->ro)
+				set_device_ro(dev, 0);
+			if (mddev->pers->stop(mddev)) {
+				if (mddev->ro)
+					set_device_ro(dev, 1);
+				OUT(-EBUSY);
+			}
+			if (mddev->ro)
+				mddev->ro = 0;
+		}
+		if (mddev->sb) {
+			/*
+			 * mark it clean only if there was no resync
+			 * interrupted.
+			 */
+			if (!mddev->recovery_running && !resync_interrupted) {
+				printk("marking sb clean...\n");
+				mddev->sb->state |= 1 << MD_SB_CLEAN;
+			}
+			md_update_sb(mddev);
+		}
+		if (ro)
+			set_device_ro(dev, 1);
+	}
+ 
+	/*
+	 * Free resources if final stop
+	 */
+	if (!ro) {
+		export_array(mddev);
+		md_size[mdidx(mddev)] = 0;
+		md_hd_struct[mdidx(mddev)].nr_sects = 0;
+		free_mddev(mddev);
+
+		printk (KERN_INFO "md%d stopped.\n", mdidx(mddev));
+	} else
+		printk (KERN_INFO
+			"md%d switched to read-only mode.\n", mdidx(mddev));
+out:
+	return err;
+}
+
+#undef OUT
+
+/*
+ * We have to safely support old arrays too.
+ */
+int detect_old_array (mdp_super_t *sb)
+{
+	if (sb->major_version > 0)
+		return 0;
+	if (sb->minor_version >= 90)
+		return 0;
+
+	return -EINVAL;
+}
+
+
+static void autorun_array (mddev_t *mddev)
+{
+	mdk_rdev_t *rdev;
+	struct md_list_head *tmp;
+	int err;
+
+	if (mddev->disks.prev == &mddev->disks) {
+		MD_BUG();
+		return;
+	}
+
+	printk("running: ");
+
+	ITERATE_RDEV(mddev,rdev,tmp) {
+		printk("<%s>", partition_name(rdev->dev));
+	}
+	printk("\nnow!\n");
+
+	err = do_md_run (mddev);
+	if (err) {
+		printk("do_md_run() returned %d\n", err);
+		/*
+		 * prevent the writeback of an unrunnable array
+		 */
+		mddev->sb_dirty = 0;
+		do_md_stop (mddev, 0);
+	}
+}
+
+/*
+ * lets try to run arrays based on all disks that have arrived
+ * until now. (those are in the ->pending list)
+ *
+ * the method: pick the first pending disk, collect all disks with
+ * the same UUID, remove all from the pending list and put them into
+ * the 'same_array' list. Then order this list based on superblock
+ * update time (freshest comes first), kick out 'old' disks and
+ * compare superblocks. If everything's fine then run it.
+ */
+static void autorun_devices (void)
+{
+	struct md_list_head candidates;
+	struct md_list_head *tmp;
+	mdk_rdev_t *rdev0, *rdev;
+	mddev_t *mddev;
+	kdev_t md_kdev;
+
+
+	printk("autorun ...\n");
+	while (pending_raid_disks.next != &pending_raid_disks) {
+		rdev0 = md_list_entry(pending_raid_disks.next,
+					 mdk_rdev_t, pending);
+
+		printk("considering %s ...\n", partition_name(rdev0->dev));
+		MD_INIT_LIST_HEAD(&candidates);
+		ITERATE_RDEV_PENDING(rdev,tmp) {
+			if (uuid_equal(rdev0, rdev)) {
+				if (!sb_equal(rdev0->sb, rdev->sb)) {
+					printk("%s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+					continue;
+				}
+				printk("  adding %s ...\n", partition_name(rdev->dev));
+				md_list_del(&rdev->pending);
+				md_list_add(&rdev->pending, &candidates);
+			}
+		}
+		/*
+		 * now we have a set of devices, with all of them having
+		 * mostly sane superblocks. It's time to allocate the
+		 * mddev.
+		 */
+		md_kdev = MKDEV(MD_MAJOR, rdev0->sb->md_minor);
+		mddev = kdev_to_mddev(md_kdev);
+		if (mddev) {
+			printk("md%d already running, cannot run %s\n",
+				 mdidx(mddev), partition_name(rdev0->dev));
+			ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp)
+				export_rdev(rdev);
+			continue;
+		}
+		mddev = alloc_mddev(md_kdev);
+		printk("created md%d\n", mdidx(mddev));
+		ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {
+			bind_rdev_to_array(rdev, mddev);
+			md_list_del(&rdev->pending);
+			MD_INIT_LIST_HEAD(&rdev->pending);
+		}
+		autorun_array(mddev);
+	}
+	printk("... autorun DONE.\n");
+}
+
+/*
+ * import RAID devices based on one partition
+ * if possible, the array gets run as well.
+ */
+
+#define BAD_VERSION KERN_ERR \
+"md: %s has RAID superblock version 0.%d, autodetect needs v0.90 or higher\n"
+
+#define OUT_OF_MEM KERN_ALERT \
+"md: out of memory.\n"
+
+#define NO_DEVICE KERN_ERR \
+"md: disabled device %s\n"
+
+#define AUTOADD_FAILED KERN_ERR \
+"md: auto-adding devices to md%d FAILED (error %d).\n"
+
+#define AUTOADD_FAILED_USED KERN_ERR \
+"md: cannot auto-add device %s to md%d, already used.\n"
+
+#define AUTORUN_FAILED KERN_ERR \
+"md: auto-running md%d FAILED (error %d).\n"
+
+#define MDDEV_BUSY KERN_ERR \
+"md: cannot auto-add to md%d, already running.\n"
+
+#define AUTOADDING KERN_INFO \
+"md: auto-adding devices to md%d, based on %s's superblock.\n"
+
+#define AUTORUNNING KERN_INFO \
+"md: auto-running md%d.\n"
+
+static int autostart_array (kdev_t startdev)
+{
+	int err = -EINVAL, i;
+	mdp_super_t *sb = NULL;
+	mdk_rdev_t *start_rdev = NULL, *rdev;
+
+	if (md_import_device(startdev, 1)) {
+		printk("could not import %s!\n", partition_name(startdev));
+		goto abort;
+	}
+
+	start_rdev = find_rdev_all(startdev);
+	if (!start_rdev) {
+		MD_BUG();
+		goto abort;
+	}
+	if (start_rdev->faulty) {
+		printk("can not autostart based on faulty %s!\n",
+						partition_name(startdev));
+		goto abort;
+	}
+	md_list_add(&start_rdev->pending, &pending_raid_disks);
+
+	sb = start_rdev->sb;
+
+	err = detect_old_array(sb);
+	if (err) {
+		printk("array version is too old to be autostarted, use raidtools 0.90 mkraid --upgrade\nto upgrade the array without data loss!\n");
+		goto abort;
+	}
+
+	for (i = 0; i < MD_SB_DISKS; i++) {
+		mdp_disk_t *desc;
+		kdev_t dev;
+
+		desc = sb->disks + i;
+		dev = MKDEV(desc->major, desc->minor);
+
+		if (dev == MKDEV(0,0))
+			continue;
+		if (dev == startdev)
+			continue;
+		if (md_import_device(dev, 1)) {
+			printk("could not import %s, trying to run array nevertheless.\n", partition_name(dev));
+			continue;
+		}
+		rdev = find_rdev_all(dev);
+		if (!rdev) {
+			MD_BUG();
+			goto abort;
+		}
+		md_list_add(&rdev->pending, &pending_raid_disks);
+	}
+
+	/*
+	 * possibly return codes
+	 */
+	autorun_devices();
+	return 0;
+
+abort:
+	if (start_rdev)
+		export_rdev(start_rdev);
+	return err;
+}
+
+#undef BAD_VERSION
+#undef OUT_OF_MEM
+#undef NO_DEVICE
+#undef AUTOADD_FAILED_USED
+#undef AUTOADD_FAILED
+#undef AUTORUN_FAILED
+#undef AUTOADDING
+#undef AUTORUNNING
+
+struct {
+	int set;
+	int noautodetect;
+
+} raid_setup_args md__initdata = { 0, 0 };
+
+/*
+ * Searches all registered partitions for autorun RAID arrays
+ * at boot time.
+ */
+void md__init autodetect_raid(void)
+{
+#ifdef CONFIG_AUTODETECT_RAID
+	struct gendisk *disk;
+	mdk_rdev_t *rdev;
+	int i;
+
+	if (raid_setup_args.noautodetect) {
+		printk(KERN_INFO "skipping autodetection of RAID arrays\n");
+		return;
+	}
+	printk(KERN_INFO "autodetecting RAID arrays\n");
+
+	for (disk = gendisk_head ; disk ; disk = disk->next) {
+		for (i = 0; i < disk->max_p*disk->nr_real; i++) {
+			kdev_t dev = MKDEV(disk->major,i);
+
+			if (disk->part[i].type != LINUX_RAID_PARTITION)
+				continue;
+
+			if (md_import_device(dev,1)) {
+				printk(KERN_ALERT "could not import %s!\n",
+							partition_name(dev));
+				continue;
+			}
+			/*
+			 * Sanity checks:
+			 */
+			rdev = find_rdev_all(dev);
+			if (!rdev) {
+				MD_BUG();
+				continue;
+			}
+			if (rdev->faulty) {
+				MD_BUG();
+				continue;
+			}
+			md_list_add(&rdev->pending, &pending_raid_disks);
+		}
+	}
+
+	autorun_devices();
+#endif
+}
+
+static int get_version (void * arg)
+{
+	mdu_version_t ver;
+
+	ver.major = MD_MAJOR_VERSION;
+	ver.minor = MD_MINOR_VERSION;
+	ver.patchlevel = MD_PATCHLEVEL_VERSION;
+
+	if (md_copy_to_user(arg, &ver, sizeof(ver)))
+		return -EFAULT;
+
+	return 0;
+}
+
+#define SET_FROM_SB(x) info.x = mddev->sb->x
+static int get_array_info (mddev_t * mddev, void * arg)
+{
+	mdu_array_info_t info;
+
+	if (!mddev->sb)
+		return -EINVAL;
+
+	SET_FROM_SB(major_version);
+	SET_FROM_SB(minor_version);
+	SET_FROM_SB(patch_version);
+	SET_FROM_SB(ctime);
+	SET_FROM_SB(level);
+	SET_FROM_SB(size);
+	SET_FROM_SB(nr_disks);
+	SET_FROM_SB(raid_disks);
+	SET_FROM_SB(md_minor);
+	SET_FROM_SB(not_persistent);
+
+	SET_FROM_SB(utime);
+	SET_FROM_SB(state);
+	SET_FROM_SB(active_disks);
+	SET_FROM_SB(working_disks);
+	SET_FROM_SB(failed_disks);
+	SET_FROM_SB(spare_disks);
+
+	SET_FROM_SB(layout);
+	SET_FROM_SB(chunk_size);
+
+	if (md_copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+
+	return 0;
+}
+#undef SET_FROM_SB
+
+#define SET_FROM_SB(x) info.x = mddev->sb->disks[nr].x
+static int get_disk_info (mddev_t * mddev, void * arg)
+{
+	mdu_disk_info_t info;
+	unsigned int nr;
+
+	if (!mddev->sb)
+		return -EINVAL;
+
+	if (md_copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+
+	nr = info.number;
+	if (nr >= mddev->sb->nr_disks)
+		return -EINVAL;
+
+	SET_FROM_SB(major);
+	SET_FROM_SB(minor);
+	SET_FROM_SB(raid_disk);
+	SET_FROM_SB(state);
+
+	if (md_copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+
+	return 0;
+}
+#undef SET_FROM_SB
+
+#define SET_SB(x) mddev->sb->disks[nr].x = info.x
+
+static int add_new_disk (mddev_t * mddev, void * arg)
+{
+	int err, size, persistent;
+	mdu_disk_info_t info;
+	mdk_rdev_t *rdev;
+	unsigned int nr;
+	kdev_t dev;
+
+	if (!mddev->sb)
+		return -EINVAL;
+
+	if (md_copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+
+	nr = info.number;
+	if (nr >= mddev->sb->nr_disks)
+		return -EINVAL;
+
+	dev = MKDEV(info.major,info.minor);
+
+	if (find_rdev_all(dev)) {
+		printk("device %s already used in a RAID array!\n", 
+				partition_name(dev));
+		return -EBUSY;
+	}
+
+	SET_SB(number);
+	SET_SB(major);
+	SET_SB(minor);
+	SET_SB(raid_disk);
+	SET_SB(state);
+ 
+	if ((info.state & (1<<MD_DISK_FAULTY))==0) {
+		err = md_import_device (dev, 0);
+		if (err) {
+			printk("md: error, md_import_device() returned %d\n", err);
+			return -EINVAL;
+		}
+		rdev = find_rdev_all(dev);
+		if (!rdev) {
+			MD_BUG();
+			return -EINVAL;
+		}
+ 
+		rdev->old_dev = dev;
+		rdev->desc_nr = info.number;
+ 
+		bind_rdev_to_array(rdev, mddev);
+ 
+		persistent = !mddev->sb->not_persistent;
+		if (!persistent)
+			printk("nonpersistent superblock ...\n");
+		if (!mddev->sb->chunk_size)
+			printk("no chunksize?\n");
+ 
+		size = calc_dev_size(dev, mddev, persistent);
+		rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent);
+ 
+		if (!mddev->sb->size || (mddev->sb->size > size))
+			mddev->sb->size = size;
+	}
+ 
+	/*
+	 * sync all other superblocks with the main superblock
+	 */
+	sync_sbs(mddev);
+
+	return 0;
+}
+#undef SET_SB
+
+static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
+{
+	int err;
+	mdk_rdev_t *rdev;
+	mdp_disk_t *disk;
+
+	if (!mddev->pers)
+		return -ENODEV;
+
+	printk("trying to remove %s from md%d ... \n",
+		partition_name(dev), mdidx(mddev));
+
+	if (!mddev->pers->diskop) {
+		printk("md%d: personality does not support diskops!\n",
+								 mdidx(mddev));
+		return -EINVAL;
+	}
+
+	rdev = find_rdev(mddev, dev);
+	if (!rdev)
+		return -ENXIO;
+
+	if (rdev->desc_nr == -1) {
+		MD_BUG();
+		return -EINVAL;
+	}
+	disk = &mddev->sb->disks[rdev->desc_nr];
+	if (disk_active(disk))
+		goto busy;
+	if (disk_removed(disk)) {
+		MD_BUG();
+		return -EINVAL;
+	}
+	
+	err = mddev->pers->diskop(mddev, &disk, DISKOP_HOT_REMOVE_DISK);
+	if (err == -EBUSY)
+		goto busy;
+	if (err) {
+		MD_BUG();
+		return -EINVAL;
+	}
+
+	remove_descriptor(disk, mddev->sb);
+	kick_rdev_from_array(rdev);
+	mddev->sb_dirty = 1;
+	md_update_sb(mddev);
+
+	return 0;
+busy:
+	printk("cannot remove active disk %s from md%d ... \n",
+		partition_name(dev), mdidx(mddev));
+	return -EBUSY;
+}
+
+static int hot_add_disk (mddev_t * mddev, kdev_t dev)
+{
+	int i, err, persistent;
+	unsigned int size;
+	mdk_rdev_t *rdev;
+	mdp_disk_t *disk;
+
+	if (!mddev->pers)
+		return -ENODEV;
+
+	printk("trying to hot-add %s to md%d ... \n",
+		partition_name(dev), mdidx(mddev));
+
+	if (!mddev->pers->diskop) {
+		printk("md%d: personality does not support diskops!\n",
+								 mdidx(mddev));
+		return -EINVAL;
+	}
+
+	persistent = !mddev->sb->not_persistent;
+	size = calc_dev_size(dev, mddev, persistent);
+
+	if (size < mddev->sb->size) {
+		printk("md%d: disk size %d blocks < array size %d\n",
+				mdidx(mddev), size, mddev->sb->size);
+		return -ENOSPC;
+	}
+
+	rdev = find_rdev(mddev, dev);
+	if (rdev)
+		return -EBUSY;
+
+	err = md_import_device (dev, 0);
+	if (err) {
+		printk("md: error, md_import_device() returned %d\n", err);
+		return -EINVAL;
+	}
+	rdev = find_rdev_all(dev);
+	if (!rdev) {
+		MD_BUG();
+		return -EINVAL;
+	}
+	if (rdev->faulty) {
+		printk("md: can not hot-add faulty %s disk to md%d!\n",
+				partition_name(dev), mdidx(mddev));
+		err = -EINVAL;
+		goto abort_export;
+	}
+	bind_rdev_to_array(rdev, mddev);
+
+	/*
+	 * The rest should better be atomic, we can have disk failures
+	 * noticed in interrupt contexts ...
+	 */
+	rdev->old_dev = dev;
+	rdev->size = size;
+	rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent);
+
+	disk = mddev->sb->disks + mddev->sb->raid_disks;
+	for (i = mddev->sb->raid_disks; i < MD_SB_DISKS; i++) {
+		disk = mddev->sb->disks + i;
+
+		if (!disk->major && !disk->minor)
+			break;
+		if (disk_removed(disk))
+			break;
+	}
+	if (i == MD_SB_DISKS) {
+		printk("md%d: can not hot-add to full array!\n", mdidx(mddev));
+		err = -EBUSY;
+		goto abort_unbind_export;
+	}
+
+	if (disk_removed(disk)) {
+		/*
+		 * reuse slot
+		 */
+		if (disk->number != i) {
+			MD_BUG();
+			err = -EINVAL;
+			goto abort_unbind_export;
+		}
+	} else {
+		disk->number = i;
+	}
+
+	disk->raid_disk = disk->number;
+	disk->major = MAJOR(dev);
+	disk->minor = MINOR(dev);
+
+	if (mddev->pers->diskop(mddev, &disk, DISKOP_HOT_ADD_DISK)) {
+		MD_BUG();
+		err = -EINVAL;
+		goto abort_unbind_export;
+	}
+
+	mark_disk_spare(disk);
+	mddev->sb->nr_disks++;
+	mddev->sb->spare_disks++;
+	mddev->sb->working_disks++;
+
+	mddev->sb_dirty = 1;
+
+	md_update_sb(mddev);
+
+	/*
+	 * Kick recovery, maybe this spare has to be added to the
+	 * array immediately.
+	 */
+	md_recover_arrays();
+
+	return 0;
+
+abort_unbind_export:
+	unbind_rdev_from_array(rdev);
+
+abort_export:
+	export_rdev(rdev);
+	return err;
+}
+
+#define SET_SB(x) mddev->sb->x = info.x
+static int set_array_info (mddev_t * mddev, void * arg)
+{
+	mdu_array_info_t info;
+
+	if (mddev->sb) {
+		printk("array md%d already has a superblock!\n", 
+				mdidx(mddev));
 		return -EBUSY;
+	}
+
+	if (md_copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+
+	if (alloc_array_sb(mddev))
+		return -ENOMEM;
+
+	mddev->sb->major_version = MD_MAJOR_VERSION;
+	mddev->sb->minor_version = MD_MINOR_VERSION;
+	mddev->sb->patch_version = MD_PATCHLEVEL_VERSION;
+	mddev->sb->ctime = CURRENT_TIME;
+
+	SET_SB(level);
+	SET_SB(size);
+	SET_SB(nr_disks);
+	SET_SB(raid_disks);
+	SET_SB(md_minor);
+	SET_SB(not_persistent);
+
+	SET_SB(state);
+	SET_SB(active_disks);
+	SET_SB(working_disks);
+	SET_SB(failed_disks);
+	SET_SB(spare_disks);
+
+	SET_SB(layout);
+	SET_SB(chunk_size);
+
+	mddev->sb->md_magic = MD_SB_MAGIC;
+
+	/*
+	 * Generate a 128 bit UUID
+	 */
+	get_random_bytes(&mddev->sb->set_uuid0, 4);
+	get_random_bytes(&mddev->sb->set_uuid1, 4);
+	get_random_bytes(&mddev->sb->set_uuid2, 4);
+	get_random_bytes(&mddev->sb->set_uuid3, 4);
+
+	return 0;
+}
+#undef SET_SB
+
+static int set_disk_info (mddev_t * mddev, void * arg)
+{
+	printk("not yet");
+	return -EINVAL;
+}
+
+static int clear_array (mddev_t * mddev)
+{
+	printk("not yet");
+	return -EINVAL;
+}
+
+static int write_raid_info (mddev_t * mddev)
+{
+	printk("not yet");
+	return -EINVAL;
+}
+
+static int protect_array (mddev_t * mddev)
+{
+	printk("not yet");
+	return -EINVAL;
+}
+
+static int unprotect_array (mddev_t * mddev)
+{
+	printk("not yet");
+	return -EINVAL;
+}
+
+static int set_disk_faulty (mddev_t *mddev, kdev_t dev)
+{
+	int ret;
+
+	fsync_dev(mddev_to_kdev(mddev));
+	ret = md_error(mddev_to_kdev(mddev), dev);
+	return ret;
+}
+
+static int md_ioctl (struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	unsigned int minor;
+	int err = 0;
+	struct hd_geometry *loc = (struct hd_geometry *) arg;
+	mddev_t *mddev = NULL;
+	kdev_t dev;
+
+	if (!md_capable_admin())
+		return -EACCES;
+
+	dev = inode->i_rdev;
+	minor = MINOR(dev);
+	if (minor >= MAX_MD_DEVS)
+		return -EINVAL;
+
+	/*
+	 * Commands dealing with the RAID driver but not any
+	 * particular array:
+	 */
+	switch (cmd)
+	{
+		case RAID_VERSION:
+			err = get_version((void *)arg);
+			goto done;
+
+		case PRINT_RAID_DEBUG:
+			err = 0;
+			md_print_devices();
+			goto done_unlock;
+
+		case BLKGETSIZE:   /* Return device size */
+			if (!arg) {
+				err = -EINVAL;
+				goto abort;
+			}
+			err = md_put_user(md_hd_struct[minor].nr_sects,
+						(long *) arg);
+			goto done;
+
+		case BLKFLSBUF:
+			fsync_dev(dev);
+			invalidate_buffers(dev);
+			goto done;
+
+		case BLKRASET:
+			if (arg > 0xff) {
+				err = -EINVAL;
+				goto abort;
+			}
+			read_ahead[MAJOR(dev)] = arg;
+			goto done;
+
+		case BLKRAGET:
+			if (!arg) {
+				err = -EINVAL;
+				goto abort;
+			}
+			err = md_put_user (read_ahead[
+				MAJOR(dev)], (long *) arg);
+			goto done;
+		default:
+	}
+
+	/*
+	 * Commands creating/starting a new array:
+	 */
+
+	mddev = kdev_to_mddev(dev);
+
+	switch (cmd)
+	{
+		case SET_ARRAY_INFO:
+		case START_ARRAY:
+			if (mddev) {
+				printk("array md%d already exists!\n",
+								mdidx(mddev));
+				err = -EEXIST;
+				goto abort;
+			}
+		default:
+	}
+
+	switch (cmd)
+	{
+		case SET_ARRAY_INFO:
+			mddev = alloc_mddev(dev);
+			if (!mddev) {
+				err = -ENOMEM;
+				goto abort;
+			}
+			/*
+			 * alloc_mddev() should possibly self-lock.
+			 */
+			err = lock_mddev(mddev);
+			if (err) {
+				printk("ioctl, reason %d, cmd %d\n", err, cmd);
+				goto abort;
+			}
+			err = set_array_info(mddev, (void *)arg);
+			if (err) {
+				printk("couldnt set array info. %d\n", err);
+				goto abort;
+			}
+			goto done_unlock;
+
+		case START_ARRAY:
+			/*
+			 * possibly make it lock the array ...
+			 */
+			err = autostart_array((kdev_t)arg);
+			if (err) {
+				printk("autostart %s failed!\n",
+					partition_name((kdev_t)arg));
+				goto abort;
+			}
+			goto done;
+
+		default:
+	}
+
+	/*
+	 * Commands querying/configuring an existing array:
+	 */
 
-	if (blk_size[MAJOR(dev)] == NULL || blk_size[MAJOR(dev)][MINOR(dev)] == 0) {
-		printk("md_add(): zero device size, huh, bailing out.\n");
-		return -EINVAL;
+	if (!mddev) {
+		err = -ENODEV;
+		goto abort;
+	}
+	err = lock_mddev(mddev);
+	if (err) {
+		printk("ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);
+		goto abort;
 	}
 
-	if (md_dev[minor].pers) {
-		/*
-		 * The array is already running, hot-add the drive, or
-		 * bail out:
-		 */
-		if (!md_dev[minor].pers->hot_add_disk)
-			return -EBUSY;
-		else
-			hot_add=1;
+	/*
+	 * Commands even a read-only array can execute:
+	 */
+	switch (cmd)
+	{
+		case GET_ARRAY_INFO:
+			err = get_array_info(mddev, (void *)arg);
+			goto done_unlock;
+
+		case GET_DISK_INFO:
+			err = get_disk_info(mddev, (void *)arg);
+			goto done_unlock;
+
+		case RESTART_ARRAY_RW:
+			err = restart_array(mddev);
+			goto done_unlock;
+
+		case STOP_ARRAY:
+			err = do_md_stop (mddev, 0);
+			goto done_unlock;
+
+		case STOP_ARRAY_RO:
+			err = do_md_stop (mddev, 1);
+			goto done_unlock;
+
+	/*
+	 * We have a problem here : there is no easy way to give a CHS
+	 * virtual geometry. We currently pretend that we have a 2 heads
+	 * 4 sectors (with a BIG number of cylinders...). This drives
+	 * dosfs just mad... ;-)
+	 */
+		case HDIO_GETGEO:
+			if (!loc) {
+				err = -EINVAL;
+				goto abort_unlock;
+			}
+			err = md_put_user (2, (char *) &loc->heads);
+			if (err)
+				goto abort_unlock;
+			err = md_put_user (4, (char *) &loc->sectors);
+			if (err)
+				goto abort_unlock;
+			err = md_put_user (md_hd_struct[mdidx(mddev)].nr_sects/8,
+						(short *) &loc->cylinders);
+			if (err)
+				goto abort_unlock;
+			err = md_put_user (md_hd_struct[minor].start_sect,
+						(long *) &loc->start);
+			goto done_unlock;
 	}
 
 	/*
-	 * Careful. We cannot increase nb_dev for a running array.
+	 * The remaining ioctls are changing the state of the
+	 * superblock, so we do not allow read-only arrays
+	 * here:
 	 */
-	i=md_dev[minor].nb_dev;
-	realdev = &md_dev[minor].devices[i];
-	realdev->dev=dev;
-  
-	/* Lock the device by inserting a dummy inode. This doesn't
-	   smell very good, but I need to be consistent with the
-	   mount stuff, specially with fs_may_mount. If someone have
-	   a better idea, please help ! */
-  
-	realdev->inode=get_empty_inode ();
-	if (!realdev->inode)
-		return -ENOMEM;
-	realdev->inode->i_dev=dev; 	/* don't care about other fields */
-	insert_inode_hash (realdev->inode);
-  
-	/* Sizes are now rounded at run time */
-  
-/*  md_dev[minor].devices[i].size=gen_real->sizes[MINOR(dev)]; HACKHACK*/
+	if (mddev->ro) {
+		err = -EROFS;
+		goto abort_unlock;
+	}
+
+	switch (cmd)
+	{
+		case CLEAR_ARRAY:
+			err = clear_array(mddev);
+			goto done_unlock;
+
+		case ADD_NEW_DISK:
+			err = add_new_disk(mddev, (void *)arg);
+			goto done_unlock;
+
+		case HOT_REMOVE_DISK:
+			err = hot_remove_disk(mddev, (kdev_t)arg);
+			goto done_unlock;
+
+		case HOT_ADD_DISK:
+			err = hot_add_disk(mddev, (kdev_t)arg);
+			goto done_unlock;
+
+		case SET_DISK_INFO:
+			err = set_disk_info(mddev, (void *)arg);
+			goto done_unlock;
+
+		case WRITE_RAID_INFO:
+			err = write_raid_info(mddev);
+			goto done_unlock;
+
+		case UNPROTECT_ARRAY:
+			err = unprotect_array(mddev);
+			goto done_unlock;
+
+		case PROTECT_ARRAY:
+			err = protect_array(mddev);
+			goto done_unlock;
+
+		case SET_DISK_FAULTY:
+			err = set_disk_faulty(mddev, (kdev_t)arg);
+			goto done_unlock;
 
-	realdev->size=blk_size[MAJOR(dev)][MINOR(dev)];
+		case RUN_ARRAY:
+		{
+			mdu_param_t param;
 
-	if (hot_add) {
-		/*
-		 * Check the superblock for consistency.
-		 * The personality itself has to check whether it's getting
-		 * added with the proper flags.  The personality has to be
-                 * checked too. ;)
-		 */
-		if (analyze_one_sb (realdev))
-			return -EINVAL;
-		/*
-		 * hot_add has to bump up nb_dev itself
-		 */
-		if (md_dev[minor].pers->hot_add_disk (&md_dev[minor], dev)) {
+			err = md_copy_from_user(&param, (mdu_param_t *)arg,
+							 sizeof(param));
+			if (err)
+				goto abort_unlock;
+
+			err = do_md_run (mddev);
 			/*
-			 * FIXME: here we should free up the inode and stuff
+			 * we have to clean up the mess if
+			 * the array cannot be run for some
+			 * reason ...
 			 */
-			printk ("FIXME\n");
-			return -EINVAL;
+			if (err) {
+				mddev->sb_dirty = 0;
+				do_md_stop (mddev, 0);
+			}
+			goto done_unlock;
 		}
-	} else
-		md_dev[minor].nb_dev++;
-
-	printk ("REGISTER_DEV %s to md%x done\n", partition_name(dev), minor);
-	return (0);
-}
-
-static int md_ioctl (struct inode *inode, struct file *file,
-                     unsigned int cmd, unsigned long arg)
-{
-  int minor, err;
-  struct hd_geometry *loc = (struct hd_geometry *) arg;
 
-  if (!capable(CAP_SYS_ADMIN))
-    return -EACCES;
-
-  if (((minor=MINOR(inode->i_rdev)) & 0x80) &&
-      (minor & 0x7f) < MAX_PERSONALITY &&
-      pers[minor & 0x7f] &&
-      pers[minor & 0x7f]->ioctl)
-    return (pers[minor & 0x7f]->ioctl (inode, file, cmd, arg));
-  
-  if (minor >= MAX_MD_DEV)
-    return -EINVAL;
+		default:
+			printk(KERN_WARNING "%s(pid %d) used obsolete MD ioctl, upgrade your software to use new ictls.\n", current->comm, current->pid);
+			err = -EINVAL;
+			goto abort_unlock;
+	}
 
-  switch (cmd)
-  {
-    case REGISTER_DEV:
-      return do_md_add (minor, to_kdev_t ((dev_t) arg));
-
-    case START_MD:
-      return do_md_run (minor, (int) arg);
-
-    case STOP_MD:
-      return do_md_stop (minor, inode);
-      
-    case BLKGETSIZE:   /* Return device size */
-    if  (!arg)  return -EINVAL;
-    err = put_user (md_hd_struct[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
-    if (err)
-      return err;
-    break;
-
-    
-    /* We have a problem here : there is no easy way to give a CHS
-       virtual geometry. We currently pretend that we have a 2 heads
-       4 sectors (with a BIG number of cylinders...). This drives dosfs
-       just mad... ;-) */
-    
-    case HDIO_GETGEO:
-    if (!loc)  return -EINVAL;
-    err = put_user (2, (char *) &loc->heads);
-    if (err)
-      return err;
-    err = put_user (4, (char *) &loc->sectors);
-    if (err)
-      return err;
-    err = put_user (md_hd_struct[minor].nr_sects/8, (short *) &loc->cylinders);
-    if (err)
-      return err;
-    err = put_user (md_hd_struct[MINOR(inode->i_rdev)].start_sect,
-		(long *) &loc->start);
-    if (err)
-      return err;
-    break;
-    
-    case BLKROSET:
-    case BLKROGET:
-    case BLKRAGET:
-    case BLKRASET:
-    case BLKFLSBUF:
-	  return blk_ioctl(inode->i_rdev, cmd, arg);
-    
-    default:
-    return -EINVAL;
-  }
+done_unlock:
+abort_unlock:
+	if (mddev)
+		unlock_mddev(mddev);
+	else
+		printk("huh11?\n");
 
-  return (0);
+	return err;
+done:
+	if (err)
+		printk("huh12?\n");
+abort:
+	return err;
 }
 
 static int md_open (struct inode *inode, struct file *file)
 {
-  int minor=MINOR(inode->i_rdev);
-
-  md_dev[minor].busy++;
-  return (0);			/* Always succeed */
-}
-
-
-static int md_release (struct inode *inode, struct file *file)
-{
-  int minor=MINOR(inode->i_rdev);
-  md_dev[minor].busy--;
-  return 0;
+	/*
+	 * Always succeed
+	 */
+	return (0);
 }
 
 static struct block_device_operations md_fops=
 {
 	open:		md_open,
-	release:	md_release,
 	ioctl:		md_ioctl,
 };
+ 
 
-int md_map (int minor, kdev_t *rdev, unsigned long *rsector, unsigned long size)
+int md_thread(void * arg)
 {
-  if ((unsigned int) minor >= MAX_MD_DEV)
-  {
-    printk ("Bad md device %d\n", minor);
-    return (-1);
-  }
-  
-  if (!md_dev[minor].pers)
-  {
-    printk ("Oops ! md%d not running, giving up !\n", minor);
-    return (-1);
-  }
+	mdk_thread_t *thread = arg;
 
-  return (md_dev[minor].pers->map(md_dev+minor, rdev, rsector, size));
-}
-  
-int md_make_request (int minor, int rw, struct buffer_head * bh)
-{
-	if (md_dev [minor].pers->make_request) {
-		if (buffer_locked(bh))
-			return 0;
-		set_bit(BH_Lock, &bh->b_state);
-		if (rw == WRITE) {
-			if (!buffer_dirty(bh)) {
-				bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
-				return 0;
-			}
+	md_lock_kernel();
+	exit_mm(current);
+	exit_files(current);
+	exit_fs(current);
+
+	/*
+	 * Detach thread
+	 */
+	sys_setsid();
+	sprintf(current->comm, thread->name);
+	md_init_signals();
+	md_flush_signals();
+	thread->tsk = current;
+
+	/*
+	 * md_thread is a 'system-thread', it's priority should be very
+	 * high. We avoid resource deadlocks individually in each
+	 * raid personality. (RAID5 does preallocation) We also use RR and
+	 * the very same RT priority as kswapd, thus we will never get
+	 * into a priority inversion deadlock.
+	 *
+	 * we definitely have to have equal or higher priority than
+	 * bdflush, otherwise bdflush will deadlock if there are too
+	 * many dirty RAID5 blocks.
+	 */
+	current->policy = SCHED_OTHER;
+	current->priority = 40;
+//	md_unlock_kernel();
+
+	up(thread->sem);
+
+	for (;;) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		add_wait_queue(&thread->wqueue, &wait);
+		if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
+			set_task_state(current, TASK_INTERRUPTIBLE);
+			dprintk("thread %p went to sleep.\n", thread);
+			schedule();
+			dprintk("thread %p woke up.\n", thread);
+			current->state = TASK_RUNNING;
 		}
-		if (rw == READ || rw == READA) {
-			if (buffer_uptodate(bh)) {
-				bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
-				return 0;
-			}
+		remove_wait_queue(&thread->wqueue, &wait);
+		clear_bit(THREAD_WAKEUP, &thread->flags);
+
+		if (thread->run) {
+			thread->run(thread->data);
+			run_task_queue(&tq_disk);
+		} else
+			break;
+		if (md_signal_pending(current)) {
+			printk("%8s(%d) flushing signals.\n", current->comm,
+				current->pid);
+			md_flush_signals();
 		}
-		return (md_dev[minor].pers->make_request(md_dev+minor, rw, bh));
-	} else {
-		make_request (MAJOR(bh->b_rdev), rw, bh);
-		return 0;
 	}
+	up(thread->sem);
+	return 0;
 }
 
-static void do_md_request (request_queue_t * q)
-{
-  printk ("Got md request, not good...");
-  return;
-}
-
-void md_wakeup_thread(struct md_thread *thread)
+void md_wakeup_thread(mdk_thread_t *thread)
 {
+	dprintk("waking up MD thread %p.\n", thread);
 	set_bit(THREAD_WAKEUP, &thread->flags);
 	wake_up(&thread->wqueue);
 }
 
-struct md_thread *md_register_thread (void (*run) (void *), void *data)
+mdk_thread_t *md_register_thread (void (*run) (void *),
+						void *data, const char *name)
 {
-	struct md_thread *thread = (struct md_thread *)
-		kmalloc(sizeof(struct md_thread), GFP_KERNEL);
+	mdk_thread_t *thread;
 	int ret;
 	DECLARE_MUTEX_LOCKED(sem);
 	
-	if (!thread) return NULL;
+	thread = (mdk_thread_t *) kmalloc
+				(sizeof(mdk_thread_t), GFP_KERNEL);
+	if (!thread)
+		return NULL;
 	
-	memset(thread, 0, sizeof(struct md_thread));
-	init_waitqueue_head(&thread->wqueue);
+	memset(thread, 0, sizeof(mdk_thread_t));
+	md_init_waitqueue_head(&thread->wqueue);
 	
 	thread->sem = &sem;
 	thread->run = run;
 	thread->data = data;
+	thread->name = name;
 	ret = kernel_thread(md_thread, thread, 0);
 	if (ret < 0) {
 		kfree(thread);
@@ -760,387 +2882,317 @@
 	return thread;
 }
 
-void md_unregister_thread (struct md_thread *thread)
+void md_interrupt_thread (mdk_thread_t *thread)
+{
+	if (!thread->tsk) {
+		MD_BUG();
+		return;
+	}
+	printk("interrupting MD-thread pid %d\n", thread->tsk->pid);
+	send_sig(SIGKILL, thread->tsk, 1);
+}
+
+void md_unregister_thread (mdk_thread_t *thread)
 {
 	DECLARE_MUTEX_LOCKED(sem);
 	
 	thread->sem = &sem;
 	thread->run = NULL;
-	if (thread->tsk)
-		printk("Killing md_thread %d %p %s\n",
-		       thread->tsk->pid, thread->tsk, thread->tsk->comm);
-	else
-		printk("Aiee. md_thread has 0 tsk\n");
-	send_sig(SIGKILL, thread->tsk, 1);
-	printk("downing on %p\n", &sem);
+	thread->name = NULL;
+	if (!thread->tsk) {
+		MD_BUG();
+		return;
+	}
+	md_interrupt_thread(thread);
 	down(&sem);
 }
 
-#define SHUTDOWN_SIGS   (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
+void md_recover_arrays (void)
+{
+	if (!md_recovery_thread) {
+		MD_BUG();
+		return;
+	}
+	md_wakeup_thread(md_recovery_thread);
+}
+
 
-int md_thread(void * arg)
+int md_error (kdev_t dev, kdev_t rdev)
 {
-	struct md_thread *thread = arg;
+	mddev_t *mddev = kdev_to_mddev(dev);
+	mdk_rdev_t * rrdev;
+	int rc;
 
-	lock_kernel();
-	exit_mm(current);
-	exit_files(current);
-	exit_fs(current);
-	
-	current->session = 1;
-	current->pgrp = 1;
-	sprintf(current->comm, "md_thread");
-	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
-	thread->tsk = current;
-	up(thread->sem);
+	printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
 
-	for (;;) {
-		cli();
-		if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
-			do {
-			        spin_lock(&current->sigmask_lock);
-				flush_signals(current);
-	  			spin_unlock(&current->sigmask_lock);
-				interruptible_sleep_on(&thread->wqueue);
-				cli();
-				if (test_bit(THREAD_WAKEUP, &thread->flags))
-					break;
-				if (!thread->run) {
-					sti();
-					up(thread->sem);
-					return 0;
-				}
-			} while (signal_pending(current));
-		}
-		sti();
-		clear_bit(THREAD_WAKEUP, &thread->flags);
-		if (thread->run) {
-			thread->run(thread->data);
-			run_task_queue(&tq_disk);
+	if (!mddev) {
+		MD_BUG();
+		return 0;
+	}
+	rrdev = find_rdev(mddev, rdev);
+	mark_rdev_faulty(rrdev);
+	/*
+	 * if recovery was running, stop it now.
+	 */
+	if (mddev->pers->stop_resync)
+		mddev->pers->stop_resync(mddev);
+	if (mddev->recovery_running)
+		md_interrupt_thread(md_recovery_thread);
+	if (mddev->pers->error_handler) {
+		rc = mddev->pers->error_handler(mddev, rdev);
+		md_recover_arrays();
+		return rc;
+	}
+	return 0;
+}
+
+static int status_unused (char * page)
+{
+	int sz = 0, i = 0;
+	mdk_rdev_t *rdev;
+	struct md_list_head *tmp;
+
+	sz += sprintf(page + sz, "unused devices: ");
+
+	ITERATE_RDEV_ALL(rdev,tmp) {
+		if (!rdev->same_set.next && !rdev->same_set.prev) {
+			/*
+			 * The device is not yet used by any array.
+			 */
+			i++;
+			sz += sprintf(page + sz, "%s ",
+				partition_name(rdev->dev));
 		}
 	}
+	if (!i)
+		sz += sprintf(page + sz, "<none>");
+
+	sz += sprintf(page + sz, "\n");
+	return sz;
 }
 
-EXPORT_SYMBOL(md_size);
-EXPORT_SYMBOL(md_maxreadahead);
-EXPORT_SYMBOL(register_md_personality);
-EXPORT_SYMBOL(unregister_md_personality);
-EXPORT_SYMBOL(md_dev);
-EXPORT_SYMBOL(md_error);
-EXPORT_SYMBOL(md_register_thread);
-EXPORT_SYMBOL(md_unregister_thread);
-EXPORT_SYMBOL(md_update_sb);
-EXPORT_SYMBOL(md_map);
-EXPORT_SYMBOL(md_wakeup_thread);
-EXPORT_SYMBOL(md_do_sync);
 
-#ifdef CONFIG_PROC_FS
-static int md_status_read_proc(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
+static int status_resync (char * page, mddev_t * mddev)
 {
-	int sz = 0, i, j, size;
-	int begin = 0;
+	int sz = 0;
+	unsigned int blocksize, max_blocks, resync, res, dt, tt, et;
+
+	resync = mddev->curr_resync;
+	blocksize = blksize_size[MD_MAJOR][mdidx(mddev)];
+	max_blocks = blk_size[MD_MAJOR][mdidx(mddev)] / (blocksize >> 10);
 
-	sz=sprintf( page, "Personalities : ");
-	for (i=0; i<MAX_PERSONALITY; i++)
-		if (pers[i])
-			sz+=sprintf (page+sz, "[%d %s] ", i, pers[i]->name);
-	page[sz-1]='\n';
-
-	sz+=sprintf (page+sz, "read_ahead ");
-	if (read_ahead[MD_MAJOR]==INT_MAX)
-		sz+=sprintf (page+sz, "not set\n");
+	/*
+	 * Should not happen.
+	 */		
+	if (!max_blocks) {
+		MD_BUG();
+		return 0;
+	}
+	res = (resync/1024)*1000/(max_blocks/1024 + 1);
+	{
+		int i, x = res/50, y = 20-x;
+		sz += sprintf(page + sz, "[");
+		for (i = 0; i < x; i++)
+			sz += sprintf(page + sz, "=");
+		sz += sprintf(page + sz, ">");
+		for (i = 0; i < y; i++)
+			sz += sprintf(page + sz, ".");
+		sz += sprintf(page + sz, "] ");
+	}
+	if (!mddev->recovery_running)
+		/*
+		 * true resync
+		 */
+		sz += sprintf(page + sz, " resync =%3u.%u%% (%u/%u)",
+				res/10, res % 10, resync, max_blocks);
 	else
-		sz+=sprintf (page+sz, "%d sectors\n", read_ahead[MD_MAJOR]);
+		/*
+		 * recovery ...
+		 */
+		sz += sprintf(page + sz, " recovery =%3u.%u%% (%u/%u)",
+				res/10, res % 10, resync, max_blocks);
 
-	for (i=0; i<MAX_MD_DEV; i++) {
-		if (sz < off) {
-			begin += sz;
-			off -= sz;
-			sz = 0;
-		}
-		if (sz >= off+count) {
-			*eof = 1;
-			break;
-		}
-		sz+=sprintf (page+sz, "md%d : %sactive",
-				i, md_dev[i].pers ? "" : "in");
+	/*
+	 * We do not want to overflow, so the order of operands and
+	 * the * 100 / 100 trick are important. We do a +1 to be
+	 * safe against division by zero. We only estimate anyway.
+	 *
+	 * dt: time until now
+	 * tt: total time
+	 * et: estimated finish time
+	 */
+	dt = ((jiffies - mddev->resync_start) / HZ);
+	tt = (dt * (max_blocks / (resync/100+1)))/100;
+	if (tt > dt)
+		et = tt - dt;
+	else
+		/*
+		 * ignore rounding effects near finish time
+		 */
+		et = 0;
+	
+	sz += sprintf(page + sz, " finish=%u.%umin", et / 60, (et % 60)/6);
 
-		if (md_dev[i].pers)
-			sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
+	return sz;
+}
 
-		for (j=0, size=0; j<md_dev[i].nb_dev; j++) {
-			sz+=sprintf (page+sz, " %s",
-				partition_name(md_dev[i].devices[j].dev));
-			size+=md_dev[i].devices[j].size;
+static int md_status_read_proc(char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	int sz = 0, j, size;
+	struct md_list_head *tmp, *tmp2;
+	mdk_rdev_t *rdev;
+	mddev_t *mddev;
+
+	sz += sprintf(page + sz, "Personalities : ");
+	for (j = 0; j < MAX_PERSONALITY; j++)
+	if (pers[j])
+		sz += sprintf(page+sz, "[%s] ", pers[j]->name);
+
+	sz += sprintf(page+sz, "\n");
+
+
+	sz += sprintf(page+sz, "read_ahead ");
+	if (read_ahead[MD_MAJOR] == INT_MAX)
+		sz += sprintf(page+sz, "not set\n");
+	else
+		sz += sprintf(page+sz, "%d sectors\n", read_ahead[MD_MAJOR]);
+  
+	ITERATE_MDDEV(mddev,tmp) {
+		sz += sprintf(page + sz, "md%d : %sactive", mdidx(mddev),
+						mddev->pers ? "" : "in");
+		if (mddev->pers) {
+			if (mddev->ro)	
+				sz += sprintf(page + sz, " (read-only)");
+			sz += sprintf(page + sz, " %s", mddev->pers->name);
+		}
+
+		size = 0;
+		ITERATE_RDEV(mddev,rdev,tmp2) {
+			sz += sprintf(page + sz, " %s[%d]",
+				partition_name(rdev->dev), rdev->desc_nr);
+			if (rdev->faulty) {
+				sz += sprintf(page + sz, "(F)");
+				continue;
+			}
+			size += rdev->size;
 		}
 
-		if (md_dev[i].nb_dev) {
-			if (md_dev[i].pers)
-				sz+=sprintf (page+sz, " %d blocks", md_size[i]);
+		if (mddev->nb_dev) {
+			if (mddev->pers)
+				sz += sprintf(page + sz, "\n      %d blocks",
+						 md_size[mdidx(mddev)]);
 			else
-				sz+=sprintf (page+sz, " %d blocks", size);
+				sz += sprintf(page + sz, "\n      %d blocks", size);
 		}
 
-		if (!md_dev[i].pers) {
-			sz+=sprintf (page+sz, "\n");
+		if (!mddev->pers) {
+			sz += sprintf(page+sz, "\n");
 			continue;
 		}
 
-		if (md_dev[i].pers->max_invalid_dev)
-			sz+=sprintf (page+sz, " maxfault=%ld",
-					MAX_FAULT(md_dev+i));
+		sz += mddev->pers->status (page+sz, mddev);
 
-		sz+=md_dev[i].pers->status (page+sz, i, md_dev+i);
-		sz+=sprintf (page+sz, "\n");
+		sz += sprintf(page+sz, "\n      ");
+		if (mddev->curr_resync) {
+			sz += status_resync (page+sz, mddev);
+		} else {
+			if (md_atomic_read(&mddev->resync_sem.count) != 1)
+				sz += sprintf(page + sz, "       resync=DELAYED");
+		}
+		sz += sprintf(page + sz, "\n");
 	}
+	sz += status_unused (page + sz);
 
-	sz -= off;
-	*start = page + off;
-	if (sz>count)
-		sz = count;
-	if (sz<0)
-		sz = 0;
 	return sz;
 }
-#endif
-
-static void md_geninit (void)
-{
-  int i;
-  
-  blksize_size[MD_MAJOR] = md_blocksizes;
-  max_readahead[MD_MAJOR] = md_maxreadahead;
-  for(i=0;i<MAX_MD_DEV;i++)
-  {
-    md_blocksizes[i] = 1024;
-    md_maxreadahead[i] = MD_DEFAULT_DISK_READAHEAD;
-    md_dev[i].pers=NULL;
-    register_disk(&md_gendisk, MKDEV(MAJOR_NR,i), 1, &md_fops, 0);
-  }
-
-#ifdef CONFIG_PROC_FS
-	create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
-#endif
-}
-
-int md_error (kdev_t mddev, kdev_t rdev)
-{
-    unsigned int minor = MINOR (mddev);
-    int rc;
 
-    if (MAJOR(mddev) != MD_MAJOR || minor > MAX_MD_DEV)
-	panic ("md_error gets unknown device\n");
-    if (!md_dev [minor].pers)
-	panic ("md_error gets an error for an unknown device\n");
-    if (md_dev [minor].pers->error_handler) {
-	rc = md_dev [minor].pers->error_handler (md_dev+minor, rdev);
-#if SUPPORT_RECONSTRUCTION
-	md_wakeup_thread(md_sync_thread);
-#endif /* SUPPORT_RECONSTRUCTION */
-	return rc;
-    }
-    return 0;
-}
-
-int register_md_personality (int p_num, struct md_personality *p)
+int register_md_personality (int pnum, mdk_personality_t *p)
 {
-  int i=(p_num >> PERSONALITY_SHIFT);
-
-  if (i >= MAX_PERSONALITY)
-    return -EINVAL;
+	if (pnum >= MAX_PERSONALITY)
+		return -EINVAL;
 
-  if (pers[i])
-    return -EBUSY;
+	if (pers[pnum])
+		return -EBUSY;
   
-  pers[i]=p;
-  printk ("%s personality registered\n", p->name);
-  return 0;
+	pers[pnum] = p;
+	printk(KERN_INFO "%s personality registered\n", p->name);
+	return 0;
 }
 
-int unregister_md_personality (int p_num)
+int unregister_md_personality (int pnum)
 {
-  int i=(p_num >> PERSONALITY_SHIFT);
-
-  if (i >= MAX_PERSONALITY)
-    return -EINVAL;
+	if (pnum >= MAX_PERSONALITY)
+		return -EINVAL;
 
-  printk ("%s personality unregistered\n", pers[i]->name);
-  pers[i]=NULL;
-  return 0;
+	printk(KERN_INFO "%s personality unregistered\n", pers[pnum]->name);
+	pers[pnum] = NULL;
+	return 0;
 } 
 
-static md_descriptor_t *get_spare(struct md_dev *mddev)
-{
-	int i;
-	md_superblock_t *sb = mddev->sb;
-	md_descriptor_t *descriptor;
-	struct real_dev *realdev;
-	
-  	for (i = 0; i < mddev->nb_dev; i++) {
-  		realdev = &mddev->devices[i];
-		if (!realdev->sb)
-			continue;
-		descriptor = &sb->disks[realdev->sb->descriptor.number];
-		if (descriptor->state & (1 << MD_FAULTY_DEVICE))
-			continue;
-		if (descriptor->state & (1 << MD_ACTIVE_DEVICE))
-			continue;
-		return descriptor;
-	}
-	return NULL;
-}
-
-/*
- * parallel resyncing thread. 
- *
- * FIXME: - make it abort with a dirty array on mdstop, now it just blocks
- *        - fix read error handing
- */
-
-int md_do_sync(struct md_dev *mddev)
+int md_notify_reboot(struct notifier_block *this,
+					unsigned long code, void *x)
 {
-        struct buffer_head *bh;
-	int max_blocks, blocksize, curr_bsize, percent=1, j;
-	kdev_t read_disk = MKDEV(MD_MAJOR, mddev - md_dev);
-	int major = MAJOR(read_disk), minor = MINOR(read_disk);
-	unsigned long starttime;
-
-	blocksize = blksize_size[major][minor];
-	max_blocks = blk_size[major][minor] / (blocksize >> 10);
-
-	printk("... resync log\n");
-	printk(" ....   mddev->nb_dev: %d\n", mddev->nb_dev);
-	printk(" ....   raid array: %s\n", kdevname(read_disk));
-	printk(" ....   max_blocks: %d blocksize: %d\n", max_blocks, blocksize);
-	printk("md: syncing RAID array %s\n", kdevname(read_disk));
-
-	mddev->busy++;
-
-	starttime=jiffies;
-	for (j = 0; j < max_blocks; j++) {
-
-		/*
-		 * B careful. When some1 mounts a non-'blocksize' filesystem
-		 * then we get the blocksize changed right under us. Go deal
-		 * with it transparently, recalculate 'blocksize', 'j' and
-		 * 'max_blocks':
-		 */
-		curr_bsize = blksize_size[major][minor];
-		if (curr_bsize != blocksize) {
-		diff_blocksize:
-			if (curr_bsize > blocksize)
-				/*
-				 * this is safe, rounds downwards.
-				 */
-				j /= curr_bsize/blocksize;
-			else
-				j *= blocksize/curr_bsize;
-
-			blocksize = curr_bsize;
-			max_blocks = blk_size[major][minor] / (blocksize >> 10);
-		}
-        	if ((bh = breada (read_disk, j, blocksize, j * blocksize,
-					max_blocks * blocksize)) != NULL) {
-			mark_buffer_dirty(bh, 1);
-			brelse(bh);
-		} else {
-			/*
-			 * FIXME: Ugly, but set_blocksize() isnt safe ...
-			 */
-			curr_bsize = blksize_size[major][minor];
-			if (curr_bsize != blocksize)
-				goto diff_blocksize;
+	struct md_list_head *tmp;
+	mddev_t *mddev;
 
-			/*
-			 * It's a real read problem. FIXME, handle this
-			 * a better way.
-			 */
-			printk ( KERN_ALERT
-				 "read error, stopping reconstruction.\n");
-			mddev->busy--;
-			return 1;
-		}
+	if ((code == MD_SYS_DOWN) || (code == MD_SYS_HALT)
+				  || (code == MD_SYS_POWER_OFF)) {
 
-		/*
-		 * Let's sleep some if we are faster than our speed limit:
-		 */
-		while (blocksize*j/(jiffies-starttime+1)*HZ/1024 > SPEED_LIMIT)
-		{
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(1);
-		}
+		printk(KERN_INFO "stopping all md devices.\n");
 
+		ITERATE_MDDEV(mddev,tmp)
+			do_md_stop (mddev, 1);
 		/*
-		 * FIXME: put this status bar thing into /proc
+		 * certain more exotic SCSI devices are known to be
+		 * volatile wrt too early system reboots. While the
+		 * right place to handle this issue is the given
+		 * driver, we do want to have a safe RAID driver ...
 		 */
-		if (!(j%(max_blocks/100))) {
-			if (!(percent%10))
-				printk (" %03d%% done.\n",percent);
-			else
-				printk (".");
-			percent++;
-		}
+		md_mdelay(1000*1);
 	}
-	fsync_dev(read_disk);
-	printk("md: %s: sync done.\n", kdevname(read_disk));
-	mddev->busy--;
-	return 0;
+	return NOTIFY_DONE;
 }
 
-/*
- * This is a kernel thread which: syncs a spare disk with the active array
- *
- * the amount of foolproofing might seem to be a tad excessive, but an
- * early (not so error-safe) version of raid1syncd synced the first 0.5 gigs
- * of my root partition with the first 0.5 gigs of my /home partition ... so
- * i'm a bit nervous ;)
- */
-void mdsyncd (void *data)
+struct notifier_block md_notifier = {
+	md_notify_reboot,
+	NULL,
+	0
+};
+
+void md__init raid_setup(char *str, int *ints)
 {
-	int i;
-	struct md_dev *mddev;
-	md_superblock_t *sb;
-	md_descriptor_t *spare;
-	unsigned long flags;
+	char tmpline[100];
+	int len, pos, nr, i;
 
-	for (i = 0, mddev = md_dev; i < MAX_MD_DEV; i++, mddev++) {
-		if ((sb = mddev->sb) == NULL)
-			continue;
-		if (sb->active_disks == sb->raid_disks)
-			continue;
-		if (!sb->spare_disks)
-			continue;
-		if ((spare = get_spare(mddev)) == NULL)
-			continue;
-		if (!mddev->pers->mark_spare)
-			continue;
-		if (mddev->pers->mark_spare(mddev, spare, SPARE_WRITE))
-			continue;
-		if (md_do_sync(mddev) || (spare->state & (1 << MD_FAULTY_DEVICE))) {
-			mddev->pers->mark_spare(mddev, spare, SPARE_INACTIVE);
+	len = strlen(str) + 1;
+	nr = 0;
+	pos = 0;
+
+	for (i = 0; i < len; i++) {
+		char c = str[i];
+
+		if (c == ',' || !c) {
+			tmpline[pos] = 0;
+			if (!strcmp(tmpline,"noautodetect"))
+				raid_setup_args.noautodetect = 1;
+			nr++;
+			pos = 0;
 			continue;
 		}
-		save_flags(flags);
-		cli();
-		mddev->pers->mark_spare(mddev, spare, SPARE_ACTIVE);
-		spare->state |= (1 << MD_SYNC_DEVICE);
-		spare->state |= (1 << MD_ACTIVE_DEVICE);
-		sb->spare_disks--;
-		sb->active_disks++;
-		mddev->sb_dirty = 1;
-		md_update_sb(mddev - md_dev);
-		restore_flags(flags);
+		tmpline[pos] = c;
+		pos++;
 	}
-	
+	raid_setup_args.set = 1;
+	return;
 }
 
 #ifdef CONFIG_MD_BOOT
 struct {
 	unsigned long set;
-	int pers[MAX_MD_DEV];
-	kdev_t devices[MAX_MD_DEV][MAX_REAL];
-} md_setup_args __initdata = {
+	int pers[MAX_MD_DEVS];
+	kdev_t devices[MAX_MD_DEVS][MAX_REAL];
+} md_setup_args md__initdata = {
 	0,{0},{{0}}
 };
 
@@ -1155,7 +3207,7 @@
  *             the MD devices (by specifying multiple "md=" lines)
  *             instead of just one.  -- KTK
  */
-int __init md_setup(char *str)
+static int __init md_setup(char *str)
 {
 	int minor, level, factor, fault, i;
 	kdev_t device;
@@ -1167,31 +3219,31 @@
 	   get_option(&str, &fault) != 2) {
 		printk("md: Too few arguments supplied to md=.\n");
 		return 0;
-	} else if (minor >= MAX_MD_DEV) {
-		printk ("md: Minor device number too high.\n");
+	} else if (minor >= MAX_MD_DEVS) {
+ 		printk ("md: Minor device number too high.\n");
 		return 0;
 	} else if (md_setup_args.set & (1 << minor)) {
 		printk ("md: Warning - md=%d,... has been specified twice;\n"
 			"    will discard the first definition.\n", minor);
-	}
+ 	}
 	switch(level) {
 #ifdef CONFIG_MD_LINEAR
 	case -1:
 		level = LINEAR;
 		pername = "linear";
-		break;
+ 		break;
 #endif
 #ifdef CONFIG_MD_STRIPED
 	case 0:
 		level = STRIPED;
 		pername = "striped";
-		break;
+ 		break;
 #endif
 	default:
 		printk ("md: The kernel has not been configured for raid%d"
 			" support!\n", level);
 		return 0;
-	}
+ 	}
 	devnames = str;
 	for (i = 0; str; i++) {
 		if ((device = name_to_kdev_t(str))) {
@@ -1215,61 +3267,87 @@
 	md_setup_args.set |= (1 << minor);
 	return 0;
 }
-
 #endif
 
+static void md_geninit (void)
+{
+	int i;
+
+	blksize_size[MD_MAJOR] = md_blocksizes;
+	max_readahead[MD_MAJOR] = md_maxreadahead;
+
+	for(i = 0; i < MAX_MD_DEVS; i++) {
+		md_blocksizes[i] = 1024;
+		md_maxreadahead[i] = MD_READAHEAD;
+		register_disk(&md_gendisk, MKDEV(MAJOR_NR,i), 1, &md_fops, 0);
+
+	}
+
+	printk("md.c: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
+
+#ifdef CONFIG_PROC_FS
+	create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
+#endif
+}
+void hsm_init (void);
+void translucent_init (void);
 void linear_init (void);
 void raid0_init (void);
 void raid1_init (void);
 void raid5_init (void);
 
-int __init md_init (void)
+int md__init md_init (void)
 {
-  printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n",
-    MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION,
-    MAX_MD_DEV, MAX_REAL);
-
-  if (register_blkdev (MD_MAJOR, "md", &md_fops))
-  {
-    printk ("Unable to get major %d for md\n", MD_MAJOR);
-    return (-1);
-  }
-
-  blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
-  read_ahead[MD_MAJOR]=INT_MAX;
-  memset(md_dev, 0, MAX_MD_DEV * sizeof (struct md_dev));
-  md_gendisk.next=gendisk_head;
-
-  gendisk_head=&md_gendisk;
-
-#if SUPPORT_RECONSTRUCTION
-  if ((md_sync_thread = md_register_thread(mdsyncd, NULL)) == NULL)
-    printk("md: bug: md_sync_thread == NULL\n");
-#endif /* SUPPORT_RECONSTRUCTION */
+	printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n",
+			MD_MAJOR_VERSION, MD_MINOR_VERSION,
+			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL);
+
+	if (register_blkdev (MD_MAJOR, "md", &md_fops))
+	{
+		printk (KERN_ALERT "Unable to get major %d for md\n", MD_MAJOR);
+		return (-1);
+	}
+
+	blk_dev[MD_MAJOR].queue = md_get_queue;
+
+	read_ahead[MD_MAJOR] = INT_MAX;
+	md_gendisk.next = gendisk_head;
+
+	gendisk_head = &md_gendisk;
+
+	md_register_reboot_notifier(&md_notifier);
 
 #ifdef CONFIG_MD_LINEAR
-  linear_init ();
+	linear_init ();
 #endif
 #ifdef CONFIG_MD_STRIPED
-  raid0_init ();
+	raid0_init ();
 #endif
 #ifdef CONFIG_MD_MIRRORING
-  raid1_init ();
+	raid1_init ();
 #endif
 #ifdef CONFIG_MD_RAID5
-  raid5_init ();
+	raid5_init ();
 #endif
-  md_geninit();
-  return (0);
+#if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE)
+        /*
+         * pick a XOR routine, runtime.
+         */
+	calibrate_xor_block();
+#endif
+	md_geninit();
+	return (0);
 }
 
 #ifdef CONFIG_MD_BOOT
-void __init md_setup_drive(void)
+static void __init md_setup_drive(void)
 {
+	if(md_setup_args.set)
+		do_md_setup(md_setup_args.str, md_setup_args.ints);
 	int minor, i;
 	kdev_t dev;
 
-	for (minor = 0; minor < MAX_MD_DEV; minor++) {
+	for (minor = 0; minor < MAX_MD_DEVS; minor++) {
 		if ((md_setup_args.set & (1 << minor)) == 0)
 			continue;
 		printk("md: Loading md%d.\n", minor);
@@ -1281,3 +3359,20 @@
 
 __setup("md=", md_setup);
 #endif
+
+MD_EXPORT_SYMBOL(md_size);
+MD_EXPORT_SYMBOL(register_md_personality);
+MD_EXPORT_SYMBOL(unregister_md_personality);
+MD_EXPORT_SYMBOL(partition_name);
+MD_EXPORT_SYMBOL(md_error);
+MD_EXPORT_SYMBOL(md_recover_arrays);
+MD_EXPORT_SYMBOL(md_register_thread);
+MD_EXPORT_SYMBOL(md_unregister_thread);
+MD_EXPORT_SYMBOL(md_update_sb);
+MD_EXPORT_SYMBOL(md_wakeup_thread);
+MD_EXPORT_SYMBOL(md_print_devices);
+MD_EXPORT_SYMBOL(find_rdev_nr);
+MD_EXPORT_SYMBOL(md_interrupt_thread);
+MD_EXPORT_SYMBOL(mddev_map);
+MD_EXPORT_SYMBOL(md_check_ordering);
+
diff -u --recursive --new-file v2.3.42/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c
--- v2.3.42/linux/drivers/block/paride/pg.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/block/paride/pg.c	Wed Feb  9 11:42:35 2000
@@ -260,18 +260,10 @@
 /* kernel glue structures */
 
 static struct file_operations pg_fops = {
-	NULL,                   /* lseek - default */
-	pg_read,                /* read */
-	pg_write,               /* write */
-	NULL,                   /* readdir - bad */
-	NULL,                   /* select */
-	NULL,                   /* ioctl */
-	NULL,                   /* mmap */
-	pg_open,                /* open */
-	NULL,			/* flush */
-	pg_release,             /* release */
-	NULL,                   /* fsync */
-	NULL,                   /* fasync */
+	read:		pg_read,
+	write:		pg_write,
+	open:		pg_open,
+	release:	pg_release,
 };
 
 void pg_init_units( void )
diff -u --recursive --new-file v2.3.42/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.3.42/linux/drivers/block/paride/pt.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/block/paride/pt.c	Wed Feb  9 11:42:35 2000
@@ -262,18 +262,11 @@
 /* kernel glue structures */
 
 static struct file_operations pt_fops = {
-        NULL,                   /* lseek - default */
-        pt_read,                /* read */
-        pt_write,               /* write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* select */
-        pt_ioctl,               /* ioctl */
-        NULL,                   /* mmap */
-        pt_open,                /* open */
-	NULL,			/* flush */
-        pt_release,             /* release */
-        NULL,                   /* fsync */
-        NULL,                   /* fasync */
+	read:		pt_read,
+	write:		pt_write,
+	ioctl:		pt_ioctl,
+	open:		pt_open,
+	release:	pt_release,
 };
 
 void pt_init_units( void )
diff -u --recursive --new-file v2.3.42/linux/drivers/block/raid0.c linux/drivers/block/raid0.c
--- v2.3.42/linux/drivers/block/raid0.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/block/raid0.c	Tue Feb  8 11:39:00 2000
@@ -1,9 +1,10 @@
-
 /*
    raid0.c : Multiple Devices driver for Linux
              Copyright (C) 1994-96 Marc ZYNGIER
 	     <zyngier@ufr-info-p7.ibp.fr> or
 	     <maz@gloups.fdn.fr>
+             Copyright (C) 1999, 2000 Ingo Molnar, Red Hat
+
 
    RAID-0 management functions.
 
@@ -18,146 +19,201 @@
 */
 
 #include <linux/module.h>
-#include <linux/md.h>
-#include <linux/raid0.h>
-#include <linux/vmalloc.h>
+#include <linux/raid/raid0.h>
 
 #define MAJOR_NR MD_MAJOR
 #define MD_DRIVER
 #define MD_PERSONALITY
 
-static int create_strip_zones (int minor, struct md_dev *mddev)
+static int create_strip_zones (mddev_t *mddev)
 {
-  int i, j, c=0;
-  int current_offset=0;
-  struct real_dev *smallest_by_zone;
-  struct raid0_data *data=(struct raid0_data *) mddev->private;
-  
-  data->nr_strip_zones=1;
-  
-  for (i=1; i<mddev->nb_dev; i++)
-  {
-    for (j=0; j<i; j++)
-      if (mddev->devices[i].size==mddev->devices[j].size)
-      {
-	c=1;
-	break;
-      }
-
-    if (!c)
-      data->nr_strip_zones++;
-
-    c=0;
-  }
-
-  if ((data->strip_zone=vmalloc(sizeof(struct strip_zone)*data->nr_strip_zones)) == NULL)
-    return 1;
-
-  data->smallest=NULL;
-  
-  for (i=0; i<data->nr_strip_zones; i++)
-  {
-    data->strip_zone[i].dev_offset=current_offset;
-    smallest_by_zone=NULL;
-    c=0;
-
-    for (j=0; j<mddev->nb_dev; j++)
-      if (mddev->devices[j].size>current_offset)
-      {
-	data->strip_zone[i].dev[c++]=mddev->devices+j;
-	if (!smallest_by_zone ||
-	    smallest_by_zone->size > mddev->devices[j].size)
-	  smallest_by_zone=mddev->devices+j;
-      }
-
-    data->strip_zone[i].nb_dev=c;
-    data->strip_zone[i].size=(smallest_by_zone->size-current_offset)*c;
-
-    if (!data->smallest ||
-	data->smallest->size > data->strip_zone[i].size)
-      data->smallest=data->strip_zone+i;
-
-    data->strip_zone[i].zone_offset=i ? (data->strip_zone[i-1].zone_offset+
-					   data->strip_zone[i-1].size) : 0;
-    current_offset=smallest_by_zone->size;
-  }
-  return 0;
+	int i, c, j, j1, j2;
+	int current_offset, curr_zone_offset;
+	raid0_conf_t *conf = mddev_to_conf(mddev);
+	mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev;
+ 
+	/*
+	 * The number of 'same size groups'
+	 */
+	conf->nr_strip_zones = 0;
+ 
+	ITERATE_RDEV_ORDERED(mddev,rdev1,j1) {
+		printk("raid0: looking at %s\n", partition_name(rdev1->dev));
+		c = 0;
+		ITERATE_RDEV_ORDERED(mddev,rdev2,j2) {
+			printk("raid0:   comparing %s(%d) with %s(%d)\n", partition_name(rdev1->dev), rdev1->size, partition_name(rdev2->dev), rdev2->size);
+			if (rdev2 == rdev1) {
+				printk("raid0:   END\n");
+				break;
+			}
+			if (rdev2->size == rdev1->size)
+			{
+				/*
+				 * Not unique, dont count it as a new
+				 * group
+				 */
+				printk("raid0:   EQUAL\n");
+				c = 1;
+				break;
+			}
+			printk("raid0:   NOT EQUAL\n");
+		}
+		if (!c) {
+			printk("raid0:   ==> UNIQUE\n");
+			conf->nr_strip_zones++;
+			printk("raid0: %d zones\n", conf->nr_strip_zones);
+		}
+	}
+		printk("raid0: FINAL %d zones\n", conf->nr_strip_zones);
+
+	conf->strip_zone = vmalloc(sizeof(struct strip_zone)*
+				conf->nr_strip_zones);
+	if (!conf->strip_zone)
+		return 1;
+
+
+	conf->smallest = NULL;
+	current_offset = 0;
+	curr_zone_offset = 0;
+
+	for (i = 0; i < conf->nr_strip_zones; i++)
+	{
+		struct strip_zone *zone = conf->strip_zone + i;
+
+		printk("zone %d\n", i);
+		zone->dev_offset = current_offset;
+		smallest = NULL;
+		c = 0;
+
+		ITERATE_RDEV_ORDERED(mddev,rdev,j) {
+
+			printk(" checking %s ...", partition_name(rdev->dev));
+			if (rdev->size > current_offset)
+			{
+				printk(" contained as device %d\n", c);
+				zone->dev[c] = rdev;
+				c++;
+				if (!smallest || (rdev->size <smallest->size)) {
+					smallest = rdev;
+					printk("  (%d) is smallest!.\n", rdev->size);
+				}
+			} else
+				printk(" nope.\n");
+		}
+
+		zone->nb_dev = c;
+		zone->size = (smallest->size - current_offset) * c;
+		printk(" zone->nb_dev: %d, size: %d\n",zone->nb_dev,zone->size);
+
+		if (!conf->smallest || (zone->size < conf->smallest->size))
+			conf->smallest = zone;
+
+		zone->zone_offset = curr_zone_offset;
+		curr_zone_offset += zone->size;
+
+		current_offset = smallest->size;
+		printk("current zone offset: %d\n", current_offset);
+	}
+	printk("done.\n");
+	return 0;
 }
 
-static int raid0_run (int minor, struct md_dev *mddev)
+static int raid0_run (mddev_t *mddev)
 {
-  int cur=0, i=0, size, zone0_size, nb_zone;
-  struct raid0_data *data;
+	int cur=0, i=0, size, zone0_size, nb_zone;
+	raid0_conf_t *conf;
 
-  MOD_INC_USE_COUNT;
-
-  if ((mddev->private=vmalloc (sizeof (struct raid0_data))) == NULL) return 1;
-  data=(struct raid0_data *) mddev->private;
-  
-  if (create_strip_zones (minor, mddev)) 
-  {
-  	vfree(data);
-  	return 1;
-  }
-
-  nb_zone=data->nr_zones=
-    md_size[minor]/data->smallest->size +
-    (md_size[minor]%data->smallest->size ? 1 : 0);
-
-  printk ("raid0 : Allocating %ld bytes for hash.\n",(long)sizeof(struct raid0_hash)*nb_zone);
-  if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL)
-  {
-    vfree(data->strip_zone);
-    vfree(data);
-    return 1;
-  }
-  size=data->strip_zone[cur].size;
-
-  i=0;
-  while (cur<data->nr_strip_zones)
-  {
-    data->hash_table[i].zone0=data->strip_zone+cur;
-
-    if (size>=data->smallest->size)/* If we completely fill the slot */
-    {
-      data->hash_table[i++].zone1=NULL;
-      size-=data->smallest->size;
-
-      if (!size)
-      {
-	if (++cur==data->nr_strip_zones) continue;
-	size=data->strip_zone[cur].size;
-      }
-
-      continue;
-    }
-
-    if (++cur==data->nr_strip_zones) /* Last dev, set unit1 as NULL */
-    {
-      data->hash_table[i].zone1=NULL;
-      continue;
-    }
-
-    zone0_size=size;		/* Here, we use a 2nd dev to fill the slot */
-    size=data->strip_zone[cur].size;
-    data->hash_table[i++].zone1=data->strip_zone+cur;
-    size-=(data->smallest->size - zone0_size);
-  }
+	MOD_INC_USE_COUNT;
 
-  return (0);
+	conf = vmalloc(sizeof (raid0_conf_t));
+	if (!conf)
+		goto out;
+	mddev->private = (void *)conf;
+ 
+	if (md_check_ordering(mddev)) {
+		printk("raid0: disks are not ordered, aborting!\n");
+		goto out_free_conf;
+	}
+
+	if (create_strip_zones (mddev)) 
+		goto out_free_conf;
+
+	printk("raid0 : md_size is %d blocks.\n", md_size[mdidx(mddev)]);
+	printk("raid0 : conf->smallest->size is %d blocks.\n", conf->smallest->size);
+	nb_zone = md_size[mdidx(mddev)]/conf->smallest->size +
+			(md_size[mdidx(mddev)] % conf->smallest->size ? 1 : 0);
+	printk("raid0 : nb_zone is %d.\n", nb_zone);
+	conf->nr_zones = nb_zone;
+
+	printk("raid0 : Allocating %d bytes for hash.\n",
+				sizeof(struct raid0_hash)*nb_zone);
+
+	conf->hash_table = vmalloc (sizeof (struct raid0_hash)*nb_zone);
+	if (!conf->hash_table)
+		goto out_free_zone_conf;
+	size = conf->strip_zone[cur].size;
+
+	i = 0;
+	while (cur < conf->nr_strip_zones) {
+		conf->hash_table[i].zone0 = conf->strip_zone + cur;
+
+		/*
+		 * If we completely fill the slot
+		 */
+		if (size >= conf->smallest->size) {
+			conf->hash_table[i++].zone1 = NULL;
+			size -= conf->smallest->size;
+
+			if (!size) {
+				if (++cur == conf->nr_strip_zones)
+					continue;
+				size = conf->strip_zone[cur].size;
+			}
+			continue;
+		}
+		if (++cur == conf->nr_strip_zones) {
+			/*
+			 * Last dev, set unit1 as NULL
+			 */
+			conf->hash_table[i].zone1=NULL;
+			continue;
+		}
+
+		/*
+		 * Here we use a 2nd dev to fill the slot
+		 */
+		zone0_size = size;
+		size = conf->strip_zone[cur].size;
+		conf->hash_table[i++].zone1 = conf->strip_zone + cur;
+		size -= (conf->smallest->size - zone0_size);
+	}
+	return 0;
+
+out_free_zone_conf:
+	vfree(conf->strip_zone);
+	conf->strip_zone = NULL;
+
+out_free_conf:
+	vfree(conf);
+	mddev->private = NULL;
+out:
+	MOD_DEC_USE_COUNT;
+	return 1;
 }
 
-
-static int raid0_stop (int minor, struct md_dev *mddev)
+static int raid0_stop (mddev_t *mddev)
 {
-  struct raid0_data *data=(struct raid0_data *) mddev->private;
+	raid0_conf_t *conf = mddev_to_conf(mddev);
 
-  vfree (data->hash_table);
-  vfree (data->strip_zone);
-  vfree (data);
+	vfree (conf->hash_table);
+	conf->hash_table = NULL;
+	vfree (conf->strip_zone);
+	conf->strip_zone = NULL;
+	vfree (conf);
+	mddev->private = NULL;
 
-  MOD_DEC_USE_COUNT;
-  return 0;
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 /*
@@ -167,135 +223,142 @@
  * Of course, those facts may not be valid anymore (and surely won't...)
  * Hey guys, there's some work out there ;-)
  */
-static int raid0_map (struct md_dev *mddev, kdev_t *rdev,
-		      unsigned long *rsector, unsigned long size)
+static int raid0_make_request (mddev_t *mddev, int rw, struct buffer_head * bh)
 {
-  struct raid0_data *data=(struct raid0_data *) mddev->private;
-  static struct raid0_hash *hash;
-  struct strip_zone *zone;
-  struct real_dev *tmp_dev;
-  int blk_in_chunk, factor, chunk, chunk_size;
-  long block, rblock;
-
-  factor=FACTOR(mddev);
-  chunk_size=(1UL << FACTOR_SHIFT(factor));
-  block=*rsector >> 1;
-  hash=data->hash_table+(block/data->smallest->size);
-
-  if (hash - data->hash_table > data->nr_zones) 
-  { 
-	  printk(KERN_DEBUG "raid0_map: invalid block %ul\n", block);
-	  return -1;
-  }
-
-  /* Sanity check */
-  if ((chunk_size*2)<(*rsector % (chunk_size*2))+size)
-  {
-    printk ("raid0_convert : can't convert block across chunks or bigger than %dk %ld %ld\n", chunk_size, *rsector, size);
-    return (-1);
-  }
-  
-  if (block >= (hash->zone0->size +
-		hash->zone0->zone_offset))
-  {
-    if (!hash->zone1)
-    {
-      printk ("raid0_convert : hash->zone1==NULL for block %ld\n", block);
-      return (-1);
-    }
-    
-    zone=hash->zone1;
-  }
-  else
-    zone=hash->zone0;
+	unsigned long size = bh->b_size >> 10;
+	raid0_conf_t *conf = mddev_to_conf(mddev);
+	struct raid0_hash *hash;
+	struct strip_zone *zone;
+	mdk_rdev_t *tmp_dev;
+	int blk_in_chunk, chunksize_bits, chunk, chunk_size;
+	long block, rblock;
+
+	chunk_size = mddev->param.chunk_size >> 10;
+	chunksize_bits = ffz(~chunk_size);
+	block = bh->b_blocknr * size;
+	hash = conf->hash_table + block / conf->smallest->size;
+
+	/* Sanity check */
+	if (chunk_size < (block % chunk_size) + size)
+		goto bad_map;
+ 
+	if (!hash)
+		goto bad_hash;
+
+	if (!hash->zone0)
+		goto bad_zone0;
+ 
+	if (block >= (hash->zone0->size + hash->zone0->zone_offset)) {
+		if (!hash->zone1)
+			goto bad_zone1;
+		zone = hash->zone1;
+	} else
+		zone = hash->zone0;
     
-  blk_in_chunk=block & (chunk_size -1);
-  chunk=(block - zone->zone_offset) / (zone->nb_dev<<FACTOR_SHIFT(factor));
-  tmp_dev=zone->dev[(block >> FACTOR_SHIFT(factor)) % zone->nb_dev];
-  rblock=(chunk << FACTOR_SHIFT(factor)) + blk_in_chunk + zone->dev_offset;
-  
-  *rdev=tmp_dev->dev;
-  *rsector=rblock<<1;
-
-  return (0);
+	blk_in_chunk = block & (chunk_size -1);
+	chunk = (block - zone->zone_offset) / (zone->nb_dev << chunksize_bits);
+	tmp_dev = zone->dev[(block >> chunksize_bits) % zone->nb_dev];
+	rblock = (chunk << chunksize_bits) + blk_in_chunk + zone->dev_offset;
+ 
+	/*
+	 * Important, at this point we are not guaranteed to be the only
+	 * CPU modifying b_rdev and b_rsector! Only __make_request() later
+	 * on serializes the IO. So in 2.4 we must never write temporary
+	 * values to bh->b_rdev, like 2.2 and 2.0 did.
+	 */
+	bh->b_rdev = tmp_dev->dev;
+	bh->b_rsector = rblock << 1;
+
+	generic_make_request(rw, bh);
+
+	return 0;
+
+bad_map:
+	printk ("raid0_make_request bug: can't convert block across chunks or bigger than %dk %ld %ld\n", chunk_size, bh->b_rsector, size);
+	return -1;
+bad_hash:
+	printk("raid0_make_request bug: hash==NULL for block %ld\n", block);
+	return -1;
+bad_zone0:
+	printk ("raid0_make_request bug: hash->zone0==NULL for block %ld\n", block);
+	return -1;
+bad_zone1:
+	printk ("raid0_make_request bug: hash->zone1==NULL for block %ld\n", block);
+	return -1;
 }
-
 			   
-static int raid0_status (char *page, int minor, struct md_dev *mddev)
+static int raid0_status (char *page, mddev_t *mddev)
 {
-  int sz=0;
+	int sz = 0;
 #undef MD_DEBUG
 #ifdef MD_DEBUG
-  int j, k;
-  struct raid0_data *data=(struct raid0_data *) mddev->private;
+	int j, k;
+	raid0_conf_t *conf = mddev_to_conf(mddev);
   
-  sz+=sprintf (page+sz, "      ");
-  for (j=0; j<data->nr_zones; j++)
-  {
-    sz+=sprintf (page+sz, "[z%d",
-		 data->hash_table[j].zone0-data->strip_zone);
-    if (data->hash_table[j].zone1)
-      sz+=sprintf (page+sz, "/z%d] ",
-		   data->hash_table[j].zone1-data->strip_zone);
-    else
-      sz+=sprintf (page+sz, "] ");
-  }
+	sz += sprintf(page + sz, "      ");
+	for (j = 0; j < conf->nr_zones; j++) {
+		sz += sprintf(page + sz, "[z%d",
+				conf->hash_table[j].zone0 - conf->strip_zone);
+		if (conf->hash_table[j].zone1)
+			sz += sprintf(page+sz, "/z%d] ",
+				conf->hash_table[j].zone1 - conf->strip_zone);
+		else
+			sz += sprintf(page+sz, "] ");
+	}
   
-  sz+=sprintf (page+sz, "\n");
+	sz += sprintf(page + sz, "\n");
   
-  for (j=0; j<data->nr_strip_zones; j++)
-  {
-    sz+=sprintf (page+sz, "      z%d=[", j);
-    for (k=0; k<data->strip_zone[j].nb_dev; k++)
-      sz+=sprintf (page+sz, "%s/",
-		   partition_name(data->strip_zone[j].dev[k]->dev));
-    sz--;
-    sz+=sprintf (page+sz, "] zo=%d do=%d s=%d\n",
-		 data->strip_zone[j].zone_offset,
-		 data->strip_zone[j].dev_offset,
-		 data->strip_zone[j].size);
-  }
+	for (j = 0; j < conf->nr_strip_zones; j++) {
+		sz += sprintf(page + sz, "      z%d=[", j);
+		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
+			sz += sprintf (page+sz, "%s/", partition_name(
+				conf->strip_zone[j].dev[k]->dev));
+		sz--;
+		sz += sprintf (page+sz, "] zo=%d do=%d s=%d\n",
+				conf->strip_zone[j].zone_offset,
+				conf->strip_zone[j].dev_offset,
+				conf->strip_zone[j].size);
+	}
 #endif
-  sz+=sprintf (page+sz, " %dk chunks", 1<<FACTOR_SHIFT(FACTOR(mddev)));
-  return sz;
+	sz += sprintf(page + sz, " %dk chunks", mddev->param.chunk_size/1024);
+	return sz;
 }
 
-
-static struct md_personality raid0_personality=
+static mdk_personality_t raid0_personality=
 {
-  "raid0",
-  raid0_map,
-  NULL,				/* no special make_request */
-  NULL,				/* no special end_request */
-  raid0_run,
-  raid0_stop,
-  raid0_status,
-  NULL,				/* no ioctls */
-  0,
-  NULL,				/* no error_handler */
-  NULL,				/* hot_add_disk */
-  NULL,				/* hot_remove_disk */
-  NULL				/* mark_spare */
+	"raid0",
+	NULL,				/* no special map */
+	raid0_make_request,
+	NULL,				/* no special end_request */
+	raid0_run,
+	raid0_stop,
+	raid0_status,
+	NULL,				/* no ioctls */
+	0,
+	NULL,				/* no error_handler */
+	NULL,				/* no diskop */
+	NULL,				/* no stop resync */
+	NULL				/* no restart resync */
 };
 
-
 #ifndef MODULE
 
 void raid0_init (void)
 {
-  register_md_personality (RAID0, &raid0_personality);
+	register_md_personality (RAID0, &raid0_personality);
 }
 
 #else
 
 int init_module (void)
 {
-  return (register_md_personality (RAID0, &raid0_personality));
+	return (register_md_personality (RAID0, &raid0_personality));
 }
 
 void cleanup_module (void)
 {
-  unregister_md_personality (RAID0);
+	unregister_md_personality (RAID0);
 }
 
 #endif
+
diff -u --recursive --new-file v2.3.42/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.42/linux/drivers/block/rd.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/block/rd.c	Wed Feb  9 19:33:13 2000
@@ -270,7 +270,7 @@
 		}
 	}
 	if (rbh) {
- 		set_bit(BH_Protected, &rbh->b_state);
+		mark_buffer_protected(rbh);
 		brelse(rbh);
 	}
 
@@ -290,7 +290,10 @@
 	switch (cmd) {
 		case BLKFLSBUF:
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-			invalidate_buffers(inode->i_rdev);
+			/* special: we want to release the ramdisk memory,
+			   it's not like with the other blockdevices where
+			   this ioctl only flushes away the buffer cache. */
+			destroy_buffers(inode->i_rdev);
 			break;
 
          	case BLKGETSIZE:   /* Return device size */
@@ -338,17 +341,8 @@
 
 
 static struct file_operations initrd_fops = {
-	NULL,		/* lseek */
-	initrd_read,	/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL, 		/* ioctl */
-	NULL,		/* mmap */
-	NULL,		/* open */
-	NULL,		/* flush */
-	initrd_release,	/* release */
-	NULL		/* fsync */ 
+	read:		initrd_read,
+	release:	initrd_release,
 };
 
 #endif
@@ -391,7 +385,7 @@
 	int i;
 
 	for (i = 0 ; i < NUM_RAMDISKS; i++)
-		invalidate_buffers(MKDEV(MAJOR_NR, i));
+		destroy_buffers(MKDEV(MAJOR_NR, i));
 
 	unregister_blkdev( MAJOR_NR, "ramdisk" );
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
diff -u --recursive --new-file v2.3.42/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v2.3.42/linux/drivers/cdrom/mcd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/cdrom/mcd.c	Tue Feb  8 12:01:59 2000
@@ -1247,18 +1247,13 @@
 
         if (result[1] == 'D') 
 	{
-		sprintf(msg, " mcd: Mitsumi Double Speed CD-ROM at port=0x%x,"
-			     " irq=%d\n", mcd_port, mcd_irq);
 		MCMD_DATA_READ = MCMD_2X_READ;
-
-		mcd_info.speed = 2;
 		/* Added flag to drop to 1x speed if too many errors */
 		mcdDouble = 1;
-        } else {
-		sprintf(msg, " mcd: Mitsumi Single Speed CD-ROM at port=0x%x,"
-			     " irq=%d\n", mcd_port, mcd_irq);
-		mcd_info.speed = 2;
-	}
+        } else 
+		mcd_info.speed = 1;
+	sprintf(msg, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x,"
+		     " irq=%d\n", mcd_info.speed == 1 ?  "Single" : "Double", mcd_port, mcd_irq);
 
 	request_region(mcd_port, 4, "mcd");
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.3.42/linux/drivers/char/Makefile	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/Makefile	Mon Feb  7 09:51:43 2000
@@ -9,6 +9,18 @@
 # parent makes..
 #
 
+O_OBJS		:=
+OX_OBJS		:=
+M_OBJS		:=
+MX_OBJS		:=
+
+# Object file lists.
+
+obj-y		:=
+obj-m		:=
+obj-n		:=
+obj-		:=
+
 SUB_DIRS     := 
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia
@@ -19,9 +31,13 @@
 FONTMAPFILE = cp437.uni
 
 O_TARGET := char.o
-M_OBJS   :=
-O_OBJS   := tty_io.o n_tty.o tty_ioctl.o mem.o raw.o
-OX_OBJS  := pty.o misc.o random.o
+obj-y	 += tty_io.o n_tty.o tty_ioctl.o mem.o raw.o pty.o misc.o random.o
+
+# All of the (potential) objects that export symbols.
+# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
+
+export-objs     :=	busmouse.o console.o i2c-old.o keyboard.o \
+			misc.o pty.o random.o selection.o serial.o videodev.o
 
 KEYMAP   =defkeymap.o
 KEYBD    =pc_keyb.o
@@ -44,195 +60,55 @@
   SERIAL   =
 endif
 
-ifdef CONFIG_VT
-O_OBJS += vt.o vc_screen.o consolemap.o consolemap_deftbl.o
-OX_OBJS += $(CONSOLE) selection.o
-endif
-
-ifeq ($(CONFIG_SERIAL),y)
-OX_OBJS += $(SERIAL)
-else
-  ifeq ($(CONFIG_SERIAL),m)
-  MX_OBJS += $(SERIAL)
-  endif
-endif
-
-ifeq ($(CONFIG_SERIAL_21285),y)
-O_OBJS += serial_21285.o
-endif
+obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
+obj-$(CONFIG_SERIAL) += $(SERIAL)
+obj-$(CONFIG_SERIAL_21285) += serial_21285.o
 
 ifndef CONFIG_SUN_KEYBOARD
-  ifdef CONFIG_VT
-    OX_OBJS += keyboard.o
-    O_OBJS  += $(KEYMAP) $(KEYBD)
-  endif
+  obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD)
 else
-  ifdef CONFIG_PCI
-    OX_OBJS += keyboard.o
-    O_OBJS  += $(KEYMAP)
-  endif
+  obj-$(CONFIG_PCI) += keyboard.o $(KEYMAP)
 endif
 
-ifdef CONFIG_MAGIC_SYSRQ
-OX_OBJS += sysrq.o
-endif
+obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
 
+obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
 ifeq ($(CONFIG_ATARI_DSP56K),y)
-O_OBJS += dsp56k.o
 S = y
 else
   ifeq ($(CONFIG_ATARI_DSP56K),m)
-  M_OBJS += dsp56k.o
   SM = y
   endif
 endif
 
-ifeq ($(CONFIG_ROCKETPORT),y)
-O_OBJS += rocket.o
-else
-  ifeq ($(CONFIG_ROCKETPORT),m)
-  M_OBJS += rocket.o
-  endif
-endif
-
-ifeq ($(CONFIG_MOXA_SMARTIO),y)
-L_OBJS += mxser.o
-else
-  ifeq ($(CONFIG_MOXA_SMARTIO),m)
-  M_OBJS += mxser.o
-  endif
-endif
-
-ifeq ($(CONFIG_MOXA_INTELLIO),y)
-L_OBJS += moxa.o
-else
-  ifeq ($(CONFIG_MOXA_INTELLIO),m)
-  M_OBJS += moxa.o
-  endif
-endif
-
-ifeq ($(CONFIG_DIGI),y)
-O_OBJS += pcxx.o
-else
-  ifeq ($(CONFIG_DIGI),m)
-  M_OBJS += pcxx.o
-  endif
-endif
-
-ifeq ($(CONFIG_DIGIEPCA),y)
-O_OBJS += epca.o
-else
-  ifeq ($(CONFIG_DIGIEPCA),m)
-  M_OBJS += epca.o
-  endif
-endif
-
-ifeq ($(CONFIG_CYCLADES),y)
-O_OBJS += cyclades.o
-else
-  ifeq ($(CONFIG_CYCLADES),m)
-  M_OBJS += cyclades.o
-  endif
-endif
-
-ifeq ($(CONFIG_STALLION),y)
-O_OBJS += stallion.o
-else
-  ifeq ($(CONFIG_STALLION),m)
-  M_OBJS += stallion.o
-  endif
-endif
-
-ifeq ($(CONFIG_ISTALLION),y)
-O_OBJS += istallion.o
-else
-  ifeq ($(CONFIG_ISTALLION),m)
-  M_OBJS += istallion.o
-  endif
-endif
-
-ifeq ($(CONFIG_COMPUTONE),y)
-O_OBJS += ip2.o ip2main.o
-else
-  ifeq ($(CONFIG_COMPUTONE),m)
-  M_OBJS += ip2.o ip2main.o
-  endif
-endif
-
-ifeq ($(CONFIG_RISCOM8),y)
-O_OBJS += riscom8.o
-else
-  ifeq ($(CONFIG_RISCOM8),m)
-  M_OBJS += riscom8.o
-  endif
-endif
-
-ifeq ($(CONFIG_ISI),y)
-O_OBJS += isicom.o
-else
-  ifeq ($(CONFIG_ISI),m)
-  M_OBJS += isicom.o
-  endif
-endif
-
-ifeq ($(CONFIG_ESPSERIAL),y)
-O_OBJS += esp.o
-else
-  ifeq ($(CONFIG_ESPSERIAL),m)
-  M_OBJS += esp.o
-  endif
-endif
-
-ifeq ($(CONFIG_SYNCLINK),m)
-  M_OBJS += synclink.o
-endif
-
-ifeq ($(CONFIG_N_HDLC),m)
-  M_OBJS += n_hdlc.o
-endif
-
-ifeq ($(CONFIG_SPECIALIX),y)
-O_OBJS += specialix.o
-else
-  ifeq ($(CONFIG_SPECIALIX),m)
-  M_OBJS += specialix.o
-  endif
-endif
+obj-$(CONFIG_ROCKETPORT) += rocket.o
+obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
+obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
+obj-$(CONFIG_DIGI) += pcxx.o
+obj-$(CONFIG_DIGIEPCA) += epca.o
+obj-$(CONFIG_CYCLADES) += cyclades.o
+obj-$(CONFIG_STALLION) += stallion.o
+obj-$(CONFIG_ISTALLION) += istallion.o
+obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o
+obj-$(CONFIG_RISCOM8) += riscom8.o
+obj-$(CONFIG_ISI) += isicom.o
+obj-$(CONFIG_ESPSERIAL) += esp.o
+obj-$(CONFIG_SYNCLINK) += synclink.o
+obj-$(CONFIG_N_HDLC) += n_hdlc.o
+obj-$(CONFIG_SPECIALIX) += specialix.o
 
 ifeq ($(CONFIG_SX),y)
-O_OBJS += sx.o generic_serial.o
-else
-  ifeq ($(CONFIG_SX),m)
-  M_OBJS += sx.o
-  endif
-endif
-
-ifeq ($(CONFIG_ATIXL_BUSMOUSE),y)
-O_OBJS += atixlmouse.o
+obj-y += sx.o generic_serial.o
 else
-  ifeq ($(CONFIG_ATIXL_BUSMOUSE),m)
-  M_OBJS += atixlmouse.o
-  endif
+  obj-$(CONFIG_SX) += sx.o
 endif
 
-ifeq ($(CONFIG_LOGIBUSMOUSE),y)
-O_OBJS += logibusmouse.o
-else
-  ifeq ($(CONFIG_LOGIBUSMOUSE),m)
-  M_OBJS += logibusmouse.o
-  endif
-endif
-
-ifeq ($(CONFIG_PRINTER),y)
-O_OBJS += lp.o
-else
-  ifeq ($(CONFIG_PRINTER),m)
-  M_OBJS += lp.o
-  endif
-endif
+obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o
+obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o
+obj-$(CONFIG_PRINTER) += lp.o
 
 ifeq ($(CONFIG_JOYSTICK),y)
-O_OBJS += joystick/js.o
+obj-y += joystick/js.o
 SUB_DIRS += joystick
 MOD_SUB_DIRS += joystick
 else
@@ -241,155 +117,35 @@
   endif
 endif
 
+obj-$(CONFIG_BUSMOUSE) += busmouse.o
 ifeq ($(CONFIG_BUSMOUSE),y)
 M = y
-OX_OBJS += busmouse.o
 else
   ifeq ($(CONFIG_BUSMOUSE),m)
   MM = m
-  MX_OBJS += busmouse.o
-  endif
-endif
-
-ifeq ($(CONFIG_DTLK),y)
-O_OBJS += dtlk.o
-else
-  ifeq ($(CONFIG_DTLK),m)
-  M_OBJS += dtlk.o
-  endif
-endif
-
-ifeq ($(CONFIG_R3964),y)
-O_OBJS += n_r3964.o
-else
-  ifeq ($(CONFIG_R3964),m)
-  M_OBJS += n_r3964.o
-  endif
-endif
-
-ifeq ($(CONFIG_APPLICOM),y)
-O_OBJS += applicom.o
-else
-  ifeq ($(CONFIG_APPLICOM),m)
-  M_OBJS += applicom.o
-  endif
-endif
-
-ifeq ($(CONFIG_MS_BUSMOUSE),y)
-O_OBJS += msbusmouse.o
-else
-  ifeq ($(CONFIG_MS_BUSMOUSE),m)
-  M_OBJS += msbusmouse.o
-  endif
-endif
-
-ifeq ($(CONFIG_82C710_MOUSE),y)
-O_OBJS += qpmouse.o
-else
-  ifeq ($(CONFIG_82C710_MOUSE),m)
-  M_OBJS += qpmouse.o
-  endif
-endif
-
-ifeq ($(CONFIG_SOFT_WATCHDOG),y)
-O_OBJS += softdog.o
-else
-  ifeq ($(CONFIG_SOFT_WATCHDOG),m)
-  M_OBJS += softdog.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCWATCHDOG),y)
-O_OBJS += pcwd.o
-else
-  ifeq ($(CONFIG_PCWATCHDOG),m)
-  M_OBJS += pcwd.o
-  endif
-endif
-
-ifeq ($(CONFIG_ACQUIRE_WDT),y)
-O_OBJS += acquirewdt.o
-else
-  ifeq ($(CONFIG_ACQUIRE_WDT),m)
-  M_OBJS += acquirewdt.o
-  endif
-endif
-
-ifeq ($(CONFIG_MIXCOMWD),y)
-O_OBJS += mixcomwd.o
-else
-  ifeq ($(CONFIG_MIXCOMWD),m)
-  M_OBJS += mixcomwd.o
-  endif
-endif
-
-ifeq ($(CONFIG_AMIGAMOUSE),y)
-O_OBJS += amigamouse.o
-else
-  ifeq ($(CONFIG_AMIGAMOUSE),m)
-    M_OBJS += amigamouse.o
-  endif
-endif
-
-ifeq ($(CONFIG_ATARIMOUSE),y)
-O_OBJS += atarimouse.o
-else
-  ifeq ($(CONFIG_ATARIMOUSE),m)
-    M_OBJS += atarimouse.o
-  endif
-endif
-
-ifeq ($(CONFIG_ADBMOUSE),y)
-O_OBJS += adbmouse.o
-else
-  ifeq ($(CONFIG_ADBMOUSE),m)
-    M_OBJS += adbmouse.o
-  endif
-endif
-
-ifeq ($(CONFIG_PC110_PAD),y)
-O_OBJS += pc110pad.o
-else
-  ifeq ($(CONFIG_PC110_PAD),m)
-    M_OBJS += pc110pad.o
   endif
 endif
 
-ifeq ($(CONFIG_WDT),y)
-O_OBJS += wdt.o
-else
-  ifeq ($(CONFIG_WDT),m)
-    M_OBJS += wdt.o
-  endif
+obj-$(CONFIG_DTLK) += dtlk.o
+obj-$(CONFIG_R3964) += n_r3964.o
+obj-$(CONFIG_APPLICOM) += applicom.o
+obj-$(CONFIG_MS_BUSMOUSE) += msbusmouse.o
+obj-$(CONFIG_82C710_MOUSE) += qpmouse.o
+obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+obj-$(CONFIG_PCWATCHDOG) += pcwd.o
+obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
+obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o
+obj-$(CONFIG_ATARIMOUSE) += atarimouse.o
+obj-$(CONFIG_ADBMOUSE) += adbmouse.o
+obj-$(CONFIG_PC110_PAD) += pc110pad.o
+obj-$(CONFIG_WDT) += wdt.o
+obj-$(CONFIG_RTC) += rtc.o
+ifeq ($(CONFIG_PPC),)
+  obj-$(CONFIG_NVRAM) += nvram.o
 endif
 
-ifeq ($(CONFIG_RTC),y)
-O_OBJS += rtc.o
-else
-  ifeq ($(CONFIG_RTC),m)
-    M_OBJS += rtc.o
-  endif
-endif
-
-ifeq ($(CONFIG_NVRAM),y)
-  ifeq ($(CONFIG_PPC),)
-  O_OBJS += nvram.o
-  endif
-else
-  ifeq ($(CONFIG_NVRAM),m)
-    ifeq ($(CONFIG_PPC),)
-    M_OBJS += nvram.o
-    endif
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_DEV),y)
-OX_OBJS += videodev.o
-else
-  ifeq ($(CONFIG_VIDEO_DEV),m)
-    MX_OBJS += videodev.o
-  endif
-endif
+obj-$(CONFIG_VIDEO_DEV) += videodev.o
 
 #
 # for external dependencies in arm/config.in and video/config.in
@@ -398,222 +154,85 @@
 	L_I2C=y
 else
   ifeq ($(CONFIG_BUS_I2C),m)
-	M_I2C=y
+	L_I2C=m
   endif
 endif
 
+obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda9855.o tea6300.o
 ifeq ($(CONFIG_VIDEO_BT848),y)
-O_OBJS += bttv.o msp3400.o tda8425.o tda9855.o tea6300.o
 L_I2C=y
 L_TUNERS=y
 else
   ifeq ($(CONFIG_VIDEO_BT848),m)
-    M_OBJS += bttv.o msp3400.o tda8425.o tda9855.o tea6300.o
-    M_I2C=y
-    M_TUNERS=y
+    L_I2C=m
+    L_TUNERS=m
   endif
 endif
 
+obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
 ifeq ($(CONFIG_VIDEO_ZR36120),y)
-O_OBJS += zoran.o
 L_I2C=y
 L_TUNERS=y
 L_DECODERS=y
 else
   ifeq ($(CONFIG_VIDEO_ZR36120),m)
-    M_OBJS += zoran.o
-    M_I2C=y
-    M_TUNERS=y
-    M_DECODERS=y
+    L_I2C=m
+    L_TUNERS=m
+    L_DECODERS=m
   endif
 endif
 
+obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
 ifeq ($(CONFIG_I2C_PARPORT),y)
-O_OBJS += i2c-parport.o
 L_I2C = y
 else
   ifeq ($(CONFIG_I2C_PARPORT),m)
-    M_OBJS += i2c-parport.o
     M_I2C = y
   endif
 endif
 
+obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
 ifeq ($(CONFIG_VIDEO_SAA5249),y)
-O_OBJS += saa5249.o
 L_I2C=y
 else
   ifeq ($(CONFIG_VIDEO_SAA5249),m)
-    M_OBJS += saa5249.o
-    M_I2C=y
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_CQCAM),y)
-O_OBJS += c-qcam.o
-else
-  ifeq ($(CONFIG_VIDEO_CQCAM),m)
-    M_OBJS += c-qcam.o
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_BWQCAM),y)
-O_OBJS += bw-qcam.o
-else
-  ifeq ($(CONFIG_VIDEO_BWQCAM),m)
-    M_OBJS += bw-qcam.o
+    L_I2C=m
   endif
 endif
 
+obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
+obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
+obj-$(CONFIG_VIDEO_ZORAN) += buz.o
 ifeq ($(CONFIG_VIDEO_ZORAN),y)
-O_OBJS += buz.o
 L_I2C=y
 L_DECODERS=y
 else
   ifeq ($(CONFIG_VIDEO_ZORAN),m)
-    M_OBJS += buz.o
-    M_I2C=y
-    M_DECODERS=y
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_LML33),y)
-O_OBJS += bt856.o bt819.o
-else
-  ifeq ($(CONFIG_VIDEO_LML33),m)
-    M_OBJS += bt856.o bt819.o
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_PMS),y)
-O_OBJS += pms.o
-else
-  ifeq ($(CONFIG_VIDEO_PMS),m)
-  M_OBJS += pms.o
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_PLANB),y)
-O_OBJS += planb.o
-else
-  ifeq ($(CONFIG_VIDEO_PLANB),m)
-  M_OBJS += planb.o
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_VINO),y)
-O_OBJS += vino.o
-else
-  ifeq ($(CONFIG_VIDEO_VINO),m)
-  M_OBJS += vino.o
-  endif
-endif
-
-ifeq ($(CONFIG_VIDEO_STRADIS),y)
-O_OBJS += vino.o
-else
-  ifeq ($(CONFIG_VIDEO_STRADIS),m)
-  M_OBJS += stradis.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_AZTECH),y)
-O_OBJS += radio-aztech.o
-else
-  ifeq ($(CONFIG_RADIO_AZTECH),m)
-  M_OBJS += radio-aztech.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_RTRACK2),y)
-O_OBJS += radio-rtrack2.o
-else
-  ifeq ($(CONFIG_RADIO_RTRACK2),m)
-  M_OBJS += radio-rtrack2.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_SF16FMI),y)
-O_OBJS += radio-sf16fmi.o
-else
-  ifeq ($(CONFIG_RADIO_SF16FMI),m)
-  M_OBJS += radio-sf16fmi.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_CADET),y)
-O_OBJS += radio-cadet.o
-else
-  ifeq ($(CONFIG_RADIO_CADET),m)
-  M_OBJS += radio-cadet.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_TYPHOON),y)
-O_OBJS += radio-typhoon.o
-else
-  ifeq ($(CONFIG_RADIO_TYPHOON),m)
-  M_OBJS += radio-typhoon.o
+    L_I2C=m
+    L_DECODERS=m
   endif
 endif
 
-ifeq ($(CONFIG_RADIO_TERRATEC),y)
-O_OBJS += radio-terratec.o
-else
-  ifeq ($(CONFIG_RADIO_TERRATEC),m)
-  M_OBJS += radio-terratec.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_RTRACK),y)
-O_OBJS += radio-aimslab.o
-else
-  ifeq ($(CONFIG_RADIO_RTRACK),m)
-  M_OBJS += radio-aimslab.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_ZOLTRIX),y)
-O_OBJS += radio-zoltrix.o
-else
-  ifeq ($(CONFIG_RADIO_ZOLTRIX),m)
-  M_OBJS += radio-zoltrix.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_MIROPCM20),y)
-O_OBJS += radio-miropcm20.o
-else
-  ifeq ($(CONFIG_RADIO_MIROPCM20),m)
-  M_OBJS += radio-miropcm20.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_GEMTEK),y)
-O_OBJS += radio-gemtek.o
-else
-  ifeq ($(CONFIG_RADIO_GEMTEK),m)
-  M_OBJS += radio-gemtek.o
-  endif
-endif
-
-ifeq ($(CONFIG_RADIO_TRUST),y)
-O_OBJS += radio-trust.o
-else
-  ifeq ($(CONFIG_RADIO_TRUST),m)
-  M_OBJS += radio-trust.o
-  endif
-endif
-
-ifeq ($(CONFIG_QIC02_TAPE),y)
-O_OBJS += tpqic02.o
-else
-  ifeq ($(CONFIG_QIC02_TAPE),m)
-  M_OBJS += tpqic02.o
-  endif
-endif
+obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
+obj-$(CONFIG_VIDEO_PMS) += pms.o
+obj-$(CONFIG_VIDEO_PLANB) += planb.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o
+obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
+obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
+obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
+obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o
+obj-$(CONFIG_RADIO_CADET) += radio-cadet.o
+obj-$(CONFIG_RADIO_TYPHOON) += radio-typhoon.o
+obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o
+obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
+obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
+obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
+obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
+obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
+obj-$(CONFIG_QIC02_TAPE) += tpqic02.o
 
 ifeq ($(CONFIG_FTAPE),y)
-O_OBJS       += ftape/ftape.o
+obj-y       += ftape/ftape.o
 SUB_DIRS     += ftape
 ifneq ($(CONFIG_ZFTAPE),n)
 MOD_SUB_DIRS += ftape
@@ -624,45 +243,17 @@
   endif
 endif
 
-ifdef CONFIG_H8
-OX_OBJS += h8.o
-endif
-
-ifeq ($(CONFIG_PPDEV),y)
-O_OBJS += ppdev.o
-else
-  ifeq ($(CONFIG_PPDEV),m)
-  M_OBJS += ppdev.o
-  endif
-endif
-
+obj-$(CONFIG_H8) += h8.o
+obj-$(CONFIG_PPDEV) += ppdev.o
 
 # set when a framegrabber supports external tuners
-ifeq ($(L_TUNERS),y)
-O_OBJS += tuner.o
-else
-  ifeq ($(M_TUNERS),y)
-    M_OBJS += tuner.o
-  endif
-endif
+obj-$(L_TUNERS) += tuner.o
 
 # set when a framegrabber supports external decoders
-ifeq ($(L_DECODERS),y)
-O_OBJS += saa7110.o saa7111.o saa7185.o
-else
-  ifeq ($(M_DECODERS),y)
-    M_OBJS += saa7110.o saa7111.o saa7185.o
-  endif
-endif
+obj-$(L_DECODERS) += saa7110.o saa7111.o saa7185.o
 
 # set when a framegrabber implements i2c support
-ifeq ($(L_I2C),y)
-OX_OBJS += i2c-old.o
-else
- ifeq ($(M_I2C),y)
- MX_OBJS += i2c-old.o
-  endif
-endif
+obj-$(L_I2C) += i2c-old.o
 
 ifeq ($(CONFIG_DRM),y)
   SUB_DIRS += drm
@@ -689,6 +280,30 @@
     MOD_SUB_DIRS += agp
   endif
 endif
+
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
+
+multi-y         := $(filter $(list-multi), $(obj-y))
+multi-m         := $(filter $(list-multi), $(obj-m))
+int-y           := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m           := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
+
+# Files that are both resident and modular: remove from modular.
+
+obj-m           := $(filter-out $(obj-y), $(obj-m))
+int-m           := $(filter-out $(int-y), $(int-m))
+
+# Take multi-part drivers out of obj-y and put components in.
+
+obj-y           := $(filter-out $(list-multi), $(obj-y)) $(int-y)
+
+# Translate to Rules.make lists.
+
+O_OBJS          := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS         := $(filter     $(export-objs), $(obj-y))
+M_OBJS          := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS         := $(sort $(filter     $(export-objs), $(obj-m)))
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.3.42/linux/drivers/char/acquirewdt.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/char/acquirewdt.c	Wed Feb  9 11:42:35 2000
@@ -166,16 +166,11 @@
  
  
 static struct file_operations acq_fops = {
-	NULL,
-	acq_read,
-	acq_write,
-	NULL,		/* No Readdir */
-	NULL,		/* No Select */
-	acq_ioctl,
-	NULL,		/* No mmap */
-	acq_open,
-	NULL,		/* flush */
-	acq_close
+	read:		acq_read,
+	write:		acq_write,
+	ioctl:		acq_ioctl,
+	open:		acq_open,
+	release:	acq_close,
 };
 
 static struct miscdevice acq_miscdev=
diff -u --recursive --new-file v2.3.42/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h
--- v2.3.42/linux/drivers/char/agp/agp.h	Wed Dec 15 10:43:16 1999
+++ linux/drivers/char/agp/agp.h	Thu Feb 10 12:22:03 2000
@@ -112,26 +112,6 @@
 	int (*remove_memory) (agp_memory *, off_t, int);
 	agp_memory *(*alloc_by_type) (size_t, int);
 	void (*free_by_type) (agp_memory *);
-
-	/* Links to vendor/device specific setup functions */
-#ifdef CONFIG_AGP_INTEL
-	void (*intel_generic_setup) (void);
-#endif
-#ifdef CONFIG_AGP_I810
-	void (*intel_i810_setup) (struct pci_dev *);
-#endif
-#ifdef CONFIG_AGP_VIA
-	void (*via_generic_setup) (void);
-#endif
-#ifdef CONFIG_AGP_SIS
-	void (*sis_generic_setup) (void);
-#endif
-#ifdef CONFIG_AGP_AMD
-	void (*amd_irongate_setup) (void);
-#endif
-#ifdef CONFIG_AGP_ALI
-	void (*ali_generic_setup) (void);
-#endif
 };
 
 #define OUTREG32(mmap, addr, val)   __raw_writel((val), (mmap)+(addr))
@@ -156,6 +136,11 @@
 #ifndef min
 #define min(a,b)	(((a)<(b))?(a):(b))
 #endif
+
+#define arraysize(x)            (sizeof(x)/sizeof(*(x)))
+
+#define AGPGART_MODULE_NAME	"agpgart"
+#define PFX			AGPGART_MODULE_NAME ": "
 
 #define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge.scratch_page)
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c
--- v2.3.42/linux/drivers/char/agp/agpgart_be.c	Tue Feb  1 01:35:43 2000
+++ linux/drivers/char/agp/agpgart_be.c	Thu Feb 10 12:22:03 2000
@@ -96,7 +96,7 @@
 {
 	atomic_set(&cpus_waiting, smp_num_cpus - 1);
 	if (smp_call_function(ipi_handler, NULL, 1, 0) != 0)
-		panic("agpgart: timed out waiting for the other CPUs!\n");
+		panic(PFX "timed out waiting for the other CPUs!\n");
 	flush_cache();
 	while (atomic_read(&cpus_waiting) > 0)
 		barrier();
@@ -811,7 +811,7 @@
 	values = A_SIZE_FIX(agp_bridge.aperture_sizes);
 
 	if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
-		printk("agpgart: i810 is disabled\n");
+		printk(KERN_WARNING PFX "i810 is disabled\n");
 		return 0;
 	}
 	if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
@@ -846,8 +846,7 @@
 	if ((INREG32(intel_i810_private.registers, I810_DRAM_CTL)
 	     & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
 		/* This will need to be dynamically assigned */
-		printk(KERN_INFO
-		       "agpgart: detected 4MB dedicated video ram.\n");
+		printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
 		intel_i810_private.num_dcache_entries = 1024;
 	}
 	pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
@@ -1024,7 +1023,7 @@
 	return addr | agp_bridge.masks[type].mask;
 }
 
-static void intel_i810_setup(struct pci_dev *i810_dev)
+static int __init intel_i810_setup(struct pci_dev *i810_dev)
 {
 	intel_i810_private.i810_dev = i810_dev;
 
@@ -1048,9 +1047,11 @@
 	agp_bridge.remove_memory = intel_i810_remove_entries;
 	agp_bridge.alloc_by_type = intel_i810_alloc_by_type;
 	agp_bridge.free_by_type = intel_i810_free_by_type;
+
+	return 0;
 }
 
-#endif
+#endif /* CONFIG_AGP_I810 */
 
 #ifdef CONFIG_AGP_INTEL
 
@@ -1150,7 +1151,7 @@
 	{4, 1024, 0, 63}
 };
 
-static void intel_generic_setup(void)
+static int __init intel_generic_setup (struct pci_dev *pdev)
 {
 	agp_bridge.masks = intel_generic_masks;
 	agp_bridge.num_of_masks = 1;
@@ -1172,9 +1173,13 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+
+	return 0;
+	
+	(void) pdev; /* unused */
 }
 
-#endif
+#endif /* CONFIG_AGP_INTEL */
 
 #ifdef CONFIG_AGP_VIA
 
@@ -1259,7 +1264,7 @@
 	{0x00000000, 0}
 };
 
-static void via_generic_setup(void)
+static int __init via_generic_setup (struct pci_dev *pdev)
 {
 	agp_bridge.masks = via_generic_masks;
 	agp_bridge.num_of_masks = 1;
@@ -1281,9 +1286,13 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+
+	return 0;
+	
+	(void) pdev; /* unused */
 }
 
-#endif
+#endif /* CONFIG_AGP_VIA */
 
 #ifdef CONFIG_AGP_SIS
 
@@ -1364,7 +1373,7 @@
 	{0x00000000, 0}
 };
 
-static void sis_generic_setup(void)
+static int __init sis_generic_setup (struct pci_dev *pdev)
 {
 	agp_bridge.masks = sis_generic_masks;
 	agp_bridge.num_of_masks = 1;
@@ -1386,9 +1395,13 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+
+	return 0;
+	
+	(void) pdev; /* unused */
 }
 
-#endif
+#endif /* CONFIG_AGP_SIS */
 
 #ifdef CONFIG_AGP_AMD
 
@@ -1523,7 +1536,7 @@
 	{0x00000001, 0}
 };
 
-static void amd_irongate_setup(void)
+static int __init amd_irongate_setup (struct pci_dev *pdev)
 {
 	agp_bridge.masks = amd_irongate_masks;
 	agp_bridge.num_of_masks = 1;
@@ -1545,9 +1558,13 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+
+	return 0;
+	
+	(void) pdev; /* unused */
 }
 
-#endif
+#endif /* CONFIG_AGP_AMD */
 
 #ifdef CONFIG_AGP_ALI
 
@@ -1645,7 +1662,7 @@
 	{4, 1024, 0, 3}
 };
 
-static void ali_generic_setup(void)
+static int __init ali_generic_setup (struct pci_dev *pdev)
 {
 	agp_bridge.masks = ali_generic_masks;
 	agp_bridge.num_of_masks = 1;
@@ -1667,24 +1684,188 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+
+	return 0;
+	
+	(void) pdev; /* unused */
 }
 
-#endif
+#endif /* CONFIG_AGP_ALI */
 
 
+/* per-chipset initialization data.
+ * note -- all chipsets for a single vendor MUST be grouped together
+ */
+static struct {
+	unsigned short device_id; /* first, to make table easier to read */
+	unsigned short vendor_id;
+	enum chipset_type chipset;
+	const char *vendor_name;
+	const char *chipset_name;
+	int (*chipset_setup) (struct pci_dev *pdev);
+} agp_bridge_info[] __initdata = {
+
+#ifdef CONFIG_AGP_ALI
+	{ PCI_DEVICE_ID_AL_M1541_0,
+		PCI_VENDOR_ID_AL,
+		ALI_M1541,
+		"Ali",
+		"M1541",
+		ali_generic_setup },
+	{ 0,
+		PCI_VENDOR_ID_AL,
+		ALI_GENERIC,
+		"Ali",
+		"Generic",
+		ali_generic_setup },
+#endif /* CONFIG_AGP_ALI */
+
+#ifdef CONFIG_AGP_AMD
+	{ PCI_DEVICE_ID_AMD_IRONGATE_0,
+		PCI_VENDOR_ID_AMD,
+		AMD_IRONGATE,
+		"AMD",
+		"Irongate",
+		amd_irongate_setup },
+	{ 0,
+		PCI_VENDOR_ID_AMD,
+		AMD_GENERIC,
+		"AMD",
+		"Generic",
+		amd_irongate_setup },
+#endif /* CONFIG_AGP_AMD */
+
+#ifdef CONFIG_AGP_INTEL
+	{ PCI_DEVICE_ID_INTEL_82443LX_0,
+		PCI_VENDOR_ID_INTEL,
+		INTEL_LX,
+		"Intel",
+		"440LX",
+		intel_generic_setup },
+	{ PCI_DEVICE_ID_INTEL_82443BX_0,
+		PCI_VENDOR_ID_INTEL,
+		INTEL_BX,
+		"Intel",
+		"440BX",
+		intel_generic_setup },
+	{ PCI_DEVICE_ID_INTEL_82443GX_0,
+		PCI_VENDOR_ID_INTEL,
+		INTEL_GX,
+		"Intel",
+		"440GX",
+		intel_generic_setup },
+	{ 0,
+		PCI_VENDOR_ID_INTEL,
+		INTEL_GENERIC,
+		"Intel",
+		"Generic",
+		intel_generic_setup },
+#endif /* CONFIG_AGP_INTEL */
+
+#ifdef CONFIG_AGP_SIS
+	{ 0,
+		PCI_VENDOR_ID_SI,
+		SIS_GENERIC,
+		"SiS",
+		"Generic",
+		sis_generic_setup },
+#endif /* CONFIG_AGP_SIS */
+
+#ifdef CONFIG_AGP_VIA
+	{ PCI_DEVICE_ID_VIA_8501_0,
+		PCI_VENDOR_ID_VIA,
+		VIA_MVP4,
+		"Via",
+		"MVP4",
+		via_generic_setup },
+	{ PCI_DEVICE_ID_VIA_82C597_0,
+		PCI_VENDOR_ID_VIA,
+		VIA_VP3,
+		"Via",
+		"VP3",
+		via_generic_setup },
+	{ PCI_DEVICE_ID_VIA_82C598_0,
+		PCI_VENDOR_ID_VIA,
+		VIA_MVP3,
+		"Via",
+		"MVP3",
+		via_generic_setup },
+	{ PCI_DEVICE_ID_VIA_82C691_0,
+		PCI_VENDOR_ID_VIA,
+		VIA_APOLLO_PRO,
+		"Via",
+		"Apollo Pro",
+		via_generic_setup },
+	{ 0,
+		PCI_VENDOR_ID_VIA,
+		VIA_GENERIC,
+		"Via",
+		"Generic",
+		via_generic_setup },
+#endif /* CONFIG_AGP_VIA */
+
+	{ 0, }, /* dummy final entry, always present */
+};
+
+
+/* scan table above for supported devices */
+static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
+{
+	int i;
+	
+	for (i = 0; i < arraysize (agp_bridge_info); i++)
+		if (pdev->vendor == agp_bridge_info[i].vendor_id)
+			break;
+
+	if (i >= arraysize (agp_bridge_info)) {
+		printk (KERN_DEBUG PFX "unsupported bridge\n");
+		return -ENODEV;
+	}
+
+	while ((i < arraysize (agp_bridge_info)) &&
+	       (agp_bridge_info[i].vendor_id == pdev->vendor)) {
+		if (pdev->device == agp_bridge_info[i].device_id) {
+			printk (KERN_INFO PFX "Detected %s %s chipset\n",
+				agp_bridge_info[i].vendor_name,
+				agp_bridge_info[i].chipset_name);
+			agp_bridge.type = agp_bridge_info[i].chipset;
+			return agp_bridge_info[i].chipset_setup (pdev);
+		}
+		
+		i++;
+	}
+
+	i--; /* point to vendor generic entry (device_id == 0) */
+
+	/* try init anyway, if user requests it AND
+	 * there is a 'generic' bridge entry for this vendor */
+	if (agp_try_unsupported && agp_bridge_info[i].device_id == 0) {
+		printk(KERN_WARNING PFX "Trying generic %s routines"
+		       " for device id: %x\n",
+		       agp_bridge_info[i].vendor_name, pdev->device);
+		agp_bridge.type = agp_bridge_info[i].chipset;
+		return agp_bridge_info[i].chipset_setup (pdev);
+	}
+
+	printk(KERN_ERR PFX "Unsupported %s chipset,"
+	       " you might want to try "
+	       "agp_try_unsupported=1.\n",
+	       agp_bridge_info[i].vendor_name);
+	return -ENODEV;
+}
+
 
 /* Supported Device Scanning routine */
 
-static void agp_find_supported_device(void)
+static int __init agp_find_supported_device(void)
 {
 	struct pci_dev *dev = NULL;
 	u8 cap_ptr = 0x00;
 	u32 cap_id, scratch;
 
-	if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL) {
-		agp_bridge.type = NOT_SUPPORTED;
-		return;
-	}
+	if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL)
+		return -ENODEV;
+
 	agp_bridge.dev = dev;
 
 	/* Need to test for I810 here */
@@ -1698,65 +1879,58 @@
 					       PCI_DEVICE_ID_INTEL_810_1,
 						   NULL);
 			if (i810_dev == NULL) {
-				printk("agpgart: Detected an Intel i810,"
+				printk(KERN_ERR PFX "Detected an Intel i810,"
 				       " but could not find the secondary"
 				       " device.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
+				return -ENODEV;
 			}
-			printk(KERN_INFO "agpgart: Detected an Intel "
+			printk(KERN_INFO PFX "Detected an Intel "
 			       "i810 Chipset.\n");
 			agp_bridge.type = INTEL_I810;
-			agp_bridge.intel_i810_setup(i810_dev);
-			return;
+			return intel_i810_setup (i810_dev);
 
 		case PCI_DEVICE_ID_INTEL_810_DC100_0:
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
 					 PCI_DEVICE_ID_INTEL_810_DC100_1,
 						   NULL);
 			if (i810_dev == NULL) {
-				printk("agpgart: Detected an Intel i810 "
+				printk(KERN_ERR PFX "Detected an Intel i810 "
 				       "DC100, but could not find the "
 				       "secondary device.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
+				return -ENODEV;
 			}
-			printk(KERN_INFO "agpgart: Detected an Intel i810 "
+			printk(KERN_INFO PFX "Detected an Intel i810 "
 			       "DC100 Chipset.\n");
 			agp_bridge.type = INTEL_I810;
-			agp_bridge.intel_i810_setup(i810_dev);
-			return;
+			return intel_i810_setup(i810_dev);
 
 		case PCI_DEVICE_ID_INTEL_810_E_0:
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
 					     PCI_DEVICE_ID_INTEL_810_E_1,
 						   NULL);
 			if (i810_dev == NULL) {
-				printk("agpgart: Detected an Intel i810 E"
+				printk(KERN_ERR PFX "Detected an Intel i810 E"
 				    ", but could not find the secondary "
 				       "device.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
+				return -ENODEV;
 			}
-			printk(KERN_INFO "agpgart: Detected an Intel i810 E "
+			printk(KERN_INFO PFX "Detected an Intel i810 E "
 			       "Chipset.\n");
 			agp_bridge.type = INTEL_I810;
-			agp_bridge.intel_i810_setup(i810_dev);
-			return;
+			return intel_i810_setup(i810_dev);
+
 		default:
 			break;
 		}
 	}
-#endif
+#endif /* CONFIG_AGP_I810 */
+
 	/* find capndx */
 	pci_read_config_dword(dev, 0x04, &scratch);
+	if (!(scratch & 0x00100000))
+		return -ENODEV;
 
-	if (!(scratch & 0x00100000)) {
-		agp_bridge.type = NOT_SUPPORTED;
-		return;
-	}
 	pci_read_config_byte(dev, 0x34, &cap_ptr);
-
 	if (cap_ptr != 0x00) {
 		do {
 			pci_read_config_dword(dev, cap_ptr, &cap_id);
@@ -1766,10 +1940,8 @@
 		}
 		while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
 	}
-	if (cap_ptr == 0x00) {
-		agp_bridge.type = NOT_SUPPORTED;
-		return;
-	}
+	if (cap_ptr == 0x00)
+		return -ENODEV;
 	agp_bridge.capndx = cap_ptr;
 
 	/* Fill in the mode register */
@@ -1777,175 +1949,8 @@
 			      agp_bridge.capndx + 4,
 			      &agp_bridge.mode);
 
-	switch (dev->vendor) {
-#ifdef CONFIG_AGP_INTEL
-	case PCI_VENDOR_ID_INTEL:
-		switch (dev->device) {
-		case PCI_DEVICE_ID_INTEL_82443LX_0:
-			agp_bridge.type = INTEL_LX;
-			printk(KERN_INFO "agpgart: Detected an Intel 440LX"
-			       " Chipset.\n");
-			agp_bridge.intel_generic_setup();
-			return;
-
-		case PCI_DEVICE_ID_INTEL_82443BX_0:
-			agp_bridge.type = INTEL_BX;
-			printk(KERN_INFO "agpgart: Detected an Intel 440BX "
-			       "Chipset.\n");
-			agp_bridge.intel_generic_setup();
-			return;
-
-		case PCI_DEVICE_ID_INTEL_82443GX_0:
-			agp_bridge.type = INTEL_GX;
-			printk(KERN_INFO "agpgart: Detected an Intel 440GX "
-			       "Chipset.\n");
-			agp_bridge.intel_generic_setup();
-			return;
-
-		default:
-			if (agp_try_unsupported != 0) {
-				printk("agpgart: Trying generic intel "
-				       "routines for device id: %x\n",
-				       dev->device);
-				agp_bridge.type = INTEL_GENERIC;
-				agp_bridge.intel_generic_setup();
-				return;
-			} else {
-				printk("agpgart: Unsupported intel chipset,"
-				       " you might want to try "
-				       "agp_try_unsupported=1.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
-			}
-		}
-		break;
-#endif
-
-#ifdef CONFIG_AGP_VIA
-	case PCI_VENDOR_ID_VIA:
-		switch (dev->device) {
-		case PCI_DEVICE_ID_VIA_82C597_0:
-			agp_bridge.type = VIA_VP3;
-			printk(KERN_INFO "agpgart: Detected a VIA VP3 "
-			       "Chipset.\n");
-			agp_bridge.via_generic_setup();
-			return;
-
-		case PCI_DEVICE_ID_VIA_82C598_0:
-			agp_bridge.type = VIA_MVP3;
-			printk(KERN_INFO "agpgart: Detected a VIA MVP3 "
-			       "Chipset.\n");
-			agp_bridge.via_generic_setup();
-			return;
-
-		case PCI_DEVICE_ID_VIA_82C691_0:
-			agp_bridge.type = VIA_APOLLO_PRO;
-			printk(KERN_INFO "agpgart: Detected a VIA Apollo "
-			       "Pro Chipset.\n");
-			agp_bridge.via_generic_setup();
-			return;
-
-		default:
-			if (agp_try_unsupported != 0) {
-				printk("agpgart: Trying generic VIA routines"
-				    " for device id: %x\n", dev->device);
-				agp_bridge.type = VIA_GENERIC;
-				agp_bridge.via_generic_setup();
-				return;
-			} else {
-				printk("agpgart: Unsupported VIA chipset,"
-				       " you might want to try "
-				       "agp_try_unsupported=1.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
-			}
-		}
-		break;
-#endif
-
-#ifdef CONFIG_AGP_SIS
-	case PCI_VENDOR_ID_SI:
-		switch (dev->device) {
-			/* ToDo need to find out the
-			 * specific devices supported.
-			 */
-		default:
-			if (agp_try_unsupported != 0) {
-				printk("agpgart: Trying generic SiS routines"
-				    " for device id: %x\n", dev->device);
-				agp_bridge.type = SIS_GENERIC;
-				agp_bridge.sis_generic_setup();
-				return;
-			} else {
-				printk("agpgart: Unsupported SiS chipset, "
-				       "you might want to try "
-				       "agp_try_unsupported=1.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
-			}
-		}
-		break;
-#endif
-
-#ifdef CONFIG_AGP_AMD
-	case PCI_VENDOR_ID_AMD:
-		switch (dev->device) {
-		case PCI_DEVICE_ID_AMD_IRONGATE_0:
-			agp_bridge.type = AMD_IRONGATE;
-			printk(KERN_INFO "agpgart: Detected an AMD Irongate"
-			       " Chipset.\n");
-			agp_bridge.amd_irongate_setup();
-			return;
-
-		default:
-			if (agp_try_unsupported != 0) {
-				printk("agpgart: Trying Amd irongate"
-				       " routines for device id: %x\n",
-				       dev->device);
-				agp_bridge.type = AMD_GENERIC;
-				agp_bridge.amd_irongate_setup();
-				return;
-			} else {
-				printk("agpgart: Unsupported Amd chipset,"
-				       " you might want to try "
-				       "agp_try_unsupported=1.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
-			}
-		}
-		break;
-#endif
-
-#ifdef CONFIG_AGP_ALI
-	case PCI_VENDOR_ID_AL:
-		switch (dev->device) {
-		case PCI_DEVICE_ID_AL_M1541_0:
-			agp_bridge.type = ALI_M1541;
-			printk(KERN_INFO "agpgart: Detected an ALi M1541"
-			       " Chipset\n");
-			agp_bridge.ali_generic_setup();
-			return;
-		default:
-			if (agp_try_unsupported != 0) {
-				printk("agpgart: Trying ALi generic routines"
-				    " for device id: %x\n", dev->device);
-				agp_bridge.type = ALI_GENERIC;
-				agp_bridge.ali_generic_setup();
-				return;
-			} else {
-				printk("agpgart: Unsupported ALi chipset,"
-				       " you might want to type "
-				       "agp_try_unsupported=1.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return;
-			}
-		}
-		break;
-#endif
-	default:
-		agp_bridge.type = NOT_SUPPORTED;
-		return;
-	}
+	/* probe for known chipsets */
+	return agp_lookup_host_bridge (dev);
 }
 
 struct agp_max_table {
@@ -1953,7 +1958,7 @@
 	int agp;
 };
 
-static struct agp_max_table maxes_table[9] =
+static struct agp_max_table maxes_table[9] __initdata =
 {
 	{0, 0},
 	{32, 4},
@@ -1966,7 +1971,7 @@
 	{4096, 3932}
 };
 
-static int agp_find_max(void)
+static int __init agp_find_max (void)
 {
 	long memory, index, result;
 
@@ -1983,7 +1988,7 @@
 	     (maxes_table[index].agp - maxes_table[index - 1].agp)) /
 	   (maxes_table[index].mem - maxes_table[index - 1].mem);
 
-	printk(KERN_INFO "agpgart: Maximum main memory to use "
+	printk(KERN_INFO PFX "Maximum main memory to use "
 	       "for agp memory: %ldM\n", result);
 	result = result << (20 - PAGE_SHIFT);
         return result;
@@ -1998,39 +2003,27 @@
 	AGPGART_VERSION_MINOR
 };
 
-static int agp_backend_initialize(void)
+static int __init agp_backend_initialize(void)
 {
-	int size_value;
+	int size_value, rc, got_gatt=0, got_keylist=0;
 
 	memset(&agp_bridge, 0, sizeof(struct agp_bridge_data));
 	agp_bridge.type = NOT_SUPPORTED;
-#ifdef CONFIG_AGP_INTEL
-	agp_bridge.intel_generic_setup = intel_generic_setup;
-#endif
-#ifdef CONFIG_AGP_I810
-	agp_bridge.intel_i810_setup = intel_i810_setup;
-#endif
-#ifdef CONFIG_AGP_VIA
-	agp_bridge.via_generic_setup = via_generic_setup;
-#endif
-#ifdef CONFIG_AGP_SIS
-	agp_bridge.sis_generic_setup = sis_generic_setup;
-#endif
-#ifdef CONFIG_AGP_AMD
-	agp_bridge.amd_irongate_setup = amd_irongate_setup;
-#endif
-#ifdef CONFIG_AGP_ALI
-	agp_bridge.ali_generic_setup = ali_generic_setup;
-#endif
 	agp_bridge.max_memory_agp = agp_find_max();
 	agp_bridge.version = &agp_current_version;
-	agp_find_supported_device();
+
+	rc = agp_find_supported_device();
+	if (rc) {
+		/* not KERN_ERR because error msg should have already printed */
+		printk(KERN_DEBUG PFX "no supported devices found.\n");
+		return rc;
+	}
 
 	if (agp_bridge.needs_scratch_page == TRUE) {
 		agp_bridge.scratch_page = agp_alloc_page();
 
 		if (agp_bridge.scratch_page == 0) {
-			printk("agpgart: unable to get memory for "
+			printk(KERN_ERR PFX "unable to get memory for "
 			       "scratch page.\n");
 			return -ENOMEM;
 		}
@@ -2039,43 +2032,59 @@
 		agp_bridge.scratch_page =
 		    agp_bridge.mask_memory(agp_bridge.scratch_page, 0);
 	}
-	if (agp_bridge.type == NOT_SUPPORTED) {
-		printk("agpgart: no supported devices found.\n");
-		return -EINVAL;
-	}
+
 	size_value = agp_bridge.fetch_size();
 
 	if (size_value == 0) {
-		printk("agpgart: unable to detrimine aperture size.\n");
-		return -EINVAL;
+		printk(KERN_ERR PFX "unable to detrimine aperture size.\n");
+		rc = -EINVAL;
+		goto err_out;
 	}
 	if (agp_bridge.create_gatt_table()) {
-		printk("agpgart: unable to get memory for graphics "
+		printk(KERN_ERR PFX "unable to get memory for graphics "
 		       "translation table.\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto err_out;
 	}
+	got_gatt = 1;
+	
 	agp_bridge.key_list = vmalloc(PAGE_SIZE * 4);
-
 	if (agp_bridge.key_list == NULL) {
-		printk("agpgart: error allocating memory for key lists.\n");
-		agp_bridge.free_gatt_table();
-		return -ENOMEM;
-	}
+		printk(KERN_ERR PFX "error allocating memory for key lists.\n");
+		rc = -ENOMEM;
+		goto err_out;
+	}
+	got_keylist = 1;
+	
+	/* FIXME vmalloc'd memory not guaranteed contiguous */
 	memset(agp_bridge.key_list, 0, PAGE_SIZE * 4);
 
 	if (agp_bridge.configure()) {
-		printk("agpgart: error configuring host chipset.\n");
-		agp_bridge.free_gatt_table();
-		vfree(agp_bridge.key_list);
-		return -EINVAL;
+		printk(KERN_ERR PFX "error configuring host chipset.\n");
+		rc = -EINVAL;
+		goto err_out;
 	}
-	printk(KERN_INFO "agpgart: Physical address of the agp aperture:"
-	       " 0x%lx\n", agp_bridge.gart_bus_addr);
-	printk(KERN_INFO "agpgart: Agp aperture is %dM in size.\n",
-	       size_value);
+
+	printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
+	       size_value, agp_bridge.gart_bus_addr);
+
 	return 0;
+
+err_out:
+	if (agp_bridge.needs_scratch_page == TRUE) {
+		agp_bridge.scratch_page &= ~(0x00000fff);
+		agp_destroy_page((unsigned long)
+				 phys_to_virt(agp_bridge.scratch_page));
+	}
+	if (got_gatt)
+		agp_bridge.free_gatt_table();
+	if (got_keylist)
+		vfree(agp_bridge.key_list);
+	return rc;
 }
 
+
+/* cannot be __exit b/c as it could be called from __init code */
 static void agp_backend_cleanup(void)
 {
 	agp_bridge.cleanup();
@@ -2098,17 +2107,17 @@
 
 	printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Jeff Hartmann\n",
 	       AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
-	ret_val = agp_backend_initialize();
 
-	if (ret_val != 0) {
+	ret_val = agp_backend_initialize();
+	if (ret_val)
 		return ret_val;
-	}
-	ret_val = agp_frontend_initialize();
 
-	if (ret_val != 0) {
+	ret_val = agp_frontend_initialize();
+	if (ret_val) {
 		agp_backend_cleanup();
 		return ret_val;
 	}
+
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/agp/agpgart_fe.c linux/drivers/char/agp/agpgart_fe.c
--- v2.3.42/linux/drivers/char/agp/agpgart_fe.c	Tue Feb  1 01:35:43 2000
+++ linux/drivers/char/agp/agpgart_fe.c	Thu Feb 10 12:41:51 2000
@@ -47,6 +47,8 @@
 #include <asm/page.h>
 #include <asm/mman.h>
 
+#include "agp.h"
+
 static struct agp_front_data agp_fe;
 
 static agp_memory *agp_find_mem_by_key(int key)
@@ -298,7 +300,7 @@
 	agp_memory *memory;
 
 	memory = agp_allocate_memory(pg_count, type);
-   printk("memory : %p\n", memory);
+   	printk(KERN_DEBUG "memory : %p\n", memory);
 	if (memory == NULL) {
 		return NULL;
 	}
@@ -969,132 +971,123 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	agp_file_private *curr_priv = (agp_file_private *) file->private_data;
-	int ret_val;
+	int ret_val = -ENOTTY;
 
 	AGP_LOCK();
 
 	if ((agp_fe.current_controller == NULL) &&
 	    (cmd != AGPIOC_ACQUIRE)) {
-		return -EINVAL;
+		ret_val = -EINVAL;
+	   	goto ioctl_out;
 	}
 	if ((agp_fe.backend_acquired != TRUE) &&
 	    (cmd != AGPIOC_ACQUIRE)) {
-		return -EBUSY;
+		ret_val = -EBUSY;
+	   	goto ioctl_out;
 	}
 	if (cmd != AGPIOC_ACQUIRE) {
 		if (!(test_bit(AGP_FF_IS_CONTROLLER,
 			       &curr_priv->access_flags))) {
-			return -EPERM;
+			ret_val = -EPERM;
+		   	goto ioctl_out;
 		}
 		/* Use the original pid of the controller,
 		 * in case it's threaded */
 
 		if (agp_fe.current_controller->pid != curr_priv->my_pid) {
-			return -EBUSY;
+			ret_val = -EBUSY;
+		   	goto ioctl_out;
 		}
 	}
 	switch (cmd) {
 	case AGPIOC_INFO:
 		{
 			ret_val = agpioc_info_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_ACQUIRE:
 		{
 			ret_val = agpioc_acquire_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_RELEASE:
 		{
 			ret_val = agpioc_release_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_SETUP:
 		{
 			ret_val = agpioc_setup_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_RESERVE:
 		{
 			ret_val = agpioc_reserve_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_PROTECT:
 		{
 			ret_val = agpioc_protect_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_ALLOCATE:
 		{
 			ret_val = agpioc_allocate_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_DEALLOCATE:
 		{
 			ret_val = agpioc_deallocate_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_BIND:
 		{
 			ret_val = agpioc_bind_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	case AGPIOC_UNBIND:
 		{
 			ret_val = agpioc_unbind_wrap(curr_priv, arg);
-			AGP_UNLOCK();
-			return ret_val;
+		   	goto ioctl_out;
 		}
 	}
-
+   
+ioctl_out:
 	AGP_UNLOCK();
-	return -ENOTTY;
+	return ret_val;
 }
 
 static struct file_operations agp_fops =
 {
-	agp_lseek,
-	agp_read,
-	agp_write,
-	NULL,
-	NULL,
-	agp_ioctl,
-	agp_mmap,
-	agp_open,
-	NULL,
-	agp_release
+	llseek:		agp_lseek,
+	read:		agp_read,
+	write:		agp_write,
+	ioctl:		agp_ioctl,
+	mmap:		agp_mmap,
+	open:		agp_open,
+	release:	agp_release,
 };
 
 static struct miscdevice agp_miscdev =
 {
 	AGPGART_MINOR,
-	"agpgart",
+	AGPGART_MODULE_NAME,
 	&agp_fops
 };
 
-int agp_frontend_initialize(void)
+int __init agp_frontend_initialize(void)
 {
 	memset(&agp_fe, 0, sizeof(struct agp_front_data));
 	AGP_LOCK_INIT();
 
 	if (misc_register(&agp_miscdev)) {
-		printk("agpgart: unable to get minor: %d\n", AGPGART_MINOR);
+		printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
 		return -EIO;
 	}
 	return 0;
 }
 
-void agp_frontend_cleanup(void)
+void __exit agp_frontend_cleanup(void)
 {
 	misc_deregister(&agp_miscdev);
-	return;
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/char/applicom.c linux/drivers/char/applicom.c
--- v2.3.42/linux/drivers/char/applicom.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/char/applicom.c	Wed Feb  9 11:42:35 2000
@@ -98,17 +98,12 @@
 static void ac_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 
 struct file_operations ac_fops={
-	ac_llseek,      /* llseek */
-	ac_read,        /* read */
-	ac_write,       /* write */
-	NULL,           /* readdir */
-	NULL,           /* poll */
-       	ac_ioctl,       /* ioctl */
-       	NULL,           /* mmap */
-	ac_open,        /* open */
-	NULL,           /* flush */
-	ac_release,     /* release */
-	NULL            /* fsync */
+	llseek:		ac_llseek,
+	read:		ac_read,
+	write:		ac_write,
+	ioctl:		ac_ioctl,
+	open:		ac_open,
+	release:	ac_release,
 };
 
 struct miscdevice ac_miscdev={
diff -u --recursive --new-file v2.3.42/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.42/linux/drivers/char/bttv.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/char/bttv.c	Wed Feb  9 18:48:03 2000
@@ -1765,6 +1765,14 @@
 	return count;
 }
 
+static inline void burst(int on)
+{
+	tvnorms[0].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0);
+	tvnorms[0].hdelayx1     = 186  - (on?BURSTOFFSET  :0);
+	tvnorms[2].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0);
+	tvnorms[2].hdelayx1     = 186  - (on?BURSTOFFSET  :0);
+}
+
 /*
  *	Open a bttv card. Right now the flags stuff is just playing
  */
@@ -1775,6 +1783,7 @@
         int i,ret;
 
 	ret = -EBUSY;
+	down(&btv->lock);
 	if (btv->user)
 		goto out_unlock;
 	
@@ -1789,6 +1798,7 @@
         for (i = 0; i < MAX_GBUFFERS; i++)
                 btv->frame_stat[i] = GBUFFER_UNUSED;
 
+        burst(0);
         btv->user++;
 	up(&btv->lock);
         MOD_INC_USE_COUNT;
@@ -2454,19 +2464,13 @@
 		
 	case BTTV_BURST_ON:
 	{
-		tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2;
-		tvnorms[0].hdelayx1=186-BURSTOFFSET;
-		tvnorms[2].scaledtwidth=1135-BURSTOFFSET-2;
-		tvnorms[2].hdelayx1=186-BURSTOFFSET;
+		burst(1);
 		return 0;
 	}
 
 	case BTTV_BURST_OFF:
 	{
-		tvnorms[0].scaledtwidth=1135;
-		tvnorms[0].hdelayx1=186;
-		tvnorms[2].scaledtwidth=1135;
-		tvnorms[2].hdelayx1=186;
+		burst(0);
 		return 0;
 	}
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.3.42/linux/drivers/char/busmouse.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/char/busmouse.c	Wed Feb  9 11:42:35 2000
@@ -343,18 +343,12 @@
 
 struct file_operations busmouse_fops=
 {
-	NULL,			/* busmouse_seek */
-	busmouse_read,
-	busmouse_write,
-	NULL,			/* busmouse_readdir */
-	busmouse_poll,
-	NULL,			/* busmouse_ioctl */
-	NULL,			/* busmouse_mmap */
-	busmouse_open,
-	NULL,			/* busmouse_flush */
-	busmouse_release,
-	NULL,
-	busmouse_fasync,
+	read:		busmouse_read,
+	write:		busmouse_write,
+	poll:		busmouse_poll,
+	open:		busmouse_open,
+	release:	busmouse_release,
+	fasync:		busmouse_fasync,
 };
 
 int
diff -u --recursive --new-file v2.3.42/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- v2.3.42/linux/drivers/char/dsp56k.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/dsp56k.c	Wed Feb  9 11:42:35 2000
@@ -501,18 +501,11 @@
 }
 
 static struct file_operations dsp56k_fops = {
-	NULL,    /* no special dsp56k_lseek */
-	dsp56k_read,
-	dsp56k_write,
-	NULL,    /* no special dsp56k_readdir */
-	NULL,    /* dsp56k_poll? */
-	dsp56k_ioctl,
-	NULL,    /* no special dsp56k_mmap */
-	dsp56k_open,
-	NULL,	/* flush */
-	dsp56k_release,
-	NULL,    /* no special dsp56k_fsync */
-	NULL,    /* no special dsp56k_fasync */
+	read:		dsp56k_read,
+	write:		dsp56k_write,
+	ioctl:		dsp56k_ioctl,
+	open:		dsp56k_open,
+	release:	dsp56k_release,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/dtlk.c linux/drivers/char/dtlk.c
--- v2.3.42/linux/drivers/char/dtlk.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/dtlk.c	Wed Feb  9 11:42:35 2000
@@ -98,19 +98,12 @@
 
 static struct file_operations dtlk_fops =
 {
-	NULL,			/* lseek */
-	dtlk_read,
-	dtlk_write,
-	NULL,			/* readdir */
-	dtlk_poll,
-	dtlk_ioctl,
-	NULL,			/* mmap */
-	dtlk_open,
-	NULL,			/* flush */
-	dtlk_release,
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	NULL			/* lock */
+	read:		dtlk_read,
+	write:		dtlk_write,
+	poll:		dtlk_poll,
+	ioctl:		dtlk_ioctl,
+	open:		dtlk_open,
+	release:	dtlk_release,
 };
 
 /* local prototypes */
diff -u --recursive --new-file v2.3.42/linux/drivers/char/efirtc.c linux/drivers/char/efirtc.c
--- v2.3.42/linux/drivers/char/efirtc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/efirtc.c	Thu Feb 10 12:38:03 2000
@@ -0,0 +1,356 @@
+/*
+ * EFI Time Services Driver for Linux
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * Based on skeleton from the drivers/char/rtc.c driver by P. Gortmaker
+ *
+ * This code provides a architected & portable interface to the real time 
+ * clock by using EFI instead of direct bit fiddling. The functionalities are 
+ * quite different from the rtc.c driver. The only way to talk to the device 
+ * is by using ioctl(). There is a /proc interface which provides the raw 
+ * information.
+ *
+ * Please note that we have kept the API as close as possible from the 
+ * legacy RTC. The standard /sbin/hwclock program should work normally 
+ * when used to get/set the time.
+ *
+ * NOTES:
+ *	- Locking is required for safe execution of EFI calls with regards
+ *	  to interrrupts and SMP.
+ *
+ * TODO (December 1999):
+ * 	- provide the API to set/get the WakeUp Alarm (different from the
+ *	  rtc.c alarm).
+ *	- SMP testing
+ * 	- Add module support
+ */
+
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/proc_fs.h>
+
+#include <asm/efi.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define EFI_RTC_VERSION		"0.1"
+
+#define EFI_ISDST (EFI_TIME_ADJUST_DAYLIGHT|EFI_TIME_IN_DAYLIGHT)
+/*
+ * EFI Epoch is 1/1/1998
+ */
+#define EFI_RTC_EPOCH		1998
+
+static spinlock_t efi_rtc_lock;
+
+static int efi_rtc_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg);
+
+#define is_leap(year) \
+          ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+static const unsigned short int __mon_yday[2][13] =
+{
+	/* Normal years.  */
+	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+	/* Leap years.  */  
+	{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
+
+/*
+ * returns day of the year [0-365]
+ */
+static inline int
+compute_yday(efi_time_t *eft)
+{
+	/* efi_time_t.month is in the [1-12] so, we need -1 */
+	return  __mon_yday[is_leap(eft->year)][eft->month-1]+ eft->day -1;
+}
+/*
+ * returns day of the week [0-6] 0=Sunday
+ *
+ * Don't try to provide a year that's before 1998, please !
+ */
+static int
+compute_wday(efi_time_t *eft)
+{
+	int y;
+	int ndays = 0;
+
+	if ( eft->year < 1998 ) {
+		printk(KERN_ERR "efirtc: EFI year < 1998, invalid date\n");
+		return -1;
+	}
+
+	for(y=EFI_RTC_EPOCH; y < eft->year; y++ ) {
+		ndays += 365 + (is_leap(y) ? 1 : 0);
+	}
+	ndays += compute_yday(eft);
+
+	/*
+	 * 4=1/1/1998 was a Thursday
+	 */
+	return (ndays + 4) % 7;
+}
+
+static void
+convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft)
+{
+
+	eft->year	= wtime->tm_year + 1900;
+	eft->month	= wtime->tm_mon + 1; 
+	eft->day	= wtime->tm_mday;
+	eft->hour	= wtime->tm_hour;
+	eft->minute	= wtime->tm_min;
+	eft->second 	= wtime->tm_sec;
+	eft->nanosecond = 0; 
+	eft->daylight	= wtime->tm_isdst ? EFI_ISDST: 0;
+	eft->timezone	= EFI_UNSPECIFIED_TIMEZONE;
+}
+
+static void
+convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
+{
+	wtime->tm_sec  = eft->second;
+	wtime->tm_min  = eft->minute;
+	wtime->tm_hour = eft->hour;
+	wtime->tm_mday = eft->day;
+	wtime->tm_mon  = eft->month - 1;
+	wtime->tm_year = eft->year - 1900;
+
+	/* day of the week [0-6], Sunday=0 */
+	wtime->tm_wday = compute_wday(eft);
+
+	/* day in the year [1-365]*/
+	wtime->tm_yday = compute_yday(eft);
+
+
+	switch (eft->daylight & EFI_ISDST) {
+		case EFI_ISDST:
+			wtime->tm_isdst = 1;
+			break;
+		case EFI_TIME_ADJUST_DAYLIGHT:
+			wtime->tm_isdst = 0;
+			break;
+		default:
+			wtime->tm_isdst = -1;
+	}
+}
+
+static int
+efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+
+	efi_status_t	status;
+	unsigned long	flags;
+	efi_time_t	eft;
+	efi_time_cap_t	cap;
+	struct rtc_time	wtime;
+
+	switch (cmd) {
+		case RTC_UIE_ON:
+		case RTC_UIE_OFF:
+		case RTC_PIE_ON:
+		case RTC_PIE_OFF:
+		case RTC_AIE_ON:
+		case RTC_AIE_OFF:
+		case RTC_ALM_SET:
+		case RTC_ALM_READ:
+		case RTC_IRQP_READ:
+		case RTC_IRQP_SET:
+		case RTC_EPOCH_READ:
+		case RTC_EPOCH_SET:
+			return -EINVAL;
+
+		case RTC_RD_TIME:
+
+			spin_lock_irqsave(&efi_rtc_lock, flags);
+
+			status = efi.get_time(&eft, &cap);
+
+			spin_unlock_irqrestore(&efi_rtc_lock,flags);
+
+			if (status != EFI_SUCCESS) {
+				/* should never happen */
+				printk(KERN_ERR "efitime: can't read time\n");
+				return -EINVAL;
+			}
+
+			convert_from_efi_time(&eft, &wtime);
+
+ 			return copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)) ? - EFAULT : 0;
+
+		case RTC_SET_TIME:
+
+			if (!capable(CAP_SYS_TIME)) return -EACCES;
+
+			if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
+				return -EFAULT;
+
+			convert_to_efi_time(&wtime, &eft);
+
+			spin_lock_irqsave(&efi_rtc_lock, flags);
+
+			status = efi.set_time(&eft);
+
+			spin_unlock_irqrestore(&efi_rtc_lock,flags);
+
+			return status == EFI_SUCCESS ? 0 : -EINVAL;
+	}
+	return -EINVAL;
+}
+
+/*
+ *	We enforce only one user at a time here with the open/close.
+ *	Also clear the previous interrupt data on an open, and clean
+ *	up things on a close.
+ */
+
+static int
+efi_rtc_open(struct inode *inode, struct file *file)
+{
+	/*
+	 * nothing special to do here
+	 * We do accept multiple open files at the same time as we
+	 * synchronize on the per call operation.
+	 */
+	return 0;
+}
+
+static int
+efi_rtc_close(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+/*
+ *	The various file operations we support.
+ */
+
+static struct file_operations efi_rtc_fops = {
+	ioctl:		efi_rtc_ioctl,
+	open:		efi_rtc_open,
+	release:	efi_rtc_close,
+};
+
+static struct miscdevice efi_rtc_dev=
+{
+	EFI_RTC_MINOR,
+	"efirtc",
+	&efi_rtc_fops
+};
+
+/*
+ *	We export RAW EFI information to /proc/efirtc
+ */
+static int
+efi_rtc_get_status(char *buf)
+{
+	efi_time_t 	eft, alm;
+	efi_time_cap_t	cap;
+	char		*p = buf;
+	efi_bool_t	enabled, pending;	
+	unsigned long	flags;
+
+	spin_lock_irqsave(&efi_rtc_lock, flags);
+
+	efi.get_time(&eft, &cap);
+	efi.get_wakeup_time(&enabled, &pending, &alm);
+
+	spin_unlock_irqrestore(&efi_rtc_lock,flags);
+
+	p += sprintf(p,
+		     "Time      :\n"
+		     "Year      : %u\n"
+		     "Month     : %u\n"
+		     "Day       : %u\n"
+		     "Hour      : %u\n"
+		     "Minute    : %u\n"
+		     "Second    : %u\n"
+		     "Nanosecond: %u\n"
+		     "Daylight  : %u\n",
+		     eft.year, eft.month, eft.day, eft.hour, eft.minute,
+		     eft.second, eft.nanosecond, eft.daylight);
+
+	if ( eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
+		p += sprintf(p, "Timezone  : unspecified\n");
+	else
+		/* XXX fixme: convert to string? */
+		p += sprintf(p, "Timezone  : %u\n", eft.timezone);
+		
+
+	p += sprintf(p,
+		     "\nWakeup Alm:\n"
+		     "Enabled   : %s\n"
+		     "Pending   : %s\n"
+		     "Year      : %u\n"
+		     "Month     : %u\n"
+		     "Day       : %u\n"
+		     "Hour      : %u\n"
+		     "Minute    : %u\n"
+		     "Second    : %u\n"
+		     "Nanosecond: %u\n"
+		     "Daylight  : %u\n",
+		     enabled == 1 ? "Yes" : "No",
+		     pending == 1 ? "Yes" : "No",
+		     alm.year, alm.month, alm.day, alm.hour, alm.minute,
+		     alm.second, alm.nanosecond, alm.daylight);
+
+	if ( eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
+		p += sprintf(p, "Timezone  : unspecified\n");
+	else
+		/* XXX fixme: convert to string? */
+		p += sprintf(p, "Timezone  : %u\n", eft.timezone);
+
+	/*
+	 * now prints the capabilities
+	 */
+	p += sprintf(p,
+		     "\nClock Cap :\n"
+		     "Resolution: %u\n"
+		     "Accuracy  : %u\n"
+		     "SetstoZero: %u\n",
+		      cap.resolution, cap.accuracy, cap.sets_to_zero);
+
+	return  p - buf;
+}
+
+static int
+efi_rtc_read_proc(char *page, char **start, off_t off,
+                                 int count, int *eof, void *data)
+{
+        int len = efi_rtc_get_status(page);
+        if (len <= off+count) *eof = 1;
+        *start = page + off;
+        len -= off;
+        if (len>count) len = count;
+        if (len<0) len = 0;
+        return len;
+}
+static int __init 
+efi_rtc_init(void)
+{
+	printk(KERN_INFO "EFI Time Services Driver v%s\n", EFI_RTC_VERSION);
+
+	misc_register(&efi_rtc_dev);
+
+	create_proc_read_entry ("efirtc", 0, NULL, efi_rtc_read_proc, NULL);
+
+	return 0;
+}
+static int __exit
+efi_rtc_exit(void)
+{
+	/* not yet used */
+	return 0;
+}
+
+module_init(efi_rtc_init);
+module_exit(efi_rtc_exit);
diff -u --recursive --new-file v2.3.42/linux/drivers/char/ftape/zftape/zftape-init.c linux/drivers/char/ftape/zftape/zftape-init.c
--- v2.3.42/linux/drivers/char/ftape/zftape/zftape-init.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/char/ftape/zftape/zftape-init.c	Wed Feb  9 11:42:35 2000
@@ -121,17 +121,12 @@
 
 static struct file_operations zft_cdev =
 {
-	NULL,			/* llseek */
-	zft_read,		/* read */
-	zft_write,		/* write */
-	NULL,			/* readdir */
-	NULL,		       	/* select */
-	zft_ioctl,		/* ioctl */
-	zft_mmap,		/* mmap */
-	zft_open,		/* open */
-	NULL,			/* flush */
-	zft_close,		/* release */
-	NULL,			/* fsync */
+	read:		zft_read,
+	write:		zft_write,
+	ioctl:		zft_ioctl,
+	mmap:		zft_mmap,
+	open:		zft_open,
+	release:	zft_close,
 };
 
 /*      Open floppy tape device
diff -u --recursive --new-file v2.3.42/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c
--- v2.3.42/linux/drivers/char/ip2main.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/ip2main.c	Wed Feb  9 11:42:35 2000
@@ -185,16 +185,11 @@
 /* This is the driver descriptor for the ip2ipl device, which is used to
  * download the loadware to the boards.
  */
-static struct file_operations
-ip2_ipl = {
-	NULL,
-	ip2_ipl_read,
-	ip2_ipl_write,
-	NULL,
-	NULL,
-	ip2_ipl_ioctl,
-	NULL,
-	ip2_ipl_open,
+static struct file_operations ip2_ipl = {
+	read:		ip2_ipl_read,
+	write:		ip2_ipl_write,
+	ioctl:		ip2_ipl_ioctl,
+	open:		ip2_ipl_open,
 }; 
 
 static long irq_counter = 0;
diff -u --recursive --new-file v2.3.42/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.3.42/linux/drivers/char/isicom.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/isicom.c	Wed Feb  9 11:42:35 2000
@@ -109,18 +109,9 @@
  */
 
 static struct file_operations ISILoad_fops = {
-	NULL,	/*	lseek	*/
-	NULL,	/*	read	*/
-	NULL,	/*	write	*/
-	NULL,	/*	readdir	*/
-	NULL,	/*	select	*/
-	ISILoad_ioctl,
-	NULL,	/*	mmap	*/
-	ISILoad_open,
-	NULL,	/*	flush	*/
-	ISILoad_release,
-	NULL,	/*	fsync	*/
-	NULL,	/*	fasync	*/
+	ioctl:		ISILoad_ioctl,
+	open:		ISILoad_open,
+	release:	ISILoad_release,
 };
 
 struct miscdevice isiloader_device = {
diff -u --recursive --new-file v2.3.42/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v2.3.42/linux/drivers/char/istallion.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/istallion.c	Wed Feb  9 11:42:35 2000
@@ -777,19 +777,11 @@
  *	board. This is also a very useful debugging tool.
  */
 static struct file_operations	stli_fsiomem = {
-	NULL,		/* llseek */
-	stli_memread,	/* read */
-	stli_memwrite,	/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	stli_memioctl,	/* ioctl */
-	NULL,		/* mmap */
-	stli_memopen,	/* open */
-	NULL,		/* flush */
-	stli_memclose,	/* release */
-	NULL,		/* fsync */
-	NULL,		/* fasync */
-	NULL		/* lock */
+	read:		stli_memread,
+	write:		stli_memwrite,
+	ioctl:		stli_memioctl,
+	open:		stli_memopen,
+	release:	stli_memclose,
 };
 
 /*****************************************************************************/
diff -u --recursive --new-file v2.3.42/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.3.42/linux/drivers/char/keyboard.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/keyboard.c	Wed Feb  9 20:08:09 2000
@@ -898,7 +898,7 @@
  * used, but this allows for easy and efficient race-condition
  * prevention later on.
  */
-static void kbd_bh(void)
+static void kbd_bh(unsigned long dummy)
 {
 	unsigned char leds = getleds();
 
@@ -909,6 +909,8 @@
 	}
 }
 
+DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
+
 int __init kbd_init(void)
 {
 	int i;
@@ -928,8 +930,9 @@
 	ttytab = console_driver.table;
 
 	kbd_init_hw();
-	init_bh(KEYBOARD_BH, kbd_bh);
-	mark_bh(KEYBOARD_BH);
+
+	tasklet_enable(&keyboard_tasklet);
+	tasklet_schedule(&keyboard_tasklet);
 	
 	pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, NULL);
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.3.42/linux/drivers/char/lp.c	Tue Jan  4 13:57:16 2000
+++ linux/drivers/char/lp.c	Wed Feb  9 11:42:35 2000
@@ -106,6 +106,8 @@
  * month ago...
  *
  *                                     14 Dec 1998, Andrea Arcangeli
+ *
+ * Copyright (C) 2000 by Tim Waugh (added LPSETTIMEOUT ioctl)
  */
 
 #include <linux/module.h>
@@ -133,6 +135,9 @@
 /* if you have more than 3 printers, remember to increase LP_NO */
 #define LP_NO 3
 
+/* ROUND_UP macro from fs/select.c */
+#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
+
 struct lp_struct lp_table[LP_NO];
 
 static unsigned int lp_count = 0;
@@ -321,6 +326,7 @@
 	ssize_t retv = 0;
 	ssize_t written;
 	size_t copy_size = count;
+	long old_to;
 
 #ifdef LP_STATS
 	if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
@@ -346,6 +352,9 @@
 	/* Go to compatibility mode. */
 	parport_negotiate (port, IEEE1284_MODE_COMPAT);
 
+	old_to = parport_set_timeout (lp_table[minor].dev,
+				      lp_table[minor].timeout);
+
 	do {
 		/* Write the data. */
 		written = parport_write (port, kbuf, copy_size);
@@ -390,6 +399,9 @@
 		}	
 	} while (count > 0);
 
+	/* Not really necessary, but polite. */
+	parport_set_timeout (lp_table[minor].dev, old_to);
+
  	lp_parport_release (minor);
 
 	up (&lp_table[minor].port_mutex);
@@ -527,6 +539,9 @@
 	if ((LP_F(minor) & LP_EXIST) == 0)
 		return -ENODEV;
 	switch ( cmd ) {
+		struct timeval par_timeout;
+		long to_jiffies;
+
 		case LPTIME:
 			LP_TIME(minor) = arg * HZ/100;
 			break;
@@ -588,6 +603,26 @@
 			if (copy_to_user((int *) arg, &status, sizeof(int)))
 				return -EFAULT;
 			break;
+
+		case LPSETTIMEOUT:
+			if (copy_from_user (&par_timeout,
+					    (struct timeval *) arg,
+					    sizeof (struct timeval))) {
+				return -EFAULT;
+			}
+			/* Convert to jiffies, place in lp_table */
+			if ((par_timeout.tv_sec < 0) ||
+			    (par_timeout.tv_usec < 0)) {
+				return -EINVAL;
+			}
+			to_jiffies = ROUND_UP(par_timeout.tv_usec, 1000000/HZ);
+			to_jiffies += par_timeout.tv_sec * (long) HZ;
+			if (to_jiffies <= 0) {
+				return -EINVAL;
+			}
+			lp_table[minor].timeout = to_jiffies;
+			break;
+
 		default:
 			retval = -EINVAL;
 	}
@@ -610,24 +645,14 @@
 #endif /* IEEE 1284 support */
 
 static struct file_operations lp_fops = {
-	lp_lseek,
-#ifdef CONFIG_PARPORT_1284
-	lp_read,
-#else
-	NULL,
-#endif
-	lp_write,
-	NULL,		/* lp_readdir */
+	write:		lp_write,
+	ioctl:		lp_ioctl,
+	open:		lp_open,
+	release:	lp_release,
 #ifdef CONFIG_PARPORT_1284
-	lp_poll,
-#else
-	NULL,
+	read:		lp_read,
+	poll:		lp_poll,
 #endif
-	lp_ioctl,
-	NULL,		/* lp_mmap */
-	lp_open,
-	NULL,		/* flush */
-	lp_release
 };
 
 /* --- support for console on the line printer ----------------- */
@@ -664,28 +689,33 @@
 	do {
 		/* Write the data, converting LF->CRLF as we go. */
 		ssize_t canwrite = count;
-		char *line = strchr (s, '\n');
-		if (line)
-			canwrite = line - s;
-
-		written = parport_write (port, s, canwrite);
-		if (written <= 0)
-			continue;
-
-		s += written;
-		count -= written;
-		if (line) {
+		char *lf = strchr (s, '\n');
+		if (lf)
+			canwrite = lf - s;
+
+		if (canwrite > 0) {
+			written = parport_write (port, s, canwrite);
+
+			if (written <= 0)
+				continue;
+
+			s += written;
+			count -= written;
+			canwrite -= written;
+		}
+
+		if (lf && canwrite <= 0) {
 			const char *crlf = "\r\n";
 			int i = 2;
 
 			/* Dodge the original '\n', and put '\r\n' instead. */
 			s++;
 			count--;
-			while (i) {
+			do {
 				written = parport_write (port, crlf, i);
 				if (written > 0)
 					i -= written, crlf += written;
-			}
+			} while (i > 0 && (CONSOLE_LP_STRICT || written > 0));
 		}
 	} while (count > 0 && (CONSOLE_LP_STRICT || written > 0));
 
@@ -698,7 +728,7 @@
 }
 
 static struct console lpcons = {
-	"lp0",
+	"lp",
 	lp_console_write,
 	NULL,
 	lp_console_device,
@@ -706,7 +736,7 @@
 	NULL,
 	NULL,
 	CON_PRINTBUFFER,
-	-1,
+	0,
 	0,
 	NULL
 };
@@ -778,6 +808,7 @@
 #ifdef CONFIG_LP_CONSOLE
 	if (!nr) {
 		if (port->modes & PARPORT_MODE_SAFEININT) {
+			MOD_INC_USE_COUNT;
 			register_console (&lpcons);
 			printk (KERN_INFO "lp%d: console ready\n", CONSOLE_LP);
 		} else
@@ -854,6 +885,7 @@
 		init_waitqueue_head (&lp_table[i].waitq);
 		init_waitqueue_head (&lp_table[i].dataq);
 		init_MUTEX (&lp_table[i].port_mutex);
+		lp_table[i].timeout = 10 * HZ;
 	}
 
 	if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) {
diff -u --recursive --new-file v2.3.42/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.3.42/linux/drivers/char/mem.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/mem.c	Wed Feb  9 18:48:03 2000
@@ -145,11 +145,15 @@
 	return do_write_mem(file, __va(p), p, buf, count, ppos);
 }
 
+#ifndef pgprot_noncached
+
 /*
  * This should probably be per-architecture in <asm/pgtable.h>
  */
-static inline unsigned long pgprot_noncached(unsigned long prot)
+static inline pgprot_t pgprot_noncached(pgprot_t _prot)
 {
+	unsigned long prot = pgprot_val(_prot);
+
 #if defined(__i386__)
 	/* On PPro and successors, PCD alone doesn't always mean 
 	    uncached because of interactions with the MTRRs. PCD | PWT
@@ -173,9 +177,11 @@
 	prot &= ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE);
 #endif
 
-	return prot;
+	return __pgprot(prot);
 }
 
+#endif /* !pgprot_noncached */
+
 /*
  * Architectures vary in how they handle caching for addresses 
  * outside of main memory.
@@ -208,8 +214,7 @@
 	 * done non-cached.
 	 */
 	if (noncached_address(offset) || (file->f_flags & O_SYNC))
-		pgprot_val(vma->vm_page_prot) 
-			= pgprot_noncached(pgprot_val(vma->vm_page_prot));
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 	/*
 	 * Don't dump addresses that are not real memory to a core file.
@@ -486,87 +491,47 @@
 #define open_kmem	open_mem
 
 static struct file_operations mem_fops = {
-	memory_lseek,
-	read_mem,
-	write_mem,
-	NULL,		/* mem_readdir */
-	NULL,		/* mem_poll */
-	NULL,		/* mem_ioctl */
-	mmap_mem,
-	open_mem,
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* fsync */
+	llseek:		memory_lseek,
+	read:		read_mem,
+	write:		write_mem,
+	mmap:		mmap_mem,
+	open:		open_mem,
 };
 
 static struct file_operations kmem_fops = {
-	memory_lseek,
-	read_kmem,
-	write_kmem,
-	NULL,		/* kmem_readdir */
-	NULL,		/* kmem_poll */
-	NULL,		/* kmem_ioctl */
-	mmap_kmem,
-	open_kmem,
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* fsync */
+	llseek:		memory_lseek,
+	read:		read_kmem,
+	write:		write_kmem,
+	mmap:		mmap_kmem,
+	open:		open_kmem,
 };
 
 static struct file_operations null_fops = {
-	null_lseek,
-	read_null,
-	write_null,
-	NULL,		/* null_readdir */
-	NULL,		/* null_poll */
-	NULL,		/* null_ioctl */
-	NULL,		/* null_mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* fsync */
+	llseek:		null_lseek,
+	read:		read_null,
+	write:		write_null,
 };
 
 #if !defined(CONFIG_PPC) && !defined(__mc68000__)
 static struct file_operations port_fops = {
-	memory_lseek,
-	read_port,
-	write_port,
-	NULL,		/* port_readdir */
-	NULL,		/* port_poll */
-	NULL,		/* port_ioctl */
-	NULL,		/* port_mmap */
-	open_port,
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* fsync */
+	llseek:		memory_lseek,
+	read:		read_port,
+	write:		write_port,
+	open:		open_port,
 };
 #endif
 
 static struct file_operations zero_fops = {
-	zero_lseek,
-	read_zero,
-	write_zero,
-	NULL,		/* zero_readdir */
-	NULL,		/* zero_poll */
-	NULL,		/* zero_ioctl */
-	mmap_zero,
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL		/* no special release code */
+	llseek:		zero_lseek,
+	read:		read_zero,
+	write:		write_zero,
+	mmap:		mmap_zero,
 };
 
 static struct file_operations full_fops = {
-	full_lseek,
-	read_full,
-	write_full,
-	NULL,		/* full_readdir */
-	NULL,		/* full_poll */
-	NULL,		/* full_ioctl */	
-	NULL,		/* full_mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL		/* no special release code */
+	llseek:		full_lseek,
+	read:		read_full,
+	write:		write_full,
 };
 
 static int memory_open(struct inode * inode, struct file * filp)
@@ -607,17 +572,7 @@
 }
 
 static struct file_operations memory_fops = {
-	NULL,		/* lseek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	memory_open,	/* just a selector for the real open */
-	NULL,		/* flush */
-	NULL,		/* release */
-	NULL		/* fsync */
+	open:		memory_open,	/* just a selector for the real open */
 };
 
 int __init chr_dev_init(void)
@@ -630,7 +585,7 @@
 	usb_init();
 #endif
 #ifdef CONFIG_I2C
-        i2c_init_all();
+	i2c_init_all();
 #endif
 #if defined (CONFIG_FB)
 	fbmem_init();
diff -u --recursive --new-file v2.3.42/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.3.42/linux/drivers/char/misc.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/misc.c	Wed Feb  9 11:42:35 2000
@@ -116,16 +116,7 @@
 }
 
 static struct file_operations misc_fops = {
-        NULL,		/* seek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-        misc_open,
-	NULL,		/* flush */
-        NULL		/* release */
+	open:		misc_open,
 };
 
 int misc_register(struct miscdevice * misc)
diff -u --recursive --new-file v2.3.42/linux/drivers/char/mixcomwd.c linux/drivers/char/mixcomwd.c
--- v2.3.42/linux/drivers/char/mixcomwd.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/mixcomwd.c	Wed Feb  9 11:42:35 2000
@@ -166,18 +166,10 @@
 
 static struct file_operations mixcomwd_fops=
 {
-	NULL,		/* Seek */
-	NULL,		/* Read */
-	mixcomwd_write,	/* Write */
-	NULL,		/* Readdir */
-	NULL,		/* Select */
-	mixcomwd_ioctl,	/* Ioctl */
-	NULL,		/* MMap */
-	mixcomwd_open,
-	NULL,		/* flush */
-	mixcomwd_release,
-	NULL,		
-	NULL		/* Fasync */
+	write:		mixcomwd_write,
+	ioctl:		mixcomwd_ioctl,
+	open:		mixcomwd_open,
+	release:	mixcomwd_release,
 };
 
 static struct miscdevice mixcomwd_miscdev=
diff -u --recursive --new-file v2.3.42/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c
--- v2.3.42/linux/drivers/char/msp3400.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/char/msp3400.c	Wed Feb  9 11:42:35 2000
@@ -1274,19 +1274,10 @@
 }
 
 static struct file_operations msp3400c_mixer_fops = {
-        msp3400c_mixer_llseek,
-        NULL,  /* read */
-        NULL,  /* write */
-        NULL,  /* readdir */
-        NULL,  /* poll */
-        msp3400c_mixer_ioctl,
-        NULL,  /* mmap */
-        msp3400c_mixer_open,
-	NULL,
-        msp3400c_mixer_release,
-        NULL,  /* fsync */
-        NULL,  /* fasync */
-        NULL,  /* lock */
+	llseek:		msp3400c_mixer_llseek,
+	ioctl:		msp3400c_mixer_ioctl,
+	open:		msp3400c_mixer_open,
+	release:	msp3400c_mixer_release,
 };
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/drivers/char/nvram.c linux/drivers/char/nvram.c
--- v2.3.42/linux/drivers/char/nvram.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/char/nvram.c	Wed Feb  9 11:42:35 2000
@@ -393,16 +393,12 @@
 #endif /* CONFIG_PROC_FS */
 
 static struct file_operations nvram_fops = {
-	nvram_llseek,
-	nvram_read,
-	nvram_write,
-	NULL,			/* No readdir */
-	NULL,			/* No poll */
-	nvram_ioctl,
-	NULL,			/* No mmap */
-	nvram_open,
-	NULL,			/* flush */
-	nvram_release
+	llseek:		nvram_llseek,
+	read:		nvram_read,
+	write:		nvram_write,
+	ioctl:		nvram_ioctl,
+	open:		nvram_open,
+	release:	nvram_release,
 };
 
 static struct miscdevice nvram_dev = {
diff -u --recursive --new-file v2.3.42/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
--- v2.3.42/linux/drivers/char/pc110pad.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/pc110pad.c	Thu Feb 10 12:29:58 2000
@@ -1,5 +1,9 @@
 /*
  *	Linux driver for the PC110 pad
+ */
+ 
+/**
+ * 	DOC: PC110 Digitizer Hardware
  *
  *	The pad provides triples of data. The first byte has
  *	0x80=bit 8 X, 0x01=bit 7 X, 0x08=bit 8 Y, 0x01=still down
@@ -7,13 +11,24 @@
  *	The third is bits 0-6 Y
  *
  *	This is read internally and used to synthesize a stream of
- *	triples in the form expected from a PS/2 device.
+ *	triples in the form expected from a PS/2 device. Specialist
+ *	applications can choose to obtain the pad data in other formats
+ *	including a debugging mode.
+ *
+ *	It would be good to add a joystick driver mode to this pad so
+ *	that doom and other game playing are better. One possible approach
+ *	would be to deactive the mouse mode while the joystick port is opened.
+ */
+ 
+/*
+ *	History
  *
  *	0.0 1997-05-16 Alan Cox <alan@redhat.com> - Pad reader
  *	0.1 1997-05-19 Robin O'Leary <robin@acm.org> - PS/2 emulation
  *	0.2 1997-06-03 Robin O'Leary <robin@acm.org> - tap gesture
  *	0.3 1997-06-27 Alan Cox <alan@redhat.com> - 2.1 commit
  *	0.4 1997-11-09 Alan Cox <alan@redhat.com> - Single Unix VFS API changes
+ *	0.5 2000-02-10 Alan Cox <alan@redhat.com> - 2.3.x cleanup, documentation
  */
 
 #include <linux/module.h>
@@ -56,7 +71,9 @@
 static struct semaphore reader_lock;
 
 /*
- * Utility to reset a timer to go off some time in the future.
+ *	set_timer_callback:
+ *
+ *	Utility to reset a timer to go off some time in the future.
  */
 
 static void set_timer_callback(struct timer_list *timer, int ticks)
@@ -67,10 +84,14 @@
 }
 
 
-/*
- * Take care of letting any waiting processes know that
- * now would be a good time to do a read().  Called
- * whenever a state transition occurs, real or synthetic.
+/**
+ *	wake_readers:
+ *
+ *	Take care of letting any waiting processes know that
+ *	now would be a good time to do a read().  Called
+ *	whenever a state transition occurs, real or synthetic. Also
+ *	issue any SIGIO's to programs that use SIGIO on mice (eg
+ *	Executor)
  */
  
 static void wake_readers(void)
@@ -112,7 +133,10 @@
 static struct timer_list tap_timer = { NULL, NULL, 0, 0, tap_timeout };
 
 
-/*
+/**
+ * tap_timeout:
+ * @data: Unused
+ *
  * This callback goes off a short time after an up/down transition;
  * before it goes off, transitions will be considered part of a
  * single PS/2 event and counted in transition_count.  Once the
@@ -136,7 +160,9 @@
 }
 
 
-/*
+/**
+ * notify_pad_up_down:
+ *
  * Called by the raw pad read routines when a (debounced) up/down
  * transition is detected.
  */
@@ -159,6 +185,13 @@
 	wake_readers();
 }
 
+/**
+ *	read_button:
+ *	@b: pointer to the button status.
+ *
+ *	The actual button state depends on what we are seeing. We have to check
+ *	for the tap gesture and also for dragging.
+ */
 
 static void read_button(int *b)
 {
@@ -216,12 +249,17 @@
 static struct timer_list bounce_timer = { NULL, NULL, 0, 0, bounce_timeout };
 
 
+
+/**
+ * bounce_timeout:
+ * @data: Unused
+ *
+ * No further up/down transitions happened within the
+ * bounce period, so treat this as a genuine transition.
+ */
+
 static void bounce_timeout(unsigned long data)
 {
-	/*
-	 * No further up/down transitions happened within the
-	 * bounce period, so treat this as a genuine transition.
-	 */
 	switch(bounce)
 	{
 		case NO_BOUNCE:
@@ -230,7 +268,7 @@
 			 * Strange; the timer callback should only go off if
 			 * we were expecting to do bounce processing!
 			 */
-			printk("pc110pad, bounce_timeout: bounce flag not set!\n");
+			printk(KERN_WARNING "pc110pad, bounce_timeout: bounce flag not set!\n");
 			break;
 		}
 		case JUST_GONE_UP:
@@ -242,7 +280,7 @@
 			bounce=NO_BOUNCE;
 			if(debounced_down==raw_down)
 			{
-				printk("pc110pad, bounce_timeout: raw already debounced!\n");
+				printk(KERN_WARNING "pc110pad, bounce_timeout: raw already debounced!\n");
 			}
 			debounced_down=raw_down;
 
@@ -263,10 +301,17 @@
 }
 
 
-/*
+/**
+ * pad_irq:
+ * @irq: Interrupt number
+ * @ptr: Unused
+ * @regs: Unused
+ *
  * Callback when pad's irq goes off; copies values in to raw_* globals;
- * initiates debounce processing.
+ * initiates debounce processing. This isn't SMP safe however there are
+ * no SMP machines with a PC110 touchpad on them.
  */
+ 
 static void pad_irq(int irq, void *ptr, struct pt_regs *regs)
 {
 
@@ -356,6 +401,18 @@
 	}
 }
 
+/**
+ *	read_raw_pad:
+ *	@down: set if the pen is down
+ *	@debounced: set if the debounced pen position is down
+ *	@x: X position
+ *	@y: Y position
+ *
+ *	Retrieve the data saved by the interrupt handler and indicate we
+ *	have no more pending XY to do. 
+ *
+ *	FIXME: We should switch to a spinlock for this.
+ */
 
 static void read_raw_pad(int *down, int *debounced, int *x, int *y)
 {
@@ -384,6 +441,12 @@
 static int read_bytes[3];
 static int read_byte_count=0;
 
+/**
+ *	sample_raw:
+ *	@d: sample buffer
+ *
+ *	Retrieve a triple of sample data. 
+ */
 
 
 static void sample_raw(int d[3])
@@ -393,6 +456,14 @@
 	d[2]=raw_data[2];
 }
 
+/**
+ *	sample_rare:
+ *	@d: sample buffer
+ *
+ *	Retrieve a triple of sample data and sanitize it. We do the needed
+ *	scaling and masking to get the current status.
+ */
+
 
 static void sample_rare(int d[3])
 {
@@ -409,20 +480,40 @@
 	d[2]=thisy%256;
 }
 
+/**
+ *	sample_debug:
+ *	@d: sample buffer
+ *
+ *	Retrieve a triple of sample data and mix it up with the state 
+ *	information in the gesture parser. Not useful for normal users but
+ *	handy when debugging
+ */
 
 static void sample_debug(int d[3])
 {
 	int thisd, thisdd, thisx, thisy;
 	int b;
+	unsigned long flags;
+	
+	save_flags(flags);
 	cli();
 	read_raw_pad(&thisd, &thisdd, &thisx, &thisy);
 	d[0]=(thisd?0x80:0) | (thisdd?0x40:0) | bounce;
 	d[1]=(recent_transition?0x80:0)+transition_count;
 	read_button(&b);
 	d[2]=(synthesize_tap<<4) | (b?0x01:0);
-	sti();
+	restore_flags(flags);
 }
 
+/**
+ *	sample_ps2:
+ *	@d: sample buffer
+ *
+ *	Retrieve a triple of sample data and turn the debounced tap and
+ *	stroke information into what appears to be a PS/2 mouse. This means
+ *	the PC110 pad needs no funny application side support.
+ */
+
 
 static void sample_ps2(int d[3])
 {
@@ -474,7 +565,16 @@
 }
 
 
-
+/**
+ *	fasync_pad:
+ *	@fd:	file number for the file 
+ *	@filp:	file handle
+ *	@on:	1 to add, 0 to remove a notifier
+ *
+ *	Update the queue of asynchronous event notifiers. We can use the
+ *	same helper the mice do and that does almost everything we need.
+ */
+ 
 static int fasync_pad(int fd, struct file *filp, int on)
 {
 	int retval;
@@ -486,9 +586,16 @@
 }
 
 
-/*
- * close access to the pad
+/**
+ *	close_pad:
+ *	@inode: inode of pad
+ *	@file: file handle to pad
+ *
+ *	Close access to the pad. We turn the pad power off if this is the
+ *	last user of the pad. I've not actually measured the power draw but
+ *	the DOS driver is careful to do this so we follow suit.
  */
+ 
 static int close_pad(struct inode * inode, struct file * file)
 {
 	fasync_pad(-1, file, 0);
@@ -500,9 +607,17 @@
 }
 
 
-/*
- * open access to the pad
+/**
+ *	open_pad:
+ *	@inode: inode of pad
+ *	@file: file handle to pad
+ *
+ *	Open access to the pad. We turn the pad off first (we turned it off
+ *	on close but if this is the first open after a crash the state is
+ *	indeterminate). The device has a small fifo so we empty that before
+ *	we kick it back into action.
  */
+ 
 static int open_pad(struct inode * inode, struct file * file)
 {
 	unsigned long flags;
@@ -533,15 +648,31 @@
 }
 
 
-/*
- * writes are disallowed
+/**
+ *	write_pad:
+ *	@file: File handle to the pad
+ *	@buffer: Unused
+ *	@count: Unused
+ *	@ppos: Unused
+ *
+ *	Writes are disallowed. A true PS/2 mouse lets you write stuff. Everyone
+ *	seems happy with this and not faking the write modes.
  */
+
 static ssize_t write_pad(struct file * file, const char * buffer, size_t count, loff_t *ppos)
 {
 	return -EINVAL;
 }
 
 
+/*
+ *	new_sample:
+ *	@d: sample buffer
+ *
+ *	Fetch a new sample according the current mouse mode the pad is 
+ *	using.
+ */
+ 
 void new_sample(int d[3])
 {
 	switch(current_params.mode)
@@ -554,9 +685,17 @@
 }
 
 
-/*
- * Read pad data.  Currently never blocks.
+/**
+ * read_pad:
+ * @file: File handle to pad
+ * @buffer: Target for the mouse data
+ * @count: Buffer length
+ * @ppos: Offset (unused)
+ *
+ * Read data from the pad. We use the reader_lock to avoid mess when there are
+ * two readers. This shouldnt be happening anyway but we play safe.
  */
+ 
 static ssize_t read_pad(struct file * file, char * buffer, size_t count, loff_t *ppos)
 {
 	int r;
@@ -578,8 +717,14 @@
 }
 
 
-/*
- * select for pad input
+/**
+ * pad_poll:
+ * @file: File of the pad device
+ * @wait: Poll table
+ *
+ * The pad is ready to read if there is a button or any position change
+ * pending in the queue. The reading and interrupt routines maintain the
+ * required state for us and do needed wakeups.
  */
 
 static unsigned int pad_poll(struct file *file, poll_table * wait)
@@ -591,6 +736,20 @@
 }
 
 
+/**
+ *	pad_ioctl;
+ *	@inode: Inode of the pad
+ *	@file: File handle to the pad
+ *	@cmd: Ioctl command
+ *	@arg: Argument pointer
+ *
+ *	The PC110 pad supports two ioctls both of which use the pc110pad_params
+ *	structure. GETP queries the current pad status. SETP changes the pad
+ *	configuration. Changing configuration during normal mouse operations
+ *	may give momentarily odd results as things like tap gesture state
+ *	may be lost.
+ */
+ 
 static int pad_ioctl(struct inode *inode, struct file * file,
 	unsigned int cmd, unsigned long arg)
 {
@@ -627,19 +786,13 @@
 
 
 static struct file_operations pad_fops = {
-	NULL,		/* pad_seek */
-	read_pad,
-	write_pad,
-	NULL, 		/* pad_readdir */
-	pad_poll,
-	pad_ioctl,
-	NULL,		/* pad_mmap */
-	open_pad,
-	NULL,		/* flush */
-	close_pad,
-	NULL,		/* fsync */
-	fasync_pad,
-	NULL		/* lock */
+	read:		read_pad,
+	write:		write_pad,
+	poll:		pad_poll,
+	ioctl:		pad_ioctl,
+	open:		open_pad,
+	release:	close_pad,
+	fasync:		fasync_pad,
 };
 
 
@@ -648,6 +801,15 @@
 };
 
 
+/**
+ *	pc110pad_init:
+ *
+ *	We configure the pad with the default parameters (that is PS/2 
+ *	emulation mode. We then claim the needed I/O and interrupt resources.
+ *	Finally as a matter of paranoia we turn the pad off until we are
+ *	asked to open it by an application.
+ */
+ 
 int pc110pad_init(void)
 {
 	current_params = default_params;
@@ -675,6 +837,13 @@
 
 #ifdef MODULE
 
+/**
+ *	pc110pad_unload:
+ *
+ *	Free the resources we acquired when the module was loaded. We also
+ *	turn the pad off to be sure we don't leave it using power.
+ */
+ 
 static void pc110pad_unload(void)
 {
 	outb(0x30, current_params.io+2);	/* switch off digitiser */
diff -u --recursive --new-file v2.3.42/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.3.42/linux/drivers/char/pc_keyb.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/pc_keyb.c	Wed Feb  9 20:08:09 2000
@@ -30,6 +30,7 @@
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
 #include <linux/malloc.h>
+#include <linux/kbd_kern.h>
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
@@ -412,16 +413,13 @@
 #endif
 }
 
-static unsigned char kbd_exists = 1;
-
 static inline void handle_keyboard_event(unsigned char scancode)
 {
-	kbd_exists = 1;
 #ifdef CONFIG_VT
 	if (do_acknowledge(scancode))
 		handle_scancode(scancode, !(scancode & 0x80));
 #endif				
-	mark_bh(KEYBOARD_BH);
+	tasklet_schedule(&keyboard_tasklet);
 }	
 
 /*
@@ -485,8 +483,6 @@
 {
 	int retries = 3;
 
-	if (!kbd_exists) return 0;
-
 	do {
 		unsigned long timeout = KBD_TIMEOUT;
 
@@ -504,7 +500,6 @@
 #ifdef KBD_REPORT_TIMEOUTS
 				printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?\n");
 #endif
-				kbd_exists = 0;
 				return 0;
 			}
 		}
@@ -512,7 +507,6 @@
 #ifdef KBD_REPORT_TIMEOUTS
 	printk(KERN_WARNING "keyboard: Too many NACKs -- noisy kbd cable?\n");
 #endif
-	kbd_exists = 0;
 	return 0;
 }
 
@@ -971,18 +965,12 @@
 }
 
 struct file_operations psaux_fops = {
-	NULL,		/* seek */
-	read_aux,
-	write_aux,
-	NULL, 		/* readdir */
-	aux_poll,
-	NULL, 		/* ioctl */
-	NULL,		/* mmap */
-	open_aux,
-	NULL,		/* flush */
-	release_aux,
-	NULL,
-	fasync_aux,
+	read:		read_aux,
+	write:		write_aux,
+	poll:		aux_poll,
+	open:		open_aux,
+	release:	release_aux,
+	fasync:		fasync_aux,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.3.42/linux/drivers/char/pcwd.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/char/pcwd.c	Wed Feb  9 11:42:35 2000
@@ -574,19 +574,11 @@
 }
 
 static struct file_operations pcwd_fops = {
-	NULL,		/* Seek */
-	pcwd_read,	/* Read */
-	pcwd_write,	/* Write */
-	NULL,		/* Readdir */
-	NULL,		/* Poll */
-	pcwd_ioctl,	/* IOctl */
-	NULL,		/* MMAP */
-	pcwd_open,	/* Open */
-	NULL,		/* flush */
-	pcwd_close,	/* Release */
-	NULL,		/* Fsync */
-	NULL,		/* Fasync */
-	NULL,		/* Lock */
+	read:		pcwd_read,
+	write:		pcwd_write,
+	ioctl:		pcwd_ioctl,
+	open:		pcwd_open,
+	release:	pcwd_close,
 };
 
 static struct miscdevice pcwd_miscdev = {
diff -u --recursive --new-file v2.3.42/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- v2.3.42/linux/drivers/char/ppdev.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/ppdev.c	Wed Feb  9 11:42:35 2000
@@ -4,7 +4,7 @@
  * This is the code behind /dev/parport* -- it allows a user-space
  * application to use the parport subsystem.
  *
- * Copyright (C) 1998-9 Tim Waugh <tim@cyberelk.demon.co.uk>
+ * Copyright (C) 1998-2000 Tim Waugh <tim@cyberelk.demon.co.uk>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -506,9 +506,13 @@
 	if (minor >= PARPORT_MAX)
 		return -ENXIO;
 
+	MOD_INC_USE_COUNT;
+
 	pp = kmalloc (sizeof (struct pp_struct), GFP_KERNEL);
-	if (!pp)
+	if (!pp) {
+		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
+	}
 
 	pp->state.mode = IEEE1284_MODE_COMPAT;
 	pp->state.phase = init_phase (pp->state.mode);
@@ -524,7 +528,6 @@
 	pp->pdev = NULL;
 	file->private_data = pp;
 
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -567,16 +570,13 @@
 }
 
 static struct file_operations pp_fops = {
-	pp_lseek,
-	pp_read,
-	pp_write,
-	NULL,	/* pp_readdir */
-	pp_poll,
-	pp_ioctl,
-	NULL,	/* pp_mmap */
-	pp_open,
-	NULL,   /* pp_flush */
-	pp_release
+	llseek:		pp_lseek,
+	read:		pp_read,
+	write:		pp_write,
+	poll:		pp_poll,
+	ioctl:		pp_ioctl,
+	open:		pp_open,
+	release:	pp_release,
 };
 
 static int __init ppdev_init (void)
diff -u --recursive --new-file v2.3.42/linux/drivers/char/qpmouse.c linux/drivers/char/qpmouse.c
--- v2.3.42/linux/drivers/char/qpmouse.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/char/qpmouse.c	Wed Feb  9 11:42:35 2000
@@ -290,18 +290,12 @@
 }
 
 struct file_operations qp_fops = {
-	NULL,		/* seek */
-	read_qp,
-	write_qp,
-	NULL, 		/* readdir */
-	poll_qp,
-	NULL, 		/* ioctl */
-	NULL,		/* mmap */
-	open_qp,
-	NULL,		/* flush */
-	release_qp,
-	NULL,
-	fasync_qp,
+	read:		read_qp,
+	write:		write_qp,
+	poll:		poll_qp,
+	open:		open_qp,
+	release:	release_qp,
+	fasync:		fasync_qp,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.3.42/linux/drivers/char/random.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/random.c	Wed Feb  9 11:42:35 2000
@@ -1637,29 +1637,16 @@
 }
 
 struct file_operations random_fops = {
-	NULL,		/* random_lseek */
-	random_read,
-	random_write,
-	NULL,		/* random_readdir */
-	random_poll,	/* random_poll */
-	random_ioctl,
-	NULL,		/* random_mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL		/* no special release code */
+	read:		random_read,
+	write:		random_write,
+	poll:		random_poll,
+	ioctl:		random_ioctl,
 };
 
 struct file_operations urandom_fops = {
-	NULL,		/* unrandom_lseek */
-	urandom_read,
-	random_write,
-	NULL,		/* urandom_readdir */
-	NULL,		/* urandom_poll */
-	random_ioctl,
-	NULL,		/* urandom_mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL		/* no special release code */
+	read:		urandom_read,
+	write:		random_write,
+	ioctl:		random_ioctl,
 };
 
 /***************************************************************
diff -u --recursive --new-file v2.3.42/linux/drivers/char/raw.c linux/drivers/char/raw.c
--- v2.3.42/linux/drivers/char/raw.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/char/raw.c	Wed Feb  9 11:42:35 2000
@@ -33,31 +33,15 @@
 
 
 static struct file_operations raw_fops = {
-	NULL,		/* llseek */
-	raw_read,	/* read */
-	raw_write,	/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	raw_open,	/* open */
-	NULL,		/* flush */
-	raw_release,	/* release */
-	NULL		/* fsync */
+	read:		raw_read,
+	write:		raw_write,
+	open:		raw_open,
+	release:	raw_release,
 };
 
 static struct file_operations raw_ctl_fops = {
-	NULL,		/* llseek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	raw_ctl_ioctl,	/* ioctl */
-	NULL,		/* mmap */
-	raw_open,	/* open */
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* fsync */
+	ioctl:		raw_ctl_ioctl,
+	open:		raw_open,
 };
 
 void __init raw_init(void)
diff -u --recursive --new-file v2.3.42/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.3.42/linux/drivers/char/rtc.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/rtc.c	Mon Feb  7 09:51:43 2000
@@ -34,10 +34,11 @@
  *	1.09	Nikita Schmidt: epoch support and some Alpha cleanup.
  *	1.09a	Pete Zaitcev: Sun SPARC
  *	1.09b	Jeff Garzik: Modularize, init cleanup
- *
+ *	1.09c	Jeff Garzik: SMP cleanup
+ *	1.10    Paul Barton-Davis: add support for async I/O
  */
 
-#define RTC_VERSION		"1.09b"
+#define RTC_VERSION		"1.10"
 
 #define RTC_IRQ 	8	/* Can't see this changing soon.	*/
 #define RTC_IO_EXTENT	0x10	/* Only really two ports, but...	*/
@@ -80,6 +81,8 @@
  *	ioctls.
  */
 
+static struct fasync_struct *rtc_async_queue;
+
 static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
 
 static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -153,6 +156,9 @@
 
 	wake_up_interruptible(&rtc_wait);	
 
+	if (rtc_async_queue)
+		kill_fasync (rtc_async_queue, SIGIO, POLL_IN);
+
 	if (atomic_read(&rtc_status) & RTC_TIMER_ON)
 		mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
 }
@@ -480,6 +486,12 @@
 	return 0;
 }
 
+static int rtc_fasync (int fd, struct file *filp, int on)
+
+{
+	return fasync_helper (fd, filp, on, &rtc_async_queue);
+}
+
 static int rtc_release(struct inode *inode, struct file *file)
 {
 	/*
@@ -504,6 +516,10 @@
 		del_timer(&rtc_irq_timer);
 	}
 
+	if (file->f_flags & FASYNC) {
+		rtc_fasync (-1, file, 0);
+	}
+
 	MOD_DEC_USE_COUNT;
 
 	spin_lock_irqsave (&rtc_lock, flags);
@@ -533,16 +549,13 @@
  */
 
 static struct file_operations rtc_fops = {
-	rtc_llseek,
-	rtc_read,
-	NULL,		/* No write */
-	NULL,		/* No readdir */
-	rtc_poll,
-	rtc_ioctl,
-	NULL,		/* No mmap */
-	rtc_open,
-	NULL,		/* flush */
-	rtc_release
+	llseek:		rtc_llseek,
+	read:		rtc_read,
+	poll:		rtc_poll,
+	ioctl:		rtc_ioctl,
+	open:		rtc_open,
+	release:	rtc_release,
+	fasync:		rtc_fasync,
 };
 
 static struct miscdevice rtc_dev=
diff -u --recursive --new-file v2.3.42/linux/drivers/char/saa5249.c linux/drivers/char/saa5249.c
--- v2.3.42/linux/drivers/char/saa5249.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/saa5249.c	Wed Feb  9 18:48:03 2000
@@ -256,7 +256,7 @@
 static struct i2c_driver i2c_driver_videotext = 
 {
 	IF_NAME,		/* name */
-	I2C_DRIVERID_VIDEOTEXT, /* in i2c.h */
+	I2C_DRIVERID_SAA5249, /* in i2c.h */
 	I2C_DF_NOTIFY,
 	saa5249_probe,
 	saa5249_detach,
diff -u --recursive --new-file v2.3.42/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.3.42/linux/drivers/char/softdog.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/softdog.c	Wed Feb  9 11:42:35 2000
@@ -158,18 +158,10 @@
 
 static struct file_operations softdog_fops=
 {
-	NULL,		/* Seek */
-	NULL,		/* Read */
-	softdog_write,	/* Write */
-	NULL,		/* Readdir */
-	NULL,		/* Select */
-	softdog_ioctl,	/* Ioctl */
-	NULL,		/* MMap */
-	softdog_open,
-	NULL,		/* flush */
-	softdog_release,
-	NULL,		
-	NULL		/* Fasync */
+	write:		softdog_write,
+	ioctl:		softdog_ioctl,
+	open:		softdog_open,
+	release:	softdog_release,
 };
 
 static struct miscdevice softdog_miscdev=
diff -u --recursive --new-file v2.3.42/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.3.42/linux/drivers/char/stallion.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/stallion.c	Wed Feb  9 11:42:35 2000
@@ -743,19 +743,9 @@
  *	to get at port stats - only not using the port device itself.
  */
 static struct file_operations	stl_fsiomem = {
-	NULL,		/* llseek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	stl_memioctl,	/* ioctl */
-	NULL,		/* mmap */
-	stl_memopen,	/* open */
-	NULL,		/* flush */
-	stl_memclose,	/* release */
-	NULL,		/* fsync */
-	NULL,		/* fasync */
-	NULL		/* lock */
+	ioctl:		stl_memioctl,
+	open:		stl_memopen,
+	release:	stl_memclose,
 };
 
 /*****************************************************************************/
diff -u --recursive --new-file v2.3.42/linux/drivers/char/sx.c linux/drivers/char/sx.c
--- v2.3.42/linux/drivers/char/sx.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/sx.c	Wed Feb  9 11:42:35 2000
@@ -531,20 +531,9 @@
  */
 
 static struct file_operations sx_fw_fops = {
-	NULL,	/*	lseek	*/
-	NULL,	/*	read	*/
-	NULL,	/*	write	*/
-	NULL,	/*	readdir	*/
-	NULL,	/*	select	*/
-	sx_fw_ioctl,
-	NULL,	/*	mmap	*/
-	sx_fw_open,
-#ifndef TWO_ZERO
-	NULL,	/*	flush	*/
-#endif
-	sx_fw_release,
-	NULL,	/*	fsync	*/
-	NULL,	/*	fasync	*/
+	ioctl:		sx_fw_ioctl,
+	open:		sx_fw_open,
+	release:	sx_fw_release,
 };
 
 struct miscdevice sx_fw_device = {
diff -u --recursive --new-file v2.3.42/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.3.42/linux/drivers/char/tpqic02.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/tpqic02.c	Wed Feb  9 11:42:35 2000
@@ -2765,18 +2765,12 @@
 
 /* These are (most) of the interface functions: */
 static struct file_operations qic02_tape_fops = {
-	qic02_tape_lseek,		/* not allowed */
-	qic02_tape_read,		/* read */
-	qic02_tape_write,		/* write */
-	NULL,				/* readdir not allowed */
-	NULL,				/* poll ??? */
-	qic02_tape_ioctl,		/* ioctl */
-	NULL,				/* mmap not allowed */
-	qic02_tape_open,		/* open */
-	NULL,				/* flush */
-	qic02_tape_release,		/* release */
-	NULL,				/* fsync */
-	NULL,				/* fasync */
+	llseek:		qic02_tape_lseek,	/* not allowed */
+	read:		qic02_tape_read,
+	write:		qic02_tape_write,
+	ioctl:		qic02_tape_ioctl,
+	open:		qic02_tape_open,
+	release:	qic02_tape_release,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.3.42/linux/drivers/char/tty_io.c	Tue Feb  1 01:35:43 2000
+++ linux/drivers/char/tty_io.c	Wed Feb  9 11:42:35 2000
@@ -358,33 +358,23 @@
 }
 
 static struct file_operations tty_fops = {
-	tty_lseek,
-	tty_read,
-	tty_write,
-	NULL,		/* tty_readdir */
-	tty_poll,
-	tty_ioctl,
-	NULL,		/* tty_mmap */
-	tty_open,
-	NULL,		/* flush */
-	tty_release,
-	NULL,		/* tty_fsync */
-	tty_fasync
+	llseek:		tty_lseek,
+	read:		tty_read,
+	write:		tty_write,
+	poll:		tty_poll,
+	ioctl:		tty_ioctl,
+	open:		tty_open,
+	release:	tty_release,
+	fasync:		tty_fasync,
 };
 
 static struct file_operations hung_up_tty_fops = {
-	tty_lseek,
-	hung_up_tty_read,
-	hung_up_tty_write,
-	NULL,		/* hung_up_tty_readdir */
-	hung_up_tty_poll,
-	hung_up_tty_ioctl,
-	NULL,		/* hung_up_tty_mmap */
-	NULL,		/* hung_up_tty_open */
-	NULL,		/* flush */
-	tty_release,	/* hung_up_tty_release */
-	NULL,		/* hung_up_tty_fsync  */
-	NULL		/* hung_up_tty_fasync */
+	llseek:		tty_lseek,
+	read:		hung_up_tty_read,
+	write:		hung_up_tty_write,
+	poll:		hung_up_tty_poll,
+	ioctl:		hung_up_tty_ioctl,
+	release:	tty_release,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.3.42/linux/drivers/char/vc_screen.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/char/vc_screen.c	Wed Feb  9 11:42:35 2000
@@ -297,17 +297,10 @@
 }
 
 static struct file_operations vcs_fops = {
-	vcs_lseek,	/* lseek */
-	vcs_read,	/* read */
-	vcs_write,	/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	vcs_open,	/* open */
-	NULL,		/* flush */
-	NULL,		/* release */
-	NULL		/* fsync */
+	llseek:		vcs_lseek,
+	read:		vcs_read,
+	write:		vcs_write,
+	open:		vcs_open,
 };
 
 int __init vcs_init(void)
diff -u --recursive --new-file v2.3.42/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.3.42/linux/drivers/char/videodev.c	Tue Jan  4 13:57:16 2000
+++ linux/drivers/char/videodev.c	Wed Feb  9 11:42:35 2000
@@ -302,22 +302,16 @@
 
 static struct file_operations video_fops=
 {
-	video_lseek,
-	video_read,
-	video_write,
-	NULL,	/* readdir */
-#if LINUX_VERSION_CODE >= 0x020100
-	video_poll,	/* poll */
-#else
-	NULL,
+	llseek:		video_lseek,
+	read:		video_read,
+	write:		video_write,
+	ioctl:		video_ioctl,
+	mmap:		video_mmap,
+	open:		video_open,
+	release:	video_release,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+	poll:		video_poll,
 #endif
-	video_ioctl,
-	video_mmap,
-	video_open,
-#if LINUX_VERSION_CODE >= 0x020100
-	NULL,		/* flush */
-#endif
-	video_release
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.3.42/linux/drivers/char/vt.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/vt.c	Wed Feb  9 20:08:09 2000
@@ -804,10 +804,12 @@
 				 * When we actually do the console switch,
 				 * make sure we are atomic with respect to
 				 * other console switches..
+				 *
+				 * Damn! Was it difficult to make this clean?
 				 */
-				start_bh_atomic();
+				disable_bh(CONSOLE_BH);
 				complete_change_console(newvt);
-				end_bh_atomic();
+				enable_bh(CONSOLE_BH);
 			}
 		}
 
diff -u --recursive --new-file v2.3.42/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.3.42/linux/drivers/char/wdt.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/char/wdt.c	Thu Feb 10 12:31:07 2000
@@ -62,8 +62,13 @@
 
 #ifndef MODULE
 
-/*
- *	Setup options
+/**
+ *	wdt_setup:
+ *	@str: command line string
+ *
+ *	Setup options. The board isn't really probe-able so we have to
+ *	get the user to tell us the configuration. Sane people build it 
+ *	modular but the others come here.
  */
  
 static int __init wdt_setup(char *str)
@@ -108,6 +113,17 @@
  *	Kernel methods.
  */
  
+ 
+/**
+ *	wdt_status:
+ *	
+ *	Extract the status information from a WDT watchdog device. There are
+ *	several board variants so we have to know which bits are valid. Some
+ *	bits default to one and some to zero in order to be maximally painful.
+ *
+ *	we then map the bits onto the status ioctl flags.
+ */
+ 
 static int wdt_status(void)
 {
 	/*
@@ -134,11 +150,26 @@
 	return flag;
 }
 
+/**
+ *	wdt_interrupt:
+ *	@irq:		Interrupt number
+ *	@dev_id:	Unused as we don't allow multiple devices.
+ *	@regs:		Unused.
+ *
+ *	Handle an interrupt from the board. These are raised when the status
+ *	map changes in what the board considers an interesting way. That means
+ *	a failure condition occuring.
+ *
+ *	FIXME:	We need to pass a dev_id as the PCI card can share irqs
+ *	although its arguably a _very_ dumb idea to share watchdog
+ *	irq lines
+ */
+ 
 void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/*
 	 *	Read the status register see what is up and
-	 *	then printk it.
+	 *	then printk it. 
 	 */
 	 
 	unsigned char status=inb_p(WDT_SR);
@@ -175,6 +206,13 @@
 	return -ESPIPE;
 }
 
+/**
+ *	wdt_ping:
+ *
+ *	Reload counter one with the watchdog timeout. We don't bother reloading
+ *	the cascade counter. 
+ */
+ 
 static void wdt_ping(void)
 {
 	/* Write a watchdog value */
@@ -184,6 +222,17 @@
 	outb_p(0, WDT_DC);
 }
 
+/**
+ *	wdt_write:
+ *	@file: file handle to the watchdog
+ *	@buf: buffer to write (unused as data does not matter here 
+ *	@count: count of bytes
+ *	@ppos: pointer to the position to write. No seeks allowed
+ *
+ *	A write to a watchdog device is defined as a keepalive signal. Any
+ *	write of data will do, as we we don't define content meaning.
+ */
+ 
 static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
 	/*  Can't seek (pwrite) on this device  */
@@ -198,8 +247,15 @@
 	return 0;
 }
 
-/*
- *	Read reports the temperature in degrees Fahrenheit.
+/**
+ *	wdt_read:
+ *	@file: file handle to the watchdog board
+ *	@buf: buffer to write 1 byte into
+ *	@count: length of buffer
+ *	@ptr: offset (no seek allowed)
+ *
+ *	Read reports the temperature in degrees Fahrenheit. The API is in
+ *	farenheit. It was designed by an imperial measurement luddite.
  */
  
 static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
@@ -225,6 +281,18 @@
 	}
 }
 
+/**
+ *	wdt_ioctl:
+ *	@inode: inode of the device
+ *	@file: file handle to the device
+ *	@cmd: watchdog command
+ *	@arg: argument pointer
+ *
+ *	The watchdog API defines a common set of functions for all watchdogs
+ *	according to their available features. We only actually usefully support
+ *	querying capabilities and current status. 
+ */
+ 
 static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
@@ -254,6 +322,18 @@
 	}
 }
 
+/**
+ *	wdt_open:
+ *	@inode: inode of device
+ *	@file: file handle to device
+ *
+ *	One of our two misc devices has been opened. The watchdog device is
+ *	single open and on opening we load the counters. Counter zero is a 
+ *	100Hz cascade, into counter 1 which downcounts to reboot. When the
+ *	counter triggers counter 2 downcounts the length of the reset pulse
+ *	which set set to be as long as possible. 
+ */
+ 
 static int wdt_open(struct inode *inode, struct file *file)
 {
 	switch(MINOR(inode->i_rdev))
@@ -284,6 +364,18 @@
 	}
 }
 
+/**
+ *	wdt_close:
+ *	@inode: inode to board
+ *	@file: file handle to board
+ *
+ *	The watchdog has a configurable API. There is a religious dispute 
+ *	between people who want their watchdog to be able to shut down and 
+ *	those who want to be sure if the watchdog manager dies the machine
+ *	reboots. In the former case we disable the counters, in the latter
+ *	case you have to open it again very soon.
+ */
+ 
 static int wdt_release(struct inode *inode, struct file *file)
 {
 	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
@@ -298,8 +390,16 @@
 	return 0;
 }
 
-/*
- *	Notifier for system down
+/**
+ *	notify_sys:
+ *	@this: our notifier block
+ *	@code: the event being reported
+ *	@unused: unused
+ *
+ *	Our notifier is called on system shutdowns. We want to turn the card
+ *	off at reboot otherwise the machine will reboot again during memory
+ *	test or worse yet during the following fsck. This would suck, in fact
+ *	trust me - if it happens it does suck.
  */
 
 static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
@@ -320,16 +420,12 @@
  
  
 static struct file_operations wdt_fops = {
-	wdt_llseek,
-	wdt_read,
-	wdt_write,
-	NULL,		/* No Readdir */
-	NULL,		/* No Select */
-	wdt_ioctl,
-	NULL,		/* No mmap */
-	wdt_open,
-	NULL,		/* flush */
-	wdt_release
+	llseek:		wdt_llseek,
+	read:		wdt_read,
+	write:		wdt_write,
+	ioctl:		wdt_ioctl,
+	open:		wdt_open,
+	release:	wdt_release,
 };
 
 static struct miscdevice wdt_miscdev=
@@ -364,6 +460,16 @@
 
 #define wdt_init init_module
 
+/**
+ *	cleanup_module:
+ *
+ *	Unload the watchdog. You cannot do this with any file handles open.
+ *	If your watchdog is set to continue ticking on close and you unload
+ *	it, well it keeps ticking. We won't get the interrupt but the board
+ *	will not touch PC memory so all is fine. You just have to load a new
+ *	module in 60 seconds or reboot.
+ */
+ 
 void cleanup_module(void)
 {
 	misc_deregister(&wdt_miscdev);
@@ -377,6 +483,14 @@
 
 #endif
 
+/**
+ * 	wdt_init:
+ *
+ *	Set up the WDT watchdog board. All we have to do is grab the
+ *	resources we require and bitch if anyone beat us to them.
+ *	The open() function will actually kick the board off.
+ */
+ 
 int __init wdt_init(void)
 {
 	printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io,irq);
diff -u --recursive --new-file v2.3.42/linux/drivers/i2c/i2c-algo-bit.c linux/drivers/i2c/i2c-algo-bit.c
--- v2.3.42/linux/drivers/i2c/i2c-algo-bit.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/i2c/i2c-algo-bit.c	Wed Feb  9 18:48:03 2000
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /* i2c-algo-bit.c i2c driver algorithms for bit-shift adapters		     */
 /* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-99 Simon G. Vogl
+/*   Copyright (C) 1995-2000 Simon G. Vogl
 
     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
@@ -21,35 +21,15 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-algo-bit.c,v 1.21 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-algo-bit.c,v 1.26 2000/01/24 02:06:33 mds Exp $ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
 #include <linux/version.h>
-#if LINUX_VERSION_CODE >= 0x020135
 #include <linux/init.h>
-#else
-#define __init 
-#endif
-
-#if LINUX_VERSION_CODE >= 0x020100
-#  include <asm/uaccess.h>
-#else
-#  include <asm/segment.h>
-#endif
-
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
-
+#include <asm/uaccess.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -69,13 +49,8 @@
 /* respectively. This makes sure that the algorithm works. Some chips   */
 /* might not like this, as they have an internal timeout of some mils	*/
 /*
-#if LINUX_VERSION_CODE >= 0x02016e
 #define SLO_IO      jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
                         if (need_resched) schedule();
-#else
-#define SLO_IO      jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
-			if (need_resched) schedule();
-#endif
 */
 
 
@@ -100,22 +75,22 @@
 
 static inline void sdalo(struct i2c_algo_bit_data *adap)
 {
-    setsda(adap,0);
-    udelay(adap->udelay);
+	setsda(adap,0);
+	udelay(adap->udelay);
 }
 
 static inline void sdahi(struct i2c_algo_bit_data *adap)
 {
-    setsda(adap,1);
-    udelay(adap->udelay);
+	setsda(adap,1);
+	udelay(adap->udelay);
 }
 
 static inline void scllo(struct i2c_algo_bit_data *adap)
 {
-    setscl(adap,0);
-    udelay(adap->udelay);
+	setscl(adap,0);
+	udelay(adap->udelay);
 #ifdef SLO_IO
-    SLO_IO
+	SLO_IO
 #endif
 }
 
@@ -145,13 +120,8 @@
 		if (start+adap->timeout <= jiffies) {
 			return -ETIMEDOUT;
 		}
-#if LINUX_VERSION_CODE >= 0x02016e
 		if (current->need_resched)
 			schedule();
-#else
-		if (need_resched)
-			schedule();
-#endif
 	}
 	DEBSTAT(printk("needed %ld jiffies\n", jiffies-start));
 #ifdef SLO_IO
@@ -259,7 +229,7 @@
 		};
 		indata *= 2;
 		if ( getsda(adap) ) 
-		  indata |= 0x01;
+			indata |= 0x01;
 		scllo(adap);
 	}
 	/* assert: scl is low */
@@ -280,13 +250,14 @@
 	}
 	scl=getscl(adap);
 	printk("i2c-algo-bit.o: Adapter: %s scl: %d  sda: %d -- testing...\n",
-	name,getscl(adap),getsda(adap));
+	       name,getscl(adap),getsda(adap));
 	if (!scl || !sda ) {
 		printk("i2c-algo-bit.o: %s seems to be busy.\n",name);
 		goto bailout;
 	}
 	sdalo(adap);
-	printk("i2c-algo-bit.o:1 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-bit.o:1 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 != getsda(adap) ) {
 		printk("i2c-algo-bit.o: %s SDA stuck high!\n",name);
 		sdahi(adap);
@@ -298,18 +269,21 @@
 		goto bailout;
 	}		
 	sdahi(adap);
-	printk("i2c-algo-bit.o:2 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-bit.o:2 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 == getsda(adap) ) {
 		printk("i2c-algo-bit.o: %s SDA stuck low!\n",name);
 		sdahi(adap);
 		goto bailout;
 	}
 	if ( 0 == getscl(adap) ) {
-		printk("i2c-algo-bit.o: %s SCL unexpected low while SDA high!\n",name);
+		printk("i2c-algo-bit.o: %s SCL unexpected low while SDA high!\n",
+		       name);
 	goto bailout;
 	}
 	scllo(adap);
-	printk("i2c-algo-bit.o:3 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-bit.o:3 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 != getscl(adap) ) {
 		printk("i2c-algo-bit.o: %s SCL stuck high!\n",name);
 		sclhi(adap);
@@ -321,7 +295,8 @@
 		goto bailout;
 	}
 	sclhi(adap);
-	printk("i2c-algo-bit.o:4 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-bit.o:4 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 == getscl(adap) ) {
 		printk("i2c-algo-bit.o: %s SCL stuck low!\n",name);
 		sclhi(adap);
@@ -366,7 +341,8 @@
 		i2c_start(adap);
 		udelay(adap->udelay);
 	}
-	DEB2(if (i) printk("i2c-algo-bit.o: needed %d retries for %d\n",i,addr));
+	DEB2(if (i) printk("i2c-algo-bit.o: needed %d retries for %d\n",
+	                   i,addr));
 	return ret;
 }
 
@@ -391,7 +367,8 @@
 			printk("i2c-algo-bit.o: %s i2c_write: error - bailout.\n",
 			       i2c_adap->name);
 			i2c_stop(adap);
-			return (retval<0)? retval : -EFAULT; /* got a better one ?? */
+			return (retval<0)? retval : -EFAULT;
+			        /* got a better one ?? */
 		}
 #if 0
 		/* from asm/delay.h */
@@ -447,8 +424,8 @@
  * -x an error occured (like: -EREMOTEIO if the device did not answer, or
  *	-ETIMEDOUT, for example if the lines are stuck...) 
  */
-static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, 
-			int retries) 
+static inline int bit_doAddress(struct i2c_adapter *i2c_adap,
+                                struct i2c_msg *msg, int retries) 
 {
 	unsigned short flags = msg->flags;
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
@@ -486,6 +463,8 @@
 		addr = ( msg->addr << 1 );
 		if (flags & I2C_M_RD )
 			addr |= 1;
+		if (flags & I2C_M_REV_DIR_ADDR )
+			addr ^= 1;
 		ret = try_address(i2c_adap, addr, retries);
 		if (ret!=1) {
 			return -EREMOTEIO;
@@ -505,11 +484,16 @@
 	i2c_start(adap);
 	for (i=0;i<num;i++) {
 		pmsg = &msgs[i];
-		ret = bit_doAddress(i2c_adap,pmsg,i2c_adap->retries);
-		if (ret != 0) {
-			DEB2(printk("i2c-algo-bit.o: NAK from device adr %#2x msg #%d\n"
-			       ,msgs[i].addr,i));
-			return (ret<0) ? ret : -EREMOTEIO;
+		if (!(pmsg->flags & I2C_M_NOSTART)) {
+			if (i) {
+				i2c_repstart(adap);
+			}
+			ret = bit_doAddress(i2c_adap,pmsg,i2c_adap->retries);
+			if (ret != 0) {
+				DEB2(printk("i2c-algo-bit.o: NAK from device adr %#2x msg #%d\n"
+				       ,msgs[i].addr,i));
+				return (ret<0) ? ret : -EREMOTEIO;
+			}
 		}
 		if (pmsg->flags & I2C_M_RD ) {
 			/* read bytes into buffer*/
@@ -526,9 +510,6 @@
 				return (ret<0) ? ret : -EREMOTEIO;
 			}
 		}
-		if (i<num-1) {
-			i2c_repstart(adap);
-		}
 	}
 	i2c_stop(adap);
 	return num;
@@ -542,7 +523,8 @@
 
 static u32 bit_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
+	       I2C_FUNC_PROTOCOL_MANGLING;
 }
 
 
@@ -556,7 +538,7 @@
 	NULL,				/* slave_xmit		*/
 	NULL,				/* slave_recv		*/
 	algo_control,			/* ioctl		*/
-        bit_func,                       /* functionality        */
+	bit_func,			/* functionality	*/
 };
 
 /* 
@@ -565,7 +547,7 @@
 int i2c_bit_add_bus(struct i2c_adapter *adap)
 {
 	int i;
-        struct i2c_algo_bit_data *bit_adap = adap->algo_data;
+	struct i2c_algo_bit_data *bit_adap = adap->algo_data;
 
 	if (bit_test) {
 		int ret = test_bus(bit_adap, adap->name);
@@ -573,7 +555,8 @@
 			return -ENODEV;
 	}
 
-	DEB2(printk("i2c-algo-bit.o: hw routines for %s registered.\n",adap->name));
+	DEB2(printk("i2c-algo-bit.o: hw routines for %s registered.\n",
+	            adap->name));
 
 	/* register new adapter to i2c module... */
 
@@ -585,8 +568,9 @@
 
 	/* scan bus */
 	if (bit_scan) {
-	        int ack;
-		printk(KERN_INFO " i2c-algo-bit.o: scanning bus %s.\n", adap->name);
+		int ack;
+		printk(KERN_INFO " i2c-algo-bit.o: scanning bus %s.\n",
+		       adap->name);
 		for (i = 0x00; i < 0xff; i+=2) {
 			i2c_start(bit_adap);
 			ack = i2c_outb(adap,i);
@@ -642,7 +626,8 @@
 
 MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
 MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
-MODULE_PARM_DESC(i2c_debug,"debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
+MODULE_PARM_DESC(i2c_debug,
+            "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
 
 int init_module(void) 
 {
diff -u --recursive --new-file v2.3.42/linux/drivers/i2c/i2c-algo-pcf.c linux/drivers/i2c/i2c-algo-pcf.c
--- v2.3.42/linux/drivers/i2c/i2c-algo-pcf.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/i2c/i2c-algo-pcf.c	Wed Feb  9 18:48:03 2000
@@ -2,8 +2,8 @@
 /* ------------------------------------------------------------------------- */
 /* i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters		     */
 /* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-97 Simon G. Vogl
-                   1998-99 Hans Berglund
+/*   Copyright (C) 1995-1997 Simon G. Vogl
+                   1998-2000 Hans Berglund
 
     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
@@ -20,43 +20,22 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
 /* ------------------------------------------------------------------------- */
 
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and 
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-algo-pcf.c,v 1.15 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-algo-pcf.c,v 1.20 2000/01/24 02:06:33 mds Exp $ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
 #include <linux/version.h>
-#if LINUX_VERSION_CODE >= 0x020135
 #include <linux/init.h>
-#else
-#define __init 
-#endif
-
-#if LINUX_VERSION_CODE >= 0x020100
-#  include <asm/uaccess.h>
-#else
-#  include <asm/segment.h>
-#endif
-
-
+#include <asm/uaccess.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
-
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pcf.h>
 #include "i2c-pcf8584.h"
@@ -74,13 +53,8 @@
 /* respectively. This makes sure that the algorithm works. Some chips   */
 /* might not like this, as they have an internal timeout of some mils	*/
 /*
-#if LINUX_VERSION_CODE >= 0x02016e
 #define SLO_IO      jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
                         if (need_resched) schedule();
-#else
-#define SLO_IO      jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
-			if (need_resched) schedule();
-#endif
 */
 
 
@@ -108,52 +82,42 @@
 
 /* --- other auxiliary functions --------------------------------------	*/
 
-#if LINUX_VERSION_CODE < 0x02017f
-static void schedule_timeout(int j)
-{
-	current->state   = TASK_INTERRUPTIBLE;
-	current->timeout = jiffies + j;
-	schedule();
-}
-#endif
-
-
 static void i2c_start(struct i2c_algo_pcf_data *adap) 
 {
-   DEBPROTO(printk("S "));
-   set_pcf(adap, 1, I2C_PCF_START);
+	DEBPROTO(printk("S "));
+	set_pcf(adap, 1, I2C_PCF_START);
 }
 
 static void i2c_repstart(struct i2c_algo_pcf_data *adap) 
 {
-   DEBPROTO(printk(" Sr "));
-   set_pcf(adap, 1, I2C_PCF_REPSTART);
+	DEBPROTO(printk(" Sr "));
+	set_pcf(adap, 1, I2C_PCF_REPSTART);
 }
 
 
 static void i2c_stop(struct i2c_algo_pcf_data *adap) 
 {
-   DEBPROTO(printk("P\n"));
-   set_pcf(adap, 1, I2C_PCF_STOP);
+	DEBPROTO(printk("P\n"));
+	set_pcf(adap, 1, I2C_PCF_STOP);
 }
 
 
 static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
 
-   int timeout = DEF_TIMEOUT;
-   int status;
+	int timeout = DEF_TIMEOUT;
+	int status;
 
-   status = get_pcf(adap, 1);
-   while (timeout-- && !(status & I2C_PCF_BB)) {
-      udelay(1000); /* How much is this? */
-      status = get_pcf(adap, 1);
-   }
-   if (timeout<=0)
-      printk("Timeout waiting for Bus Busy\n");
-     /*
-      set_pcf(adap, 1, I2C_PCF_STOP);
-   */
-   return(timeout<=0);
+	status = get_pcf(adap, 1);
+	while (timeout-- && !(status & I2C_PCF_BB)) {
+		udelay(1000); /* How much is this? */
+		status = get_pcf(adap, 1);
+	}
+	if (timeout<=0)
+		printk("Timeout waiting for Bus Busy\n");
+	/*
+	set_pcf(adap, 1, I2C_PCF_STOP);
+	*/
+	return(timeout<=0);
 }
 
 
@@ -165,17 +129,17 @@
 
 static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
 
-   int timeout = DEF_TIMEOUT;
+	int timeout = DEF_TIMEOUT;
 
-   *status = get_pcf(adap, 1);
-   while (timeout-- && (*status & I2C_PCF_PIN)) {
-      adap->waitforpin();
-      *status = get_pcf(adap, 1);
-   }
-   if (timeout <= 0)
-      return(-1);
-   else
-      return(0);
+	*status = get_pcf(adap, 1);
+	while (timeout-- && (*status & I2C_PCF_PIN)) {
+		adap->waitforpin();
+		*status = get_pcf(adap, 1);
+	}
+	if (timeout <= 0)
+		return(-1);
+	else
+		return(0);
 }
 
 
@@ -231,7 +195,8 @@
 		goto bailout;
 	}
 	sdalo(adap);
-	printk("i2c-algo-pcf.o:1 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-pcf.o:1 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 != getsda(adap) ) {
 		printk("i2c-algo-pcf.o: %s SDA stuck high!\n",name);
 		sdahi(adap);
@@ -243,18 +208,21 @@
 		goto bailout;
 	}		
 	sdahi(adap);
-	printk("i2c-algo-pcf.o:2 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-pcf.o:2 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 == getsda(adap) ) {
 		printk("i2c-algo-pcf.o: %s SDA stuck low!\n",name);
 		sdahi(adap);
 		goto bailout;
 	}
 	if ( 0 == getscl(adap) ) {
-		printk("i2c-algo-pcf.o: %s SCL unexpected low while SDA high!\n",adap->name);
+		printk("i2c-algo-pcf.o: %s SCL unexpected low while SDA high!\n",
+		       adap->name);
 	goto bailout;
 	}
 	scllo(adap);
-	printk("i2c-algo-pcf.o:3 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-pcf.o:3 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 != getscl(adap) ) {
 		printk("i2c-algo-pcf.o: %s SCL stuck high!\n",name);
 		sclhi(adap);
@@ -266,7 +234,8 @@
 		goto bailout;
 	}
 	sclhi(adap);
-	printk("i2c-algo-pcf.o:4 scl: %d  sda: %d \n",getscl(adap),getsda(adap));
+	printk("i2c-algo-pcf.o:4 scl: %d  sda: %d \n",getscl(adap),
+	       getsda(adap));
 	if ( 0 == getscl(adap) ) {
 		printk("i2c-algo-pcf.o: %s SCL stuck low!\n",name);
 		sclhi(adap);
@@ -293,99 +262,99 @@
 static inline int try_address(struct i2c_algo_pcf_data *adap,
 		       unsigned char addr, int retries)
 {
-   int i, status, ret = -1;
-   for (i=0;i<retries;i++) {
-      i2c_outb(adap, addr);
-      i2c_start(adap);
-      status = get_pcf(adap, 1);
-      if (wait_for_pin(adap, &status) >= 0) {
-	 if ((status && I2C_PCF_LRB) == 0) { 
-	    i2c_stop(adap);
-	    break;	/* success! */
-	 }
-      }
-      i2c_stop(adap);
-      udelay(adap->udelay);
-   }
-   DEB2(if (i) printk("i2c-algo-pcf.o: needed %d retries for %d\n",i,addr));
-   return ret;
+	int i, status, ret = -1;
+	for (i=0;i<retries;i++) {
+		i2c_outb(adap, addr);
+		i2c_start(adap);
+		status = get_pcf(adap, 1);
+		if (wait_for_pin(adap, &status) >= 0) {
+			if ((status && I2C_PCF_LRB) == 0) { 
+				i2c_stop(adap);
+				break;	/* success! */
+			}
+		}
+		i2c_stop(adap);
+		udelay(adap->udelay);
+	}
+	DEB2(if (i) printk("i2c-algo-pcf.o: needed %d retries for %d\n",i,
+	                   addr));
+	return ret;
 }
 
 
-static int pcf_sendbytes(struct i2c_adapter *i2c_adap,const char *buf, int count)
-{
-   struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
-   int wrcount, status, timeout;
-
-   for (wrcount=0; wrcount<count; ++wrcount) {
-      DEB2(printk("i2c-algo-pcf.o: %s i2c_write: writing %2.2X\n",
-		  i2c_adap->name, buf[wrcount]&0xff));
-      i2c_outb(adap, buf[wrcount]);
-      timeout = wait_for_pin(adap, &status);
-      if (timeout) {
-	 printk("i2c-algo-pcf.o: %s i2c_write: error - timeout.\n",
-		i2c_adap->name);
-	 i2c_stop(adap);
-	 return -EREMOTEIO; /* got a better one ?? */
-      }
-      if (status & I2C_PCF_LRB) {
-	 printk("i2c-algo-pcf.o: %s i2c_write: error - no ack.\n",
-		i2c_adap->name);
-	 i2c_stop(adap);
-	 return -EREMOTEIO; /* got a better one ?? */
-      }
-   }
-   return (wrcount);
+static int pcf_sendbytes(struct i2c_adapter *i2c_adap,const char *buf,
+                         int count)
+{
+	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
+	int wrcount, status, timeout;
+
+	for (wrcount=0; wrcount<count; ++wrcount) {
+		DEB2(printk("i2c-algo-pcf.o: %s i2c_write: writing %2.2X\n",
+		     i2c_adap->name, buf[wrcount]&0xff));
+		i2c_outb(adap, buf[wrcount]);
+		timeout = wait_for_pin(adap, &status);
+		if (timeout) {
+			printk("i2c-algo-pcf.o: %s i2c_write: error - timeout.\n",
+			       i2c_adap->name);
+			i2c_stop(adap);
+			return -EREMOTEIO; /* got a better one ?? */
+		}
+		if (status & I2C_PCF_LRB) {
+			 printk("i2c-algo-pcf.o: %s i2c_write: error - no ack.\n",
+				i2c_adap->name);
+			 i2c_stop(adap);
+			 return -EREMOTEIO; /* got a better one ?? */
+		}
+	}
+	return (wrcount);
 }
 
 
 static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
 {
-   int rdcount=0, i, status, timeout, dummy=1;
-   struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
+	int rdcount=0, i, status, timeout, dummy=1;
+	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
  
-   for (i=0; i<count-1; ++i) {
-      buf[rdcount] =  i2c_inb(adap);
-      if (dummy) {
-	 dummy = 0;
-      }
-      else
-	 rdcount++;
-      timeout = wait_for_pin(adap, &status);
-      if (timeout) {
-	 printk("i2c-algo-pcf.o: i2c_read: i2c_inb timed out.\n");
-	 return (-1);
-      }
-      if (status & I2C_PCF_LRB) {
-	 printk("i2c-algo-pcf.o: i2c_read: i2c_inb, No ack.\n");
-	 return (-1);
-      }
-   }
-   set_pcf(adap, 1, I2C_PCF_ESO);
-   buf[rdcount] = i2c_inb(adap);
-   if (dummy) {
-      dummy = 0;
-   }
-   else
-      rdcount++;
-   timeout = wait_for_pin(adap, &status);
-   if (timeout) {
-      printk("i2c-algo-pcf.o: i2c_read: i2c_inb timed out.\n");
-      return (-1);
-   }
-   return (rdcount);
+	for (i=0; i<count-1; ++i) {
+		buf[rdcount] =  i2c_inb(adap);
+		if (dummy) {
+			dummy = 0;
+		} else
+			rdcount++;
+		timeout = wait_for_pin(adap, &status);
+		if (timeout) {
+			printk("i2c-algo-pcf.o: i2c_read: i2c_inb timed out.\n");
+			return (-1);
+		}
+		if (status & I2C_PCF_LRB) {
+			printk("i2c-algo-pcf.o: i2c_read: i2c_inb, No ack.\n");
+			return (-1);
+		}
+	}
+	set_pcf(adap, 1, I2C_PCF_ESO);
+	buf[rdcount] = i2c_inb(adap);
+	if (dummy) {
+		dummy = 0;
+	} else
+		rdcount++;
+	timeout = wait_for_pin(adap, &status);
+	if (timeout) {
+		printk("i2c-algo-pcf.o: i2c_read: i2c_inb timed out.\n");
+		return (-1);
+	}
+	return (rdcount);
 }
 
 
-static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap, struct i2c_msg *msg,
-			 int retries) 
+static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap,
+                                struct i2c_msg *msg, int retries) 
 {
 	unsigned short flags = msg->flags;
 	unsigned char addr;
 	int ret;
 	if ( (flags & I2C_M_TEN)  ) { 
 		/* a ten bit address */
-                addr = 0xf0 | (( msg->addr >> 7) & 0x03);
+		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
 		DEB2(printk("addr0: %d\n",addr));
 		/* try extended address code...*/
 		ret = try_address(adap, addr, retries);
@@ -414,6 +383,8 @@
 		addr = ( msg->addr << 1 );
 		if (flags & I2C_M_RD )
 			addr |= 1;
+		if (flags & I2C_M_REV_DIR_ADDR )
+			addr ^= 1;
 		i2c_outb(adap, addr);
 	}
 	return 0;
@@ -423,71 +394,50 @@
 		    struct i2c_msg msgs[], 
 		    int num)
 {
-   struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
-   struct i2c_msg *pmsg;
-   int i, ret, timeout, status;
-
-   timeout = wait_for_bb(adap);
-   if (timeout) {
-      DEB2(printk("i2c-algo-pcf.o: Timeout waiting for BB in pcf_xfer\n");)
-      return -EIO;
-   }
-   pmsg = &msgs[0];
-   ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
-   i2c_start(adap);
-
-   for (i=0; i<num; i++) {
-      DEB3(printk("i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
-		  i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
-      timeout = wait_for_pin(adap, &status);
-      if (timeout) {
-	 DEB2(printk("i2c-algo-pcf.o: Timeout waiting for PIN(1) in pcf_xfer\n");)
-	 i2c_stop(adap);
-	 return (-EREMOTEIO);
-      }
-      if (status & I2C_PCF_LRB) {
-	 i2c_stop(adap);
-	 DEB2(printk("i2c-algo-pcf.o: NAK from device adr %#2x msg #%d\n"
-			       ,msgs[i].addr,i));
-	 return -EREMOTEIO;
-      }
-      if (pmsg->flags & I2C_M_RD ) {
-	 /* read bytes into buffer*/
-	 ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len);
-	 DEB2(printk("i2c-algo-pcf.o: read %d bytes.\n",ret));
-      } else {
-	 /* write bytes from buffer */
-	 ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len);
-	 DEB2(printk("i2c-algo-pcf.o: wrote %d bytes.\n",ret));
-      }
-      if (i == (num-1)) {
-	 i2c_stop(adap);	 
-      }
-      else {
-	 i2c_repstart(adap);
-      }
-      if (pmsg->flags & I2C_M_RD ) {
-	 pmsg->buf[pmsg->len-1] =  i2c_inb(adap);
-      }
-      if (i != (num-1)) {
-	 pmsg = &msgs[0];
-	 ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
-	 timeout = wait_for_pin(adap, &status);
-	 if (timeout) {
-	    DEB2(printk("i2c-algo-pcf.o: Timeout waiting for PIN(2) in pcf_xfer\n");)
-	    return (-EREMOTEIO);
-	 }
-	 if (status & I2C_PCF_LRB) {
-	    i2c_stop(adap);
-	    DEB2(printk("i2c-algo-pcf.o: No LRB(2) in pcf_xfer\n");)
-	    return (-EREMOTEIO);
-	 }
-      }
-   }
-   return (num);
+	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
+	struct i2c_msg *pmsg;
+	int i, ret, timeout, status;
+
+	timeout = wait_for_bb(adap);
+	if (timeout) {
+		DEB2(printk("i2c-algo-pcf.o: Timeout waiting for BB in pcf_xfer\n");)
+		return -EIO;
+	}
+	i2c_start(adap);
+
+	for (i=0; i<num; i++) {
+		pmsg = &msgs[i];
+		if (!(pmsg->flags & I2C_M_NOSTART)) {
+			if (i) 
+				i2c_repstart(adap);
+		 	ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
+		 	timeout = wait_for_pin(adap, &status);
+		 	if (timeout) {
+				DEB2(printk("i2c-algo-pcf.o: Timeout waiting for PIN(1) in pcf_xfer\n");)
+				return (-EREMOTEIO);
+		 	}
+		 	if (status & I2C_PCF_LRB) {
+				i2c_stop(adap);
+				DEB2(printk("i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
+				return (-EREMOTEIO);
+		 	}
+		}
+		DEB3(printk("i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
+		            i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
+		if (pmsg->flags & I2C_M_RD ) {
+			/* read bytes into buffer*/
+			ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len);
+			DEB2(printk("i2c-algo-pcf.o: read %d bytes.\n",ret));
+		} else {
+			/* write bytes from buffer */
+			ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len);
+			DEB2(printk("i2c-algo-pcf.o: wrote %d bytes.\n",ret));
+		}
+	}
+	i2c_stop(adap);	 
+	return (num);
 }
 
-
 static int algo_control(struct i2c_adapter *adapter, 
 	unsigned int cmd, unsigned long arg)
 {
@@ -496,7 +446,8 @@
 
 static u32 pcf_func(struct i2c_adapter *adap)
 {
-        return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 
+	       I2C_FUNC_PROTOCOL_MANGLING; 
 }
 
 /* -----exported algorithm data: -------------------------------------	*/
@@ -509,7 +460,7 @@
 	NULL,				/* slave_xmit		*/
 	NULL,				/* slave_recv		*/
 	algo_control,			/* ioctl		*/
-	pcf_func,                       /* functionality        */
+	pcf_func,			/* functionality	*/
 };
 
 /* 
@@ -526,7 +477,8 @@
 			return -ENODEV;
 	}
 
-	DEB2(printk("i2c-algo-pcf.o: hw routines for %s registered.\n",adap->name));
+	DEB2(printk("i2c-algo-pcf.o: hw routines for %s registered.\n",
+	            adap->name));
 
 	/* register new adapter to i2c module... */
 
@@ -545,20 +497,21 @@
 
 	/* scan bus */
 	if (pcf_scan) {
-	   printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s.\n", adap->name);
-	   for (i = 0x00; i < 0xff; i+=2) {
-	      i2c_outb(pcf_adap, i);
-	      i2c_start(pcf_adap);
-	      if ((wait_for_pin(pcf_adap, &status) >= 0) && 
-		  ((status && I2C_PCF_LRB) == 0)) { 
-		 printk("(%02x)",i>>1); 
-	      } else {
-		 printk("."); 
-	      }
-	      i2c_stop(pcf_adap);
-	      udelay(pcf_adap->udelay);
-	   }
-	   printk("\n");
+		printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s.\n",
+		       adap->name);
+		for (i = 0x00; i < 0xff; i+=2) {
+			i2c_outb(pcf_adap, i);
+			i2c_start(pcf_adap);
+			if ((wait_for_pin(pcf_adap, &status) >= 0) && 
+			    ((status && I2C_PCF_LRB) == 0)) { 
+				printk("(%02x)",i>>1); 
+			} else {
+				printk("."); 
+			}
+			i2c_stop(pcf_adap);
+			udelay(pcf_adap->udelay);
+		}
+		printk("\n");
 	}
 	return 0;
 }
@@ -577,7 +530,7 @@
 
 int __init i2c_algo_pcf_init (void)
 {
-        printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n");
+	printk("i2c-algo-pcf.o: i2c pcf8584 algorithm module\n");
 	return 0;
 }
 
@@ -595,7 +548,8 @@
 
 MODULE_PARM_DESC(pcf_test, "Test if the I2C bus is available");
 MODULE_PARM_DESC(pcf_scan, "Scan for active chips on the bus");
-MODULE_PARM_DESC(i2c_debug,"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
+MODULE_PARM_DESC(i2c_debug,
+        "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
 
 
 int init_module(void) 
diff -u --recursive --new-file v2.3.42/linux/drivers/i2c/i2c-core.c linux/drivers/i2c/i2c-core.c
--- v2.3.42/linux/drivers/i2c/i2c-core.c	Tue Feb  1 01:35:43 2000
+++ linux/drivers/i2c/i2c-core.c	Wed Feb  9 18:48:03 2000
@@ -20,7 +20,7 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-core.c,v 1.48 2000/01/24 21:41:19 frodo Exp $ */
+/* $Id: i2c-core.c,v 1.50 2000/02/02 23:29:54 frodo Exp $ */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -98,8 +98,7 @@
 /* To implement the dynamic /proc/bus/i2c-? files, we need our own 
    implementation of the read hook */
 static struct file_operations i2cproc_operations = {
-	NULL,
-	i2cproc_bus_read,
+	read:		i2cproc_bus_read,
 };
 
 static struct inode_operations i2cproc_inode_operations = {
@@ -475,38 +474,58 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	char *kbuf;
 	struct i2c_client *client;
-	int i,j,len=0;
+	int i,j,k,order_nr,len=0,len_total;
+	int order[I2C_CLIENT_MAX];
 
 	if (count < 0)
-		return -EINVAL;
-	if (count > 4000)
-		count = 4000;
+		return -EINVAL; 
+	len_total = file->f_pos + count;
+	/* Too bad if this gets longer (unlikely) */
+	if (len_total > 4000)
+		len_total = 4000;
 	for (i = 0; i < I2C_ADAP_MAX; i++)
 		if (adapters[i]->inode == inode->i_ino) {
 		/* We need a bit of slack in the kernel buffer; this makes the
 		   sprintf safe. */
 			if (! (kbuf = kmalloc(count + 80,GFP_KERNEL)))
 				return -ENOMEM;
-			for (j = 0; j < I2C_CLIENT_MAX; j++)
-				if ((client = adapters[i]->clients[j]))
-					/* Filter out dummy clients */
-					if (client->driver->id != I2C_DRIVERID_I2CDEV)
-						len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
-						              client->addr,
-						              client->name,client->driver->name);
-					if (file->f_pos+len > count)
-						len = count - file->f_pos;
-					len = len - file->f_pos;
-					if (len < 0) 
-						len = 0;
-					if (copy_to_user (buf,kbuf+file->f_pos,
-					    len)) {
-						kfree(kbuf);
-						return -EFAULT;
-					}
-					file->f_pos += len;
-					kfree(kbuf);
-					return len;
+			/* Order will hold the indexes of the clients
+			   sorted by address */
+			order_nr=0;
+			for (j = 0; j < I2C_CLIENT_MAX; j++) {
+				if ((client = adapters[i]->clients[j]) && 
+				    (client->driver->id != I2C_DRIVERID_I2CDEV))  {
+					for(k = order_nr; 
+					    (k > 0) && 
+					    adapters[i]->clients[order[k-1]]->
+					             addr > client->addr; 
+					    k--)
+						order[k] = order[k-1];
+					order[k] = j;
+					order_nr++;
+				}
+			}
+
+
+			for (j = 0; (j < order_nr) && (len < len_total); j++) {
+				client = adapters[i]->clients[order[j]];
+				len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
+				              client->addr,
+				              client->name,
+				              client->driver->name);
+			}
+			len = len - file->f_pos;
+			if (len > count)
+				len = count;
+			if (len < 0) 
+				len = 0;
+			if (copy_to_user (buf,kbuf+file->f_pos, len)) {
+				kfree(kbuf);
+				return -EFAULT;
+			}
+			file->f_pos += len;
+			kfree(kbuf);
+			return len;
 		}
 	return -ENOENT;
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/i2c/i2c-dev.c linux/drivers/i2c/i2c-dev.c
--- v2.3.42/linux/drivers/i2c/i2c-dev.c	Tue Feb  1 01:35:43 2000
+++ linux/drivers/i2c/i2c-dev.c	Wed Feb  9 11:42:35 2000
@@ -74,16 +74,12 @@
 static int i2cdev_cleanup(void);
 
 static struct file_operations i2cdev_fops = {
-	i2cdev_lseek,
-	i2cdev_read,
-	i2cdev_write,
-	NULL,			/* i2cdev_readdir	*/
-	NULL,			/* i2cdev_select	*/
-	i2cdev_ioctl,
-	NULL,			/* i2cdev_mmap		*/
-	i2cdev_open,
-	NULL,			/* i2cdev_flush		*/
-	i2cdev_release,
+	llseek:		i2cdev_lseek,
+	read:		i2cdev_read,
+	write:		i2cdev_write,
+	ioctl:		i2cdev_ioctl,
+	open:		i2cdev_open,
+	release:	i2cdev_release,
 };
 
 #define I2CDEV_ADAPS_MAX I2C_ADAP_MAX
diff -u --recursive --new-file v2.3.42/linux/drivers/i2c/i2c-elv.c linux/drivers/i2c/i2c-elv.c
--- v2.3.42/linux/drivers/i2c/i2c-elv.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/i2c/i2c-elv.c	Wed Feb  9 18:48:03 2000
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /* i2c-elv.c i2c-hw access for philips style parallel port adapters	     */
 /* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-99 Simon G. Vogl
+/*   Copyright (C) 1995-2000 Simon G. Vogl
 
     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
@@ -16,39 +16,21 @@
     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., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
-/* ------------------------------------------------------------------------- 
+/* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-elv.c,v 1.12 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-elv.c,v 1.16 2000/01/18 23:54:07 frodo Exp $ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
 #include <linux/version.h>
-#if LINUX_VERSION_CODE >= 0x020135
 #include <linux/init.h>
-#else
-#define __init 
-#endif
-
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
 
-#if LINUX_VERSION_CODE >= 0x020100
-#  include <asm/uaccess.h>
-#else
-#  include <asm/segment.h>
-#endif
+#include <asm/uaccess.h>
 
 #include <linux/ioport.h>
 #include <asm/io.h>
@@ -66,11 +48,11 @@
 #define DEBE(x)	x	/* error messages 				*/
 #define DEBINIT(x) x	/* detection status messages			*/
 
-/* --- Convenience defines for the parallel port:                       */
-#define BASE    (unsigned int)(data)
-#define DATA    BASE                    /* Centronics data port         */
-#define STAT    (BASE+1)                /* Centronics status port       */
-#define CTRL    (BASE+2)                /* Centronics control port      */
+/* --- Convenience defines for the parallel port:			*/
+#define BASE	(unsigned int)(data)
+#define DATA	BASE			/* Centronics data port		*/
+#define STAT	(BASE+1)		/* Centronics status port	*/
+#define CTRL	(BASE+2)		/* Centronics control port	*/
 
 
 /* ----- local functions ----------------------------------------------	*/
@@ -127,8 +109,8 @@
 		request_region(base,(base == 0x3bc)? 3 : 8,
 			"i2c (ELV adapter)");
 		PortData = 0;
-                bit_elv_setsda((void*)base,1);
-                bit_elv_setscl((void*)base,1);
+		bit_elv_setsda((void*)base,1);
+		bit_elv_setscl((void*)base,1);
 	}
 	return 0;
 }
@@ -140,7 +122,7 @@
 
 static int bit_elv_reg(struct i2c_client *client)
 {
-        return 0;
+	return 0;
 }
 
 static int bit_elv_unreg(struct i2c_client *client)
@@ -151,14 +133,14 @@
 static void bit_elv_inc_use(struct i2c_adapter *adap)
 {
 #ifdef MODULE
-  MOD_INC_USE_COUNT;
+	MOD_INC_USE_COUNT;
 #endif
 }
 
 static void bit_elv_dec_use(struct i2c_adapter *adap)
 {
 #ifdef MODULE
-  MOD_DEC_USE_COUNT;
+	MOD_DEC_USE_COUNT;
 #endif
 }
 
@@ -172,7 +154,7 @@
 	bit_elv_setscl,
 	bit_elv_getsda,
 	bit_elv_getscl,
-	80, 80, 100,		/*      waits, timeout */
+	80, 80, 100,		/*	waits, timeout */
 };
 
 static struct i2c_adapter bit_elv_ops = {
@@ -186,30 +168,30 @@
 	bit_elv_unreg,	
 };
 
-int  __init i2c_bitelv_init(void)
+int __init i2c_bitelv_init(void)
 {
 	printk("i2c-elv.o: i2c ELV parallel port adapter module\n");
-        if (base==0) {
-                /* probe some values */
-                base=DEFAULT_BASE;
-                bit_elv_data.data=(void*)DEFAULT_BASE;
-                if (bit_elv_init()==0) {
-                        if(i2c_bit_add_bus(&bit_elv_ops) < 0)
+	if (base==0) {
+		/* probe some values */
+		base=DEFAULT_BASE;
+		bit_elv_data.data=(void*)DEFAULT_BASE;
+		if (bit_elv_init()==0) {
+			if(i2c_bit_add_bus(&bit_elv_ops) < 0)
 				return -ENODEV;
-                } else {
-                        return -ENODEV;
-                }
-        } else {
-                bit_elv_ops.data=(void*)base;
-                if (bit_elv_init()==0) {
-                        if(i2c_bit_add_bus(&bit_elv_ops) < 0)
+		} else {
+			return -ENODEV;
+		}
+	} else {
+		bit_elv_ops.data=(void*)base;
+		if (bit_elv_init()==0) {
+			if(i2c_bit_add_bus(&bit_elv_ops) < 0)
 				return -ENODEV;
-                } else {
-                        return -ENODEV;
-                }
-        }
-        printk("i2c-elv.o: found device at %#x.\n",base);
-        return 0;
+		} else {
+			return -ENODEV;
+		}
+	}
+	printk("i2c-elv.o: found device at %#x.\n",base);
+	return 0;
 }
 
 
@@ -224,13 +206,13 @@
 
 int init_module(void)
 {
-        return i2c_bitelv_init();
+	return i2c_bitelv_init();
 }
 
 void cleanup_module(void)
 {
-        i2c_bit_del_bus(&bit_elv_ops);
-        bit_elv_exit();
+	i2c_bit_del_bus(&bit_elv_ops);
+	bit_elv_exit();
 }
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/drivers/i2c/i2c-philips-par.c linux/drivers/i2c/i2c-philips-par.c
--- v2.3.42/linux/drivers/i2c/i2c-philips-par.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/i2c/i2c-philips-par.c	Wed Feb  9 18:48:03 2000
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /* i2c-philips-par.c i2c-hw access for philips style parallel port adapters  */
 /* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-99 Simon G. Vogl
+/*   Copyright (C) 1995-2000 Simon G. Vogl
 
     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
@@ -16,34 +16,20 @@
     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., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
-/* ------------------------------------------------------------------------- 
+/* ------------------------------------------------------------------------- */ 
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c-philips-par.c,v 1.12 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-philips-par.c,v 1.16 2000/01/18 23:54:07 frodo Exp $ */
 
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
-#if LINUX_VERSION_CODE >= 0x020135
 #include <linux/init.h>
-#else
-#define __init 
-#endif
 #include <asm/io.h>
 #include <linux/stddef.h>
 
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
-
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
@@ -147,12 +133,12 @@
 
 static void bit_lp_inc_use(struct i2c_adapter *adap)
 {
-  MOD_INC_USE_COUNT;
+	MOD_INC_USE_COUNT;
 }
 
 static void bit_lp_dec_use(struct i2c_adapter *adap)
 {
-  MOD_DEC_USE_COUNT;
+	MOD_DEC_USE_COUNT;
 }
 
 /* ------------------------------------------------------------------------
@@ -183,7 +169,7 @@
 
 int __init i2c_bitlp_init(void)
 {
-        printk("i2c-philips-par.o: i2c Philips parallel port adapter module\n");
+	printk("i2c-philips-par.o: i2c Philips parallel port adapter module\n");
 	if (base==0) {
 		/* probe some values */
 		base=DEFAULT_BASE;
diff -u --recursive --new-file v2.3.42/linux/drivers/i2c/i2c-velleman.c linux/drivers/i2c/i2c-velleman.c
--- v2.3.42/linux/drivers/i2c/i2c-velleman.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/i2c/i2c-velleman.c	Wed Feb  9 18:48:03 2000
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------- */
 /* i2c-velleman.c i2c-hw access for Velleman K9000 adapters		     */
 /* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-96 Simon G. Vogl
+/*   Copyright (C) 1995-96, 2000 Simon G. Vogl
 
     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
@@ -16,32 +16,18 @@
     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., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
-/* ------------------------------------------------------------------------- 
+/* ------------------------------------------------------------------------- */
 
-/* $Id: i2c-velleman.c,v 1.14 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-velleman.c,v 1.19 2000/01/24 02:06:33 mds Exp $ */
 
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
-#if LINUX_VERSION_CODE >= 0x020135
 #include <linux/init.h>
-#else
-#define __init 
-#endif
 #include <linux/string.h>  /* for 2.0 kernels to get NULL   */
 #include <asm/errno.h>     /* for 2.0 kernels to get ENODEV */
 #include <asm/io.h>
 
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
-
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
@@ -55,7 +41,7 @@
 #define I2C_SCL		0x08		/*  ctrl bit 3 	(inv)	*/
 
 #define I2C_SDAIN	0x10		/* stat bit 4		*/
-#define I2C_SCLIN	0x08		/*  ctrl bit 3 (inv) (reads own output) */
+#define I2C_SCLIN	0x08		/* ctrl bit 3 (inv)(reads own output)*/
 
 #define I2C_DMASK	0xfd
 #define I2C_CMASK	0xf7
@@ -105,7 +91,8 @@
 static int bit_velle_init(void)
 {
 	if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
-		DEBE(printk("i2c-velleman.o: Port %#x already in use.\n", base));
+		DEBE(printk("i2c-velleman.o: Port %#x already in use.\n",
+		     base));
 		return -ENODEV;
 	} else {
 		request_region(base, (base == 0x3bc)? 3 : 8, 
@@ -173,7 +160,7 @@
 
 int __init  i2c_bitvelle_init(void)
 {
-        printk("i2c-velleman.o: i2c Velleman K8000 adapter module\n");
+	printk("i2c-velleman.o: i2c Velleman K8000 adapter module\n");
 	if (base==0) {
 		/* probe some values */
 		base=DEFAULT_BASE;
diff -u --recursive --new-file v2.3.42/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c
--- v2.3.42/linux/drivers/i2o/i2o_config.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/i2o/i2o_config.c	Wed Feb  9 11:42:35 2000
@@ -881,18 +881,13 @@
 
 static struct file_operations config_fops =
 {
-	cfg_llseek,
-	cfg_read,
-	cfg_write,
-	NULL,
-	NULL /*cfg_poll*/,
-	cfg_ioctl,
-	NULL,		/* No mmap */
-	cfg_open,
-	NULL,		/* No flush */
-	cfg_release,
-	NULL,
-	cfg_fasync
+	llseek:		cfg_llseek,
+	read:		cfg_read,
+	write:		cfg_write,
+	ioctl:		cfg_ioctl,
+	open:		cfg_open,
+	release:	cfg_release,
+	fasync:		cfg_fasync,
 };
 
 static struct miscdevice i2o_miscdev = {
diff -u --recursive --new-file v2.3.42/linux/drivers/ieee1394/pcilynx.c linux/drivers/ieee1394/pcilynx.c
--- v2.3.42/linux/drivers/ieee1394/pcilynx.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/ieee1394/pcilynx.c	Wed Feb  9 11:42:35 2000
@@ -681,12 +681,12 @@
 
 
 static struct file_operations aux_ops = {
-        /* FIXME: should have custom llseek with bounds checking*/
-        read:     mem_read,
-        write:    mem_write,
-        poll:     aux_poll,
-        open:     mem_open,
-        release:  mem_release
+	/* FIXME: should have custom llseek with bounds checking */
+	read:		mem_read,
+	write:		mem_write,
+	poll:		aux_poll,
+	open:		mem_open,
+	release:	mem_release,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.3.42/linux/drivers/isdn/avmb1/capi.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/isdn/avmb1/capi.c	Wed Feb  9 11:42:35 2000
@@ -511,18 +511,13 @@
 
 static struct file_operations capi_fops =
 {
-	capi_llseek,
-	capi_read,
-	capi_write,
-	NULL,			/* capi_readdir */
-	capi_poll,
-	capi_ioctl,
-	NULL,			/* capi_mmap */
-	capi_open,
-        NULL,                   /* capi_flush */
-	capi_release,
-	NULL,			/* capi_fsync */
-	NULL,			/* capi_fasync */
+	llseek:		capi_llseek,
+	read:		capi_read,
+	write:		capi_write,
+	poll:		capi_poll,
+	ioctl:		capi_ioctl,
+	open:		capi_open,
+	release:	capi_release,
 };
 
 /* -------- /proc functions ----------------------------------- */
diff -u --recursive --new-file v2.3.42/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c
--- v2.3.42/linux/drivers/isdn/divert/divert_procfs.c	Tue Dec  7 09:32:43 1999
+++ linux/drivers/isdn/divert/divert_procfs.c	Wed Feb  9 11:42:35 2000
@@ -279,17 +279,13 @@
 
 static struct file_operations isdn_fops =
 {
-	isdn_divert_lseek,
-	isdn_divert_read,
-	isdn_divert_write,
-	NULL,                          /* isdn_readdir */
-	isdn_divert_poll,              /* isdn_poll */
-	isdn_divert_ioctl,             /* isdn_ioctl */
-	NULL,                          /* isdn_mmap */
-	isdn_divert_open,
-	NULL,                          /* flush */ 
-	isdn_divert_close,
-	NULL                           /* fsync */
+	llseek:		isdn_divert_lseek,
+	read:		isdn_divert_read,
+	write:		isdn_divert_write,
+	poll:		isdn_divert_poll,
+	ioctl:		isdn_divert_ioctl,
+	open:		isdn_divert_open,
+	release:	isdn_divert_close,
 };
 
 struct inode_operations divert_file_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.3.42/linux/drivers/isdn/isdn_common.c	Thu Nov 11 20:11:38 1999
+++ linux/drivers/isdn/isdn_common.c	Wed Feb  9 11:42:35 2000
@@ -2024,17 +2024,13 @@
 
 static struct file_operations isdn_fops =
 {
-	isdn_lseek,
-	isdn_read,
-	isdn_write,
-	NULL,                   /* isdn_readdir */
-	isdn_poll,              /* isdn_poll */
-	isdn_ioctl,             /* isdn_ioctl */
-	NULL,                   /* isdn_mmap */
-	isdn_open,
-	NULL,			/* flush */
-	isdn_close,
-	NULL                    /* fsync */
+	llseek:		isdn_lseek,
+	read:		isdn_read,
+	write:		isdn_write,
+	poll:		isdn_poll,
+	ioctl:		isdn_ioctl,
+	open:		isdn_open,
+	release:	isdn_close,
 };
 
 char *
diff -u --recursive --new-file v2.3.42/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile
--- v2.3.42/linux/drivers/macintosh/Makefile	Sat Oct  9 11:47:50 1999
+++ linux/drivers/macintosh/Makefile	Mon Feb  7 09:51:43 2000
@@ -18,6 +18,10 @@
 
 ifeq ($(CONFIG_PMAC_PBOOK),y)
   L_OBJS += mediabay.o
+else
+  ifeq ($(CONFIG_MAC_FLOPPY),y)
+    L_OBJS += mediabay.o
+  endif
 endif
 
 ifeq ($(CONFIG_MAC_SERIAL),y)
diff -u --recursive --new-file v2.3.42/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.3.42/linux/drivers/macintosh/adb.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/macintosh/adb.c	Wed Feb  9 19:43:57 2000
@@ -247,6 +247,8 @@
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 		adb_got_sleep = 1;
+		if (adb_controller->autopoll)
+			adb_controller->autopoll(0);
 		ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
 		if (ret & NOTIFY_STOP_MASK)
 			return PBOOK_SLEEP_REFUSE;
@@ -262,6 +264,7 @@
 		break;
 	case PBOOK_WAKE:
 		adb_reset_bus();
+		adb_got_sleep = 0;
 		break;
 	}
 	return PBOOK_SLEEP_OK;
@@ -271,15 +274,21 @@
 int
 adb_reset_bus(void)
 {
-	int ret, devs;
+	int ret, nret, devs;
 	unsigned long flags;
 	
 	if (adb_controller == NULL)
 		return -ENXIO;
 		
-	ret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL);
-	if (ret & NOTIFY_STOP_MASK)
+	if (adb_controller->autopoll)
+		adb_controller->autopoll(0);
+
+	nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL);
+	if (nret & NOTIFY_STOP_MASK) {
+		if (adb_controller->autopoll)
+			adb_controller->autopoll(devs);
 		return -EBUSY;
+	}
 
 	save_flags(flags);
 	cli();
@@ -291,18 +300,17 @@
 	else
 		ret = 0;
 
-	if (!ret)
-	{
+	if (!ret) {
 		devs = adb_scan_bus();
 		if (adb_controller->autopoll)
 			adb_controller->autopoll(devs);
 	}
 
-	ret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL);
-	if (ret & NOTIFY_STOP_MASK)
+	nret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL);
+	if (nret & NOTIFY_STOP_MASK)
 		return -EBUSY;
 	
-	return 1;
+	return ret;
 }
 
 void
@@ -383,6 +391,12 @@
 	int i, id;
 	static int dump_adb_input = 0;
 
+	/* We skip keystrokes and mouse moves when the sleep process
+	 * has been started. We stop autopoll, but this is another security
+	 */
+	if (adb_got_sleep)
+		return;
+		
 	id = buf[0] >> 4;
 	if (dump_adb_input) {
 		printk(KERN_INFO "adb packet: ");
@@ -403,12 +417,8 @@
 
 	if (adb_handler[address].handler_id == new_id)
 	    return 1;
-	adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
-    	    ADB_READREG(address,3));
-	if (req.reply_len < 2)
-	    return 0;
 	adb_request(&req, NULL, ADBREQ_SYNC, 3,
-	    ADB_WRITEREG(address, 3), req.reply[1] & 0xF0, new_id);	
+	    ADB_WRITEREG(address, 3), address | 0x20, new_id);
 	adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
 	    ADB_READREG(address, 3));
 	if (req.reply_len < 2)
@@ -611,10 +621,11 @@
 	/* Special case for ADB_BUSRESET request, all others are sent to
 	   the controller */
 	if ((req->data[0] == ADB_PACKET)&&(count > 1)
-		&&(req->data[1] == ADB_BUSRESET))
+		&&(req->data[1] == ADB_BUSRESET)) {
 		ret = adb_reset_bus();
-	else
-	{	
+		atomic_dec(&state->n_pending);
+		goto out;
+	} else {	
 		req->reply_expected = ((req->data[1] & 0xc) == 0xc);
 
 		if (adb_controller && adb_controller->send_request)
@@ -635,16 +646,11 @@
 }
 
 static struct file_operations adb_fops = {
-	adb_lseek,
-	adb_read,
-	adb_write,
-	NULL,		/* no readdir */
-	NULL,		/* no poll yet */
-	NULL,		/* no ioctl yet */
-	NULL,		/* no mmap */
-	adb_open,
-	NULL,		/* flush */
-	adb_release
+	llseek:		adb_lseek,
+	read:		adb_read,
+	write:		adb_write,
+	open:		adb_open,
+	release:	adb_release,
 };
 
 void adbdev_init()
diff -u --recursive --new-file v2.3.42/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
--- v2.3.42/linux/drivers/macintosh/mac_keyb.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/macintosh/mac_keyb.c	Wed Feb  9 19:43:47 2000
@@ -16,13 +16,15 @@
  *
  * - Standard 1 button mouse
  * - All standard Apple Extended protocol (handler ID 4)
- *   mice & trackballs
+ * - mouseman and trackman mice & trackballs 
  * - PowerBook Trackpad (default setup: enable tapping)
  * - MicroSpeed mouse & trackball (needs testing)
  * - CH Products Trackball Pro (needs testing)
  * - Contour Design (Contour Mouse)
  * - Hunter digital (NoHandsMouse)
  * - Kensignton TurboMouse 5 (needs testing)
+ * - Mouse Systems A3 mice and trackballs <aidan@kublai.com>
+ * - MacAlly 2-buttons mouse (needs testing) <pochini@denise.shiny.it>
  *
  * To do:
  *
@@ -66,10 +68,10 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,	/* esc...option */
-	0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* fn, num lock */
+	0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* fn, num lock */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* R modifiers */
 };
 
 /* Simple translation table for the SysRq keys */
@@ -239,6 +241,7 @@
 static void init_trackball(int id);
 static void init_turbomouse(int id);
 static void init_microspeed(int id);
+static void init_ms_a3(int id);
 
 #ifdef CONFIG_ADBMOUSE
 /* XXX: Hook for mouse driver */
@@ -268,6 +271,8 @@
 #define ADBMOUSE_TURBOMOUSE5    5	/* Turbomouse 5 (previously req. mousehack) */
 #define ADBMOUSE_MICROSPEED	6	/* Microspeed mouse (&trackball ?), MacPoint */
 #define ADBMOUSE_TRACKBALLPRO	7	/* Trackball Pro (special buttons) */
+#define ADBMOUSE_MS_A3		8	/* Mouse systems A3 trackball (handler 3) */
+#define ADBMOUSE_MACALLY2	9	/* MacAlly 2-button mouse */
 
 static int adb_mouse_kinds[16];
 
@@ -484,6 +489,19 @@
     data[3] = byyy bxxx Third button and fourth button.  Y is additional
 	      high bits of y-axis motion.  XY is additional
 	      high bits of x-axis motion.
+
+    MacAlly 2-button mouse protocol.
+
+    For MacAlly 2-button mouse protocol the data array will contain the
+    following values:
+
+		BITS    COMMENTS
+    data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.
+    data[1] = bxxx xxxx Left button and x-axis motion.
+    data[2] = byyy yyyy Right button and y-axis motion.
+    data[3] = ???? ???? unknown
+    data[4] = ???? ???? unknown
+
   */
 	struct kbd_struct *kbd;
 
@@ -510,6 +528,16 @@
 		data[2] = (data[2] & 0x7f) | ((data[3] & 0x01) << 7);
 		data[3] = (data[3] & 0x77) | ((data[3] & 0x02) << 6);
 		break;
+	    case ADBMOUSE_MS_A3:
+		data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);
+		data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6);
+		data[3] = ((data[3] & 0x04) << 5);
+		break;
+            case ADBMOUSE_MACALLY2:
+		data[3] = (data[2] & 0x80) ? 0x80 : 0x00;
+		data[2] |= 0x80;  /* Right button is mapped as button 3 */
+		nb=4;
+                break;
 	}
 
 	if (adb_mouse_interrupt_hook)
@@ -642,7 +670,6 @@
 
 static void real_mackbd_leds(unsigned char leds, int device)
 {
-
     if (led_request.complete) {
 	adb_request(&led_request, leds_done, 0, 3,
 		    ADB_WRITEREG(device, KEYB_LEDREG), 0xff,
@@ -715,10 +742,18 @@
 static int
 adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
 {
+	unsigned long flags;
+	
 	switch (code) {
 	case ADB_MSG_PRE_RESET:
 	case ADB_MSG_POWERDOWN:
-		/* Add unregister_keyboard when merging with Paul Mackerras */
+	    	/* Stop the repeat timer. Autopoll is already off at this point */
+		save_flags(flags);
+		cli();
+		del_timer(&repeat_timer);
+		restore_flags(flags);
+
+		/* Stop pending led requests */
 		while(!led_request.complete)
 			adb_poll();
 		break;
@@ -753,9 +788,12 @@
 		/* Enable full feature set of the keyboard
 		   ->get it to send separate codes for left and right shift,
 		   control, option keys */
+#if 0		/* handler 5 doesn't send separate codes for R modifiers */
 		if (adb_try_handler_change(id, 5))
 			printk("ADB keyboard at %d, handler set to 5\n", id);
-		else if (adb_try_handler_change(id, 3))
+		else
+#endif
+		if (adb_try_handler_change(id, 3))
 			printk("ADB keyboard at %d, handler set to 3\n", id);
 		else
 			printk("ADB keyboard at %d, handler 1\n", id);
@@ -769,10 +807,6 @@
 			printk("ADB mouse at %d, handler set to 4", id);
 			adb_mouse_kinds[id] = ADBMOUSE_EXTENDED;
 		}
-		else if (adb_try_handler_change(id, 2)) {
-			printk("ADB mouse at %d, handler set to 2", id);
-			adb_mouse_kinds[id] = ADBMOUSE_STANDARD_200;
-		}
 		else if (adb_try_handler_change(id, 0x2F)) {
 			printk("ADB mouse at %d, handler set to 0x2F", id);
 			adb_mouse_kinds[id] = ADBMOUSE_MICROSPEED;
@@ -789,6 +823,14 @@
 			printk("ADB mouse at %d, handler set to 0x5F", id);
 			adb_mouse_kinds[id] = ADBMOUSE_MICROSPEED;
 		}
+		else if (adb_try_handler_change(id, 3)) {
+			printk("ADB mouse at %d, handler set to 3", id);
+			adb_mouse_kinds[id] = ADBMOUSE_MS_A3;
+		}
+		else if (adb_try_handler_change(id, 2)) {
+			printk("ADB mouse at %d, handler set to 2", id);
+			adb_mouse_kinds[id] = ADBMOUSE_STANDARD_200;
+		}
 		else {
 			printk("ADB mouse at %d, handler 1", id);
 			adb_mouse_kinds[id] = ADBMOUSE_STANDARD_100;
@@ -797,6 +839,8 @@
 		if ((adb_mouse_kinds[id] == ADBMOUSE_TRACKBALLPRO)
 		    || (adb_mouse_kinds[id] == ADBMOUSE_MICROSPEED)) {
 			init_microspeed(id);
+		} else if (adb_mouse_kinds[id] == ADBMOUSE_MS_A3) {
+			init_ms_a3(id);	
 		}  else if (adb_mouse_kinds[id] ==  ADBMOUSE_EXTENDED) {
 			/*
 			 * Register 1 is usually used for device
@@ -808,7 +852,8 @@
 				    ADB_READREG(id, 1));
 
 			if ((req.reply_len) &&
-			    (req.reply[1] == 0x9a) && (req.reply[2] == 0x21))
+			    (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21)
+			    	|| (req.reply[2] == 0x20)))
 				init_trackball(id);
 			else if ((req.reply_len >= 4) &&
 			    (req.reply[1] == 0x74) && (req.reply[2] == 0x70) &&
@@ -818,6 +863,14 @@
 			    (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) &&
 			    (req.reply[3] == 0x4c) && (req.reply[4] == 0x31))
 				init_turbomouse(id);
+			else if ((req.reply_len == 9) &&
+			    (req.reply[1] == 0x4b) && (req.reply[2] == 0x4f) &&
+			    (req.reply[3] == 0x49) && (req.reply[4] == 0x54)){
+				if (adb_try_handler_change(id, 0x42)) {
+					printk("\nADB MacAlly 2-button mouse at %d, handler set to 0x42", id);
+					adb_mouse_kinds[id] = ADBMOUSE_MACALLY2;
+				}
+			}
 		}
 		printk("\n");
         }
@@ -880,7 +933,7 @@
 {
 	struct adb_request req;
 	
-	printk(" (trackball)");
+	printk(" (trackman/mouseman)");
 	
 	adb_mouse_kinds[id] = ADBMOUSE_TRACKBALL;
 
@@ -920,13 +973,10 @@
 	
 	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
 
-	adb_request(&req, NULL, ADBREQ_SYNC, 3,
-		ADB_WRITEREG(id,3), 0x20 | id, 4);
-
-	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3));
 
 	adb_request(&req, NULL, ADBREQ_SYNC, 9,
-	ADB_WRITEREG(id,2),
+	ADB_WRITEREG(3,2),
 	    0xe7,
 	    0x8c,
 	    0,
@@ -936,10 +986,10 @@
 	    0xff,
 	    0x94);
 
-	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3));
 
 	adb_request(&req, NULL, ADBREQ_SYNC, 9,
-	ADB_WRITEREG(id,2),
+	ADB_WRITEREG(3,2),
 	    0xa5,
 	    0x14,
 	    0,
@@ -989,4 +1039,18 @@
 
 	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
 }
+
+static void
+init_ms_a3(int id)
+{
+	struct adb_request req;
+
+	printk(" (Mouse Systems A3 Mouse, or compatible)");
+	adb_request(&req, NULL, ADBREQ_SYNC, 3,
+	ADB_WRITEREG(id, 0x2),
+	    0x00,
+	    0x07);
+ 
+ 	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+ }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.3.42/linux/drivers/macintosh/macserial.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/macintosh/macserial.c	Wed Feb  9 19:43:53 2000
@@ -8,7 +8,7 @@
  *
  * Receive DMA code by Takashi Oe <toe@unlserve.unl.edu>.
  *
- * $Id: macserial.c,v 1.24.2.3 1999/09/10 02:05:58 paulus Exp $
+ * $Id: macserial.c,v 1.24.2.4 1999/10/19 04:36:42 paulus Exp $
  */
 
 #include <linux/config.h>
@@ -130,6 +130,22 @@
 
 #define _INLINE_ inline
 
+#ifdef SERIAL_DEBUG_OPEN
+#define OPNDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#else
+#define OPNDBG(fmt, arg...)	do { } while (0)
+#endif
+#ifdef SERIAL_DEBUG_POWER
+#define PWRDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#else
+#define PWRDBG(fmt, arg...)	do { } while (0)
+#endif
+#ifdef SERIAL_DEBUG_BAUDS
+#define BAUDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#else
+#define BAUDBG(fmt, arg...)	do { } while (0)
+#endif
+
 static void probe_sccs(void);
 static void change_speed(struct mac_serial *info, struct termios *old);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
@@ -318,7 +334,7 @@
 	 * to it. - paulus)
 	 */
 	for (i = 200; i > 0; --i)
-		if (ld_le32(&dma->control) & RUN)
+		if (ld_le32(&dma->status) & RUN)
 			udelay(1);
 }
 
@@ -718,14 +734,10 @@
 {
 	int delay;
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("startup() (ttyS%d, irq %d)\n", info->line, info->irq);
-#endif
+	OPNDBG("startup() (ttyS%d, irq %d)\n", info->line, info->irq);
  
 	if (info->flags & ZILOG_INITIALIZED) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk(" -> already inited\n");
-#endif
+		OPNDBG(" -> already inited\n");
  		return 0;
 	}
 
@@ -735,17 +747,13 @@
 			return -ENOMEM;
 	}
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
-#endif
+	OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
 
 	delay = set_scc_power(info, 1);
 	
 	setup_scc(info);
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq);
-#endif
+	OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq);
 
 	info->flags |= ZILOG_INITIALIZED;
 	enable_irq(info->irq);
@@ -951,9 +959,7 @@
 {
 	unsigned long flags;
 	
-#ifdef SERIAL_DEBUG_OPEN
-	printk("setting up ttys%d SCC...\n", info->line);
-#endif
+	OPNDBG("setting up ttys%d SCC...\n", info->line);
 
 	save_flags(flags); cli(); /* Disable interrupts */	
 
@@ -1050,16 +1056,11 @@
  */
 static void shutdown(struct mac_serial * info)
 {
-#ifdef SERIAL_DEBUG_OPEN
-	printk("Shutting down serial port %d (irq %d)....\n", info->line,
+	OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line,
 	       info->irq);
-#endif
 	
 	if (!(info->flags & ZILOG_INITIALIZED)) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("(already shutdown)\n");
-#endif
-	
+		OPNDBG("(already shutdown)\n");
 		return;
 	}
 
@@ -1125,24 +1126,27 @@
 	   ones, at least whe not using the modem, this should be tested.
 	 */				
 	if (state) {
-#ifdef SERIAL_DEBUG_POWER
-		printk(KERN_INFO "ttyS%02d: powering up hardware\n", info->line);
-#endif
+		PWRDBG("ttyS%02d: powering up hardware\n", info->line);
 		if (feature_test(info->dev_node, FEATURE_Serial_enable) == 0) {
-			feature_clear(info->dev_node, FEATURE_Serial_reset);
-			mdelay(5);
 			feature_set(info->dev_node, FEATURE_Serial_enable);
+			mdelay(10);
+			feature_set(info->dev_node, FEATURE_Serial_reset);
+			mdelay(15);
+			feature_clear(info->dev_node, FEATURE_Serial_reset);
+			mdelay(10);
 		}
 		if (info->zs_chan_a == info->zs_channel)
 			feature_set(info->dev_node, FEATURE_Serial_IO_A);
 		else
 			feature_set(info->dev_node, FEATURE_Serial_IO_B);
-		delay = 1;
-		
+		delay = 10;
 		if (info->is_cobalt_modem){
-			feature_set(info->dev_node, FEATURE_Modem_Reset);
+			mdelay(300);
+			feature_set(info->dev_node, FEATURE_Modem_power);
 	   		mdelay(5);
-			feature_clear(info->dev_node, FEATURE_Modem_Reset);
+			feature_clear(info->dev_node, FEATURE_Modem_power);
+	   		mdelay(10);
+			feature_set(info->dev_node, FEATURE_Modem_power);
 			delay = 2500;	/* wait for 2.5s before using */
 		}
 #ifdef CONFIG_PMAC_PBOOK
@@ -1150,33 +1154,11 @@
 			pmu_enable_irled(1);
 #endif /* CONFIG_PMAC_PBOOK */
 	} else {
-#ifdef SERIAL_DEBUG_POWER
-		printk(KERN_INFO "ttyS%02d: shutting down hardware\n", info->line);
-#endif
-#ifdef CONFIG_KGDB
-		if (info->kgdb_channel) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "        (canceled by KGDB)\n");
-#endif
-			return 0;
-		}
-#endif
-#ifdef CONFIG_XMON
-		if (!info->is_cobalt_modem) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "        (canceled by XMON)\n");
-#endif
-			return 0;
-		}
-#endif
+		PWRDBG("ttyS%02d: shutting down hardware\n", info->line);
 		if (info->is_cobalt_modem) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down modem\n", info->line);
-#endif
-			feature_set(info->dev_node, FEATURE_Modem_Reset);
-			mdelay(15);
-			feature_clear(info->dev_node, FEATURE_Modem_Reset);
-			mdelay(25);
+			PWRDBG("ttyS%02d: shutting down modem\n", info->line);
+			feature_clear(info->dev_node, FEATURE_Modem_power);
+			mdelay(10);
 		}
 #ifdef CONFIG_PMAC_PBOOK
 		if (info->is_pwbk_ir)
@@ -1184,25 +1166,21 @@
 #endif /* CONFIG_PMAC_PBOOK */
 			
 		if (info->zs_chan_a == info->zs_channel) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down SCC channel A\n", info->line);
-#endif
+			PWRDBG("ttyS%02d: shutting down SCC channel A\n", info->line);
 			feature_clear(info->dev_node, FEATURE_Serial_IO_A);
 		} else {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down SCC channel B\n", info->line);
-#endif
+			PWRDBG("ttyS%02d: shutting down SCC channel B\n", info->line);
 			feature_clear(info->dev_node, FEATURE_Serial_IO_B);
 		}
 		/* XXX for now, shut down SCC core only on powerbooks */
 		if (is_powerbook
 		    && !(feature_test(info->dev_node, FEATURE_Serial_IO_A) ||
 			 feature_test(info->dev_node, FEATURE_Serial_IO_B))) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down SCC core\n", info->line);
-#endif
+			PWRDBG("ttyS%02d: shutting down SCC core\n", info->line);
 			feature_set(info->dev_node, FEATURE_Serial_reset);
-			mdelay(10);
+			mdelay(15);
+			feature_clear(info->dev_node, FEATURE_Serial_reset);
+			mdelay(25);
 			feature_clear(info->dev_node, FEATURE_Serial_enable);
 			mdelay(5);
 		}
@@ -1249,9 +1227,7 @@
 	info->zs_baud = baud;
 	info->clk_divisor = 16;
 
-#ifdef SERIAL_DEBUG_BAUDS
-	printk("set speed to %d bds, ", baud);
-#endif
+	BAUDBG("set speed to %d bds, ", baud);
 
 	switch (baud) {
 	case ZS_CLOCK/16:	/* 230400 */
@@ -1278,34 +1254,26 @@
 	case CS5:
 		info->curregs[3] |= Rx5;
 		info->curregs[5] |= Tx5;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("5 bits, ");
-#endif
+		BAUDBG("5 bits, ");
 		bits = 7;
 		break;
 	case CS6:
 		info->curregs[3] |= Rx6;
 		info->curregs[5] |= Tx6;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("6 bits, ");
-#endif
+		BAUDBG("6 bits, ");
 		bits = 8;
 		break;
 	case CS7:
 		info->curregs[3] |= Rx7;
 		info->curregs[5] |= Tx7;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("7 bits, ");
-#endif
+		BAUDBG("7 bits, ");
 		bits = 9;
 		break;
 	case CS8:
 	default: /* defaults to 8 bits */
 		info->curregs[3] |= Rx8;
 		info->curregs[5] |= Tx8;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("8 bits, ");
-#endif
+		BAUDBG("8 bits, ");
 		bits = 10;
 		break;
 	}
@@ -1316,21 +1284,15 @@
 	if (cflag & CSTOPB) {
 		info->curregs[4] |= SB2;
 		bits++;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("2 stop, ");
-#endif
+		BAUDBG("2 stop, ");
 	} else {
 		info->curregs[4] |= SB1;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("1 stop, ");
-#endif
+		BAUDBG("1 stop, ");
 	}
 	if (cflag & PARENB) {
 		bits++;
  		info->curregs[4] |= PAR_ENA;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("parity, ");
-#endif
+		BAUDBG("parity, ");
 	}
 	if (!(cflag & PARODD)) {
 		info->curregs[4] |= PAR_EVEN;
@@ -1360,9 +1322,8 @@
 	info->timeout = ((info->xmit_fifo_size*HZ*bits) / baud);
 	info->timeout += HZ/50+1;	/* Add .02 seconds of slop */
 
-#ifdef SERIAL_DEBUG_BAUDS
-	printk("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ, (int)info->baud_base);
-#endif
+	BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ,
+	       (int)info->baud_base);
 
 	/* Load up the new values */
 	load_zsregs(info->zs_channel, info->curregs);
@@ -1823,9 +1784,7 @@
 		return;
 	}
 	
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttys%d, count = %d\n", info->line, info->count);
-#endif
+	OPNDBG("rs_close ttys%d, count = %d\n", info->line, info->count);
 	if ((tty->count == 1) && (info->count != 1)) {
 		/*
 		 * Uh, oh.  tty->count is 1, which means that the tty
@@ -1861,9 +1820,7 @@
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
-#ifdef SERIAL_DEBUG_OPEN
-	printk("waiting end of Tx... (timeout:%d)\n", info->closing_wait);
-#endif
+	OPNDBG("waiting end of Tx... (timeout:%d)\n", info->closing_wait);
 	tty->closing = 1;
 	if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) {
 		restore_flags(flags);
@@ -1887,9 +1844,7 @@
 		 * Before we drop DTR, make sure the SCC transmitter
 		 * has completely drained.
 		 */
-#ifdef SERIAL_DEBUG_OPEN
-		printk("waiting end of Rx...\n");
-#endif
+		OPNDBG("waiting end of Rx...\n");
 		restore_flags(flags);
 		rs_wait_until_sent(tty, info->timeout);
 		save_flags(flags); cli();
@@ -2059,10 +2014,8 @@
 	 */
 	retval = 0;
 	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttys%d, count = %d\n",
+	OPNDBG("block_til_ready before block: ttys%d, count = %d\n",
 	       info->line, info->count);
-#endif
 	cli();
 	if (!tty_hung_up_p(filp)) 
 		info->count--;
@@ -2095,10 +2048,8 @@
 			retval = -ERESTARTSYS;
 			break;
 		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		OPNDBG("block_til_ready blocking: ttys%d, count = %d\n",
 		       info->line, info->count);
-#endif
 		schedule();
 	}
 	current->state = TASK_RUNNING;
@@ -2106,10 +2057,8 @@
 	if (!tty_hung_up_p(filp))
 		info->count++;
 	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	OPNDBG("block_til_ready after blocking: ttys%d, count = %d\n",
 	       info->line, info->count);
-#endif
 	if (retval)
 		return retval;
 	info->flags |= ZILOG_NORMAL_ACTIVE;
@@ -2144,10 +2093,8 @@
 #endif
 	if (serial_paranoia_check(info, tty->device, "rs_open"))
 		return -ENODEV;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+	OPNDBG("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
 	       info->count);
-#endif
 
 	info->count++;
 	tty->driver_data = info;
@@ -2188,10 +2135,8 @@
 
 	retval = block_til_ready(tty, filp, info);
 	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("rs_open returning after block_til_ready with %d\n",
+		OPNDBG("rs_open returning after block_til_ready with %d\n",
 			retval);
-#endif
 		return retval;
 	}
 
@@ -2213,9 +2158,7 @@
 	info->session = current->session;
 	info->pgrp = current->pgrp;
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open ttys%d successful...\n", info->line);
-#endif
+	OPNDBG("rs_open ttys%d successful...\n", info->line);
 	return 0;
 }
 
@@ -2237,6 +2180,10 @@
 	struct device_node *ch = zss->dev_node;
 	char *conn;
 	int len;
+	struct slot_names_prop {
+		int	count;
+		char	name[1];
+	} *slots;
 
 	zss->irq = ch->intrs[0].line;
 	zss->has_dma = 0;
@@ -2262,6 +2209,10 @@
 	   should do no harm anyway */
 	conn = get_property(ch, "AAPL,connector", &len);
 	zss->is_pwbk_ir = conn && (strcmp(conn, "infrared") == 0);
+	/* 1999 Powerbook G3 has slot-names property instead */
+	slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len);
+	if (slots && slots->count > 0 && strcmp(slots->name, "IrDA") == 0)
+		zss->is_pwbk_ir = 1;
 
 	if (zss->has_dma) {
 		zss->dma_priv = NULL;
@@ -2506,16 +2457,13 @@
 			printk(" (powerbook IR)");
 		printk("\n");
 
+#ifndef CONFIG_XMON
 #ifdef CONFIG_KGDB
-		if (info->kgdb_channel)
-			continue;
-#endif			
-#ifdef CONFIG_XMON
-		if (!info->is_cobalt_modem)
-			continue;
-#endif			
+		if (!info->kgdb_channel)
+#endif /* CONFIG_KGDB */
 		/* By default, disable the port */
 		set_scc_power(info, 0);
+#endif /* CONFIG_XMON */
  	}
 	tmp_buf = 0;
 
diff -u --recursive --new-file v2.3.42/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c
--- v2.3.42/linux/drivers/macintosh/mediabay.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/macintosh/mediabay.c	Wed Feb  9 19:43:53 2000
@@ -38,6 +38,14 @@
 #endif
 
 #undef MB_USE_INTERRUPTS
+#undef MB_DEBUG
+#define MB_IGNORE_SIGNALS
+
+#ifdef MB_DEBUG
+#define MBDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#else
+#define MBDBG(fmt, arg...)	do { } while (0)
+#endif
 
 struct media_bay_hw {
 	unsigned char	b0;
@@ -49,17 +57,16 @@
 struct media_bay_info {
 	volatile struct media_bay_hw*	addr;
 	int				content_id;
-	int				previous_id;
-	int				ready;
+	int				state;
 	int				last_value;
 	int				value_count;
-	int				reset_timer;
+	int				timer;
 	struct device_node*		dev_node;
 #ifdef CONFIG_BLK_DEV_IDE
 	unsigned long			cd_base;
 	int 				cd_index;
 	int				cd_irq;
-	int				cd_timer;
+	int				cd_retry;
 #endif
 };
 
@@ -73,31 +80,79 @@
 #ifdef CONFIG_BLK_DEV_IDE
 /* check the busy bit in the media-bay ide interface
    (assumes the media-bay contains an ide device) */
+//#define MB_IDE_READY(i)	((inb(media_bays[i].cd_base + 0x70) & 0xc0) == 0x40)
 #define MB_IDE_READY(i)	((inb(media_bays[i].cd_base + 0x70) & 0x80) == 0)
 #endif
 
+/* Note: All delays are not in milliseconds and converted to HZ relative
+ * values by the macro below
+ */
+#define MS_TO_HZ(ms)	((ms * HZ) / 1000)
+
 /*
  * Consider the media-bay ID value stable if it is the same for
- * this many consecutive samples (at intervals of 1/HZ seconds).
+ * this number of milliseconds
  */
-#define MB_STABLE_COUNT	4
+#define MB_STABLE_DELAY	40
+
+/* Wait after powering up the media bay this delay in ms
+ * timeout bumped for some powerbooks
+ */
+#define MB_POWER_DELAY	200
 
 /*
  * Hold the media-bay reset signal true for this many ticks
  * after a device is inserted before releasing it.
  */
-#define MB_RESET_COUNT	40
+#define MB_RESET_DELAY	40
+
+/*
+ * Wait this long after the reset signal is released and before doing
+ * further operations. After this delay, the IDE reset signal is released
+ * too for an IDE device
+ */
+#define MB_SETUP_DELAY	100
 
 /*
  * Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted
- * (or until the device is ready) before registering the IDE interface.
+ * (or until the device is ready) before waiting for busy bit to disappear
+ */
+#define MB_IDE_WAIT	1000
+
+/*
+ * Timeout waiting for busy bit of an IDE device to go down
+ */
+#define MB_IDE_TIMEOUT	5000
+
+/*
+ * Max retries of the full power up/down sequence for an IDE device
+ */
+#define MAX_CD_RETRIES	3
+
+/*
+ * States of a media bay
  */
-#define MB_IDE_WAIT	1500
+enum {
+	mb_empty = 0,		/* Idle */
+	mb_powering_up,		/* power bit set, waiting MB_POWER_DELAY */
+	mb_enabling_bay,	/* enable bits set, waiting MB_RESET_DELAY */
+	mb_resetting,		/* reset bit unset, waiting MB_SETUP_DELAY */
+	mb_ide_resetting,	/* IDE reset bit unser, waiting MB_IDE_WAIT */
+	mb_ide_waiting,		/* Waiting for BUSY bit to go away until MB_IDE_TIMEOUT */
+	mb_up,			/* Media bay full */
+	mb_powering_down	/* Powering down (avoid too fast down/up) */
+};
 
 static void poll_media_bay(int which);
 static void set_media_bay(int which, int id);
+static void set_mb_power(int which, int onoff);
+static void media_bay_step(int i);
 static int media_bay_task(void *);
 
+#ifdef MB_USE_INTERRUPTS
+static void media_bay_intr(int irq, void *devid, struct pt_regs *regs);
+#endif
+
 /*
  * It seems that the bit for the media-bay interrupt in the IRQ_LEVEL
  * register is always set when there is something in the media bay.
@@ -113,8 +168,7 @@
 	struct device_node *np;
 	int		n,i;
 	
-	for (i=0; i<MAX_BAYS; i++)
-	{
+	for (i=0; i<MAX_BAYS; i++) {
 		memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info));
 		media_bays[i].content_id	= -1;
 #ifdef CONFIG_BLK_DEV_IDE
@@ -124,40 +178,43 @@
 	
 	np = find_devices("media-bay");
 	n = 0;
-	while(np && (n<MAX_BAYS))
-	{
+	while(np && (n<MAX_BAYS)) {
 		if (np->n_addrs == 0)
 			continue;
 		media_bays[n].addr = (volatile struct media_bay_hw *)
 			ioremap(np->addrs[0].address, sizeof(struct media_bay_hw));
 
 #ifdef MB_USE_INTERRUPTS
-		if (np->n_intrs == 0)
-		{
+		if (np->n_intrs == 0) {
 			printk(KERN_ERR "media bay %d has no irq\n",n);
 			continue;
 		}
 		
-		if (request_irq(np_intrs[0].line, media_bay_intr, 0, "Media bay", NULL))
-		{
-			printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n", irq, n);
+		if (request_irq(np->intrs[0].line, media_bay_intr, 0, "Media bay", (void *)n)) {
+			printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n",
+				np->intrs[0].line, n);
 			continue;
 		}
 #endif	
 		media_bay_count++;
 	
-		set_media_bay(n, MB_CONTENTS(n));
-		if (media_bays[n].content_id != MB_NO) {
-			feature_clear(media_bays[n].dev_node, FEATURE_Mediabay_reset);
-			udelay(500);
-		}
-		media_bays[n].ready		= 1;
-		media_bays[n].previous_id	= media_bays[n].content_id;
-		media_bays[n].reset_timer	= 0;
 		media_bays[n].dev_node		= np;
-#ifdef CONFIG_BLK_DEV_IDE
-		media_bays[n].cd_timer		= 0;
-#endif
+
+		/* Force an immediate detect */
+		set_mb_power(n,0);
+		mdelay(MB_POWER_DELAY);
+		out_8(&media_bays[n].addr->contents, 0x70);
+		mdelay(MB_STABLE_DELAY);
+		media_bays[n].content_id = MB_NO;
+		media_bays[n].last_value = MB_CONTENTS(n);
+		media_bays[n].value_count = MS_TO_HZ(MB_STABLE_DELAY);
+		media_bays[n].state = mb_empty;
+		do {
+			mdelay(1000/HZ);
+			media_bay_step(n);
+		} while((media_bays[n].state != mb_empty) &&
+			(media_bays[n].state != mb_up));
+		
 		n++;
 		np=np->next;
 	}
@@ -174,17 +231,66 @@
 	}
 }
 
-#if 0
-static void
+#ifdef MB_USE_INTERRUPTS
+static void __pmac
 media_bay_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	int id = MB_CONTENTS();
-
-	if (id == MB_NO)
-		set_media_bay(id);
 }
 #endif
 
+static void __pmac
+set_mb_power(int which, int onoff)
+{
+	volatile struct media_bay_info*	mb = &media_bays[which];
+
+	if (onoff) {
+		feature_set(mb->dev_node, FEATURE_Mediabay_power);
+		udelay(10);
+		feature_set(mb->dev_node, FEATURE_Mediabay_reset);
+		udelay(10);
+		mb->state = mb_powering_up;
+		MBDBG("mediabay%d: powering up\n", which);
+	} else {
+		feature_clear(mb->dev_node, FEATURE_Mediabay_floppy_enable);
+		feature_clear(mb->dev_node, FEATURE_Mediabay_IDE_enable);
+		feature_clear(mb->dev_node, FEATURE_Mediabay_PCI_enable);
+		feature_clear(mb->dev_node, FEATURE_SWIM3_enable);
+		feature_clear(mb->dev_node, FEATURE_Mediabay_power);
+		mb->state = mb_powering_down;
+		MBDBG("mediabay%d: powering down\n", which);
+	}
+	mb->timer = MS_TO_HZ(MB_POWER_DELAY);
+}
+
+static void __pmac
+set_media_bay(int which, int id)
+{
+	volatile struct media_bay_info* bay;
+
+	bay = &media_bays[which];
+	
+	switch (id) {
+	case MB_CD:
+		feature_set(bay->dev_node, FEATURE_Mediabay_IDE_enable);
+		udelay(10);
+		feature_set(bay->dev_node, FEATURE_Mediabay_IDE_reset);
+		printk(KERN_INFO "media bay %d contains a CD-ROM drive\n", which);
+		break;
+	case MB_FD:
+	case MB_FD1:
+		feature_set(bay->dev_node, FEATURE_Mediabay_floppy_enable);
+		feature_set(bay->dev_node, FEATURE_SWIM3_enable);
+		printk(KERN_INFO "media bay %d contains a floppy disk drive\n", which);
+		break;
+	case MB_NO:
+		break;
+	default:
+		printk(KERN_INFO "media bay %d contains an unknown device (%d)\n",
+		       which, id);
+		break;
+	}
+}
+
 int __pmac
 check_media_bay(struct device_node *which_bay, int what)
 {
@@ -194,7 +300,7 @@
 	for (i=0; i<media_bay_count; i++)
 		if (which_bay == media_bays[i].dev_node)
 		{
-			if ((what == media_bays[i].content_id) && media_bays[i].ready)
+			if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up)
 				return 0;
 			media_bays[i].cd_index = -1;
 			return -EINVAL;
@@ -212,7 +318,7 @@
 	for (i=0; i<media_bay_count; i++)
 		if (base == media_bays[i].cd_base)
 		{
-			if ((what == media_bays[i].content_id) && media_bays[i].ready)
+			if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up)
 				return 0;
 			media_bays[i].cd_index = -1;
 			return -EINVAL;
@@ -232,17 +338,135 @@
 	for (i=0; i<media_bay_count; i++)
 		if (which_bay == media_bays[i].dev_node)
 		{
+			int timeout = 5000;
+			
  			media_bays[i].cd_base	= base;
 			media_bays[i].cd_irq	= irq;
-			media_bays[i].cd_index	= index;
+
+			if ((MB_CD != media_bays[i].content_id) || media_bays[i].state != mb_up)
+				return 0;
+				
 			printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i);			
-			return 0;
+			do {
+				if (MB_IDE_READY(i)) {
+					media_bays[i].cd_index	= index;
+					return 0;
+				}
+				mdelay(1);
+			} while(--timeout);
+			printk(KERN_DEBUG "Timeout waiting IDE in bay %d\n", i);			
+			return -ENODEV;
 		} 
 #endif
 	
 	return -ENODEV;
 }
 
+static void __pmac
+media_bay_step(int i)
+{
+	volatile struct media_bay_info* bay = &media_bays[i];
+
+	/* We don't poll when powering down */
+	if (bay->state != mb_powering_down)
+	    poll_media_bay(i);
+
+	/* If timer expired or polling IDE busy, run state machine */
+	if ((bay->state != mb_ide_waiting) && (bay->timer != 0) && ((--bay->timer) != 0))
+	    return;
+
+	switch(bay->state) {
+	case mb_powering_up:
+	    	set_media_bay(i, bay->last_value);
+	    	bay->timer = MS_TO_HZ(MB_RESET_DELAY);
+	    	bay->state = mb_enabling_bay;
+		MBDBG("mediabay%d: enabling (kind:%d)\n", i, bay->content_id);
+		break;
+	case mb_enabling_bay:
+	    	feature_clear(bay->dev_node, FEATURE_Mediabay_reset);
+	    	bay->timer = MS_TO_HZ(MB_SETUP_DELAY);
+	    	bay->state = mb_resetting;
+		MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id);
+	    	break;
+	    
+	case mb_resetting:
+		if (bay->content_id != MB_CD) {
+			MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id);
+			bay->state = mb_up;
+			break;
+	    	}
+#ifdef CONFIG_BLK_DEV_IDE
+		MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id);
+	    	feature_clear(bay->dev_node, FEATURE_Mediabay_IDE_reset);
+	    	bay->timer = MS_TO_HZ(MB_IDE_WAIT);
+	    	bay->state = mb_ide_resetting;
+#else
+		printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i);
+		set_mb_power(i, 0);
+#endif // #ifdef CONFIG_BLK_DEV_IDE
+	    	break;
+	    
+#ifdef CONFIG_BLK_DEV_IDE
+	case mb_ide_resetting:
+	    	bay->timer = MS_TO_HZ(MB_IDE_TIMEOUT);
+	    	bay->state = mb_ide_waiting;
+		MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id);
+	    	break;
+	    
+	case mb_ide_waiting:
+	    	if (bay->cd_base == 0) {
+			bay->timer = 0;
+			bay->state = mb_up;
+			MBDBG("mediabay%d: up before IDE init\n", i);
+			break;
+	    	} else if (MB_IDE_READY(i)) {
+			bay->timer = 0;
+			bay->state = mb_up;
+			if (bay->cd_index < 0)
+				bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq);
+			if (bay->cd_index == -1) {
+				/* We eventually do a retry */
+				bay->cd_retry++;
+				printk("IDE register error\n");
+				set_mb_power(i, 0);
+			} else {
+				printk(KERN_DEBUG "media-bay %d is ide %d\n", i, bay->cd_index);
+				MBDBG("mediabay %d IDE ready\n", i);
+			}
+			break;
+	    	}
+	    	if (bay->timer == 0) {
+			printk("\nIDE Timeout in bay %d !\n", i);
+			MBDBG("mediabay%d: nIDE Timeout !\n", i);
+			set_mb_power(i, 0);
+	    	}
+		break;
+#endif // #ifdef CONFIG_BLK_DEV_IDE
+
+	case mb_powering_down:
+	    	bay->state = mb_empty;
+#ifdef CONFIG_BLK_DEV_IDE
+    	        if (bay->cd_index >= 0) {
+			printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i,
+			       bay->cd_index);
+			ide_unregister(bay->cd_index);
+			bay->cd_index = -1;
+		}
+	    	if (bay->cd_retry) {
+			if (bay->cd_retry > MAX_CD_RETRIES) {
+				/* Should add an error sound (sort of beep in dmasound) */
+				printk("\nmedia-bay %d, IDE device badly inserted or unrecognised\n", i);
+			} else {
+				/* Force a new power down/up sequence */
+				bay->content_id = MB_NO;
+			}
+	    	}
+#endif	    
+		MBDBG("mediabay%d: end of power down\n", i);
+	    	break;
+	}
+}
+
 /*
  * This procedure runs as a kernel thread to poll the media bay
  * once each tick and register and unregister the IDE interface
@@ -252,123 +476,57 @@
 int __pmac
 media_bay_task(void *x)
 {
-	volatile struct media_bay_info* bay;
 	int	i = 0;
 	
 	strcpy(current->comm, "media-bay");
-	for (;;)
-	{
-		bay = &media_bays[i];
-		poll_media_bay(i);
-		if (bay->content_id != bay->previous_id) {
-			bay->reset_timer = (bay->content_id != MB_NO) ?
-				MB_RESET_COUNT: 0;
-			bay->ready = 0;
-#ifdef CONFIG_BLK_DEV_IDE
-			bay->cd_timer = 0;
-			if (bay->content_id != MB_CD && bay->cd_index >= 0) {
-				printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, bay->cd_index);
-				ide_unregister(bay->cd_index);
-				bay->cd_index = -1;
-			}
-#endif
-		} else if (bay->reset_timer) {
-			if (--bay->reset_timer == 0) {
- 				feature_clear(bay->dev_node, FEATURE_Mediabay_reset);
-				bay->ready = 1;
-#ifdef CONFIG_BLK_DEV_IDE
-				bay->cd_timer = 0;
-				if (bay->content_id == MB_CD && bay->cd_base != 0)
-					bay->cd_timer = MB_IDE_WAIT;
-#endif
-			}
-#ifdef CONFIG_BLK_DEV_IDE
-		} else if (bay->cd_timer && (--bay->cd_timer == 0 || MB_IDE_READY(i))
-			   && bay->cd_index < 0) {
-			bay->cd_timer = 0;
-			printk(KERN_DEBUG "Registering IDE, base:0x%08lx, irq:%d\n", bay->cd_base, bay->cd_irq);
-			printk("\n");
-			bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq);
-			if (bay->cd_index == -1)
-				printk("\nCD-ROM badly inserted. Remove it and try again !\n");
-			else
-				printk(KERN_DEBUG "media-bay %d is ide %d\n", i, bay->cd_index);
+#ifdef MB_IGNORE_SIGNALS
+	sigfillset(&current->blocked);
 #endif
-		}
 
-		bay->previous_id = bay->content_id;
+	for (;;) {
+	    media_bay_step(i);
+
+	    if (++i >= media_bay_count) {
+		i = 0;
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(1);
 		if (signal_pending(current))
 			return 0;
-		i = (i+1)%media_bay_count;
+	    }
 	}
 }
 
 void __pmac
 poll_media_bay(int which)
 {
+	volatile struct media_bay_info* bay = &media_bays[which];
 	int id = MB_CONTENTS(which);
 
-	if (id == media_bays[which].last_value) {
-	    if (id != media_bays[which].content_id
-	        && ++media_bays[which].value_count >= MB_STABLE_COUNT) {
+	if (id == bay->last_value) {
+	    if (id != bay->content_id
+	        && ++bay->value_count >= MS_TO_HZ(MB_STABLE_DELAY)) {
 	        /* If the device type changes without going thru "MB_NO", we force
 	           a pass by "MB_NO" to make sure things are properly reset */
-	        if ((id != MB_NO) && (media_bays[which].content_id != MB_NO)) {
-		    set_media_bay(which, MB_NO);
-		    udelay(500);
+	        if ((id != MB_NO) && (bay->content_id != MB_NO)) {
+	            id = MB_NO;
+		    MBDBG("mediabay%d: forcing MB_NO\n", which);
+		}
+		MBDBG("mediabay%d: switching to %d\n", which, id);
+		set_mb_power(which, id != MB_NO);
+		bay->content_id = id;
+		if (id == MB_NO) {
+#ifdef CONFIG_BLK_DEV_IDE
+		    bay->cd_retry = 0;
+#endif
+		    printk(KERN_INFO "media bay %d is empty\n", which);
 		}
- 		set_media_bay(which, id);
  	    }
 	} else {
-		media_bays[which].last_value = id;
-		media_bays[which].value_count = 0;
+		bay->last_value = id;
+		bay->value_count = 0;
 	}
 }
 
-static void __pmac
-set_media_bay(int which, int id)
-{
-	volatile struct media_bay_info* bay;
-
-	bay = &media_bays[which];
-	
-	bay->content_id = id;
-	bay->last_value = id;
-	
-	switch (id) {
-	case MB_CD:
-		feature_set(bay->dev_node, FEATURE_Mediabay_enable);
-		feature_set(bay->dev_node, FEATURE_Mediabay_IDE_enable);
-		udelay(500);
-		feature_set(bay->dev_node, FEATURE_CD_power);
-		printk(KERN_INFO "media bay %d contains a CD-ROM drive\n", which);
-		break;
-	case MB_FD:
-		feature_set(bay->dev_node, FEATURE_Mediabay_enable);
-		feature_set(bay->dev_node, FEATURE_Mediabay_floppy_enable);
-		feature_set(bay->dev_node, FEATURE_SWIM3_enable);
-		printk(KERN_INFO "media bay %d contains a floppy disk drive\n", which);
-		break;
-	case MB_NO:
-		feature_clear(bay->dev_node, FEATURE_CD_power);
-		feature_clear(bay->dev_node, FEATURE_Mediabay_enable);
-		feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
-		feature_clear(bay->dev_node, FEATURE_Mediabay_IDE_enable);
-		feature_clear(bay->dev_node, FEATURE_SWIM3_enable);
-		feature_set(bay->dev_node, FEATURE_Mediabay_reset);
-		printk(KERN_INFO "media bay %d is empty\n", which);
-		break;
-	default:
-		feature_set(bay->dev_node, FEATURE_Mediabay_enable);
-		printk(KERN_INFO "media bay %d contains an unknown device (%d)\n",
-		       which, id);
-		break;
-	}
-	
-	udelay(500);
-}
 
 #ifdef CONFIG_PMAC_PBOOK
 /*
@@ -388,42 +546,34 @@
 	case PBOOK_SLEEP_NOW:
 		for (i=0; i<media_bay_count; i++) {
 			bay = &media_bays[i];
-			feature_clear(bay->dev_node, FEATURE_Mediabay_enable);
-			feature_clear(bay->dev_node, FEATURE_Mediabay_IDE_enable);
-			feature_clear(bay->dev_node, FEATURE_SWIM3_enable);
-			feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
-			feature_set(bay->dev_node, FEATURE_Mediabay_reset);
-			feature_clear(bay->dev_node, FEATURE_CD_power);
-			out_8(&media_bays[i].addr->contents, 0x70);
+			set_mb_power(i, 0);
+			mdelay(10);
+			out_8(&bay->addr->contents, 0x70);
 		}
 		break;
 	case PBOOK_WAKE:
 		for (i=0; i<media_bay_count; i++) {
 			bay = &media_bays[i];
-			feature_set(bay->dev_node, FEATURE_Mediabay_enable);
-			/* I suppose this is enough delay to stabilize MB_CONTENT ... */
-			mdelay(10);
-			/* We re-enable the bay using it's previous content only if
-			   it did not change */
-			if (MB_CONTENTS(i) == bay->content_id) {
-				set_media_bay(i, bay->content_id);
-				if (bay->content_id != MB_NO) {
-					mdelay(400);
-					/* Clear the bay reset */
-					feature_clear(bay->dev_node, FEATURE_Mediabay_reset);
-					/* This small delay makes sure the device has time
-					   to assert the BUSY bit (used by IDE sleep) */
-					udelay(100);
-					/* We reset the state machine timers in case we were in the
-					   middle of a wait loop */
-					if (bay->reset_timer)
-						bay->reset_timer = MB_RESET_COUNT;
-#ifdef CONFIG_BLK_DEV_IDE
-					if (bay->cd_timer)
-						bay->cd_timer = MB_IDE_WAIT;
-#endif
-				}
-			}
+			/* We re-enable the bay using it's previous content
+			   only if it did not change. Note those bozo timings, they seem
+			   to help the 3400 get it right
+			 */
+			mdelay(MB_STABLE_DELAY);
+			out_8(&bay->addr->contents, 0x70);
+			mdelay(MB_STABLE_DELAY);
+			if (MB_CONTENTS(i) != bay->content_id)
+				continue;
+			set_mb_power(i, 1);
+			mdelay(MB_POWER_DELAY);
+			media_bays[i].last_value = bay->content_id;
+			media_bays[i].value_count = MS_TO_HZ(MB_STABLE_DELAY);
+			media_bays[i].timer = 0;
+			media_bays[i].cd_retry = 0;
+			do {
+				mdelay(1000/HZ);
+				media_bay_step(i);
+			} while((media_bays[i].state != mb_empty) &&
+				(media_bays[i].state != mb_up));
 		}
 		break;
 	}
diff -u --recursive --new-file v2.3.42/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c
--- v2.3.42/linux/drivers/macintosh/nvram.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/macintosh/nvram.c	Wed Feb  9 11:42:35 2000
@@ -83,17 +83,11 @@
 }
 
 struct file_operations nvram_fops = {
-	nvram_llseek,
-	read_nvram,
-	write_nvram,
-	NULL,		/* nvram_readdir */
-	NULL,		/* nvram_select */
-	NULL,		/* nvram_ioctl */
-	NULL,		/* nvram_mmap */
-	nvram_open,
-	NULL,		/* flush */
-	nvram_release,
-	NULL		/* fsync */
+	llseek:		nvram_llseek,
+	read:		read_nvram,
+	write:		write_nvram,
+	open:		nvram_open,
+	release:	nvram_release,
 };
 
 static struct miscdevice nvram_dev = {
diff -u --recursive --new-file v2.3.42/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.3.42/linux/drivers/macintosh/via-pmu.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/macintosh/via-pmu.c	Wed Feb  9 19:43:53 2000
@@ -9,6 +9,12 @@
  * and the RTC (real time clock) chip.
  *
  * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
+ * 
+ * todo: - Check this driver for smp safety (new Core99 motherboards).
+ *       - Cleanup synchro between VIA interrupt and GPIO-based PMU
+ *         interrupt.
+ *
+ *
  */
 #include <stdarg.h>
 #include <linux/config.h>
@@ -91,13 +97,16 @@
 static unsigned char *reply_ptr;
 static int data_index;
 static int data_len;
-static int adb_int_pending;
+static volatile int adb_int_pending;
 static int pmu_adb_flags;
 static int adb_dev_map = 0;
 static struct adb_request bright_req_1, bright_req_2, bright_req_3;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
 static int pmu_fully_inited = 0;
+static int pmu_has_adb, pmu_has_backlight;
+static unsigned char *gpio_reg = NULL;
+static int gpio_irq;
 
 int asleep;
 struct notifier_block *sleep_notifier_list;
@@ -118,6 +127,7 @@
 static void pmu_handle_data(unsigned char *data, int len,
 			    struct pt_regs *regs);
 static void set_volume(int level);
+static void gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
 #ifdef CONFIG_PMAC_PBOOK
 static void pmu_pass_intr(unsigned char *data, int len);
 #endif
@@ -191,6 +201,7 @@
 	"PowerBook 2400/3400/3500(G3)",
 	"PowerBook G3 Series",
 	"1999 PowerBook G3",
+	"Core99 (iBook/iMac/G4)"
 };
 
 int __openfirmware
@@ -203,9 +214,6 @@
 		return 0;
 	if (vias->next != 0)
 		printk(KERN_WARNING "Warning: only using 1st via-pmu\n");
-	
-	feature_set(vias, FEATURE_VIA_enable);
-
 #if 0
 	{ int i;
 
@@ -218,13 +226,16 @@
 	printk("\n"); }
 #endif
 
-	if (vias->n_addrs != 1 || vias->n_intrs != 1) {
+	if (vias->n_addrs < 1 || vias->n_intrs < 1) {
 		printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n",
 		       vias->n_addrs, vias->n_intrs);
 		if (vias->n_addrs < 1 || vias->n_intrs < 1)
 			return 0;
 	}
 
+	pmu_has_adb = 1;
+	pmu_has_backlight = 1;
+
 	if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
 	    || device_is_compatible(vias->parent, "ohare")))
 		pmu_kind = PMU_OHARE_BASED;
@@ -232,12 +243,17 @@
 		pmu_kind = PMU_PADDINGTON_BASED;
 	else if (device_is_compatible(vias->parent, "heathrow"))
 		pmu_kind = PMU_HEATHROW_BASED;
-	else
+	else if (device_is_compatible(vias->parent, "Keylargo")) {
+		pmu_kind = PMU_KEYLARGO_BASED;
+		pmu_has_adb = (find_type_devices("adb") != NULL);
+		pmu_has_backlight = (find_type_devices("backlight") != NULL);
+	} else
 		pmu_kind = PMU_UNKNOWN;
 
 	via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000);
 
 	out_8(&via[IER], IER_CLR | 0x7f);	/* disable all intrs */
+	out_8(&via[IFR], 0x7f);			/* clear IFR */
 
 	pmu_state = idle;
 
@@ -289,6 +305,23 @@
 		return;
 	}
 
+	if (pmu_kind == PMU_KEYLARGO_BASED) {
+		struct device_node *gpio, *gpiop;
+
+		gpiop = find_devices("gpio");
+		if (gpiop && gpiop->n_addrs) {
+			gpio_reg = ioremap(gpiop->addrs->address, 0x10);
+			gpio = find_devices("extint-gpio1");
+			if (gpio && gpio->parent == gpiop && gpio->n_intrs) {
+				gpio_irq = gpio->intrs[0].line;
+				if (request_irq(gpio_irq, gpio1_interrupt, 0,
+			   			"GPIO1/ADB", (void *)0))
+				    printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n",
+						gpio->intrs[0].line);
+			}
+		}
+	}
+
 	/* Enable interrupts */
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 
@@ -395,6 +428,8 @@
 		}
 		break;
 	case ADB_PACKET:
+	    	if (!pmu_has_adb)
+    			return -ENXIO;
 		for (i = req->nbytes - 1; i > 1; --i)
 			req->data[i+2] = req->data[i];
 		req->data[3] = req->nbytes - 2;
@@ -425,7 +460,7 @@
 {
 	struct adb_request req;
 
-	if ((vias == NULL) || (!pmu_fully_inited))
+	if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)
 		return -ENXIO;
 
 	if (devs) {
@@ -447,10 +482,9 @@
 pmu_adb_reset_bus(void)
 {
 	struct adb_request req;
-	long timeout;
 	int save_autopoll = adb_dev_map;
 
-	if ((vias == NULL) || (!pmu_fully_inited))
+	if ((vias == NULL) || (!pmu_fully_inited) || !pmu_has_adb)
 		return -ENXIO;
 
 	/* anyone got a better idea?? */
@@ -460,27 +494,17 @@
 	req.done = NULL;
 	req.data[0] = PMU_ADB_CMD;
 	req.data[1] = 0;
-	req.data[2] = 3; /* ADB_BUSRESET ??? */
+	req.data[2] = ADB_BUSRESET; /* 3 ??? */
 	req.data[3] = 0;
 	req.data[4] = 0;
 	req.reply_len = 0;
 	req.reply_expected = 1;
-	if (pmu_queue_request(&req) != 0)
-	{
+	if (pmu_queue_request(&req) != 0) {
 		printk(KERN_ERR "pmu_adb_reset_bus: pmu_queue_request failed\n");
 		return -EIO;
 	}
 	while (!req.complete)
 		pmu_poll();
-	timeout = 100000;
-	while (!req.complete) {
-		if (--timeout < 0) {
-			printk(KERN_ERR "pmu_adb_reset_bus (reset): no response from PMU\n");
-			return -EIO;
-		}
-		udelay(10);
-		pmu_poll();
-	}
 
 	if (save_autopoll != 0)
 		pmu_adb_autopoll(save_autopoll);
@@ -558,6 +582,8 @@
 	return 0;
 }
 
+/* New PMU seems to be very sensitive to those timings, so we make sure
+ * PCI is flushed immediately */
 static void __openfirmware
 send_byte(int x)
 {
@@ -566,6 +592,7 @@
 	out_8(&v[ACR], in_8(&v[ACR]) | SR_OUT | SR_EXT);
 	out_8(&v[SR], x);
 	out_8(&v[B], in_8(&v[B]) & ~TREQ);		/* assert TREQ */
+	(void)in_8(&v[B]);
 }
 
 static void __openfirmware
@@ -575,10 +602,11 @@
 
 	out_8(&v[ACR], (in_8(&v[ACR]) & ~SR_OUT) | SR_EXT);
 	in_8(&v[SR]);		/* resets SR */
-	out_8(&v[B], in_8(&v[B]) & ~0x10);
+	out_8(&v[B], in_8(&v[B]) & ~TREQ);
+	(void)in_8(&v[B]);
 }
 
-static int disable_poll;
+static volatile int disable_poll;
 
 static void __openfirmware
 pmu_start()
@@ -616,7 +644,8 @@
 		return;
 	save_flags(flags);
 	cli();
-	if (via[IFR] & (SR_INT | CB1_INT))
+	if ((via[IFR] & (SR_INT | CB1_INT)) ||
+		(gpio_reg && (in_8(gpio_reg + 0x9) & 0x02) == 0))
 		via_pmu_interrupt(0, 0, 0);
 	restore_flags(flags);
 }
@@ -626,7 +655,12 @@
 {
 	int intr;
 	int nloop = 0;
+	unsigned long flags;
 
+	/* Currently, we use brute-force cli() for syncing with GPIO
+	 * interrupt. I'll make this smarter later, along with some
+	 * spinlocks for SMP */
+	save_flags(flags);cli();
 	++disable_poll;
 	while ((intr = in_8(&via[IFR])) != 0) {
 		if (++nloop > 1000) {
@@ -645,6 +679,9 @@
 			out_8(&via[IFR], intr);
 		}
 	}
+	if (gpio_reg && (in_8(gpio_reg + 0x9) & 0x02) == 0)
+		adb_int_pending = 1;
+
 	if (pmu_state == idle) {
 		if (adb_int_pending) {
 			pmu_state = intack;
@@ -655,6 +692,13 @@
 		}
 	}
 	--disable_poll;
+	restore_flags(flags);
+}
+
+static void __openfirmware
+gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
+{
+	via_pmu_interrupt(0, 0, 0);
 }
 
 static void __openfirmware
@@ -668,9 +712,17 @@
 		out_8(&via[IFR], SR_INT);
 		return;
 	}
-	if (via[B] & TACK)
+	/* This one seems to appear with PMU99. According to OF methods,
+	 * the protocol didn't change...
+	 */
+	if (via[B] & TACK) {
+		while ((in_8(&via[B]) & TACK) != 0)
+			;
+#if 0
 		printk(KERN_ERR "PMU: sr_intr but ack still high! (%x)\n",
 		       via[B]);
+#endif
+	}
 
 	/* reset TREQ and wait for TACK to go high */
 	out_8(&via[B], in_8(&via[B]) | TREQ);
@@ -832,7 +884,7 @@
 {
 	struct adb_request req;
 
-	if (vias == NULL)
+	if ((vias == NULL) || !pmu_has_backlight)
 		return;
 		
 	/* first call: get current backlight value */
@@ -853,6 +905,7 @@
 			printk(KERN_DEBUG "pmu: nvram returned bright: %d\n", backlight_level);
 			break;
 		case PMU_PADDINGTON_BASED:
+		case PMU_KEYLARGO_BASED:
 			/* the G3 PB 1999 has a backlight node
 			   and chrp-structured nvram */
 			/* XXX should read macos's "blkt" property in nvram
@@ -883,7 +936,7 @@
 {
 	int bright;
 
-	if (vias == NULL)
+	if ((vias == NULL) || !pmu_has_backlight)
 		return ;
 
 	backlight_level = level;
@@ -963,6 +1016,12 @@
 		;
 }
 
+int
+pmu_present(void)
+{
+	return via != 0;
+}
+
 #ifdef CONFIG_PMAC_PBOOK
 
 static LIST_HEAD(sleep_notifiers);
@@ -995,7 +1054,7 @@
 
 /* Sleep is broadcast last-to-first */
 static int
-broadcast_sleep(int when, int can_cancel)
+broadcast_sleep(int when, int fallback)
 {
 	int ret = PBOOK_SLEEP_OK;
 	struct list_head *list;
@@ -1005,8 +1064,13 @@
 	     list = list->prev) {
 		current = list_entry(list, struct pmu_sleep_notifier, list);
 		ret = current->notifier_call(current, when);
-		if (can_cancel && (ret != PBOOK_SLEEP_OK))
+		if (ret != PBOOK_SLEEP_OK) {
+			for (; list != &sleep_notifiers; list = list->next) {
+				current = list_entry(list, struct pmu_sleep_notifier, list);
+				current->notifier_call(current, fallback);
+			}
 			return ret;
+		}
 	}
 	return ret;
 }
@@ -1101,6 +1165,24 @@
 	}
 }
 
+#if 0
+/* N.B. This doesn't work on the 3400 */
+void pmu_blink(int n)
+{
+	struct adb_request req;
+
+	for (; n > 0; --n) {
+		pmu_request(&req, NULL, 4, 0xee, 4, 0, 1);
+		while (!req.complete) pmu_poll();
+		udelay(50000);
+		pmu_request(&req, NULL, 4, 0xee, 4, 0, 0);
+		while (!req.complete) pmu_poll();
+		udelay(50000);
+	}
+	udelay(50000);
+}
+#endif
+
 /*
  * Put the powerbook to sleep.
  */
@@ -1127,19 +1209,27 @@
 		macio_base = (unsigned long)
 			ioremap(macio->addrs[0].address, 0x40);
 
+	/* Notify device drivers */
+	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
+	if (ret != PBOOK_SLEEP_OK) {
+		printk("pmu: sleep rejected\n");
+		return -EBUSY;
+	}
+
 	/* Sync the disks. */
 	/* XXX It would be nice to have some way to ensure that
-	 * nobody is dirtying any new buffers while we wait. */
+	 * nobody is dirtying any new buffers while we wait.
+	 * BenH: Moved to _after_ sleep request and changed video
+	 * drivers to vmalloc() during sleep request. This way, all
+	 * vmalloc's are done before actual sleep of block drivers */
 	fsync_dev(0);
 
-	/* Notify device drivers */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, 1);
+	/* Sleep can fail now. May not be very robust but useful for debugging */
+	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
 	if (ret != PBOOK_SLEEP_OK) {
-		broadcast_sleep(PBOOK_SLEEP_REJECT, 0);
-		printk("pmu: sleep rejected\n");
+		printk("pmu: sleep failed\n");
 		return -EBUSY;
 	}
-	broadcast_sleep(PBOOK_SLEEP_NOW, 0);
 
 	/* Give the disks a little time to actually finish writing */
 	for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
@@ -1191,6 +1281,10 @@
 	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
 	grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
 
+	/* Make sure the PMU is idle */
+	while (pmu_state != idle)
+		pmu_poll();
+
 	sti();
 #if 0
 	/* According to someone from Apple, this should not be needed,
@@ -1202,8 +1296,8 @@
 
 	/* Restore L2 cache */
 	if (save_l2cr)
-		_set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */
-	
+ 		_set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */
+
 	/* reenable interrupts */
 	sleep_restore_intrs();
 
@@ -1223,19 +1317,27 @@
 	unsigned long p, wait;
 	struct adb_request sleep_req;
 
+	/* Notify device drivers */
+	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
+	if (ret != PBOOK_SLEEP_OK) {
+		printk("pmu: sleep rejected\n");
+		return -EBUSY;
+	}
+
 	/* Sync the disks. */
 	/* XXX It would be nice to have some way to ensure that
-	 * nobody is dirtying any new buffers while we wait. */
+	 * nobody is dirtying any new buffers while we wait.
+	 * BenH: Moved to _after_ sleep request and changed video
+	 * drivers to vmalloc() during sleep request. This way, all
+	 * vmalloc's are done before actual sleep of block drivers */
 	fsync_dev(0);
 
-	/* Notify device drivers */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, 1);
+	/* Sleep can fail now. May not be very robust but useful for debugging */
+	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
 	if (ret != PBOOK_SLEEP_OK) {
-		broadcast_sleep(PBOOK_SLEEP_REJECT, 0);
-		printk("pmu: sleep rejected\n");
+		printk("pmu: sleep failed\n");
 		return -EBUSY;
 	}
-	broadcast_sleep(PBOOK_SLEEP_NOW, 0);
 
 	/* Give the disks a little time to actually finish writing */
 	for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
@@ -1462,33 +1564,35 @@
 			error = powerbook_sleep_G3();
 			break;
 		default:
-			error = ENOSYS;
+			error = -ENOSYS;
 		}
 		return error;
 	case PMU_IOC_GET_BACKLIGHT:
+		if (!pmu_has_backlight)
+			return -ENOSYS;
 		return put_user(backlight_level, (__u32 *)arg);
 	case PMU_IOC_SET_BACKLIGHT:
+		if (!pmu_has_backlight)
+			return -ENOSYS;
 		error = get_user(value, (__u32 *)arg);
 		if (!error)
 			pmu_set_brightness(value);
 		return error;
 	case PMU_IOC_GET_MODEL:
 	    	return put_user(pmu_kind, (__u32 *)arg);
+	case PMU_IOC_HAS_ADB:
+		return put_user(pmu_has_adb, (__u32 *)arg);
 	}
 	return -EINVAL;
 }
 
 static struct file_operations pmu_device_fops = {
-	NULL,		/* no seek */
-	pmu_read,
-	pmu_write,
-	NULL,		/* no readdir */
-	pmu_fpoll,
-	pmu_ioctl,
-	NULL,		/* no mmap */
-	pmu_open,
-	NULL,		/* flush */
-	pmu_release,
+	read:		pmu_read,
+	write:		pmu_write,
+	poll:		pmu_fpoll,
+	ioctl:		pmu_ioctl,
+	open:		pmu_open,
+	release:	pmu_release,
 };
 
 static struct miscdevice pmu_device = {
@@ -1502,3 +1606,70 @@
 }
 #endif /* CONFIG_PMAC_PBOOK */
 
+#if 0
+static inline void polled_handshake(volatile unsigned char *via)
+{
+	via[B] &= ~TREQ; eieio();
+	while ((via[B] & TACK) != 0)
+		;
+	via[B] |= TREQ; eieio();
+	while ((via[B] & TACK) == 0)
+		;
+}
+
+static inline void polled_send_byte(volatile unsigned char *via, int x)
+{
+	via[ACR] |= SR_OUT | SR_EXT; eieio();
+	via[SR] = x; eieio();
+	polled_handshake(via);
+}
+
+static inline int polled_recv_byte(volatile unsigned char *via)
+{
+	int x;
+
+	via[ACR] = (via[ACR] & ~SR_OUT) | SR_EXT; eieio();
+	x = via[SR]; eieio();
+	polled_handshake(via);
+	x = via[SR]; eieio();
+	return x;
+}
+
+int
+pmu_polled_request(struct adb_request *req)
+{
+	unsigned long flags;
+	int i, l, c;
+	volatile unsigned char *v = via;
+
+	req->complete = 1;
+	c = req->data[0];
+	l = pmu_data_len[c][0];
+	if (l >= 0 && req->nbytes != l + 1)
+		return -EINVAL;
+
+	save_flags(flags); cli();
+	while (pmu_state != idle)
+		pmu_poll();
+
+	polled_send_byte(v, c);
+	if (l < 0) {
+		l = req->nbytes - 1;
+		polled_send_byte(v, l);
+	}
+	for (i = 1; i <= l; ++i)
+		polled_send_byte(v, req->data[i]);
+
+	l = pmu_data_len[c][1];
+	if (l < 0)
+		l = polled_recv_byte(v);
+	for (i = 0; i < l; ++i)
+		req->reply[i + req->reply_len] = polled_recv_byte(v);
+
+	if (req->done)
+		(*req->done)(req);
+
+	restore_flags(flags);
+	return 0;
+}
+#endif /* 0 */
diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v2.3.42/linux/drivers/net/3c501.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/net/3c501.c	Thu Feb 10 12:34:24 2000
@@ -29,54 +29,64 @@
     with a TX-TX optimisation to see if we can touch 180-200K/second as seems
     theoretically maximum.
     		19950402 Alan Cox <Alan.Cox@linux.org>
+    		
+    Cleaned up for 2.3.x because we broke SMP now. 
+    		20000208 Alan Cox <alan@redhat.com>
+    		
+*/
 
-    Some notes on this thing if you have to hack it.  [Alan]
-
-    1]	Some documentation is available from 3Com. Due to the boards age
-    	standard responses when you ask for this will range from 'be serious'
-    	to 'give it to a museum'. The documentation is incomplete and mostly
-    	of historical interest anyway.
-
-    2]  The basic system is a single buffer which can be used to receive or
-    	transmit a packet. A third command mode exists when you are setting
-    	things up.
-
-    3]	If it's transmitting it's not receiving and vice versa. In fact the
-    	time to get the board back into useful state after an operation is
-    	quite large.
-
-    4]	The driver works by keeping the board in receive mode waiting for a
-    	packet to arrive. When one arrives it is copied out of the buffer
-    	and delivered to the kernel. The card is reloaded and off we go.
-
-    5]	When transmitting dev->tbusy is set and the card is reset (from
-    	receive mode) [possibly losing a packet just received] to command
-    	mode. A packet is loaded and transmit mode triggered. The interrupt
-    	handler runs different code for transmit interrupts and can handle
-    	returning to receive mode or retransmissions (yes you have to help
-    	out with those too).
-
-    Problems:
-    	There are a wide variety of undocumented error returns from the card
-    and you basically have to kick the board and pray if they turn up. Most
-    only occur under extreme load or if you do something the board doesn't
-    like (eg touching a register at the wrong time).
-
-    	The driver is less efficient than it could be. It switches through
-    receive mode even if more transmits are queued. If this worries you buy
-    a real Ethernet card.
-
-    	The combination of slow receive restart and no real multicast
-    filter makes the board unusable with a kernel compiled for IP
-    multicasting in a real multicast environment. That's down to the board,
-    but even with no multicast programs running a multicast IP kernel is
-    in group 224.0.0.1 and you will therefore be listening to all multicasts.
-    One nv conference running over that Ethernet and you can give up.
 
-*/
+/**
+ * DOC: 3c501 Card Notes
+ *
+ *  Some notes on this thing if you have to hack it.  [Alan]
+ *
+ *  Some documentation is available from 3Com. Due to the boards age
+ *  standard responses when you ask for this will range from 'be serious'
+ *  to 'give it to a museum'. The documentation is incomplete and mostly
+ *  of historical interest anyway. 
+ *
+ *  The basic system is a single buffer which can be used to receive or
+ *  transmit a packet. A third command mode exists when you are setting
+ *  things up.
+ *
+ *  If it's transmitting it's not receiving and vice versa. In fact the
+ *  time to get the board back into useful state after an operation is
+ *  quite large.
+ *
+ *  The driver works by keeping the board in receive mode waiting for a
+ *  packet to arrive. When one arrives it is copied out of the buffer
+ *  and delivered to the kernel. The card is reloaded and off we go.
+ *
+ *  When transmitting lp->txing is set and the card is reset (from
+ *  receive mode) [possibly losing a packet just received] to command
+ *  mode. A packet is loaded and transmit mode triggered. The interrupt
+ *  handler runs different code for transmit interrupts and can handle
+ *  returning to receive mode or retransmissions (yes you have to help
+ *  out with those too).
+ *
+ * DOC: Problems
+ *  
+ *  There are a wide variety of undocumented error returns from the card
+ *  and you basically have to kick the board and pray if they turn up. Most
+ *  only occur under extreme load or if you do something the board doesn't
+ *  like (eg touching a register at the wrong time).
+ *
+ *  The driver is less efficient than it could be. It switches through
+ *  receive mode even if more transmits are queued. If this worries you buy
+ *  a real Ethernet card.
+ *
+ *  The combination of slow receive restart and no real multicast
+ *  filter makes the board unusable with a kernel compiled for IP
+ *  multicasting in a real multicast environment. That's down to the board,
+ *  but even with no multicast programs running a multicast IP kernel is
+ *  in group 224.0.0.1 and you will therefore be listening to all multicasts.
+ *  One nv conference running over that Ethernet and you can give up.
+ *
+ */
 
 static const char *version =
-    "3c501.c: 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov).\n";
+    "3c501.c: 2000/02/08 Alan Cox (alan@redhat.com).\n";
 
 /*
  *	Braindamage remaining:
@@ -119,6 +129,7 @@
 int el1_probe(struct net_device *dev);
 static int  el1_probe1(struct net_device *dev, int ioaddr);
 static int  el_open(struct net_device *dev);
+static void el_timeout(struct net_device *dev);
 static int  el_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void el_receive(struct net_device *dev);
@@ -144,6 +155,7 @@
 	int		tx_pkt_start;	/* The length of the current Tx packet. */
 	int		collisions;	/* Tx collisions this packet */
 	int		loading;	/* Spot buffer load collisions */
+	int		txing;		/* True if card is in TX mode */
 	spinlock_t	lock;		/* Serializing lock */
 };
 
@@ -210,6 +222,19 @@
 struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
 #else
 
+/**
+ * el1_probe:
+ * @dev: The device structure passed in to probe. 
+ *
+ * This can be called from two places. The network layer will probe using
+ * a device structure passed in with the probe information completed. For a
+ * modular driver we use #init_module to fill in our own structure and probe
+ * for it.
+ *
+ * Returns 0 on success. ENXIO if asked not to probe and ENODEV if asked to
+ * probe and failing to find anything.
+ */
+ 
 int __init el1_probe(struct net_device *dev)
 {
 	int i;
@@ -233,8 +258,17 @@
 }
 #endif
 
-/*
- *	The actual probe.
+/**
+ *	el1_probe: 
+ *	@dev: The device structure to use
+ *	@ioaddr: An I/O address to probe at.
+ *
+ *	The actual probe. This is iterated over by #el1_probe in order to
+ *	check all the applicable device locations.
+ *
+ *	Returns 0 for a success, in which case the device is activated,
+ *	EAGAIN if the IRQ is in use by another driver, and ENODEV if the
+ *	board cannot be found.
  */
 
 static int __init el1_probe1(struct net_device *dev, int ioaddr)
@@ -310,11 +344,11 @@
 	if (autoirq)
 		dev->irq = autoirq;
 
-	printk("%s: %s EtherLink at %#lx, using %sIRQ %d.\n", dev->name, mname, dev->base_addr,
+	printk(KERN_INFO "%s: %s EtherLink at %#lx, using %sIRQ %d.\n", dev->name, mname, dev->base_addr,
 			autoirq ? "auto":"assigned ", dev->irq);
 
 #ifdef CONFIG_IP_MULTICAST
-	printk("WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
+	printk(KERN_WARNING "WARNING: Use of the 3c501 in a multicast kernel is NOT recommended.\n");
 #endif
 
 	if (el_debug)
@@ -338,6 +372,8 @@
 
 	dev->open = &el_open;
 	dev->hard_start_xmit = &el_start_xmit;
+	dev->tx_timeout = &el_timeout;
+	dev->watchdog_timeo = HZ;
 	dev->stop = &el1_close;
 	dev->get_stats = &el1_get_stats;
 	dev->set_multicast_list = &set_multicast_list;
@@ -351,13 +387,24 @@
 	return 0;
 }
 
-/*
- *	Open/initialize the board.
+/**
+ *	el1_open:
+ *	@dev: device that is being opened
+ *
+ *	When an ifconfig is issued which changes the device flags to include
+ *	IFF_UP this function is called. It is only called when the change 
+ *	occurs, not when the interface remains up. #el1_close will be called
+ *	when it goes down.
+ *
+ *	Returns 0 for a successful open, or -EAGAIN if someone has run off
+ *	with our interrupt line.
  */
 
 static int el_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
+	struct net_local *lp = (struct net_local *)dev->priv;
+	unsigned long flags;
 
 	if (el_debug > 2)
 		printk("%s: Doing el_open()...", dev->name);
@@ -365,47 +412,75 @@
 	if (request_irq(dev->irq, &el_interrupt, 0, "3c501", dev))
 		return -EAGAIN;
 
+	spin_lock_irqsave(&lp->lock, flags);
 	el_reset(dev);
+	spin_unlock_irqrestore(&lp->lock, flags);
 
-	dev->start = 1;
-
+	lp->txing = 0;		/* Board in RX mode */
 	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
+	netif_start_queue(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
-static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
+/**
+ * el_timeout:
+ * @dev: The 3c501 card that has timed out
+ *
+ * Attempt to restart the board. This is basically a mixture of extreme
+ * violence and prayer
+ *
+ */
+ 
+static void el_timeout(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
-	unsigned long flags;
+ 
+	if (el_debug)
+		printk (KERN_DEBUG "%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
+			dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
+	lp->stats.tx_errors++;
+	outb(TX_NORM, TX_CMD);
+	outb(RX_NORM, RX_CMD);
+	outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
+	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
+	lp->txing = 0;		/* Ripped back in to RX */
+	netif_wake_queue(dev);
+}
 
-	if(dev->interrupt)		/* May be unloading, don't stamp on */
-		return 1;		/* the packet buffer this time      */
+ 
+/**
+ * el_start_xmit:
+ * @skb: The packet that is queued to be sent
+ * @dev: The 3c501 card we want to throw it down
+ *
+ * Attempt to send a packet to a 3c501 card. There are some interesting
+ * catches here because the 3c501 is an extremely old and therefore
+ * stupid piece of technology.
+ *
+ * If we are handling an interrupt on the other CPU we cannot load a packet
+ * as we may still be attempting to retrieve the last RX packet buffer.
+ *
+ * When a transmit times out we dump the card into control mode and just
+ * start again. It happens enough that it isnt worth logging.
+ *
+ * We avoid holding the spin locks when doing the packet load to the board.
+ * The device is very slow, and its DMA mode is even slower. If we held the
+ * lock while loading 1500 bytes onto the controller we would drop a lot of
+ * serial port characters. This requires we do extra locking, but we have
+ * no real choice.
+ */
 
-	if (dev->tbusy)
-	{
-		if (jiffies - dev->trans_start < 20)
-		{
-			if (el_debug > 2)
-				printk(" transmitter busy, deferred.\n");
-			return 1;
-		}
-		if (el_debug)
-			printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
-				dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
-		lp->stats.tx_errors++;
-		outb(TX_NORM, TX_CMD);
-		outb(RX_NORM, RX_CMD);
-		outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
-		outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
-		dev->tbusy = 0;
-		dev->trans_start = jiffies;
-	}
+static int el_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *)dev->priv;
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
 
 	/*
-	 *	Avoid incoming interrupts between us flipping tbusy and flipping
-	 *	mode as the driver assumes tbusy is a faithful indicator of card
+	 *	Avoid incoming interrupts between us flipping txing and flipping
+	 *	mode as the driver assumes txing is a faithful indicator of card
 	 *	state
 	 */
 
@@ -415,17 +490,13 @@
 	 *	Avoid timer-based retransmission conflicts.
 	 */
 
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-	{
-		spin_unlock_irqrestore(&lp->lock, flags);
-		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
-	}
-	else
+	netif_stop_queue(dev);
+
+	do
 	{
 		int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
 		unsigned char *buf = skb->data;
 
-load_it_again_sam:
 		lp->tx_pkt_start = gp_start;
     		lp->collisions = 0;
 
@@ -440,7 +511,8 @@
 		inb_p(RX_STATUS);
 		inb_p(TX_STATUS);
 
-		lp->loading=1;
+		lp->loading = 1;
+		lp->txing = 1;
 
 		/*
 		 *	Turn interrupts back on while we spend a pleasant afternoon
@@ -453,29 +525,48 @@
 		outw(gp_start, GP_LOW);		/* aim - packet will be loaded into buffer start */
 		outsb(DATAPORT,buf,skb->len);	/* load buffer (usual thing each byte increments the pointer) */
 		outw(gp_start, GP_LOW);		/* the board reuses the same register */
-
-		if(lp->loading==2)		/* A receive upset our load, despite our best efforts */
+	
+		if(lp->loading != 2)
 		{
-			if(el_debug>2)
-				printk("%s: burped during tx load.\n", dev->name);
-			spin_lock_irqsave(&lp->lock, flags);
-			goto load_it_again_sam;	/* Sigh... */
+			outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */
+			lp->loading=0;
+			dev->trans_start = jiffies;
+			if (el_debug > 2)
+				printk(" queued xmit.\n");
+			dev_kfree_skb (skb);
+			return 0;
 		}
-		outb(AX_XMIT, AX_CMD);		/* fire ... Trigger xmit.  */
-		lp->loading=0;
-		dev->trans_start = jiffies;
+		/* A receive upset our load, despite our best efforts */
+		if(el_debug>2)
+			printk("%s: burped during tx load.\n", dev->name);
+		spin_lock_irqsave(&lp->lock, flags);
 	}
+	while(1);
 
-	if (el_debug > 2)
-		printk(" queued xmit.\n");
-	dev_kfree_skb (skb);
-	return 0;
 }
 
 
-/*
- *	The typical workload of the driver:
- *	Handle the ether interface interrupts.
+/**
+ * el_interrupt:
+ * @irq: Interrupt number
+ * @dev_id: The 3c501 that burped
+ * @regs: Register data (surplus to our requirements)
+ *
+ * Handle the ether interface interrupts. The 3c501 needs a lot more 
+ * hand holding than most cards. In paticular we get a transmit interrupt
+ * with a collision error because the board firmware isnt capable of rewinding
+ * its own transmit buffer pointers. It can however count to 16 for us.
+ *
+ * On the receive side the card is also very dumb. It has no buffering to
+ * speak of. We simply pull the packet out of its PIO buffer (which is slow)
+ * and queue it for the kernel. Then we reset the card for the next packet.
+ *
+ * We sometimes get suprise interrupts late both because the SMP IRQ delivery
+ * is message passing and because the card sometimes seems to deliver late. I
+ * think if it is part way through a receive and the mode is changed it carries
+ * on receiving and sends us an interrupt. We have to band aid all these cases
+ * to get a sensible 150kbytes/second performance. Even then you want a small
+ * TCP window.
  */
 
 static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -485,12 +576,6 @@
 	int ioaddr;
 	int axsr;			/* Aux. status reg. */
 
-	if (dev == NULL  ||  dev->irq != irq)
-	{
-		printk (KERN_ERR "3c501 driver: irq %d for unknown device.\n", irq);
-		return;
-	}
-
 	ioaddr = dev->base_addr;
 	lp = (struct net_local *)dev->priv;
 
@@ -508,14 +593,12 @@
 
 	if (el_debug > 3)
 		printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x", dev->name, axsr);
-	if (dev->interrupt)
-		printk(KERN_WARNING "%s: Reentering the interrupt driver!\n", dev->name);
-	dev->interrupt = 1;
-        if(lp->loading==1 && !dev->tbusy)
+
+        if(lp->loading==1 && !lp->txing)
         	printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n",
         		dev->name);
 
-	if (dev->tbusy)
+	if (lp->txing)
 	{
 
     		/*
@@ -533,7 +616,6 @@
 				printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW));
 			}
 			lp->loading=2;		/* Force a reload */
-			dev->interrupt = 0;
 			spin_unlock(&lp->lock);
 			return;
 		}
@@ -551,8 +633,8 @@
 				printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x"
 			  		" gp=%03x rp=%03x.\n", dev->name, txsr, axsr,
 			inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));
-			dev->tbusy = 0;
-			mark_bh(NET_BH);
+			lp->txing = 0;
+			netif_wake_queue(dev);
 		}
 		else if (txsr & TX_16COLLISIONS)
 		{
@@ -562,7 +644,9 @@
 			if (el_debug)
 				printk("%s: Transmit failed 16 times, Ethernet jammed?\n",dev->name);
 			outb(AX_SYS, AX_CMD);
+			lp->txing = 0;
 			lp->stats.tx_aborted_errors++;
+			netif_wake_queue(dev);
 		}
 		else if (txsr & TX_COLLISION)
 		{
@@ -580,7 +664,6 @@
 			outw(lp->tx_pkt_start, GP_LOW);
 			outb(AX_XMIT, AX_CMD);
 			lp->stats.collisions++;
-			dev->interrupt = 0;
 			spin_unlock(&lp->lock);
 			return;
 		}
@@ -597,8 +680,8 @@
 			 *	This is safe the interrupt is atomic WRT itself.
 			 */
 
-			dev->tbusy = 0;
-			mark_bh(NET_BH);	/* In case more to transmit */
+			lp->txing = 0;
+			netif_wake_queue(dev);	/* In case more to transmit */
 		}
 	}
 	else
@@ -650,15 +733,19 @@
 	outw(0x00, RX_BUF_CLR);
 	inb(RX_STATUS);		/* Be certain that interrupts are cleared. */
 	inb(TX_STATUS);
-	dev->interrupt = 0;
 	spin_unlock(&lp->lock);
 	return;
 }
 
 
-/*
- *	We have a good packet. Well, not really "good", just mostly not broken.
- *	We must check everything to see if it is good.
+/**
+ * el_receive:
+ * @dev: Device to pull the packets from
+ *
+ * We have a good packet. Well, not really "good", just mostly not broken.
+ * We must check everything to see if it is good. In paticular we occasionally
+ * get wild packet sizes from the card. If the packet seems sane we PIO it
+ * off the card and queue it for the protocol layers.
  */
 
 static void el_receive(struct net_device *dev)
@@ -717,8 +804,18 @@
 	return;
 }
 
+/**
+ * el_reset: Reset a 3c501 card
+ * @dev: The 3c501 card about to get zapped
+ *
+ * Even resetting a 3c501 isnt simple. When you activate reset it loses all
+ * its configuration. You must hold the lock when doing this. The function
+ * cannot take the lock itself as it is callable from the irq handler.
+ */
+
 static void  el_reset(struct net_device *dev)
 {
+	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
 
 	if (el_debug> 2)
@@ -732,16 +829,24 @@
 	}
 
 	outw(0, RX_BUF_CLR);		/* Set rx packet area to 0. */
-	cli();				/* Avoid glitch on writes to CMD regs */
 	outb(TX_NORM, TX_CMD);		/* tx irq on done, collision */
 	outb(RX_NORM, RX_CMD);		/* Set Rx commands. */
 	inb(RX_STATUS);			/* Clear status. */
 	inb(TX_STATUS);
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	sti();
+	lp->txing = 0;
 }
 
+/**
+ * el1_close:
+ * @dev: 3c501 card to shut down
+ *
+ * Close a 3c501 card. The IFF_UP flag has been cleared by the user via
+ * the SIOCSIFFLAGS ioctl. We stop any further transmissions being queued,
+ * and then disable the interrupts. Finally we reset the chip. The effects
+ * of the rest will be cleaned up by #el1_open. Always returns 0 indicating
+ * a success.
+ */
+ 
 static int el1_close(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
@@ -749,9 +854,8 @@
 	if (el_debug > 2)
 		printk("%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr);
 
-	dev->tbusy = 1;
-	dev->start = 0;
-
+	netif_stop_queue(dev);
+	
 	/*
 	 *	Free and disable the IRQ.
 	 */
@@ -763,15 +867,31 @@
 	return 0;
 }
 
+/**
+ * el1_get_stats:
+ * @dev: The card to get the statistics for
+ *
+ * In smarter devices this function is needed to pull statistics off the
+ * board itself. The 3c501 has no hardware statistics. We maintain them all
+ * so they are by definition always up to date.
+ *
+ * Returns the statistics for the card from the card private data
+ */
+ 
 static struct net_device_stats *el1_get_stats(struct net_device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	return &lp->stats;
 }
 
-/*
- *	Set or clear the multicast filter for this adaptor.
- *			best-effort filtering.
+/**
+ * set_multicast_list:
+ * @dev: The device to adjust
+ *
+ * Set or clear the multicast filter for this adaptor to use the best-effort 
+ * filtering supported. The 3c501 supports only three modes of filtering.
+ * It always receives broadcasts and packets for itself. You can choose to
+ * optionally receive all packets, or all multicast packets on top of this.
  */
 
 static void set_multicast_list(struct net_device *dev)
@@ -812,6 +932,18 @@
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
 
+/**
+ * init_module:
+ *
+ * When the driver is loaded as a module this function is called. We fake up
+ * a device structure with the base I/O and interrupt set as if it was being
+ * called from Space.c. This minimises the extra code that would otherwise
+ * be required.
+ *
+ * Returns 0 for success or -EIO if a card is not found. Returning an error
+ * here also causes the module to be unloaded
+ */
+ 
 int init_module(void)
 {
 	dev_3c501.irq=irq;
@@ -821,6 +953,13 @@
 	return 0;
 }
 
+/**
+ * cleanup_module:
+ * 
+ * The module is being unloaded. We unhook our network device from the system
+ * and then free up the resources we took when the card was found.
+ */
+ 
 void cleanup_module(void)
 {
 	/*
diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v2.3.42/linux/drivers/net/3c503.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/3c503.c	Thu Feb 10 12:34:24 2000
@@ -314,7 +314,6 @@
 
     ei_status.saved_irq = dev->irq;
 
-    dev->start = 0;
     dev->open = &el2_open;
     dev->stop = &el2_close;
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v2.3.42/linux/drivers/net/3c507.c	Thu Nov 11 20:11:39 1999
+++ linux/drivers/net/3c507.c	Thu Feb 10 12:22:03 2000
@@ -40,7 +40,6 @@
 	info that the casual reader might think that it documents the i82586 :-<.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -437,9 +436,7 @@
 	/* Initialize the 82586 memory and start it. */
 	init_82586_mem(dev);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
 	MOD_INC_USE_COUNT;
 
@@ -453,7 +450,8 @@
 	unsigned long shmem = dev->mem_start;
 	unsigned long flags;
 
-	if (dev->tbusy) 
+#if 0 /* LINK_STATE_XOFF is never set when we reach here */
+	if (test_bit(LINK_STATE_XOFF, &dev->flags))
 	{
 		/* If we get here, some higher level has decided we are broken.
 		   There should really be a "kick me" function call instead. */
@@ -476,31 +474,30 @@
 			outb(0, ioaddr + SIGNAL_CA);			/* Issue channel-attn. */
 			lp->last_restart = lp->stats.tx_packets;
 		}
-		dev->tbusy=0;
+		netif_start_queue(dev);
 		dev->trans_start = jiffies;
 	}
+#endif
 
-	/* Block a timer-based transmit from overlapping. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-		printk("%s: Transmitter access conflict.\n", dev->name);
-	else
 	{
 		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		unsigned char *buf = skb->data;
 
+		spin_lock_irqsave(&lp->lock, flags);
+
 		lp->stats.tx_bytes+=length;
 		/* Disable the 82586's input to the interrupt line. */
 		outb(0x80, ioaddr + MISC_CTRL);
-#ifdef CONFIG_SMP
-		spin_lock_irqsave(&lp->lock, flags);
-		hardware_send_packet(dev, buf, length);
-		spin_unlock_irqrestore(&lp->lock, flags);
-#else
+
 		hardware_send_packet(dev, buf, length);
-#endif		
+
 		dev->trans_start = jiffies;
 		/* Enable the 82586 interrupt input. */
 		outb(0x84, ioaddr + MISC_CTRL);
+
+		spin_unlock_irqrestore(&lp->lock, flags);
+
+		netif_stop_queue(dev);
 	}
 
 	dev_kfree_skb (skb);
@@ -524,8 +521,6 @@
 		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
 		return;
 	}
-	dev->interrupt = 1;
-	
 
 	ioaddr = dev->base_addr;
 	lp = (struct net_local *)dev->priv;
@@ -553,8 +548,7 @@
 	  if (tx_status & 0x2000) {
 		lp->stats.tx_packets++;
 		lp->stats.collisions += tx_status & 0xf;
-		dev->tbusy = 0;
-		mark_bh(NET_BH);		/* Inform upper layers. */
+		netif_wake_queue(dev);
 	  } else {
 		lp->stats.tx_errors++;
 		if (tx_status & 0x0600)  lp->stats.tx_carrier_errors++;
@@ -580,7 +574,8 @@
 	/* Acknowledge the interrupt sources. */
 	ack_cmd = status & 0xf000;
 
-	if ((status & 0x0700) != 0x0200 && dev->start) {
+	if ((status & 0x0700) != 0x0200 &&
+	    (test_bit(LINK_STATE_START, &dev->state))) {
 		if (net_debug)
 			printk("%s: Command unit stopped, status %04x, restarting.\n",
 				   dev->name, status);
@@ -590,7 +585,8 @@
 		ack_cmd |= CUC_RESUME;
 	}
 
-	if ((status & 0x0070) != 0x0040  &&  dev->start) 
+	if ((status & 0x0070) != 0x0040  &&
+	    (test_bit(LINK_STATE_START, &dev->state)))
 	{
 		static void init_rx_bufs(struct net_device *);
 		/* The Rx unit is not ready, it must be hung.  Restart the receiver by
@@ -612,8 +608,6 @@
 	/* Enable the 82586's interrupt input. */
 	outb(0x84, ioaddr + MISC_CTRL);
 	spin_unlock(&lp->lock);
-
-	return;
 }
 
 static int el16_close(struct net_device *dev)
@@ -621,8 +615,7 @@
 	int ioaddr = dev->base_addr;
 	unsigned long shmem = dev->mem_start;
 
-	dev->tbusy = 1;
-	dev->start = 0;
+	netif_stop_queue(dev);
 
 	/* Flush the Tx and disable Rx. */
 	isa_writew(RX_SUSPEND | CUC_SUSPEND,shmem+iSCB_CMD);
@@ -795,7 +788,7 @@
 	}
 
 	if (lp->tx_head != lp->tx_reap)
-		dev->tbusy = 0;
+		netif_start_queue(dev);
 }
 
 static void el16_rx(struct net_device *dev)
diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.3.42/linux/drivers/net/3c509.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/3c509.c	Thu Feb 10 12:31:07 2000
@@ -53,6 +53,7 @@
 #include <linux/module.h>
 
 #include <linux/mca.h>
+#include <linux/isapnp.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
@@ -149,6 +150,7 @@
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
+static void el3_tx_timeout (struct net_device *dev);
 
 #ifdef CONFIG_MCA
 struct el3_mca_adapters_struct {
@@ -166,12 +168,34 @@
 };
 #endif
 
+#ifdef CONFIG_ISAPNP
+struct el3_isapnp_adapters_struct {
+	unsigned short vendor, function;
+	char *name;
+};
+struct el3_isapnp_adapters_struct el3_isapnp_adapters[] = {
+	{ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090), "3Com Etherlink III (TP)"},
+	{ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5091), "3Com Etherlink III"},
+	{ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5094), "3Com Etherlink III (combo)"},
+	{ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5095), "3Com Etherlink III (TPO)"},
+	{ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098), "3Com Etherlink III (TPC)"},
+	{ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8), "3Com Etherlink III compatible"},
+	{0, }
+};
+u16 el3_isapnp_phys_addr[8][3] = {
+	{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
+	{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}
+};
+#endif
+static int nopnp = 0;
+
 int el3_probe(struct net_device *dev)
 {
 	short lrs_state = 0xff, i;
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
 	static int current_tag = 0;
+	static int pnp_cards = 0;
 	int mca_slot = -1;
 
 	/* First check all slots of the EISA bus.  The next slot address to
@@ -265,9 +289,43 @@
 		return -ENODEV;
 	}
 #endif
-	/* Reset the ISA PnP mechanism on 3c509b. */
-	outb(0x02, 0x279);           /* Select PnP config control register. */
-	outb(0x02, 0xA79);           /* Return to WaitForKey state. */
+
+#ifdef CONFIG_ISAPNP
+	if (nopnp == 1)
+		goto no_pnp;
+
+	for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) {
+		struct pci_dev *idev = NULL;
+		int j;
+		while ((idev = isapnp_find_dev(NULL,
+						el3_isapnp_adapters[i].vendor,
+						el3_isapnp_adapters[i].function,
+						idev))) {
+			idev->prepare(idev);
+			/* Deactivation is needed if the driver was called
+			   with "nopnp=1" before, does not harm if not. */
+			idev->deactivate(idev);
+			idev->activate(idev);
+			if (!idev->resource[0].start || check_region(idev->resource[0].start,16))
+				continue;
+			ioaddr = idev->resource[0].start;
+			irq = idev->irq_resource[0].start;
+			if (el3_debug > 3)
+				printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n",
+					el3_isapnp_adapters[i].name, ioaddr, irq);
+			EL3WINDOW(0);
+			for (j = 0; j < 3; j++)
+				el3_isapnp_phys_addr[pnp_cards][j] =
+					phys_addr[j] =
+						htons(read_eeprom(ioaddr, j));
+			if_port = read_eeprom(ioaddr, 8) >> 14;
+			pnp_cards++;
+			goto found;
+		}
+	}
+no_pnp:
+#endif
+
 	/* Select an open I/O location at 0x1*0 to do contention select. */
 	for ( ; id_port < 0x200; id_port += 0x10) {
 		if (check_region(id_port, 1))
@@ -312,6 +370,28 @@
 		phys_addr[i] = htons(id_read_eeprom(i));
 	}
 
+#ifdef CONFIG_ISAPNP
+	if (nopnp == 0) {
+		/* The ISA PnP 3c509 cards respond to the ID sequence.
+		   This check is needed in order not to register them twice. */
+		for (i = 0; i < pnp_cards; i++) {
+			if (phys_addr[0] == el3_isapnp_phys_addr[i][0] &&
+			    phys_addr[1] == el3_isapnp_phys_addr[i][1] &&
+			    phys_addr[2] == el3_isapnp_phys_addr[i][2])
+			{
+				if (el3_debug > 3)
+					printk("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+						phys_addr[0] & 0xff, phys_addr[0] >> 8,
+						phys_addr[1] & 0xff, phys_addr[1] >> 8,
+						phys_addr[2] & 0xff, phys_addr[2] >> 8);
+				/* Set the adaptor tag so that the next card can be found. */
+				outb(0xd0 + ++current_tag, id_port);
+				goto no_pnp;
+			}
+		}
+	}
+#endif
+
 	{
 		unsigned int iobase = id_read_eeprom(8);
 		if_port = iobase >> 14;
@@ -357,8 +437,8 @@
 
 	{
 		const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
-		printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
-			   dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
+		printk("%s: 3c509 at %#3.3lx, %s port, address ",
+			   dev->name, dev->base_addr, if_names[dev->if_port]);
 	}
 
 	/* Read in the station address. */
@@ -387,6 +467,8 @@
 	dev->stop = &el3_close;
 	dev->get_stats = &el3_get_stats;
 	dev->set_multicast_list = &set_multicast_list;
+	dev->tx_timeout = el3_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 
 	/* Fill in the generic fields of the device structure. */
 	ether_setup(dev);
@@ -481,9 +563,7 @@
 	outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
 	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
 	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -503,28 +583,32 @@
 	return 0;					/* Always succeed */
 }
 
-static int
-el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void
+el3_tx_timeout (struct net_device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	int ioaddr = dev->base_addr;
 
 	/* Transmitter timeout, serious problems. */
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < TX_TIMEOUT)
-			return 1;
-		printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
-			   "Tx FIFO room %d.\n",
-			   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
-			   inw(ioaddr + TX_FREE));
-		lp->stats.tx_errors++;
-		dev->trans_start = jiffies;
-		/* Issue TX_RESET and TX_START commands. */
-		outw(TxReset, ioaddr + EL3_CMD);
-		outw(TxEnable, ioaddr + EL3_CMD);
-		dev->tbusy = 0;
-	}
+	printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
+		   "Tx FIFO room %d.\n",
+		   dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
+		   inw(ioaddr + TX_FREE));
+	lp->stats.tx_errors++;
+	dev->trans_start = jiffies;
+	/* Issue TX_RESET and TX_START commands. */
+	outw(TxReset, ioaddr + EL3_CMD);
+	outw(TxEnable, ioaddr + EL3_CMD);
+	netif_start_queue(dev);
+}
+
+
+static int
+el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct el3_private *lp = (struct el3_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	unsigned long flags;
 
 	lp->stats.tx_bytes += skb->len;
 	
@@ -551,47 +635,37 @@
 	}
 #endif
 #endif
-	/* Avoid timer-based retransmission conflicts. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-		printk("%s: Transmitter access conflict.\n", dev->name);
-	else {
-		/*
-		 *	We lock the driver against other processors. Note
-		 *	we don't need to lock versus the IRQ as we suspended
-		 *	that. This means that we lose the ability to take
-		 *	an RX during a TX upload. That sucks a bit with SMP
-		 *	on an original 3c509 (2K buffer)
-		 *
-		 *	Using disable_irq stops us crapping on other
-		 *	time sensitive devices.
-		 */
-
-#ifdef __SMP__
-		disable_irq_nosync(dev->irq);
-	    	spin_lock(&lp->lock);
-#endif	    	
+	/*
+	 *	We lock the driver against other processors. Note
+	 *	we don't need to lock versus the IRQ as we suspended
+	 *	that. This means that we lose the ability to take
+	 *	an RX during a TX upload. That sucks a bit with SMP
+	 *	on an original 3c509 (2K buffer)
+	 *
+	 *	Using disable_irq stops us crapping on other
+	 *	time sensitive devices.
+	 */
+
+    	spin_lock_irqsave(&lp->lock, flags);
 	    
-		/* Put out the doubleword header... */
-		outw(skb->len, ioaddr + TX_FIFO);
-		outw(0x00, ioaddr + TX_FIFO);
-		/* ... and the packet rounded to a doubleword. */
+	/* Put out the doubleword header... */
+	outw(skb->len, ioaddr + TX_FIFO);
+	outw(0x00, ioaddr + TX_FIFO);
+	/* ... and the packet rounded to a doubleword. */
 #ifdef  __powerpc__
-		outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+	outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 #else
-		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 #endif
 
-		dev->trans_start = jiffies;
-		if (inw(ioaddr + TX_FREE) > 1536) {
-			dev->tbusy = 0;
-		} else
-			/* Interrupt us when the FIFO has room for max-sized packet. */
-			outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
-#ifdef __SMP__
-		spin_unlock(&lp->lock);
-		enable_irq(dev->irq);
-#endif		
-	}
+	dev->trans_start = jiffies;
+	if (inw(ioaddr + TX_FREE) > 1536)
+		netif_start_queue(dev);
+	else
+		/* Interrupt us when the FIFO has room for max-sized packet. */
+		outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
 
 	dev_kfree_skb (skb);
 
@@ -627,10 +701,6 @@
 	lp = (struct el3_private *)dev->priv;
 	spin_lock(&lp->lock);
 
-	if (dev->interrupt)
-		printk("%s: Re-entering the interrupt handler.\n", dev->name);
-	dev->interrupt = 1;
-
 	ioaddr = dev->base_addr;
 
 	if (el3_debug > 4) {
@@ -649,8 +719,7 @@
 				printk("	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			dev->tbusy = 0;
-			mark_bh(NET_BH);
+			netif_wake_queue (dev);
 		}
 		if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
 			/* Handle all uncommon interrupts. */
@@ -701,7 +770,6 @@
 			   inw(ioaddr + EL3_STATUS));
 	}
 	spin_unlock(&lp->lock);
-	dev->interrupt = 0;
 	return;
 }
 
@@ -862,8 +930,7 @@
 	if (el3_debug > 2)
 		printk("%s: Shutting down ethercard.\n", dev->name);
 
-	dev->tbusy = 1;
-	dev->start = 0;
+	netif_stop_queue(dev);
 
 	/* Turn off statistics ASAP.  We update lp->stats below. */
 	outw(StatsDisable, ioaddr + EL3_CMD);
@@ -902,6 +969,7 @@
 MODULE_PARM(irq,"1-8i");
 MODULE_PARM(xcvr,"1-8i");
 MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(nopnp, "i");
 
 int
 init_module(void)
diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c523.c linux/drivers/net/3c523.c
--- v2.3.42/linux/drivers/net/3c523.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/3c523.c	Thu Feb 10 12:34:51 2000
@@ -177,7 +177,7 @@
     if(!p->scb->cmd) break; \
     DELAY_16(); \
     if(i == 1023) { \
-      printk("%s:%d: scb_cmd timed out .. resetting i82586\n",\
+      printk(KERN_WARNING "%s:%d: scb_cmd timed out .. resetting i82586\n",\
       	dev->name,__LINE__); \
       elmc_id_reset586(); } } }
 
@@ -186,6 +186,7 @@
 static int elmc_close(struct net_device *dev);
 static int elmc_send_packet(struct sk_buff *, struct net_device *);
 static struct net_device_stats *elmc_get_stats(struct net_device *dev);
+static void elmc_timeout(struct net_device *dev);
 #ifdef ELMC_MULTICAST
 static void set_multicast_list(struct net_device *dev);
 #endif
@@ -270,17 +271,10 @@
 
 static int elmc_close(struct net_device *dev)
 {
+	netif_stop_queue(dev);
 	elmc_id_reset586();	/* the hard way to stop the receiver */
-
 	free_irq(dev->irq, dev);
-
-	dev->start = 0;
-	dev->tbusy = 0;
-
-#ifdef MODULE
 	MOD_DEC_USE_COUNT;
-#endif
-
 	return 0;
 }
 
@@ -296,22 +290,15 @@
 	if (request_irq(dev->irq, &elmc_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM,
 			"3c523", dev)
 	    ) {
-		printk("%s: couldn't get irq %d\n", dev->name, dev->irq);
+		printk(KERN_ERR "%s: couldn't get irq %d\n", dev->name, dev->irq);
 		elmc_id_reset586();
 		return -EAGAIN;
 	}
 	alloc586(dev);
 	init586(dev);
 	startrecv586(dev);
-
-	dev->interrupt = 0;
-	dev->tbusy = 0;
-	dev->start = 1;
-
-#ifdef MODULE
+	netif_wake_queue(dev);
 	MOD_INC_USE_COUNT;
-#endif
-
 	return 0;		/* most done by init */
 }
 
@@ -384,7 +371,7 @@
 	DELAY(2);
 
 	if (p->iscp->busy) {
-		printk("%s: Init-Problems (alloc).\n", dev->name);
+		printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name);
 	}
 	memset((char *) p->scb, 0, sizeof(struct scb_struct));
 }
@@ -466,7 +453,7 @@
 	mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
 
 	/* if we get this far, adapter has been found - carry on */
-	printk("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
+	printk(KERN_INFO "%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
 
 	/* Now we extract configuration info from the card.
 	   The 3c523 provides information in two of the POS registers, but
@@ -510,7 +497,7 @@
 
 	((struct priv *) (dev->priv))->slot = slot;
 
-	printk("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
+	printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
 	       dev->base_addr);
 
 	/* Determine if we're using the on-board transceiver (i.e. coax) or
@@ -532,7 +519,7 @@
 
 	size = 0x4000;		/* check for 16K mem */
 	if (!check586(dev, dev->mem_start, size)) {
-		printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
+		printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
 		       dev->mem_start);
 		release_region(dev->base_addr, ELMC_IO_EXTENT);
 		return ENODEV;
@@ -548,13 +535,13 @@
 	((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
 
 	/* dump all the assorted information */
-	printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
+	printk(KERN_INFO "%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
 	       dev->irq, dev->if_port ? "ex" : "in", 
 	       dev->mem_start, dev->mem_end - 1);
 
 	/* The hardware address for the 3c523 is stored in the first six
 	   bytes of the IO address. */
-	printk("%s: hardware address ", dev->name);
+	printk(KERN_INFO "%s: hardware address ", dev->name);
 	for (i = 0; i < 6; i++) {
 		dev->dev_addr[i] = inb(dev->base_addr + i);
 		printk(" %02x", dev->dev_addr[i]);
@@ -565,6 +552,8 @@
 	dev->stop = &elmc_close;
 	dev->get_stats = &elmc_get_stats;
 	dev->hard_start_xmit = &elmc_send_packet;
+	dev->tx_timeout = &elmc_timeout;
+	dev->watchdog_timeo = HZ;
 #ifdef ELMC_MULTICAST
 	dev->set_multicast_list = &set_multicast_list;
 #else
@@ -573,10 +562,6 @@
 
 	ether_setup(dev);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 0;
-
 	/* note that we haven't actually requested the IRQ from the kernel.
 	   That gets done in elmc_open().  I'm not sure that's such a good idea,
 	   but it works, so I'll go with it. */
@@ -640,7 +625,7 @@
 	}
 
 	if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) {
-		printk("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
+		printk(KERN_WARNING "%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
 		return 1;
 	}
 	/*
@@ -666,7 +651,7 @@
 	}
 
 	if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) {
-		printk("%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status);
+		printk(KERN_WARNING "%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status);
 		return 1;
 	}
 	/*
@@ -687,7 +672,7 @@
 	s = jiffies;
 	while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
 		if (jiffies - s > 30*HZ/100) {
-			printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
+			printk(KERN_WARNING "%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
 			result = 1;
 			break;
 		}
@@ -703,14 +688,14 @@
 		if (result & TDR_LNK_OK) {
 			/* empty */
 		} else if (result & TDR_XCVR_PRB) {
-			printk("%s: TDR: Transceiver problem!\n", dev->name);
+			printk(KERN_WARNING "%s: TDR: Transceiver problem!\n", dev->name);
 		} else if (result & TDR_ET_OPN) {
-			printk("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+			printk(KERN_WARNING "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
 		} else if (result & TDR_ET_SRT) {
 			if (result & TDR_TIMEMASK)	/* time == 0 -> strange :-) */
-				printk("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+				printk(KERN_WARNING "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
 		} else {
-			printk("%s: TDR: Unknown status %04x\n", dev->name, result);
+			printk(KERN_WARNING "%s: TDR: Unknown status %04x\n", dev->name, result);
 		}
 	}
 	/*
@@ -754,11 +739,11 @@
 		/* I don't understand this: do we really need memory after the init? */
 		int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
 		if (len <= 0) {
-			printk("%s: Ooooops, no memory for MC-Setup!\n", dev->name);
+			printk(KERN_ERR "%s: Ooooops, no memory for MC-Setup!\n", dev->name);
 		} else {
 			if (len < num_addrs) {
 				num_addrs = len;
-				printk("%s: Sorry, can only apply %d MC-Address(es).\n",
+				printk(KERN_WARNING "%s: Sorry, can only apply %d MC-Address(es).\n",
 				       dev->name, num_addrs);
 			}
 			mc_cmd = (struct mcsetup_cmd_struct *) ptr;
@@ -779,7 +764,7 @@
 					break;
 			}
 			if (!(mc_cmd->cmd_status & STAT_COMPL)) {
-				printk("%s: Can't apply multicast-address-list.\n", dev->name);
+				printk(KERN_WARNING "%s: Can't apply multicast-address-list.\n", dev->name);
 			}
 		}
 	}
@@ -792,7 +777,7 @@
 		p->xmit_buffs[i] = (struct tbd_struct *) ptr;	/* TBD */
 		ptr = (char *) ptr + sizeof(struct tbd_struct);
 		if ((void *) ptr > (void *) p->iscp) {
-			printk("%s: not enough shared-mem for your configuration!\n", dev->name);
+			printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name);
 			return 1;
 		}
 		memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct));
@@ -882,9 +867,9 @@
 	struct priv *p;
 
 	if (dev == NULL) {
-		printk("elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
+		printk(KERN_ERR "elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
 		return;
-	} else if (!dev->start) {
+	} else if (!test_bit(LINK_STATE_START, &dev->state)) {
 		/* The 3c523 has this habit of generating interrupts during the
 		   reset.  I'm not sure if the ni52 has this same problem, but it's
 		   really annoying if we haven't finished initializing it.  I was
@@ -901,8 +886,6 @@
 
 	p = (struct priv *) dev->priv;
 
-	dev->interrupt = 1;
-
 	while ((stat = p->scb->status & STAT_MASK)) 
 	{
 		p->scb->cmd = stat;
@@ -919,8 +902,8 @@
 #ifndef NO_NOPCOMMANDS
 		if (stat & STAT_CNA) {
 			/* CU went 'not ready' */
-			if (dev->start) {
-				printk("%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+			if (test_bit(LINK_STATE_START, &dev->state)) {
+				printk(KERN_WARNING "%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
 			}
 		}
 #endif
@@ -935,7 +918,7 @@
 				p->scb->cmd = RUC_RESUME;
 				elmc_attn586();
 			} else {
-				printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+				printk(KERN_WARNING "%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
 				elmc_rnr_int(dev);
 			}
 		}
@@ -944,8 +927,6 @@
 			break;
 		}
 	}
-
-	dev->interrupt = 0;
 }
 
 /*******************************************************
@@ -980,11 +961,11 @@
 					p->stats.rx_dropped++;
 				}
 			} else {
-				printk("%s: received oversized frame.\n", dev->name);
+				printk(KERN_WARNING "%s: received oversized frame.\n", dev->name);
 				p->stats.rx_dropped++;
 			}
 		} else {	/* frame !(ok), only with 'save-bad-frames' */
-			printk("%s: oops! rfd-error-status: %04x\n", dev->name, status);
+			printk(KERN_WARNING "%s: oops! rfd-error-status: %04x\n", dev->name, status);
 			p->stats.rx_errors++;
 		}
 		p->rfd_top->status = 0;
@@ -1013,7 +994,7 @@
 	alloc_rfa(dev, (char *) p->rfd_first);
 	startrecv586(dev);	/* restart RU */
 
-	printk("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
+	printk(KERN_WARNING "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
 
 }
 
@@ -1028,7 +1009,7 @@
 
 	status = p->xmit_cmds[p->xmit_last]->cmd_status;
 	if (!(status & STAT_COMPL)) {
-		printk("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
+		printk(KERN_WARNING "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
 	}
 	if (status & STAT_OK) {
 		p->stats.tx_packets++;
@@ -1036,18 +1017,18 @@
 	} else {
 		p->stats.tx_errors++;
 		if (status & TCMD_LATECOLL) {
-			printk("%s: late collision detected.\n", dev->name);
+			printk(KERN_WARNING "%s: late collision detected.\n", dev->name);
 			p->stats.collisions++;
 		} else if (status & TCMD_NOCARRIER) {
 			p->stats.tx_carrier_errors++;
-			printk("%s: no carrier detected.\n", dev->name);
+			printk(KERN_WARNING "%s: no carrier detected.\n", dev->name);
 		} else if (status & TCMD_LOSTCTS) {
-			printk("%s: loss of CTS detected.\n", dev->name);
+			printk(KERN_WARNING "%s: loss of CTS detected.\n", dev->name);
 		} else if (status & TCMD_UNDERRUN) {
 			p->stats.tx_fifo_errors++;
-			printk("%s: DMA underrun detected.\n", dev->name);
+			printk(KERN_WARNING "%s: DMA underrun detected.\n", dev->name);
 		} else if (status & TCMD_MAXCOLL) {
-			printk("%s: Max. collisions exceeded.\n", dev->name);
+			printk(KERN_WARNING "%s: Max. collisions exceeded.\n", dev->name);
 			p->stats.collisions += 16;
 		}
 	}
@@ -1058,8 +1039,7 @@
 	}
 #endif
 
-	dev->tbusy = 0;
-	mark_bh(NET_BH);
+	netif_wake_queue(dev);
 }
 
 /***********************************************************
@@ -1077,6 +1057,37 @@
 }
 
 /******************************************************
+ * timeout
+ */
+ 
+static void elmc_timeout(struct net_device *dev)
+{
+	struct priv *p = (struct priv *) dev->priv;
+	/* COMMAND-UNIT active? */
+	if (p->scb->status & CU_ACTIVE) {
+#ifdef DEBUG
+		printk("%s: strange ... timeout with CU active?!?\n", dev->name);
+		printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point);
+#endif
+		p->scb->cmd = CUC_ABORT;
+		elmc_attn586();
+		WAIT_4_SCB_CMD();
+		p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
+		p->scb->cmd = CUC_START;
+		elmc_attn586();
+		WAIT_4_SCB_CMD();
+		netif_wake_queue(dev);
+	} else {
+#ifdef DEBUG
+		printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status);
+		printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
+#endif
+		elmc_close(dev);
+		elmc_open(dev);
+	}
+}
+ 
+/******************************************************
  * send frame
  */
 
@@ -1088,103 +1099,63 @@
 #endif
 	struct priv *p = (struct priv *) dev->priv;
 
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 5) {
-			return 1;
-		}
-		/* COMMAND-UNIT active? */
-		if (p->scb->status & CU_ACTIVE) {
-			dev->tbusy = 0;
-#ifdef DEBUG
-			printk("%s: strange ... timeout with CU active?!?\n", dev->name);
-			printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point);
-#endif
-			p->scb->cmd = CUC_ABORT;
-			elmc_attn586();
-			WAIT_4_SCB_CMD();
-			p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
-			p->scb->cmd = CUC_START;
-			elmc_attn586();
-			WAIT_4_SCB_CMD();
-			dev->trans_start = jiffies;
-			return 0;
-		} else {
-#ifdef DEBUG
-			printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status);
-			printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
-#endif
-			elmc_close(dev);
-			elmc_open(dev);
-		}
-		dev->trans_start = jiffies;
-		return 0;
-	}
-	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("%s: Transmitter access conflict.\n", dev->name);
-	} else {
-		memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
-		len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+	netif_stop_queue(dev);
+
+	memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
+	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 
 #if (NUM_XMIT_BUFFS == 1)
 #ifdef NO_NOPCOMMANDS
-		p->xmit_buffs[0]->size = TBD_LAST | len;
-		for (i = 0; i < 16; i++) {
-			p->scb->cbl_offset = make16(p->xmit_cmds[0]);
-			p->scb->cmd = CUC_START;
-			p->xmit_cmds[0]->cmd_status = 0;
-
+	p->xmit_buffs[0]->size = TBD_LAST | len;
+	for (i = 0; i < 16; i++) {
+		p->scb->cbl_offset = make16(p->xmit_cmds[0]);
+		p->scb->cmd = CUC_START;
+		p->xmit_cmds[0]->cmd_status = 0;
 			elmc_attn586();
-			dev->trans_start = jiffies;
-			if (!i) {
-				dev_kfree_skb(skb);
-			}
-			WAIT_4_SCB_CMD();
-			if ((p->scb->status & CU_ACTIVE)) {	/* test it, because CU sometimes doesn't start immediately */
-				break;
-			}
-			if (p->xmit_cmds[0]->cmd_status) {
-				break;
-			}
-			if (i == 15) {
-				printk("%s: Can't start transmit-command.\n", dev->name);
-			}
+		dev->trans_start = jiffies;
+		if (!i) {
+			dev_kfree_skb(skb);
+		}
+		WAIT_4_SCB_CMD();
+		if ((p->scb->status & CU_ACTIVE)) {	/* test it, because CU sometimes doesn't start immediately */
+			break;
+		}
+		if (p->xmit_cmds[0]->cmd_status) {
+			break;
+		}
+		if (i == 15) {
+			printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name);
 		}
+	}
 #else
-		next_nop = (p->nop_point + 1) & 0x1;
-		p->xmit_buffs[0]->size = TBD_LAST | len;
-
-		p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
-		    = make16((p->nop_cmds[next_nop]));
-		p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
-
-		p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
-		dev->trans_start = jiffies;
-		p->nop_point = next_nop;
-		dev_kfree_skb(skb);
+	next_nop = (p->nop_point + 1) & 0x1;
+	p->xmit_buffs[0]->size = TBD_LAST | len;
+	
+	p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
+	    = make16((p->nop_cmds[next_nop]));
+	p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
+
+	p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
+	dev->trans_start = jiffies;
+	p->nop_point = next_nop;
+	dev_kfree_skb(skb);
 #endif
 #else
-		p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
-		if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
-			next_nop = 0;
-		}
-		p->xmit_cmds[p->xmit_count]->cmd_status = 0;
-		p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
-		    = make16((p->nop_cmds[next_nop]));
-		p->nop_cmds[next_nop]->cmd_status = 0;
-
+	p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
+	if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
+		next_nop = 0;
+	}
+	p->xmit_cmds[p->xmit_count]->cmd_status = 0;
+	p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
+	    = make16((p->nop_cmds[next_nop]));
+	p->nop_cmds[next_nop]->cmd_status = 0;
 		p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
-		dev->trans_start = jiffies;
-		p->xmit_count = next_nop;
-
-		cli();
-		if (p->xmit_count != p->xmit_last) {
-			dev->tbusy = 0;
-		}
-		sti();
-		dev_kfree_skb(skb);
+	dev->trans_start = jiffies;
+	p->xmit_count = next_nop;
+	if (p->xmit_count != p->xmit_last)
+		netif_wake_queue(dev);
+	dev_kfree_skb(skb);
 #endif
-	}
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c527.c linux/drivers/net/3c527.c
--- v2.3.42/linux/drivers/net/3c527.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/3c527.c	Thu Feb 10 12:34:51 2000
@@ -1,4 +1,3 @@
-
 /* 3c527.c: 3Com Etherlink/MC32 driver for Linux
  *
  *	(c) Copyright 1998 Red Hat Software Inc
@@ -18,11 +17,8 @@
 static const char *version =
 	"3c527.c:v0.07 2000/01/18 Alan Cox (alan@redhat.com)\n";
 
-/*
- *	Things you need
- *	o	The databook.
- *
- *	Traps for the unwary
+/**
+ * DOC: Traps for the unwary
  *
  *	The diagram (Figure 1-1) and the POS summary disagree with the
  *	"Interrupt Level" section in the manual.
@@ -30,6 +26,32 @@
  *	The documentation in places seems to miss things. In actual fact
  *	I've always eventually found everything is documented, it just
  *	requires careful study.
+ *
+ * DOC: Theory Of Operation
+ *
+ *	The 3com 3c527 is a 32bit MCA bus mastering adapter with a large
+ *	amount of on board intelligence that housekeeps a somewhat dumber
+ *	Intel NIC. For performance we want to keep the transmit queue deep
+ *	as the card can transmit packets while fetching others from main
+ *	memory by bus master DMA. Transmission and reception are driven by
+ *	ring buffers. When updating the ring we are required to do some
+ *	housekeeping work using the mailboxes and the command register.
+ *
+ *	The mailboxes provide a method for sending control requests to the
+ *	card. The transmit mail box is used to update the transmit ring 
+ *	pointers and the receive mail box to update the receive ring
+ *	pointers. The exec mailbox allows a variety of commands to be
+ *	executed. Each command must complete before the next is executed.
+ *	Primarily we use the exec mailbox for controlling the multicast lists.
+ *	We have to do a certain amount of interesting hoop jumping as the 
+ *	multicast list changes can occur in interrupt state when the card
+ *	has an exec command pending. We defer such events until the command
+ *	completion interrupt.
+ *
+ *	The control register is used to pass status information. It tells us
+ *	the transmit and receive status for packets and allows us to control
+ *	the card operation mode. You must stop the card when emptying the
+ *	receive ring, or you will race with the ring buffer and lose packets.
  */
 
 #include <linux/module.h>
@@ -135,6 +157,7 @@
 
 static int	mc32_probe1(struct net_device *dev, int ioaddr);
 static int	mc32_open(struct net_device *dev);
+static void	mc32_timeout(struct net_device *dev);
 static int	mc32_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void	mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int	mc32_close(struct net_device *dev);
@@ -143,12 +166,14 @@
 static void	mc32_reset_multicast_list(struct net_device *dev);
 
 
-/*
- * Check for a network adaptor of this type, and return '0' iff one exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- * If dev->base_addr == 2, allocate space for the device and return success
- * (detachable devices only).
+/**
+ * mc32_probe:
+ * @dev: device to probe
+ *
+ * Because MCA bus is a real bus and we can scan for cards we could do a
+ * single scan for all boards here. Right now we use the passed in device
+ * structure and scan for only one board. This needs fixing for modules
+ * in paticular.
  */
 
 int __init mc32_probe(struct net_device *dev)
@@ -182,11 +207,17 @@
 	return -ENODEV;
 }
 
-/*
- * This is the real probe routine. Linux has a history of friendly device
- * probes on the ISA bus. A good device probes avoids doing writes, and
- * verifies that the correct device exists and functions.
+/**
+ * mc32_probe1:
+ * @dev:  Device structure to fill in
+ * @slot: The MCA bus slot being used by this card
+ *
+ * Decode the slot data and configure the card structures. Having done this we
+ * can reset the card and configure it. The card does a full self test cycle
+ * in firmware so we have to wait for it to return and post us either a 
+ * failure case or some addresses we use to find the board internals.
  */
+ 
 static int __init mc32_probe1(struct net_device *dev, int slot)
 {
 	static unsigned version_printed = 0;
@@ -239,13 +270,14 @@
 		return -ENODEV;
 	}
 
-	/* Allocate a new 'dev' if needed. */
-	if (dev == NULL) {
-		/*
-		 * Don't allocate the private data here, it is done later
-		 * This makes it easier to free the memory when this driver
-		 * is used as a module.
-		 */
+	/*
+	 * Don't allocate the private data here, it is done later
+	 * This makes it easier to free the memory when this driver
+	 * is used as a module.
+	 */
+
+	if(dev==NULL)
+	{
 		dev = init_etherdev(0, 0);
 		if (dev == NULL)
 			return -ENOMEM;
@@ -425,6 +457,8 @@
 	dev->hard_start_xmit	= mc32_send_packet;
 	dev->get_stats		= mc32_get_stats;
 	dev->set_multicast_list = mc32_set_multicast_list;
+	dev->tx_timeout		= mc32_timeout;
+	dev->watchdog_timeo	= HZ*5;	/* Board does all the work */
 	
 	lp->rx_halted		= 1;
 	lp->tx_halted		= 1;
@@ -435,8 +469,13 @@
 }
 
 
-/*
- *	Polled command stuff 
+/**
+ *	mc32_ring_poll:
+ *	@dev:	The device to wait for
+ *	
+ *	Wait until a command we issues to the control register is completed.
+ *	This actually takes very little time at all, which is fortunate as
+ *	we often have to busy wait it.
  */
  
 static void mc32_ring_poll(struct net_device *dev)
@@ -446,25 +485,20 @@
 }
 
 
-/*
- *	Send exec commands. This requires a bit of explaining.
- *
- *	You feed the card a command, you wait, it interrupts you get a 
- *	reply. All well and good. The complication arises because you use
- *	commands for filter list changes which come in at bh level from things
- *	like IPV6 group stuff.
- *
- *	We have a simple state machine
- *
- *	0	- nothing issued
- *	1	- command issued, wait reply
- *	2	- reply waiting - reader then goes to state 0
- *	3	- command issued, trash reply. In which case the irq
- *		  takes it back to state 0
- */
 
-/*
- *	Send command from interrupt state
+/**
+ *	mc32_command_nowait:
+ *	@dev: The 3c527 to issue the command to
+ *	@cmd: The command word to write to the mailbox
+ *	@data: A data block if the command expects one
+ *	@len: Length of the data block
+ *
+ *	Send a command from interrupt state. If there is a command currently
+ *	being executed then we return an error of -1. It simply isnt viable
+ *	to wait around as commands may be slow. Providing we get in then
+ *	we send the command and busy wait for the board to acknowledge that
+ *	a command request is pending. We do not wait for the command to 
+ *	complete, just for the card to admit to noticing it.  
  */
 
 static int mc32_command_nowait(struct net_device *dev, u16 cmd, void *data, int len)
@@ -488,7 +522,35 @@
 }
 
 
-/*
+/**
+ *	mc32_command: 
+ *	@dev: The 3c527 card to issue the command to
+ *	@cmd: The command word to write to the mailbox
+ *	@data: A data block if the command expects one
+ *	@len: Length of the data block
+ *
+ *	Sends exec commands in a user context. This permits us to wait around
+ *	for the replies and also to wait for the command buffer to complete
+ *	from a previous command before we execute our command. After our 
+ *	command completes we will complete any pending multicast reload
+ *	we blocked off by hogging the exec buffer.
+ *
+ *	You feed the card a command, you wait, it interrupts you get a 
+ *	reply. All well and good. The complication arises because you use
+ *	commands for filter list changes which come in at bh level from things
+ *	like IPV6 group stuff.
+ *
+ *	We have a simple state machine
+ *
+ *	0	- nothing issued
+ *
+ *	1	- command issued, wait reply
+ *
+ *	2	- reply waiting - reader then goes to state 0
+ *
+ *	3	- command issued, trash reply. In which case the irq
+ *		  takes it back to state 0
+ *
  *	Send command and block for results. On completion spot and reissue
  *	multicasts
  */
@@ -548,8 +610,13 @@
 }
 
 
-/*
- *	RX abort
+/**
+ *	mc32_rx_abort:
+ *	@dev: 3c527 to abort
+ *
+ *	Peforms a receive abort sequence on the card. In fact after some
+ *	experimenting we now simply tell the card to suspend reception. When
+ *	issuing aborts occasionally odd things happened.
  */
  
 static void mc32_rx_abort(struct net_device *dev)
@@ -564,8 +631,13 @@
 }
 
  
-/*
- *	RX enable
+/**
+ *	mc32_rx_begin:
+ *	@dev: 3c527 to enable
+ *
+ *	We wait for any pending command to complete and then issue 
+ *	a start reception command to the board itself. At this point 
+ *	receive handling continues as it was before.
  */
  
 static void mc32_rx_begin(struct net_device *dev)
@@ -582,6 +654,18 @@
 	lp->rx_halted=0;
 }
 
+/**
+ *	mc32_tx_abort:
+ *	@dev: 3c527 to abort
+ *
+ *	Peforms a receive abort sequence on the card. In fact after some
+ *	experimenting we now simply tell the card to suspend transmits . When
+ *	issuing aborts occasionally odd things happened. In theory we want
+ *	an abort to be sure we can recycle our buffers. As it happens we
+ *	just have to be careful to shut the card down on close, and
+ *	boot it carefully from scratch on setup.
+ */
+ 
 static void mc32_tx_abort(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
@@ -625,8 +709,16 @@
 	lp->tx_skb_top=lp->tx_skb_end=0;
 }
 
-/*
- *	TX enable
+/**
+ *	mc32_tx_begin:
+ *	@dev: 3c527 to enable
+ *
+ *	We wait for any pending command to complete and then issue 
+ *	a start transmit command to the board itself. At this point 
+ *	transmit handling continues as it was before. The ring must
+ *	be setup before you do this and must have an end marker in it.
+ *	It turns out we can avoid issuing this specific command when
+ *	doing our setup so we avoid it.
  */
  
 static void mc32_tx_begin(struct net_device *dev)
@@ -648,8 +740,17 @@
 }
 
 	
-/*
- *	Load the rx ring
+/**
+ *	mc32_load_rx_ring:
+ *	@dev: 3c527 to build the ring for
+ *
+ *	The card setups up the receive ring for us. We are required to
+ *	use the ring it provides although we can change the size of the
+ *	ring.
+ *
+ *	We allocate an sk_buff for each ring entry in turn and set the entry
+ *	up for a single non s/g buffer. The first buffer we mark with the
+ *	end marker bits. Finally we clear the rx mailbox.
  */
  
 static int mc32_load_rx_ring(struct net_device *dev)
@@ -686,6 +787,15 @@
 	return 0;
 }	
 
+/**
+ *	mc32_flush_rx_ring:
+ *	@lp: Local data of 3c527 to flush the rx ring of
+ *
+ *	Free the buffer for each ring slot. Because of the receive 
+ *	algorithm we use the ring will always be loaded will a full set
+ *	of buffers.
+ */
+
 static void mc32_flush_rx_ring(struct mc32_local *lp)
 {
 	int i;
@@ -693,6 +803,15 @@
 		kfree_skb(lp->rx_skb[i]);
 }
 
+/**
+ *	mc32_flush_tx_ring:
+ *	@lp: Local data of 3c527 to flush the tx ring of
+ *
+ *	We have to consider two cases here. We want to free the pending
+ *	buffers only. If the ring buffer head is past the start then the
+ *	ring segment we wish to free wraps through zero.
+ */
+
 static void mc32_flush_tx_ring(struct mc32_local *lp)
 {
 	int i;
@@ -711,9 +830,20 @@
 	}
 }
  	
-/*
- * Open/initialize the board. This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
+/**
+ *	mc32_open
+ *	@dev: device to open
+ *
+ *	The user is trying to bring the card into ready state. This requires
+ *	a brief dialogue with the card. Firstly we enable interrupts and then
+ *	'indications'. Without these enabled the card doesn't bother telling
+ *	us what it has done. This had me puzzled for a week.
+ *
+ *	We then load the network address and multicast filters. Turn on the
+ *	workaround mode. This works around a bug in the 82586 - it asks the
+ *	firmware to do so. It has a performance hit but is needed on busy
+ *	[read most] lans. We load the ring with buffers then we kick it
+ *	all off.
  */
 
 static int mc32_open(struct net_device *dev)
@@ -723,10 +853,6 @@
 	u8 one=1;
 	u8 regs;
 	
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
 	/*
 	 *	Interrupts enabled
 	 */
@@ -775,100 +901,138 @@
 	
 	mc32_rx_begin(dev);
 	mc32_tx_begin(dev);
-	
+
+	netif_wake_queue(dev);	
 	MOD_INC_USE_COUNT;
 
 	return 0;
 }
 
+/**
+ *	mc32_timeout:
+ *	@dev: 3c527 that timed out
+ *
+ *	Handle a timeout on transmit from the 3c527. This normally means
+ *	bad things as the hardware handles cable timeouts and mess for
+ *	us.
+ *
+ */
+
+static void mc32_timeout(struct net_device *dev)
+{
+	printk(KERN_WARNING "%s: transmit timed out?\n", dev->name);
+	/* Try to restart the adaptor. */
+	netif_wake_queue(dev);
+}
+ 
+/**
+ *	mc32_send_packet:
+ *	@skb: buffer to transmit
+ *	@dev: 3c527 to send it out of
+ *
+ *	Transmit a buffer. This normally means throwing the buffer onto
+ *	the transmit queue as the queue is quite large. If the queue is
+ *	full then we set tx_busy and return. Once the interrupt handler
+ *	gets messages telling it to reclaim transmit queue entries we will
+ *	clear tx_busy and the kernel will start calling this again.
+ *
+ *	We use cli rather than spinlocks. Since I have no access to an SMP
+ *	MCA machine I don't plan to change it. It is probably the top 
+ *	performance hit for this driver on SMP however.
+ */
+ 
 static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
-
-	if (dev->tbusy) {
-		/*
-		 * If we get here, some higher level has decided we are broken.
-		 * There should really be a "kick me" function call instead.
-		 */
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 5)
-			return 1;
-		printk(KERN_WARNING "%s: transmit timed out?\n", dev->name);
-		/* Try to restart the adaptor. */
-		dev->tbusy=0;
-		dev->trans_start = jiffies;
-	}
-
-	/*
-	 * Block a timer-based transmit from overlapping. This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	 */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-	{
-		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
-		dev_kfree_skb(skb);
-	}
-	else 
-	{
-		unsigned long flags;
+	unsigned long flags;
 		
-		u16 tx_head;
-		volatile struct skb_header *p, *np;
+	u16 tx_head;
+	volatile struct skb_header *p, *np;
 
-		save_flags(flags);
-		cli();
+	netif_stop_queue(dev);
+	
+	save_flags(flags);
+	cli();
 		
-		if(atomic_read(&lp->tx_count)==0)
-		{
-			dev->tbusy=1;
-			restore_flags(flags);
-			return 1;
-		}
-
-		tx_head = lp->tx_box->data[0];
-		atomic_dec(&lp->tx_count);
+	if(atomic_read(&lp->tx_count)==0)
+	{
+		restore_flags(flags);
+		return 1;
+	}
 
-		/* We will need this to flush the buffer out */
-		
-		lp->tx_skb[lp->tx_skb_end] = skb;
-		lp->tx_skb_end++;
-		lp->tx_skb_end&=(TX_RING_MAX-1);
-		
-		/* P is the last sending/sent buffer as a pointer */
-		p=(struct skb_header *)bus_to_virt(lp->base+tx_head);
-		
-		/* NP is the buffer we will be loading */
-		np=(struct skb_header *)bus_to_virt(lp->base+p->next);
+	tx_head = lp->tx_box->data[0];
+	atomic_dec(&lp->tx_count);
+	/* We will need this to flush the buffer out */
+	
+	lp->tx_skb[lp->tx_skb_end] = skb;
+	lp->tx_skb_end++;
+	lp->tx_skb_end&=(TX_RING_MAX-1);
+	
+	/* P is the last sending/sent buffer as a pointer */
+	p=(struct skb_header *)bus_to_virt(lp->base+tx_head);
+	
+	/* NP is the buffer we will be loading */
+	np=(struct skb_header *)bus_to_virt(lp->base+p->next);
 		
-		np->control	|= (1<<6);	/* EOL */
-		wmb();
+	np->control	|= (1<<6);	/* EOL */
+	wmb();
 		
-		np->length	= skb->len;
+	np->length	= skb->len;
 		
-		if(np->length < 60)
-			np->length = 60;
+	if(np->length < 60)
+		np->length = 60;
 			
-		np->data	= virt_to_bus(skb->data);
-		np->status	= 0;
-		np->control	= (1<<7)|(1<<6);	/* EOP EOL */
-		wmb();
-		
-		p->status	= 0;
-		p->control	&= ~(1<<6);
-		
-		dev->tbusy	= 0;			/* Keep feeding me */		
+	np->data	= virt_to_bus(skb->data);
+	np->status	= 0;
+	np->control	= (1<<7)|(1<<6);	/* EOP EOL */
+	wmb();
 		
-		lp->tx_box->mbox=0;
-		restore_flags(flags);
-	}
+	p->status	= 0;
+	p->control	&= ~(1<<6);
+	
+	lp->tx_box->mbox=0;
+	restore_flags(flags);
+	
+	netif_wake_queue(dev);
 	return 0;
 }
 
+/**
+ *	mc32_update_stats:
+ *	@dev: 3c527 to service
+ *
+ *	When the board signals us that its statistics need attention we
+ *	should query the table and clear it. In actual fact we currently
+ *	track all our statistics in software and I haven't implemented it yet.
+ */
+ 
 static void mc32_update_stats(struct net_device *dev)
 {
 }
 
-
+/**
+ *	mc32_rx_ring:
+ *	@dev: 3c527 that needs its receive ring processing
+ *
+ *	We have received one or more indications from the card that
+ *	a receive has completed. The ring buffer thus contains dirty
+ *	entries. Firstly we tell the card to stop receiving, then We walk 
+ *	the ring from the first filled entry, which is pointed to by the 
+ *	card rx mailbox and for each completed packet we will either copy 
+ *	it and pass it up the stack or if the packet is near MTU sized we 
+ *	allocate another buffer and flip the old one up the stack.
+ *
+ *	We must succeed in keeping a buffer on the ring. If neccessary we
+ *	will toss a received packet rather than lose a ring entry. Once the
+ *	first packet that is unused is found we reload the mailbox with the
+ *	buffer so that the card knows it can use the buffers again. Finally
+ *	we set it receiving again. 
+ *
+ *	We must stop reception during the ring walk. I thought it would be
+ *	neat to avoid it by clever tricks, but it turns out the event order
+ *	on the card means you have to play by the manual.
+ */
+ 
 static void mc32_rx_ring(struct net_device *dev)
 {
 	struct mc32_local *lp=dev->priv;
@@ -877,6 +1041,12 @@
 	volatile struct skb_header *p;
 	u16 base;
 	u16 top;
+
+	/* Halt RX before walking the ring */
+	
+	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
+	outb(3<<3, ioaddr+HOST_CMD);
+	while(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR);
 	
 	top = base = lp->rx_box->data[0];
 	do
@@ -927,13 +1097,6 @@
 	}
 	while(x++<48);
 	
-	/* 
-	 *	This is curious. It seems the receive stop and receive continue
-	 *	commands race against each other, even though we poll for 
-	 *	command ready to be issued. The delay is hackish but is a workaround
-	 *	while I investigate in depth
-	 */
-	
 	while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
 	lp->rx_box->mbox=0;
 	lp->rx_box->data[0] = top;
@@ -941,10 +1104,20 @@
 }
 
 
-/*
- * The typical workload of the driver:
- *   Handle the network interface interrupts.
+/**
+ *	mc32_interrupt:
+ *	@irq: Interrupt number
+ *	@dev_id: 3c527 that requires servicing
+ *	@regs: Registers (unused)
+ *
+ *	The 3c527 interrupts us for four reasons. The command register 
+ *	contains the message it wishes to send us packed into a single
+ *	byte field. We keep reading status entries until we have processed
+ *	all the transmit and control items, but simply count receive
+ *	reports. When the receive reports are in we can call the mc32_rx_ring
+ *	and empty the ring. This saves the overhead of multiple command requests
  */
+ 
 static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
@@ -956,8 +1129,6 @@
 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
 		return;
 	}
-	dev->interrupt = 1;
-
 	ioaddr = dev->base_addr;
 	lp = (struct mc32_local *)dev->priv;
 
@@ -990,8 +1161,7 @@
 				lp->tx_skb_top++;
 				lp->tx_skb_top&=(TX_RING_MAX-1);
 				atomic_inc(&lp->tx_count);
-				dev->tbusy=0;
-				mark_bh(NET_BH);
+				netif_wake_queue(dev);
 				break;
 			case 3: /* Halt */
 			case 4: /* Abort */
@@ -1066,13 +1236,27 @@
 	 
 	if(rx_event)
 		mc32_rx_ring(dev);
-	dev->interrupt = 0;
 	return;
 }
 
 
-/* The inverse routine to mc32_open(). */
-
+/**
+ *	mc32_close:
+ *	@dev: 3c527 card to shut down
+ *
+ *	The 3c527 is a bus mastering device. We must be careful how we
+ *	shut it down. It may also be running shared interrupt so we have
+ *	to be sure to silence it properly
+ *
+ *	We abort any receive and transmits going on and then wait until
+ *	any pending exec commands have completed in other code threads.
+ *	In theory we can't get here while that is true, in practice I am
+ *	paranoid
+ *
+ *	We turn off the interrupt enable for the board to be sure it can't
+ *	intefere with other devices.
+ */
+ 
 static int mc32_close(struct net_device *dev)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
@@ -1080,6 +1264,8 @@
 	u8 regs;
 	u16 one=1;
 
+	netif_stop_queue(dev);
+	
 	/*
 	 *	Send the indications on command (handy debug check)
 	 */
@@ -1105,9 +1291,6 @@
 	mc32_flush_rx_ring(lp);
 	mc32_flush_tx_ring(lp);
 	
-	dev->tbusy = 1;
-	dev->start = 0;
-
 	/* Update the statistics here. */
 
 	MOD_DEC_USE_COUNT;
@@ -1116,9 +1299,14 @@
 
 }
 
-/*
- * Get the current statistics.
- * This may be called with the card open or closed.
+/**
+ *	mc32_get_stats:
+ *	@dev: The 3c527 card to handle
+ *
+ *	As we currently handle our statistics in software this one is
+ *	easy to handle. With hardware statistics it will get messy
+ *	as the get_stats call will need to send exec mailbox messages and
+ *	need to lock out the multicast reloads.
  */
 
 static struct net_device_stats *mc32_get_stats(struct net_device *dev)
@@ -1127,13 +1315,24 @@
 	return &lp->net_stats;
 }
 
-/*
- * Set or clear the multicast filter for this adaptor.
+/**
+ *	do_mc32_set_multicast_list:
+ *	@dev: 3c527 device to load the list on
+ *	@retry: indicates this is not the first call. 
+ *
+ * Actually set or clear the multicast filter for this adaptor. The locking
+ * issues are handled by this routine. We have to track state as it may take
+ * multiple calls to get the command sequence completed. We just keep trying
+ * to schedule the loads until we manage to process them all.
+ *
  * num_addrs == -1	Promiscuous mode, receive all packets
+ *
  * num_addrs == 0	Normal mode, clear multicast list
+ *
  * num_addrs > 0	Multicast mode, receive normal and MC packets,
  *			and do best-effort filtering.
  */
+
 static void do_mc32_set_multicast_list(struct net_device *dev, int retry)
 {
 	struct mc32_local *lp = (struct mc32_local *)dev->priv;
@@ -1189,11 +1388,30 @@
 	}
 }
 
+/**
+ *	mc32_set_multicast_list:
+ *	@dev: The 3c527 to use
+ *
+ *	Commence loading the multicast list. This is called when the kernel
+ *	changes the lists. It will override any pending list we are trying to
+ *	load.
+ */
+ 
 static void mc32_set_multicast_list(struct net_device *dev)
 {
 	do_mc32_set_multicast_list(dev,0);
 }
 
+/**
+ *	mc32_reset_multicast_list:
+ *	@dev: The 3c527 to use
+ *
+ *	Attempt the next step in loading the multicast lists. If this attempt
+ *	fails to complete then it will be scheduled and this function called
+ *	again later from elsewhere.
+ */
+ 
+
 static void mc32_reset_multicast_list(struct net_device *dev)
 {
 	do_mc32_set_multicast_list(dev,1);
@@ -1208,6 +1426,15 @@
 	0, 0,  /* I/O address, IRQ */
 	0, 0, 0, NULL, mc32_probe };
 
+
+/**
+ *	init_module:
+ *
+ *	Probe and locate a 3c527 card. This really should probe and locate
+ *	all the 3c527 cards in the machine not just one of them. Yes you can
+ *	insmod multiple modules for now but its a hack.
+ */
+ 
 int init_module(void)
 {
 	int result;
@@ -1218,6 +1445,17 @@
 	return 0;
 }
 
+/**
+ *	cleanup_module:
+ *
+ *	Unloading time. We release the MCA bus resources and the interrupt
+ *	at which point everything is ready to unload. The card must be stopped
+ *	at this point or we would not have been called. When we unload we
+ *	leave the card stopped but not totally shut down. When the card is
+ *	initialized it must be rebooted or the rings reloaded before any
+ *	transmit operations are allowed to start scribbling into memory.
+ */
+ 
 void cleanup_module(void)
 {
 	int slot;
@@ -1227,8 +1465,6 @@
 
 	/*
 	 * If we don't do this, we can't re-insmod it later.
-	 * Release irq/dma here, when you have jumpered versions and
-	 * allocate them in mc32_probe1().
 	 */
 	 
 	if (this_device.priv)
diff -u --recursive --new-file v2.3.42/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.3.42/linux/drivers/net/3c59x.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/3c59x.c	Thu Feb 10 12:22:03 2000
@@ -1,4 +1,4 @@
-/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
+/* 3c59x.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
 /*
 	Written 1996-1998 by Donald Becker.
 
@@ -12,10 +12,16 @@
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
 	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-*/
+
+ Version history:
+ 	0.99H+lk1.0 - Jeff Garzik <jgarzik@mandrakesoft.com>
+		Remove compatibility defines for kernel versions < 2.2.x.
+		Update for new 2.3.x module interface
+		
+ */
 
 static char *version =
-"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99H+lk1.0 Feb 9, 2000 The Linux Kernel Team http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
 
 /* "Knobs" that adjust features and parameters. */
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
@@ -49,22 +55,14 @@
 
 #include <linux/config.h>
 #include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/in.h>
+#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
@@ -72,9 +70,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
-#include <linux/bios32.h>
-#endif
 #include <asm/irq.h>			/* For NR_IRQS only. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -86,35 +81,9 @@
 
 #include <linux/delay.h>
 
-#if (LINUX_VERSION_CODE <= 0x20100)
-#ifndef __alpha__
-#define ioremap(a,b) \
-	(((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
-#define iounmap(v) \
-	do { if ((u_long)(v) > 0x100000) vfree(v); } while (0)
-#endif
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#define le32_to_cpu(val) (val)
-#define cpu_to_le32(val) (val)
-#endif
-#if LINUX_VERSION_CODE < 0x20155
-#define PCI_SUPPORT_VER1
-#else
 #define PCI_SUPPORT_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
-#else  /* Grrr, unneeded incompatible change. */
 #define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
 
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
 MODULE_PARM(debug, "i");
@@ -125,7 +94,6 @@
 MODULE_PARM(compaq_ioaddr, "i");
 MODULE_PARM(compaq_irq, "i");
 MODULE_PARM(compaq_device_id, "i");
-#endif
 
 /* Operational parameter that usually are not changed. */
 
@@ -229,12 +197,12 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int drv_flags, io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
 enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
 	   HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, int dev_id, int card_idx);
+static struct net_device *vortex_probe1(struct pci_dev *pdev, long ioaddr, int irq, int dev_id, int card_idx);
 
 static struct pci_id_info pci_tbl[] = {
 	{"3c590 Vortex 10Mbps",			0x10B7, 0x5900, 0xffff,
@@ -426,22 +394,27 @@
 
 struct vortex_private {
 	/* The Rx and Tx rings should be quad-word-aligned. */
-	struct boom_rx_desc rx_ring[RX_RING_SIZE];
-	struct boom_tx_desc tx_ring[TX_RING_SIZE];
+	struct boom_rx_desc* rx_ring;
+	struct boom_tx_desc* tx_ring;
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
 	/* The addresses of transmit- and receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	struct net_device *next_module;
 	void *priv_addr;
+	dma_addr_t ring_dma;
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
 	struct net_device_stats stats;
 	struct sk_buff *tx_skb;		/* Packet being eaten by bus master ctrl.  */
+	dma_addr_t tx_skb_dma;	/* Allocated DMA address for bus master ctrl DMA.   */
 
 	/* PCI configuration space information. */
 	u8 pci_bus, pci_devfn;		/* PCI bus location, for power management. */
 	char *cb_fn_base;			/* CardBus function status addr space. */
 	int chip_id;
+	struct pci_dev *pdev;			/* Device for DMA mapping */
 
 	/* The remainder are related to chip state, mostly media selection. */
 	unsigned long in_interrupt;
@@ -499,6 +472,7 @@
 static void mdio_write(long ioaddr, int phy_id, int location, int value);
 static void vortex_timer(unsigned long arg);
 static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void vortex_tx_timeout(struct net_device *dev);
 static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int vortex_rx(struct net_device *dev);
 static int boomerang_rx(struct net_device *dev);
@@ -518,7 +492,6 @@
 /* A list of all installed Vortex devices, for removing the driver module. */
 static struct net_device *root_vortex_dev = NULL;
 
-#ifdef MODULE
 #ifndef CARDBUS
 /* Variables to work-around the Compaq PCI BIOS32 problem. */
 static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
@@ -532,18 +505,20 @@
 {
 	u16 dev_id, vendor_id;
 	u32 io;
-	u8 bus, devfn, irq;
+	u8 irq;
 	struct net_device *dev;
+	struct pci_dev *pdev;
 	int chip_idx;
 
 	if (loc->bus != LOC_PCI) return NULL;
-	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
-	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
-	pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
-	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+	if (!pdev) return NULL;
+	io = pdev->resource[0].start;
+	irq = pdev->irq;
+	vendor_id = pdev->vendor;
+	dev_id = pdev->device;
 	printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
-		   bus, devfn, dev_id);
+		   pdev->bus->number, pdev->devfn, dev_id);
 	io &= ~3;
 	if (io == 0 || irq == 0) {
 		printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
@@ -561,7 +536,7 @@
 			   "vortex_attach().\n", vendor_id, dev_id);
 		return NULL;
 	}
-	dev = vortex_probe1(bus, devfn, io, irq, chip_idx, MAX_UNITS+1);
+	dev = vortex_probe1(pdev, io, irq, chip_idx, MAX_UNITS+1);
 	if (dev) {
 		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
 		strcpy(node->dev_name, dev->name);
@@ -604,7 +579,7 @@
 #endif  /* Cardbus support */
 
 
-int init_module(void)
+static int __init vortex_init_module (void)
 {
 	if (vortex_debug)
 		printk(KERN_INFO "%s", version);
@@ -616,17 +591,6 @@
 #endif
 }
 
-#else
-int tc59x_probe(void)
-{
-	static int scanned=0;
-	if(scanned++)
-		return -ENODEV;
-	printk(KERN_INFO "%s", version);
-	return vortex_scan(pci_tbl);
-}
-#endif  /* not MODULE */
-
 #ifndef CARDBUS
 static int vortex_scan(struct pci_id_info pci_tbl[])
 {
@@ -639,7 +603,7 @@
 	   be best done a central PCI probe dispatch, which wouldn't work
 	   well with the current structure.  So instead we detect 3Com cards
 	   in slot order. */
-	if (pcibios_present()) {
+	if (pci_present()) {
 		static int pci_index = 0;
 		unsigned char pci_bus, pci_device_fn;
 
@@ -647,15 +611,16 @@
 			u16 vendor, device, pci_command, new_command, pwr_cmd;
 			int chip_idx, irq;
 			long ioaddr;
+			struct pci_dev *pdev;
 
 			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
 									&pci_bus, &pci_device_fn)
 				!= PCIBIOS_SUCCESSFUL)
 				break;
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_VENDOR_ID, &vendor);
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_DEVICE_ID, &device);
+			pdev = pci_find_slot (pci_bus, pci_device_fn);
+			if (!pdev) continue;
+			vendor = pdev->vendor;
+			device = pdev->device;
 			for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
 				if (vendor == pci_tbl[chip_idx].vendor_id
 					&& (device & pci_tbl[chip_idx].device_id_mask) ==
@@ -671,21 +636,18 @@
 			}
 
 			/* Power-up the card. */
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-										 0xe0, &pwr_cmd);
+			pci_read_config_word(pdev, 0xe0, &pwr_cmd);
+			
 			if (pwr_cmd & 0x3) {
 				/* Save the ioaddr and IRQ info! */
 				printk(KERN_INFO "  A 3Com network adapter is powered down!"
 					   "  Setting the power state %4.4x->%4.4x.\n",
 					   pwr_cmd, pwr_cmd & ~3);
-				pcibios_write_config_word(pci_bus, pci_device_fn,
-										  0xe0, pwr_cmd & ~3);
+				pci_write_config_word(pdev, 0xe0, pwr_cmd & ~3);
 				printk(KERN_INFO "  Setting the IRQ to %d, IOADDR to %#lx.\n",
 					   irq, ioaddr);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										 PCI_INTERRUPT_LINE, irq);
-				pcibios_write_config_dword(pci_bus, pci_device_fn,
-										  PCI_BASE_ADDRESS_0, ioaddr);
+				pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+				pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, ioaddr);
 			}
 
 			if (ioaddr == 0) {
@@ -700,19 +662,18 @@
 				continue;
 
 			/* Activate the card. */
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_COMMAND, &pci_command);
+			pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+
 			new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
 			if (pci_command != new_command) {
 				printk(KERN_INFO "  The PCI BIOS has not enabled the device "
 					   "at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
 					   pci_bus, pci_device_fn, pci_command, new_command);
-				pcibios_write_config_word(pci_bus, pci_device_fn,
-										  PCI_COMMAND, new_command);
+				pci_write_config_word(pdev, PCI_COMMAND, new_command);
 			}
 
-			dev = vortex_probe1(pci_bus, pci_device_fn, ioaddr, irq,
-								chip_idx, cards_found);
+			dev = vortex_probe1(pdev, ioaddr, irq,
+					    chip_idx, cards_found);
 
 			if (dev) {
 				/* Get and check the latency values.  On the 3c590 series
@@ -722,14 +683,12 @@
 				u8 pci_latency;
 				u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
 				
-				pcibios_read_config_byte(pci_bus, pci_device_fn,
-										 PCI_LATENCY_TIMER, &pci_latency);
+				pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 				if (pci_latency < new_latency) {
 					printk(KERN_INFO "%s: Overriding PCI latency"
 						   " timer (CFLT) setting of %d, new value is %d.\n",
 						   dev->name, pci_latency, new_latency);
-					pcibios_write_config_byte(pci_bus, pci_device_fn,
-											  PCI_LATENCY_TIMER, new_latency);
+					pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
 				}
 				dev = 0;
 				cards_found++;
@@ -752,27 +711,33 @@
 			device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
 			if ((device_id & 0xFF00) != 0x5900)
 				continue;
-			vortex_probe1(0, 0, ioaddr, inw(ioaddr + 0xC88) >> 12,
-						  4, cards_found);
+			vortex_probe1(NULL, ioaddr, inw(ioaddr + 0xC88) >> 12,
+				      4, cards_found);
 			cards_found++;
 		}
 	}
 
-#ifdef MODULE
 	/* Special code to work-around the Compaq PCI BIOS32 problem. */
 	if (compaq_ioaddr) {
-		vortex_probe1(0, 0, compaq_ioaddr, compaq_irq,
+		vortex_probe1(NULL, compaq_ioaddr, compaq_irq,
 					  compaq_device_id, cards_found++);
 		dev = 0;
 	}
-#endif
 
 	return cards_found ? 0 : -ENODEV;
 }
 #endif  /* ! Cardbus */
 
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
-					long ioaddr, int irq, int chip_idx, int card_idx)
+/*
+ * vortex_probe1 - initialize one vortex board, after probing
+ *		   has located one during bus scan.
+ *
+ * NOTE: pdev==NULL is a valid condition, indicating
+ * non-PCI (generally EISA) bus device
+ */
+static struct net_device *vortex_probe1(struct pci_dev *pdev,
+					long ioaddr, int irq,
+					int chip_idx, int card_idx)
 {
 	struct vortex_private *vp;
 	int option;
@@ -790,11 +755,8 @@
 	dev->mtu = mtu;
 
 	/* Make certain the descriptor lists are aligned. */
-	{
-		void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
-		vp =  (void *)(((long)mem + 15) & ~15);
-		vp->priv_addr = mem;
-	}
+	vp = kmalloc(sizeof(*vp), GFP_KERNEL);
+
 	memset(vp, 0, sizeof(*vp));
 	dev->priv = vp;
 
@@ -802,8 +764,18 @@
 	root_vortex_dev = dev;
 
 	vp->chip_id = chip_idx;
-	vp->pci_bus = pci_bus;
-	vp->pci_devfn = pci_devfn;
+	vp->pci_bus = pdev == NULL ? 0 : pdev->bus->number;
+	vp->pci_devfn = pdev == NULL ? 0 : pdev->devfn;
+	vp->pdev = pdev;
+
+	vp->priv_addr = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+					     + sizeof(struct boom_tx_desc) * TX_RING_SIZE
+					     + 15, &vp->ring_dma);
+	/* Make sure rings are 16 byte aligned. */
+	vp->rx_ring = (void *)(((long)vp->priv_addr + 15) & ~15);
+	vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
+	vp->rx_ring_dma = (vp->ring_dma + 15) & ~15;
+	vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE;
 
 	/* The lower four bits are the media type. */
 	if (dev->mem_start)
@@ -872,8 +844,7 @@
 
 	if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
 		u32 fn_st_addr;			/* Cardbus function status space */
-		pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
-								  &fn_st_addr);
+		fn_st_addr = pdev == NULL ? 0 : pdev->resource[2].start;
 		if (fn_st_addr)
 			vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
 		printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"
@@ -963,6 +934,8 @@
 	/* The 3c59x-specific entries in the device structure. */
 	dev->open = &vortex_open;
 	dev->hard_start_xmit = &vortex_start_xmit;
+	dev->tx_timeout = &vortex_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT; 
 	dev->stop = &vortex_close;
 	dev->get_stats = &vortex_get_stats;
 	dev->do_ioctl = &vortex_ioctl;
@@ -1106,7 +1079,7 @@
 			printk(KERN_DEBUG "%s:  Filling in the Rx ring.\n", dev->name);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			struct sk_buff *skb;
-			vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));
+			vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1));
 			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
 			vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
 			skb = dev_alloc_skb(PKT_BUF_SZ);
@@ -1115,11 +1088,11 @@
 				break;			/* Bad news!  */
 			skb->dev = dev;			/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
+			vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ));
 		}
 		/* Wrap the ring. */
-		vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
-		outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+		vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
+		outl(vp->rx_ring_dma, ioaddr + UpListPtr);
 	}
 	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */
 		dev->hard_start_xmit = &boomerang_start_xmit;
@@ -1135,9 +1108,6 @@
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
 	vp->in_interrupt = 0;
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
 
 	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
 	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -1157,6 +1127,8 @@
 	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
 		writel(0x8000, vp->cb_fn_base + 4);
 
+	netif_start_queue(dev);
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -1313,11 +1285,11 @@
 			printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n",
 				   dev->name);
 		if (vp->cur_tx - vp->dirty_tx > 0  &&  inl(ioaddr + DownListPtr) == 0)
-			outl(virt_to_bus(&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]),
+			outl(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
 				 ioaddr + DownListPtr);
 		if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {
 			vp->tx_full = 0;
-			clear_bit(0, (void*)&dev->tbusy);
+			netif_wake_queue(dev);
 		}
 		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
 		outw(DownUnstall, ioaddr + EL3_CMD);
@@ -1431,27 +1403,23 @@
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start >= TX_TIMEOUT)
-			vortex_tx_timeout(dev);
-		return 1;
-	}
+	netif_stop_queue(dev);
 
 	/* Put out the doubleword header... */
 	outl(skb->len, ioaddr + TX_FIFO);
 	if (vp->bus_master) {
 		/* Set the bus-master controller to transfer the packet. */
-		outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
-		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+		int len = (skb->len + 3) & ~3;
+		outl(vp->tx_skb_dma = pci_map_single(vp->pdev, skb->data, len), ioaddr + Wn7_MasterAddr);
+		outw(len, ioaddr + Wn7_MasterLen);
 		vp->tx_skb = skb;
 		outw(StartDMADown, ioaddr + EL3_CMD);
-		/* dev->tbusy will be cleared at the DMADone interrupt. */
 	} else {
 		/* ... and the packet rounded to a doubleword. */
 		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 		DEV_FREE_SKB(skb);
 		if (inw(ioaddr + TxFree) > 1536) {
-			clear_bit(0, (void*)&dev->tbusy);
+			netif_wake_queue(dev);
 		} else
 			/* Interrupt us when the FIFO has room for max-sized packet. */
 			outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
@@ -1493,11 +1461,9 @@
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start >= TX_TIMEOUT)
-			vortex_tx_timeout(dev);
-		return 1;
-	} else {
+	netif_stop_queue(dev);
+
+	if (1) {
 		/* Calculate the next Tx descriptor entry. */
 		int entry = vp->cur_tx % TX_RING_SIZE;
 		struct boom_tx_desc *prev_entry =
@@ -1516,10 +1482,11 @@
 		}
 		vp->tx_skbuff[entry] = skb;
 		vp->tx_ring[entry].next = 0;
-		vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));
+		vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, skb->len));
 		vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
 		vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
 
+		/* Hmm... And some poor people try to use it on SMP machines 8) */
 		save_flags(flags);
 		cli();
 		outw(DownStall, ioaddr + EL3_CMD);
@@ -1527,20 +1494,20 @@
 		for (i = 600; i >= 0 ; i--)
 			if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
 				break;
-		prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
+		prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
 		if (inl(ioaddr + DownListPtr) == 0) {
-			outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
+			outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
 			queued_packet++;
 		}
 		outw(DownUnstall, ioaddr + EL3_CMD);
 		restore_flags(flags);
 
 		vp->cur_tx++;
-		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
+		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
 			vp->tx_full = 1;
-		else {					/* Clear previous interrupt enable. */
+		} else {					/* Clear previous interrupt enable. */
 			prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
-			clear_bit(0, (void*)&dev->tbusy);
+			netif_wake_queue(dev);
 		}
 		dev->trans_start = jiffies;
 		vp->stats.tx_bytes += skb->len;
@@ -1558,23 +1525,6 @@
 	int latency, status;
 	int work_done = max_interrupt_work;
 
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		dev->interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-#else
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
-	dev->interrupt = 1;
-#endif
-
-	dev->interrupt = 1;
 	ioaddr = dev->base_addr;
 	latency = inb(ioaddr + Timer);
 	status = inw(ioaddr + EL3_STATUS);
@@ -1598,8 +1548,7 @@
 				printk(KERN_DEBUG "	TX room bit was handled.\n");
 			/* There's room in the FIFO for a full-sized packet. */
 			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			clear_bit(0, (void*)&dev->tbusy);
-			mark_bh(NET_BH);
+			netif_wake_queue(dev);
 		}
 
 		if (status & DownComplete) {
@@ -1608,10 +1557,13 @@
 			while (vp->cur_tx - dirty_tx > 0) {
 				int entry = dirty_tx % TX_RING_SIZE;
 				if (inl(ioaddr + DownListPtr) ==
-					virt_to_bus(&vp->tx_ring[entry]))
+					vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc))
 					break;			/* It still hasn't been processed. */
 				if (vp->tx_skbuff[entry]) {
-					DEV_FREE_SKB(vp->tx_skbuff[entry]);
+					struct sk_buff *skb = vp->tx_skbuff[entry];
+					
+					pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[entry].addr), skb->len);
+					dev_kfree_skb_irq(vp->tx_skbuff[entry]);
 					vp->tx_skbuff[entry] = 0;
 				}
 				/* vp->stats.tx_packets++;  Counted below. */
@@ -1621,17 +1573,16 @@
 			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
 			if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
 				vp->tx_full= 0;
-				clear_bit(0, (void*)&dev->tbusy);
-				mark_bh(NET_BH);
+				netif_wake_queue(dev);
 			}
 		}
 		if (status & DMADone) {
 			if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
 				outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
-				DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+				pci_unmap_single(vp->pdev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3);
+				dev_kfree_skb_irq(vp->tx_skb); /* Release the transfered buffer */
 				if (inw(ioaddr + TxFree) > 1536) {
-					clear_bit(0, (void*)&dev->tbusy);
-					mark_bh(NET_BH);
+					netif_wake_queue(dev);
 				} else /* Interrupt when FIFO has room for max-sized packet. */
 					outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
 			}
@@ -1669,11 +1620,6 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
 			   dev->name, status);
 
-#if defined(__i386__)
-	clear_bit(0, (void*)&dev->interrupt);
-#else
-	dev->interrupt = 0;
-#endif
 	return;
 }
 
@@ -1713,12 +1659,14 @@
 				/* 'skb_put()' points to the start of sk_buff data area. */
 				if (vp->bus_master &&
 					! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
-					outl(virt_to_bus(skb_put(skb, pkt_len)),
-						 ioaddr + Wn7_MasterAddr);
+					dma_addr_t dma = pci_map_single(vp->pdev, skb_put(skb, pkt_len),
+									   pkt_len);
+					outl(dma, ioaddr + Wn7_MasterAddr);
 					outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
 					outw(StartDMAUp, ioaddr + EL3_CMD);
 					while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
 						;
+					pci_unmap_single(vp->pdev, dma, pkt_len);
 				} else {
 					insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
 						 (pkt_len + 3) >> 2);
@@ -1779,6 +1727,7 @@
 			/* The packet length: up to 4.5K!. */
 			int pkt_len = rx_status & 0x1fff;
 			struct sk_buff *skb;
+			dma_addr_t dma = le32_to_cpu(vp->rx_ring[entry].addr);
 
 			vp->stats.rx_bytes += pkt_len;
 			if (vortex_debug > 4)
@@ -1791,23 +1740,18 @@
 				&& (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ);
 				/* 'skb_put()' points to the start of sk_buff data area. */
 				memcpy(skb_put(skb, pkt_len),
-					   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
+					   vp->rx_skbuff[entry]->tail,
 					   pkt_len);
 				rx_copy++;
 			} else {
-				void *temp;
 				/* Pass up the skbuff already on the Rx ring. */
 				skb = vp->rx_skbuff[entry];
 				vp->rx_skbuff[entry] = NULL;
-				temp = skb_put(skb, pkt_len);
-				/* Remove this checking code for final release. */
-				if (bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)) != temp)
-					printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
-						   " in boomerang_rx: %p vs. %p.\n", dev->name,
-						   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
-						   temp);
+				skb_put(skb, pkt_len);
+				pci_unmap_single(vp->pdev, dma, PKT_BUF_SZ);
 				rx_nocopy++;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
@@ -1836,7 +1780,7 @@
 				break;			/* Bad news!  */
 			skb->dev = dev;			/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail));
+			vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ));
 			vp->rx_skbuff[entry] = skb;
 		}
 		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
@@ -1852,8 +1796,7 @@
 	long ioaddr = dev->base_addr;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (vortex_debug > 1) {
 		printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
@@ -1885,9 +1828,7 @@
 		outl(0, ioaddr + UpListPtr);
 		for (i = 0; i < RX_RING_SIZE; i++)
 			if (vp->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
-				vp->rx_skbuff[i]->free = 1;
-#endif
+				pci_unmap_single(vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), PKT_BUF_SZ);
 				DEV_FREE_SKB(vp->rx_skbuff[i]);
 				vp->rx_skbuff[i] = 0;
 			}
@@ -1896,7 +1837,10 @@
 		outl(0, ioaddr + DownListPtr);
 		for (i = 0; i < TX_RING_SIZE; i++)
 			if (vp->tx_skbuff[i]) {
-				DEV_FREE_SKB(vp->tx_skbuff[i]);
+				struct sk_buff *skb = vp->tx_skbuff[i];
+
+				pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[i].addr), skb->len);
+				DEV_FREE_SKB(skb);
 				vp->tx_skbuff[i] = 0;
 			}
 	}
@@ -1911,7 +1855,7 @@
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	unsigned long flags;
 
-	if (dev->start) {
+	if (test_bit(LINK_STATE_START, &dev->state)) {
 		save_flags(flags);
 		cli();
 		update_stats(dev->base_addr, dev);
@@ -2097,9 +2041,8 @@
 	return;
 }
 
-
-#ifdef MODULE
-void cleanup_module(void)
+
+static void __exit vortex_cleanup_module (void)
 {
 	struct net_device *next_dev;
 
@@ -2116,13 +2059,18 @@
 		release_region(root_vortex_dev->base_addr,
 					   pci_tbl[vp->chip_id].io_size);
 		kfree(root_vortex_dev);
-		kfree(vp->priv_addr);
+		pci_free_consistent(vp->pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+					    + sizeof(struct boom_tx_desc) * TX_RING_SIZE
+					    + 15, vp->priv_addr, vp->ring_dma);
+		kfree(vp);
 		root_vortex_dev = next_dev;
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(vortex_init_module);
+module_exit(vortex_cleanup_module);
+
+
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.3.42/linux/drivers/net/8390.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/8390.c	Wed Feb  9 20:08:09 2000
@@ -167,7 +167,8 @@
 	NS8390_init(dev, 1);
 	/* Set the flag before we drop the lock, That way the IRQ arrives
 	   after its set and we get no silly warnings */
-	dev->start = 1;
+	clear_bit(LINK_STATE_RXSEM, &dev->state);
+	netif_start_queue(dev);
       	spin_unlock_irqrestore(&ei_local->page_lock, flags);
 	ei_local->irqlock = 0;
 	return 0;
@@ -186,7 +187,7 @@
       	spin_lock_irqsave(&ei_local->page_lock, flags);
 	NS8390_init(dev, 0);
       	spin_unlock_irqrestore(&ei_local->page_lock, flags);
-	dev->start = 0;
+	netif_stop_queue(dev);
 	return 0;
 }
 
@@ -198,13 +199,11 @@
 	unsigned long flags;
 
 	/*
-	 *  We normally shouldn't be called if dev->tbusy is set, but the
-	 *  existing code does anyway. If it has been too long since the
-	 *  last Tx, we assume the board has died and kick it. We are
-	 *  bh_atomic here.
+	 *  If it has been too long since the last Tx, we assume the
+	 *  board has died and kick it.
 	 */
  
-	if (dev->tbusy) 
+	if (test_bit(LINK_STATE_XOFF, &dev->state)) 
 	{	/* Do timeouts, just like the 8003 driver. */
 		int txsr;
 		int isr;
@@ -225,7 +224,7 @@
 
 		ei_local->stat.tx_errors++;
 		isr = inb(e8390_base+EN0_ISR);
-		if (dev->start == 0) 
+		if (!test_bit(LINK_STATE_START, &dev->state))
 		{
 			spin_unlock_irqrestore(&ei_local->page_lock, flags);
 			printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name);
@@ -289,16 +288,6 @@
 	
 	spin_lock(&ei_local->page_lock);
 	
-	if (dev->interrupt) 
-	{
-		printk(KERN_WARNING "%s: Tx request while isr active.\n",dev->name);
-		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-		spin_unlock(&ei_local->page_lock);
-		enable_irq(dev->irq);
-		ei_local->stat.tx_errors++;
-		dev_kfree_skb(skb);
-		return 0;
-	}
 	ei_local->irqlock = 1;
 
 	send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
@@ -332,10 +321,10 @@
 	else
 	{	/* We should never get here. */
 		if (ei_debug)
-			printk(KERN_DEBUG "%s: No Tx buffers free! irq=%ld tx1=%d tx2=%d last=%d\n",
-				dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+			printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+				dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
 		ei_local->irqlock = 0;
-		dev->tbusy = 1;
+		netif_stop_queue(dev);
 		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 		spin_unlock(&ei_local->page_lock);
 		enable_irq(dev->irq);
@@ -368,7 +357,10 @@
 	}
 	else ei_local->txqueue++;
 
-	dev->tbusy = (ei_local->tx1  &&  ei_local->tx2);
+	if (ei_local->tx1  &&  ei_local->tx2)
+		netif_stop_queue(dev);
+	else
+		netif_start_queue(dev);
 
 #else	/* EI_PINGPONG */
 
@@ -382,7 +374,7 @@
 	ei_local->txing = 1;
 	NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
 	dev->trans_start = jiffies;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 #endif	/* EI_PINGPONG */
 
@@ -424,7 +416,7 @@
 	 
 	spin_lock(&ei_local->page_lock);
 
-	if (dev->interrupt || ei_local->irqlock) 
+	if (ei_local->irqlock) 
 	{
 #if 1 /* This might just be an interrupt for a PCI device sharing this line */
 		/* The "irqlock" check is only for testing. */
@@ -438,8 +430,7 @@
 		return;
 	}
     
-	
-	dev->interrupt = 1;
+	set_bit(LINK_STATE_RXSEM, &dev->state);
     
 	/* Change to page 0 and read the intr status reg. */
 	outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
@@ -451,7 +442,7 @@
 	while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
 		   && ++nr_serviced < MAX_SERVICE) 
 	{
-		if (dev->start == 0) 
+		if (!test_bit(LINK_STATE_START, &dev->state))
 		{
 			printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
 			interrupts = 0;
@@ -500,7 +491,7 @@
 			outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
 		}
 	}
-	dev->interrupt = 0;
+	clear_bit(LINK_STATE_RXSEM, &dev->state);
 	spin_unlock(&ei_local->page_lock);
 	return;
 }
@@ -576,7 +567,7 @@
 			printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
 				ei_local->name, ei_local->lasttx, ei_local->tx1);
 		ei_local->tx1 = 0;
-		dev->tbusy = 0;
+		netif_start_queue(dev);
 		if (ei_local->tx2 > 0) 
 		{
 			ei_local->txing = 1;
@@ -593,7 +584,7 @@
 			printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
 				ei_local->name, ei_local->lasttx, ei_local->tx2);
 		ei_local->tx2 = 0;
-		dev->tbusy = 0;
+		netif_start_queue(dev);
 		if (ei_local->tx1 > 0) 
 		{
 			ei_local->txing = 1;
@@ -613,7 +604,7 @@
 	 *  Single Tx buffer: mark it free so another packet can be loaded.
 	 */
 	ei_local->txing = 0;
-	dev->tbusy = 0;
+	netif_start_queue(dev);
 #endif
 
 	/* Minimize Tx latency: update the statistics after we restart TXing. */
@@ -638,7 +629,7 @@
 		if (status & ENTSR_OWC)
 			ei_local->stat.tx_window_errors++;
 	}
-	mark_bh (NET_BH);
+	netif_wake_queue(dev);
 }
 
 /* We have a good packet(s), get it/them out of the buffers. 
@@ -849,7 +840,7 @@
 	unsigned long flags;
     
 	/* If the card is stopped, just return the present stats. */
-	if (dev->start == 0) 
+	if (!test_bit(LINK_STATE_START, &dev->state))
 		return &ei_local->stat;
 
 	spin_lock_irqsave(&ei_local->page_lock,flags);
@@ -945,7 +936,7 @@
 	 * Ultra32 EISA) appears to have this bug fixed.
 	 */
 	 
-	if (dev->start)
+	if (test_bit(LINK_STATE_START, &dev->state))
 		outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
 	outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
 	for(i = 0; i < 8; i++) 
@@ -1064,8 +1055,7 @@
 	outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
+	netif_start_queue(dev);
 	ei_local->tx1 = ei_local->tx2 = 0;
 	ei_local->txing = 0;
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.3.42/linux/drivers/net/Config.in	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/Config.in	Thu Feb 10 12:28:01 2000
@@ -33,6 +33,7 @@
    if [ "$CONFIG_PPC" = "y" ]; then
       tristate '  MACE (Power Mac ethernet) support' CONFIG_MACE
       tristate '  BMAC (G3 ethernet) support' CONFIG_BMAC
+      tristate '  GMAC (G4/iBook ethernet) support' CONFIG_GMAC
       tristate '  Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E
       tristate '  National DP83902AV (Oak ethernet) support' CONFIG_OAKNET
    fi
@@ -126,7 +127,7 @@
       tristate '    Apricot Xen-II on board Ethernet' CONFIG_APRICOT
       tristate '    CS89x0 support' CONFIG_CS89x0
       tristate '    Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
-      tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
+      tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP
       tristate '    Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
       tristate '    EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
diff -u --recursive --new-file v2.3.42/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.3.42/linux/drivers/net/Makefile	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/Makefile	Thu Feb 10 12:24:54 2000
@@ -20,8 +20,6 @@
 ALL_SUB_DIRS := $(SUB_DIRS) fc hamradio irda pcmcia tokenring wan sk98lin arcnet
 
 O_TARGET := net.o
-O_OBJS   :=
-M_OBJS   :=
 MOD_LIST_NAME := NET_MODULES
 
 # All of the (potential) objects that export symbols.
@@ -48,15 +46,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_SK98LIN),y)
-SUB_DIRS += sk98lin
-obj-y += sk98lin/sk98lin.o
-else
-  ifeq ($(CONFIG_SK98LIN),m)
-  MOD_IN_SUB_DIRS += sk98lin
-  endif
-endif
-
 ifeq ($(CONFIG_TR),y)
 SUB_DIRS += tokenring
 MOD_IN_SUB_DIRS += tokenring
@@ -105,7 +94,55 @@
   endif
 endif
 
+#
+# link order important here
+#
+obj-$(CONFIG_PLIP) += plip.o
+
+obj-$(CONFIG_ROADRUNNER) += rrunner.o
+
+obj-$(CONFIG_HAPPYMEAL) += sunhme.o
+obj-$(CONFIG_SUNLANCE) += sunlance.o
+obj-$(CONFIG_SUNQE) += sunqe.o
+obj-$(CONFIG_SUNBMAC) += sunbmac.o
+obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
+
+obj-$(CONFIG_MACE) += mace.o
+obj-$(CONFIG_BMAC) += bmac.o
+obj-$(CONFIG_GMAC) += gmac.o
+obj-$(CONFIG_NCR885E) += ncr885e.o
+
+obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
+
+obj-$(CONFIG_DGRS) += dgrs.o
+obj-$(CONFIG_RCPCI) += rcpci.o
+obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+obj-$(CONFIG_PCNET32) += pcnet32.o
+obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o
+obj-$(CONFIG_TLAN) += tlan.o
+obj-$(CONFIG_TULIP) += tulip.o
+obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_SIS900) += sis900.o
+obj-$(CONFIG_DM9102) += dmfe.o
+obj-$(CONFIG_YELLOWFIN) += yellowfin.o
+obj-$(CONFIG_ACENIC) += acenic.o
+
+ifeq ($(CONFIG_SK98LIN),y)
+SUB_DIRS += sk98lin
+obj-y += sk98lin/sk98lin.o
+else
+  ifeq ($(CONFIG_SK98LIN),m)
+  MOD_IN_SUB_DIRS += sk98lin
+  endif
+endif
+
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 
+#
+# end link order section
+#
 
 obj-$(CONFIG_AIRONET4500) 	+= aironet4500_core.o
 obj-$(CONFIG_AIRONET4500_NONCS)  += aironet4500_card.o
@@ -126,7 +163,6 @@
 obj-$(CONFIG_ARM_ETHERH) += 8390.o
 obj-$(CONFIG_WD80x3) += wd.o 8390.o
 obj-$(CONFIG_EL2) += 3c503.o 8390.o
-obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_NE2000) += ne.o 8390.o
 obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
 obj-$(CONFIG_HPLAN) += hp.o 8390.o
@@ -138,7 +174,6 @@
 obj-$(CONFIG_ES3210) += es3210.o 8390.o
 obj-$(CONFIG_LNE390) += lne390.o 8390.o
 obj-$(CONFIG_NE3210) += ne3210.o 8390.o
-obj-$(CONFIG_PLIP) += plip.o
 
 # bsd_comp.o is *always* a module, for some documented reason
 # (licensing).
@@ -180,14 +215,8 @@
 obj-$(CONFIG_AT1500) += lance.o
 obj-$(CONFIG_LANCE) += lance.o
 obj-$(CONFIG_SUN3LANCE) += sun3lance.o
-obj-$(CONFIG_PCNET32) += pcnet32.o
 obj-$(CONFIG_DEFXX) += defxx.o
-obj-$(CONFIG_SUNLANCE) += sunlance.o
 obj-$(CONFIG_SGISEEQ) += sgiseeq.o
-obj-$(CONFIG_HAPPYMEAL) += sunhme.o
-obj-$(CONFIG_SUNQE) += sunqe.o
-obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
 obj-$(CONFIG_AT1700) += at1700.o
 obj-$(CONFIG_FMV18X) += fmv18x.o
 obj-$(CONFIG_EL1) += 3c501.o
@@ -197,19 +226,11 @@
 obj-$(CONFIG_ELMC_II) += 3c527.o
 obj-$(CONFIG_EL3) += 3c509.o
 obj-$(CONFIG_3C515) += 3c515.o
-obj-$(CONFIG_VORTEX) += 3c59x.o
 obj-$(CONFIG_EEXPRESS) += eexpress.o
 obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
-obj-$(CONFIG_SIS900) += sis900.o
-obj-$(CONFIG_DM9102) += dmfe.o
-obj-$(CONFIG_YELLOWFIN) += yellowfin.o
-obj-$(CONFIG_ACENIC) += acenic.o
 obj-$(CONFIG_WAVELAN) += wavelan.o
 obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
-obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_ZNET) += znet.o
 obj-$(CONFIG_DEPCA) += depca.o
 obj-$(CONFIG_EWRK3) += ewrk3.o
@@ -223,9 +244,7 @@
 obj-$(CONFIG_APRICOT) += 82596.o
 obj-$(CONFIG_MVME16x_NET) += 82596.o
 obj-$(CONFIG_BVME6000_NET) += 82596.o
-obj-$(CONFIG_DEC_ELCP) += tulip.o
 obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_EPIC100) += epic100.o
 obj-$(CONFIG_ARIADNE2) += ariadne2.o 8390.o
 obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
 obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
@@ -239,26 +258,18 @@
 obj-$(CONFIG_A2065) += a2065.o
 obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
-obj-$(CONFIG_DGRS) += dgrs.o
 obj-$(CONFIG_CS89x0) += cs89x0.o
 obj-$(CONFIG_LTPC) += ltpc.o
 obj-$(CONFIG_COPS) += cops.o
 obj-$(CONFIG_IPDDP) += ipddp.o
-obj-$(CONFIG_RCPCI) += rcpci.o
-obj-$(CONFIG_MACE) += mace.o
 obj-$(CONFIG_MACSONIC) += macsonic.o
 obj-$(CONFIG_MACMACE) += macmace.o
 obj-$(CONFIG_MAC89x0) += mac89x0.o
-obj-$(CONFIG_BMAC) += bmac.o
-obj-$(CONFIG_NCR885E) += ncr885e.o
-obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
-obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
 
 #
 # HIPPI adapters
 #
 
-obj-$(CONFIG_ROADRUNNER) += rrunner.o
 
 # Extract lists of the multi-part drivers.
 # The 'int-*' lists are the intermediate files used to build the multi's.
diff -u --recursive --new-file v2.3.42/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.3.42/linux/drivers/net/Space.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/Space.c	Mon Feb  7 09:53:20 2000
@@ -92,7 +92,6 @@
 extern int apne_probe(struct net_device *);
 extern int bionet_probe(struct net_device *);
 extern int pamsnet_probe(struct net_device *);
-extern int tlan_probe(struct net_device *);
 extern int cs89x0_probe(struct net_device *dev);
 extern int ethertap_probe(struct net_device *dev);
 extern int ether1_probe (struct net_device *dev);
@@ -168,9 +167,6 @@
 struct devprobe eisa_probes[] __initdata = {
 #ifdef CONFIG_DE4X5             /* DEC DE425, DE434, DE435 adapters */
 	{de4x5_probe, 0},
-#endif
-#ifdef CONFIG_TLAN
-	{tlan_probe, 0},
 #endif
 #ifdef CONFIG_ULTRA32 
 	{ultra32_probe, 0},	
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- v2.3.42/linux/drivers/net/ac3200.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/ac3200.c	Thu Feb 10 12:22:03 2000
@@ -326,9 +326,6 @@
 
 static int ac_close_card(struct net_device *dev)
 {
-	dev->start = 0;
-	dev->tbusy = 1;
-
 	if (ei_debug > 1)
 		printk("%s: Shutting down ethercard.\n", dev->name);
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.3.42/linux/drivers/net/acenic.c	Thu Nov 11 20:11:39 1999
+++ linux/drivers/net/acenic.c	Thu Feb 10 12:22:03 2000
@@ -20,11 +20,13 @@
  * Additional work by Pete Wyckoff <wyckoff@ca.sandia.gov> for initial
  * Alpha and trace dump support. The trace dump support has not been
  * integrated yet however.
+ *
+ * Big-endian+Sparc fixes and conversion to new PCI dma mapping
+ * infrastructure by David S. Miller <davem@redhat.com>.
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
@@ -83,10 +85,6 @@
 #define wmb()	mb()
 #endif
 
-#if (LINUX_VERSION_CODE < 0x02030e)
-#define net_device device
-#endif
-
 #include "acenic.h"
 
 /*
@@ -294,8 +292,103 @@
 
 static int probed __initdata = 0;
 
+void ace_free_descriptors(struct net_device *dev)
+{
+	struct ace_private *ap = dev->priv;
+	int size;
+
+	if (ap->rx_std_ring != NULL) {
+		size = (sizeof(struct rx_desc) *
+			(RX_STD_RING_ENTRIES +
+			 RX_JUMBO_RING_ENTRIES +
+			 RX_MINI_RING_ENTRIES +
+			 RX_RETURN_RING_ENTRIES));
+		pci_free_consistent(ap->pdev, size,
+				    ap->rx_std_ring,
+				    ap->rx_ring_base_dma);
+		ap->rx_std_ring = NULL;
+		ap->rx_jumbo_ring = NULL;
+		ap->rx_mini_ring = NULL;
+		ap->rx_return_ring = NULL;
+	}
+	if (ap->evt_ring != NULL) {
+		size = (sizeof(struct event) * EVT_RING_ENTRIES);
+		pci_free_consistent(ap->pdev, size,
+				    ap->evt_ring,
+				    ap->evt_ring_dma);
+		ap->evt_ring = NULL;
+	}
+	if (ap->evt_prd != NULL) {
+		pci_free_consistent(ap->pdev, sizeof(u32),
+				    (void *)ap->evt_prd, ap->evt_prd_dma);
+		ap->evt_prd = NULL;
+	}
+	if (ap->rx_ret_prd != NULL) {
+		pci_free_consistent(ap->pdev, sizeof(u32),
+				    (void *)ap->rx_ret_prd, ap->rx_ret_prd_dma);
+		ap->rx_ret_prd = NULL;
+	}
+	if (ap->tx_csm != NULL) {
+		pci_free_consistent(ap->pdev, sizeof(u32),
+				    (void *)ap->tx_csm, ap->tx_csm_dma);
+		ap->tx_csm = NULL;
+	}
+}
+
+int ace_allocate_descriptors(struct net_device *dev)
+{
+	struct ace_private *ap = dev->priv;
+	int size;
+
+	size = (sizeof(struct rx_desc) *
+		(RX_STD_RING_ENTRIES +
+		 RX_JUMBO_RING_ENTRIES +
+		 RX_MINI_RING_ENTRIES +
+		 RX_RETURN_RING_ENTRIES));
+
+	ap->rx_std_ring = pci_alloc_consistent(ap->pdev, size,
+					       &ap->rx_ring_base_dma);
+	if (ap->rx_std_ring == NULL)
+		goto fail;
+
+	ap->rx_jumbo_ring = ap->rx_std_ring + RX_STD_RING_ENTRIES;
+	ap->rx_mini_ring = ap->rx_jumbo_ring + RX_JUMBO_RING_ENTRIES;
+	ap->rx_return_ring = ap->rx_mini_ring + RX_MINI_RING_ENTRIES;
+
+	size = (sizeof(struct event) * EVT_RING_ENTRIES);
+
+	ap->evt_ring = pci_alloc_consistent(ap->pdev, size,
+					    &ap->evt_ring_dma);
+
+	if (ap->evt_ring == NULL)
+		goto fail;
+
+	ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
+					   &ap->evt_prd_dma);
+	if (ap->evt_prd == NULL)
+		goto fail;
+
+	ap->rx_ret_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
+					      &ap->rx_ret_prd_dma);
+	if (ap->rx_ret_prd == NULL)
+		goto fail;
+
+	ap->tx_csm = pci_alloc_consistent(ap->pdev, sizeof(u32),
+					  &ap->tx_csm_dma);
+	if (ap->tx_csm == NULL)
+		goto fail;
+
+	return 0;
+
+fail:
+	/* Clean up. */
+	ace_free_descriptors(dev);
+	iounmap(ap->regs);
+	unregister_netdev(dev);
+	return 1;
+}
 
-int __init acenic_probe(void)
+static int __init acenic_probe(void)
 {
 	int boards_found = 0;
 	int version_disp;
@@ -380,16 +473,16 @@
 
 		pci_set_master(pdev);
 
+#ifdef __sparc__
+		/* NOTE: Cache line size is in 32-bit word units. */
+		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10);
+#endif
 		/*
 		 * Remap the regs into kernel space - this is abuse of
 		 * dev->base_addr since it was means for I/O port
 		 * addresses but who gives a damn.
 		 */
-#if (LINUX_VERSION_CODE < 0x02030d)
-		dev->base_addr = pdev->base_address[0];
-#else
 		dev->base_addr = pdev->resource[0].start;
-#endif
 
 		ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000);
 		if (!ap->regs){
@@ -442,6 +535,9 @@
 		}
 #endif
 
+		if (ace_allocate_descriptors(dev))
+			continue;
+
 #ifdef MODULE
 		if (ace_init(dev, boards_found))
 			continue;
@@ -470,8 +566,6 @@
 }
 
 
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
 MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver");
 MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
@@ -480,10 +574,9 @@
 MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-#endif
 
 
-int init_module(void)
+static int __init acenic_init_module (void)
 {
 	int cards;
 
@@ -494,7 +587,7 @@
 }
 
 
-void cleanup_module(void)
+static void __exit acenic_cleanup_module (void)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -528,26 +621,46 @@
 		synchronize_irq();
 
 		for (i = 0; i < RX_STD_RING_ENTRIES; i++) {
-			if (ap->skb->rx_std_skbuff[i]) {
+			struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb;
+
+			if (skb) {
+				dma_addr_t mapping;
+
+				mapping = ap->skb->rx_std_skbuff[i].mapping;
+
 				ap->rx_std_ring[i].size = 0;
-				set_aceaddr_bus(&ap->rx_std_ring[i].addr, 0);
-				dev_kfree_skb(ap->skb->rx_std_skbuff[i]);
+				set_aceaddr(&ap->rx_std_ring[i].addr, 0);
+				pci_unmap_single(ap->pdev, mapping,
+						 ACE_STD_BUFSIZE - (2 + 16));
+				dev_kfree_skb(skb);
+				ap->skb->rx_std_skbuff[i].skb = NULL;
 			}
 		}
 		if (ap->version >= 2) {
 			for (i = 0; i < RX_MINI_RING_ENTRIES; i++) {
-				if (ap->skb->rx_mini_skbuff[i]) {
+				struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb;
+
+				if (skb) {
+					dma_addr_t mapping;
+
+					mapping = ap->skb->rx_mini_skbuff[i].mapping;
+
 					ap->rx_mini_ring[i].size = 0;
-					set_aceaddr_bus(&ap->rx_mini_ring[i].addr, 0);
-					dev_kfree_skb(ap->skb->rx_mini_skbuff[i]);
+					set_aceaddr(&ap->rx_mini_ring[i].addr, 0);
+					pci_unmap_single(ap->pdev, mapping,
+							 ACE_MINI_BUFSIZE - (2 + 16));
+					dev_kfree_skb(skb);
 				}
 			}
 		}
 
+		ace_free_descriptors(root_dev);
+
 		iounmap(regs);
 		if(ap->trace_buf)
 			kfree(ap->trace_buf);
-		kfree(ap->info);
+		pci_free_consistent(ap->pdev, sizeof(struct ace_info),
+				    ap->info, ap->info_dma);
 		kfree(ap->skb);
 		free_irq(root_dev->irq, root_dev);
 		unregister_netdev(root_dev);
@@ -556,7 +669,9 @@
 		root_dev = next;
 	}
 }
-#endif
+
+module_init(acenic_init_module);
+module_exit(acenic_cleanup_module);
 
 
 /*
@@ -590,14 +705,8 @@
 	/*
 	 * Don't access any other registes before this point!
 	 */
-#ifdef __BIG_ENDIAN
-	writel(((BYTE_SWAP | WORD_SWAP | CLR_INT) |
-		((BYTE_SWAP | WORD_SWAP | CLR_INT) << 24)),
-	       &regs->HostCtrl);
-#else
 	writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)),
 	       &regs->HostCtrl);
-#endif
 	mb();
 
 	/*
@@ -640,12 +749,8 @@
 	 * value a second time works as well. This is what caused the
 	 * `Firmware not running' problem on the Tigon II.
 	 */
-#ifdef __LITTLE_ENDIAN
 	writel(ACE_BYTE_SWAP_DATA | ACE_WARN | ACE_FATAL |
 	       ACE_WORD_SWAP | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
-#else
-#error "this driver doesn't run on big-endian machines yet!"
-#endif
 
 	mac1 = 0;
 	for(i = 0; i < 4; i++){
@@ -731,19 +836,23 @@
 	 * and the control blocks for the transmit and receive rings
 	 * as they need to be setup once and for all.
 	 */
-	if (!(info = kmalloc(sizeof(struct ace_info), GFP_KERNEL)))
-		return -EAGAIN;
+	info = pci_alloc_consistent(ap->pdev, sizeof(struct ace_info),
+				    &ap->info_dma);
+	if (info == NULL)
+		goto fail;
 
 	/*
 	 * Get the memory for the skb rings.
 	 */
 	if (!(ap->skb = kmalloc(sizeof(struct ace_skb), GFP_KERNEL)))
-		return -EAGAIN;
+		goto fail;
+
+	memset(ap->skb, 0, sizeof(struct ace_skb));
 
 	if (request_irq(dev->irq, ace_interrupt, SA_SHIRQ, ap->name, dev)) {
 		printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
 		       dev->name, dev->irq);
-		return -EAGAIN;
+		goto fail;
 	}
 
 	/*
@@ -754,13 +863,11 @@
 	root_dev = dev;
 
 	ap->info = info;
-	memset(info, 0, sizeof(struct ace_info));
-	memset(ap->skb, 0, sizeof(struct ace_skb));
 
 	ace_load_firmware(dev);
 	ap->fw_running = 0;
 
-	tmp_ptr = virt_to_bus((void *)info);
+	tmp_ptr = (unsigned long) ap->info_dma;
 #if (BITS_PER_LONG == 64)
 	writel(tmp_ptr >> 32, &regs->InfoPtrHi);
 #else
@@ -770,15 +877,15 @@
 
 	memset(ap->evt_ring, 0, EVT_RING_ENTRIES * sizeof(struct event));
 
-	set_aceaddr(&info->evt_ctrl.rngptr, ap->evt_ring);
+	set_aceaddr(&info->evt_ctrl.rngptr, ap->evt_ring_dma);
 	info->evt_ctrl.flags = 0;
 
-	set_aceaddr(&info->evt_prd_ptr, &ap->evt_prd);
-	ap->evt_prd = 0;
+	set_aceaddr(&info->evt_prd_ptr, ap->evt_prd_dma);
+	*(ap->evt_prd) = 0;
 	wmb();
 	writel(0, &regs->EvtCsm);
 
-	set_aceaddr_bus(&info->cmd_ctrl.rngptr, (void *)0x100);
+	set_aceaddr(&info->cmd_ctrl.rngptr, 0x100);
 	info->cmd_ctrl.flags = 0;
 	info->cmd_ctrl.max_len = 0;
 
@@ -788,30 +895,35 @@
 	writel(0, &regs->CmdPrd);
 	writel(0, &regs->CmdCsm);
 
-	set_aceaddr(&info->stats2_ptr, &info->s.stats);
-
-	set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_std_ring);
-	info->rx_std_ctrl.max_len = ACE_STD_MTU + ETH_HLEN + 4;
-	info->rx_std_ctrl.flags = RCB_FLG_TCP_UDP_SUM;
+	tmp_ptr = ap->info_dma;
+	tmp_ptr += (unsigned long) &(((struct ace_info *)0)->s.stats);
+	set_aceaddr(&info->stats2_ptr, (dma_addr_t) tmp_ptr);
+
+	set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
+	info->rx_std_ctrl.max_len = cpu_to_le16(ACE_STD_MTU + ETH_HLEN + 4);
+	info->rx_std_ctrl.flags = cpu_to_le16(RCB_FLG_TCP_UDP_SUM);
 
 	memset(ap->rx_std_ring, 0,
 	       RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
 
 	for (i = 0; i < RX_STD_RING_ENTRIES; i++)
-		ap->rx_std_ring[i].flags = BD_FLG_TCP_UDP_SUM;
+		ap->rx_std_ring[i].flags = cpu_to_le16(BD_FLG_TCP_UDP_SUM);
 
 	ap->rx_std_skbprd = 0;
 	atomic_set(&ap->cur_rx_bufs, 0);
 
-	set_aceaddr(&info->rx_jumbo_ctrl.rngptr, ap->rx_jumbo_ring);
+	set_aceaddr(&info->rx_jumbo_ctrl.rngptr,
+		    (ap->rx_ring_base_dma +
+		     (sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
 	info->rx_jumbo_ctrl.max_len = 0;
-	info->rx_jumbo_ctrl.flags = RCB_FLG_TCP_UDP_SUM;
+	info->rx_jumbo_ctrl.flags = cpu_to_le16(RCB_FLG_TCP_UDP_SUM);
 
 	memset(ap->rx_jumbo_ring, 0,
 	       RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
 
 	for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++)
-		ap->rx_jumbo_ring[i].flags = BD_FLG_TCP_UDP_SUM | BD_FLG_JUMBO;
+		ap->rx_jumbo_ring[i].flags =
+			cpu_to_le16(BD_FLG_TCP_UDP_SUM | BD_FLG_JUMBO);
 
 	ap->rx_jumbo_skbprd = 0;
 	atomic_set(&ap->cur_jumbo_bufs, 0);
@@ -820,30 +932,40 @@
 	       RX_MINI_RING_ENTRIES * sizeof(struct rx_desc));
 
 	if (ap->version >= 2) {
-		set_aceaddr(&info->rx_mini_ctrl.rngptr, ap->rx_mini_ring);
-		info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
-		info->rx_mini_ctrl.flags = RCB_FLG_TCP_UDP_SUM;
+		set_aceaddr(&info->rx_mini_ctrl.rngptr,
+			    (ap->rx_ring_base_dma +
+			     (sizeof(struct rx_desc) *
+			      (RX_STD_RING_ENTRIES +
+			       RX_JUMBO_RING_ENTRIES))));
+		info->rx_mini_ctrl.max_len = cpu_to_le16(ACE_MINI_SIZE);
+		info->rx_mini_ctrl.flags = cpu_to_le16(RCB_FLG_TCP_UDP_SUM);
 
 		for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
 			ap->rx_mini_ring[i].flags =
-				BD_FLG_TCP_UDP_SUM | BD_FLG_MINI;
+				cpu_to_le16(BD_FLG_TCP_UDP_SUM | BD_FLG_MINI);
 	} else {
 		set_aceaddr(&info->rx_mini_ctrl.rngptr, 0);
-		info->rx_mini_ctrl.flags = RCB_FLG_RNG_DISABLE;
+		info->rx_mini_ctrl.flags = cpu_to_le16(RCB_FLG_RNG_DISABLE);
 		info->rx_mini_ctrl.max_len = 0;
 	}
 
 	ap->rx_mini_skbprd = 0;
 	atomic_set(&ap->cur_mini_bufs, 0);
 
-	set_aceaddr(&info->rx_return_ctrl.rngptr, ap->rx_return_ring);
+	set_aceaddr(&info->rx_return_ctrl.rngptr,
+		    (ap->rx_ring_base_dma +
+		     (sizeof(struct rx_desc) *
+		      (RX_STD_RING_ENTRIES +
+		       RX_JUMBO_RING_ENTRIES +
+		       RX_MINI_RING_ENTRIES))));
 	info->rx_return_ctrl.flags = 0;
-	info->rx_return_ctrl.max_len = RX_RETURN_RING_ENTRIES;
+	info->rx_return_ctrl.max_len = cpu_to_le16(RX_RETURN_RING_ENTRIES);
 
 	memset(ap->rx_return_ring, 0,
 	       RX_RETURN_RING_ENTRIES * sizeof(struct rx_desc));
 
-	set_aceaddr(&info->rx_ret_prd_ptr, &ap->rx_ret_prd);
+	set_aceaddr(&info->rx_ret_prd_ptr, ap->rx_ret_prd_dma);
+	*(ap->rx_ret_prd) = 0;
 
 	writel(TX_RING_BASE, &regs->WinBase);
 	ap->tx_ring = (struct tx_desc *)regs->Window;
@@ -851,15 +973,15 @@
 		writel(0, (unsigned long)ap->tx_ring + i * 4);
 	}
 
-	set_aceaddr_bus(&info->tx_ctrl.rngptr, (void *)TX_RING_BASE);
-	info->tx_ctrl.max_len = TX_RING_ENTRIES;
+	set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE);
+	info->tx_ctrl.max_len = cpu_to_le16(TX_RING_ENTRIES);
 #if TX_COAL_INTS_ONLY
-	info->tx_ctrl.flags = RCB_FLG_COAL_INT_ONLY;
+	info->tx_ctrl.flags = cpu_to_le16(RCB_FLG_COAL_INT_ONLY);
 #else
 	info->tx_ctrl.flags = 0;
 #endif
 
-	set_aceaddr(&info->tx_csm_ptr, &ap->tx_csm);
+	set_aceaddr(&info->tx_csm_ptr, ap->tx_csm_dma);
 
 	/*
 	 * Potential item for tuning parameter
@@ -975,7 +1097,7 @@
 	 */
 	ap->tx_full = 0;
 	ap->cur_rx = 0;
-	ap->tx_prd = ap->tx_csm = ap->tx_ret_csm = 0;
+	ap->tx_prd = *(ap->tx_csm) = ap->tx_ret_csm = 0;
 
 	wmb();
 	writel(0, &regs->TxPrd);
@@ -1015,6 +1137,17 @@
 			       "the RX mini ring\n", dev->name);
 	}
 	return 0;
+
+fail:
+	if (info != NULL)
+		pci_free_consistent(ap->pdev, sizeof(struct ace_info),
+				    info, ap->info_dma);
+	if (ap->skb != NULL) {
+		kfree(ap->skb);
+		ap->skb = NULL;
+	}
+
+	return -EAGAIN;
 }
 
 
@@ -1032,7 +1165,7 @@
 	 * seconds and there is data in the transmit queue, thus we
 	 * asume the card is stuck.
 	 */
-	if (ap->tx_csm != ap->tx_ret_csm){
+	if (le32_to_cpu(*(ap->tx_csm)) != ap->tx_ret_csm){
 		printk(KERN_WARNING "%s: Transmitter is stuck, %08x\n",
 		       dev->name, (unsigned int)readl(&regs->HostCtrl));
 	}
@@ -1112,18 +1245,22 @@
 	for (i = 0; i < nr_bufs; i++) {
 		struct sk_buff *skb;
 		struct rx_desc *rd;
+		dma_addr_t mapping;
 
 		skb = alloc_skb(ACE_STD_BUFSIZE, GFP_ATOMIC);
 		/*
 		 * Make sure IP header starts on a fresh cache line.
 		 */
 		skb_reserve(skb, 2 + 16);
-		ap->skb->rx_std_skbuff[idx] = skb;
+		mapping = pci_map_single(ap->pdev, skb->data,
+					 ACE_STD_BUFSIZE - (2 + 16));
+		ap->skb->rx_std_skbuff[idx].skb = skb;
+		ap->skb->rx_std_skbuff[idx].mapping = mapping;
 
 		rd = &ap->rx_std_ring[idx];
-		set_aceaddr(&rd->addr, skb->data);
-		rd->size = ACE_STD_MTU + ETH_HLEN + 4;
-		rd->idx = idx;
+		set_aceaddr(&rd->addr, mapping);
+		rd->size = cpu_to_le16(ACE_STD_MTU + ETH_HLEN + 4);
+		rd->idx = cpu_to_le16(idx);
 		idx = (idx + 1) % RX_STD_RING_ENTRIES;
 	}
 
@@ -1157,18 +1294,22 @@
 	for (i = 0; i < nr_bufs; i++) {
 		struct sk_buff *skb;
 		struct rx_desc *rd;
+		dma_addr_t mapping;
 
 		skb = alloc_skb(ACE_MINI_BUFSIZE, GFP_ATOMIC);
 		/*
 		 * Make sure the IP header ends up on a fresh cache line
 		 */
 		skb_reserve(skb, 2 + 16);
-		ap->skb->rx_mini_skbuff[idx] = skb;
+		mapping = pci_map_single(ap->pdev, skb->data,
+					 ACE_MINI_BUFSIZE - (2 + 16));
+		ap->skb->rx_mini_skbuff[idx].skb = skb;
+		ap->skb->rx_mini_skbuff[idx].mapping = mapping;
 
 		rd = &ap->rx_mini_ring[idx];
-		set_aceaddr(&rd->addr, skb->data);
-		rd->size = ACE_MINI_SIZE;
-		rd->idx = idx;
+		set_aceaddr(&rd->addr, mapping);
+		rd->size = cpu_to_le16(ACE_MINI_SIZE);
+		rd->idx = cpu_to_le16(idx);
 		idx = (idx + 1) % RX_MINI_RING_ENTRIES;
 	}
 
@@ -1200,18 +1341,22 @@
 	for (i = 0; i < nr_bufs; i++) {
 		struct sk_buff *skb;
 		struct rx_desc *rd;
+		dma_addr_t mapping;
 
 		skb = alloc_skb(ACE_JUMBO_BUFSIZE, GFP_ATOMIC);
 		/*
 		 * Make sure the IP header ends up on a fresh cache line
 		 */
 		skb_reserve(skb, 2 + 16);
-		ap->skb->rx_jumbo_skbuff[idx] = skb;
+		mapping = pci_map_single(ap->pdev, skb->data,
+					 ACE_JUMBO_BUFSIZE - (2 + 16));
+		ap->skb->rx_jumbo_skbuff[idx].skb = skb;
+		ap->skb->rx_jumbo_skbuff[idx].mapping = mapping;
 
 		rd = &ap->rx_jumbo_ring[idx];
-		set_aceaddr(&rd->addr, skb->data);
-		rd->size = ACE_JUMBO_MTU + ETH_HLEN + 4;
-		rd->idx = idx;
+		set_aceaddr(&rd->addr, mapping);
+		rd->size = cpu_to_le16(ACE_JUMBO_MTU + ETH_HLEN + 4);
+		rd->idx = cpu_to_le16(idx);
 		idx = (idx + 1) % RX_JUMBO_RING_ENTRIES;
 	}
 
@@ -1254,10 +1399,20 @@
 		ace_issue_cmd(regs, &cmd);
 
 		for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
-			if (ap->skb->rx_jumbo_skbuff[i]) {
+			struct sk_buff *skb;
+
+			skb = ap->skb->rx_jumbo_skbuff[i].skb;
+			if (skb) {
+				dma_addr_t mapping;
+
+				mapping = ap->skb->rx_jumbo_skbuff[i].mapping;
+
 				ap->rx_jumbo_ring[i].size = 0;
-				set_aceaddr_bus(&ap->rx_jumbo_ring[i].addr, 0);
-				dev_kfree_skb(ap->skb->rx_jumbo_skbuff[i]);
+				set_aceaddr(&ap->rx_jumbo_ring[i].addr, 0);
+				pci_unmap_single(ap->pdev, mapping,
+						 ACE_JUMBO_BUFSIZE - (2 + 16));
+				dev_kfree_skb(skb);
+				ap->skb->rx_jumbo_skbuff[i].skb = NULL;
 			}
 		}
 	}else
@@ -1280,7 +1435,11 @@
 	ap = (struct ace_private *)dev->priv;
 
 	while (evtcsm != evtprd){
-		switch (ap->evt_ring[evtcsm].evt){
+		struct event evt_local;
+
+		memcpy(&evt_local, &ap->evt_ring[evtcsm], sizeof(evt_local));
+		evt_local.u.word = le32_to_cpu(evt_local.u.word);
+		switch (evt_local.u.data.evt){
 		case E_FW_RUNNING:
 			printk(KERN_INFO "%s: Firmware up and running\n",
 			       dev->name);
@@ -1290,7 +1449,7 @@
 			break;
 		case E_LNK_STATE:
 		{
-			u16 code = ap->evt_ring[evtcsm].code;
+			u16 code = evt_local.u.data.code;
 			if (code == E_C_LINK_UP){
 				printk(KERN_WARNING "%s: Optical link UP\n",
 				       dev->name);
@@ -1304,7 +1463,7 @@
 			break;
 		}
 		case E_ERROR:
-			switch(ap->evt_ring[evtcsm].code){
+			switch(evt_local.u.data.code){
 			case E_C_ERR_INVAL_CMD:
 				printk(KERN_ERR "%s: invalid command error\n",
 				       dev->name);
@@ -1319,14 +1478,14 @@
 				break;
 			default:
 				printk(KERN_ERR "%s: unknown error %02x\n",
-				       dev->name, ap->evt_ring[evtcsm].code);
+				       dev->name, evt_local.u.data.code);
 			}
 			break;
 		case E_RESET_JUMBO_RNG:
 			break;
 		default:
 			printk(KERN_ERR "%s: Unhandled event 0x%02x\n",
-			       dev->name, ap->evt_ring[evtcsm].evt);
+			       dev->name, evt_local.u.data.evt);
 		}
 		evtcsm = (evtcsm + 1) % EVT_RING_ENTRIES;
 	}
@@ -1344,14 +1503,16 @@
 	idx = rxretcsm;
 
 	while (idx != rxretprd){
-		struct sk_buff *skb, **oldskb_p;
+		struct ring_info *rip;
+		struct sk_buff *skb;
 		struct rx_desc *rxdesc;
+		dma_addr_t mapping;
 		u32 skbidx;
-		int desc_type;
+		int desc_type, mapsize;
 		u16 csum;
 
-		skbidx = ap->rx_return_ring[idx].idx;
-		desc_type = ap->rx_return_ring[idx].flags &
+		skbidx = le16_to_cpu(ap->rx_return_ring[idx].idx);
+		desc_type = le16_to_cpu(ap->rx_return_ring[idx].flags) &
 			(BD_FLG_JUMBO | BD_FLG_MINI);
 
 		switch(desc_type) {
@@ -1363,42 +1524,47 @@
 			 * atomic operations for each packet arriving.
 			 */
 		case 0:
-			oldskb_p = &ap->skb->rx_std_skbuff[skbidx];
+			rip = &ap->skb->rx_std_skbuff[skbidx];
+			mapsize = ACE_STD_BUFSIZE - (2 + 16);
 			rxdesc = &ap->rx_std_ring[skbidx];
 			std_count++;
 			break;
 		case BD_FLG_JUMBO:
-			oldskb_p = &ap->skb->rx_jumbo_skbuff[skbidx];
+			rip = &ap->skb->rx_jumbo_skbuff[skbidx];
+			mapsize = ACE_JUMBO_BUFSIZE - (2 + 16);
 			rxdesc = &ap->rx_jumbo_ring[skbidx];
 			atomic_dec(&ap->cur_jumbo_bufs);
 			break;
 		case BD_FLG_MINI:
-			oldskb_p = &ap->skb->rx_mini_skbuff[skbidx];
+			rip = &ap->skb->rx_mini_skbuff[skbidx];
+			mapsize = ACE_MINI_BUFSIZE - (2 + 16);
 			rxdesc = &ap->rx_mini_ring[skbidx];
 			mini_count++; 
 			break;
 		default:
 			printk(KERN_INFO "%s: unknown frame type (0x%02x) "
 			       "returned by NIC\n", dev->name,
-			       ap->rx_return_ring[idx].flags);
+			       le16_to_cpu(ap->rx_return_ring[idx].flags));
 			goto error;
 		}
 
-		skb = *oldskb_p;
+		skb = rip->skb;
+		mapping = rip->mapping;
 #if DEBUG
 		if (skb == NULL) {
 			printk("Mayday! illegal skb received! (idx %i)\n", skbidx);
 			goto error;
 		}
 #endif
-		*oldskb_p = NULL;
-		skb_put(skb, rxdesc->size);
+		rip->skb = NULL;
+		pci_unmap_single(ap->pdev, mapping, mapsize);
+		skb_put(skb, le16_to_cpu(rxdesc->size));
 		rxdesc->size = 0;
 
 		/*
 		 * Fly baby, fly!
 		 */
-		csum = ap->rx_return_ring[idx].tcp_udp_csum;
+		csum = le16_to_cpu(ap->rx_return_ring[idx].tcp_udp_csum);
 
 		skb->dev = dev;
 		skb->protocol = eth_type_trans(skb, dev);
@@ -1476,22 +1642,30 @@
 	 * working on the other stuff - hey we don't need a spin lock
 	 * anymore.
 	 */
-	rxretprd = ap->rx_ret_prd;
+	rxretprd = le32_to_cpu(*(ap->rx_ret_prd));
 	rxretcsm = ap->cur_rx;
 
 	if (rxretprd != rxretcsm)
 		ace_rx_int(dev, rxretprd, rxretcsm);
 
-	txcsm = ap->tx_csm;
+	txcsm = le32_to_cpu(*(ap->tx_csm));
 	idx = ap->tx_ret_csm;
 
 	if (txcsm != idx) {
 		do {
+			struct sk_buff *skb;
+			dma_addr_t mapping;
+
+			skb = ap->skb->tx_skbuff[idx].skb;
+			mapping = ap->skb->tx_skbuff[idx].mapping;
+
 			ap->stats.tx_packets++;
-			ap->stats.tx_bytes += ap->skb->tx_skbuff[idx]->len;
-			dev_kfree_skb(ap->skb->tx_skbuff[idx]);
+			ap->stats.tx_bytes += skb->len;
+
+			pci_unmap_single(ap->pdev, mapping, skb->len);
+			dev_kfree_skb(skb);
 
-			ap->skb->tx_skbuff[idx] = NULL;
+			ap->skb->tx_skbuff[idx].skb = NULL;
 
 			/*
 			 * Question here is whether one should not skip
@@ -1514,14 +1688,14 @@
 		 * Ie. skip the comparison of the tx producer vs. the
 		 * consumer.
 		 */
-		if (ap->tx_full && dev->tbusy) {
+		if (ap->tx_full &&
+		    test_bit(LINK_STATE_XOFF, &dev->state)) {
 			ap->tx_full = 0;
 			/*
 			 * This does not need to be atomic (and expensive),
 			 * I've seen cases where it would fail otherwise ;-(
 			 */
-			clear_bit(0, &dev->tbusy);
-			mark_bh(NET_BH);
+			netif_wake_queue(dev);
 
 			/*
 			 * TX ring is no longer full, aka the
@@ -1535,7 +1709,7 @@
 	}
 
 	evtcsm = readl(&regs->EvtCsm);
-	evtprd = ap->evt_prd;
+	evtprd = le32_to_cpu(*(ap->evt_prd));
 
 	if (evtcsm != evtprd) {
 		evtcsm = ace_handle_event(dev, evtcsm, evtprd);
@@ -1546,7 +1720,7 @@
 	 * This has to go last in the interrupt handler and run with
 	 * the spin lock released ... what lock?
 	 */
-	if (dev->start) {
+	if (test_bit(LINK_STATE_START, &dev->state)) {
 		int cur_size;
 		int run_bh = 0;
 
@@ -1651,10 +1825,6 @@
 	ace_issue_cmd(regs, &cmd);
 #endif
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
 	MOD_INC_USE_COUNT;
 
 	/*
@@ -1684,8 +1854,7 @@
 	unsigned long flags;
 	short i;
 
-	dev->start = 0;
-	set_bit(0, &dev->tbusy);
+	netif_stop_queue(dev);
 
 	ap = (struct ace_private *)dev->priv;
 	regs = ap->regs;
@@ -1713,11 +1882,17 @@
 	cli();
 
 	for (i = 0; i < TX_RING_ENTRIES; i++) {
-		if (ap->skb->tx_skbuff[i]) {
+		struct sk_buff *skb;
+		dma_addr_t mapping;
+
+		skb = ap->skb->tx_skbuff[i].skb;
+		mapping = ap->skb->tx_skbuff[i].mapping;
+		if (skb) {
 			writel(0, &ap->tx_ring[i].addr.addrhi);
 			writel(0, &ap->tx_ring[i].addr.addrlo);
 			writel(0, &ap->tx_ring[i].flagsize);
-			dev_kfree_skb(ap->skb->tx_skbuff[i]);
+			pci_unmap_single(ap->pdev, mapping, skb->len);
+			dev_kfree_skb(skb);
 		}
 	}
 
@@ -1738,9 +1913,6 @@
 	unsigned long addr;
 	u32 idx, flagsize;
 
-	if (test_and_set_bit(0, &dev->tbusy))
-		return 1;
-
 	idx = ap->tx_prd;
 
 	if ((idx + 1) % TX_RING_ENTRIES == ap->tx_ret_csm) {
@@ -1752,8 +1924,10 @@
 		return 1;
 	}
 
-	ap->skb->tx_skbuff[idx] = skb;
-	addr = virt_to_bus(skb->data);
+	ap->skb->tx_skbuff[idx].skb = skb;
+	ap->skb->tx_skbuff[idx].mapping =
+		pci_map_single(ap->pdev, skb->data, skb->len);
+	addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping;
 #if (BITS_PER_LONG == 64)
 	writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi);
 #endif
@@ -1784,7 +1958,7 @@
 		/*
 		 * No need for it to be atomic - seems it needs to be
 		 */
-		clear_bit(0, &dev->tbusy);
+		netif_stop_queue(dev);
 	}
 
 	dev->trans_start = jiffies;
@@ -1956,7 +2130,7 @@
 	u16 *da;
 	struct cmd cmd;
 
-	if(dev->start)
+	if(test_bit(LINK_STATE_START, &dev->state))
 		return -EBUSY;
 
 	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
@@ -2038,11 +2212,11 @@
 }
 
 
-void __init ace_copy(struct ace_regs *regs, void *src, u32 dest, int size)
+void __init ace_copy(struct ace_regs *regs, void *src, unsigned long dest, int size)
 {
 	unsigned long tdest;
 	u32 *wsrc;
-	short tsize, i;
+	unsigned long tsize, i;
 
 	if (size <= 0)
 		return;
@@ -2053,14 +2227,10 @@
 		tdest = (unsigned long)&regs->Window +
 			(dest & (ACE_WINDOW_SIZE - 1));
 		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
-#ifdef __BIG_ENDIAN
-#error "data must be swapped here"
-#else
 		wsrc = src;
 		for (i = 0; i < (tsize / 4); i++){
 			writel(wsrc[i], tdest + i*4);
 		}
-#endif
 		dest += tsize;
 		src += tsize;
 		size -= tsize;
@@ -2070,10 +2240,10 @@
 }
 
 
-void __init ace_clear(struct ace_regs *regs, u32 dest, int size)
+void __init ace_clear(struct ace_regs *regs, unsigned long dest, int size)
 {
 	unsigned long tdest;
-	short tsize = 0, i;
+	unsigned long tsize = 0, i;
 
 	if (size <= 0)
 		return;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/acenic.h linux/drivers/net/acenic.h
--- v2.3.42/linux/drivers/net/acenic.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/net/acenic.h	Tue Feb  8 18:58:25 2000
@@ -24,60 +24,19 @@
 } aceaddr;
 
 
-static inline void set_aceaddr(aceaddr *aa, volatile void *addr)
+static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
 {
-	unsigned long baddr = virt_to_bus((void *)addr);
+	unsigned long baddr = (unsigned long) addr;
 #if (BITS_PER_LONG == 64)
-	aa->addrlo = baddr & 0xffffffff;
-	aa->addrhi = baddr >> 32;
+	aa->addrlo = cpu_to_le32(baddr & 0xffffffff);
+	aa->addrhi = cpu_to_le32(baddr >> 32);
 #else
     /* Don't bother setting zero every time */
-	aa->addrlo = baddr;
+	aa->addrlo = cpu_to_le32(baddr);
 #endif
 	mb();
 }
 
-
-static inline void set_aceaddr_bus(aceaddr *aa, volatile void *addr)
-{
-	unsigned long baddr = (unsigned long)addr;
-#if (BITS_PER_LONG == 64)
-	aa->addrlo = baddr & 0xffffffff;
-	aa->addrhi = baddr >> 32;
-#else
-    /* Don't bother setting zero every time */
-	aa->addrlo = baddr;
-#endif
-	mb();
-}
-
-
-static inline void *get_aceaddr(aceaddr *aa)
-{
-	unsigned long addr;
-	mb();
-#if (BITS_PER_LONG == 64)
-	addr = (u64)aa->addrhi << 32 | aa->addrlo;
-#else
-	addr = aa->addrlo;
-#endif
-	return bus_to_virt(addr);
-}
-
-
-static inline void *get_aceaddr_bus(aceaddr *aa)
-{
-	unsigned long addr;
-	mb();
-#if (BITS_PER_LONG == 64)
-	addr = (u64)aa->addrhi << 32 | aa->addrlo;
-#else
-	addr = aa->addrlo;
-#endif
-	return (void *)addr;
-}
-
-
 struct ace_regs {
 	u32	pad0[16];	/* PCI control registers */
 
@@ -341,15 +300,20 @@
 #define EVT_RING_SIZE	(EVT_RING_ENTRIES * sizeof(struct event))
 
 struct event {
-#ifdef __LITTLE_ENDIAN
-	u32	idx:12;
-	u32	code:12;
-	u32	evt:8;
-#else
-	u32	evt:8;
-	u32	code:12;
-	u32	idx:12;
+	union {
+		u32 word;
+		struct {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+			u32	idx:12;
+			u32	code:12;
+			u32	evt:8;
+#else
+			u32	evt:8;
+			u32	code:12;
+			u32	idx:12;
 #endif
+		} data;
+	} u;
 	u32     pad;
 };
 
@@ -387,7 +351,7 @@
 #define CMD_RING_ENTRIES	64
 
 struct cmd {
-#ifdef __LITTLE_ENDIAN
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 	u32	idx:12;
 	u32	code:12;
 	u32	evt:8;
@@ -471,17 +435,10 @@
  * This is in PCI shared mem and must be accessed with readl/writel
  * real layout is:
  */
-#if __LITTLE_ENDIAN
 	u16	flags;
 	u16	size;
 	u16	vlan;
 	u16	reserved;
-#else
-	u16	size;
-	u16	flags;
-	u16	reserved;
-	u16	vlan;
-#endif
 #endif
 	u32	vlanres;
 };
@@ -502,34 +459,14 @@
 
 struct rx_desc{
 	aceaddr	addr;
-#ifdef __LITTLE_ENDIAN
 	u16	size;
 	u16	idx;
-#else
-	u16	idx;
-	u16	size;
-#endif
-#ifdef __LITTLE_ENDIAN
 	u16	flags;
 	u16	type;
-#else
-	u16	type;
-	u16	flags;
-#endif
-#ifdef __LITTLE_ENDIAN
 	u16	tcp_udp_csum;
 	u16	ip_csum;
-#else
-	u16	ip_csum;
-	u16	tcp_udp_csum;
-#endif
-#ifdef __LITTLE_ENDIAN
 	u16	vlan;
 	u16	err_flags;
-#else
-	u16	err_flags;
-	u16	vlan;
-#endif
 	u32	reserved;
 	u32	opague;
 };
@@ -540,13 +477,8 @@
  */
 struct ring_ctrl {
 	aceaddr	rngptr;
-#ifdef __LITTLE_ENDIAN
 	u16	flags;
 	u16	max_len;
-#else
-	u16	max_len;
-	u16	flags;
-#endif
 	u32	pad;
 };
 
@@ -608,12 +540,17 @@
  * pointers, but I don't see any other smart mode to do this in an
  * efficient manner ;-(
  */
+struct ring_info {
+	struct sk_buff		*skb;
+	dma_addr_t		mapping;
+};
+
 struct ace_skb
 {
-	struct sk_buff		*tx_skbuff[TX_RING_ENTRIES];
-	struct sk_buff		*rx_std_skbuff[RX_STD_RING_ENTRIES];
-	struct sk_buff		*rx_mini_skbuff[RX_MINI_RING_ENTRIES];
-	struct sk_buff		*rx_jumbo_skbuff[RX_JUMBO_RING_ENTRIES];
+	struct ring_info	tx_skbuff[TX_RING_ENTRIES];
+	struct ring_info	rx_std_skbuff[RX_STD_RING_ENTRIES];
+	struct ring_info	rx_mini_skbuff[RX_MINI_RING_ENTRIES];
+	struct ring_info	rx_jumbo_skbuff[RX_JUMBO_RING_ENTRIES];
 };
 
 
@@ -631,12 +568,14 @@
 {
 	struct ace_skb		*skb;
 	struct ace_regs		*regs;		/* register base */
-	int			version, fw_running, fw_up, link;
+	volatile int		fw_running;
+	int			version, fw_up, link;
 	int			promisc, mcast_all;
 	/*
 	 * The send ring is located in the shared memory window
 	 */
 	struct ace_info		*info;
+	dma_addr_t		info_dma;
 	struct tx_desc		*tx_ring;
 	u32			tx_prd, tx_full, tx_ret_csm;
 	struct timer_list	timer;
@@ -651,18 +590,22 @@
 	u32			cur_rx;
 	struct tq_struct	immediate;
 	int			bh_pending, jumbo;
-	struct rx_desc		rx_std_ring[RX_STD_RING_ENTRIES]
-				__attribute__ ((aligned (L1_CACHE_BYTES)));
-	struct rx_desc		rx_jumbo_ring[RX_JUMBO_RING_ENTRIES];
-	struct rx_desc		rx_mini_ring[RX_MINI_RING_ENTRIES];
-	struct rx_desc		rx_return_ring[RX_RETURN_RING_ENTRIES];
-	struct event		evt_ring[EVT_RING_ENTRIES];
-	volatile u32		evt_prd
-				__attribute__ ((aligned (L1_CACHE_BYTES)));
-	volatile u32		rx_ret_prd
-				__attribute__ ((aligned (L1_CACHE_BYTES)));
-	volatile u32		tx_csm
-				__attribute__ ((aligned (L1_CACHE_BYTES)));
+
+	/* These elements are allocated using consistent PCI
+	 * dma memory.
+	 */
+	struct rx_desc		*rx_std_ring;
+	struct rx_desc		*rx_jumbo_ring;
+	struct rx_desc		*rx_mini_ring;
+	struct rx_desc		*rx_return_ring;
+	dma_addr_t		rx_ring_base_dma;
+
+	struct event		*evt_ring;
+	dma_addr_t		evt_ring_dma;
+
+	volatile u32		*evt_prd, *rx_ret_prd, *tx_csm;
+	dma_addr_t		evt_prd_dma, rx_ret_prd_dma, tx_csm_dma;
+
 	unsigned char		*trace_buf;
 	struct pci_dev		*pdev;
 	struct net_device	*next;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.3.42/linux/drivers/net/bmac.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/bmac.c	Thu Feb 10 12:22:03 2000
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 #include <asm/prom.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
@@ -1256,7 +1257,7 @@
 	return 1;
 }
 
-int bmac_probe(void)
+static int __init bmac_probe (void)
 {
 	int j, rev;
 	struct bmac_data *bp;
@@ -1265,6 +1266,11 @@
 	static struct device_node *all_bmacs = NULL, *next_bmac;
 	struct net_device *dev = NULL;
 
+#ifdef MODULE
+	if(bmac_devs != NULL)
+		return -EBUSY;
+#endif
+
 	if (all_bmacs == NULL) {
 		all_bmacs = find_devices("bmac");
 		is_bmac_plus = 0;
@@ -1593,23 +1599,14 @@
 	return len;
 }
 
-#ifdef MODULE
 
 MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
 MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
 
-int init_module(void)
-{
-    int res;
-   
-    if(bmac_devs != NULL)
-        return -EBUSY;
-    res = bmac_probe();
-    return res;
-}
 
-void cleanup_module(void)
+static void __exit bmac_cleanup (void)
 {
+#ifdef MODULE
     struct bmac_data *bp;
 
     if (bmac_devs == 0)
@@ -1628,6 +1625,8 @@
 #endif
     kfree(bmac_devs);
     bmac_devs = NULL;
+#endif
 }
 
-#endif
+module_init(bmac_probe);
+module_exit(bmac_cleanup);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.3.42/linux/drivers/net/de4x5.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/net/de4x5.c	Thu Feb 10 12:22:03 2000
@@ -766,8 +766,8 @@
 struct de4x5_private {
     char adapter_name[80];                  /* Adapter name                 */
     u_long interrupt;                       /* Aligned ISR flag             */
-    struct de4x5_desc rx_ring[NUM_RX_DESC]; /* RX descriptor ring           */
-    struct de4x5_desc tx_ring[NUM_TX_DESC]; /* TX descriptor ring           */
+    struct de4x5_desc *rx_ring;		    /* RX descriptor ring           */
+    struct de4x5_desc *tx_ring;		    /* TX descriptor ring           */
     struct sk_buff *tx_skb[NUM_TX_DESC];    /* TX skb for freeing when sent */
     struct sk_buff *rx_skb[NUM_RX_DESC];    /* RX skb's                     */
     int rx_new, rx_old;                     /* RX descriptor ring pointers  */
@@ -815,7 +815,6 @@
     int tmp;                                /* Temporary global per card    */
     struct {
 	void *priv;                         /* Original kmalloc'd mem addr  */
-	void *buf;                          /* Original kmalloc'd mem addr  */
 	u_long lock;                        /* Lock the cache accesses      */
 	s32 csr0;                           /* Saved Bus Mode Register      */
 	s32 csr6;                           /* Saved Operating Mode Reg.    */
@@ -846,6 +845,10 @@
     u_char *rst;                            /* Pointer to Type 5 reset info */
     u_char  ibn;                            /* Infoblock number             */
     struct parameters params;               /* Command line/ #defined params */
+    struct pci_dev *pdev;		    /* Device cookie for DMA alloc  */
+    dma_addr_t dma_rings;		    /* DMA handle for rings	    */
+    int dma_size;			    /* Size of the DMA area	    */
+    char *rx_bufs;			    /* rx bufs on alpha, sparc, ... */
 };
 
 /*
@@ -910,7 +913,7 @@
 /*
 ** Private functions
 */
-static int     de4x5_hw_init(struct net_device *dev, u_long iobase);
+static int     de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev);
 static int     de4x5_init(struct net_device *dev);
 static int     de4x5_sw_reset(struct net_device *dev);
 static int     de4x5_rx(struct net_device *dev);
@@ -1125,7 +1128,7 @@
 }
 
 static int __init 
-de4x5_hw_init(struct net_device *dev, u_long iobase)
+de4x5_hw_init(struct net_device *dev, u_long iobase, struct pci_dev *pdev)
 {
     struct bus_type *lp = &bus;
     int i, status=0;
@@ -1210,6 +1213,7 @@
 	lp->asBitValid = TRUE;
 	lp->timeout = -1;
 	lp->useSROM = useSROM;
+	lp->pdev = pdev;
 	memcpy((char *)&lp->srom,(char *)&bus.srom,sizeof(struct de4x5_srom));
 	lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	de4x5_parse_params(dev);
@@ -1228,7 +1232,20 @@
         }
 	lp->fdx = lp->params.fdx;
 	sprintf(lp->adapter_name,"%s (%s)", name, dev->name);
-	
+
+	lp->dma_size = (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc);
+#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc_v9__) || defined(DE4X5_DO_MEMCPY)
+	lp->dma_size += RX_BUFF_SZ * NUM_RX_DESC + ALIGN;
+#endif
+	lp->rx_ring = pci_alloc_consistent(pdev, lp->dma_size, &lp->dma_rings);
+	if (lp->rx_ring == NULL) {
+	    kfree(lp->cache.priv);
+	    lp->cache.priv = NULL;
+	    return -ENOMEM;
+	}
+
+	lp->tx_ring = lp->rx_ring + NUM_RX_DESC;
+	    
 	/*
 	** Set up the RX descriptor ring (Intels)
 	** Allocate contiguous receive buffers, long word aligned (Alphas) 
@@ -1236,28 +1253,30 @@
 #if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY)
 	for (i=0; i<NUM_RX_DESC; i++) {
 	    lp->rx_ring[i].status = 0;
-	    lp->rx_ring[i].des1 = RX_BUFF_SZ;
+	    lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
 	    lp->rx_ring[i].buf = 0;
 	    lp->rx_ring[i].next = 0;
 	    lp->rx_skb[i] = (struct sk_buff *) 1;     /* Dummy entry */
 	}
 
 #else
-	if ((tmp = (void *)kmalloc(RX_BUFF_SZ * NUM_RX_DESC + ALIGN, 
-				   GFP_KERNEL)) == NULL) {
-	    kfree(lp->cache.priv);
-	    lp->cache.priv = NULL;
-	    return -ENOMEM;
-	}
+	{
+		dma_addr_t dma_rx_bufs;
+
+		dma_rx_bufs = lp->dma_rings + (NUM_RX_DESC + NUM_TX_DESC)
+		      	* sizeof(struct de4x5_desc);
+		dma_rx_bufs = (dma_rx_bufs + ALIGN) & ~ALIGN;
+		lp->rx_bufs = (char *)(((long)(lp->rx_ring + NUM_RX_DESC
+		      	+ NUM_TX_DESC) + ALIGN) & ~ALIGN);
+		for (i=0; i<NUM_RX_DESC; i++) {
+	    		lp->rx_ring[i].status = 0;
+	    		lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
+	    		lp->rx_ring[i].buf =
+				cpu_to_le32(dma_rx_bufs+i*RX_BUFF_SZ);
+	    		lp->rx_ring[i].next = 0;
+	    		lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */
+		}
 
-	lp->cache.buf = tmp;
-	tmp = (char *)(((u_long) tmp + ALIGN) & ~ALIGN);
-	for (i=0; i<NUM_RX_DESC; i++) {
-	    lp->rx_ring[i].status = 0;
-	    lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
-	    lp->rx_ring[i].buf = cpu_to_le32(virt_to_bus(tmp+i*RX_BUFF_SZ));
-	    lp->rx_ring[i].next = 0;
-	    lp->rx_skb[i] = (struct sk_buff *) 1;     /* Dummy entry */
 	}
 #endif
 
@@ -1273,10 +1292,11 @@
 	/* Write the end of list marker to the descriptor lists */
 	lp->rx_ring[lp->rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
 	lp->tx_ring[lp->txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
-	    
+
 	/* Tell the adapter where the TX/RX rings are located. */
-	outl(virt_to_bus(lp->rx_ring), DE4X5_RRBA);
-	outl(virt_to_bus(lp->tx_ring), DE4X5_TRBA);
+	outl(lp->dma_rings, DE4X5_RRBA);
+	outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
+	     DE4X5_TRBA);
 	    
 	/* Initialise the IRQ mask and Enable/Disable */
 	lp->irq_mask = IMR_RIM | IMR_TIM | IMR_TUM | IMR_UNM;
@@ -1388,8 +1408,6 @@
 	}
     }
 
-    dev->tbusy = 0;                         
-    dev->start = 1;
     lp->interrupt = UNMASK_INTERRUPTS;
     dev->trans_start = jiffies;
     
@@ -1425,7 +1443,7 @@
 de4x5_init(struct net_device *dev)
 {  
     /* Lock out other processes whilst setting up the hardware */
-    test_and_set_bit(0, (void *)&dev->tbusy);
+    netif_stop_queue(dev);
     
     de4x5_sw_reset(dev);
     
@@ -1467,8 +1485,9 @@
 	omr |= (OMR_SDP | OMR_SB);
     }
     lp->setup_f = PERFECT;
-    outl(virt_to_bus(lp->rx_ring), DE4X5_RRBA);
-    outl(virt_to_bus(lp->tx_ring), DE4X5_TRBA);
+    outl(lp->dma_rings, DE4X5_RRBA);
+    outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
+	 DE4X5_TRBA);
     
     lp->rx_new = lp->rx_old = 0;
     lp->tx_new = lp->tx_old = 0;
@@ -1486,7 +1505,7 @@
     /* Build the setup frame depending on filtering mode */
     SetMulticastFilter(dev);
     
-    load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, NULL);
+    load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, (struct sk_buff *)1);
     outl(omr|OMR_ST, DE4X5_OMR);
 
     /* Poll for setup frame completion (adapter interrupts are disabled now) */
@@ -1520,7 +1539,7 @@
     int status = 0;
     u_long flags = 0;
 
-    test_and_set_bit(0, (void*)&dev->tbusy);     /* Stop send re-tries */
+    netif_stop_queue(dev);
     if (lp->tx_enable == NO) {                   /* Cannot send for now */
 	return -1;                                
     }
@@ -1539,14 +1558,15 @@
 	return -1;
 
     /* Transmit descriptor ring full or stale skb */
-    if (dev->tbusy || lp->tx_skb[lp->tx_new]) {
+    if (test_bit(LINK_STATE_XOFF, &dev->state) ||
+	(u_long) lp->tx_skb[lp->tx_new] > 1) {
 	if (lp->interrupt) {
 	    de4x5_putb_cache(dev, skb);          /* Requeue the buffer */
 	} else {
 	    de4x5_put_cache(dev, skb);
 	}
 	if (de4x5_debug & DEBUG_TX) {
-	    printk("%s: transmit busy, lost media or stale skb found:\n  STS:%08x\n  tbusy:%ld\n  IMR:%08x\n  OMR:%08x\n Stale skb: %s\n",dev->name, inl(DE4X5_STS), dev->tbusy, inl(DE4X5_IMR), inl(DE4X5_OMR), (lp->tx_skb[lp->tx_new] ? "YES" : "NO"));
+	    printk("%s: transmit busy, lost media or stale skb found:\n  STS:%08x\n  tbusy:%d\n  IMR:%08x\n  OMR:%08x\n Stale skb: %s\n",dev->name, inl(DE4X5_STS), test_bit(LINK_STATE_XOFF, &dev->state), inl(DE4X5_IMR), inl(DE4X5_OMR), ((u_long) lp->tx_skb[lp->tx_new] > 1) ? "YES" : "NO");
 	}
     } else if (skb->len > 0) {
 	/* If we already have stuff queued locally, use that first */
@@ -1555,9 +1575,9 @@
 	    skb = de4x5_get_cache(dev);
 	}
 
-	while (skb && !dev->tbusy && !lp->tx_skb[lp->tx_new]) {
+	while (skb && !test_bit(LINK_STATE_XOFF, &dev->state) && (u_long) lp->tx_skb[lp->tx_new] <= 1) {
 	    spin_lock_irqsave(&lp->lock, flags);
-	    test_and_set_bit(0, (void*)&dev->tbusy);
+	    netif_stop_queue(dev);
 	    load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb);
  	    lp->stats.tx_bytes += skb->len;
 	    outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */
@@ -1566,7 +1586,7 @@
 	    dev->trans_start = jiffies;
 		    
 	    if (TX_BUFFS_AVAIL) {
-		dev->tbusy = 0;         /* Another pkt may be queued */
+		netif_start_queue(dev);         /* Another pkt may be queued */
 	    }
 	    skb = de4x5_get_cache(dev);
 	    spin_unlock_irqrestore(&lp->lock, flags);
@@ -1643,7 +1663,7 @@
 
     /* Load the TX ring with any locally stored packets */
     if (!test_and_set_bit(0, (void *)&lp->cache.lock)) {
-	while (lp->cache.skb && !dev->tbusy && lp->tx_enable) {
+	while (lp->cache.skb && !test_bit(LINK_STATE_XOFF, &dev->state) && lp->tx_enable) {
 	    de4x5_queue_pkt(de4x5_get_cache(dev), dev);
 	}
 	lp->cache.lock = 0;
@@ -1732,6 +1752,16 @@
     return 0;
 }
 
+static inline void
+de4x5_free_tx_buff(struct de4x5_private *lp, int entry)
+{
+    pci_unmap_single(lp->pdev, le32_to_cpu(lp->tx_ring[entry].buf),
+		     le32_to_cpu(lp->tx_ring[entry].des1) & TD_TBS1);
+    if ((u_long) lp->tx_skb[entry] > 1)
+	dev_kfree_skb(lp->tx_skb[entry]);
+    lp->tx_skb[entry] = NULL;
+}
+
 /*
 ** Buffer sent - check for TX buffer errors.
 */
@@ -1768,19 +1798,20 @@
 				                      ((status & TD_CC) >> 3));
 
 	    /* Free the buffer. */
-	    if (lp->tx_skb[entry] != NULL) {
-		dev_kfree_skb(lp->tx_skb[entry]);
-		lp->tx_skb[entry] = NULL;
-	    }
+	    if (lp->tx_skb[entry] != NULL)
+	    	de4x5_free_tx_buff(lp, entry);
 	}
 	
 	/* Update all the pointers */
 	lp->tx_old = (++lp->tx_old) % lp->txRingSize;
     }
 
-    if (TX_BUFFS_AVAIL && dev->tbusy) {  /* Any resources available? */
-	dev->tbusy = 0;                  /* Clear TX busy flag */
-	if (lp->interrupt) mark_bh(NET_BH);
+    /* Any resources available? */
+    if (TX_BUFFS_AVAIL && test_bit(LINK_STATE_XOFF, &dev->state)) {
+	if (lp->interrupt)
+	    netif_wake_queue(dev);
+	else
+	    netif_start_queue(dev);
     }
 	
     return 0;
@@ -1861,8 +1892,8 @@
     s32 imr, omr;
     
     disable_ast(dev);
-    dev->start = 0;
-    dev->tbusy = 1;
+
+    netif_stop_queue(dev);
     
     if (de4x5_debug & DEBUG_CLOSE) {
 	printk("%s: Shutting down ethercard, status was %8.8x.\n",
@@ -1946,8 +1977,9 @@
 {
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     int entry = (lp->tx_new ? lp->tx_new-1 : lp->txRingSize-1);
+    dma_addr_t buf_dma = pci_map_single(lp->pdev, buf, flags & TD_TBS1);
 
-    lp->tx_ring[lp->tx_new].buf = cpu_to_le32(virt_to_bus(buf));
+    lp->tx_ring[lp->tx_new].buf = cpu_to_le32(buf_dma);
     lp->tx_ring[lp->tx_new].des1 &= cpu_to_le32(TD_TER);
     lp->tx_ring[lp->tx_new].des1 |= cpu_to_le32(flags);
     lp->tx_skb[lp->tx_new] = skb;
@@ -1956,8 +1988,6 @@
 
     lp->tx_ring[lp->tx_new].status = cpu_to_le32(T_OWN);
     barrier();
-    
-    return;
 }
 
 /*
@@ -1979,7 +2009,7 @@
 	} else { 
 	    SetMulticastFilter(dev);
 	    load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
-			                                SETUP_FRAME_LEN, NULL);
+			                                SETUP_FRAME_LEN, (struct sk_buff *)1);
 	    
 	    lp->tx_new = (++lp->tx_new) % lp->txRingSize;
 	    outl(POLL_DEMAND, DE4X5_TPD);       /* Start the TX */
@@ -2108,7 +2138,7 @@
 	DevicePresent(EISA_APROM);
 
 	dev->irq = irq;
-	if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+	if ((status = de4x5_hw_init(dev, iobase, NULL)) == 0) {
 	    num_de4x5s++;
 	    if (loading_module) link_modules(lastModule, dev);
 	    lastEISA = i;
@@ -2228,7 +2258,7 @@
 	DevicePresent(DE4X5_APROM);
 	if (check_region(iobase, DE4X5_PCI_TOTAL_SIZE) == 0) {
 	    dev->irq = irq;
-	    if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+	    if ((status = de4x5_hw_init(dev, iobase, pdev)) == 0) {
 		num_de4x5s++;
 		lastPCI = index;
 		if (loading_module) link_modules(lastModule, dev);
@@ -3265,10 +3295,10 @@
     de4x5_rst_desc_ring(dev);
     de4x5_setup_intr(dev);
     lp->tx_enable = YES;
-    dev->tbusy = 0;
     spin_unlock_irqrestore(&lp->lock, flags);
     outl(POLL_DEMAND, DE4X5_TPD);
-    mark_bh(NET_BH);
+
+    netif_wake_queue(dev);
 
     return;
 }
@@ -3554,7 +3584,7 @@
 	lp->timeout = msec/100;
 	
 	lp->tmp = lp->tx_new;                /* Remember the ring position */
-	load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), NULL);
+	load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1);
 	lp->tx_new = (++lp->tx_new) % lp->txRingSize;
 	outl(POLL_DEMAND, DE4X5_TPD);
     }
@@ -3622,13 +3652,10 @@
     skb_reserve(p, 2);	                               /* Align */
     if (index < lp->rx_old) {                          /* Wrapped buffer */
 	short tlen = (lp->rxRingSize - lp->rx_old) * RX_BUFF_SZ;
-	memcpy(skb_put(p,tlen), 
-	       bus_to_virt(le32_to_cpu(lp->rx_ring[lp->rx_old].buf)),tlen);
-	memcpy(skb_put(p,len-tlen), 
-	       bus_to_virt(le32_to_cpu(lp->rx_ring[0].buf)), len-tlen);
+	memcpy(skb_put(p,tlen),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,tlen);
+	memcpy(skb_put(p,len-tlen),lp->rx_bufs,len-tlen);
     } else {                                           /* Linear buffer */
-	memcpy(skb_put(p,len), 
-	       bus_to_virt(le32_to_cpu(lp->rx_ring[lp->rx_old].buf)),len);
+	memcpy(skb_put(p,len),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,len);
     }
 		    
     return p;
@@ -3659,10 +3686,8 @@
     int i;
 
     for (i=0; i<lp->txRingSize; i++) {
-	if (lp->tx_skb[i]) {
-	    dev_kfree_skb(lp->tx_skb[i]);
-	    lp->tx_skb[i] = NULL;
-	}
+	if (lp->tx_skb[i])
+	    de4x5_free_tx_buff(lp, i);
 	lp->tx_ring[i].status = 0;
     }
 
@@ -3712,8 +3737,9 @@
 
     if (lp->cache.save_cnt) {
 	STOP_DE4X5;
-	outl(virt_to_bus(lp->rx_ring), DE4X5_RRBA);
-	outl(virt_to_bus(lp->tx_ring), DE4X5_TRBA);
+	outl(lp->dma_rings, DE4X5_RRBA);
+	outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
+	     DE4X5_TRBA);
     
 	lp->rx_new = lp->rx_old = 0;
 	lp->tx_new = lp->tx_old = 0;
@@ -5578,12 +5604,13 @@
 	}
 	build_setup_frame(dev, PHYS_ADDR_ONLY);
 	/* Set up the descriptor and give ownership to the card */
-	while (test_and_set_bit(0, (void *)&dev->tbusy) != 0) barrier();
+	while (test_and_set_bit(LINK_STATE_XOFF, &dev->state) != 0)
+	    barrier();
 	load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
-		                                       SETUP_FRAME_LEN, NULL);
+		                                       SETUP_FRAME_LEN, (struct sk_buff *)1);
 	lp->tx_new = (++lp->tx_new) % lp->txRingSize;
 	outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
-	dev->tbusy = 0;                              /* Unlock the TX ring */
+	netif_start_queue(dev);                      /* Unlock the TX ring */
 	break;
 
     case DE4X5_SET_PROM:             /* Set Promiscuous Mode */
@@ -5735,7 +5762,7 @@
 	}
 	
 	tmp.addr[j++] = lp->txRingSize;
-	tmp.addr[j++] = dev->tbusy;
+	tmp.addr[j++] = test_bit(LINK_STATE_XOFF, &dev->state);
 	
 	ioc->len = j;
 	if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
@@ -5780,12 +5807,13 @@
 		release_region(p->base_addr, (lp->bus == PCI ? 
 					      DE4X5_PCI_TOTAL_SIZE :
 					      DE4X5_EISA_TOTAL_SIZE));
-		if (lp->cache.buf) {        /* MAC buffers allocated?    */
-		    kfree(lp->cache.buf);   /* Free the MAC buffers      */
-		}
 		if (lp->cache.priv) {       /* Private area allocated?   */
 		    kfree(lp->cache.priv);  /* Free the private area     */
 		}
+		if (lp->rx_ring) {
+		    pci_free_consistent(lp->pdev, lp->dma_size, lp->rx_ring,
+					lp->dma_rings);
+		}
 	    }
 	    kfree(p);
 	} else {
@@ -5816,8 +5844,9 @@
 	struct de4x5_private *lp = (struct de4x5_private *)p->priv;
 
 	next = lp->next_module;
-	if (lp->cache.buf) {                /* MAC buffers allocated?    */
-	    kfree(lp->cache.buf);           /* Free the MAC buffers      */
+	if (lp->rx_ring) {
+		pci_free_consistent(lp->pdev, lp->dma_size, lp->rx_ring,
+				    lp->dma_rings);
 	}
 	release_region(p->base_addr, (lp->bus == PCI ? 
 				      DE4X5_PCI_TOTAL_SIZE :
diff -u --recursive --new-file v2.3.42/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.3.42/linux/drivers/net/dgrs.c	Thu Nov 11 20:11:39 1999
+++ linux/drivers/net/dgrs.c	Thu Feb 10 12:22:03 2000
@@ -182,9 +182,7 @@
 /*
  *	Chain of device structures
  */
-#ifdef MODULE
-	static struct net_device *dgrs_root_dev = NULL;
-#endif
+static struct net_device *dgrs_root_dev = NULL;
 
 /*
  *	Private per-board data structure (dev->priv)
@@ -355,7 +353,7 @@
 )
 {
         int     	i;
-        ulong   	csr;
+        ulong   	csr = 0;
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
 
 	if (pciaddr)
@@ -717,7 +715,7 @@
 		printk("%s: xmit len=%d\n", devN->name, (int) skb->len);
 
 	devN->trans_start = jiffies;
-	devN->tbusy = 0;
+	netif_start_queue(devN);
 
 	if (priv0->rfdp->cmd & I596_RFD_EL)
 	{	/* Out of RFD's */
@@ -790,13 +788,9 @@
 static int
 dgrs_open( struct net_device *dev )
 {
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
-#ifdef MODULE
 	MOD_INC_USE_COUNT;
-#endif
 
 	return (0);
 }
@@ -806,12 +800,9 @@
  */
 static int dgrs_close( struct net_device *dev )
 {
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
-#ifdef MODULE
 	MOD_DEC_USE_COUNT;
-#endif
 
 	return (0);
 }
@@ -940,10 +931,10 @@
 		if (dgrs_nicmode)
 		{
 			for (i = 0; i < priv0->nports; ++i)
-				priv0->devtbl[i]->tbusy = 0;
+				netif_wake_queue (priv0->devtbl[i]);
 		}
 		else
-			dev0->tbusy = 0;
+			netif_wake_queue (dev0);
 		/* if (bd->flags & TX_QUEUED)
 			DL_sched(bd, bdd); */
 	}
@@ -1451,16 +1442,9 @@
 	return cards_found;
 }
 
-/*
- *	Module/driver initialization points.  Two ways, depending on
- *	whether we are a module or statically linked, ala Don Becker's
- *	3c59x driver.
- */
-
-#ifdef MODULE
 
 /*
- *	Variables that can be overriden from command line
+ *	Variables that can be overriden from module command line
  */
 static int	debug = -1;
 static int	dma = -1;
@@ -1480,8 +1464,7 @@
 MODULE_PARM(ipxnet, "i");
 MODULE_PARM(nicmode, "i");
 
-int
-init_module(void)
+static int __init dgrs_init_module (void)
 {
 	int	cards_found;
 	int	i;
@@ -1531,8 +1514,7 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-void
-cleanup_module(void)
+static void __exit dgrs_cleanup_module (void)
 {
         while (dgrs_root_dev)
 	{
@@ -1560,17 +1542,5 @@
         }
 }
 
-#else
-
-int __init 
-dgrs_probe(struct net_device *dev)
-{
-	int	cards_found;
-
-	cards_found = dgrs_scan();
-	if (dgrs_debug && cards_found)
-		printk("dgrs: SW=%s FW=Build %d %s\n",
-			version, dgrs_firmnum, dgrs_firmdate);
-	return cards_found ? 0 : -ENODEV;
-}
-#endif
+module_init(dgrs_init_module);
+module_exit(dgrs_cleanup_module);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- v2.3.42/linux/drivers/net/dmfe.c	Thu Nov 18 20:25:37 1999
+++ linux/drivers/net/dmfe.c	Thu Feb 10 12:22:03 2000
@@ -275,7 +275,7 @@
 };
 
 /* function declaration ------------------------------------- */
-int dmfe_reg_board(void);
+static int dmfe_reg_board(void);
 static int dmfe_open(struct net_device *);
 static int dmfe_start_xmit(struct sk_buff *, struct net_device *);
 static int dmfe_stop(struct net_device *);
@@ -309,7 +309,7 @@
  *	Search DM910X board, allocate space and register it
  */
  
-int __init dmfe_reg_board(void)
+static int __init dmfe_reg_board(void)
 {
 	u32 pci_iobase;
 	u16 dm9102_count = 0;
@@ -329,7 +329,6 @@
 	while ((net_dev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, net_dev)))
 	{
 		u32 pci_id;
-		u8 pci_cmd;
 
 		index++;
 		if (pci_read_config_dword(net_dev, PCI_VENDOR_ID, &pci_id) != DMFE_SUCC)
@@ -341,15 +340,14 @@
 		pci_iobase = net_dev->resource[0].start;
 		pci_irqline = net_dev->irq;
 				
+		if (check_region(pci_iobase, DM9102_IO_SIZE))	/* IO range check */
+			continue;
+
 		/* Enable Master/IO access, Disable memory access */
 		
+		pci_enable_device (net_dev);
 		pci_set_master(net_dev);
 		
-		pci_read_config_byte(net_dev, PCI_COMMAND, &pci_cmd);
-		pci_cmd |= PCI_COMMAND_IO;
-		pci_cmd &= ~PCI_COMMAND_MEMORY;
-		pci_write_config_byte(net_dev, PCI_COMMAND, pci_cmd);
-
 		/* Set Latency Timer 80h */
 		
 		/* FIXME: setting values > 32 breaks some SiS 559x stuff.
@@ -359,22 +357,17 @@
 
 		/* IO range and interrupt check */
 
-		if (check_region(pci_iobase, DM9102_IO_SIZE))	/* IO range check */
-			continue;
-
 		/* Found DM9102 card and PCI resource allocated OK */
 		dm9102_count++;	/* Found a DM9102 card */
 
 		/* Init network device */
-		dev = init_etherdev(NULL, 0);
+		dev = init_etherdev(NULL, sizeof(*db));
+		if (dev == NULL)
+			continue;
+		
+		db = dev->priv;
 
-		/* Allocated board information structure */
-		db = (void *) (kmalloc(sizeof(*db), GFP_KERNEL | GFP_DMA));
-		if(db==NULL)
-			continue;	/* Out of memory */
-			
 		memset(db, 0, sizeof(*db));
-		dev->priv = db;	/* link device and board info */
 		db->next_dev = dmfe_root_dev;
 		dmfe_root_dev = dev;
 
@@ -405,10 +398,9 @@
 
 	}
 
-#ifdef MODULE
 	if (!dm9102_count)
 		printk(KERN_WARNING "dmfe: Can't find DM910X board\n");
-#endif		
+
 	return dm9102_count ? 0 : -ENODEV;
 }
 
@@ -1453,7 +1445,6 @@
 
 }
 
-#ifdef MODULE
 
 MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");
 MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");
@@ -1467,7 +1458,7 @@
  *	to initilize and register.
  */
  
-int init_module(void)
+static int __init dmfe_init_module(void)
 {
 	DMFE_DBUG(0, "init_module() ", debug);
 
@@ -1497,7 +1488,7 @@
  *	to un-register device.
  */
  
-void cleanup_module(void)
+static void __exit dmfe_cleanup_module(void)
 {
 	struct net_device *next_dev;
 
@@ -1514,4 +1505,5 @@
 	DMFE_DBUG(0, "clean_module() exit", 0);
 }
 
-#endif				/* MODULE */
+module_init(dmfe_init_module);
+module_exit(dmfe_cleanup_module);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.3.42/linux/drivers/net/eepro.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/eepro.c	Thu Feb 10 12:22:03 2000
@@ -138,18 +138,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-
-
-/* need to remove these asap      */
-/* 2.1.xx compatibility macros... */
-/*                                */
-
-
-#include <linux/version.h>
-
-/* For linux 2.1.xx */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -160,16 +148,6 @@
 /* udelay(2) */
 #define compat_init_data     __initdata
 
-#else 
-/* for 2.x */
-
-#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) )
-#define test_and_set_bit(a,b) set_bit((a),(b))
-#define SLOW_DOWN SLOW_DOWN_IO
-#define compat_init_data
-
-#endif
-
 
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
@@ -210,9 +188,8 @@
 	int version;	/* a flag to indicate if this is a TX or FX
 				   version of the 82595 chip. */
 	int stepping;
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+
 	spinlock_t lock; /* Serializing lock  */ 
-#endif
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
@@ -299,6 +276,7 @@
 #define ee_id_eepro10p0 0x10   /* ID for eepro/10+ */
 #define ee_id_eepro10p1 0x31
 
+#define TX_TIMEOUT 40
 
 /* Index to functions, as function prototypes. */
 
@@ -313,6 +291,7 @@
 static int	eepro_close(struct net_device *dev);
 static struct enet_statistics *eepro_get_stats(struct net_device *dev);
 static void     set_multicast_list(struct net_device *dev);
+static void     eepro_tx_timeout (struct net_device *dev);
 
 static int read_eeprom(int ioaddr, int location);
 static void hardware_send_packet(struct net_device *dev, void *buf, short length);
@@ -710,14 +689,15 @@
 				return -ENOMEM;
 			memset(dev->priv, 0, sizeof(struct eepro_local));
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-			spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
-#endif
+			((struct eepro_local *)dev->priv)->lock = SPIN_LOCK_UNLOCKED;
+
 			dev->open               = eepro_open;
 			dev->stop               = eepro_close;
 			dev->hard_start_xmit    = eepro_send_packet;
 			dev->get_stats          = eepro_get_stats;
 			dev->set_multicast_list = &set_multicast_list;
+			dev->tx_timeout		= eepro_tx_timeout;
+			dev->watchdog_timeo	= TX_TIMEOUT;
 
 			/* Fill in the fields of the device structure with
 			   ethernet generic values */
@@ -969,10 +949,8 @@
 
 	lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
 	lp->tx_last = 0;
-	
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+
+	netif_start_queue(dev);	
 
 	if (net_debug > 3)
 		printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
@@ -983,81 +961,53 @@
 	return 0;
 }
 
-static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void eepro_tx_timeout (struct net_device *dev)
 {
-	struct eepro_local *lp = (struct eepro_local *)dev->priv;
+	struct eepro_local *lp = (struct eepro_local *) dev->priv;
 	int ioaddr = dev->base_addr;
 	int rcv_ram = dev->mem_end;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+	/* if (net_debug > 1) */
+	printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
+		"network cable problem");
+	/* This is not a duplicate. One message for the console, 
+	   one for the the log file  */
+	printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
+		"network cable problem");
+	lp->stats.tx_errors++;
+
+	/* Try to restart the adaptor. */
+	outb (SEL_RESET_CMD, ioaddr);
+	/* We are supposed to wait for 2 us after a SEL_RESET */
+	SLOW_DOWN;
+	SLOW_DOWN;
+
+	/* Do I also need to flush the transmit buffers here? YES? */
+	lp->tx_start = lp->tx_end = rcv_ram;
+	lp->tx_last = 0;
+
+	dev->trans_start = jiffies;
+	netif_start_queue (dev);
+
+	outb (RCV_ENABLE_CMD, ioaddr);
+}
+
+
+static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	unsigned long flags;
-#endif
 	
 	if (net_debug > 5)
 		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
 	
-	if (dev->tbusy) {
-		/* If we get here, some higher level has decided we are broken.
-		   There should really be a "kick me" function call instead. */
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 40)
-			return 1;
-	
-		/* if (net_debug > 1) */
-		printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, 
-			"network cable problem");
-		/* This is not a duplicate. One message for the console, 
-		   one for the the log file  */
-		printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
-			"network cable problem");
-		lp->stats.tx_errors++;
-
-		/* Try to restart the adaptor. */
-		outb(SEL_RESET_CMD, ioaddr); 
-		/* We are supposed to wait for 2 us after a SEL_RESET */
-		SLOW_DOWN;
-		SLOW_DOWN;
-
-		/* Do I also need to flush the transmit buffers here? YES? */
-		lp->tx_start = lp->tx_end = rcv_ram; 
-		lp->tx_last = 0;
-	
-		dev->tbusy=0;
-		dev->trans_start = jiffies;
-
-		outb(RCV_ENABLE_CMD, ioaddr);
-
-	}
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20155
-	/* If some higher layer thinks we've missed an tx-done interrupt
-	   we are passed NULL. Caution: dev_tint() handles the cli()/sti()
-	   itself. */
-	/*	if (skb == NULL) {
-		dev_tint(dev);
-	  	return 0;
-	}*/
-	/* according to A. Cox, this is obsolete since 1.0 */
-#endif
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 	spin_lock_irqsave(&lp->lock, flags);
-#endif
-
-	/* Block a timer-based transmit from overlapping. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-		spin_unlock_irqrestore(&lp->lock, flags);
-#endif
-	} else {
+	{
 		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		unsigned char *buf = skb->data;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 		lp->stats.tx_bytes+=skb->len;
-#endif
 
 		hardware_send_packet(dev, buf, length);
 		dev->trans_start = jiffies;
@@ -1072,9 +1022,7 @@
 	if (net_debug > 5)
 		printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 	spin_unlock_irqrestore(&lp->lock, flags);
-#endif
 	
 	return 0;
 }
@@ -1096,21 +1044,7 @@
                 return;
         }
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
         spin_lock(&lp->lock);
-#endif
-
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-		spin_unlock(&lp->lock);
-		/* FIXME : with the lock, could this ever happen ? */
-#endif
-
-		return;
-	}
-	dev->interrupt = 1;
 
 	if (net_debug > 5)
 		printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
@@ -1143,14 +1077,10 @@
 	
 	} while ((boguscount-- > 0) && (status & 0x06));
 
-	dev->interrupt = 0; 
-
 	if (net_debug > 5)
 		printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 	spin_unlock(&lp->lock);
-#endif
 	return;
 }
 
@@ -1161,8 +1091,7 @@
 	int rcv_ram = dev->mem_end;
 	short temp_reg;
 
-	dev->tbusy = 1;
-	dev->start = 0;
+	netif_stop_queue(dev);
 
 	outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */
 
@@ -1402,12 +1331,6 @@
 		service routines. */
 		outb(ALL_MASK, ioaddr + INT_MASK_REG);
 
-		if (dev->interrupt == 1) {
-			/* Enable RX and TX interrupts */
-			outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
-			continue;
-		}
-
 		/* determine how much of the transmit buffer space is available */
 		if (lp->tx_end > lp->tx_start)
 			tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
@@ -1484,9 +1407,8 @@
 		lp->tx_last = last;
 		lp->tx_end = end;
 
-		if (dev->tbusy) {
-			dev->tbusy = 0;
-		}
+		if (test_bit(LINK_STATE_XOFF, &dev->flags))
+			netif_start_queue(dev);
 		
 		/* Enable RX and TX interrupts */
 		outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
@@ -1496,7 +1418,7 @@
 		return;
 	}
 
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 	if (net_debug > 5)
 		printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
 }
@@ -1529,9 +1451,7 @@
 			/* Malloc up new buffer. */
 			struct sk_buff *skb;
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
 			lp->stats.rx_bytes+=rcv_size;
-#endif
 			rcv_size &= 0x3fff;
 			skb = dev_alloc_skb(rcv_size+5);
 			if (skb == NULL) {
@@ -1622,8 +1542,7 @@
 		xmt_status = inw(ioaddr+IO_PORT); 
 		lp->tx_start = inw(ioaddr+IO_PORT);
 
-		dev->tbusy = 0;
-		mark_bh(NET_BH);
+		netif_wake_queue (dev);
 
 		if (xmt_status & 0x2000)
 			lp->stats.tx_packets++; 
@@ -1650,8 +1569,6 @@
 	}
 }
 
-#ifdef MODULE
-
 #define MAX_EEPRO 8
 static char devicename[MAX_EEPRO][9];
 static struct net_device dev_eepro[MAX_EEPRO];
@@ -1670,13 +1587,14 @@
 
 static int n_eepro = 0;
 /* For linux 2.1.xx */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+
 MODULE_AUTHOR("Pascal Dupuis <dupuis@lei.ucl.ac.be> for the 2.1 stuff (locking,...)");
 MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i");
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i");
 MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-#endif 
+
+#ifdef MODULE
 
 int 
 init_module(void)
diff -u --recursive --new-file v2.3.42/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.3.42/linux/drivers/net/eepro100.c	Thu Nov 11 20:11:40 1999
+++ linux/drivers/net/eepro100.c	Thu Feb 10 12:22:03 2000
@@ -49,9 +49,7 @@
    e.g. "options=16" for FD, "options=32" for 100mbps-only. */
 static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#ifdef MODULE
 static int debug = -1;			/* The debug level */
-#endif
 
 /* A few values that may be tweaked. */
 /* The ring sizes should be a power of two for efficiency. */
@@ -81,11 +79,11 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#include <linux/timer.h>
 #ifdef HAS_PCI_NETIF
 #include "pci-netif.h"
 #else
@@ -95,6 +93,7 @@
 #endif
 #endif
 #include <linux/spinlock.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -103,7 +102,6 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 
-#if LINUX_VERSION_CODE > 0x20118  &&  defined(MODULE)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
 MODULE_PARM(debug, "i");
@@ -117,12 +115,8 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(multicast_filter_limit, "i");
-#endif
 
 #define RUN_AT(x) (jiffies + (x))
-/* Condensed bus+endian portability operations. */
-#define virt_to_le32bus(addr)  cpu_to_le32(virt_to_bus(addr))
-#define le32bus_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
 
 #if (LINUX_VERSION_CODE < 0x20123)
 #define test_and_set_bit(val, addr) set_bit(val, addr)
@@ -356,12 +350,15 @@
 	CmdTxFlex = 0x00080000,		/* Use "Flexible mode" for CmdTx command. */
 };
 /* Do atomically if possible. */
-#if defined(__i386__) || defined(__alpha__)
-#define clear_suspend(cmd)   clear_bit(30, &(cmd)->cmd_status)
+#if defined(__i386__) || defined(__alpha__) || defined(__ia64__)
+#define clear_suspend(cmd)	clear_bit(30, &(cmd)->cmd_status)
 #elif defined(__powerpc__)
 #define clear_suspend(cmd)	clear_bit(6, &(cmd)->cmd_status)
 #else
-#define clear_suspend(cmd)	(cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)
+#if 0
+# error You are probably in trouble: clear_suspend() MUST be atomic.
+#endif
+# define clear_suspend(cmd)	(cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)
 #endif
 
 enum SCBCmdBits {
@@ -439,11 +436,13 @@
 /* Do not change the position (alignment) of the first few elements!
    The later elements are grouped for cache locality. */
 struct speedo_private {
-	struct TxFD	tx_ring[TX_RING_SIZE];	/* Commands (usually CmdTxPacket). */
+	struct TxFD	*tx_ring;		/* Commands (usually CmdTxPacket). */
 	struct RxFD *rx_ringp[RX_RING_SIZE];	/* Rx descriptor, used as ring. */
 	/* The addresses of a Tx/Rx-in-place packets/buffers. */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+	dma_addr_t	rx_ring_dma[RX_RING_SIZE];
+	dma_addr_t	tx_ring_dma;
 	struct descriptor  *last_cmd;	/* Last command sent. */
 	unsigned int cur_tx, dirty_tx;	/* The ring entries to be free()ed. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
@@ -455,14 +454,15 @@
 	struct net_device *next_module;
 	void *priv_addr;					/* Unaligned address for kfree */
 	struct enet_statistics stats;
-	struct speedo_stats lstats;
+	struct speedo_stats *lstats;
 	int chip_id;
 	unsigned char pci_bus, pci_devfn, acpi_pwr;
+	struct pci_dev *pdev;
 	struct timer_list timer;	/* Media selection timer. */
 	int mc_setup_frm_len;			 	/* The length of an allocated.. */
 	struct descriptor *mc_setup_frm; 	/* ..multicast setup frame. */
 	int mc_setup_busy;					/* Avoid double-use of setup frame. */
-	int in_interrupt;					/* Word-aligned dev->interrupt */
+	dma_addr_t mc_setup_dma;
 	char rx_mode;						/* Current PROMISC/ALLMULTI setting. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
@@ -474,7 +474,6 @@
 	unsigned short phy[2];				/* PHY media interfaces available. */
 	unsigned short advertising;			/* Current PHY advertised caps. */
 	unsigned short partner;				/* Link partner caps. */
-	long last_reset;
 };
 
 /* The parameters for a CmdConfigure operation.
@@ -541,7 +540,6 @@
 
 	for (; pci_index < 8; pci_index++) {
 		unsigned char pci_bus, pci_device_fn, pci_latency;
-		u32 pciaddr;
 		long ioaddr;
 		int irq;
 
@@ -556,14 +554,15 @@
 		{
 			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
 #ifdef USE_IO
-			pciaddr = pdev->resource[1].start;
+			ioaddr = pdev->resource[1].start;
 #else
-			pciaddr = pdev->resource[0].start;
+			ioaddr = pdev->resource[0].start;
 #endif
 			irq = pdev->irq;
 		}
 #else
 		{
+			u32 pciaddr;
 			u8 pci_irq_line;
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 									 PCI_INTERRUPT_LINE, &pci_irq_line);
@@ -571,23 +570,30 @@
 #ifdef USE_IO
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 									  PCI_BASE_ADDRESS_1, &pciaddr);
+			pciaddr &= ~3UL;
 #else
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 									  PCI_BASE_ADDRESS_0, &pciaddr);
 #endif
+			ioaddr = pciaddr;
 			irq = pci_irq_line;
 		}
 #endif
 		/* Remove I/O space marker in bit 0. */
-		if (pciaddr & 1) {
-			ioaddr = pciaddr & ~3UL;
-			if (check_region(ioaddr, 32))
-				continue;
-		} else if ((ioaddr = (long)ioremap(pciaddr & ~0xfUL, 0x1000)) == 0) {
-			printk(KERN_INFO "Failed to map PCI address %#x.\n",
-				   pciaddr);
+#ifdef USE_IO
+		if (check_region(ioaddr, 32))
 			continue;
+#else
+		{
+			unsigned long orig_ioaddr = ioaddr;
+
+			if ((ioaddr = (long)ioremap(ioaddr & ~0xfUL, 0x1000)) == 0) {
+				printk(KERN_INFO "Failed to map PCI address %#lx.\n",
+					   orig_ioaddr);
+				continue;
+			}
 		}
+#endif
 		if (speedo_debug > 2)
 			printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
 				   ioaddr, irq);
@@ -626,17 +632,34 @@
 {
 	struct net_device *dev;
 	struct speedo_private *sp;
+	struct pci_dev *pdev;
+	unsigned char *tx_ring;
+	dma_addr_t tx_ring_dma;
 	const char *product;
 	int i, option;
 	u16 eeprom[0x100];
 	int acpi_idle_state = 0;
-#ifndef MODULE
+
 	static int did_version = 0;			/* Already printed version info. */
 	if (speedo_debug > 0  &&  did_version++ == 0)
 		printk(version);
-#endif
+
+	pdev = pci_find_slot(pci_bus, pci_devfn);
+
+	tx_ring = pci_alloc_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
+					     + sizeof(struct speedo_stats), &tx_ring_dma);
+	if (!tx_ring) {
+		printk(KERN_ERR "Could not allocate DMA memory.\n");
+		return NULL;
+	}
 
 	dev = init_etherdev(NULL, sizeof(struct speedo_private));
+	if (dev == NULL) {
+		pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
+					  + sizeof(struct speedo_stats),
+				    tx_ring, tx_ring_dma);
+		return NULL;
+	}
 
 	if (dev->mem_start > 0)
 		option = dev->mem_start;
@@ -708,7 +731,7 @@
 	{
 		const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"};
 		/* The self-test results must be paragraph aligned. */
-		s32 str[6], *volatile self_test_results;
+		volatile s32 *self_test_results = (volatile s32 *)tx_ring;
 		int boguscnt = 16000;	/* Timeout for set-test. */
 		if (eeprom[3] & 0x03)
 			printk(KERN_INFO "  Receiver lock-up bug exists -- enabling"
@@ -742,11 +765,10 @@
 					   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
 		}
 
-		/* Perform a system self-test. */
-		self_test_results = (s32*) ((((long) str) + 15) & ~0xf);
+		/* Perform a system self-test. Use the tx_ring consistent DMA mapping for it. */
 		self_test_results[0] = 0;
 		self_test_results[1] = -1;
-		outl(virt_to_bus(self_test_results) | PortSelfTest, ioaddr + SCBPort);
+		outl(tx_ring_dma | PortSelfTest, ioaddr + SCBPort);
 		do {
 			udelay(10);
 		} while (self_test_results[1] == -1  &&  --boguscnt >= 0);
@@ -794,9 +816,13 @@
 
 	sp->pci_bus = pci_bus;
 	sp->pci_devfn = pci_devfn;
+	sp->pdev = pdev;
 	sp->chip_id = chip_idx;
 	sp->acpi_pwr = acpi_idle_state;
-
+	sp->tx_ring = (struct TxFD *)tx_ring;
+	sp->tx_ring_dma = tx_ring_dma;
+	sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
+	
 	sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
 	if (card_idx >= 0) {
 		if (full_duplex[card_idx] >= 0)
@@ -814,6 +840,8 @@
 	/* The Speedo-specific entries in the device structure. */
 	dev->open = &speedo_open;
 	dev->hard_start_xmit = &speedo_start_xmit;
+	dev->tx_timeout = &speedo_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->stop = &speedo_close;
 	dev->get_stats = &speedo_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
@@ -909,8 +937,7 @@
 	sp->dirty_tx = 0;
 	sp->last_cmd = 0;
 	sp->tx_full = 0;
-	sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
-	sp->in_interrupt = 0;
+	spin_lock_init(&sp->lock);
 
 	/* .. we can safely take handler calls during init. */
 	if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) {
@@ -943,9 +970,8 @@
 	/* Fire up the hardware. */
 	speedo_resume(dev);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	clear_bit(LINK_STATE_RXSEM, &dev->state);
+	netif_start_queue(dev);
 
 	/* Setup the chip and configure the multicast list. */
 	sp->mc_setup_frm = NULL;
@@ -999,12 +1025,12 @@
 	wait_for_cmd_done(ioaddr + SCBCmd);
 
 	/* Load the statistics block and rx ring addresses. */
-	outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);
+	outl(sp->tx_ring_dma + sizeof(struct TxFD) * TX_RING_SIZE, ioaddr + SCBPointer);
 	outb(CUStatsAddr, ioaddr + SCBCmd);
-	sp->lstats.done_marker = 0;
+	sp->lstats->done_marker = 0;
 	wait_for_cmd_done(ioaddr + SCBCmd);
 
-	outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
+	outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
 		 ioaddr + SCBPointer);
 	outb(RxStart, ioaddr + SCBCmd);
 	wait_for_cmd_done(ioaddr + SCBCmd);
@@ -1019,7 +1045,8 @@
 		/* Avoid a bug(?!) here by marking the command already completed. */
 		cur_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000);
 		cur_cmd->link =
-			virt_to_le32bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
+			cpu_to_le32(sp->tx_ring_dma + (sp->cur_tx % TX_RING_SIZE)
+						      * sizeof(struct TxFD));
 		memcpy(cur_cmd->params, dev->dev_addr, 6);
 		if (sp->last_cmd)
 			clear_suspend(sp->last_cmd);
@@ -1028,7 +1055,8 @@
 
 	/* Start the chip's Tx process and unmask interrupts. */
 	wait_for_cmd_done(ioaddr + SCBCmd);
-	outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
+	outl(sp->tx_ring_dma
+	     + (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD),
 		 ioaddr + SCBPointer);
 	outw(CUStart, ioaddr + SCBCmd);
 }
@@ -1065,12 +1093,6 @@
 		printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 	}
-	/* This has a small false-trigger window. */
-	if (test_bit(0, (void*)&dev->tbusy) &&
-		(jiffies - dev->trans_start) > TX_TIMEOUT) {
-		speedo_tx_timeout(dev);
-		sp->last_reset = jiffies;
-	}
 	if (sp->rx_mode < 0  ||
 		(sp->rx_bug  && jiffies - sp->last_rx_time > 2*HZ)) {
 		/* We haven't received a packet in a Long Time.  We might have been
@@ -1135,18 +1157,16 @@
 		skb->dev = dev;			/* Mark as being used by this device. */
 		rxf = (struct RxFD *)skb->tail;
 		sp->rx_ringp[i] = rxf;
+		sp->rx_ring_dma[i] =
+			pci_map_single(sp->pdev, rxf, PKT_BUF_SZ + sizeof(struct RxFD));
 		skb_reserve(skb, sizeof(struct RxFD));
 		if (last_rxf)
-			last_rxf->link = virt_to_le32bus(rxf);
+			last_rxf->link = cpu_to_le32(sp->rx_ring_dma[i]);
 		last_rxf = rxf;
 		rxf->status = cpu_to_le32(0x00000001);	/* '1' is flag value only. */
 		rxf->link = 0;						/* None yet. */
-		/* This field unused by i82557, we use it as a consistency check. */
-#ifdef final_version
+		/* This field unused by i82557. */
 		rxf->rx_buf_addr = 0xffffffff;
-#else
-		rxf->rx_buf_addr = virt_to_bus(skb->tail);
-#endif
 		rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
 	}
 	sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -1175,7 +1195,8 @@
 		/* Only the command unit has stopped. */
 		printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
 			   dev->name);
-		outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
+		outl(sp->tx_ring_dma
+		     + (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD),
 			 ioaddr + SCBPointer);
 		outw(CUStart, ioaddr + SCBCmd);
 	} else {
@@ -1209,22 +1230,6 @@
 	long ioaddr = dev->base_addr;
 	int entry;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	   If this ever occurs the queue layer is doing something evil! */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < TX_TIMEOUT - 2)
-			return 1;
-		if (tickssofar < TX_TIMEOUT) {
-			/* Reap sent packets from the full Tx queue. */
-			outw(SCBTriggerIntr, ioaddr + SCBCmd);
-			return 1;
-		}
-		speedo_tx_timeout(dev);
-		return 1;
-	}
-
 	/* Caution: the write order is important here, set the base address
 	   with the "ownership" bits last. */
 
@@ -1240,12 +1245,18 @@
 		sp->tx_ring[entry].status =
 			cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex);
 		sp->tx_ring[entry].link =
-			virt_to_le32bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
+			cpu_to_le32(sp->tx_ring_dma
+				    + (sp->cur_tx % TX_RING_SIZE)
+				    * sizeof(struct TxFD));
 		sp->tx_ring[entry].tx_desc_addr =
-			virt_to_le32bus(&sp->tx_ring[entry].tx_buf_addr0);
+			cpu_to_le32(sp->tx_ring_dma
+				    + ((long)&sp->tx_ring[entry].tx_buf_addr0
+				       - (long)sp->tx_ring));
 		/* The data region is always in one buffer descriptor. */
 		sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold);
-		sp->tx_ring[entry].tx_buf_addr0 = virt_to_le32bus(skb->data);
+		sp->tx_ring[entry].tx_buf_addr0 =
+			cpu_to_le32(pci_map_single(sp->pdev, skb->data,
+						   skb->len));
 		sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len);
 		/* Todo: perhaps leave the interrupt bit set if the Tx queue is more
 		   than half full.  Argument against: we should be receiving packets
@@ -1255,12 +1266,12 @@
 		{
 			struct descriptor *last_cmd = sp->last_cmd;
 			sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-			clear_suspend(last_cmd);
+			last_cmd->cmd_status &= cpu_to_le32(~(CmdSuspend | CmdIntr));
 		}
-		if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT)
+		if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) {
 			sp->tx_full = 1;
-		else
-			clear_bit(0, (void*)&dev->tbusy);
+			netif_stop_queue(dev);
+		}
 		spin_unlock_irqrestore(&sp->lock, flags);
 	}
 	wait_for_cmd_done(ioaddr + SCBCmd);
@@ -1288,16 +1299,6 @@
 
 	ioaddr = dev->base_addr;
 	sp = (struct speedo_private *)dev->priv;
-#ifndef final_version
-	/* A lock to prevent simultaneous entry on SMP machines. */
-	if (test_and_set_bit(0, (void*)&sp->in_interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		sp->in_interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-	dev->interrupt = 1;
-#endif
 
 	do {
 		status = inw(ioaddr + SCBStatus);
@@ -1319,7 +1320,7 @@
 				outw(RxResumeNoResources, ioaddr + SCBCmd);
 			else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */
 				/* No idea of what went wrong.  Restart the receiver. */
-				outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]),
+				outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
 					 ioaddr + SCBPointer);
 				outw(RxStart, ioaddr + SCBCmd);
 			}
@@ -1350,10 +1351,18 @@
 #if LINUX_VERSION_CODE > 0x20127
 					sp->stats.tx_bytes += sp->tx_skbuff[entry]->len;
 #endif
-					dev_free_skb(sp->tx_skbuff[entry]);
+					pci_unmap_single(sp->pdev,
+							 le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
+							 sp->tx_skbuff[entry]->len);
+					dev_kfree_skb_irq(sp->tx_skbuff[entry]);
 					sp->tx_skbuff[entry] = 0;
-				} else if ((status & 0x70000) == CmdNOp)
+				} else if ((status & 0x70000) == CmdNOp) {
+					if (sp->mc_setup_busy)
+						pci_unmap_single(sp->pdev,
+								 sp->mc_setup_dma,
+								 sp->mc_setup_frm_len);
 					sp->mc_setup_busy = 0;
+				}
 				dirty_tx++;
 			}
 
@@ -1371,7 +1380,6 @@
 				&&  sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) {
 				/* The ring is no longer full, clear tbusy. */
 				sp->tx_full = 0;
-				clear_bit(0, (void*)&dev->tbusy);
 				spin_unlock(&sp->lock);
 				netif_wake_queue(dev);
 			} else
@@ -1391,8 +1399,6 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, inw(ioaddr + SCBStatus));
 
-	dev->interrupt = 0;
-	clear_bit(0, (void*)&sp->in_interrupt);
 	return;
 }
 
@@ -1436,6 +1442,8 @@
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
 				/* 'skb_put()' points to the start of sk_buff data area. */
+				pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry],
+						    PKT_BUF_SZ + sizeof(struct RxFD));
 #if 1 || USE_IP_CSUM
 				/* Packet is in one chunk -- we can copy + cksum. */
 				eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0);
@@ -1455,15 +1463,9 @@
 				}
 				sp->rx_skbuff[entry] = NULL;
 				temp = skb_put(skb, pkt_len);
-#if !defined(final_version) && !defined(__powerpc__)
-				if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp)
-					printk(KERN_ERR "%s: Rx consistency error -- the skbuff "
-						   "addresses do not match in speedo_rx: %p vs. %p "
-						   "/ %p.\n", dev->name,
-						   bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
-						   skb->head, temp);
-#endif
 				sp->rx_ringp[entry] = NULL;
+				pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
+						 PKT_BUF_SZ + sizeof(struct RxFD));
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
@@ -1489,16 +1491,19 @@
 				break;			/* Better luck next time!  */
 			}
 			rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail;
+			sp->rx_ring_dma[entry] =
+				pci_map_single(sp->pdev, rxf, PKT_BUF_SZ
+					       + sizeof(struct RxFD));
 			skb->dev = dev;
 			skb_reserve(skb, sizeof(struct RxFD));
-			rxf->rx_buf_addr = virt_to_bus(skb->tail);
+			rxf->rx_buf_addr = 0xffffffff;
 		} else {
 			rxf = sp->rx_ringp[entry];
 		}
 		rxf->status = cpu_to_le32(0xC0000001); 	/* '1' for driver use only. */
 		rxf->link = 0;			/* None yet. */
 		rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
-		sp->last_rxf->link = virt_to_le32bus(rxf);
+		sp->last_rxf->link = cpu_to_le32(sp->rx_ring_dma[entry]);
 		sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
 		sp->last_rxf = rxf;
 	}
@@ -1514,8 +1519,7 @@
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (speedo_debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
@@ -1536,6 +1540,9 @@
 		sp->rx_skbuff[i] = 0;
 		/* Clear the Rx descriptors. */
 		if (skb) {
+			pci_unmap_single(sp->pdev,
+					 sp->rx_ring_dma[i],
+					 PKT_BUF_SZ + sizeof(struct RxFD));
 #if LINUX_VERSION_CODE < 0x20100
 			skb->free = 1;
 #endif
@@ -1546,9 +1553,14 @@
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		struct sk_buff *skb = sp->tx_skbuff[i];
 		sp->tx_skbuff[i] = 0;
+
 		/* Clear the Tx descriptors. */
-		if (skb)
+		if (skb) {
+			pci_unmap_single(sp->pdev,
+							 le32_to_cpu(sp->tx_ring[i].tx_buf_addr0),
+							 skb->len);
 			dev_free_skb(skb);
+		}
 	}
 	if (sp->mc_setup_frm) {
 		kfree(sp->mc_setup_frm);
@@ -1587,20 +1599,20 @@
 	long ioaddr = dev->base_addr;
 
 	/* Update only if the previous dump finished. */
-	if (sp->lstats.done_marker == le32_to_cpu(0xA007)) {
-		sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats.tx_coll16_errs);
-		sp->stats.tx_window_errors += le32_to_cpu(sp->lstats.tx_late_colls);
-		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_underruns);
-		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats.tx_lost_carrier);
-		/*sp->stats.tx_deferred += le32_to_cpu(sp->lstats.tx_deferred);*/
-		sp->stats.collisions += le32_to_cpu(sp->lstats.tx_total_colls);
-		sp->stats.rx_crc_errors += le32_to_cpu(sp->lstats.rx_crc_errs);
-		sp->stats.rx_frame_errors += le32_to_cpu(sp->lstats.rx_align_errs);
-		sp->stats.rx_over_errors += le32_to_cpu(sp->lstats.rx_resource_errs);
-		sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats.rx_overrun_errs);
-		sp->stats.rx_length_errors += le32_to_cpu(sp->lstats.rx_runt_errs);
-		sp->lstats.done_marker = 0x0000;
-		if (dev->start) {
+	if (sp->lstats->done_marker == le32_to_cpu(0xA007)) {
+		sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats->tx_coll16_errs);
+		sp->stats.tx_window_errors += le32_to_cpu(sp->lstats->tx_late_colls);
+		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_underruns);
+		sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_lost_carrier);
+		/*sp->stats.tx_deferred += le32_to_cpu(sp->lstats->tx_deferred);*/
+		sp->stats.collisions += le32_to_cpu(sp->lstats->tx_total_colls);
+		sp->stats.rx_crc_errors += le32_to_cpu(sp->lstats->rx_crc_errs);
+		sp->stats.rx_frame_errors += le32_to_cpu(sp->lstats->rx_align_errs);
+		sp->stats.rx_over_errors += le32_to_cpu(sp->lstats->rx_resource_errs);
+		sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats->rx_overrun_errs);
+		sp->stats.rx_length_errors += le32_to_cpu(sp->lstats->rx_runt_errs);
+		sp->lstats->done_marker = 0x0000;
+		if (test_bit(LINK_STATE_START, &dev->state)) {
 			wait_for_cmd_done(ioaddr + SCBCmd);
 			outw(CUDumpStats, ioaddr + SCBCmd);
 		}
@@ -1690,7 +1702,8 @@
 		sp->tx_skbuff[entry] = 0;			/* Redundant. */
 		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure);
 		sp->tx_ring[entry].link =
-			virt_to_le32bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
+			cpu_to_le32(sp->tx_ring_dma + ((entry + 1) % TX_RING_SIZE)
+				    * sizeof(struct TxFD));
 		config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
 		/* Construct a full CmdConfig frame. */
 		memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd));
@@ -1726,7 +1739,8 @@
 		sp->tx_skbuff[entry] = 0;
 		sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList);
 		sp->tx_ring[entry].link =
-			virt_to_le32bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
+			cpu_to_le32(sp->tx_ring_dma + ((entry + 1) % TX_RING_SIZE)
+				    * sizeof(struct TxFD));
 		sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
 		setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr;
 		*setup_params++ = cpu_to_le16(dev->mc_count*6);
@@ -1750,12 +1764,17 @@
 		struct descriptor *mc_setup_frm = sp->mc_setup_frm;
 		int i;
 
+		/* If we are busy, someone might be quickly adding to the MC list.
+		   Try again later when the list updates stop. */
+		if (sp->mc_setup_busy) {
+			sp->rx_mode = -1;
+			return;
+		}
 		if (sp->mc_setup_frm_len < 10 + dev->mc_count*6
 			|| sp->mc_setup_frm == NULL) {
 			/* Allocate a full setup frame, 10bytes + <max addrs>. */
 			if (sp->mc_setup_frm)
 				kfree(sp->mc_setup_frm);
-			sp->mc_setup_busy = 0;
 			sp->mc_setup_frm_len = 10 + multicast_filter_limit*6;
 			sp->mc_setup_frm = kmalloc(sp->mc_setup_frm_len, GFP_ATOMIC);
 			if (sp->mc_setup_frm == NULL) {
@@ -1765,12 +1784,6 @@
 				return;
 			}
 		}
-		/* If we are busy, someone might be quickly adding to the MC list.
-		   Try again later when the list updates stop. */
-		if (sp->mc_setup_busy) {
-			sp->rx_mode = -1;
-			return;
-		}
 		mc_setup_frm = sp->mc_setup_frm;
 		/* Fill the setup frame. */
 		if (speedo_debug > 1)
@@ -1796,16 +1809,18 @@
 		entry = sp->cur_tx++ % TX_RING_SIZE;
 		last_cmd = sp->last_cmd;
 		sp->last_cmd = mc_setup_frm;
-		sp->mc_setup_busy++;
+		sp->mc_setup_busy = 1;
 
 		/* Change the command to a NoOp, pointing to the CmdMulti command. */
 		sp->tx_skbuff[entry] = 0;
 		sp->tx_ring[entry].status = cpu_to_le32(CmdNOp);
-		sp->tx_ring[entry].link = virt_to_le32bus(mc_setup_frm);
+		sp->mc_setup_dma = pci_map_single(sp->pdev, mc_setup_frm, sp->mc_setup_frm_len);
+		sp->tx_ring[entry].link = cpu_to_le32(sp->mc_setup_dma);
 
 		/* Set the link in the setup frame. */
 		mc_setup_frm->link =
-			virt_to_le32bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE]));
+			cpu_to_le32(sp->tx_ring_dma + ((entry + 1) % TX_RING_SIZE)
+				    * sizeof(struct TxFD));
 
 		wait_for_cmd_done(ioaddr + SCBCmd);
 		clear_suspend(last_cmd);
@@ -1819,10 +1834,9 @@
 
 	sp->rx_mode = new_rx_mode;
 }
-
-#ifdef MODULE
 
-int init_module(void)
+
+static int __init eepro100_init_module(void)
 {
 	int cards_found;
 
@@ -1847,7 +1861,7 @@
 	return 0;
 }
 
-void cleanup_module(void)
+static void __exit eepro100_cleanup_module(void)
 {
 	struct net_device *next_dev;
 
@@ -1871,22 +1885,9 @@
 	}
 }
 
-#else   /* not MODULE */
+module_init(eepro100_init_module);
+module_exit(eepro100_cleanup_module);
 
-int eepro100_probe(void)
-{
-	int cards_found = 0;
-
-	cards_found = eepro100_init();
-
-	/* Only emit the version if the driver is being used. */
-	if (speedo_debug > 0  &&  cards_found)
-		printk(version);
-
-	return cards_found ? 0 : -ENODEV;
-}
-#endif  /* MODULE */
-
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` `[ -f ./pci-netif.h ] && echo -DHAS_PCI_NETIF`"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.3.42/linux/drivers/net/epic100.c	Thu Nov 11 20:11:40 1999
+++ linux/drivers/net/epic100.c	Thu Feb 10 12:22:03 2000
@@ -46,17 +46,7 @@
 #define TX_FIFO_THRESH 256		/* Rounded down to 4 byte units. */
 #define RX_FIFO_THRESH 1		/* 0-3, 0==32, 64,96, or 3==128 bytes  */
 
-#include <linux/version.h>		/* Evil, but neccessary */
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
@@ -65,11 +55,8 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE >= 0x20155
+#include <linux/init.h>
 #define PCI_SUPPORT_VER2
-#else
-#include <linux/bios32.h>
-#endif
 #include <linux/delay.h>
 
 #include <asm/processor.h>		/* Processor type for cache alignment. */
@@ -83,13 +70,8 @@
 /* Kernel compatibility defines, common to David Hind's PCMCIA package.
    This is only in the support-all-kernels source code. */
 
-#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000
-#warning This driver version is only for kernel versions 2.0.0 and later.
-#endif
-
 #define RUN_AT(x) (jiffies + (x))
 
-#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
 MODULE_PARM(debug, "i");
@@ -97,19 +79,7 @@
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else  /* Grrr, unneeded incompatible change. */
 #define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
 
 /* The I/O extent. */
 #define EPIC_TOTAL_SIZE 0x100
@@ -151,7 +121,7 @@
 
 /* The rest of these values should never change. */
 
-static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
+static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq,
 					  int chip_id, int card_idx);
 
 enum pci_flags_bit {
@@ -163,8 +133,9 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, pci_flags;
 	int io_size, min_latency;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn,
-							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(struct pci_dev *pdev,
+				     long ioaddr, int irq, int chip_idx,
+				     int fnd_cnt);
 } chip_tbl[] = {
 	{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
 	 PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
@@ -217,6 +188,8 @@
 	char devname[8];			/* Used only for kernel debugging. */
 	const char *product_name;
 	struct net_device *next_module;
+	
+	spinlock_t lock;
 
 	/* Tx and Rx rings here so that they remain paragraph aligned. */
 	struct epic_rx_desc rx_ring[RX_RING_SIZE];
@@ -273,7 +246,7 @@
 static struct net_device *root_epic_dev = NULL;
 
 #ifndef CARDBUS
-int epic100_probe(void)
+static int __init epic100_probe(void)
 {
 	int cards_found = 0;
 	int chip_idx, irq;
@@ -281,7 +254,6 @@
 	unsigned char pci_bus, pci_device_fn;
 	struct net_device *dev;
 
-#ifdef PCI_SUPPORT_VER2
 	struct pci_dev *pcidev = NULL;
 	while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
 			!= NULL) {
@@ -300,76 +272,33 @@
 		pci_bus = pcidev->bus->number;
 		pci_device_fn = pcidev->devfn;
 		irq = pcidev->irq;
-#else
-	int pci_index;
-
-	if ( ! pcibios_present())
-		return -ENODEV;
-
-	for (pci_index = 0; pci_index < 0xff; pci_index++) {
-		u8 pci_irq_line;
-		u16 vendor, device;
-		u32 pci_ioaddr;
-
-		if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-								pci_index, &pci_bus, &pci_device_fn)
-			!= PCIBIOS_SUCCESSFUL)
-			break;
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
-
-		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
-			if (vendor == chip_tbl[chip_idx].vendor_id
-				&& (device & chip_tbl[chip_idx].device_id_mask) ==
-				chip_tbl[chip_idx].device_id)
-				break;
-		if (chip_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
-			continue;
-
-		pcibios_read_config_dword(pci_bus, pci_device_fn,
-								  PCI_BASE_ADDRESS_0, &pci_ioaddr);
-		pcibios_read_config_byte(pci_bus, pci_device_fn,
-								 PCI_INTERRUPT_LINE, &pci_irq_line);
-		/* Remove I/O space marker in bit 0. */
-		pci_ioaddr &= ~3;
-		irq = pci_irq_line;
-
-		if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
-			continue;
-#endif
 
 		/* EPIC-specific code: Soft-reset the chip ere setting as master. */
 		outl(0x0001, pci_ioaddr + GENCTL);
 
 		/* Activate the card: fix for brain-damaged Win98 BIOSes. */
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_COMMAND, &pci_command);
+		pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
 		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled Ethernet"
 				   " device %4.4x-%4.4x."
 				   "  Updating PCI command %4.4x->%4.4x.\n",
 				   vendor, device, pci_command, new_command);
-			pcibios_write_config_word(pci_bus, pci_device_fn,
-									  PCI_COMMAND, new_command);
+			pci_write_config_word(pcidev, PCI_COMMAND, new_command);
 		}
 
-		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, pci_ioaddr,
-									   irq, chip_idx, cards_found);
+		dev = chip_tbl[chip_idx].probe1(pcidev, pci_ioaddr, irq,
+						chip_idx, cards_found);
 
 		/* Check the latency timer. */
 		if (dev) {
 			u8 pci_latency;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_LATENCY_TIMER, &pci_latency);
+			pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency);
 			if (pci_latency < chip_tbl[chip_idx].min_latency) {
 				printk(KERN_INFO "  PCI latency timer (CFLT) value of %d is "
 					   "unreasonably low, setting to %d.\n", pci_latency,
 					   chip_tbl[chip_idx].min_latency);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										  PCI_LATENCY_TIMER,
+				pci_write_config_byte(pcidev, PCI_LATENCY_TIMER,
 										  chip_tbl[chip_idx].min_latency);
 			}
 			dev = 0;
@@ -381,8 +310,8 @@
 }
 #endif  /* not CARDBUS */
 
-static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
-								  int chip_idx, int card_idx)
+static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq,
+				      int chip_idx, int card_idx)
 {
 	struct epic_private *ep;
 	int i, option = 0, duplex = 0;
@@ -444,13 +373,10 @@
 	ep->next_module = root_epic_dev;
 	root_epic_dev = dev;
 
-	ep->pci_bus = pci_bus;
-	ep->pci_dev_fn = pci_devfn;
-#if defined(PCI_SUPPORT_VER2)
-	ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device;
-#else
-	ep->chip_id = chip_tbl[chip_idx].device_id;
-#endif
+	ep->lock = SPIN_LOCK_UNLOCKED;
+	ep->pci_bus = pdev->bus->number;
+	ep->pci_dev_fn = pdev->devfn;
+	ep->chip_id = pdev->device;
 
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
@@ -497,6 +423,8 @@
 	dev->get_stats = &epic_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &mii_ioctl;
+	dev->tx_timeout = epic_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 
 	return dev;
 }
@@ -653,9 +581,7 @@
 	set_rx_mode(dev);
 	outl(0x000A, ioaddr + COMMAND);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
@@ -864,15 +790,6 @@
 	int entry;
 	u32 flag;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		epic_tx_timeout(dev);
-		return 1;
-	}
-
 	/* Caution: the write order is important here, set the base address
 	   with the "ownership" bits last. */
 
@@ -889,13 +806,13 @@
 	
 	if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
 	  flag = 0x10; /* No interrupt */
-	  clear_bit(0, (void*)&dev->tbusy);
+	  netif_start_queue(dev);
 	} else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
 	  flag = 0x14; /* Tx-done intr. */
-	  clear_bit(0, (void*)&dev->tbusy);
+	  netif_start_queue(dev);
 	} else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
 	  flag = 0x10; /* No Tx-done intr. */
-	  clear_bit(0, (void*)&dev->tbusy);
+	  netif_start_queue(dev);
 	} else {
 	  /* Leave room for two additional entries. */
 	  flag = 0x14; /* Tx-done intr. */
@@ -927,21 +844,7 @@
 	long ioaddr = dev->base_addr;
 	int status, boguscnt = max_interrupt_work;
 
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR "%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		dev->interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-#else
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
-	dev->interrupt = 1;
-#endif
+	spin_lock (&ep->lock);
 
 	do {
 		status = inl(ioaddr + INTSTAT);
@@ -1004,12 +907,12 @@
 			}
 #endif
 
-			if (ep->tx_full && dev->tbusy
-				&& dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
+			if (ep->tx_full &&
+			    test_bit(LINK_STATE_XOFF, &dev->flags) &&
+			    dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
 				/* The ring is no longer full, clear tbusy. */
 				ep->tx_full = 0;
-				clear_bit(0, (void*)&dev->tbusy);
-				mark_bh(NET_BH);
+				netif_wake_queue (dev);
 			}
 
 			ep->dirty_tx = dirty_tx;
@@ -1057,12 +960,7 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
 			   dev->name, inl(ioaddr + INTSTAT));
 
-#if defined(__i386__)
-	clear_bit(0, (void*)&dev->interrupt);
-#else
-	dev->interrupt = 0;
-#endif
-	return;
+	spin_unlock (&ep->lock);
 }
 
 static int epic_rx(struct net_device *dev)
@@ -1147,8 +1045,7 @@
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (epic_debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
@@ -1176,9 +1073,6 @@
 		ep->rx_ring[i].buflength = 0;
 		ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
 		if (skb) {
-#if LINUX_VERSION_CODE < 0x20100
-			skb->free = 1;
-#endif
 			DEV_FREE_SKB(skb);
 		}
 	}
@@ -1202,7 +1096,7 @@
 	struct epic_private *ep = (struct epic_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (dev->start) {
+	if (test_bit(LINK_STATE_START, &dev->state)) {
 		/* Update the error counts. */
 		ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
 		ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
@@ -1288,12 +1182,12 @@
 		data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f;
 		/* Fall Through */
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		if (! dev->start) {
+		if (! test_bit(LINK_STATE_START, &dev->state)) {
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 		}
 		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
-		if (! dev->start) {
+		if (! test_bit(LINK_STATE_START, &dev->state)) {
 #ifdef notdef
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
@@ -1303,12 +1197,12 @@
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
 		if (!suser())
 			return -EPERM;
-		if (! dev->start) {
+		if (! test_bit(LINK_STATE_START, &dev->state)) {
 			outl(0x0200, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 		}
 		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
-		if (! dev->start) {
+		if (! test_bit(LINK_STATE_START, &dev->state)) {
 #ifdef notdef
 			outl(0x0008, ioaddr + GENCTL);
 			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
@@ -1331,13 +1225,15 @@
 	u16 dev_id;
 	u32 io;
 	u8 bus, devfn, irq;
+	struct pci_dev *pdev;
 
 	if (loc->bus != LOC_PCI) return NULL;
-	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+	pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+	if (!pdev) return NULL;
 	printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
-	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
-	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	io = pdev->resource[0].start;
+	irq = pdev->irq;
+	dev_id = pdev->device;
 	io &= ~3;
 	if (io == 0 || irq == 0) {
 		printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not "
@@ -1407,10 +1303,8 @@
 
 #endif  /* Cardbus support */
 
-
-#ifdef MODULE
 
-int init_module(void)
+static int __init epic100_init_module(void)
 {
 	if (epic_debug)
 		printk(KERN_INFO "%s", version);
@@ -1423,7 +1317,7 @@
 #endif
 }
 
-void cleanup_module(void)
+static void __exit epic100_cleanup_module(void)
 {
 	struct net_device *next_dev;
 
@@ -1443,8 +1337,10 @@
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(epic100_init_module);
+module_exit(epic100_cleanup_module);
+
+
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ethertap.c linux/drivers/net/ethertap.c
--- v2.3.42/linux/drivers/net/ethertap.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ethertap.c	Wed Feb  9 20:08:09 2000
@@ -123,9 +123,7 @@
 		MOD_DEC_USE_COUNT;
 		return -ENOBUFS;
 	}
-
-	dev->start = 1;
-	dev->tbusy = 0;
+	netif_start_queue(dev);
 	return 0;
 }
 
@@ -319,8 +317,7 @@
 	if (ethertap_debug > 2)
 		printk("%s: Shutting down.\n", dev->name);
 
-	dev->tbusy = 1;
-	dev->start = 0;
+	netif_stop_queue(dev);
 
 	if (sk) {
 		lp->nl = NULL;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/gmac.c linux/drivers/net/gmac.c
--- v2.3.42/linux/drivers/net/gmac.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/gmac.c	Thu Feb 10 12:22:03 2000
@@ -0,0 +1,612 @@
+/*
+ * Network device driver for the GMAC ethernet controller on
+ * Apple G4 Powermacs.
+ *
+ * Copyright (C) 2000 Paul Mackerras.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include "gmac.h"
+
+#define DEBUG_PHY
+
+#define NTX		32		/* must be power of 2 */
+#define NRX		32		/* must be power of 2 */
+#define RX_BUFLEN	(ETH_FRAME_LEN + 8)
+
+struct gmac_dma_desc {
+	unsigned int	cmd;
+	unsigned int	status;
+	unsigned int	address;	/* phys addr, low 32 bits */
+	unsigned int	hi_addr;
+};
+
+/* Bits in cmd */
+#define RX_OWN	0x80000000		/* 1 = owned by chip */
+#define TX_SOP	0x80000000
+#define TX_EOP	0x40000000
+
+struct gmac {
+	volatile unsigned int *regs;	/* hardware registers, virtual addr */
+	volatile unsigned int *sysregs;
+	unsigned long	desc_page;	/* page for DMA descriptors */
+	volatile struct gmac_dma_desc *rxring;
+	struct sk_buff	*rx_buff[NRX];
+	int		next_rx;
+	volatile struct gmac_dma_desc *txring;
+	struct sk_buff	*tx_buff[NTX];
+	int		next_tx;
+	int		tx_gone;
+	unsigned char	tx_full;
+	int		phy_addr;
+	int		full_duplex;
+	struct net_device_stats stats;
+};
+
+#define GM_OUT(r, v)	out_le32(gm->regs + (r)/4, (v))
+#define GM_IN(r)	in_le32(gm->regs + (r)/4)
+#define GM_BIS(r, v)	GM_OUT((r), GM_IN(r) | (v))
+#define GM_BIC(r, v)	GM_OUT((r), GM_IN(r) & ~(v))
+
+#define PHY_B5400	0x6040
+#define PHY_B5201	0x6212
+
+static unsigned char dummy_buf[RX_BUFLEN+2];
+static struct net_device *gmacs = NULL;
+
+/* Prototypes */
+static int mii_read(struct gmac *gm, int phy, int r);
+static int mii_write(struct gmac *gm, int phy, int r, int v);
+static void powerup_transceiver(struct gmac *gm);
+static int gmac_reset(struct net_device *dev);
+static void gmac_mac_init(struct gmac *gm, unsigned char *mac_addr);
+static void gmac_init_rings(struct gmac *gm);
+static void gmac_start_dma(struct gmac *gm);
+static int gmac_open(struct net_device *dev);
+static int gmac_close(struct net_device *dev);
+static int gmac_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static int gmac_tx_cleanup(struct gmac *gm);
+static void gmac_receive(struct net_device *dev);
+static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct net_device_stats *gmac_stats(struct net_device *dev);
+static int gmac_probe(void);
+
+/* Stuff for talking to the physical-layer chip */
+static int
+mii_read(struct gmac *gm, int phy, int r)
+{
+	int timeout;
+
+	GM_OUT(MIFFRAME, 0x60020000 | (phy << 23) | (r << 18));
+	for (timeout = 1000; timeout > 0; --timeout) {
+		udelay(20);
+		if (GM_IN(MIFFRAME) & 0x10000)
+			return GM_IN(MIFFRAME) & 0xffff;
+	}
+	return -1;
+}
+
+static int
+mii_write(struct gmac *gm, int phy, int r, int v)
+{
+	int timeout;
+
+	GM_OUT(MIFFRAME, 0x50020000 | (phy << 23) | (r << 18) | (v & 0xffff));
+	for (timeout = 1000; timeout > 0; --timeout) {
+		udelay(20);
+		if (GM_IN(MIFFRAME) & 0x10000)
+			return 0;
+	}
+	return -1;
+}
+
+static void 
+mii_poll_start(struct gmac *gm)
+{
+	unsigned int tmp;
+	
+	/* Start the MIF polling on the external transceiver. */
+	tmp = GM_IN(MIFCONFIG);
+	tmp &= ~(GMAC_MIF_CFGPR_MASK | GMAC_MIF_CFGPD_MASK);
+	tmp |= ((gm->phy_addr & 0x1f) << GMAC_MIF_CFGPD_SHIFT);
+	tmp |= (0x19 << GMAC_MIF_CFGPR_SHIFT);
+	tmp |= GMAC_MIF_CFGPE;
+	GM_OUT(MIFCONFIG, tmp);
+
+	/* Let the bits set. */
+	udelay(GMAC_MIF_POLL_DELAY);
+
+	GM_OUT(MIFINTMASK, 0xffc0);
+}
+
+static void 
+mii_poll_stop(struct gmac *gm)
+{
+	GM_OUT(MIFINTMASK, 0xffff);
+	GM_BIC(MIFCONFIG, GMAC_MIF_CFGPE);
+	udelay(GMAC_MIF_POLL_DELAY);
+}
+
+static void
+mii_interrupt(struct gmac *gm)
+{
+	unsigned long	flags;
+	int		phy_status;
+	
+	save_flags(flags);
+	cli();
+
+	mii_poll_stop(gm);
+
+	/* May the status change before polling is re-enabled ? */
+	mii_poll_start(gm);
+	
+	/* We read the Auxilliary Status Summary register */
+	phy_status = mii_read(gm, gm->phy_addr, 0x19);
+#ifdef DEBUG_PHY
+	printk("mii_interrupt, phy_status: %x\n", phy_status);
+#endif
+	/* Auto-neg. complete ? */
+	if (phy_status & 0x8000) {
+		int full_duplex = 0;
+		switch((phy_status >> 8) & 0x7) {
+			case 2:
+			case 5:
+				full_duplex = 1;
+				break;
+		}
+		if (full_duplex != gm->full_duplex) {
+			GM_BIC(TXMAC_CONFIG, 1);
+			udelay(200);
+			if (full_duplex) {
+				printk("full duplex active\n");
+				GM_OUT(TXMAC_CONFIG, 6);
+				GM_OUT(XIF_CONFIG, 1);
+			} else {
+				printk("half duplex active\n");
+				GM_OUT(TXMAC_CONFIG, 0);
+				GM_OUT(XIF_CONFIG, 5);
+			}
+			GM_BIS(TXMAC_CONFIG, 1);
+			gm->full_duplex = full_duplex;
+		}
+	}
+
+	restore_flags(flags);
+}
+
+static void
+powerup_transceiver(struct gmac *gm)
+{
+	int phytype = mii_read(gm, 0, 3);
+#ifdef DEBUG_PHY
+	int i;
+#endif	
+	switch (phytype) {
+	case PHY_B5400:
+		mii_write(gm, 0, 0, mii_read(gm, 0, 0) & ~0x800);
+		mii_write(gm, 31, 30, mii_read(gm, 31, 30) & ~8);
+		break;
+	case PHY_B5201:
+		mii_write(gm, 0, 30, mii_read(gm, 0, 30) & ~8);
+		break;
+	default:
+		printk(KERN_ERR "GMAC: unknown PHY type %x\n", phytype);
+	}
+	/* Check this */
+	gm->phy_addr = 0;
+	gm->full_duplex = 0;
+
+#ifdef DEBUG_PHY
+	printk("PHY regs:\n");
+	for (i=0; i<0x20; i++) {
+		printk("%04x ", mii_read(gm, 0, i)); 
+		if ((i % 4) == 3)
+			printk("\n");
+	}
+#endif
+}
+
+static int
+gmac_reset(struct net_device *dev)
+{
+	struct gmac *gm = (struct gmac *) dev->priv;
+	int timeout;
+
+	/* turn on GB clock */
+	out_le32(gm->sysregs + 0x20/4, in_le32(gm->sysregs + 0x20/4) | 2);
+	udelay(10);
+	GM_OUT(SW_RESET, 3);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mdelay(10);
+		if ((GM_IN(SW_RESET) & 3) == 0)
+			return 0;
+	}
+	printk(KERN_ERR "GMAC: reset failed!\n");
+	return -1;
+}
+
+static void
+gmac_mac_init(struct gmac *gm, unsigned char *mac_addr)
+{
+	int i;
+
+	GM_OUT(RANSEED, 937);
+	GM_OUT(DATAPATHMODE, 4);
+	mii_write(gm, 0, 0, 0x1000);
+	GM_OUT(TXDMA_CONFIG, 0xffc00);
+	GM_OUT(RXDMA_CONFIG, 0);
+	GM_OUT(MACPAUSE, 0x1bf0);
+	GM_OUT(IPG0, 0);
+	GM_OUT(IPG1, 8);
+	GM_OUT(IPG2, 4);
+	GM_OUT(MINFRAMESIZE, 64);
+	GM_OUT(MAXFRAMESIZE, 2000);
+	GM_OUT(PASIZE, 7);
+	GM_OUT(JAMSIZE, 4);
+	GM_OUT(ATTEMPT_LIMIT, 16);
+	GM_OUT(SLOTTIME, 64);
+	GM_OUT(MACCNTL_TYPE, 0x8808);
+	GM_OUT(MAC_ADDR_0, (mac_addr[4] << 8) + mac_addr[5]);
+	GM_OUT(MAC_ADDR_1, (mac_addr[2] << 8) + mac_addr[3]);
+	GM_OUT(MAC_ADDR_2, (mac_addr[0] << 8) + mac_addr[1]);
+	GM_OUT(MAC_ADDR_3, 0);
+	GM_OUT(MAC_ADDR_4, 0);
+	GM_OUT(MAC_ADDR_5, 0);
+	GM_OUT(MAC_ADDR_6, 0x0180);
+	GM_OUT(MAC_ADDR_7, 0xc200);
+	GM_OUT(MAC_ADDR_8, 0x0001);
+	GM_OUT(MAC_ADDR_FILTER_0, 0);
+	GM_OUT(MAC_ADDR_FILTER_1, 0);
+	GM_OUT(MAC_ADDR_FILTER_2, 0);
+	GM_OUT(MAC_ADDR_FILTER_MASK21, 0);
+	GM_OUT(MAC_ADDR_FILTER_MASK0, 0);
+	for (i = 0; i < 27; ++i)
+		GM_OUT(MAC_HASHTABLE + i, 0);
+	GM_OUT(MACCNTL_CONFIG, 0);
+	/* default to half duplex */
+	GM_OUT(TXMAC_CONFIG, 0);
+	GM_OUT(XIF_CONFIG, 5);
+}
+
+static void
+gmac_init_rings(struct gmac *gm)
+{
+	int i;
+	struct sk_buff *skb;
+	unsigned char *data;
+	struct gmac_dma_desc *ring;
+
+	/* init rx ring */
+	ring = (struct gmac_dma_desc *) gm->rxring;
+	memset(ring, 0, NRX * sizeof(struct gmac_dma_desc));
+	for (i = 0; i < NRX; ++i, ++ring) {
+		data = dummy_buf;
+		gm->rx_buff[i] = skb = dev_alloc_skb(RX_BUFLEN + 2);
+		if (skb != 0) {
+			/*skb_reserve(skb, 2);*/
+			data = skb->data;
+		}
+		st_le32(&ring->address, virt_to_bus(data));
+		st_le32(&ring->cmd, RX_OWN);
+	}
+
+	/* init tx ring */
+	ring = (struct gmac_dma_desc *) gm->txring;
+	memset(ring, 0, NRX * sizeof(struct gmac_dma_desc));
+
+	/* set pointers in chip */
+	mb();
+	GM_OUT(RXDMA_BASE_HIGH, 0);
+	GM_OUT(RXDMA_BASE_LOW, virt_to_bus(gm->rxring));
+	GM_OUT(TXDMA_BASE_HIGH, 0);
+	GM_OUT(TXDMA_BASE_LOW, virt_to_bus(gm->txring));
+}
+
+static void
+gmac_start_dma(struct gmac *gm)
+{
+	GM_BIS(RXDMA_CONFIG, 1);
+	GM_BIS(RXMAC_CONFIG, 1);
+	GM_OUT(RXDMA_KICK, NRX);
+	GM_BIS(TXDMA_CONFIG, 1);
+	GM_BIS(TXMAC_CONFIG, 1);
+}
+
+static int gmac_open(struct net_device *dev)
+{
+	struct gmac *gm = (struct gmac *) dev->priv;
+
+	if (gmac_reset(dev))
+		return -EIO;
+
+	MOD_INC_USE_COUNT;
+
+	powerup_transceiver(gm);
+	gmac_mac_init(gm, dev->dev_addr);
+	gmac_init_rings(gm);
+	gmac_start_dma(gm);
+	mii_interrupt(gm);
+
+	GM_OUT(INTR_DISABLE, 0xfffdffe8);
+
+	return 0;
+}
+
+static int gmac_close(struct net_device *dev)
+{
+	struct gmac *gm = (struct gmac *) dev->priv;
+	int i;
+
+	mii_poll_stop(gm);
+	
+	GM_BIC(RXDMA_CONFIG, 1);
+	GM_BIC(RXMAC_CONFIG, 1);
+	GM_BIC(TXDMA_CONFIG, 1);
+	GM_BIC(TXMAC_CONFIG, 1);
+	GM_OUT(INTR_DISABLE, ~0U);
+	for (i = 0; i < NRX; ++i) {
+		if (gm->rx_buff[i] != 0) {
+			dev_kfree_skb(gm->rx_buff[i]);
+			gm->rx_buff[i] = 0;
+		}
+	}
+	for (i = 0; i < NTX; ++i) {
+		if (gm->tx_buff[i] != 0) {
+			dev_kfree_skb(gm->tx_buff[i]);
+			gm->tx_buff[i] = 0;
+		}
+	}
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int gmac_xmit_start(struct sk_buff *skb, struct net_device *dev)
+{
+	struct gmac *gm = (struct gmac *) dev->priv;
+	volatile struct gmac_dma_desc *dp;
+	unsigned long flags;
+	int i;
+
+	save_flags(flags); cli();
+	i = gm->next_tx;
+	if (gm->tx_buff[i] != 0) {
+		/* buffer is full, can't send this packet at the moment */
+		dev->tbusy = 1;
+		gm->tx_full = 1;
+		restore_flags(flags);
+		return 1;
+	}
+	gm->next_tx = (i + 1) & (NTX - 1);
+	gm->tx_buff[i] = skb;
+	restore_flags(flags);
+
+	dp = &gm->txring[i];
+	dp->status = 0;
+	dp->hi_addr = 0;
+	st_le32(&dp->address, virt_to_bus(skb->data));
+	mb();
+	st_le32(&dp->cmd, TX_SOP | TX_EOP | skb->len);
+	mb();
+
+	GM_OUT(TXDMA_KICK, gm->next_tx);
+
+	return 0;
+}
+
+static int gmac_tx_cleanup(struct gmac *gm)
+{
+	int i = gm->tx_gone;
+	volatile struct gmac_dma_desc *dp;
+	struct sk_buff *skb;
+	int ret = 0;
+	int gone = GM_IN(TXDMA_COMPLETE);
+
+	while (i != gone) {
+		skb = gm->tx_buff[i];
+		if (skb == NULL)
+			break;
+		dp = &gm->txring[i];
+		gm->stats.tx_bytes += skb->len;
+		++gm->stats.tx_packets;
+		gm->tx_buff[i] = NULL;
+		dev_kfree_skb(skb);
+		if (++i >= NTX)
+			i = 0;
+	}
+	if (i != gm->tx_gone) {
+		ret = gm->tx_full;
+		gm->tx_gone = i;
+		gm->tx_full = 0;
+	}
+	return ret;
+}
+
+static void gmac_receive(struct net_device *dev)
+{
+	struct gmac *gm = (struct gmac *) dev->priv;
+	int i = gm->next_rx;
+	volatile struct gmac_dma_desc *dp;
+	struct sk_buff *skb;
+	int len;
+	unsigned char *data;
+
+	for (;;) {
+		dp = &gm->rxring[i];
+		if (ld_le32(&dp->cmd) & RX_OWN)
+			break;
+		len = (ld_le32(&dp->cmd) >> 16) & 0x7fff;
+		skb = gm->rx_buff[i];
+		if (skb == 0) {
+			++gm->stats.rx_dropped;
+		} else if (ld_le32(&dp->status) & 0x40000000) {
+			++gm->stats.rx_errors;
+			dev_kfree_skb(skb);
+		} else {
+			skb_put(skb, len);
+			skb->dev = dev;
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			gm->stats.rx_bytes += skb->len;
+			++gm->stats.rx_packets;
+		}
+		data = dummy_buf;
+		gm->rx_buff[i] = skb = dev_alloc_skb(RX_BUFLEN + 2);
+		if (skb != 0) {
+			/*skb_reserve(skb, 2);*/
+			data = skb->data;
+		}
+		st_le32(&dp->address, virt_to_bus(data));
+		dp->hi_addr = 0;
+		mb();
+		st_le32(&dp->cmd, RX_OWN);
+		if (++i >= NRX)
+			i = 0;
+	}
+	gm->next_rx = i;
+}
+
+static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct gmac *gm = (struct gmac *) dev->priv;
+	unsigned int status;
+
+	status = GM_IN(INTR_STATUS);
+	GM_OUT(INTR_ACK, status);
+	
+	if (status & GMAC_IRQ_MIF) {
+		mii_interrupt(gm);
+	}
+	gmac_receive(dev);
+	if (gmac_tx_cleanup(gm)){
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
+	}
+}
+
+static struct net_device_stats *gmac_stats(struct net_device *dev)
+{
+	struct gmac *gm = (struct gmac *) dev->priv;
+
+	return &gm->stats;
+}
+
+static int __init gmac_probe(void)
+{
+	static int gmacs_found;
+	static struct device_node *next_gmac;
+	struct device_node *gmac;
+	struct gmac *gm;
+	unsigned long descpage;
+	unsigned char *addr;
+	int i;
+
+	if (gmacs != NULL)
+		return -EBUSY;
+
+	/*
+	 * We could (and maybe should) do this using PCI scanning
+	 * for vendor/net_device ID 0x106b/0x21.
+	 */
+	if (!gmacs_found) {
+		next_gmac = find_compatible_devices("network", "gmac");
+		gmacs_found = 1;
+	}
+	if ((gmac = next_gmac) == 0)
+		return -ENODEV;
+	next_gmac = gmac->next;
+
+	if (gmac->n_addrs < 1 || gmac->n_intrs < 1) {
+		printk(KERN_ERR "can't use GMAC %s: %d addrs and %d intrs\n",
+		       gmac->full_name, gmac->n_addrs, gmac->n_intrs);
+		return -ENODEV;
+	}
+
+	dev = init_etherdev(0, sizeof(struct gmac));
+	memset(dev->priv, 0, sizeof(struct gmac));
+
+	gm = (struct gmac *) dev->priv;
+	dev->base_addr = gmac->addrs[0].address;
+	gm->regs = (volatile unsigned int *)
+		ioremap(gmac->addrs[0].address, 0x10000);
+	gm->sysregs = (volatile unsigned int *) ioremap(0xf8000000, 0x1000);
+	dev->irq = gmac->intrs[0].line;
+
+	addr = get_property(gmac, "local-mac-address", NULL);
+	if (addr == NULL) {
+		printk(KERN_ERR "Can't get mac-address for GMAC %s\n",
+		       gmac->full_name);
+		return -EAGAIN;
+	}
+
+	printk(KERN_INFO "%s: GMAC at", dev->name);
+	for (i = 0; i < 6; ++i) {
+		dev->dev_addr[i] = addr[i];
+		printk("%c%.2x", (i? ':': ' '), addr[i]);
+	}
+	printk("\n");
+
+	descpage = get_free_page(GFP_KERNEL);
+	if (descpage == 0) {
+		printk(KERN_ERR "GMAC: can't get a page for descriptors\n");
+		return -EAGAIN;
+	}
+
+	gm->desc_page = descpage;
+	gm->rxring = (volatile struct gmac_dma_desc *) descpage;
+	gm->txring = (volatile struct gmac_dma_desc *) (descpage + 0x800);
+
+	gm->phy_addr = 0;
+	
+	dev->open = gmac_open;
+	dev->stop = gmac_close;
+	dev->hard_start_xmit = gmac_xmit_start;
+	dev->get_stats = gmac_stats;
+
+	ether_setup(dev);
+
+	if (request_irq(dev->irq, gmac_interrupt, 0, "GMAC", dev)) {
+		printk(KERN_ERR "GMAC: can't get irq %d\n", dev->irq);
+		return -EAGAIN;
+	}
+
+	gmacs = dev;
+
+	return 0;
+}
+
+MODULE_AUTHOR("Paul Mackerras");
+MODULE_DESCRIPTION("PowerMac GMAC driver.");
+
+
+static void __exit gmac_cleanup_module(void)
+{
+	struct gmac *gm;
+
+	/* XXX should handle more than one */
+	if (gmacs == NULL)
+		return;
+
+	gm = (struct gmac *) gmacs->priv;
+	free_irq(gmacs->irq, gmac_interrupt);
+	free_page(gm->descpage);
+	unregister_netdev(gmacs);
+	kfree(gmacs);
+	gmacs = NULL;
+}
+
+module_init(gmac_probe);
+module_exit(gmac_cleanup_module);
+
diff -u --recursive --new-file v2.3.42/linux/drivers/net/gmac.h linux/drivers/net/gmac.h
--- v2.3.42/linux/drivers/net/gmac.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/gmac.h	Wed Feb  9 19:43:53 2000
@@ -0,0 +1,113 @@
+/*
+ * Definitions for the GMAC ethernet chip, used in the
+ * Apple G4 powermac.
+ */
+
+/* Register offsets */
+#define	INTR_STATUS		0x000c
+#define INTR_DISABLE		0x0010
+#define INTR_ACK		0x0014
+#define SW_RESET		0x1010
+#define TXDMA_KICK		0x2000
+#define TXDMA_CONFIG		0x2004
+#define TXDMA_BASE_LOW		0x2008
+#define TXDMA_BASE_HIGH		0x200c
+#define TXDMA_STATE_MACH	0x2028
+#define TXDMA_COMPLETE		0x2100
+#define RXDMA_CONFIG		0x4000
+#define RXDMA_BASE_LOW		0x4004
+#define RXDMA_BASE_HIGH		0x4008
+#define RXDMA_KICK		0x4100
+#define MACPAUSE		0x6008
+#define TXMAC_STATUS		0x6010
+#define TXMAC_CONFIG		0x6030
+#define RXMAC_CONFIG		0x6034
+#define MACCNTL_CONFIG		0x6038
+#define XIF_CONFIG		0x603c
+#define IPG0			0x6040
+#define IPG1			0x6044
+#define IPG2			0x6048
+#define SLOTTIME		0x604c
+#define MINFRAMESIZE		0x6050
+#define MAXFRAMESIZE		0x6054
+#define PASIZE			0x6058
+#define JAMSIZE			0x605c
+#define ATTEMPT_LIMIT		0x6060
+#define MACCNTL_TYPE		0x6064
+#define MAC_ADDR_0		0x6080
+#define MAC_ADDR_1		0x6084
+#define MAC_ADDR_2		0x6088
+#define MAC_ADDR_3		0x608c
+#define MAC_ADDR_4		0x6090
+#define MAC_ADDR_5		0x6094
+#define MAC_ADDR_6		0x6098
+#define MAC_ADDR_7		0x609c
+#define MAC_ADDR_8		0x60a0
+#define MAC_ADDR_FILTER_0	0x60a4
+#define MAC_ADDR_FILTER_1	0x60a8
+#define MAC_ADDR_FILTER_2	0x60ac
+#define MAC_ADDR_FILTER_MASK21	0x60b0
+#define MAC_ADDR_FILTER_MASK0	0x60b4
+#define MAC_HASHTABLE		0x60c0
+#define RANSEED			0x6130
+#define MIFFRAME		0x620c
+#define MIFCONFIG		0x6210
+#define MIFINTMASK		0x6214
+#define MIFSTATUS		0x6218
+#define DATAPATHMODE		0x9050
+
+/* -- 0x000C	R-C	Global Interrupt status. 
+ * d: 0x00000000	bits 0-6 cleared on read (C)
+ */
+#define GMAC_IRQ_TX_INT_ME	0x00000001	/* C Frame with INT_ME bit set in fifo */
+#define GMAC_IRQ_TX_ALL		0x00000002	/* C TX descriptor ring empty */
+#define GMAC_IRQ_TX_DONE	0x00000004	/* C moved from host to TX fifo */
+#define GMAC_IRQ_RX_DONE	0x00000010	/* C moved from RX fifo to host */
+#define GMAC_IRQ_RX_NO_BUF	0x00000020	/* C No RX buffer available */
+#define GMAC_IRQ_RX_TAG_ERR	0x00000040	/* C RX tag error */
+
+#define GMAC_IRQ_PCS		0x00002000	/* PCS interrupt ? */
+#define GMAC_IRQ_MAC_TX		0x00004000	/* MAC tx register set */
+#define GMAC_IRQ_MAC_RX		0x00008000	/* MAC rx register set  */
+#define GMAC_IRQ_MAC_CTRL	0x00010000	/* MAC control register set  */
+#define GMAC_IRQ_MIF		0x00020000	/* MIF status register set */
+#define GMAC_IRQ_BUS_ERROR	0x00040000	/* Bus error status register set */
+
+#define GMAC_IRQ_TX_COMP	0xfff80000	/* TX completion mask */
+
+/* -- 0x6210	RW	MIF config reg
+ */
+
+#define	GMAC_MIF_CFGPS			0x00000001	/* PHY Select */
+#define	GMAC_MIF_CFGPE			0x00000002	/* Poll Enable */
+#define	GMAC_MIF_CFGBB			0x00000004	/* Bit Bang Enable */
+#define	GMAC_MIF_CFGPR_MASK		0x000000f8	/* Poll Register address */
+#define	GMAC_MIF_CFGPR_SHIFT		3
+#define	GMAC_MIF_CFGM0			0x00000100	/* MDIO_0 Data / MDIO_0 attached */
+#define	GMAC_MIF_CFGM1			0x00000200	/* MDIO_1 Data / MDIO_1 attached */
+#define	GMAC_MIF_CFGPD_MASK		0x00007c00	/* Poll Device PHY address */
+#define	GMAC_MIF_CFGPD_SHIFT		10
+
+#define	GMAC_MIF_POLL_DELAY		200
+
+#define	GMAC_INTERNAL_PHYAD		1		/* PHY address for int. transceiver */
+#define	GMAC_EXTERNAL_PHYAD		0		/* PHY address for ext. transceiver */
+
+
+/* -- 0x6214	RW	MIF interrupt mask reg
+ *			same as basic/status Register
+ */
+
+/* -- 0x6214	RW	MIF basic/status reg
+ *			The Basic portion of this register indicates the last
+ *			value of the register read indicated in the POLL REG field
+ *			of the Configuration Register.
+ *			The Status portion indicates bit(s) that have changed.
+ *			The MIF Mask register is corresponding to this register in
+ *			terms of the bit(s) that need to be masked for generating
+ *			interrupt on the MIF Interrupt Bit of the Global Status Rgister.
+ */
+
+#define	GMAC_MIF_STATUS			0x0000ffff	/* 0-15 : Status */
+#define	GMAC_MIF_BASIC			0xffff0000	/* 16-31 : Basic register */
+
diff -u --recursive --new-file v2.3.42/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.3.42/linux/drivers/net/hp100.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/net/hp100.c	Thu Feb 10 12:24:54 2000
@@ -96,6 +96,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/spinlock.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -177,6 +178,7 @@
 
 struct hp100_private {
   struct hp100_eisa_id *id;
+  spinlock_t lock;
   u_short chip;
   u_short soft_model;
   u_int memory_size; 
@@ -192,7 +194,7 @@
   struct pci_dev *pci_dev;
 #endif
   short mem_mapped;	  /* memory mapped access */
-  u32 *mem_ptr_virt;    /* virtual memory mapped area, maybe NULL */
+  void *mem_ptr_virt;    /* virtual memory mapped area, maybe NULL */
   unsigned long mem_ptr_phys;	  /* physical memory mapped area */
   short lan_type;	  /* 10Mb/s, 100Mb/s or -1 (error) */
   int hub_status;	  /* was login to hub successful? */
@@ -308,7 +310,7 @@
 static hp100_stats_t *hp100_get_stats( struct net_device *dev );
 static void hp100_misc_interrupt( struct net_device *dev );
 static void hp100_update_stats( struct net_device *dev );
-static void hp100_clear_stats( int ioaddr );
+static void hp100_clear_stats( struct hp100_private *lp, int ioaddr );
 static void hp100_set_multicast_list( struct net_device *dev);
 static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs );
 static void hp100_start_interface( struct net_device *dev );
@@ -533,7 +535,7 @@
   u_short local_mode, lsw;
   short mem_mapped;
   unsigned long mem_ptr_phys;
-  u32 **mem_ptr_virt;
+  void **mem_ptr_virt;
   struct hp100_private *lp;
   struct hp100_eisa_id *eid;
 
@@ -761,7 +763,7 @@
 		  else
 		    {
 #ifdef HP100_DEBUG
-		      printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to 0x%lx.\n", dev->name, virt_memory_size, mem_ptr_phys, (u_long)mem_ptr_virt);
+		      printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to %p.\n", dev->name, virt_memory_size, mem_ptr_phys, mem_ptr_virt);
 #endif
 		      break;
 		    }
@@ -792,6 +794,7 @@
 
   lp = (struct hp100_private *)dev->priv;
   memset( lp, 0, sizeof( struct hp100_private ) );
+  lp->lock = SPIN_LOCK_UNLOCKED;
   lp->id = eid;
   lp->chip = chip;
   lp->mode = local_mode;
@@ -855,7 +858,7 @@
     dev->dev_addr[ i ] = hp100_inb( LAN_ADDR + i );
 
   /* Reset statistics (counters) */
-  hp100_clear_stats( ioaddr );
+  hp100_clear_stats( lp, ioaddr );
 
   ether_setup( dev );
 
@@ -914,7 +917,7 @@
               dev->name,mem_ptr_phys,
               (mem_ptr_phys+(mem_ptr_phys>0x100000?(u_long)lp->memory_size:16*1024))-1 );
       if ( mem_ptr_virt )
-	printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt );
+	printk( " (virtual base %p)", mem_ptr_virt );
       printk( ".\n" );
 
       /* Set for info when doing ifconfig */
@@ -1252,10 +1255,8 @@
 
   MOD_INC_USE_COUNT;
 
-  dev->tbusy = 0;
   dev->trans_start = jiffies;
-  dev->interrupt = 0;
-  dev->start = 1;
+  netif_start_queue(dev);
 
   lp->lan_type = hp100_sense_lan( dev );
   lp->mac1_mode = HP100_MAC1MODE3;
@@ -1291,8 +1292,7 @@
   if ( lp->lan_type == HP100_LAN_100 ) 
     lp->hub_status=hp100_login_to_vg_hub( dev, FALSE );
 
-  dev->tbusy = 1;
-  dev->start = 0;
+  netif_stop_queue(dev);
 
   free_irq( dev->irq, dev );
 
@@ -1724,8 +1724,7 @@
    * we have to turn int's off before modifying this, otherwise
    * a tx_pdl_cleanup could occur at the same time
    */
-  save_flags( flags );
-  cli();
+  spin_lock_irqsave (&lp->lock, flags);
   ringptr=lp->txrtail;
   lp->txrtail=ringptr->next;
 	
@@ -1751,7 +1750,7 @@
   hp100_outl( ringptr->pdl_paddr, TX_PDA_L ); /* Low Prio. Queue */
 	
   lp->txrcommit++;
-  restore_flags( flags );
+  spin_unlock_irqrestore (&lp->lock, flags);
 	
   /* Update statistics */	
   lp->stats.tx_packets++;
@@ -1931,9 +1930,9 @@
       if ( lp->mem_ptr_virt ) /* high pci memory was remapped */
 	{
 	  /* Note: The J2585B needs alignment to 32bits here!  */
-	  memcpy( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 );
+	  memcpy_toio( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 );
 	  if ( !ok_flag )
-	    memset( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len );
+	    memset_io( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len );
 	}
       else
 	{
@@ -2060,7 +2059,7 @@
 	  if ( lp->mode==2 )
             {
               if ( lp->mem_ptr_virt )
-                memcpy( ptr, lp->mem_ptr_virt, pkt_len );
+                memcpy_fromio( ptr, lp->mem_ptr_virt, pkt_len );
               /* Note alignment to 32bit transfers */
               else
                 isa_memcpy_fromio( ptr, lp->mem_ptr_phys, pkt_len );
@@ -2284,7 +2283,7 @@
   lp->stats.tx_errors++;
 }
 
-static void hp100_clear_stats( int ioaddr )
+static void hp100_clear_stats( struct hp100_private *lp, int ioaddr )
 {
   unsigned long flags;
 
@@ -2293,14 +2292,13 @@
   printk("hp100: %s: clear_stats\n", dev->name);
 #endif
 
-  save_flags( flags );
-  cli();
+  spin_lock_irqsave (&lp->lock, flags);
   hp100_page( MAC_CTRL );    /* get all statistics bytes */
   hp100_inw( DROPPED );
   hp100_inb( CRC );
   hp100_inb( ABORT );
   hp100_page( PERFORMANCE );
-  restore_flags( flags );
+  spin_unlock_irqrestore (&lp->lock, flags);
 }
 
 
@@ -2323,8 +2321,7 @@
   printk("hp100: %s: set_mc_list\n", dev->name);
 #endif
 
-  save_flags( flags );
-  cli();
+  spin_lock_irqsave (&lp->lock, flags);
   hp100_ints_off();
   hp100_page( MAC_CTRL );
   hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 );  /* stop rx/tx */
@@ -2457,7 +2454,7 @@
 
   hp100_page( PERFORMANCE );
   hp100_ints_on();
-  restore_flags( flags );
+  spin_unlock_irqrestore (&lp->lock, flags);
 }
 
 
@@ -2475,11 +2472,10 @@
 
   if ( dev == NULL ) return;
   ioaddr = dev->base_addr;
+  
+  spin_lock (&lp->lock);
 
-  if ( dev->interrupt )
-    printk( "hp100: %s: re-entering the interrupt handler\n", dev->name );
   hp100_ints_off();
-  dev->interrupt = 1;          /* mark that we are inside the handler */
 
 #ifdef HP100_DEBUG_B
   hp100_outw( 0x4219, TRACE );
@@ -2501,7 +2497,7 @@
 
   if(val==0) /* might be a shared interrupt */ 
     {
-      dev->interrupt=0;
+      spin_unlock (&lp->lock);
       hp100_ints_on();
       return;
     }
@@ -2598,8 +2594,8 @@
 	}
       hp100_misc_interrupt( dev );
     }
-	
-  dev->interrupt = 0;
+
+  spin_unlock (&lp->lock);	
   hp100_ints_on();
 }
 
@@ -2619,8 +2615,7 @@
   printk("hp100: %s: hp100_start_interface\n",dev->name);
 #endif
 
-  save_flags( flags );
-  cli();
+  spin_lock_irqsave (&lp->lock, flags);
 
   /* Ensure the adapter does not want to request an interrupt when */
   /* enabling the IRQ line to be active on the bus (i.e. not tri-stated) */
@@ -2671,7 +2666,7 @@
   /* Enable MAC Tx and RX, set MAC modes, ... */
   hp100_set_multicast_list( dev );
 
-  restore_flags( flags );
+  spin_unlock_irqrestore (&lp->lock, flags);
 }
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c
--- v2.3.42/linux/drivers/net/irda/nsc-ircc.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/irda/nsc-ircc.c	Tue Feb  8 18:48:39 2000
@@ -41,9 +41,7 @@
  *     
  ********************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
@@ -58,9 +56,7 @@
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
+#include <linux/pm.h>
 
 #include <net/irda/wrapper.h>
 #include <net/irda/irda.h>
@@ -144,9 +140,7 @@
 static int  nsc_ircc_net_close(struct net_device *dev);
 static int  nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
-#ifdef CONFIG_APM
-static int nsc_ircc_apmproc(apm_event_t event);
-#endif /* CONFIG_APM */
+static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 
 /*
  * Function nsc_ircc_init ()
@@ -216,11 +210,6 @@
 		} 
 		
 	}
-#ifdef CONFIG_APM
-	/* Make sure at least one chip was found before enabling APM */
-	if (ret == 0)
-		apm_register_callback(nsc_ircc_apmproc);
-#endif /* CONFIG_APM */
 
 	return ret;
 }
@@ -236,9 +225,7 @@
 {
 	int i;
 
-#ifdef CONFIG_APM
-	apm_unregister_callback(nsc_ircc_apmproc);
-#endif /* CONFIG_APM */
+	pm_unregister_all(nsc_ircc_pmproc);
 
 	for (i=0; i < 4; i++) {
 		if (dev_self[i])
@@ -257,6 +244,7 @@
 {
 	struct net_device *dev;
 	struct nsc_ircc_cb *self;
+        struct pm_dev *pmdev;
 	int ret;
 	int err;
 
@@ -380,6 +368,10 @@
 	self->io.dongle_id = dongle_id;
 	nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
 
+        pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc);
+        if (pmdev)
+                pmdev->data = self;
+
 	return 0;
 }
 
@@ -1984,7 +1976,6 @@
 	return &self->stats;
 }
 
-#ifdef CONFIG_APM
 static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
 {
 	MESSAGE("%s, Suspending\n", driver_name);
@@ -2019,36 +2010,21 @@
 	self->io.suspended = 0;
 }
 
-static int nsc_ircc_apmproc(apm_event_t event)
+static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-	static int down = 0; /* Filter out double events */
-	int i;
-
-	switch (event) {
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-		if (!down) {			
-			for (i=0; i<4; i++) {
-				if (dev_self[i])
-					nsc_ircc_suspend(dev_self[i]);
-			}
-		}
-		down = 1;
-		break;
-	case APM_NORMAL_RESUME:
-	case APM_CRITICAL_RESUME:
-		if (down) {
-			for (i=0; i<4; i++) {
-				if (dev_self[i])
-					nsc_ircc_wakeup(dev_self[i]);
-			}
-		}
-		down = 0;
-		break;
-	}
+        struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data;
+        if (self) {
+                switch (rqst) {
+                case PM_SUSPEND:
+                        nsc_ircc_suspend(self);
+                        break;
+                case PM_RESUME:
+                        nsc_ircc_wakeup(self);
+                        break;
+                }
+        }
 	return 0;
 }
-#endif /* CONFIG_APM */
 
 #ifdef MODULE
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
diff -u --recursive --new-file v2.3.42/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.3.42/linux/drivers/net/irda/smc-ircc.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/irda/smc-ircc.c	Tue Feb  8 18:48:47 2000
@@ -33,9 +33,7 @@
  *
  ********************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
@@ -51,9 +49,7 @@
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
+#include <linux/pm.h>
 
 #include <net/irda/wrapper.h>
 #include <net/irda/irda.h>
@@ -91,9 +87,7 @@
 
 static int  ircc_net_open(struct net_device *dev);
 static int  ircc_net_close(struct net_device *dev);
-#ifdef CONFIG_APM
-static int  ircc_apmproc(apm_event_t event);
-#endif /* CONFIG_APM */
+static int  ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 
 /* These are the currently known SMC chipsets */
 static smc_chip_t chips[] =
@@ -291,6 +285,10 @@
 
 	irport_start(self->irport);
 
+        self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ircc_pmproc);
+        if (self->pmdev)
+                self->pmdev->data = self;
+
 	return 0;
 }
 
@@ -999,7 +997,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_APM
 static void ircc_suspend(struct ircc_cb *self)
 {
 	int i = 10;
@@ -1031,36 +1028,21 @@
 	MESSAGE("%s, Waking up\n", driver_name);
 }
 
-static int ircc_apmproc(apm_event_t event)
+static int ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-	static int down = 0;          /* Filter out double events */
-	int i;
-
-	switch (event) {
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-		if (!down) {			
-			for (i=0; i<4; i++) {
-				if (dev_self[i])
-					ircc_suspend(dev_self[i]);
-			}
-		}
-		down = 1;
-		break;
-	case APM_NORMAL_RESUME:
-	case APM_CRITICAL_RESUME:
-		if (down) {
-			for (i=0; i<4; i++) {
-				if (dev_self[i])
-					ircc_wakeup(dev_self[i]);
-			}
-		}
-		down = 0;
-		break;
-	}
+        struct ircc_cb *self = (struct ircc_cb*) dev->data;
+        if (self) {
+                switch (rqst) {
+                case PM_SUSPEND:
+                        ircc_suspend(self);
+                        break;
+                case PM_RESUME:
+                        ircc_wakeup(self);
+                        break;
+                }
+        }
 	return 0;
 }
-#endif /* CONFIG_APM */
 
 #ifdef MODULE
 MODULE_AUTHOR("Thomas Davis <tadavis@jps.net>");
diff -u --recursive --new-file v2.3.42/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.3.42/linux/drivers/net/irda/toshoboe.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/irda/toshoboe.c	Tue Feb  8 18:48:57 2000
@@ -56,7 +56,6 @@
 /* No user servicable parts below here */
 
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
@@ -77,9 +76,8 @@
 #include <net/irda/irlap_frame.h>
 #include <net/irda/irda_device.h>
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
+#include <linux/pm.h>
+static int toshoboe_pmproc (struct pm_dev *dev, pm_request_t rqst, void *data);
 
 #include <net/irda/toshoboe.h>
 
@@ -690,6 +688,7 @@
 {
   struct toshoboe_cb *self;
   struct net_device *dev;
+  struct pm_dev *pmdev;
   int i = 0;
   int ok = 0;
   int err;
@@ -858,6 +857,10 @@
 	  return -1;
   }
 
+  pmdev = pm_register (PM_PCI_DEV, PM_PCI_ID(pci_dev), toshoboe_pmproc);
+  if (pmdev)
+	  pmdev->data = self;
+
   printk (KERN_WARNING "ToshOboe: Using ");
 #ifdef ONETASK
   printk ("single");
@@ -869,7 +872,6 @@
   return (0);
 }
 
-#ifdef CONFIG_APM
 static void 
 toshoboe_gotosleep (struct toshoboe_cb *self)
 {
@@ -935,52 +937,23 @@
 }
 
 static int 
-toshoboe_apmproc (apm_event_t event)
+toshoboe_pmproc (struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-  static int down = 0;          /*Filter out double events */
-  int i;
-
-  switch (event)
-    {
-    case APM_SYS_SUSPEND:
-    case APM_USER_SUSPEND:
-      if (!down)
-        {
-
-          for (i = 0; i < 4; i++)
-            {
-              if (dev_self[i])
-                toshoboe_gotosleep (dev_self[i]);
-            }
-
-        }
-      down = 1;
-      break;
-    case APM_NORMAL_RESUME:
-    case APM_CRITICAL_RESUME:
-      if (down)
-        {
-
-
-
-          for (i = 0; i < 4; i++)
-            {
-              if (dev_self[i])
-                toshoboe_wakeup (dev_self[i]);
-            }
-
-
-
-        }
-      down = 0;
-      break;
-    }
+  struct toshoboe_cb *self = (struct toshoboe_cb *) dev->data;
+  if (self) {
+	  switch (rqst) {
+	  case PM_SUSPEND:
+		  toshoboe_gotosleep (self);
+		  break;
+	  case PM_RESUME:
+		  toshoboe_wakeup (self);
+		  break;
+	  }
+  }
   return 0;
 }
 
 
-#endif
-
 int __init toshoboe_init (void)
 {
   struct pci_dev *pci_dev = NULL;
@@ -997,7 +970,7 @@
                   pci_dev->irq);
 
           if (!toshoboe_open (pci_dev))
-            found++;
+	      found++;
         }
 
     }
@@ -1006,9 +979,6 @@
 
   if (found)
     {
-#ifdef CONFIG_APM
-      apm_register_callback (toshoboe_apmproc);
-#endif
       return 0;
     }
 
@@ -1030,10 +1000,7 @@
         toshoboe_close (dev_self[i]);
     }
 
-#ifdef CONFIG_APM
-  apm_unregister_callback (toshoboe_apmproc);
-#endif
-
+  pm_unregister_all (toshoboe_pmproc);
 }
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v2.3.42/linux/drivers/net/loopback.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/loopback.c	Wed Feb  9 20:08:09 2000
@@ -107,17 +107,10 @@
 	return (struct net_device_stats *)dev->priv;
 }
 
-static int loopback_open(struct net_device *dev)
-{
-	dev->flags|=IFF_LOOPBACK;
-	return 0;
-}
-
 /* Initialize the rest of the LOOPBACK device. */
 int __init loopback_init(struct net_device *dev)
 {
 	dev->mtu		= LOOPBACK_MTU;
-	dev->tbusy		= 0;
 	dev->hard_start_xmit	= loopback_xmit;
 	dev->hard_header	= eth_header;
 	dev->hard_header_cache	= eth_header_cache;
@@ -127,7 +120,6 @@
 	dev->tx_queue_len	= 0;
 	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001		*/
 	dev->rebuild_header	= eth_rebuild_header;
-	dev->open		= loopback_open;
 	dev->flags		= IFF_LOOPBACK;
 	dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
 	if (dev->priv == NULL)
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ltpc.c linux/drivers/net/ltpc.c
--- v2.3.42/linux/drivers/net/ltpc.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ltpc.c	Thu Feb 10 12:24:54 2000
@@ -1250,8 +1250,12 @@
 }
 
 /* handles "ltpc=io,irq,dma" kernel command lines */
-void __init ltpc_setup(char *str, int *ints)
+static int __init ltpc_setup(char *str)
 {
+	int ints[5];
+
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+
 	if (ints[0] == 0) {
 		if (str && !strncmp(str, "auto", 4)) {
 			/* do nothing :-) */
@@ -1261,21 +1265,23 @@
 			printk (KERN_ERR
 				"ltpc: usage: ltpc=auto|iobase[,irq[,dma]]\n");
 		}
-		return;
+		return 1;
 	} else {
 		io = ints[1];
 		if (ints[0] > 1) {
 			irq = ints[2];
-			return;
+			return 1;
 		}
 		if (ints[0] > 2) {
 			dma = ints[3];
-			return;
+			return 1;
 		}
 		/* ignore any other paramters */
 	}
-	return;
+	return 1;
 }
+
+__setup("ltpc=", ltpc_setup);
 
 #ifdef MODULE
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/mace.c linux/drivers/net/mace.c
--- v2.3.42/linux/drivers/net/mace.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/mace.c	Thu Feb 10 12:24:54 2000
@@ -5,17 +5,15 @@
  * Copyright (C) 1996 Paul Mackerras.
  */
 
-#ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
-#endif
-
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/timer.h>
+#include <linux/init.h>
 #include <asm/prom.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
@@ -101,7 +99,7 @@
     return d;
 }
 
-int mace_probe(void)
+static int __init mace_probe (void)
 {
 	int j, rev;
 	struct net_device *dev;
@@ -111,6 +109,11 @@
 	static int maces_found = 0;
 	static struct device_node *next_mace;
 
+#ifdef MODULE
+	if(mace_devs != NULL)
+		return -EBUSY;
+#endif
+
 	if (!maces_found) {
 		next_mace = find_devices("mace");
 		maces_found = 1;
@@ -894,25 +897,13 @@
     }
 }
 
-#ifdef MODULE
 
-#if LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("Paul Mackerras");
 MODULE_DESCRIPTION("PowerMac MACE driver.");
-#endif
 
-int init_module(void)
-{
-    int res;
-
-    if(mace_devs != NULL)
-	return -EBUSY;
-    res = mace_probe();
-    return res;
-}
-
-void cleanup_module(void)
+static void __exit mace_cleanup (void)
 {
+#ifdef MODULE
     struct mace_data *mp = (struct mace_data *) mace_devs->priv;
     unregister_netdev(mace_devs);
 
@@ -922,6 +913,8 @@
 
     kfree(mace_devs);
     mace_devs = NULL;
+#endif
 }
 
-#endif
+module_init(mace_probe);
+module_exit(mace_cleanup);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
--- v2.3.42/linux/drivers/net/myri_sbus.c	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/myri_sbus.c	Thu Feb 10 12:24:54 2000
@@ -551,7 +551,6 @@
 
 		DIRQ(("IRQ_DISAB "));
 		myri_disable_irq(lregs, mp->cregs);
-		dev->interrupt = 1;
 		softstate = sbus_readl(&chan->state);
 		DIRQ(("state[%08x] ", softstate));
 		if (softstate != STATE_READY) {
@@ -562,7 +561,6 @@
 		myri_rx(mp, dev);
 		DIRQ(("\nistat=ISTAT_HOST "));
 		sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT);
-		dev->interrupt = 0;
 		DIRQ(("IRQ_ENAB "));
 		myri_enable_irq(lregs, mp->cregs);
 	}
@@ -584,6 +582,17 @@
 	return 0;
 }
 
+static void myri_tx_timeout(struct net_device *dev)
+{
+	struct myri_eth *mp = (struct myri_eth *) dev->priv;
+
+	printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
+
+	mp->enet_stats.tx_errors++;
+	myri_init(mp, 0);
+	netif_start_queue(dev);
+}
+
 static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct myri_eth *mp = (struct myri_eth *) dev->priv;
@@ -598,29 +607,7 @@
 
 	myri_tx(mp, dev);
 
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-
-		DTX(("tbusy tickssofar[%d] ", tickssofar));
-		if (tickssofar < 40) {
-			DTX(("returning 1\n"));
-			return 1;
-		} else {
-			DTX(("resetting, return 0\n"));
-			printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-			mp->enet_stats.tx_errors++;
-			myri_init(mp, in_interrupt());
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-			return 0;
-		}
-	}
-
-	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		DTX(("tbusy, maybe a race? returning 1\n"));
-		printk("%s: Transmitter access conflict.\n", dev->name);
-		return 1;
-	}
+	netif_stop_queue(dev);
 
 	/* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
 	head = sbus_readl(&sq->head);
@@ -677,7 +664,7 @@
 	bang_the_chip(mp);
 
 	DTX(("tbusy=0, returning 0\n"));
-	dev->tbusy = 0;
+	netif_start_queue(dev);
 	restore_flags(flags);
 	return 0;
 }
@@ -1059,6 +1046,8 @@
 	dev->open = &myri_open;
 	dev->stop = &myri_close;
 	dev->hard_start_xmit = &myri_start_xmit;
+	dev->tx_timeout = &myri_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
 	dev->get_stats = &myri_get_stats;
 	dev->set_multicast_list = &myri_set_multicast;
 	dev->irq = sdev->irqs[0];
@@ -1105,7 +1094,7 @@
 	return 0;
 }
 
-int __init myri_sbus_probe(void)
+static int __init myri_sbus_probe(void)
 {
 	struct net_device *dev = NULL;
 	struct sbus_bus *bus;
@@ -1113,6 +1102,10 @@
 	static int called = 0;
 	int cards = 0, v;
 
+#ifdef MODULE
+	root_myri_dev = NULL;
+#endif
+
 	if (called)
 		return ENODEV;
 	called++;
@@ -1134,18 +1127,9 @@
 	return 0;
 }
 
-#ifdef MODULE
-
-int
-init_module(void)
-{
-	root_myri_dev = NULL;
-	return myri_sbus_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit myri_sbus_cleanup(void)
 {
+#ifdef MODULE
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_myri_dev) {
 		struct myri_eth *next = root_myri_dev->next_module;
@@ -1154,6 +1138,8 @@
 		kfree(root_myri_dev->dev);
 		root_myri_dev = next;
 	}
+#endif /* MODULE */
 }
 
-#endif /* MODULE */
+module_init(myri_sbus_probe);
+module_exit(myri_sbus_cleanup);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ncr885e.c linux/drivers/net/ncr885e.c
--- v2.3.42/linux/drivers/net/ncr885e.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/ncr885e.c	Thu Feb 10 12:29:58 2000
@@ -14,18 +14,8 @@
 "ncr885e.c:v0.8 11/30/98 dan@synergymicro.com\n";
 
 #include <linux/config.h>
-
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
 #include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT 
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -91,6 +81,8 @@
 
 int ncr885e_debug = NCR885E_DEBUG;
 static int print_version = 0;
+static int debug = NCR885E_DEBUG; /* module parm */
+
 
 struct ncr885e_private {
 
@@ -124,10 +116,7 @@
 	spinlock_t lock;
 };
 
-#ifdef MODULE
 static struct net_device *root_dev = NULL;
-#endif
-
 
 static int ncr885e_open( struct net_device *dev );
 static int ncr885e_close( struct net_device *dev );
@@ -1169,13 +1158,18 @@
 	unsigned char *p;
 	int  i;
 
+	if (!request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name))
+		return -EBUSY;
+
 	dev = init_etherdev(NULL, 0 );
 
 	/* construct private data for the 885 ethernet */
 	dev->priv = kmalloc( sizeof( struct ncr885e_private ), GFP_KERNEL );
 
-	if ( dev->priv == NULL )
+	if ( dev->priv == NULL ) {
+		release_region( ioaddr, NCR885E_TOTAL_SIZE );
 		return -ENOMEM;
+	}
 
 	sp = (struct ncr885e_private *) dev->priv;
 	memset( sp, 0, sizeof( struct ncr885e_private ));
@@ -1198,8 +1192,6 @@
 
 	printk(", IRQ %d.\n", irq );
 
-	request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name );
-
 	/* set up a timer */
 	init_timer( &sp->tx_timeout );
 	sp->timeout_active = 0;
@@ -1216,6 +1208,8 @@
 	dev->hard_start_xmit = ncr885e_xmit_start;
 	dev->set_multicast_list = ncr885e_set_multicast;
 	dev->set_mac_address = ncr885e_set_address;
+	
+	root_dev = dev;
 
 	return 0;
 }
@@ -1226,13 +1220,16 @@
  *  worry about the rest.
  */
 
-int __init ncr885e_probe(void)
+static int __init ncr885e_probe(void)
 {
 	struct pci_dev *pdev = NULL;
 	unsigned int ioaddr, chips = 0;
 	unsigned short cmd;
 	unsigned char irq, latency;
 
+	if ( debug >= 0)
+		ncr885e_debug = debug;
+
 	while(( pdev = pci_find_device( PCI_VENDOR_ID_NCR, 
 					PCI_DEVICE_ID_NCR_53C885_ETHERNET,
 					pdev )) != NULL ) {
@@ -1416,26 +1413,12 @@
 
 #endif /* NCR885E_DEBUG_MII */
 
-#ifdef MODULE
-#if defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("dan@synergymicro.com");
 MODULE_DESCRIPTION("Symbios 53C885 Ethernet driver");
 MODULE_PARM(debug, "i");
-#endif 
 
-static int debug = 1;
 
-int
-init_module(void)
-{
-	if ( debug >= 0)
-		ncr885e_debug = debug;
-
-	return ncr885e_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit ncr885e_cleanup (void)
 {
 	struct ncr885e_private *np;
 
@@ -1448,7 +1431,10 @@
 		root_dev = NULL;
 	}  
 }
-#endif /* MODULE */
+
+module_init(ncr885e_probe);
+module_exit(ncr885e_cleanup);
+
 
 /*
  * Local variables:
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.3.42/linux/drivers/net/ne.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/net/ne.c	Thu Feb 10 12:24:54 2000
@@ -606,9 +606,8 @@
 	if (ei_status.dmaing) 
 	{
 		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
-			"[DMAstat:%d][irqlock:%d][intr:%ld].\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock,
-			dev->interrupt);
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
 		return;
 	}
 
@@ -646,9 +645,8 @@
 	if (ei_status.dmaing) 
 	{
 		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
-			"[DMAstat:%d][irqlock:%d][intr:%ld].\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock,
-			dev->interrupt);
+			"[DMAstat:%d][irqlock:%d].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
@@ -721,9 +719,8 @@
 	if (ei_status.dmaing) 
 	{
 		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
-			"[DMAstat:%d][irqlock:%d][intr:%ld]\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock,
-			dev->interrupt);
+			"[DMAstat:%d][irqlock:%d]\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.3.42/linux/drivers/net/ne2k-pci.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/ne2k-pci.c	Thu Feb 10 12:24:54 2000
@@ -104,7 +104,7 @@
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
-int ne2k_pci_probe(void);
+static int ne2k_pci_probe(void);
 static struct net_device *ne2k_pci_probe1(long ioaddr, int irq, int chip_idx);
 
 static int ne2k_pci_open(struct net_device *dev);
@@ -129,10 +129,7 @@
 /* A list of all installed devices, for removing the driver module. */
 static struct ne2k_pci_card *ne2k_card_list = NULL;
 
-#ifdef MODULE
-
-int
-init_module(void)
+static int __init ne2k_pci_init_module(void)
 {
 	/* We must emit version information. */
 	if (debug)
@@ -146,8 +143,7 @@
 	return 0;
 }
 
-void
-cleanup_module(void)
+static void __exit ne2k_pci_cleanup_module(void)
 {
 	struct net_device *dev;
 	struct ne2k_pci_card *this_card;
@@ -165,7 +161,8 @@
 	unlock_8390_module();
 }
 
-#endif  /* MODULE */
+module_init(ne2k_pci_init_module);
+module_exit(ne2k_pci_cleanup_module);
 
 /*
   NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet
@@ -185,7 +182,7 @@
 {"ne2k_pci", ne2k_pci_probe1, NE_IO_EXTENT, 0};
 #endif
 
-int __init ne2k_pci_probe(void)
+static int __init ne2k_pci_probe(void)
 {
 	struct pci_dev *pdev = NULL;
 	int cards_found = 0;
@@ -216,13 +213,11 @@
 		if (check_region(pci_ioaddr, NE_IO_EXTENT))
 			continue;
 
-#ifndef MODULE
 		{
 			static unsigned version_printed = 0;
 			if (version_printed++ == 0)
 				printk(KERN_INFO "%s", version);
 		}
-#endif
 
 		/* Activate the card: fix for brain-damaged Win98 BIOSes. */
 		new_command = pci_command | PCI_COMMAND_IO;
@@ -451,9 +446,8 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
-			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   (int)dev->interrupt);
+			   "[DMAstat:%d][irqlock:%d].\n",
+			   dev->name, ei_status.dmaing, ei_status.irqlock);
 		return;
 	}
 
@@ -490,9 +484,8 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_block_input "
-			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   (int)dev->interrupt);
+			   "[DMAstat:%d][irqlock:%d].\n",
+			   dev->name, ei_status.dmaing, ei_status.irqlock);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
@@ -543,9 +536,8 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_block_output."
-			   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
-			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   (int)dev->interrupt);
+			   "[DMAstat:%d][irqlock:%d]\n",
+			   dev->name, ei_status.dmaing, ei_status.irqlock);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.3.42/linux/drivers/net/net_init.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/net_init.c	Wed Feb  9 20:08:09 2000
@@ -153,7 +153,7 @@
 static int eth_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr=p;
-	if(dev->start)
+	if(test_bit(LINK_STATE_START, &dev->state))
 		return -EBUSY;
 	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
 	return 0;
@@ -200,7 +200,7 @@
 static int hippi_mac_addr(struct net_device *dev, void *p)
 {
 	struct sockaddr *addr = p;
-	if(dev->start)
+	if(test_bit(LINK_STATE_START, &dev->state))
 		return -EBUSY;
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 	return 0;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ni5010.c linux/drivers/net/ni5010.c
--- v2.3.42/linux/drivers/net/ni5010.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ni5010.c	Thu Feb 10 12:24:54 2000
@@ -186,7 +186,7 @@
 {
 	static unsigned version_printed = 0;
 	int i;
-	unsigned int data;
+	unsigned int data = 0;
 	int boguscount = 40;
 
 	/*
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v2.3.42/linux/drivers/net/ni65.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ni65.c	Thu Feb 10 12:24:54 2000
@@ -808,7 +808,7 @@
  */
 static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
-	int csr0;
+	int csr0 = 0;
 	struct net_device *dev = dev_id;
 	struct priv *p;
 	int bcnt = 32;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/oaknet.c linux/drivers/net/oaknet.c
--- v2.3.42/linux/drivers/net/oaknet.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/oaknet.c	Thu Feb 10 12:24:54 2000
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
  *
  *    Module name: oaknet.c
  *
@@ -9,12 +9,17 @@
  *      on-board the IBM PowerPC "Oak" evaluation board. Adapted from the
  *      various other 8390 drivers written by Donald Becker and Paul Gortmaker.
  *
+ *      Additional inspiration from the "tcd8390.c" driver from TiVo, Inc. 
+ *      and "enetLib.c" from IBM.
+ *
  */
 
 #include <linux/module.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/init.h>
 
 #include <asm/board.h>
 #include <asm/io.h>
@@ -32,23 +37,23 @@
 #define	FALSE	0
 #endif
 
-#define	OAKNET_CMD     		0x00
-#define OAKNET_DATA		0x10	/* NS-defined port window offset. */
-#define OAKNET_RESET		0x1f	/* A read resets, a write clears. */
-
 #define	OAKNET_START_PG		0x20	/* First page of TX buffer */
 #define	OAKNET_STOP_PG		0x40	/* Last pagge +1 of RX ring */
 
-#define	OAKNET_BASE		(dev->base_addr)
-
 #define	OAKNET_WAIT		(2 * HZ / 100)	/* 20 ms */
 
+/* Experimenting with some fixes for a broken driver... */
+
+#define	OAKNET_DISINT
+#define	OAKNET_HEADCHECK
+#define	OAKNET_RWFIX
+
 
 /* Global Variables */
 
-#if defined(MODULE)
-static struct net_device *oaknet_devs;
-#endif
+static const char *name = "National DP83902AV";
+
+static struct net_device *oaknet_devs = NULL;
 
 
 /* Function Prototypes */
@@ -85,20 +90,35 @@
  *   0 if OK, otherwise system error number on error.
  *
  */
-int
-oaknet_init(void)
+static int __init oaknet_init(void)
 {
 	register int i;
 	int reg0, regd;
-	struct net_device *dev = NULL;
-	unsigned long ioaddr = OAKNET_IO_BASE;
-	const char *name = "National DP83902AV";
+	struct net_device tmp, *dev = NULL;
+#if 0
+	unsigned long ioaddr = OAKNET_IO_BASE; 
+#else
+	unsigned long ioaddr = ioremap(OAKNET_IO_BASE, OAKNET_IO_SIZE);
+#endif
 	bd_t *bip = (bd_t *)__res;
 
+	/*
+	 * This MUST happen here because of the nic_* macros
+	 * which have an implicit dependency on dev->base_addr.
+	 */
+
+	tmp.base_addr = ioaddr;
+	dev = &tmp;
+
+	if (!request_region(OAKNET_IO_BASE, OAKNET_IO_SIZE, name))
+		return -EBUSY;
+
 	/* Quick register check to see if the device is really there. */
 
-	if ((reg0 = inb_p(ioaddr)) == 0xFF)
+	if ((reg0 = ei_ibp(ioaddr)) == 0xFF) {
+		release_region(OAKNET_IO_BASE, OAKNET_IO_SIZE);
 		return (ENODEV);
+	}
 
 	/*
 	 * That worked. Now a more thorough check, using the multicast
@@ -106,19 +126,20 @@
 	 * and semi-functional.
 	 */
 
-	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
-	regd = inb_p(ioaddr + 0x0D);
-	outb_p(0xFF, ioaddr + 0x0D);
-	outb_p(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
-	inb_p(ioaddr + EN0_COUNTER0);
+	ei_obp(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
+	regd = ei_ibp(ioaddr + 0x0D);
+	ei_obp(0xFF, ioaddr + 0x0D);
+	ei_obp(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
+	ei_ibp(ioaddr + EN0_COUNTER0);
 
 	/* It's no good. Fix things back up and leave. */
 
-	if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
-		outb_p(reg0, ioaddr);
-		outb_p(regd, ioaddr + 0x0D);
+	if (ei_ibp(ioaddr + EN0_COUNTER0) != 0) {
+		ei_obp(reg0, ioaddr);
+		ei_obp(regd, ioaddr + 0x0D);
 		dev->base_addr = 0;
 
+		release_region(dev->base_addr, OAKNET_IO_SIZE);
 		return (ENODEV);
 	}
 
@@ -127,8 +148,10 @@
 	 * sure its symbols are loaded.
 	 */
 
-	if (load_8390_module("oaknet.c"))
+	if (load_8390_module("oaknet.c")) {
+		release_region(dev->base_addr, OAKNET_IO_SIZE);
 		return (-ENOSYS);
+	}
 
 	/*
 	 * We're not using the old-style probing API, so we have to allocate
@@ -136,39 +159,31 @@
 	 */
 
 	dev = init_etherdev(0, 0);
-#if defined(MODULE)
 	oaknet_devs = dev;
-#endif
 
 	/*
 	 * This controller is on an embedded board, so the base address
 	 * and interrupt assignments are pre-assigned and unchageable.
 	 */
 
-	dev->base_addr = OAKNET_IO_BASE;
+	dev->base_addr = ioaddr;
 	dev->irq = OAKNET_INT;
 
 	/* Allocate 8390-specific device-private area and fields. */
 
 	if (ethdev_init(dev)) {
 		printk(" unable to get memory for dev->priv.\n");
+		release_region(dev->base_addr, OAKNET_IO_SIZE);
 		return (-ENOMEM);
 	}
 
 	/*
-	 * Just to be safe, reset the card as we cannot really* be sure
-	 * what state it was last left in.
-	 */
-
-	oaknet_reset_8390(dev);
-
-	/*
 	 * Disable all chip interrupts for now and ACK all pending
 	 * interrupts.
 	 */
 
-	outb_p(0x0, ioaddr + EN0_IMR);
-	outb_p(0xFF, ioaddr + EN0_ISR);
+	ei_obp(0x0, ioaddr + EN0_IMR);
+	ei_obp(0xFF, ioaddr + EN0_ISR);
 
 	/* Attempt to get the interrupt line */
 
@@ -176,12 +191,10 @@
 		printk("%s: unable to request interrupt %d.\n",
 		       dev->name, dev->irq);
 		kfree(dev->priv);
-		dev->priv = NULL;
+		release_region(dev->base_addr, OAKNET_IO_SIZE);
 		return (EAGAIN);
 	}
 
-	request_region(dev->base_addr, OAKNET_IO_SIZE, name);
-
 	/* Tell the world about what and where we've found. */
 
 	printk("%s: %s at", dev->name, name);
@@ -273,7 +286,7 @@
  *   This routine resets the DP83902 chip.
  *
  * Input(s):
- *  *dev - 
+ *  *dev - Pointer to the device structure for this driver.
  *
  * Output(s):
  *   N/A
@@ -285,36 +298,48 @@
 static void
 oaknet_reset_8390(struct net_device *dev)
 {
-	int base = OAKNET_BASE;
-	unsigned long start = jiffies;
+	int base = E8390_BASE;
 
-	outb(inb(base + OAKNET_RESET), base + OAKNET_RESET);
+	/*
+	 * We have no provision of reseting the controller as is done
+	 * in other drivers, such as "ne.c". However, the following
+	 * seems to work well enough in the TiVo driver.
+	 */
 
+	printk("Resetting %s...\n", dev->name);
+	ei_obp(E8390_STOP | E8390_NODMA | E8390_PAGE0, base + E8390_CMD);
 	ei_status.txing = 0;
 	ei_status.dmaing = 0;
 
-	/* This check shouldn't be necessary eventually */
-
-	while ((inb_p(base + EN0_ISR) & ENISR_RESET) == 0) {
-		if (jiffies - start > OAKNET_WAIT) {
-			printk("%s: reset didn't complete\n", dev->name);
-			break;
-		}
-	}
-
-	outb_p(ENISR_RESET, base + EN0_ISR);	/* ACK reset interrupt */
-
 	return;
 }
 
 /*
- * XXX - Document me.
+ * static void oaknet_get_8390_hdr()
+ *
+ * Description:
+ *   This routine grabs the 8390-specific header. It's similar to the
+ *   block input routine, but we don't need to be concerned with ring wrap
+ *   as the header will be at the start of a page, so we optimize accordingly.
+ *
+ * Input(s):
+ *  *dev       - Pointer to the device structure for this driver.
+ *  *hdr       - Pointer to storage for the 8390-specific packet header.
+ *   ring_page - ?
+ *
+ * Output(s):
+ *  *hdr       - Pointer to the 8390-specific packet header for the just-
+ *               received frame.
+ *
+ * Returns:
+ *   N/A
+ *
  */
 static void
 oaknet_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 		    int ring_page)
 {
-	int base = OAKNET_BASE;
+	int base = dev->base_addr;
 
 	/*
 	 * This should NOT happen. If it does, it is the LAST thing you'll
@@ -341,6 +366,10 @@
 		insb(base + OAKNET_DATA, hdr,
 		     sizeof(struct e8390_pkt_hdr));
 
+	/* Byte-swap the packet byte count */
+
+	hdr->count = le16_to_cpu(hdr->count);
+
 	outb_p(ENISR_RDC, base + EN0_ISR);	/* ACK Remote DMA interrupt */
 	ei_status.dmaing &= ~0x01;
 
@@ -367,38 +396,99 @@
 		return;
 	}
 
+#ifdef OAKNET_DISINT
+	save_flags(flags);
+	cli();
+#endif
+
 	ei_status.dmaing |= 0x01;
-	outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, base + OAKNET_CMD);
-	outb_p(count & 0xff, base + EN0_RCNTLO);
-	outb_p(count >> 8, base + EN0_RCNTHI);
-	outb_p(ring_offset & 0xff, base + EN0_RSARLO);
-	outb_p(ring_offset >> 8, base + EN0_RSARHI);
-	outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD);
+	ei_obp(E8390_NODMA + E8390_PAGE0 + E8390_START, base + E8390_CMD);
+	ei_obp(count & 0xff, base + EN0_RCNTLO);
+	ei_obp(count >> 8, base + EN0_RCNTHI);
+	ei_obp(ring_offset & 0xff, base + EN0_RSARLO);
+	ei_obp(ring_offset >> 8, base + EN0_RSARHI);
+	ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);
 	if (ei_status.word16) {
-		insw(base + OAKNET_DATA, buf, count >> 1);
+		ei_isw(base + E8390_DATA, buf, count >> 1);
 		if (count & 0x01) {
-			buf[count-1] = inb(base + OAKNET_DATA);
+			buf[count - 1] = ei_ib(base + E8390_DATA);
+#ifdef OAKNET_HEADCHECK
+			bytes++;
+#endif
 		}
 	} else {
-		insb(base + OAKNET_DATA, buf, count);
+		ei_isb(base + E8390_DATA, buf, count);
 	}
-	outb_p(ENISR_RDC, base + EN0_ISR);	/* ACK Remote DMA interrupt */
+#ifdef OAKNET_HEADCHECK
+	/*
+	 * This was for the ALPHA version only, but enough people have
+	 * been encountering problems so it is still here.  If you see
+	 * this message you either 1) have a slightly incompatible clone
+	 * or 2) have noise/speed problems with your bus.
+	 */
+
+	/* DMA termination address check... */
+	{
+		int addr, tries = 20;
+		do {
+			/* DON'T check for 'ei_ibp(EN0_ISR) & ENISR_RDC' here
+			   -- it's broken for Rx on some cards! */
+			int high = ei_ibp(base + EN0_RSARHI);
+			int low = ei_ibp(base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if (((ring_offset + bytes) & 0xff) == low)
+				break;
+		} while (--tries > 0);
+	 	if (tries <= 0)
+			printk("%s: RX transfer address mismatch,"
+			       "%#4.4x (expected) vs. %#4.4x (actual).\n",
+			       dev->name, ring_offset + bytes, addr);
+	}
+#endif
+	ei_obp(ENISR_RDC, base + EN0_ISR);	/* ACK Remote DMA interrupt */
 	ei_status.dmaing &= ~0x01;
 
+#ifdef OAKNET_DISINT
+	restore_flags(flags);
+#endif
+
 	return;
 }
 
 /*
- * XXX - Document me.
+ * static void oaknet_block_output()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *  *dev        - Pointer to the device structure for this driver.
+ *   count      - Number of bytes to be transferred.
+ *  *buf        - 
+ *   start_page - 
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
  */
 static void
 oaknet_block_output(struct net_device *dev, int count,
 		    const unsigned char *buf, int start_page)
 {
-	int base = OAKNET_BASE;
+	int base = E8390_BASE;
+#if 0
 	int bug;
+#endif
 	unsigned long start;
-	unsigned char lobyte;
+#ifdef OAKNET_DISINT
+	unsigned long flags;
+#endif
+#ifdef OAKNET_HEADCHECK
+	int retries = 0;
+#endif
 
 	/* Round the count up for word writes. */
 
@@ -415,12 +505,22 @@
 		return;
 	}
 
+#ifdef OAKNET_DISINT
+	save_flags(flags);
+	cli();
+#endif
+
 	ei_status.dmaing |= 0x01;
 
 	/* Make sure we are in page 0. */
 
-	outb_p(E8390_PAGE0 + E8390_START + E8390_NODMA, base + OAKNET_CMD);
+	ei_obp(E8390_PAGE0 + E8390_START + E8390_NODMA, base + E8390_CMD);
 
+#ifdef OAKNET_HEADCHECK
+retry:
+#endif
+
+#if 0
 	/*
 	 * The 83902 documentation states that the processor needs to
 	 * do a "dummy read" before doing the remote write to work
@@ -433,60 +533,131 @@
 		unsigned int rdlo;
 
 		/* Now the normal output. */
-		outb_p(ENISR_RDC, base + EN0_ISR);
-		outb_p(count & 0xff, base + EN0_RCNTLO);
-		outb_p(count >> 8,   base + EN0_RCNTHI);
-		outb_p(0x00, base + EN0_RSARLO);
-		outb_p(start_page, base + EN0_RSARHI);
+		ei_obp(ENISR_RDC, base + EN0_ISR);
+		ei_obp(count & 0xff, base + EN0_RCNTLO);
+		ei_obp(count >> 8,   base + EN0_RCNTHI);
+		ei_obp(0x00, base + EN0_RSARLO);
+		ei_obp(start_page, base + EN0_RSARHI);
 
 		if (bug++)
 			break;
 
 		/* Perform the dummy read */
-		rdhi = inb_p(base + EN0_CRDAHI);
-		rdlo = inb_p(base + EN0_CRDALO);
-		outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD);
+		rdhi = ei_ibp(base + EN0_CRDAHI);
+		rdlo = ei_ibp(base + EN0_CRDALO);
+		ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);
 
 		while (1) {
 			unsigned int nrdhi;
 			unsigned int nrdlo;
-			nrdhi = inb_p(base + EN0_CRDAHI);
-			nrdlo = inb_p(base + EN0_CRDALO);
+			nrdhi = ei_ibp(base + EN0_CRDAHI);
+			nrdlo = ei_ibp(base + EN0_CRDALO);
 			if ((rdhi != nrdhi) || (rdlo != nrdlo))
 				break;
 		}
 	}
+#else
+#ifdef OAKNET_RWFIX
+	/*
+	 * Handle the read-before-write bug the same way as the
+	 * Crynwr packet driver -- the Nat'l Semi. method doesn't work.
+	 * Actually this doesn't always work either, but if you have
+	 * problems with your 83902 this is better than nothing!
+	 */
+
+	ei_obp(0x42, base + EN0_RCNTLO);
+	ei_obp(0x00, base + EN0_RCNTHI);
+	ei_obp(0x42, base + EN0_RSARLO);
+	ei_obp(0x00, base + EN0_RSARHI);
+	ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);
+	/* Make certain that the dummy read has occurred. */
+	udelay(6);
+#endif
+
+	ei_obp(ENISR_RDC, base + EN0_ISR);
 
-	outb_p(E8390_RWRITE+E8390_START, base + OAKNET_CMD);
+	/* Now the normal output. */
+	ei_obp(count & 0xff, base + EN0_RCNTLO);
+	ei_obp(count >> 8,   base + EN0_RCNTHI);
+	ei_obp(0x00, base + EN0_RSARLO);
+	ei_obp(start_page, base + EN0_RSARHI);
+#endif /* 0/1 */
+
+	ei_obp(E8390_RWRITE + E8390_START, base + E8390_CMD);
 	if (ei_status.word16) {
-		outsw(OAKNET_BASE + OAKNET_DATA, buf, count >> 1);
+		ei_osw(E8390_BASE + E8390_DATA, buf, count >> 1);
 	} else {
-		outsb(OAKNET_BASE + OAKNET_DATA, buf, count);
+		ei_osb(E8390_BASE + E8390_DATA, buf, count);
 	}
 
+#ifdef OAKNET_DISINT
+	restore_flags(flags);
+#endif
+
 	start = jiffies;
 
-	while (((lobyte = inb_p(base + EN0_ISR)) & ENISR_RDC) == 0) {
+#ifdef OAKNET_HEADCHECK
+	/*
+	 * This was for the ALPHA version only, but enough people have
+	 * been encountering problems so it is still here.
+	 */
+	
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			int high = ei_ibp(base + EN0_RSARHI);
+			int low = ei_ibp(base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if ((start_page << 8) + count == addr)
+				break;
+		} while (--tries > 0);
+
+		if (tries <= 0) {
+			printk("%s: Tx packet transfer address mismatch,"
+			       "%#4.4x (expected) vs. %#4.4x (actual).\n",
+			       dev->name, (start_page << 8) + count, addr);
+			if (retries++ == 0)
+				goto retry;
+		}
+	}
+#endif
+
+	while ((ei_ibp(base + EN0_ISR) & ENISR_RDC) == 0) {
 		if (jiffies - start > OAKNET_WAIT) {
-			unsigned char hicnt, locnt;
-			hicnt = inb_p(base + EN0_CRDAHI);
-			locnt = inb_p(base + EN0_CRDALO);
-			printk("%s: timeout waiting for Tx RDC, stat = 0x%x\n",
-			       dev->name, lobyte);
-			printk("\tstart address 0x%x, current address 0x%x, count %d\n",
-			       (start_page << 8), (hicnt << 8) | locnt, count);
+			printk("%s: timeout waiting for Tx RDC.\n", dev->name);
 			oaknet_reset_8390(dev);
 			NS8390_init(dev, TRUE);
 			break;
 		}
 	}
 	
-	outb_p(ENISR_RDC, base + EN0_ISR);	/* Ack intr. */
+	ei_obp(ENISR_RDC, base + EN0_ISR);	/* Ack intr. */
 	ei_status.dmaing &= ~0x01;
 
 	return;
 }
 
+/*
+ * static void oaknet_dma_error()
+ *
+ * Description:
+ *   This routine prints out a last-ditch informative message to the console
+ *   indicating that a DMA error occured. If you see this, it's the last
+ *   thing you'll see.
+ *
+ * Input(s):
+ *  *dev  - Pointer to the device structure for this driver.
+ *  *name - Informative text (e.g. function name) indicating where the
+ *          DMA error occurred.
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
 static void
 oaknet_dma_error(struct net_device *dev, const char *name)
 {
@@ -498,12 +669,10 @@
 	return;
 }
 
-#if defined(MODULE)
 /*
  * Oak Ethernet module load interface.
  */
-int
-init_module(void)
+static int __init oaknet_init_module (void)
 {
 	int status;
 
@@ -512,7 +681,8 @@
 
 	status = oaknet_init()
 
-	lock_8390_module();
+	if (status == 0)
+		lock_8390_module();
 
 	return (status);
 }
@@ -520,8 +690,7 @@
 /*
  * Oak Ethernet module unload interface.
  */
-void
-cleanup_module(void)
+static void __exit oaknet_cleanup_module (void)
 {
 	if (oaknet_devs == NULL)
 		return;
@@ -538,7 +707,7 @@
 	oaknet_devs = NULL;
 
 	unlock_8390_module();
-
-	return;
 }
-#endif /* MODULE */
+
+module_init(oaknet_init_module);
+module_exit(oaknet_cleanup_module);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
--- v2.3.42/linux/drivers/net/pcmcia/pcnet_cs.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/pcmcia/pcnet_cs.c	Wed Feb  9 21:15:22 2000
@@ -315,7 +315,8 @@
     dev->open = &pcnet_open;
     dev->stop = &pcnet_close;
     dev->set_config = &set_config;
-    dev->tbusy = 1;
+
+    netif_stop_queue(dev);
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -681,7 +682,7 @@
     } else {
 	dev->if_port = 0;
     }
-    dev->tbusy = 0;
+    netif_start_queue(dev);
     if (register_netdev(dev) != 0) {
 	printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
 	goto failed;
@@ -806,7 +807,8 @@
     case CS_EVENT_CARD_REMOVAL:
 	link->state &= ~DEV_PRESENT;
 	if (link->state & DEV_CONFIG) {
-	    info->dev.tbusy = 1; info->dev.start = 0;
+	    netif_stop_queue(&info->dev);
+	    clear_bit(LINK_STATE_START, &info->dev.state);
 	    link->release.expires = jiffies + HZ/20;
 	    link->state |= DEV_RELEASE_PENDING;
 	    add_timer(&link->release);
@@ -822,7 +824,8 @@
     case CS_EVENT_RESET_PHYSICAL:
 	if (link->state & DEV_CONFIG) {
 	    if (link->open) {
-		info->dev.tbusy = 1; info->dev.start = 0;
+		netif_stop_queue(&info->dev);
+		clear_bit(LINK_STATE_START, &info->dev.state);
 	    }
 	    CardServices(ReleaseConfiguration, link->handle);
 	}
@@ -836,7 +839,8 @@
 	    if (link->open) {
 		pcnet_reset_8390(&info->dev);
 		NS8390_init(&info->dev, 1);
-		info->dev.tbusy = 0; info->dev.start = 1;
+		netif_start_queue(&info->dev);
+		set_bit(LINK_STATE_START, &info->dev.state);
 	    }
 	}
 	break;
@@ -903,7 +907,8 @@
 
     free_irq(dev->irq, dev);
     
-    link->open--; dev->start = 0;
+    link->open--;
+    clear_bit(LINK_STATE_START, &dev->state);
     del_timer(&info->watchdog);
     if (link->state & DEV_STALE_CONFIG) {
 	link->release.expires = jiffies + HZ/20;
@@ -979,7 +984,8 @@
     struct net_device *dev = &info->dev;
     ioaddr_t nic_base = dev->base_addr;
 
-    if (dev->start == 0) goto reschedule;
+    if (!test_bit(LINK_STATE_START, &dev->state))
+	    goto reschedule;
 
     /* Check for pending interrupt with expired latency timer: with
        this, we can limp along even if the interrupt is blocked */
@@ -1023,9 +1029,8 @@
 
     if (ei_status.dmaing) {
 	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
-	       "[DMAstat:%1x][irqlock:%1x][intr:%ld]\n",
-	       dev->name, ei_status.dmaing, ei_status.irqlock,
-	       (long)dev->interrupt);
+	       "[DMAstat:%1x][irqlock:%1x]\n",
+	       dev->name, ei_status.dmaing, ei_status.irqlock);
 	return;
     }
     
@@ -1061,9 +1066,8 @@
 #endif
     if (ei_status.dmaing) {
 	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
-	       "[DMAstat:%1x][irqlock:%1x][intr:%ld]\n",
-	       dev->name, ei_status.dmaing, ei_status.irqlock,
-	       (long)dev->interrupt);
+	       "[DMAstat:%1x][irqlock:%1x]\n",
+	       dev->name, ei_status.dmaing, ei_status.irqlock);
 	return;
     }
     ei_status.dmaing |= 0x01;
@@ -1127,9 +1131,8 @@
 	count++;
     if (ei_status.dmaing) {
 	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_output."
-	       "[DMAstat:%1x][irqlock:%1x][intr:%ld]\n",
-	       dev->name, ei_status.dmaing, ei_status.irqlock,
-	       (long)dev->interrupt);
+	       "[DMAstat:%1x][irqlock:%1x]\n",
+	       dev->name, ei_status.dmaing, ei_status.irqlock);
 	return;
     }
     ei_status.dmaing |= 0x01;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c
--- v2.3.42/linux/drivers/net/pcmcia/ray_cs.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/net/pcmcia/ray_cs.c	Wed Feb  9 21:22:02 2000
@@ -389,7 +389,7 @@
     dev->init = &ray_dev_init;
     dev->open = &ray_open;
     dev->stop = &ray_dev_close;
-    dev->tbusy = 1;
+    netif_stop_queue(dev);
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -926,7 +926,8 @@
     switch (event) {
     case CS_EVENT_CARD_REMOVAL:
         link->state &= ~DEV_PRESENT;
-        dev->tbusy = 1; dev->start = 0;
+        netif_stop_queue(dev);
+        clear_bit(LINK_STATE_START, &dev->state);
         if (link->state & DEV_CONFIG) {
             link->release.expires = jiffies + HZ/20;
             add_timer(&link->release);
@@ -943,8 +944,8 @@
     case CS_EVENT_RESET_PHYSICAL:
         if (link->state & DEV_CONFIG) {
             if (link->open) {
-                dev->tbusy = 1;
-                dev->start = 0;
+            	netif_stop_queue(dev);
+            	clear_bit(LINK_STATE_START, &dev->state);
             }
             pcmcia_release_configuration(link->handle);
         }
@@ -957,8 +958,8 @@
             pcmcia_request_configuration(link->handle, &link->conf);
             if (link->open) {
                 ray_reset(dev);
-                dev->tbusy = 0;
-                dev->start = 1;
+		netif_start_queue(dev);
+		set_bit(LINK_STATE_START, &dev->state);
             }
         }
         break;
@@ -1019,16 +1020,11 @@
         return -1;
     }
     DEBUG(3,"ray_dev_start_xmit(skb=%p, dev=%p)\n",skb,dev);
-    if (dev->tbusy)
-    {
-        printk(KERN_NOTICE "ray_dev_start_xmit busy\n");
-        return 1;
-    }
     if (local->authentication_state == NEED_TO_AUTH) {
         DEBUG(0,"ray_cs Sending authentication request.\n");
         if (!build_auth_frame (local, local->auth_id, OPEN_AUTH_REQUEST)) {
             local->authentication_state = AUTHENTICATED;
-            dev->tbusy = 1;
+            netif_stop_queue(dev);
             return 1;
         }
     }
@@ -1037,7 +1033,7 @@
     switch (ray_hw_xmit( skb->data, length, dev, DATA_TYPE)) {
         case XMIT_NO_CCS:
         case XMIT_NEED_AUTH:
-            dev->tbusy = 1;
+	    netif_stop_queue(dev);
             return 1;
         case XMIT_NO_INTR:
         case XMIT_MSG_BAD:
@@ -1072,7 +1068,7 @@
 	case ECCSFULL:
         DEBUG(2,"ray_hw_xmit No free tx ccs\n");
 	case ECARDGONE:
-        dev->tbusy = 1;
+	netif_stop_queue(dev);
         return XMIT_NO_CCS;
 	default:
 		break;
@@ -1175,7 +1171,7 @@
     {
         if (local->sparm.b4.a_acting_as_ap_status)
         {
-            writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2);;
+            writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2);
             memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, ADDRLEN);
             memcpy_toio(ptx->mac.addr_2, local->bss_id, 6);
             memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_source, ADDRLEN);
@@ -1512,10 +1508,8 @@
     link->open++;
     MOD_INC_USE_COUNT;
 
-    dev->interrupt = 0;
-    if (sniffer) dev->tbusy = 1;
-    else         dev->tbusy = 0;
-    dev->start = 1;
+    if (sniffer) netif_stop_queue(dev);
+    else         netif_start_queue(dev);
 
     DEBUG(2,"ray_open ending\n");
     return 0;
@@ -1532,7 +1526,8 @@
     if (link == NULL)
         return -ENODEV;
 
-    link->open--; dev->start = 0;
+    link->open--;
+    netif_stop_queue(dev);
     if (link->state & DEV_STALE_CONFIG) {
         link->release.expires = jiffies + HZ/20;
         link->state |= DEV_RELEASE_PENDING;
@@ -1848,11 +1843,6 @@
 
     DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev);
 
-    if (test_and_set_bit(0,&dev->interrupt)) {
-        printk("ray_cs Reentering interrupt handler not allowed\n");
-        return;
-    }
-
     local = (ray_dev_t *)dev->priv;
     link = (dev_link_t *)local->finder;
     if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) {
@@ -1865,7 +1855,6 @@
     {
         DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex);
         clear_interrupt(local);
-        dev->interrupt = 0;
         return;
     }
     if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */
@@ -1961,8 +1950,8 @@
             else {
                 DEBUG(1,"ray_cs interrupt tx request failed\n");
             }
-            if (!sniffer) dev->tbusy = 0;
-            mark_bh(NET_BH);
+            if (!sniffer) netif_start_queue(dev);
+            netif_wake_queue(dev);
             break;
         case CCS_TEST_MEMORY:
             DEBUG(1,"ray_cs interrupt mem test done\n");
@@ -1996,7 +1985,7 @@
             local->card_status = CARD_ACQ_COMPLETE;
             /* do we need to clear tx buffers CCS's? */
             if (local->sparm.b4.a_network_type == ADHOC) {
-                if (!sniffer) dev->tbusy = 0;
+                if (!sniffer) netif_start_queue(dev);
             }
             else {
                 memcpy_fromio(&local->bss_id, prcs->var.rejoin_net_complete.bssid, ADDRLEN);
@@ -2008,7 +1997,7 @@
             break;
         case ROAMING_INITIATED:
             DEBUG(1,"ray_cs interrupt roaming initiated\n"); 
-            dev->tbusy = 1;
+            netif_stop_queue(dev);
             local->card_status = CARD_DOING_ACQ;
             break;
         case JAPAN_CALL_SIGN_RXD:
@@ -2022,7 +2011,6 @@
         writeb(CCS_BUFFER_FREE, &prcs->buffer_status);
     }
     clear_interrupt(local);
-    dev->interrupt = 0;
 } /* ray_interrupt */
 /*===========================================================================*/
 static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
@@ -2477,7 +2465,7 @@
         local->card_status = CARD_ASSOC_FAILED;
         return;
     }
-    if (!sniffer) dev->tbusy = 0;
+    if (!sniffer) netif_start_queue(dev);
 
 } /* end associate */
 /*===========================================================================*/
diff -u --recursive --new-file v2.3.42/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.3.42/linux/drivers/net/pcnet32.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/net/pcnet32.c	Thu Feb 10 12:26:47 2000
@@ -43,9 +43,7 @@
 static int pcnet32_debug = 1;
 static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
 
-#ifdef MODULE
 static struct net_device *pcnet32_dev = NULL;
-#endif
 
 static const int max_interrupt_work = 80;
 static const int rx_copybreak = 200;
@@ -273,17 +271,16 @@
 #endif
          full_duplex:1,                     	/* full duplex possible */
          mii:1;                             	/* mii port available */
-#ifdef MODULE
     struct net_device *next;
-#endif    
 };
 
-int  pcnet32_probe(void);
+static int  pcnet32_probe(void);
 static int  pcnet32_probe1(unsigned long, unsigned char, int, int);
 static int  pcnet32_open(struct net_device *);
 static int  pcnet32_init_ring(struct net_device *);
 static int  pcnet32_start_xmit(struct sk_buff *, struct net_device *);
 static int  pcnet32_rx(struct net_device *);
+static void pcnet32_tx_timeout (struct net_device *dev);
 static void pcnet32_interrupt(int, void *, struct pt_regs *);
 static int  pcnet32_close(struct net_device *);
 static struct net_device_stats *pcnet32_get_stats(struct net_device *);
@@ -433,7 +430,7 @@
 
 
 
-int __init pcnet32_probe(void)
+static int __init pcnet32_probe(void)
 {
     unsigned long ioaddr = 0; // FIXME dev ? dev->base_addr: 0;
     unsigned int  irq_line = 0; // FIXME dev ? dev->irq : 0;
@@ -754,12 +751,11 @@
 #ifdef HAVE_PRIVATE_IOCTL
     dev->do_ioctl = &pcnet32_mii_ioctl;
 #endif
+    dev->tx_timeout = pcnet32_tx_timeout;
+    dev->watchdog_timeo = (HZ >> 1);
 
-    
-#ifdef MODULE
     lp->next = pcnet32_dev;
     pcnet32_dev = dev;
-#endif	
 
     /* Fill in the generic fields of the device structure. */
     ether_setup(dev);
@@ -852,9 +848,8 @@
     lp->a.write_csr (ioaddr, 4, 0x0915);
     lp->a.write_csr (ioaddr, 0, 0x0001);
 
-    dev->tbusy = 0;
-    dev->interrupt = 0;
-    dev->start = 1;
+    netif_start_queue(dev);
+
     i = 0;
     while (i++ < 100)
 	if (lp->a.read_csr (ioaddr, 0) & 0x0100)
@@ -963,20 +958,14 @@
     lp->a.write_csr (ioaddr, 0, csr0_bits);
 }
 
-static int
-pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+static void
+pcnet32_tx_timeout (struct net_device *dev)
 {
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     unsigned int ioaddr = dev->base_addr;
-    u16 status;
-    int entry;
-    unsigned long flags;
 
     /* Transmitter timeout, serious problems. */
-    if (dev->tbusy) {
-	int tickssofar = jiffies - dev->trans_start;
-	if (tickssofar < HZ/2)
-	    return 1;
 	printk("%s: transmit timed out, status %4.4x, resetting.\n",
 	       dev->name, lp->a.read_csr (ioaddr, 0));
 	lp->a.write_csr (ioaddr, 0, 0x0004);
@@ -998,24 +987,25 @@
 	}
 	pcnet32_restart(dev, 0x0042);
 
-	dev->tbusy = 0;
 	dev->trans_start = jiffies;
-	dev_kfree_skb(skb);
-	return 0;
-    }
+	netif_start_queue(dev);
+}
+
+
+static int
+pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+    struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
+    unsigned int ioaddr = dev->base_addr;
+    u16 status;
+    int entry;
+    unsigned long flags;
 
     if (pcnet32_debug > 3) {
 	printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n",
 	       dev->name, lp->a.read_csr (ioaddr, 0));
     }
 
-    /* Block a timer-based transmit from overlapping.  This could better be
-       done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-    if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-	printk("%s: Transmitter access conflict.\n", dev->name);
-	return 1;
-    }
-
     spin_lock_irqsave(&lp->lock, flags);
 
     /* Default status -- will not enable Successful-TxDone
@@ -1059,7 +1049,7 @@
     dev->trans_start = jiffies;
 
     if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
-	clear_bit (0, (void *)&dev->tbusy);
+	netif_start_queue(dev);
     else
 	lp->tx_full = 1;
     spin_unlock_irqrestore(&lp->lock, flags);
@@ -1087,11 +1077,6 @@
     
     spin_lock(&lp->lock);
     
-    if (dev->interrupt)
-	printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
-    dev->interrupt = 1;
-
     rap = lp->a.read_rap(ioaddr);
     while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
 	/* Acknowledge all of the current interrupt sources ASAP. */
@@ -1167,12 +1152,12 @@
 		dirty_tx += TX_RING_SIZE;
 	    }
 #endif
-	    if (lp->tx_full && dev->tbusy
-		&& dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+	    if (lp->tx_full &&
+	        test_bit(LINK_STATE_XOFF, &dev->flags) &&
+		dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
 		/* The ring is no longer full, clear tbusy. */
 		lp->tx_full = 0;
-		clear_bit(0, (void *)&dev->tbusy);
-		mark_bh(NET_BH);
+		netif_wake_queue (dev);
 	    }
 	    lp->dirty_tx = dirty_tx;
 	}
@@ -1213,10 +1198,7 @@
 	printk("%s: exiting interrupt, csr0=%#4.4x.\n",
 	       dev->name, lp->a.read_csr (ioaddr, 0));
 
-    dev->interrupt = 0;
-    
     spin_unlock(&lp->lock);
-    return;
 }
 
 static int
@@ -1317,8 +1299,7 @@
     struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
     int i;
 
-    dev->start = 0;
-    set_bit (0, (void *)&dev->tbusy);
+    netif_stop_queue(dev);
 
     lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112);
 
@@ -1478,21 +1459,20 @@
 }
 #endif  /* HAVE_PRIVATE_IOCTL */
 					    
-#ifdef MODULE
 MODULE_PARM(debug, "i");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(tx_start_pt, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-					     
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards");
 
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 static int tx_start_pt = -1;
 
-int
-init_module(void)
+static int __init pcnet32_init_module(void)
 {
     if (debug > 0)
 	pcnet32_debug = debug;
@@ -1503,8 +1483,7 @@
     return pcnet32_probe();
 }
 
-void
-cleanup_module(void)
+static void __exit pcnet32_cleanup_module(void)
 {
     struct net_device *next_dev;
 
@@ -1518,10 +1497,10 @@
 	pcnet32_dev = next_dev;
     }
 }
-#endif /* MODULE */
 
+module_init(pcnet32_init_module);
+module_exit(pcnet32_cleanup_module);
 
-
 /*
  * Local variables:
  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c pcnet32.c"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v2.3.42/linux/drivers/net/plip.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/plip.c	Thu Feb 10 12:26:47 2000
@@ -160,7 +160,6 @@
 static int plip_open(struct net_device *dev);
 static int plip_close(struct net_device *dev);
 static struct net_device_stats *plip_get_stats(struct net_device *dev);
-static int plip_config(struct net_device *dev, struct ifmap *map);
 static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 static int plip_preempt(void *handle);
 static void plip_wakeup(void *handle);
@@ -1256,9 +1255,7 @@
 
 static struct net_device *dev_plip[PLIP_MAX] = { NULL, };
 
-#ifdef MODULE
-void
-cleanup_module(void)
+static void __exit plip_cleanup_module (void)
 {
 	int i;
 
@@ -1278,14 +1275,16 @@
 	}
 }
 
-#define plip_init  init_module
-
-#else /* !MODULE */
+#ifndef MODULE
 
 static int parport_ptr = 0;
 
-void plip_setup(char *str, int *ints)
+static void __init plip_setup(char *str)
 {
+	int ints[4];
+
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+
 	/* Ugh. */
 	if (!strncmp(str, "parport", 7)) {
 		int n = simple_strtoul(str+7, NULL, 10);
@@ -1307,7 +1306,9 @@
 	}
 }
 
-#endif /* MODULE */
+__setup("plip=", plip_setup);
+
+#endif /* !MODULE */
 
 static int inline 
 plip_searchfor(int list[], int a)
@@ -1319,8 +1320,7 @@
 	return 0;
 }
 
-int __init
-plip_init(void)
+static int __init plip_init (void)
 {
 	struct parport *pb = parport_enumerate();
 	int i=0;
@@ -1375,7 +1375,10 @@
 	}
 	return 0;
 }
-
+
+module_init(plip_init);
+module_exit(plip_cleanup_module);
+
 /*
  * Local variables:
  * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -c plip.c"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
--- v2.3.42/linux/drivers/net/ppp_generic.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/ppp_generic.c	Wed Feb  9 20:08:09 2000
@@ -527,7 +527,7 @@
 		} else {
 			ppp->npmode[i] = npi.mode;
 			/* we may be able to transmit more packets now (??) */
-			mark_bh(NET_BH);
+			netif_wake_queue(ppp->dev);
 		}
 		err = 0;
 		break;
@@ -539,16 +539,12 @@
 }
 
 static struct file_operations ppp_device_fops = {
-	NULL,		/* seek */
-	ppp_read,
-	ppp_write,
-	NULL,		/* readdir */
-	ppp_poll,
-	ppp_ioctl,
-	NULL,		/* mmap */
-	ppp_open,
-	NULL,		/* flush */
-	ppp_release
+	read:		ppp_read,
+	write:		ppp_write,
+	poll:		ppp_poll,
+	ioctl:		ppp_ioctl,
+	open:		ppp_open,
+	release:	ppp_release
 };
 
 #define PPP_MAJOR	108
@@ -630,11 +626,7 @@
 	pp[0] = proto >> 8;
 	pp[1] = proto;
 
-	/*
-	 * ppp->xq should only ever have more than 1 data packet on it
-	 * if the core net code calls us when dev->tbusy == 1.
-	 */
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 	skb_queue_tail(&ppp->xq, skb);
 	if (trylock_xmit_path(ppp))
 		ppp_xmit_unlock(ppp, 0);
@@ -735,12 +727,9 @@
 		while (ppp->xmit_pending == 0
 		       && (skb = skb_dequeue(&ppp->xq)) != 0)
 			ppp_send_frame(ppp, skb);
-		if (ppp->xmit_pending == 0 && skb_peek(&ppp->xq) == 0
-		    && ppp->dev->tbusy) {
-			ppp->dev->tbusy = 0;
-			if (do_mark_bh)
-				mark_bh(NET_BH);
-		}
+		if (ppp->xmit_pending == 0 && skb_peek(&ppp->xq) == 0)
+			netif_wake_queue(ppp->dev);
+
 		/* Now unlock the transmit path, let others in. */
 		unlock_xmit_path(ppp);
 		/* Check whether any work was queued up
diff -u --recursive --new-file v2.3.42/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- v2.3.42/linux/drivers/net/rcpci45.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/rcpci45.c	Thu Feb 10 12:26:47 2000
@@ -52,13 +52,13 @@
 
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/in.h>
+#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
@@ -67,14 +67,7 @@
 #include <asm/irq.h>            /* For NR_IRQS only. */
 #include <asm/bitops.h>
 #include <asm/io.h>
-
-#if LINUX_VERSION_CODE >= 0x020100
-#define LINUX_2_1
-#endif
-
-#ifdef LINUX_2_1
 #include <asm/uaccess.h>
-#endif
 
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -91,11 +84,6 @@
 #define NEW_MULTICAST
 #include <linux/delay.h>
 
-#ifndef LINUX_2_1
-#define ioremap vremap
-#define iounmap vfree
-#endif
-
 /* PCI/45 Configuration space values */
 #define RC_PCI45_VENDOR_ID  0x4916
 #define RC_PCI45_DEVICE_ID  0x1960
@@ -178,11 +166,7 @@
 /* A list of all installed RC devices, for removing the driver module. */
 static struct net_device *root_RCdev = NULL;
 
-#ifdef MODULE
-int init_module(void)
-#else
-int rcpci_probe(void)
-#endif
+static int __init rcpci_init_module (void)
 {
     int cards_found;
 
@@ -562,11 +546,7 @@
             printk("rc: skb = 0x%x\n", (uint)skb);
 #endif
             BufferContext++;
-#ifdef LINUX_2_1
             dev_kfree_skb (skb);
-#else
-            dev_kfree_skb (skb, FREE_WRITE);
-#endif
         }
         dev->tbusy = 0;
 
@@ -727,18 +707,10 @@
                 while(PktCount--)
                 {
                     skb = (struct sk_buff *)PacketDescBlock[0];
-#ifndef LINUX_2_1
-                    skb->free = 1;
-                    skb->lock = 0;    
-#endif
 #ifdef RCDEBUG
                     printk("free skb 0x%p\n", skb);
 #endif
-#ifdef LINUX_2_1
                     dev_kfree_skb (skb);
-#else
-                    dev_kfree_skb(skb, FREE_READ);
-#endif
                     pDpa->numOutRcvBuffers--;
                     PacketDescBlock += BD_SIZE; /* point to next context field */
                 }
@@ -777,12 +749,7 @@
                     if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
                     {
                         printk("rc: RCrecv_callback: post buffer failed!\n");
-#ifdef LINUX_2_1
                         dev_kfree_skb (skb);
-#else
-                        skb->free = 1;
-                        dev_kfree_skb(skb, FREE_READ);
-#endif
                     }
                     else
                     {
@@ -1089,17 +1056,8 @@
 
     case RCU_COMMAND:
     {
-#ifdef LINUX_2_1
         if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
              return -EFAULT;
-#else
-        int error;
-        error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser));
-        if (error)  {
-            return error;
-        }
-        memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser));
-#endif
         
 #ifdef RCDEBUG
         printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
@@ -1208,11 +1166,7 @@
             RCUD_DEFAULT -> rc = 0x11223344;
             break;
         }
-#ifdef LINUX_2_1
         copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
-#else
-        memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser));
-#endif
         break;
     }   /* RCU_COMMAND */ 
 
@@ -1243,9 +1197,7 @@
 }
 
 
-#ifdef MODULE
-void
-cleanup_module(void)
+static void __exit rcpci_cleanup_module (void)
 {
     PDPA pDpa;
     struct net_device *next;
@@ -1273,7 +1225,9 @@
         root_RCdev = next;
     }
 }
-#endif
+
+module_init(rcpci_init_module);
+module_exit(rcpci_clenaup_module);
 
 
 static int
@@ -1356,17 +1310,10 @@
         while(p[0])
         {
             skb = (struct sk_buff *)pB->context;
-#ifndef LINUX_2_1
-            skb->free = 1;    
-#endif
 #ifdef RCDEBUG
             printk("rc: freeing 0x%x\n", (uint)skb);
 #endif
-#ifdef LINUX_2_1
             dev_kfree_skb (skb);
-#else
-            dev_kfree_skb(skb, FREE_READ);
-#endif
             p[0]--;
             pB++;
         }
diff -u --recursive --new-file v2.3.42/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c
--- v2.3.42/linux/drivers/net/rtl8139.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/rtl8139.c	Wed Feb  9 20:08:09 2000
@@ -165,11 +165,12 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(struct pci_dev *pdev, int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct net_device * rtl8129_probe1(int pci_bus, int pci_devfn, long ioaddr,
-									  int irq, int chp_idx, int fnd_cnt);
+static struct net_device * rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
+										  int pci_devfn, long ioaddr,
+										  int irq, int chp_idx, int fnd_cnt);
 
 static struct pci_id_info pci_tbl[] =
 {{ "RealTek RTL8129 Fast Ethernet",
@@ -249,10 +250,16 @@
 	{0x0bb39de43,0x0bb39ce43,0x0bb39ce83,0x0bb39ce83}
 };
 
+struct ring_info {
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+};
+
 struct rtl8129_private {
 	char devname[8];			/* Used only for kernel debugging. */
 	const char *product_name;
 	struct net_device *next_module;
+	struct pci_dev *pdev;
 	int chip_id;
 	int chip_revision;
 	unsigned char pci_bus, pci_devfn;
@@ -265,10 +272,12 @@
 	unsigned int cur_rx;		/* Index into the Rx buffer of next Rx pkt. */
 	unsigned int cur_tx, dirty_tx, tx_flag;
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	struct sk_buff* tx_skbuff[NUM_TX_DESC];
+	struct ring_info tx_info[NUM_TX_DESC];
 	unsigned char *tx_buf[NUM_TX_DESC];	/* Tx bounce buffers */
 	unsigned char *rx_ring;
 	unsigned char *tx_bufs;				/* Tx bounce buffer region. */
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_bufs_dma;
 	char phys[4];						/* MII device addresses. */
 	char twistie, twist_cnt;			/* Twister tune state. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
@@ -328,6 +337,7 @@
 		return -ENODEV;
 
 	for (; pci_index < 0xff; pci_index++) {
+		struct pci_dev *pdev;
 		u16 vendor, device, pci_command, new_command;
 		int chip_idx, irq;
 		long ioaddr;
@@ -349,22 +359,9 @@
 		if (pci_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
 			continue;
 
-		{
-#if defined(PCI_SUPPORT_VER2)
-			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-			ioaddr = pdev->resource[0].start;
-			irq = pdev->irq;
-#else
-			u32 pci_ioaddr;
-			u8 pci_irq_line;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_INTERRUPT_LINE, &pci_irq_line);
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
-			ioaddr = pci_ioaddr & ~3;
-			irq = pci_irq_line;
-#endif
-		}
+		pdev = pci_find_slot(pci_bus, pci_device_fn);
+		ioaddr = pdev->resource[0].start;
+		irq = pdev->irq;
 
 		if ((pci_tbl[chip_idx].flags & PCI_USES_IO) &&
 			check_region(ioaddr, pci_tbl[chip_idx].io_size))
@@ -382,7 +379,7 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr, irq, chip_idx, cards_found);
+		dev = pci_tbl[chip_idx].probe1(pdev, pci_bus, pci_device_fn, ioaddr, irq, chip_idx, cards_found);
 
 		if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
 			u8 pci_latency;
@@ -403,8 +400,9 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct net_device *rtl8129_probe1(int pci_bus, int pci_devfn, long ioaddr,
-									 int irq, int chip_idx, int found_cnt)
+static struct net_device *rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
+										 int pci_devfn, long ioaddr,
+										 int irq, int chip_idx, int found_cnt)
 {
 	static int did_version = 0;			/* Already printed version info. */
 	struct rtl8129_private *tp;
@@ -449,6 +447,7 @@
 	tp->next_module = root_rtl8129_dev;
 	root_rtl8129_dev = dev;
 
+	tp->pdev = pdev;
 	tp->chip_id = chip_idx;
 	tp->pci_bus = pci_bus;
 	tp->pci_devfn = pci_devfn;
@@ -501,6 +500,8 @@
 	/* The Rtl8129-specific entries in the device structure. */
 	dev->open = &rtl8129_open;
 	dev->hard_start_xmit = &rtl8129_start_xmit;
+	dev->tx_timeout = &rtl8129_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->stop = &rtl8129_close;
 	dev->get_stats = &rtl8129_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
@@ -677,12 +678,22 @@
 
 	MOD_INC_USE_COUNT;
 
-	tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL);
-	tp->rx_ring = kmalloc(RX_BUF_LEN + 16, GFP_KERNEL);
+	tp->tx_bufs = pci_alloc_consistent(tp->pdev,
+									   TX_BUF_SIZE * NUM_TX_DESC,
+									   &tp->tx_bufs_dma);
+	tp->rx_ring = pci_alloc_consistent(tp->pdev,
+									   RX_BUF_LEN + 16,
+									   &tp->rx_ring_dma);
 	if (tp->tx_bufs == NULL ||  tp->rx_ring == NULL) {
 		free_irq(dev->irq, dev);
 		if (tp->tx_bufs)
-			kfree(tp->tx_bufs);
+			pci_free_consistent(tp->pdev,
+								TX_BUF_SIZE * NUM_TX_DESC,
+								tp->tx_bufs, tp->tx_bufs_dma);
+		if (tp->rx_ring)
+			pci_free_consistent(tp->pdev,
+								RX_BUF_LEN + 16,
+								tp->rx_ring, tp->rx_ring_dma);
 		if (rtl8129_debug > 0)
 			printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n",
 				   dev->name, RX_BUF_LEN);
@@ -725,7 +736,7 @@
 	outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
 	outb(0x00, ioaddr + Cfg9346);
 
-	outl(virt_to_bus(tp->rx_ring), ioaddr + RxBuf);
+	outl(tp->rx_ring_dma, ioaddr + RxBuf);
 
 	/* Start the chip's Tx and Rx process. */
 	outl(0, ioaddr + RxMissed);
@@ -733,10 +744,6 @@
 
 	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
 	/* Enable all known interrupts by setting the interrupt mask. */
 	outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
 		 | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
@@ -787,7 +794,8 @@
 			rtl8129_interrupt(dev->irq, dev, 0);
 		}
 	}
-	if (dev->tbusy  &&  jiffies - dev->trans_start >= 2*TX_TIMEOUT)
+	if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+		(jiffies - dev->trans_start) >= 2*TX_TIMEOUT)
 		rtl8129_tx_timeout(dev);
 
 #if 0
@@ -902,26 +910,40 @@
 	{							/* Save the unsent Tx packets. */
 		struct sk_buff *saved_skb[NUM_TX_DESC], *skb;
 		int j;
-		for (j = 0; tp->cur_tx - tp->dirty_tx > 0 ; j++, tp->dirty_tx++)
-			saved_skb[j] = tp->tx_skbuff[tp->dirty_tx % NUM_TX_DESC];
+		for (j = 0; tp->cur_tx - tp->dirty_tx > 0 ; j++, tp->dirty_tx++) {
+			struct ring_info *rp = &tp->tx_info[tp->dirty_tx % NUM_TX_DESC];
+
+			saved_skb[j] = rp->skb;
+			if (rp->mapping != 0) {
+				pci_unmap_single(tp->pdev, rp->mapping, rp->skb->len);
+				rp->mapping = 0;
+			}
+		}
 		tp->dirty_tx = tp->cur_tx = 0;
 
 		for (i = 0; i < j; i++) {
-			skb = tp->tx_skbuff[i] = saved_skb[i];
+			skb = tp->tx_info[i].skb = saved_skb[i];
 			if ((long)skb->data & 3) {		/* Must use alignment buffer. */
 				memcpy(tp->tx_buf[i], skb->data, skb->len);
-				outl(virt_to_bus(tp->tx_buf[i]), ioaddr + TxAddr0 + i*4);
-			} else
-				outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + i*4);
+				outl(tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs),
+					 ioaddr + TxAddr0 + i*4);
+			} else {
+				tp->tx_info[i].mapping =
+					pci_map_single(tp->pdev, skb->data, skb->len);
+				outl(tp->tx_info[i].mapping, ioaddr + TxAddr0 + i*4);
+			}
 			/* Note: the chip doesn't have auto-pad! */
 			outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
 				 ioaddr + TxStatus0 + i*4);
 		}
 		tp->cur_tx = i;
-		while (i < NUM_TX_DESC)
-			tp->tx_skbuff[i++] = 0;
+		while (i < NUM_TX_DESC) {
+			tp->tx_info[i].skb = NULL;
+			tp->tx_info[i].mapping = 0;
+			i++;
+		}
 		if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
-			dev->tbusy = 0;
+			netif_wake_queue(dev);
 			tp->tx_full = 0;
 		} else {
 			tp->tx_full = 1;
@@ -949,8 +971,9 @@
 	tp->dirty_tx = tp->cur_tx = 0;
 
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		tp->tx_skbuff[i] = 0;
 		tp->tx_buf[i] = &tp->tx_bufs[i*TX_BUF_SIZE];
+		tp->tx_info[i].skb = NULL;
+		tp->tx_info[i].mapping = 0;
 	}
 }
 
@@ -961,29 +984,28 @@
 	long ioaddr = dev->base_addr;
 	int entry;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start >= TX_TIMEOUT)
-			rtl8129_tx_timeout(dev);
-		return 1;
-	}
+	netif_stop_queue(dev);
 
 	/* Calculate the next Tx descriptor entry. */
 	entry = tp->cur_tx % NUM_TX_DESC;
 
-	tp->tx_skbuff[entry] = skb;
+	tp->tx_info[entry].skb = skb;
 	if ((long)skb->data & 3) {			/* Must use alignment buffer. */
+		tp->tx_info[entry].mapping = 0;
 		memcpy(tp->tx_buf[entry], skb->data, skb->len);
-		outl(virt_to_bus(tp->tx_buf[entry]), ioaddr + TxAddr0 + entry*4);
-	} else
-		outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + entry*4);
+		outl(tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs),
+			 ioaddr + TxAddr0 + entry*4);
+	} else {
+		tp->tx_info[entry].mapping =
+			pci_map_single(tp->pdev, skb->data, skb->len);
+		outl(tp->tx_info[entry].mapping, ioaddr + TxAddr0 + entry*4);
+	}
 	/* Note: the chip doesn't have auto-pad! */
 	outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
 		 ioaddr + TxStatus0 + entry*4);
 
 	if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {	/* Typical path */
-		clear_bit(0, (void*)&dev->tbusy);
+		netif_start_queue(dev);
 	} else {
 		tp->tx_full = 1;
 	}
@@ -1006,22 +1028,6 @@
 	int status, link_changed = 0;
 	long ioaddr = dev->base_addr;
 
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		dev->interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-#else
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
-	dev->interrupt = 1;
-#endif
-
 	do {
 		status = inw(ioaddr + IntrStatus);
 		/* Acknowledge all of the current interrupt sources ASAP, but
@@ -1082,14 +1088,20 @@
 					tp->stats.tx_packets++;
 				}
 
+				if (tp->tx_info[entry].mapping != 0) {
+					pci_unmap_single(tp->pdev,
+									 tp->tx_info[entry].mapping,
+									 tp->tx_info[entry].skb->len);
+					tp->tx_info[entry].mapping = 0;
+				}
+
 				/* Free the original skb. */
-				dev_free_skb(tp->tx_skbuff[entry]);
-				tp->tx_skbuff[entry] = 0;
+				dev_free_skb(tp->tx_info[entry].skb);
+				tp->tx_info[entry].skb = NULL;
 				if (tp->tx_full) {
-					/* The ring is no longer full, clear tbusy. */
+					/* The ring is no longer full, wake the queue. */
 					tp->tx_full = 0;
-					clear_bit(0, (void*)&dev->tbusy);
-					mark_bh(NET_BH);
+					netif_wake_queue(dev);
 				}
 				dirty_tx++;
 			}
@@ -1162,12 +1174,6 @@
 	if (rtl8129_debug > 3)
 		printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n",
 			   dev->name, inl(ioaddr + IntrStatus));
-
-#if defined(__i386__)
-	clear_bit(0, (void*)&dev->interrupt);
-#else
-	dev->interrupt = 0;
-#endif
 	return;
 }
 
@@ -1289,8 +1295,7 @@
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (rtl8129_debug > 1)
 		printk(KERN_DEBUG"%s: Shutting down ethercard, status was 0x%4.4x.\n",
@@ -1311,12 +1316,23 @@
 	free_irq(dev->irq, dev);
 
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		if (tp->tx_skbuff[i])
-			dev_free_skb(tp->tx_skbuff[i]);
-		tp->tx_skbuff[i] = 0;
+		struct sk_buff *skb = tp->tx_info[i].skb;
+		dma_addr_t mapping = tp->tx_info[i].mapping;
+
+		if (skb) {
+			if (mapping)
+				pci_unmap_single(tp->pdev, mapping, skb->len);
+			dev_free_skb(skb);
+		}
+		tp->tx_info[i].skb = NULL;
+		tp->tx_info[i].mapping = 0;
 	}
-	kfree(tp->rx_ring);
-	kfree(tp->tx_bufs);
+	pci_free_consistent(tp->pdev, RX_BUF_LEN + 16,
+						tp->rx_ring, tp->rx_ring_dma);
+	pci_free_consistent(tp->pdev, TX_BUF_SIZE * NUM_TX_DESC,
+						tp->tx_bufs, tp->tx_bufs_dma);
+	tp->rx_ring = NULL;
+	tp->tx_bufs = NULL;
 
 	/* Green! Put the chip in low-power mode. */
 	outb(0xC0, ioaddr + Cfg9346);
@@ -1356,7 +1372,7 @@
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (dev->start) {
+	if (test_bit(LINK_STATE_START, &dev->state)) {
 		tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
 		outl(0, ioaddr + RxMissed);
 	}
diff -u --recursive --new-file v2.3.42/linux/drivers/net/setup.c linux/drivers/net/setup.c
--- v2.3.42/linux/drivers/net/setup.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/net/setup.c	Thu Feb 10 12:24:54 2000
@@ -8,7 +8,6 @@
 #include <linux/init.h>
 #include <linux/netlink.h>
 
-extern int plip_init(void);
 extern int mkiss_init_ctrl_dev(void);
 extern int ppp_init(void);
 extern int slip_init_ctrl_dev(void);
@@ -21,42 +20,16 @@
 extern int scc_init(void);
 extern int yam_init(void);
 
-extern int acenic_probe(void); 
 extern int awc4500_pci_probe(void);
 extern int awc4500_isa_probe(void);
 extern int awc4500_pnp_probe(void);
 extern int awc4500_365_probe(void);
 extern int arcnet_init(void); 
-extern int bigmac_probe(void); 
-extern int bmac_probe(void); 
 extern int cpm_enet_init(void); 
-extern int oaknet_init(void);
 extern int dlci_setup(void); 
-extern int dgrs_probe(void); 
-extern int dmfe_reg_board(void); 
-extern int eepro100_probe(void); 
-extern int epic100_probe(void); 
-extern int happy_meal_probe(void); 
 extern int lapbeth_init(void);
-extern int mace_probe(void); 
-extern int myri_sbus_probe(void); 
-extern int ncr885e_probe(void); 
-extern int ne2k_pci_probe(void); 
-extern int pcnet32_probe(void); 
-extern int qec_probe(void); 
-extern int rcpci_probe(void); 
-extern int rr_hippi_probe(void); 
-extern int rtl8139_probe(void); 
 extern int sdla_setup(void); 
 extern int sdla_c_setup(void); 
-extern int sis900_probe(void); 
-extern int skge_probe(void); 
-extern int sparc_lance_probe(void); 
-extern int starfire_probe(void); 
-extern int tc59x_probe(void); 
-extern int tulip_probe(void); 
-extern int via_rhine_probe(void); 
-extern int yellowfin_probe(void);
 
 extern int abyss_probe(void);
 extern int madgemc_probe(void);
@@ -104,9 +77,6 @@
 #if defined(CONFIG_LAPBETHER)
 	{lapbeth_init, 0},
 #endif
-#if defined(CONFIG_PLIP)
-	{plip_init, 0},
-#endif
 #if defined(CONFIG_ARCNET)
 	{arcnet_init, 0},
 #endif
@@ -124,111 +94,6 @@
     || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
 	{slhc_install, 0},
 #endif	
-#endif
-/*
- *	HIPPI
- */
-#ifdef CONFIG_ROADRUNNER
-	{rr_hippi_probe, 0},
-#endif
-
-/*
- *	ETHERNET
- */
- 
-/*
- *	SBUS Ethernet
- */
-
-#ifdef CONFIG_HAPPYMEAL
-	{happy_meal_probe, 0},
-#endif
-#ifdef CONFIG_SUNLANCE
-	{sparc_lance_probe, 0},
-#endif
-#ifdef CONFIG_SUNQE
-	{qec_probe, 0},
-#endif
-#ifdef CONFIG_SUNBMAC
-	{bigmac_probe, 0},
-#endif
-#ifdef CONFIG_MYRI_SBUS
-	{myri_sbus_probe, 0},
-#endif
-
-/*
- *	PowerPC Mainboard
- */
-
-#ifdef CONFIG_MACE
-	{mace_probe, 0},
-#endif
-#ifdef CONFIG_BMAC
-	{bmac_probe, 0},
-#endif
-#ifdef CONFIG_NCR885E
-	{ncr885e_probe, 0},
-#endif
-
-/*
- *	IBM "Oak" Evaluation board
- */
-#ifdef	CONFIG_OAKNET
-	{oaknet_init, 0},
-#endif
-
-/*
- *	PCI Ethernet
- */
-#ifdef CONFIG_DGRS
-	{dgrs_probe, 0},
-#endif
-#ifdef CONFIG_RCPCI
-	{rcpci_probe, 0},
-#endif
-#ifdef CONFIG_VORTEX
-	{tc59x_probe, 0},
-#endif
-#ifdef CONFIG_NE2K_PCI
-	{ne2k_pci_probe, 0},
-#endif
-#ifdef CONFIG_PCNET32
-	{pcnet32_probe, 0},
-#endif	
-#ifdef CONFIG_EEXPRESS_PRO100	/* Intel EtherExpress Pro/100 */
-	{eepro100_probe, 0},
-#endif
-#ifdef CONFIG_DEC_ELCP 
-	{tulip_probe, 0},
-#endif
-#ifdef CONFIG_EPIC100
-	{epic100_probe, 0},
-#endif
-#ifdef CONFIG_RTL8139
-	{rtl8139_probe, 0},
-#endif
-#ifdef CONFIG_SIS900
-	{sis900_probe, 0},
-#endif
-
-#ifdef CONFIG_DM9102
-	{dmfe_reg_board, 0}, 
-#endif
-
-#ifdef CONFIG_YELLOWFIN
-	{yellowfin_probe, 0},
-#endif
-#ifdef CONFIG_ACENIC
-	{acenic_probe, 0},
-#endif
-#ifdef CONFIG_SK98LIN
-	{skge_probe, 0},
-#endif
-#ifdef CONFIG_VIA_RHINE
-	{via_rhine_probe, 0},
-#endif
-#ifdef CONFIG_ADAPTEC_STARFIRE
-	{starfire_probe, 0},
 #endif
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.3.42/linux/drivers/net/shaper.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/shaper.c	Wed Feb  9 20:08:09 2000
@@ -287,6 +287,7 @@
 {
 	struct shaper *sh=(struct shaper *)data;
 	shaper_kick(sh);
+	timer_exit(&sh->timer);
 }
 
 /*
@@ -404,9 +405,7 @@
 {
 	struct shaper *shaper=dev->priv;
 	shaper_flush(shaper);
-	start_bh_atomic();
-	del_timer(&shaper->timer);
-	end_bh_atomic();
+	del_timer_sync(&shaper->timer);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sis900.c linux/drivers/net/sis900.c
--- v2.3.42/linux/drivers/net/sis900.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/sis900.c	Thu Feb 10 12:26:47 2000
@@ -39,6 +39,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
+#include <linux/init.h>
 
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -112,6 +113,8 @@
 	struct net_device *next_module;
 	struct net_device_stats stats;
 	struct pci_dev * pci_dev;
+	
+	spinlock_t lock;
 
 	struct mac_chip_info * mac;
 	struct mii_phy * mii;
@@ -131,15 +134,11 @@
 	int LinkOn;
 };
 
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>");
 MODULE_DESCRIPTION("SiS 900 PCI Fast Ethernet driver");
 MODULE_PARM(multicast_filter_limit, "i");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(debug, "i");
-#endif
-#endif
 
 static int sis900_open(struct net_device *net_dev);
 static int sis900_mii_probe (struct net_device * net_dev);
@@ -167,18 +166,16 @@
 static struct net_device *root_sis900_dev = NULL;
 
 /* walk through every ethernet PCI devices to see if some of them are matched with our card list*/
-int sis900_probe (struct net_device * net_dev)
+static int __init sis900_probe (void)
 {
 	int found = 0;
 	struct pci_dev * pci_dev = NULL;
 		
-	if (!pci_present())
-		return -ENODEV;
-		
 	while ((pci_dev = pci_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_dev)) != NULL) {
 		/* pci_dev contains all ethernet devices */
 		u32 pci_io_base;
 		struct mac_chip_info * mac;
+		struct net_device *net_dev = NULL;
 
 		for (mac = mac_chip_table; mac->vendor_id; mac++) {
 			/* try to match our card list */
@@ -198,6 +195,7 @@
 			continue;
 		
 		/* setup various bits in PCI command register */
+		pci_enable_device (pci_dev);
 		pci_set_master(pci_dev);
 
 		/* do the real low level jobs */
@@ -258,6 +256,7 @@
 	net_dev->irq = irq;
 	sis_priv->pci_dev = pci_dev;
 	sis_priv->mac = mac;
+	sis_priv->lock = SPIN_LOCK_UNLOCKED;
 
 	/* probe for mii transciver */
 	if (sis900_mii_probe(net_dev) == 0) {
@@ -277,6 +276,8 @@
 	net_dev->get_stats = &sis900_get_stats;
 	net_dev->set_multicast_list = &set_rx_mode;
 	net_dev->do_ioctl = &mii_ioctl;
+	net_dev->tx_timeout = sis900_tx_timeout;
+	net_dev->watchdog_timeo = TX_TIMEOUT;
 
 	return net_dev;
 }
@@ -506,9 +507,7 @@
 
 	set_rx_mode(net_dev);
 
-	net_dev->tbusy = 0;
-	net_dev->interrupt = 0;
-	net_dev->start = 1;
+	netif_start_queue(net_dev);
 
 	/* Enable all known interrupts by setting the interrupt mask. */
 	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
@@ -811,7 +810,8 @@
 	}
 
 	net_dev->trans_start = jiffies;
-	net_dev->tbusy = sis_priv->tx_full = 0;
+	sis_priv->tx_full = 0;
+	netif_start_queue(net_dev);
 
 	/* FIXME: Should we restart the transmission thread here  ?? */
 
@@ -827,13 +827,6 @@
 	long ioaddr = net_dev->base_addr;
 	unsigned int  entry;
 
-	/* test tbusy to see if we have timeout situation then set it */
-	if (test_and_set_bit(0, (void*)&net_dev->tbusy) != 0) {
-		if (jiffies - net_dev->trans_start > TX_TIMEOUT)
-			sis900_tx_timeout(net_dev);
-		return 1;
-	}
-
 	/* Calculate the next Tx descriptor entry. */
 	entry = sis_priv->cur_tx % NUM_TX_DESC;
 	sis_priv->tx_skbuff[entry] = skb;
@@ -846,7 +839,7 @@
 	if (++sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC) {
 		/* Typical path, clear tbusy to indicate more 
 		   transmission is possible */
-		clear_bit(0, (void*)&net_dev->tbusy);
+		netif_start_queue(net_dev);
 	} else {
 		/* no more transmit descriptor avaiable, tbusy remain set */
 		sis_priv->tx_full = 1;
@@ -867,26 +860,12 @@
 static void sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *net_dev = (struct net_device *)dev_instance;
+	struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
 	int boguscnt = max_interrupt_work;
 	long ioaddr = net_dev->base_addr;
 	u32 status;
 
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&net_dev->interrupt)) {
-		printk(KERN_INFO "%s: SMP simultaneous entry of "
-		       "an interrupt handler.\n", net_dev->name);
-		net_dev->interrupt = 0;     /* Avoid halting machine. */
-		return;
-	}
-#else
-	if (net_dev->interrupt) {
-		printk(KERN_INFO "%s: Re-entering the interrupt handler.\n", 
-		       net_dev->name);
-		return;
-	}
-	net_dev->interrupt = 1;
-#endif
+	spin_lock (&sis_priv->lock);
 
 	do {
 		status = inl(ioaddr + isr);
@@ -923,11 +902,7 @@
 		       "interrupt status = 0x%#8.8x.\n",
 		       net_dev->name, inl(ioaddr + isr));
 	
-#if defined(__i386__)
-	clear_bit(0, (void*)&net_dev->interrupt);
-#else
-	net_dev->interrupt = 0;
-#endif
+	spin_unlock (&sis_priv->lock);
 	return;
 }
 
@@ -1079,13 +1054,12 @@
 		sis_priv->tx_ring[entry].cmdsts = 0;
 	}
 	
-	if (sis_priv->tx_full && net_dev->tbusy && 
+	if (sis_priv->tx_full && test_bit(LINK_STATE_XOFF, &net_dev->flags) && 
 	    sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
 		/* The ring is no longer full, clear tbusy, tx_full and
 		   schedule more transmission by marking NET_BH */
 		sis_priv->tx_full = 0;
-		clear_bit(0, (void *)&net_dev->tbusy);
-		mark_bh(NET_BH);
+		netif_wake_queue (net_dev);
 	}
 }
 
@@ -1096,8 +1070,7 @@
 	struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
 	int i;
 	
-	net_dev->start = 0;
-	net_dev->tbusy = 1;
+	netif_stop_queue(net_dev);
 
 	/* Disable interrupts by clearing the interrupt mask. */
 	outl(0x0000, ioaddr + imr);
@@ -1264,14 +1237,7 @@
 	outl(PESEL, ioaddr + cfg);
 }
 
-#ifdef MODULE
-int init_module(void)
-{
-	return sis900_probe(NULL);
-}
-
-void
-cleanup_module(void)
+static void __exit sis900_cleanup_module(void)
 {
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_sis900_dev) {
@@ -1289,4 +1255,5 @@
 	}
 }
 
-#endif  /* MODULE */
+module_init(sis900_probe);
+module_exit(sis900_cleanup_module);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sk98lin/h/skdrv2nd.h linux/drivers/net/sk98lin/h/skdrv2nd.h
--- v2.3.42/linux/drivers/net/sk98lin/h/skdrv2nd.h	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/sk98lin/h/skdrv2nd.h	Tue Feb  8 18:58:25 2000
@@ -429,6 +429,8 @@
 
 	
 	caddr_t		pDescrMem;	/* Pointer to the descriptor area */
+	dma_addr_t	pDescrMemDMA;	/* PCI DMA address of area */
+
 	/* the port structures with descriptor rings */
 	TX_PORT		TxPort[SK_MAX_MACS][2];
 	RX_PORT		RxPort[SK_MAX_MACS];
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sk98lin/skge.c linux/drivers/net/sk98lin/skge.c
--- v2.3.42/linux/drivers/net/sk98lin/skge.c	Tue Dec  7 09:32:44 1999
+++ linux/drivers/net/sk98lin/skge.c	Thu Feb 10 12:26:47 2000
@@ -228,6 +228,7 @@
 	"@(#)SK-BUILD: 3.02 (19991111) PL: 01"; 
 
 #include	<linux/module.h>
+#include	<linux/init.h>
 
 #include	"h/skdrv1st.h"
 #include	"h/skdrv2nd.h"
@@ -341,13 +342,14 @@
  *	0, if everything is ok
  *	!=0, on error
  */
-int __init skge_probe (struct net_device *dev)
+static int __init skge_probe (void)
 {
-int boards_found = 0;
-int		version_disp = 0;
-SK_AC		*pAC;
-struct pci_dev	*pdev = NULL;
-unsigned long	base_address;
+	int boards_found = 0;
+	int		version_disp = 0;
+	SK_AC		*pAC;
+	struct pci_dev	*pdev = NULL;
+	unsigned long	base_address;
+	struct net_device *dev = NULL;
 
 	if (probed)
 		return -ENODEV;
@@ -375,21 +377,12 @@
 		}
 		dev = init_etherdev(dev, sizeof(SK_AC));
 
-		if (dev == NULL){
+		if (dev == NULL || dev->priv == NULL){
 			printk(KERN_ERR "Unable to allocate etherdev "
 			       "structure!\n");
 			break;
 		}
 
-		if (!dev->priv)
-			dev->priv = kmalloc(sizeof(SK_AC), GFP_KERNEL);
-		if (dev->priv == NULL){
-			printk(KERN_ERR "Unable to allocate adapter "
-			       "structure!\n");
-			break;
-		}
-
-		
 		memset(dev->priv, 0, sizeof(SK_AC));
 
 		pAC = dev->priv;
@@ -471,14 +464,7 @@
 	 * or more boards. Otherwise, return failure (-ENODEV).
 	 */
 
-#ifdef MODULE
 	return boards_found;
-#else
-	if (boards_found > 0)
-		return 0;
-	else
-		return -ENODEV;
-#endif
 } /* skge_probe */
 
 
@@ -515,8 +501,6 @@
 } /* FreeResources */
 
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Christoph Goos <cgoos@syskonnect.de>");
 MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
 MODULE_PARM(AutoNeg_A,  "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
@@ -533,8 +517,6 @@
 MODULE_PARM(options,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
 MODULE_PARM(debug,      "i");
 
-#endif // MODULE
-
 
 #ifdef AUTO_NEG_A
 static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
@@ -597,15 +579,13 @@
 #endif
 
 
-#ifdef MODULE
-
 static int debug = 0; /* not used */
 static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
 
 
 /*****************************************************************************
  *
- * 	init_module - module initialization function
+ * 	skge_init_module - module initialization function
  *
  * Description:
  *	Very simple, only call skge_probe and return approriate result.
@@ -614,9 +594,9 @@
  *	0, if everything is ok
  *	!=0, on error
  */
-int init_module(void)
+static int __init skge_init_module(void)
 {
-int cards;
+	int cards;
 
 	root_dev = NULL;
 	
@@ -624,17 +604,17 @@
 	debug = 0;
 	options[0] = 0;
 
-	cards = skge_probe(NULL);
+	cards = skge_probe();
 	if (cards == 0) {
 		printk("No adapter found\n");
 	}
 	return cards ? 0 : -ENODEV;
-} /* init_module */
+} /* skge_init_module */
 
 
 /*****************************************************************************
  *
- * 	cleanup_module - module unload function
+ * 	skge_cleanup_module - module unload function
  *
  * Description:
  *	Disable adapter if it is still running, free resources,
@@ -642,7 +622,7 @@
  *
  * Returns: N/A
  */
-void cleanup_module(void)
+static void __exit skge_cleanup_module(void)
 {
 SK_AC	*pAC;
 struct net_device *next;
@@ -653,7 +633,7 @@
 		pAC = (SK_AC*)root_dev->priv;
 		next = pAC->Next;
 
-		root_dev->tbusy = 1;
+		netif_stop_queue(root_dev);
 		SkGeYellowLED(pAC, pAC->IoBase, 0);
 		
 		if(pAC->BoardLevel == 2) {
@@ -687,9 +667,10 @@
 
 		root_dev = next;
 	}
-}
-#endif /* cleanup_module */
+} /* skge_cleanup_module */
 
+module_init(skge_init_module);
+module_exit(skge_cleanup_module);
 
 /*****************************************************************************
  *
@@ -851,41 +832,35 @@
 	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
 		+ RX_RING_SIZE + 8;
 #endif
-	pDescrMem = kmalloc(AllocLength, GFP_KERNEL);
+	pDescrMem = pci_alloc_consistent(&pAC->PciDev, AllocLength,
+					 &pAC->pDescrMemDMA);
 	if (pDescrMem == NULL) {
 		return (SK_FALSE);
 	}
 	pAC->pDescrMem = pDescrMem;
-	memset(pDescrMem, 0, AllocLength);
-	/* Descriptors need 8 byte alignment */
-	BusAddr = virt_to_bus(pDescrMem);
-	if (BusAddr & (DESCR_ALIGN-1)) {
-		pDescrMem += DESCR_ALIGN - (BusAddr & (DESCR_ALIGN-1));
-	}
+
+	/* Descriptors need 8 byte alignment, and this is ensured
+	 * by pci_alloc_consistent.
+	 */
+	BusAddr = (unsigned long) pAC->pDescrMemDMA;
 	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		if ((virt_to_bus(pDescrMem) & ~0xFFFFFFFFULL) != 
-		    (virt_to_bus(pDescrMem+TX_RING_SIZE) & ~0xFFFFFFFFULL)) {
-			pDescrMem += TX_RING_SIZE;
-		}
 		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
 			("TX%d/A: pDescrMem: %lX,   PhysDescrMem: %lX\n",
 			i, (unsigned long) pDescrMem,
-			(unsigned long)virt_to_bus(pDescrMem)));
+			BusAddr));
 		pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
-		pAC->TxPort[i][0].VTxDescrRing = virt_to_bus(pDescrMem);
+		pAC->TxPort[i][0].VTxDescrRing = BusAddr;
 		pDescrMem += TX_RING_SIZE;
+		BusAddr += TX_RING_SIZE;
 	
-		if ((virt_to_bus(pDescrMem) & ~0xFFFFFFFFULL) != 
-		    (virt_to_bus(pDescrMem+RX_RING_SIZE) & ~0xFFFFFFFFULL)) {
-			pDescrMem += RX_RING_SIZE;
-		}
 		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
 			("RX%d: pDescrMem: %lX,   PhysDescrMem: %lX\n",
 			i, (unsigned long) pDescrMem,
-			(unsigned long)(virt_to_bus(pDescrMem))));
+			(unsigned long)BusAddr));
 		pAC->RxPort[i].pRxDescrRing = pDescrMem;
-		pAC->RxPort[i].VRxDescrRing = virt_to_bus(pDescrMem);
+		pAC->RxPort[i].VRxDescrRing = BusAddr;
 		pDescrMem += RX_RING_SIZE;
+		BusAddr += RX_RING_SIZE;
 	} /* for */
 	
 	return (SK_TRUE);
@@ -905,9 +880,19 @@
 static void BoardFreeMem(
 SK_AC		*pAC)
 {
+size_t		AllocLength;	/* length of complete descriptor area */
+
 	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
 		("BoardFreeMem\n"));
-	kfree(pAC->pDescrMem);
+#if (BITS_PER_LONG == 32)
+	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+#else
+	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+		+ RX_RING_SIZE + 8;
+#endif
+	pci_free_consistent(&pAC->PciDev, AllocLength,
+			    pAC->pDescrMem, pAC->pDescrMemDMA);
+	pAC->pDescrMem = NULL;
 } /* BoardFreeMem */
 
 
@@ -1428,10 +1413,6 @@
 	SkEventDispatcher(pAC, pAC->IoBase);
 	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
 	
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
 	MOD_INC_USE_COUNT;
 	
 	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
@@ -1460,9 +1441,8 @@
 int		i;
 SK_EVPARA	EvPara;
 
-	dev->start = 0;
-	set_bit(0, (void*)&dev->tbusy);
-	
+	netif_stop_queue(dev);
+
 	pAC = (SK_AC*) dev->priv;
 	
 	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
@@ -1529,8 +1509,10 @@
 
 	if (Rc == 0) {
 		/* transmitter out of resources */
-		set_bit(0, (void*) &dev->tbusy);
-		return (0);
+		netif_stop_queue(dev);
+
+		/* give buffer ownership back to the queueing layer */
+		return (1);
 	} 
 	dev->trans_start = jiffies;
 	return (0);
@@ -1584,7 +1566,6 @@
 				SK_DBGCAT_DRV_TX_PROGRESS,
 				("XmitFrame failed\n"));
 			/* this message can not be sent now */
-			DEV_KFREE_SKB(pMessage);
 			return (0);
 		}
 	}
@@ -1603,7 +1584,9 @@
 #endif
 
 	/* set up descriptor and CONTROL dword */
-	PhysAddr = virt_to_bus(pMessage->data);
+	PhysAddr = (SK_U64) pci_map_single(&pAC->PciDev,
+					   pMessage->data,
+					   pMessage->len);
 	pTxd->VDataLow = (SK_U32)  (PhysAddr & 0xffffffff);
 	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
 	pTxd->pMBuf = pMessage;
@@ -1662,6 +1645,7 @@
 TXD	*pTxd;		/* pointer to the checked descriptor */
 TXD	*pNewTail;	/* pointer to 'end' of the ring */
 SK_U32	Control;	/* TBControl field of descriptor */
+SK_U64	PhysAddr;	/* address of DMA mapping */
 
 	pNewTail = pTxPort->pTxdRingTail;
 	pTxd = pNewTail;
@@ -1680,17 +1664,23 @@
 			 * freed ( -> ring completely free now).
 			 */
 			pTxPort->pTxdRingTail = pTxd;
-			pAC->dev->tbusy = 0;
+			netif_start_queue(pAC->dev);
 			return;
 		}
 		if (Control & TX_CTRL_OWN_BMU) {
 			pTxPort->pTxdRingTail = pTxd;
 			if (pTxPort->TxdRingFree > 0) {
-				pAC->dev->tbusy = 0;
+				netif_start_queue(pAC->dev);
 			}
 			return;
 		}
 		
+		/* release the DMA mapping */
+		PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
+		PhysAddr |= (SK_U64) pTxd->VDataLow;
+		pci_unmap_single(&pAC->PciDev, PhysAddr,
+				 pTxd->pMBuf->len);
+
 		DEV_KFREE_SKB(pTxd->pMBuf); /* free message */
 		pTxPort->TxdRingFree++;
 		pTxd->TBControl &= ~TX_CTRL_SOFTWARE;
@@ -1767,7 +1757,9 @@
 	pRxPort->pRxdRingTail = pRxd->pNextRxd;
 	pRxPort->RxdRingFree--;
 	Length = pAC->RxBufSize;
-	PhysAddr = virt_to_bus(pMsgBlock->data);
+	PhysAddr = (SK_U64) pci_map_single(&pAC->PciDev,
+					   pMsgBlock->data,
+					   pAC->RxBufSize - 2);
 	pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
 	pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
 	pRxd->pMBuf = pMsgBlock;
@@ -1845,6 +1837,8 @@
 unsigned short	Csum2;
 unsigned short	Type;
 int		Result;
+SK_U64		PhysAddr;
+
 
 rx_start:	
 	/* do forever; exit if RX_CTRL_OWN_BMU found */
@@ -1876,17 +1870,19 @@
 		/*
 		 * if short frame then copy data to reduce memory waste
 		 */
+		pNewMsg = NULL;
 		if (FrameLength < SK_COPY_THRESHOLD) {
 			pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC);
-			if (pNewMsg == NULL) {
-				/* use original skb */
-				/* set length in message */
-				skb_put(pMsg, FrameLength);
-			}
-			else {
-				/* alloc new skb and copy data */
+			if (pNewMsg != NULL) {
+				PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+				PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+				/* use new skb and copy data */
 				skb_reserve(pNewMsg, 2);
 				skb_put(pNewMsg, FrameLength);
+				pci_dma_sync_single(&pAC->PciDev,
+						    (dma_addr_t) PhysAddr,
+						    FrameLength);
 				eth_copy_and_sum(pNewMsg, pMsg->data,
 					FrameLength, 0);
 				ReQueueRxBuffer(pAC, pRxPort, pMsg,
@@ -1894,7 +1890,20 @@
 				pMsg = pNewMsg;
 			}
 		}
-		else {
+
+		/*
+		 * if large frame, or SKB allocation failed, pass
+		 * the SKB directly to the networking
+		 */
+		if (pNewMsg == NULL) {
+			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+			PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+			/* release the DMA mapping */
+			pci_unmap_single(&pAC->PciDev,
+					 PhysAddr,
+					 pAC->RxBufSize - 2);
+
 			/* set length in message */
 			skb_put(pMsg, FrameLength);
 			/* hardware checksum */
@@ -2045,6 +2054,13 @@
 	/* remove error frame */
 	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
 		("Schrottdescriptor, length: 0x%x\n", FrameLength));
+
+	/* release the DMA mapping */
+	PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+	PhysAddr |= (SK_U64) pRxd->VDataLow;
+	pci_unmap_single(&pAC->PciDev,
+			 PhysAddr,
+			 pAC->RxBufSize - 2);
 	DEV_KFREE_SKB(pRxd->pMBuf);
 	pRxd->pMBuf = NULL;
 	pRxPort->RxdRingFree++;
@@ -2110,6 +2126,7 @@
 {
 RXD		*pRxd;	/* pointer to the current descriptor */
 unsigned int	Flags;
+ SK_U64		PhysAddr;
 
 	if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
 		return;
@@ -2118,6 +2135,11 @@
 	pRxd = pRxPort->pRxdRingHead;
 	do {
 		if (pRxd->pMBuf != NULL) {
+			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+			PhysAddr |= (SK_U64) pRxd->VDataLow;
+			pci_unmap_single(&pAC->PciDev,
+					 PhysAddr,
+					 pAC->RxBufSize - 2);
 			DEV_KFREE_SKB(pRxd->pMBuf);
 			pRxd->pMBuf = NULL;
 		}
@@ -2254,7 +2276,7 @@
 	
 	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
 		("SkGeSetMacAddr starts now...\n"));
-	if(dev->start) {
+	if(test_bit(LINK_STATE_START, &dev->state)) {
 		return -EBUSY;
 	}
 	memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
@@ -2380,7 +2402,7 @@
 		spin_lock_irqsave(
 			&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
 	}
-	pAC->dev->tbusy = 1;
+	netif_stop_queue(pAC->dev);
 
 	/* 
 	 * adjust number of rx buffers allocated
@@ -2469,7 +2491,7 @@
 	}
 #endif
 
-	pAC->dev->tbusy = 0;
+	netif_start_queue(pAC->dev);
 	for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
 		spin_unlock_irqrestore(
 			&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- v2.3.42/linux/drivers/net/sk_g16.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/sk_g16.c	Thu Feb 10 12:26:47 2000
@@ -69,6 +69,7 @@
 #include <asm/bitops.h> 
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/spinlock.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -455,6 +456,8 @@
 
 static SK_RAM *board;  /* pointer to our memory mapped board components */
 
+static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED;
+
 /* Macros */
 
 
@@ -939,11 +942,7 @@
 
     if (!(i = SK_lance_init(dev, 0)))  /* LANCE init OK? */
     {
-
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
 #ifdef SK_DEBUG
 
@@ -979,7 +978,6 @@
 	PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n", 
                SK_NAME, SK_read_reg(CSR0)));
 
-	dev->start = 0;        /* Device not ready */
 	return -EAGAIN;
     }
 
@@ -1176,7 +1174,7 @@
     struct priv *p = (struct priv *) dev->priv;
     struct tmd *tmdp;
 
-    if (dev->tbusy)
+    if (test_bit(LINK_STATE_XOFF, &dev->flags))
     {
 	/* if Transmitter more than 150ms busy -> time_out */
 
@@ -1190,7 +1188,7 @@
 
 	SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */
 
-	dev->tbusy = 0;                  /* Clear Transmitter flag */
+	netif_start_queue(dev);		 /* Clear Transmitter flag */
 
 	dev->trans_start = jiffies;      /* Mark Start of transmission */
 
@@ -1205,12 +1203,10 @@
      * This means check if we are already in. 
      */
 
-    if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) /* dev->tbusy already set ? */ 
-    {
-	printk("%s: Transmitter access conflict.\n", dev->name);
-    }
-    else
+    netif_stop_queue (dev);
+
     {
+
 	/* Evaluate Packet length */
 	short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; 
        
@@ -1248,11 +1244,13 @@
 	    * We own next buffer and are ready to transmit, so
 	    * clear busy flag
 	    */
-	   dev->tbusy = 0;
+	   netif_start_queue(dev);
 	}
 
 	p->stats.tx_bytes += skb->len;
+
     }
+
     dev_kfree_skb(skb);
     return 0;  
 } /* End of SK_send_packet */
@@ -1290,16 +1288,10 @@
 	printk("SK_interrupt(): IRQ %d for unknown device.\n", irq);
     }
     
-
-    if (dev->interrupt)
-    {
-	printk("%s: Re-entering the interrupt handler.\n", dev->name);
-    }
+    spin_lock (&SK_lock);
 
     csr0 = SK_read_reg(CSR0);      /* store register for checking */
 
-    dev->interrupt = 1;            /* We are handling an interrupt */
-
     /* 
      * Acknowledge all of the current interrupt sources, disable      
      * Interrupts (INEA = 0) 
@@ -1329,7 +1321,7 @@
 
     SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */
 
-    dev->interrupt = 0;            /* We are out */
+    spin_unlock (&SK_lock);
 } /* End of SK_interrupt() */ 
 
 
@@ -1430,14 +1422,7 @@
      * We mark transmitter not busy anymore, because now we have a free
      * transmit descriptor which can be filled by SK_send_packet and
      * afterwards sent by the LANCE
-     */
-
-    dev->tbusy = 0; 
-
-    /* 
-     * mark_bh(NET_BH);
-     * This will cause net_bh() to run after this interrupt handler.
-     *
+     * 
      * The function which do handle slow IRQ parts is do_bottom_half()
      * which runs at normal kernel priority, that means all interrupt are
      * enabled. (see kernel/irq.c)
@@ -1450,7 +1435,7 @@
      *  - try to transmit something from the send queue
      */
 
-    mark_bh(NET_BH); 
+    netif_wake_queue(dev);
 
 } /* End of SK_txintr() */
 
@@ -1625,8 +1610,7 @@
     PRINTK(("## %s: SK_close(). CSR0: %#06x\n", 
            SK_NAME, SK_read_reg(CSR0)));
 
-    dev->tbusy = 1;                /* Transmitter busy */
-    dev->start = 0;                /* Card down */
+    netif_stop_queue(dev);	   /* Transmitter busy */
 
     printk("%s: Shutting %s down CSR0 %#06x\n", dev->name, SK_NAME, 
            (int) SK_read_reg(CSR0));
@@ -2005,9 +1989,6 @@
 	printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", 
                dev->name, dev->base_addr, dev->irq);
 	       
-	printk("##   FLAGS: start: %d tbusy: %ld int: %ld\n", 
-               dev->start, dev->tbusy, dev->interrupt);
-
 	printk("## next device: %#08x init function: %#08x\n", 
               (int) dev->next, (int) dev->init);
     }
diff -u --recursive --new-file v2.3.42/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c
--- v2.3.42/linux/drivers/net/skeleton.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/skeleton.c	Wed Feb  9 20:08:09 2000
@@ -53,6 +53,7 @@
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
+#include <linux/spinlock.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/errno.h>
@@ -83,10 +84,19 @@
 /* The number of low I/O ports used by the ethercard. */
 #define NETCARD_IO_EXTENT	32
 
+#define MY_TX_TIMEOUT  ((400*HZ)/1000)
+
 /* Information that need to be kept for each board. */
 struct net_local {
 	struct net_device_stats stats;
 	long open_time;			/* Useless example local info. */
+
+	/* Tx control lock.  This protects the transmit buffer ring
+	 * state along with the "tx full" state of the driver.  This
+	 * means all netif_queue flow control actions are protected
+	 * by this lock as well.
+	 */
+	spinlock_t lock;
 };
 
 /* The station (ethernet) address prefix, used for IDing the board. */
@@ -106,6 +116,8 @@
 static int	net_close(struct net_device *dev);
 static struct	net_device_stats *net_get_stats(struct net_device *dev);
 static void	set_multicast_list(struct net_device *dev);
+static void     net_tx_timeout(struct net_device *dev);
+
 
 /* Example routines you must write ;->. */
 #define tx_done(dev) 1
@@ -157,6 +169,7 @@
  */
 static int __init netcard_probe1(struct net_device *dev, int ioaddr)
 {
+	struct net_local *np;
 	static unsigned version_printed = 0;
 	int i;
 
@@ -282,6 +295,9 @@
 
 	memset(dev->priv, 0, sizeof(struct net_local));
 
+	np = (struct net_local *)dev->priv;
+	spin_lock_init(&np->lock);
+
 	/* Grab the region so that no one else tries to probe our ioports. */
 	request_region(ioaddr, NETCARD_IO_EXTENT, cardname);
 
@@ -291,12 +307,41 @@
 	dev->get_stats		= net_get_stats;
 	dev->set_multicast_list = &set_multicast_list;
 
+        dev->tx_timeout		= &net_tx_timeout;
+        dev->watchdog_timeo	= MY_TX_TIMEOUT; 
+
 	/* Fill in the fields of the device structure with ethernet values. */
 	ether_setup(dev);
 
 	return 0;
 }
 
+static void net_tx_timeout(struct net_device *dev)
+{
+	struct net_local *np = (struct net_local *)dev->priv;
+
+	printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+	       tx_done(dev) ? "IRQ conflict" : "network cable problem");
+
+	/* Try to restart the adaptor. */
+	chipset_init(dev, 1);
+
+	np->stats.tx_errors++;
+
+	/* If we have space available to accept new transmit
+	 * requests, wake up the queueing layer.  This would
+	 * be the case if the chipset_init() call above just
+	 * flushes out the tx queue and empties it.
+	 *
+	 * If instead, the tx queue is retained then the
+	 * netif_wake_queue() call should be placed in the
+	 * TX completion interrupt handler of the driver instead
+	 * of here.
+	 */
+	if (!tx_full(dev))
+		netif_wake_queue(dev);
+}
+
 /*
  * Open/initialize the board. This is called (in the current kernel)
  * sometime after booting when the 'ifconfig' program is run.
@@ -308,7 +353,7 @@
 static int
 net_open(struct net_device *dev)
 {
-	struct net_local *lp = (struct net_local *)dev->priv;
+	struct net_local *np = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
 	/*
 	 * This is used if the interrupt line can turned off (shared).
@@ -327,100 +372,155 @@
 	}
 
 	/* Reset the hardware here. Don't forget to set the station address. */
-	/*chipset_init(dev, 1);*/
+	chipset_init(dev, 1);
 	outb(0x00, ioaddr);
-	lp->open_time = jiffies;
+	np->open_time = jiffies;
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	/* We are now ready to accept transmit requeusts from
+	 * the queueing layer of the networking.
+	 */
+	netif_start_queue(dev);
 
 	MOD_INC_USE_COUNT;
 
 	return 0;
 }
 
+/* This will only be invoked if your driver is _not_ in XOFF state.
+ * What this means is that you need not check it, and that this
+ * invariant will hold if you make sure that the netif_*_queue()
+ * calls are done at the proper times.
+ */
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_local *lp = (struct net_local *)dev->priv;
+	struct net_local *np = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
+	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	unsigned char *buf = skb->data;
 
-	if (dev->tbusy) {
-		/*
-		 * If we get here, some higher level has decided we are broken.
-		 * There should really be a "kick me" function call instead.
-		 */
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 5)
-			return 1;
-		printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
-			   tx_done(dev) ? "IRQ conflict" : "network cable problem");
-		/* Try to restart the adaptor. */
-		chipset_init(dev, 1);
-		dev->tbusy=0;
-		dev->trans_start = jiffies;
-	}
+	/* If some error occurs while trying to transmit this
+	 * packet, you should return '1' from this function.
+	 * In such a case you _may not_ do anything to the
+	 * SKB, it is still owned by the network queueing
+	 * layer when an error is returned.  This means you
+	 * may not modify any SKB fields, you may not free
+	 * the SKB, etc.
+	 */
 
-	/*
-	 * Block a timer-based transmit from overlapping. This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+#if TX_RING
+	/* This is the most common case for modern hardware.
+	 * The spinlock protects this code from the TX complete
+	 * hardware interrupt handler.  Queue flow control is
+	 * thus managed under this lock as well.
 	 */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
-		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
-	else {
-		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-		unsigned char *buf = skb->data;
-		lp->stats.tx_bytes+=skb->len;
-		hardware_send_packet(ioaddr, buf, length);
-		dev->trans_start = jiffies;
-	}
-	dev_kfree_skb (skb);
+	spin_lock_irq(&np->lock);
+
+	add_to_tx_ring(np, skb, length);
+	dev->trans_start = jiffied;
+
+	/* If we just used up the very last entry in the
+	 * TX ring on this device, tell the queueing
+	 * layer to send no more.
+	 */
+	if (tx_full(dev))
+		netif_stop_queue(dev);
+
+	/* When the TX completion hw interrupt arrives, this
+	 * is when the transmit statistics are updated.
+	 */
+
+	spin_unlock_irq(&np->lock);
+#else
+	/* This is the case for older hardware which takes
+	 * a single transmit buffer at a time, and it is
+	 * just written to the device via PIO.
+	 *
+	 * No spin locking is needed since there is no TX complete
+	 * event.  If by chance your card does have a TX complete
+	 * hardware IRQ then you may need to utilize np->lock here.
+	 */
+	hardware_send_packet(ioaddr, buf, length);
+	np->stats.tx_bytes += skb->len;
+
+	dev->trans_start = jiffies;
 
 	/* You might need to clean up and record Tx statistics here. */
 	if (inw(ioaddr) == /*RU*/81)
-		lp->stats.tx_aborted_errors++;
+		np->stats.tx_aborted_errors++;
+	dev_kfree_skb (skb);
+#endif
 
 	return 0;
 }
 
+#if TX_RING
+/* This handles TX complete events posted by the device
+ * via interrupts.
+ */
+void net_tx(struct net_device *dev)
+{
+	struct net_local *np = (struct net_local *)dev->priv;
+	int entry;
+
+	/* This protects us from concurrent execution of
+	 * our dev->hard_start_xmit function above.
+	 */
+	spin_lock(&np->lock);
+
+	entry = np->tx_old;
+	while (tx_entry_is_sent(np, entry)) {
+		struct sk_buff *skb = np->skbs[entry];
+
+		np->stats.tx_bytes += skb->len;
+		dev_kfree_skb_irq (skb);
+
+		entry = next_tx_entry(np, entry);
+	}
+	np->tx_old = entry;
+
+	/* If we had stopped the queue due to a "tx full"
+	 * condition, and space has now been made available,
+	 * wake up the queue.
+	 */
+	if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+	    ! tx_full(dev))
+		netif_wake_queue(dev);
+
+	spin_unlock(&np->lock);
+}
+#endif
+
 /*
  * The typical workload of the driver:
- *   Handle the network interface interrupts.
+ * Handle the network interface interrupts.
  */
 static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct net_device *dev = dev_id;
-	struct net_local *lp;
-	int ioaddr, status, boguscount = 0;
-
-	if (dev == NULL) {
-		printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
-		return;
-	}
-	dev->interrupt = 1;
+	struct net_local *np;
+	int ioaddr, status;
 
 	ioaddr = dev->base_addr;
-	lp = (struct net_local *)dev->priv;
-	status = inw(ioaddr + 0);
 
-	do {
-		if (status /*& RX_INTR*/) {
-			/* Got a packet(s). */
-			net_rx(dev);
-		}
-		if (status /*& TX_INTR*/) {
-			lp->stats.tx_packets++;
-			dev->tbusy = 0;
-			mark_bh(NET_BH);	/* Inform upper layers. */
-		}
-		if (status /*& COUNTERS_INTR*/) {
-			/* Increment the appropriate 'localstats' field. */
-			lp->stats.tx_window_errors++;
-		}
-	} while (++boguscount < 20) ;
+	np = (struct net_local *)dev->priv;
+	status = inw(ioaddr + 0);
 
-	dev->interrupt = 0;
-	return;
+	if (status & RX_INTR) {
+		/* Got a packet(s). */
+		net_rx(dev);
+	}
+#if TX_RING
+	if (status & TX_INTR) {
+		/* Transmit complete. */
+		net_tx(dev);
+		np->stats.tx_packets++;
+		netif_wake_queue(dev);
+	}
+#endif
+	if (status & COUNTERS_INTR) {
+		/* Increment the appropriate 'localstats' field. */
+		np->stats.tx_window_errors++;
+	}
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
@@ -470,11 +570,6 @@
 		}
 	} while (--boguscount);
 
-	/*
-	 * If any worth-while packets have been received, dev_rint()
-	 * has done a mark_bh(NET_BH) for us and will work on them
-	 * when we get to the bottom-half routine.
-	 */
 	return;
 }
 
@@ -487,8 +582,7 @@
 
 	lp->open_time = 0;
 
-	dev->tbusy = 1;
-	dev->start = 0;
+	netif_stop_queue(dev);
 
 	/* Flush the Tx and disable Rx here. */
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v2.3.42/linux/drivers/net/slip.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/net/slip.c	Wed Feb  9 20:08:09 2000
@@ -169,9 +169,9 @@
 	if (slcomp == NULL)
 		goto err_exit;
 #endif
-	start_bh_atomic();
+	spin_lock_bh(&sl->lock);
 	if (sl->tty == NULL) {
-		end_bh_atomic();
+		spin_unlock_bh(&sl->lock);
 		err = -ENODEV;
 		goto err_exit;
 	}
@@ -189,7 +189,7 @@
 	sl->xbits    = 0;
 #endif
 #endif
-	end_bh_atomic();
+	spin_unlock_bh(&sl->lock);
 	err = 0;
 
 	/* Cleanup */
@@ -268,7 +268,7 @@
 		goto done;
 	}
 
-	start_bh_atomic();
+	spin_lock_bh(&sl->lock);
 
 	err = -ENODEV;
 	if (sl->tty == NULL)
@@ -304,7 +304,7 @@
 	err = 0;
 
 done_on_bh:
-	end_bh_atomic();
+	spin_unlock_bh(&sl->lock);
 
 done:
 	if (xbuff)
@@ -323,9 +323,7 @@
 static inline void
 sl_lock(struct slip *sl)
 {
-	if (test_and_set_bit(0, (void *) &sl->dev->tbusy))  {
-		printk("%s: trying to lock already locked device!\n", sl->dev->name);
-        }
+	netif_stop_queue(sl->dev);
 }
 
 
@@ -333,9 +331,7 @@
 static inline void
 sl_unlock(struct slip *sl)
 {
-	if (!test_and_clear_bit(0, (void *)&sl->dev->tbusy))  {
-		printk("%s: trying to unlock already unlocked device!\n", sl->dev->name);
-        }
+	netif_wake_queue(sl->dev);
 }
 
 /* Send one completely decapsulated IP datagram to the IP layer. */
@@ -453,7 +449,7 @@
 	struct slip *sl = (struct slip *) tty->disc_data;
 
 	/* First make sure we're connected. */
-	if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start) {
+	if (!sl || sl->magic != SLIP_MAGIC || !test_bit(LINK_STATE_START, &sl->dev->state)) {
 		return;
 	}
 	if (sl->xleft <= 0)  {
@@ -462,7 +458,6 @@
 		sl->tx_packets++;
 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 		sl_unlock(sl);
-		mark_bh(NET_BH);
 		return;
 	}
 
@@ -471,40 +466,25 @@
 	sl->xhead += actual;
 }
 
-/* Encapsulate an IP datagram and kick it into a TTY queue. */
-static int
-sl_xmit(struct sk_buff *skb, struct net_device *dev)
+static void sl_tx_timeout(struct net_device *dev)
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
-	if (!dev->start)  {
-		printk("%s: xmit call when iface is down\n", dev->name);
-		dev_kfree_skb(skb);
-		return 0;
-	}
-	if (sl->tty == NULL) {
-		dev_kfree_skb(skb);
-		return 0;
-	}
+	spin_lock(&sl->lock);
+
+	if (test_bit(LINK_STATE_XOFF, &dev->state)) {
+		struct slip *sl = (struct slip*)(dev->priv);
+
+		if (!test_bit(LINK_STATE_START, &dev->state))
+			goto out;
 
-	/*
-	 * If we are busy already- too bad.  We ought to be able
-	 * to queue things at this point, to allow for a little
-	 * frame buffer.  Oh well...
-	 * -----------------------------------------------------
-	 * I hate queues in SLIP driver. May be it's efficient,
-	 * but for me latency is more important. ;)
-	 * So, no queues !
-	 *        14 Oct 1994  Dmitry Gorodchanin.
-	 */
-	if (dev->tbusy) {
 		/* May be we must check transmitter timeout here ?
 		 *      14 Oct 1994 Dmitry Gorodchanin.
 		 */
 #ifdef SL_CHECK_TRANSMIT
 		if (jiffies - dev->trans_start  < 20 * HZ)  {
 			/* 20 sec timeout not reached */
-			return 1;
+			goto out;
 		}
 		printk("%s: transmit timed out, %s?\n", dev->name,
 		       (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
@@ -512,19 +492,39 @@
 		sl->xleft = 0;
 		sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 		sl_unlock(sl);
-#else
-		return 1;
 #endif
 	}
 
-	/* We were not busy, so we are now... :-) */
-	if (skb != NULL) 
-	{
-		sl_lock(sl);
-		sl->tx_bytes+=skb->len;
-		sl_encaps(sl, skb->data, skb->len);
+out:
+	spin_unlock(&sl->lock);
+}
+
+
+/* Encapsulate an IP datagram and kick it into a TTY queue. */
+static int
+sl_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct slip *sl = (struct slip*)(dev->priv);
+
+	spin_lock(&sl->lock);
+	if (!test_bit(LINK_STATE_START, &dev->state))  {
+		spin_unlock(&sl->lock);
+		printk("%s: xmit call when iface is down\n", dev->name);
 		dev_kfree_skb(skb);
+		return 0;
 	}
+	if (sl->tty == NULL) {
+		spin_unlock(&sl->lock);
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	sl_lock(sl);
+	sl->tx_bytes+=skb->len;
+	sl_encaps(sl, skb->data, skb->len);
+	spin_unlock(&sl->lock);
+
+	dev_kfree_skb(skb);
 	return 0;
 }
 
@@ -540,16 +540,15 @@
 {
 	struct slip *sl = (struct slip*)(dev->priv);
 
-	start_bh_atomic();
+	spin_lock_bh(&sl->lock);
 	if (sl->tty) {
 		/* TTY discipline is running. */
 		sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 	}
-	dev->tbusy = 1;
-	dev->start = 0;
+	netif_stop_queue(dev);
 	sl->rcount   = 0;
 	sl->xleft    = 0;
-	end_bh_atomic();
+	spin_unlock_bh(&sl->lock);
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -565,8 +564,7 @@
 		return -ENODEV;
 
 	sl->flags &= (1 << SLF_INUSE);
-	dev->start = 1;
-	dev->tbusy = 0;
+	netif_start_queue(dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
@@ -634,6 +632,10 @@
 
 	dev->mtu		= sl->mtu;
 	dev->hard_start_xmit	= sl_xmit;
+#ifdef SL_CHECK_TRANSMIT
+	dev->tx_timeout		= sl_tx_timeout;
+	dev->watchdog_timeo	= 20*HZ;
+#endif
 	dev->open		= sl_open;
 	dev->stop		= sl_close;
 	dev->get_stats	        = sl_get_stats;
@@ -676,7 +678,8 @@
 {
 	struct slip *sl = (struct slip *) tty->disc_data;
 
-	if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start)
+	if (!sl || sl->magic != SLIP_MAGIC ||
+	    !test_bit(LINK_STATE_START, &sl->dev->state))
 		return;
 
 	/* Read the characters out of the buffer */
@@ -800,6 +803,7 @@
 	/* Initialize channel control data */
 	sl->magic       = SLIP_MAGIC;
 	sl->dev	      	= &slp->dev;
+	spin_lock_init(&sl->lock);
 	sl->mode        = SL_MODE_DEFAULT;
 	sprintf(slp->if_name, "sl%d", i);
 	slp->dev.name         = slp->if_name;
@@ -946,10 +950,8 @@
 
 	/* VSV = very important to remove timers */
 #ifdef CONFIG_SLIP_SMART
-	if (sl->keepalive)
-		del_timer (&sl->keepalive_timer);
-	if (sl->outfill)
-		del_timer (&sl->outfill_timer);
+	del_timer_sync(&sl->keepalive_timer);
+	del_timer_sync(&sl->outfill_timer);
 #endif
 
 	/* Count references from TTY module */
@@ -1182,20 +1184,18 @@
                 if (tmp > 255) /* max for unchar */
 			return -EINVAL;
 
-		start_bh_atomic();
+		spin_lock_bh(&sl->lock);
 		if (!sl->tty) {
-			end_bh_atomic();
+			spin_unlock_bh(&sl->lock);
 			return -ENODEV;
 		}
-                if (sl->keepalive)
-                        (void)del_timer (&sl->keepalive_timer);
 		if ((sl->keepalive = (unchar) tmp) != 0) {
-			sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
-			add_timer(&sl->keepalive_timer);
+			mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
 			set_bit(SLF_KEEPTEST, &sl->flags);
-                }
-	        end_bh_atomic();
-	
+                } else {
+                        del_timer (&sl->keepalive_timer);
+		}
+		spin_unlock_bh(&sl->lock);
 		return 0;
 
         case SIOCGKEEPALIVE:
@@ -1208,19 +1208,18 @@
 			return -EFAULT;
                 if (tmp > 255) /* max for unchar */
 			return -EINVAL;
-		start_bh_atomic();
+		spin_lock_bh(&sl->lock);
 		if (!sl->tty) {
-			end_bh_atomic();
+			spin_unlock_bh(&sl->lock);
 			return -ENODEV;
 		}
-                if (sl->outfill)
-                         (void)del_timer (&sl->outfill_timer);
                 if ((sl->outfill = (unchar) tmp) != 0){
-			sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
-			add_timer(&sl->outfill_timer);
+			mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
 			set_bit(SLF_OUTWAIT, &sl->flags);
+		} else {
+                        del_timer (&sl->outfill_timer);
 		}
-		end_bh_atomic();
+		spin_unlock_bh(&sl->lock);
                 return 0;
 
         case SIOCGOUTFILL:
@@ -1253,10 +1252,10 @@
 	if (sl == NULL)		/* Allocation failed ?? */
 		return -ENODEV;
 
-	start_bh_atomic(); /* Hangup would kill us */
+	spin_lock_bh(&sl->lock);
 
 	if (!sl->tty) {
-		end_bh_atomic();
+		spin_unlock_bh(&sl->lock);
 		return -ENODEV;
 	}
 
@@ -1265,14 +1264,15 @@
 		/* max for unchar */
                 if (((unsigned int)((unsigned long)rq->ifr_data)) > 255)
 			return -EINVAL;
-                if (sl->keepalive)
-                        (void)del_timer (&sl->keepalive_timer);
 		sl->keepalive = (unchar) ((unsigned long)rq->ifr_data);
 		if (sl->keepalive != 0) {
 			sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
-			add_timer(&sl->keepalive_timer);
+			mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
 			set_bit(SLF_KEEPTEST, &sl->flags);
-                }
+                } else {
+                        del_timer(&sl->keepalive_timer);
+		}
+		spin_unlock_bh(&sl->lock);
 		break;
 
         case SIOCGKEEPALIVE:
@@ -1282,12 +1282,11 @@
         case SIOCSOUTFILL:
                 if (((unsigned)((unsigned long)rq->ifr_data)) > 255) /* max for unchar */
 			return -EINVAL;
-                if (sl->outfill)
-			del_timer (&sl->outfill_timer);
                 if ((sl->outfill = (unchar)((unsigned long) rq->ifr_data)) != 0){
-			sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
-			add_timer(&sl->outfill_timer);
+			mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
 			set_bit(SLF_OUTWAIT, &sl->flags);
+		} else {
+                        del_timer (&sl->outfill_timer);
 		}
                 break;
 
@@ -1300,7 +1299,7 @@
 		   and opened by another process device.
 		 */
 		if (sl->tty != current->tty && sl->pid != current->pid) {
-			end_bh_atomic();
+			spin_unlock_bh(&sl->lock);
 			return -EPERM;
 		}
 		sl->leased = 0;
@@ -1311,7 +1310,7 @@
         case SIOCGLEASE:
 		rq->ifr_data=(caddr_t)((unsigned long)sl->leased);
 	};
-	end_bh_atomic();
+	spin_unlock_bh(&sl->lock);
 	return 0;
 }
 #endif
@@ -1399,15 +1398,19 @@
 			}
 
 			busy = 0;
-			start_bh_atomic();
+			local_bh_disable();
 			for (i = 0; i < slip_maxdev; i++) {
 				struct slip_ctrl *slc = slip_ctrls[i];
-				if (slc && slc->ctrl.tty) {
+				if (!slc)
+					continue;
+				spin_lock(&slc->ctrl.lock);
+				if (slc->ctrl.tty) {
 					busy++;
 					tty_hangup(slc->ctrl.tty);
 				}
+				spin_unlock(&slc->ctrl.lock);
 			}
-			end_bh_atomic();
+			local_bh_enable();
 		} while (busy && jiffies - start < 1*HZ);
 
 		busy = 0;
@@ -1449,8 +1452,10 @@
 {
 	struct slip *sl=(struct slip *)sls;
 
-	if (sl==NULL || sl->tty == NULL)
-		return;
+	spin_lock(&sl->lock);
+
+	if (sl->tty == NULL)
+		goto out;
 
 	if(sl->outfill)
 	{
@@ -1463,7 +1468,7 @@
 			unsigned char s = END;
 #endif
 			/* put END into tty queue. Is it right ??? */
-			if (!test_bit(0, (void *) &sl->dev->tbusy))
+			if (!test_bit(LINK_STATE_XOFF, &sl->dev->state))
 			{
 				/* if device busy no outfill */
 				sl->tty->driver.write(sl->tty, 0, &s, 1);
@@ -1471,18 +1476,22 @@
 		}
 		else
 			set_bit(SLF_OUTWAIT, &sl->flags);
-		(void)del_timer(&sl->outfill_timer);
-		sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
-		add_timer(&sl->outfill_timer);
+
+		mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
 	}
+out:
+	spin_unlock(&sl->lock);
+	timer_exit(&sl->outfill_timer);
 }
 
 static void sl_keepalive(unsigned long sls)
 {
 	struct slip *sl=(struct slip *)sls;
 
-	if (sl == NULL || sl->tty == NULL)
-		return;
+	spin_lock(&sl->lock);
+
+	if (sl->tty == NULL)
+		goto out;
 
 	if( sl->keepalive)
 	{
@@ -1494,13 +1503,17 @@
 			printk("%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
 			tty_hangup(sl->tty); /* this must hangup tty & close slip */
 			/* I think we need not something else */
-			return;
+			goto out;
 		}
 		else
 			set_bit(SLF_KEEPTEST, &sl->flags);
-		sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
-		add_timer(&sl->keepalive_timer);
+
+		mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
 	}
+
+out:
+	spin_unlock(&sl->lock);
+	timer_exit(&sl->keepalive_timer);
 }
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/drivers/net/slip.h linux/drivers/net/slip.h
--- v2.3.42/linux/drivers/net/slip.h	Wed Aug 18 11:36:45 1999
+++ linux/drivers/net/slip.h	Wed Feb  9 20:08:09 2000
@@ -52,7 +52,9 @@
 
   /* Various fields. */
   struct tty_struct	*tty;		/* ptr to TTY structure		*/
-  struct net_device		*dev;		/* easy for intr handling	*/
+  struct net_device	*dev;		/* easy for intr handling	*/
+  spinlock_t		lock;
+
 #ifdef SL_INCLUDE_CSLIP
   struct slcompress	*slcomp;	/* for header compression 	*/
   unsigned char		*cbuff;		/* compression buffer		*/
diff -u --recursive --new-file v2.3.42/linux/drivers/net/starfire.c linux/drivers/net/starfire.c
--- v2.3.42/linux/drivers/net/starfire.c	Thu Nov 18 20:25:37 1999
+++ linux/drivers/net/starfire.c	Thu Feb 10 12:26:47 2000
@@ -68,19 +68,8 @@
 #error You must compile this driver with "-O".
 #endif
 
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
@@ -92,6 +81,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -101,7 +91,6 @@
 
 #define RUN_AT(x) (jiffies + (x))
 
-#ifdef MODULE
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
@@ -111,7 +100,6 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
 
 /*
 				Theory of Operation
@@ -212,11 +200,12 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(struct pci_dev *pdev, int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct net_device *starfire_probe1(int pci_bus, int pci_devfn, long ioaddr,
-									  int irq, int chp_idx, int fnd_cnt);
+static struct net_device *starfire_probe1(struct pci_dev *pdev, int pci_bus,
+										  int pci_devfn, long ioaddr,
+										  int irq, int chp_idx, int fnd_cnt);
 
 #if 0
 #define ADDR_64BITS 1			/* This chip uses 64 bit addresses. */
@@ -322,25 +311,35 @@
 #endif
 };
 
+struct ring_info {
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+};
+
 struct netdev_private {
 	/* Descriptor rings first for alignment. */
 	struct starfire_rx_desc *rx_ring;
 	struct starfire_tx_desc *tx_ring;
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
 	struct net_device *next_module;			/* Link for devices of this type. */
 	const char *product_name;
 	/* The addresses of rx/tx-in-place skbuffs. */
-	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	struct ring_info rx_info[RX_RING_SIZE];
+	struct ring_info tx_info[TX_RING_SIZE];
 	/* Pointers to completion queues (full pages).  I should cache line pad..*/
 	u8 pad0[100];
 	struct rx_done_desc *rx_done_q;
+	dma_addr_t rx_done_q_dma;
 	unsigned int rx_done;
 	struct tx_done_report *tx_done_q;
 	unsigned int tx_done;
+	dma_addr_t tx_done_q_dma;
 	struct net_device_stats stats;
 	struct timer_list timer;	/* Media monitoring timer. */
 	/* Frequently used values: keep some adjacent for cache effect. */
 	int chip_id;
+	struct pci_dev *pdev;
 	unsigned char pci_bus, pci_devfn;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int cur_tx, dirty_tx;
@@ -396,10 +395,8 @@
 	unsigned char pci_bus, pci_device_fn;
 	struct net_device *dev;
 
-	if ( ! pcibios_present())
-		return -ENODEV;
-
 	for (;pci_index < 0xff; pci_index++) {
+		struct pci_dev *pdev;
 		u16 vendor, device, pci_command, new_command;
 		int chip_idx, irq;
 		long pciaddr;
@@ -409,28 +406,24 @@
 								&pci_bus, &pci_device_fn)
 			!= PCIBIOS_SUCCESSFUL)
 			break;
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
+		pdev = pci_find_slot (pci_bus, pci_device_fn);
+		if (!pdev) continue;
+		vendor = pdev->vendor;
+		device = pdev->device;
 
 		for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
 			if (vendor == pci_tbl[chip_idx].vendor_id
 				&& (device & pci_tbl[chip_idx].device_id_mask) ==
 				pci_tbl[chip_idx].device_id)
 				break;
-		if (pci_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
+		if (pci_tbl[chip_idx].vendor_id == 0)	/* Compiled out! */
 			continue;
 
-		{
-			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-
-			pciaddr = pdev->resource[0].start;
+		pciaddr = pdev->resource[0].start;
 #if defined(ADDR_64BITS) && defined(__alpha__)
-			pciaddr |= ((long)pdev->base_address[1]) << 32;
+		pciaddr |= ((long)pdev->base_address[1]) << 32;
 #endif
-			irq = pdev->irq;
-		}
+		irq = pdev->irq;
 
 		if (debug > 2)
 			printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n",
@@ -446,30 +439,26 @@
 			continue;
 		}
 
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_COMMAND, &pci_command);
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 		new_command = pci_command | (pci_tbl[chip_idx].flags & 7);
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled the"
 				   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
 				   pci_bus, pci_device_fn, pci_command, new_command);
-			pcibios_write_config_word(pci_bus, pci_device_fn,
-									  PCI_COMMAND, new_command);
+			pci_write_config_word(pdev, PCI_COMMAND, new_command);
 		}
 
-		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr,
+		dev = pci_tbl[chip_idx].probe1(pdev, pci_bus, pci_device_fn, ioaddr,
 									   irq, chip_idx, cards_found);
 
 		if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
 			u8 pci_latency;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_LATENCY_TIMER, &pci_latency);
+			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 			if (pci_latency < min_pci_latency) {
 				printk(KERN_INFO "  PCI latency timer (CFLT) is "
 					   "unreasonably low at %d.  Setting to %d clocks.\n",
 					   pci_latency, min_pci_latency);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										  PCI_LATENCY_TIMER, min_pci_latency);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency);
 			}
 		}
 		cards_found++;
@@ -478,21 +467,15 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-int starfire_probe(void)
-{
-	if (pci_etherdev_probe(pci_tbl) < 0)
-		return -ENODEV;
-	printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
-	return 0;
-}
-
-
 static struct net_device *
-starfire_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_id, int card_idx)
+starfire_probe1(struct pci_dev *pdev, int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_id, int card_idx)
 {
 	struct netdev_private *np;
 	int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
-	struct net_device *dev = init_etherdev(NULL, sizeof(struct netdev_private));
+	struct net_device *dev = init_etherdev(NULL, 0);
+
+	if (!dev)
+		return NULL;
 
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
@@ -525,6 +508,7 @@
 	np->next_module = root_net_dev;
 	root_net_dev = dev;
 
+	np->pdev = pdev;
 	np->pci_bus = pci_bus;
 	np->pci_devfn = pci_devfn;
 	np->chip_id = chip_id;
@@ -549,6 +533,8 @@
 	/* The chip-specific entries in the device structure. */
 	dev->open = &netdev_open;
 	dev->hard_start_xmit = &start_tx;
+	dev->tx_timeout = tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->stop = &netdev_close;
 	dev->get_stats = &get_stats;
 	dev->set_multicast_list = &set_rx_mode;
@@ -617,16 +603,29 @@
 			   dev->name, dev->irq);
 	/* Allocate the various queues, failing gracefully. */
 	if (np->tx_done_q == 0)
-		np->tx_done_q = (struct tx_done_report *)get_free_page(GFP_KERNEL);
+		np->tx_done_q = pci_alloc_consistent(np->pdev, PAGE_SIZE, &np->tx_done_q_dma);
 	if (np->rx_done_q == 0)
-		np->rx_done_q = (struct rx_done_desc *)get_free_page(GFP_KERNEL);
+		np->rx_done_q = pci_alloc_consistent(np->pdev, PAGE_SIZE, &np->rx_done_q_dma);
 	if (np->tx_ring == 0)
-		np->tx_ring = (struct starfire_tx_desc *)get_free_page(GFP_KERNEL);
+		np->tx_ring = pci_alloc_consistent(np->pdev, PAGE_SIZE, &np->tx_ring_dma);
 	if (np->rx_ring == 0)
-		np->rx_ring = (struct starfire_rx_desc *)get_free_page(GFP_KERNEL);
+		np->rx_ring = pci_alloc_consistent(np->pdev, PAGE_SIZE, &np->rx_ring_dma);
 	if (np->tx_done_q == 0  ||  np->rx_done_q == 0
-		|| np->rx_ring == 0 ||  np->tx_ring == 0)
+		|| np->rx_ring == 0 ||  np->tx_ring == 0) {
+		if (np->tx_done_q)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->tx_done_q, np->tx_done_q_dma);
+		if (np->rx_done_q)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->rx_done_q, np->rx_done_q_dma);
+		if (np->tx_ring)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->tx_ring, np->tx_ring_dma);
+		if (np->rx_ring)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->rx_ring, np->rx_ring_dma);
 		return -ENOMEM;
+	}
 
 	MOD_INC_USE_COUNT;
 
@@ -638,18 +637,19 @@
 	writel(0x02000401, ioaddr + TxDescCtrl);
 
 #if defined(ADDR_64BITS) && defined(__alpha__)
-	writel(virt_to_bus(np->rx_ring) >> 32, ioaddr + RxDescQHiAddr);
-	writel(virt_to_bus(np->tx_ring) >> 32, ioaddr + TxRingHiAddr);
+	/* XXX We really need a 64-bit PCI dma interfaces too... -DaveM */
+	writel(np->rx_ring_dma >> 32, ioaddr + RxDescQHiAddr);
+	writel(np->tx_ring_dma >> 32, ioaddr + TxRingHiAddr);
 #else
 	writel(0, ioaddr + RxDescQHiAddr);
 	writel(0, ioaddr + TxRingHiAddr);
 	writel(0, ioaddr + CompletionHiAddr);
 #endif
-	writel(virt_to_bus(np->rx_ring), ioaddr + RxDescQAddr);
-	writel(virt_to_bus(np->tx_ring), ioaddr + TxRingPtr);
+	writel(np->rx_ring_dma, ioaddr + RxDescQAddr);
+	writel(np->tx_ring_dma, ioaddr + TxRingPtr);
 
-	writel(virt_to_bus(np->tx_done_q), ioaddr + TxCompletionAddr);
-	writel(virt_to_bus(np->rx_done_q), ioaddr + RxCompletionAddr);
+	writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr);
+	writel(np->rx_done_q_dma, ioaddr + RxCompletionAddr);
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s:  Filling in the station address.\n", dev->name);
@@ -674,17 +674,12 @@
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-
 	if (debug > 1)
 		printk(KERN_DEBUG "%s:  Setting the Rx and Tx modes.\n", dev->name);
 	set_rx_mode(dev);
 
 	check_duplex(dev, 1);
 
-	dev->start = 1;
-
 	/* Set the interrupt mask and enable PCI interrupts. */
 	writel(IntrRxDone | IntrRxEmpty | IntrRxPCIErr |
 		   IntrTxDone | IntrTxEmpty | IntrTxPCIErr |
@@ -794,7 +789,7 @@
 
   /* Trigger an immediate transmit demand. */
 
-  dev->trans_start = jiffies;
+  netif_wake_queue(dev);
   np->stats.tx_errors++;
   return;
 }
@@ -815,12 +810,13 @@
 	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
-		np->rx_skbuff[i] = skb;
+		np->rx_info[i].skb = skb;
 		if (skb == NULL)
 			break;
+		np->rx_info[i].mapping = pci_map_single(np->pdev, skb->tail, np->rx_buf_sz);
 		skb->dev = dev;			/* Mark as being used by this device. */
 		/* Grrr, we cannot offset to correctly align the IP header. */
-		np->rx_ring[i].rxaddr = cpu_to_le32(virt_to_bus(skb->tail) | RxDescValid);
+		np->rx_ring[i].rxaddr = cpu_to_le32(np->rx_info[i].mapping | RxDescValid);
 	}
 	writew(i-1, dev->base_addr + RxDescQIdx);
 	np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -828,7 +824,8 @@
 	/* Clear the remainder of the Rx buffer ring. */
 	for (  ; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].rxaddr = 0;
-		np->rx_skbuff[i] = 0;
+		np->rx_info[i].skb = NULL;
+		np->rx_info[i].mapping = 0;
 	}
 	/* Mark the last entry as wrapping the ring. */
 	np->rx_ring[i-1].rxaddr |= cpu_to_le32(RxDescEndRing);
@@ -840,7 +837,8 @@
 	}
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		np->tx_skbuff[i] = 0;
+		np->tx_info[i].skb = NULL;
+		np->tx_info[i].mapping = 0;
 		np->tx_ring[i].status = 0;
 	}
 	return;
@@ -851,14 +849,7 @@
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	unsigned entry;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		tx_timeout(dev);
-		return 1;
-	}
+	netif_stop_queue(dev);
 
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
@@ -866,9 +857,11 @@
 	/* Calculate the next Tx descriptor entry. */
 	entry = np->cur_tx % TX_RING_SIZE;
 
-	np->tx_skbuff[entry] = skb;
+	np->tx_info[entry].skb = skb;
+	np->tx_info[entry].mapping =
+		pci_map_single(np->pdev, skb->data, skb->len);
 
-	np->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));
+	np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping);
 	/* Add  |TxDescIntr to generate Tx-done interrupts. */
 	np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID);
 	if (debug > 5) {
@@ -893,7 +886,7 @@
 	if (np->cur_tx - np->dirty_tx >= TX_RING_SIZE - 1)
 		np->tx_full = 1;
 	if (! np->tx_full)
-		clear_bit(0, (void*)&dev->tbusy);
+		netif_start_queue(dev);
 	dev->trans_start = jiffies;
 
 	if (debug > 4) {
@@ -921,21 +914,6 @@
 
 	ioaddr = dev->base_addr;
 	np = (struct netdev_private *)dev->priv;
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		dev->interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-#else
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
-	dev->interrupt = 1;
-#endif
 
 	do {
 		u32 intr_status = readl(ioaddr + IntrClear);
@@ -974,11 +952,19 @@
 				if ((tx_status & 0xe0000000) == 0xa0000000) {
 					np->stats.tx_packets++;
 				} else if ((tx_status & 0xe0000000) == 0x80000000) {
+					struct sk_buff *skb;
 					u16 entry = tx_status; 		/* Implicit truncate */
 					entry >>= 3;
+
+					skb = np->tx_info[entry].skb;
+					pci_unmap_single(np->pdev,
+									 np->tx_info[entry].mapping,
+									 skb->len);
+
 					/* Scavenge the descriptor. */
-					dev_kfree_skb(np->tx_skbuff[entry]);
-					np->tx_skbuff[entry] = 0;
+					kfree_skb(skb);
+					np->tx_info[entry].skb = NULL;
+					np->tx_info[entry].mapping = 0;
 					np->dirty_tx++;
 				}
 				np->tx_done_q[np->tx_done].status = 0;
@@ -987,10 +973,9 @@
 			writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2);
 		}
 		if (np->tx_full && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
-			/* The ring is no longer full, clear tbusy. */
+			/* The ring is no longer full, wake the queue. */
 			np->tx_full = 0;
-			clear_bit(0, (void*)&dev->tbusy);
-			mark_bh(NET_BH);
+			netif_wake_queue(dev);
 		}
 
 		/* Abnormal error summary/uncommon events handlers. */
@@ -1009,23 +994,6 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, readl(ioaddr + IntrStatus));
 
-#ifndef final_version
-	/* Code that should never be run!  Remove after testing.. */
-	{
-		static int stopit = 10;
-		if (dev->start == 0  &&  --stopit < 0) {
-			printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
-				   dev->name);
-			free_irq(irq, dev);
-		}
-	}
-#endif
-
-#if defined(__i386__)
-	clear_bit(0, (void*)&dev->interrupt);
-#else
-	dev->interrupt = 0;
-#endif
 	return;
 }
 
@@ -1074,23 +1042,24 @@
 				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
+				pci_dma_sync_single(np->pdev,
+									np->rx_info[entry].mapping,
+									pkt_len);
 #if HAS_IP_COPYSUM			/* Call copy + cksum if available. */
-				eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
+				eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
 #else
-				memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail,
+				memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail,
 					   pkt_len);
 #endif
 			} else {
-				char *temp = skb_put(skb = np->rx_skbuff[entry], pkt_len);
-				np->rx_skbuff[entry] = NULL;
-#ifndef final_version				/* Remove after testing. */
-				if (bus_to_virt(le32_to_cpu(np->rx_ring[entry].rxaddr) & ~3) != temp)
-					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
-						   "do not match in netdev_rx: %p vs. %p / %p.\n",
-						   dev->name, bus_to_virt(le32_to_cpu(np->rx_ring[entry].rxaddr)),
-						   skb->head, temp);
-#endif
+				char *temp;
+
+				pci_unmap_single(np->pdev, np->rx_info[entry].mapping, np->rx_buf_sz);
+				skb = np->rx_info[entry].skb;
+				temp = skb_put(skb, pkt_len);
+				np->rx_info[entry].skb = NULL;
+				np->rx_info[entry].mapping = 0;
 			}
 #ifndef final_version				/* Remove after testing. */
 			/* You will want this info for the initial debug. */
@@ -1124,13 +1093,16 @@
 	for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) {
 		struct sk_buff *skb;
 		int entry = np->dirty_rx % RX_RING_SIZE;
-		if (np->rx_skbuff[entry] == NULL) {
+		if (np->rx_info[entry].skb == NULL) {
 			skb = dev_alloc_skb(np->rx_buf_sz);
-			np->rx_skbuff[entry] = skb;
+			np->rx_info[entry].skb = skb;
 			if (skb == NULL)
 				break;			/* Better luck next round. */
+			np->rx_info[entry].mapping =
+				pci_map_single(np->pdev, skb->tail, np->rx_buf_sz);
 			skb->dev = dev;			/* Mark as being used by this device. */
-			np->rx_ring[entry].rxaddr = cpu_to_le32(virt_to_bus(skb->tail) | RxDescValid);
+			np->rx_ring[entry].rxaddr =
+				cpu_to_le32(np->rx_info[entry].mapping | RxDescValid);
 		}
 		if (entry == RX_RING_SIZE - 1)
 			np->rx_ring[entry].rxaddr |= cpu_to_le32(RxDescEndRing);
@@ -1184,10 +1156,8 @@
 	/* We should lock this segment of code for SMP eventually, although
 	   the vulnerability window is very small and statistics are
 	   non-critical. */
-#if LINUX_VERSION_CODE > 0x20119
 	np->stats.tx_bytes = readl(ioaddr + 0x57010);
 	np->stats.rx_bytes = readl(ioaddr + 0x57044);
-#endif
 	np->stats.tx_packets = readl(ioaddr + 0x57000);
 	np->stats.tx_aborted_errors =
 		readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028);
@@ -1313,8 +1283,7 @@
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (debug > 1) {
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was Int %4.4x.\n",
@@ -1333,14 +1302,14 @@
 #ifdef __i386__
 	if (debug > 2) {
 		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
-			   (int)virt_to_bus(np->tx_ring));
+			   np->tx_ring_dma);
 		for (i = 0; i < 8 /* TX_RING_SIZE */; i++)
 			printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n",
 				   i, le32_to_cpu(np->tx_ring[i].status),
 				   le32_to_cpu(np->tx_ring[i].addr),
 				   le32_to_cpu(np->tx_done_q[i].status));
 		printk(KERN_DEBUG "  Rx ring at %8.8x -> %p:\n",
-			   (int)virt_to_bus(np->rx_ring), np->rx_done_q);
+			   np->rx_ring_dma, np->rx_done_q);
 		if (np->rx_done_q)
 			for (i = 0; i < 8 /* RX_RING_SIZE */; i++) {
 				printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n",
@@ -1354,18 +1323,23 @@
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].rxaddr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
-		if (np->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
-			np->rx_skbuff[i]->free = 1;
-#endif
-			dev_kfree_skb(np->rx_skbuff[i]);
+		if (np->rx_info[i].skb != NULL) {
+			pci_unmap_single(np->pdev, np->rx_info[i].mapping, np->rx_buf_sz);
+			kfree_skb(np->rx_info[i].skb);
 		}
-		np->rx_skbuff[i] = 0;
+		np->rx_info[i].skb = NULL;
+		np->rx_info[i].mapping = 0;
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (np->tx_skbuff[i])
-			dev_kfree_skb(np->tx_skbuff[i]);
-		np->tx_skbuff[i] = 0;
+		struct sk_buff *skb = np->tx_info[i].skb;
+		if (skb != NULL) {
+			pci_unmap_single(np->pdev,
+							 np->tx_info[i].mapping,
+							 skb->len);
+			kfree_skb(skb);
+		}
+		np->tx_info[i].skb = NULL;
+		np->tx_info[i].mapping = 0;
 	}
 
 	MOD_DEC_USE_COUNT;
@@ -1373,9 +1347,7 @@
 	return 0;
 }
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init starfire_init_module (void)
 {
 	if (debug)					/* Emit version even if no cards detected. */
 		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
@@ -1391,7 +1363,7 @@
 #endif
 }
 
-void cleanup_module(void)
+static void __exit starfire_cleanup_module (void)
 {
 	struct net_device *next_dev;
 
@@ -1406,15 +1378,27 @@
 		next_dev = np->next_module;
 		unregister_netdev(root_net_dev);
 		iounmap((char *)root_net_dev->base_addr);
-		if (np->tx_done_q) free_page((long)np->tx_done_q);
-		if (np->rx_done_q) free_page((long)np->rx_done_q);
+		if (np->tx_done_q)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->tx_done_q, np->tx_done_q_dma);
+		if (np->rx_done_q)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->rx_done_q, np->rx_done_q_dma);
+		if (np->tx_ring)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->tx_ring, np->tx_ring_dma);
+		if (np->rx_ring)
+			pci_free_consistent(np->pdev, PAGE_SIZE,
+								np->rx_ring, np->rx_ring_dma);
 		kfree(root_net_dev);
 		root_net_dev = next_dev;
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(starfire_init_module);
+module_exit(starfire_cleanup_module);
+
+
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c starfire.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c
--- v2.3.42/linux/drivers/net/sunbmac.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/sunbmac.c	Thu Feb 10 12:26:47 2000
@@ -1,4 +1,4 @@
-/* $Id: sunbmac.c,v 1.13 2000/01/28 13:42:29 jj Exp $
+/* $Id: sunbmac.c,v 1.14 2000/02/09 11:15:35 davem Exp $
  * sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -190,14 +190,20 @@
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		if (bp->rx_skbs[i] != NULL) {
-			dev_kfree_skb(bp->rx_skbs[i]);
+			if (in_irq())
+				dev_kfree_skb_irq(bp->rx_skbs[i]);
+			else
+				dev_kfree_skb(bp->rx_skbs[i]);
 			bp->rx_skbs[i] = NULL;
 		}
 	}
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (bp->tx_skbs[i] != NULL) {
-			dev_kfree_skb(bp->tx_skbs[i]);
+			if (in_irq())
+				dev_kfree_skb_irq(bp->tx_skbs[i]);
+			else
+				dev_kfree_skb(bp->tx_skbs[i]);
 			bp->tx_skbs[i] = NULL;
 		}
 	}
@@ -750,8 +756,12 @@
 static void bigmac_tx(struct bigmac *bp)
 {
 	struct be_txd *txbase = &bp->bmac_block->be_txd[0];
-	int elem = bp->tx_old;
+	struct net_device *dev = bp->dev;
+	int elem;
+
+	spin_lock(&bp->lock);
 
+	elem = bp->tx_old;
 	DTX(("bigmac_tx: tx_old[%d] ", elem));
 	while (elem != bp->tx_new) {
 		struct sk_buff *skb;
@@ -770,12 +780,18 @@
 
 		DTX(("skb(%p) ", skb));
 		bp->tx_skbs[elem] = NULL;
-		dev_kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 
 		elem = NEXT_TX(elem);
 	}
 	DTX((" DONE, tx_old=%d\n", elem));
 	bp->tx_old = elem;
+
+	if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+	    TX_BUFFS_AVAIL(bp) > 0)
+		netif_wake_queue(bp->dev);
+
+	spin_unlock(&bp->lock);
 }
 
 /* BigMAC receive complete service routines. */
@@ -874,8 +890,6 @@
 	bmac_status = sbus_readl(bp->creg + CREG_STAT);
 	qec_status = sbus_readl(bp->gregs + GLOB_STAT);
 
-	bp->dev->interrupt = 1;
-
 	DIRQ(("qec_status=%08x bmac_status=%08x\n", qec_status, bmac_status));
 	if ((qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) ||
 	   (bmac_status & CREG_STAT_ERRORS))
@@ -886,13 +900,6 @@
 
 	if (bmac_status & CREG_STAT_RXIRQ)
 		bigmac_rx(bp);
-
-	if (bp->dev->tbusy && (TX_BUFFS_AVAIL(bp) > 0)) {
-		bp->dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-
-	bp->dev->interrupt = 0;
 }
 
 static int bigmac_open(struct net_device *dev)
@@ -928,55 +935,43 @@
 	return 0;
 }
 
+static void bigmac_tx_timeout(struct net_device *dev)
+{
+	struct bigmac *bp = (struct bigmac *) dev->priv;
+
+	bigmac_init(bp, 0);
+	netif_wake_queue(dev);
+}
+
 /* Put a packet on the wire. */
 static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 	int len, entry;
-
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-	    
-		if (tickssofar < 40) {
-			return 1;
-		} else {
-			printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-			bp->enet_stats.tx_errors++;
-			bigmac_init(bp, 0);
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-			dev_kfree_skb(skb);
-			return 0;
-		}
-	}
-
-	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name);
-		return 1;
-	}
-
-	if (!TX_BUFFS_AVAIL(bp))
-		return 1;
+	u32 mapping;
 
 	len = skb->len;
-	entry = bp->tx_new;
-	DTX(("bigmac_start_xmit: len(%d) entry(%d)\n", len, entry));
+	mapping = sbus_map_single(bp->bigmac_sdev, skb->data, len);
 
 	/* Avoid a race... */
+	spin_lock_irq(&bp->lock);
+	entry = bp->tx_new;
+	DTX(("bigmac_start_xmit: len(%d) entry(%d)\n", len, entry));
 	bp->bmac_block->be_txd[entry].tx_flags = TXD_UPDATE;
 	bp->tx_skbs[entry] = skb;
-	bp->bmac_block->be_txd[entry].tx_addr =
-		sbus_map_single(bp->bigmac_sdev, skb->data, len);
+	bp->bmac_block->be_txd[entry].tx_addr = mapping;
 	bp->bmac_block->be_txd[entry].tx_flags =
 		(TXD_OWN | TXD_SOP | TXD_EOP | (len & TXD_LENGTH));
-	dev->trans_start = jiffies;
 	bp->tx_new = NEXT_TX(entry);
+	if (TX_BUFFS_AVAIL(bp) <= 0)
+		netif_stop_queue(dev);
+	spin_unlock_irq(&bp->lock);
 
 	/* Get it going. */
 	sbus_writel(CREG_CTRL_TWAKEUP, bp->creg + CREG_CTRL);
 
-	if (TX_BUFFS_AVAIL(bp))
-		dev->tbusy = 0;
+
+	dev->trans_start = jiffies;
 
 	return 0;
 }
@@ -1084,6 +1079,8 @@
 	bp->qec_sdev = qec_sdev;
 	bp->bigmac_sdev = qec_sdev->child;
 
+	spin_lock_init(&bp->lock);
+
 	/* All further failures we find return this. */
 	res = ENODEV;
 
@@ -1194,6 +1191,9 @@
 	dev->get_stats = &bigmac_get_stats;
 	dev->set_multicast_list = &bigmac_set_multicast;
 
+	dev->tx_timeout = &bigmac_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
+
 	/* Finish net device registration. */
 	dev->irq = bp->bigmac_sdev->irqs[0];
 	dev->dma = 0;
@@ -1251,7 +1251,7 @@
 	return 1;
 }
 
-int __init bigmac_probe(void)
+static int __init bigmac_probe(void)
 {
 	struct net_device *dev = NULL;
 	struct sbus_bus *sbus;
@@ -1259,6 +1259,10 @@
 	static int called = 0;
 	int cards = 0, v;
 
+#ifdef MODULE
+	root_bigmac_dev = NULL;
+#endif
+
 	if (called)
 		return ENODEV;
 	called++;
@@ -1280,18 +1284,9 @@
 	return 0;
 }
 
-#ifdef MODULE
-
-int
-init_module(void)
-{
-	root_bigmac_dev = NULL;
-	return bigmac_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit bigmac_cleanup(void)
 {
+#ifdef MODULE
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_bigmac_dev) {
 		struct bigmac *bp = root_bigmac_dev;
@@ -1310,6 +1305,8 @@
 		kfree(bp->dev);
 		root_bigmac_dev = bp_nxt;
 	}
+#endif /* MODULE */
 }
 
-#endif /* MODULE */
+module_init(bigmac_probe);
+module_exit(bigmac_cleanup);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sunbmac.h linux/drivers/net/sunbmac.h
--- v2.3.42/linux/drivers/net/sunbmac.h	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/sunbmac.h	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: sunbmac.h,v 1.5 1999/09/21 14:36:26 davem Exp $
+/* $Id: sunbmac.h,v 1.6 2000/02/09 11:15:36 davem Exp $
  * sunbmac.h: Defines for the Sun "Big MAC" 100baseT ethernet cards.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -309,6 +309,8 @@
 	unsigned long	tregs;	/* BigMAC Transceiver                 */
 	struct bmac_init_block	*bmac_block;	/* RX and TX descriptors */
 	__u32			 bblock_dvma;	/* RX and TX descriptors */
+
+	spinlock_t		lock;
 
 	struct sk_buff		*rx_skbs[RX_RING_SIZE];
 	struct sk_buff		*tx_skbs[TX_RING_SIZE];
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.3.42/linux/drivers/net/sunhme.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/sunhme.c	Thu Feb 10 12:26:47 2000
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.85 2000/01/28 13:42:27 jj Exp $
+/* $Id: sunhme.c,v 1.86 2000/02/09 11:15:36 davem Exp $
  * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
@@ -1194,7 +1194,10 @@
 			rxd = &hp->happy_block->happy_meal_rxd[i];
 			dma_addr = hme_read_desc32(hp, &rxd->rx_addr);
 			hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE);
-			dev_kfree_skb(skb);
+			if (in_irq())
+				dev_kfree_skb_irq(skb);
+			else
+				dev_kfree_skb(skb);
 			hp->rx_skbs[i] = NULL;
 		}
 	}
@@ -1208,7 +1211,10 @@
 			txd = &hp->happy_block->happy_meal_txd[i];
 			dma_addr = hme_read_desc32(hp, &txd->tx_addr);
 			hme_dma_unmap(hp, dma_addr, skb->len);
-			dev_kfree_skb(skb);
+			if (in_irq())
+				dev_kfree_skb_irq(skb);
+			else
+				dev_kfree_skb(skb);
 			hp->tx_skbs[i] = NULL;
 		}
 	}
@@ -1871,8 +1877,12 @@
 {
 	struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0];
 	struct happy_meal_txd *this;
-	int elem = hp->tx_old;
+	struct net_device *dev = hp->dev;
+	int elem;
 
+	spin_lock(&hp->happy_lock);
+
+	elem = hp->tx_old;
 	TXD(("TX<"));
 	while (elem != hp->tx_new) {
 		struct sk_buff *skb;
@@ -1889,13 +1899,19 @@
 		hp->tx_skbs[elem] = NULL;
 		hp->net_stats.tx_bytes += skb->len;
 
-		dev_kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 
 		hp->net_stats.tx_packets++;
 		elem = NEXT_TX(elem);
 	}
 	hp->tx_old = elem;
 	TXD((">"));
+
+	if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+	    TX_BUFFS_AVAIL(hp) > 0)
+		netif_wake_queue(dev);
+
+	spin_unlock(&hp->happy_lock);
 }
 
 #ifdef RXDEBUG
@@ -2020,14 +2036,10 @@
 
 	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
-	dev->interrupt = 1;
-
 	if (happy_status & GREG_STAT_ERRORS) {
 		HMD(("ERRORS "));
-		if (happy_meal_is_not_so_happy(hp, /* un- */ happy_status)) {
-			dev->interrupt = 0;
+		if (happy_meal_is_not_so_happy(hp, /* un- */ happy_status))
 			return;
-		}
 	}
 
 	if (happy_status & GREG_STAT_MIFIRQ) {
@@ -2045,12 +2057,6 @@
 		happy_meal_rx(hp, dev);
 	}
 
-	if (dev->tbusy && (TX_BUFFS_AVAIL(hp) > 0)) {
-		hp->dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-
-	dev->interrupt = 0;
 	HMD(("done\n"));
 }
 
@@ -2072,14 +2078,10 @@
 				      GREG_STAT_RXTOHOST)))
 			continue;
 
-		dev->interrupt = 1;
-
 		if (happy_status & GREG_STAT_ERRORS) {
 			HMD(("ERRORS "));
-			if (happy_meal_is_not_so_happy(hp, happy_status)) {
-				dev->interrupt=0;
+			if (happy_meal_is_not_so_happy(hp, happy_status))
 				break;
-			}
 		}
 
 		if (happy_status & GREG_STAT_MIFIRQ) {
@@ -2096,12 +2098,6 @@
 			HMD(("RXTOHOST "));
 			happy_meal_rx(hp, dev);
 		}
-
-		if (dev->tbusy && (TX_BUFFS_AVAIL(hp) > 0)) {
-			hp->dev->tbusy = 0;
-			mark_bh(NET_BH);
-		}
-		dev->interrupt = 0;
 	}
 	HMD(("done\n"));
 }
@@ -2161,50 +2157,46 @@
 #define SXD(x)
 #endif
 
+static void happy_meal_tx_timeout(struct net_device *dev)
+{
+	struct happy_meal *hp = (struct happy_meal *) dev->priv;
+
+	printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
+	tx_dump_log();
+	printk (KERN_ERR "%s: Happy Status %08x TX[%08x:%08x]\n", dev->name,
+		hme_read32(hp, hp->gregs + GREG_STAT),
+		hme_read32(hp, hp->etxregs + ETX_CFG),
+		hme_read32(hp, hp->bigmacregs + BMAC_TXCFG));
+	happy_meal_init(hp, 0);
+	netif_wake_queue(dev);
+}
+
 static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int len, entry;
+	u32 mapping;
 
-	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		int tickssofar = jiffies - dev->trans_start;
-	    
-		if (tickssofar >= 40) {
-			printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-			hp->net_stats.tx_errors++;
-			tx_dump_log();
-			printk (KERN_ERR "%s: Happy Status %08x TX[%08x:%08x]\n", dev->name,
-				hme_read32(hp, hp->gregs + GREG_STAT),
-				hme_read32(hp, hp->etxregs + ETX_CFG),
-				hme_read32(hp, hp->bigmacregs + BMAC_TXCFG));
-			happy_meal_init(hp, 0);
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-		} else
-			tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0);
-		return 1;
-	}
-
-	if (!TX_BUFFS_AVAIL(hp)) {
-		tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0);
-		return 1;
-	}
 	len = skb->len;
-	entry = hp->tx_new;
+	mapping = hme_dma_map(hp, skb->data, len);
+
+	spin_lock_irq(&hp->happy_lock);
 
+	entry = hp->tx_new;
 	SXD(("SX<l[%d]e[%d]>", len, entry));
 	hp->tx_skbs[entry] = skb;
 	hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry],
 		      (TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE)),
-		      hme_dma_map(hp, skb->data, len));
+		      mapping);
 	hp->tx_new = NEXT_TX(entry);
+	if (TX_BUFFS_AVAIL(hp) <= 0)
+		netif_stop_queue(dev);
+
+	spin_unlock_irq(&hp->happy_lock);
 
 	/* Get it going. */
-	dev->trans_start = jiffies;
 	hme_write32(hp, hp->etxregs + ETX_PENDING, ETX_TP_DMAWAKEUP);
-
-	if (TX_BUFFS_AVAIL(hp))
-		dev->tbusy = 0;
+	dev->trans_start = jiffies;
 
 	tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
 	return 0;
@@ -2228,7 +2220,7 @@
 	u32 crc, poly = CRC_POLYNOMIAL_LE;
 
 	/* Lock out others. */
-	set_bit(0, (void *) &dev->tbusy);
+	netif_stop_queue(dev);
 
 	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
 		hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff);
@@ -2272,7 +2264,7 @@
 	}
 
 	/* Let us get going again. */
-	dev->tbusy = 0;
+	netif_wake_queue(dev);
 }
 
 /* Ethtool support... */
@@ -2552,6 +2544,8 @@
 
 	hp->happy_dev = sdev;
 
+	spin_lock_init(&hp->happy_lock);
+
 	if (sdev->num_registers != 5) {
 		printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n",
 		       sdev->num_registers);
@@ -2637,6 +2631,8 @@
 	dev->hard_start_xmit = &happy_meal_start_xmit;
 	dev->get_stats = &happy_meal_get_stats;
 	dev->set_multicast_list = &happy_meal_set_multicast;
+	dev->tx_timeout = &happy_meal_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
 	dev->do_ioctl = &happy_meal_ioctl;
 
 	dev->irq = sdev->irqs[0];
@@ -2741,6 +2737,8 @@
 
 	hp->happy_dev = pdev;
 
+	spin_lock_init(&hp->happy_lock);
+
 	if (qp != NULL) {
 		hp->qfe_parent = qp;
 		hp->qfe_ent = qfe_slot;
@@ -2912,12 +2910,16 @@
 }
 #endif
 
-int __init happy_meal_probe(void)
+static int __init happy_meal_probe(void)
 {
 	struct net_device *dev = NULL;
 	static int called = 0;
 	int cards;
 
+#ifdef MODULE
+	root_happy_dev = NULL;
+#endif
+
 	if (called)
 		return ENODEV;
 	called++;
@@ -2936,18 +2938,10 @@
 	return 0;
 }
 
-#ifdef MODULE
 
-int
-init_module(void)
-{
-	root_happy_dev = NULL;
-	return happy_meal_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit cleanup_module(void)
 {
+#ifdef MODULE
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_happy_dev) {
 		struct happy_meal *hp = root_happy_dev;
@@ -2978,6 +2972,8 @@
 		kfree(hp->dev);
 		root_happy_dev = next;
 	}
+#endif /* MODULE */
 }
 
-#endif /* MODULE */
+module_init(happy_meal_probe);
+module_exit(happy_meal_cleanup_module);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h
--- v2.3.42/linux/drivers/net/sunhme.h	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/sunhme.h	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: sunhme.h,v 1.28 1999/09/21 14:36:34 davem Exp $
+/* $Id: sunhme.h,v 1.29 2000/02/09 11:15:40 davem Exp $
  * sunhme.h: Definitions for Sparc HME/BigMac 10/100baseT ethernet driver.
  *           Also known as the "Happy Meal".
  *
@@ -509,6 +509,8 @@
 
 	/* This is either a sbus_dev or a pci_dev. */
 	void			  *happy_dev;
+
+	spinlock_t		  happy_lock;
 
 	struct sk_buff           *rx_skbs[RX_RING_SIZE];
 	struct sk_buff           *tx_skbs[TX_RING_SIZE];
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.3.42/linux/drivers/net/sunlance.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/sunlance.c	Thu Feb 10 12:26:47 2000
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.93 2000/01/28 13:42:31 jj Exp $
+/* $Id: sunlance.c,v 1.94 2000/02/09 11:15:40 davem Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *	Written 1995, 1996 by Miguel de Icaza
@@ -240,6 +240,8 @@
 	unsigned long	dregs;		/* DMA controller regs.		*/
 	volatile struct lance_init_block *init_block;
     
+	spinlock_t	lock;
+
 	int		rx_new, tx_new;
 	int		rx_old, tx_old;
     
@@ -317,7 +319,6 @@
 }
 
 /* Setup the Lance Rx and Tx rings */
-/* Sets dev->tbusy */
 static void lance_init_ring_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
@@ -327,7 +328,7 @@
 	int i;
     
 	/* Lock out other processes while setting up hardware */
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 	lp->rx_new = lp->tx_new = 0;
 	lp->rx_old = lp->tx_old = 0;
 
@@ -383,7 +384,7 @@
 	int i;
     
 	/* Lock out other processes while setting up hardware */
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 	lp->rx_new = lp->tx_new = 0;
 	lp->rx_old = lp->tx_old = 0;
 
@@ -573,6 +574,8 @@
 	volatile struct lance_init_block *ib = lp->init_block;
 	int i, j;
 
+	spin_lock(&lp->lock);
+
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
 		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
@@ -637,6 +640,12 @@
 		j = TX_NEXT(j);
 	}
 	lp->tx_old = j;
+
+	if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+	    TX_BUFFS_AVAIL > 0)
+		netif_wake_queue(dev);
+
+	spin_unlock(&lp->lock);
 }
 
 static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len)
@@ -736,6 +745,8 @@
 	volatile struct lance_init_block *ib = lp->init_block;
 	int i, j;
 
+	spin_lock(&lp->lock);
+
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
 		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
@@ -800,6 +811,12 @@
 		j = TX_NEXT(j);
 	}
 	lp->tx_old = j;
+
+	if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+	    TX_BUFFS_AVAIL > 0)
+		netif_wake_queue(dev);
+
+	spin_unlock(&lp->lock);
 }
 
 static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -808,11 +825,6 @@
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int csr0;
     
-	if (dev->interrupt)
-		printk(KERN_ERR "%s: again", dev->name);
-    
-	dev->interrupt = 1;
-
 	sbus_writew(LE_CSR0, lp->lregs + RAP);
 	csr0 = sbus_readw(lp->lregs + RDP);
 
@@ -833,11 +845,6 @@
 	if (csr0 & LE_C0_TINT)
 		lp->tx(dev);
     
-	if ((TX_BUFFS_AVAIL > 0) && dev->tbusy) {
-		dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-
 	if (csr0 & LE_C0_BABL)
 		lp->stats.tx_errors++;
 
@@ -867,11 +874,10 @@
 		lp->init_ring(dev);
 		load_csrs(lp);
 		init_restart_lance(lp);
-		dev->tbusy = 0;
+		netif_wake_queue(dev);
 	}
 
 	sbus_writew(LE_C0_INEA, lp->lregs + RDP);
-	dev->interrupt = 0;
 }
 
 /* Build a fake network packet and send it to ourselves. */
@@ -953,9 +959,7 @@
 	lp->init_ring(dev);
 	load_csrs(lp);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
 	status = init_restart_lance(lp);
 	if (!status && lp->auto_select) {
@@ -973,9 +977,8 @@
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 
-	dev->start = 0;
-	dev->tbusy = 1;
-	del_timer(&lp->multicast_timer);
+	netif_stop_queue(dev);
+	del_timer_sync(&lp->multicast_timer);
 
 	STOP_LANCE(lp);
 
@@ -1007,9 +1010,6 @@
 	lp->init_ring(dev);
 	load_csrs(lp);
 	dev->trans_start = jiffies;
-	dev->interrupt = 0;
-	dev->start = 1;
-	dev->tbusy = 0;
 	status = init_restart_lance(lp);
 	return status;
 }
@@ -1108,40 +1108,30 @@
 		sbus_writeb(0, piobuf);
 }
 
+static void lance_tx_timeout(struct net_device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+
+	printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
+	       dev->name, sbus_readw(lp->lregs + RDP));
+	lance_reset(dev);
+	netif_wake_queue(dev);
+}
+
 static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
-	unsigned long flags;
 	int entry, skblen, len;
 
-	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		int tickssofar = jiffies - dev->trans_start;
-
-		if (tickssofar < 100)
-			return 1;
-
-		printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
-		       dev->name, sbus_readw(lp->lregs + RDP));
-		lp->stats.tx_errors++;
-		lance_reset(dev);
-
-		return 1;
-	}
-
 	skblen = skb->len;
 
-	save_and_cli(flags);
-
-	if (!TX_BUFFS_AVAIL) {
-		restore_flags(flags);
-		return 1;
-	}
-
 	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
 
 	lp->stats.tx_bytes += len;
 
+	spin_lock_irq(&lp->lock);
+
 	entry = lp->tx_new & TX_RING_MOD_MASK;
 	if (lp->pio_buffer) {
 		sbus_writew((-len) | 0xf000, &ib->btx_ring[entry].length);
@@ -1161,21 +1151,22 @@
 
 	lp->tx_new = TX_NEXT(entry);
 
+	if (TX_BUFFS_AVAIL <= 0)
+		netif_stop_queue(dev);
+
+	spin_unlock_irq(&lp->lock);
+
 	/* Kick the lance: transmit now */
 	sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP);
 	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
     
-	if (TX_BUFFS_AVAIL)
-		dev->tbusy = 0;
-
 	/* Read back CSR to invalidate the E-Cache.
 	 * This is needed, because DMA_DSBL_WR_INV is set.
 	 */
 	if (lp->dregs)
 		sbus_readw(lp->lregs + RDP);
 
-	restore_flags(flags);
 	return 0;
 }
 
@@ -1255,20 +1246,17 @@
 	volatile struct lance_init_block *ib = lp->init_block;
 	u16 mode;
 
-	if (!dev->start)
+	if (!test_bit(LINK_STATE_START, &dev->state))
 		return;
 
-	if (test_and_set_bit(0, (void *)&dev->tbusy)) {
-		mod_timer(&lp->multicast_timer, jiffies + 2);
-		return;
-	}
-
 	if (lp->tx_old != lp->tx_new) {
 		mod_timer(&lp->multicast_timer, jiffies + 4);
-		dev->tbusy = 0;
+		netif_wake_queue(dev);
 		return;
 	}
 
+	netif_stop_queue(dev);
+
 	STOP_LANCE(lp);
 	lp->init_ring(dev);
 
@@ -1292,8 +1280,14 @@
 	}
 	load_csrs(lp);
 	init_restart_lance(lp);
-	dev->tbusy = 0;
-	mark_bh(NET_BH);
+	netif_wake_queue(dev);
+}
+
+static void lance_set_multicast_retry(unsigned long _opaque)
+{
+	struct net_device *dev = (struct net_device *) _opaque;
+
+	lance_set_multicast(dev);
 }
 
 static void lance_free_hwresources(struct lance_private *lp)
@@ -1476,6 +1470,8 @@
 	dev->open = &lance_open;
 	dev->stop = &lance_close;
 	dev->hard_start_xmit = &lance_start_xmit;
+	dev->tx_timeout = &lance_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
 	dev->get_stats = &lance_get_stats;
 	dev->set_multicast_list = &lance_set_multicast;
 
@@ -1491,8 +1487,7 @@
 	 */
 	init_timer(&lp->multicast_timer);
 	lp->multicast_timer.data = (unsigned long) dev;
-	lp->multicast_timer.function =
-		(void (*)(unsigned long)) &lance_set_multicast;
+	lp->multicast_timer.function = &lance_set_multicast_retry;
 
 #ifdef MODULE
 	dev->ifindex = dev_new_index();
@@ -1524,11 +1519,15 @@
 #include <asm/sun4paddr.h>
 
 /* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe(void)
+static int __init sparc_lance_probe(void)
 {
 	static struct sbus_dev sdev;
 	static int called = 0;
 
+#ifdef MODULE
+	root_lance_dev = NULL;
+#endif
+
 	if (called)
 		return ENODEV;
 	called++;
@@ -1546,7 +1545,7 @@
 #else /* !CONFIG_SUN4 */
 
 /* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe(void)
+static int __init sparc_lance_probe(void)
 {
 	struct sbus_bus *bus;
 	struct sbus_dev *sdev = 0;
@@ -1555,6 +1554,10 @@
 	static int called = 0;
 	int cards = 0, v;
 
+#ifdef MODULE
+	root_lance_dev = NULL;
+#endif
+
 	if (called)
 		return ENODEV;
 	called++;
@@ -1592,18 +1595,9 @@
 }
 #endif /* !CONFIG_SUN4 */
 
-#ifdef MODULE
-
-int
-init_module(void)
-{
-	root_lance_dev = NULL;
-	return sparc_lance_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit sparc_lance_cleanup(void)
 {
+#ifdef MODULE
 	struct lance_private *lp;
 
 	while (root_lance_dev) {
@@ -1614,6 +1608,8 @@
 		kfree(root_lance_dev->dev);
 		root_lance_dev = lp;
 	}
+#endif /* MODULE */
 }
 
-#endif /* MODULE */
+module_init(sparc_lance_probe);
+module_exit(sparc_lance_cleanup);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- v2.3.42/linux/drivers/net/sunqe.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/net/sunqe.c	Thu Feb 10 12:29:58 2000
@@ -1,4 +1,4 @@
-/* $Id: sunqe.c,v 1.41 2000/01/28 13:42:30 jj Exp $
+/* $Id: sunqe.c,v 1.43 2000/02/09 21:11:19 davem Exp $
  * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
  *          Once again I am out to prove that every ethernet
  *          controller out there can be most efficiently programmed
@@ -455,6 +455,8 @@
 		printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", qep->dev->name);
 }
 
+static void qe_tx_reclaim(struct sunqe *qep);
+
 /* Interrupts for all QE's get filtered out via the QEC master controller,
  * so we just run through each qe and check to see who is signaling
  * and thus needs to be serviced.
@@ -470,11 +472,8 @@
 	while (channel < 4) {
 		if (qec_status & 0xf) {
 			struct sunqe *qep = qecp->qes[channel];
-			struct net_device *dev = qep->dev;
 			u32 qe_status;
 
-			dev->interrupt = 1;
-
 			qe_status = sbus_readl(qep->qcregs + CREG_STAT);
 			if (qe_status & CREG_STAT_ERRORS) {
 				if (qe_is_bolixed(qep, qe_status))
@@ -482,8 +481,20 @@
 			}
 			if (qe_status & CREG_STAT_RXIRQ)
 				qe_rx(qep);
+			if (test_bit(LINK_STATE_XOFF, &qep->dev->state) &&
+			    (qe_status & CREG_STAT_TXIRQ)) {
+				spin_lock(&qep->lock);
+				qe_tx_reclaim(qep);
+				if (TX_BUFFS_AVAIL(qep) > 0) {
+					/* Wake net queue and return to
+					 * lazy tx reclaim.
+					 */
+					netif_wake_queue(qep->dev);
+					sbus_writel(1, qep->qcregs + CREG_TIMASK);
+				}
+				spin_unlock(&qep->lock);
+			}
 	next:
-			dev->interrupt = 0;
 		}
 		qec_status >>= 4;
 		channel++;
@@ -514,11 +525,12 @@
 	return 0;
 }
 
-/* Reclaim TX'd frames from the ring. */
+/* Reclaim TX'd frames from the ring.  This must always run under
+ * the IRQ protected qep->lock.
+ */
 static void qe_tx_reclaim(struct sunqe *qep)
 {
 	struct qe_txd *txbase = &qep->qe_block->qe_txd[0];
-	struct net_device *dev = qep->dev;
 	int elem = qep->tx_old;
 
 	while (elem != qep->tx_new) {
@@ -529,11 +541,31 @@
 		elem = NEXT_TX(elem);
 	}
 	qep->tx_old = elem;
+}
 
-	if (dev->tbusy && (TX_BUFFS_AVAIL(qep) > 0)) {
-		dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
+static void qe_tx_timeout(struct net_device *dev)
+{
+	struct sunqe *qep = (struct sunqe *) dev->priv;
+	int tx_full;
+
+	spin_lock_irq(&qep->lock);
+
+	/* Try to reclaim, if that frees up some tx
+	 * entries, we're fine.
+	 */
+	qe_tx_reclaim(qep);
+	tx_full = TX_BUFFS_AVAIL(qep) <= 0;
+
+	spin_unlock_irq(&qep->lock);
+
+	if (! tx_full)
+		goto out;
+
+	printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
+	qe_init(qep, 1);
+
+out:
+	netif_wake_queue(dev);
 }
 
 /* Get a packet queued to go onto the wire. */
@@ -545,19 +577,9 @@
 	unsigned char *txbuf;
 	int len, entry;
 
-	qe_tx_reclaim(qep);
-
-	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		long tickssofar = jiffies - dev->trans_start;
+	spin_lock_irq(&qep->lock);
 
-		if (tickssofar >= 40) {
-			printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-			qe_init(qep, 1);
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-		}
-		return 1;
-	}
+	qe_tx_reclaim(qep);
 
 	len = skb->len;
 	entry = qep->tx_new;
@@ -583,10 +605,18 @@
 	qep->net_stats.tx_packets++;
 	qep->net_stats.tx_bytes += len;
 
-	dev_kfree_skb(skb);
+	if (TX_BUFFS_AVAIL(qep) <= 0) {
+		/* Halt the net queue and enable tx interrupts.
+		 * When the tx queue empties the tx irq handler
+		 * will wake up the queue and return us back to
+		 * the lazy tx reclaim scheme.
+		 */
+		netif_stop_queue(dev);
+		sbus_writel(0, qep->qcregs + CREG_TIMASK);
+	}
+	spin_unlock_irq(&qep->lock);
 
-	if (TX_BUFFS_AVAIL(qep))
-		dev->tbusy = 0;
+	dev_kfree_skb(skb);
 
 	return 0;
 }
@@ -611,7 +641,7 @@
 	u32 crc, poly = CRC_POLYNOMIAL_LE;
 
 	/* Lock out others. */
-	set_bit(0, (void *) &dev->tbusy);
+	netif_stop_queue(dev);
 
 	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
 		sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET,
@@ -673,7 +703,7 @@
 	sbus_writeb(qep->mconfig, qep->mregs + MREGS_MCONFIG);
 
 	/* Let us get going again. */
-	dev->tbusy = 0;
+	netif_wake_queue(dev);
 }
 
 /* This is only called once at boot time for each card probed. */
@@ -722,6 +752,7 @@
 	qe_devs[0] = dev;
 	qeps[0] = (struct sunqe *) dev->priv;
 	qeps[0]->channel = 0;
+	spin_lock_init(&qeps[0]->lock);
 	for (j = 0; j < 6; j++)
 		qe_devs[0]->dev_addr[j] = idprom->id_ethaddr[j];
 
@@ -857,6 +888,8 @@
 		qe_devs[i]->hard_start_xmit = qe_start_xmit;
 		qe_devs[i]->get_stats = qe_get_stats;
 		qe_devs[i]->set_multicast_list = qe_set_multicast;
+		qe_devs[i]->tx_timeout = qe_tx_timeout;
+		qe_devs[i]->watchdog_timeo = 5*HZ;
 		qe_devs[i]->irq = sdev->irqs[0];
 		qe_devs[i]->dma = 0;
 		ether_setup(qe_devs[i]);
@@ -953,7 +986,7 @@
 	return 1;
 }
 
-int __init qec_probe(void)
+static int __init qec_probe(void)
 {
 	struct net_device *dev = NULL;
 	struct sbus_bus *bus;
@@ -961,6 +994,10 @@
 	static int called = 0;
 	int cards = 0, v;
 
+#ifdef MODULE
+	root_qec_dev = NULL;
+#endif
+
 	if (called)
 		return ENODEV;
 	called++;
@@ -982,18 +1019,9 @@
 	return 0;
 }
 
-#ifdef MODULE
-
-int
-init_module(void)
-{
-	root_qec_dev = NULL;
-	return qec_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit qec_cleanup(void)
 {
+#ifdef MODULE
 	struct sunqec *next_qec;
 	int i;
 
@@ -1021,6 +1049,8 @@
 		kfree(root_qec_dev);
 		root_qec_dev = next_qec;
 	}
+#endif /* MODULE */
 }
 
-#endif /* MODULE */
+module_init(qec_probe);
+module_exit(qec_cleanup);
diff -u --recursive --new-file v2.3.42/linux/drivers/net/sunqe.h linux/drivers/net/sunqe.h
--- v2.3.42/linux/drivers/net/sunqe.h	Wed Dec 29 13:13:16 1999
+++ linux/drivers/net/sunqe.h	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: sunqe.h,v 1.12 1999/09/21 14:36:44 davem Exp $
+/* $Id: sunqe.h,v 1.13 2000/02/09 11:15:42 davem Exp $
  * sunqe.h: Definitions for the Sun QuadEthernet driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -335,6 +335,7 @@
 	unsigned long			mregs;		/* Per-channel MACE Registers  */
 	struct qe_init_block      	*qe_block;	/* RX and TX descriptors       */
 	__u32                      	qblock_dvma;	/* RX and TX descriptors       */
+	spinlock_t			lock;		/* Protects txfull state       */
 	int                        	rx_new, rx_old;	/* RX ring extents	       */
 	int			   	tx_new, tx_old;	/* TX ring extents	       */
 	struct sunqe_buffers		*buffers;	/* CPU visible address.        */
diff -u --recursive --new-file v2.3.42/linux/drivers/net/tlan.c linux/drivers/net/tlan.c
--- v2.3.42/linux/drivers/net/tlan.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/net/tlan.c	Thu Feb 10 12:26:47 2000
@@ -47,7 +47,20 @@
  *			       overwrite timers like TLAN_TIMER_ACTIVITY
  *			       Patch from John Cagle <john.cagle@compaq.com>.
  *			     - Fixed a few compiler warnings.
- *			     
+ *
+ *	v1.3 Feb 04, 2000    - Fixed the remaining HZ issues.
+ *			     - Removed call to pci_present(). 
+ *			     - Removed SA_INTERRUPT flag from irq handler.
+ *			     - Added __init and __initdata to reduce resisdent 
+ *			       code size.
+ *			     - Driver now uses module_init/module_exit.
+ *			     - Rewrote init_module and tlan_probe to
+ *			       share a lot more code. We now use tlan_probe
+ *			       with builtin and module driver.
+ *			     - Driver ported to new net API. 
+ *			     - tlan.txt has been reworked to reflect current 
+ *			       driver (almost)
+ *			     - Other minor stuff
  *
  *******************************************************************************/
 
@@ -56,6 +69,7 @@
 
 #include "tlan.h"
 
+#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/etherdevice.h>
@@ -66,35 +80,32 @@
 typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );
 
 
-#ifdef MODULE
 
 static	struct net_device	*TLanDevices = NULL;
 static	int		TLanDevicesInstalled = 0;
 
+/* Force speed, duplex and aui settings */
 static	int		aui = 0;
-static	int		sa_int = 0;
-static	int		duplex = 0;
+static	int		duplex = 0; 
 static	int		speed = 0;
 
 MODULE_PARM(aui, "i");
-MODULE_PARM(sa_int, "i");
 MODULE_PARM(duplex, "i");
 MODULE_PARM(speed, "i");
 MODULE_PARM(debug, "i");
 EXPORT_NO_SYMBOLS;
 
-#endif
-
-
+/* Turn on debugging. See linux/Documentation/networking/tlan.txt for details */
 static  int		debug = 0;
+
 static	int		bbuf = 0;
 static	u8		*TLanPadBuffer;
 static	char		TLanSignature[] = "TLAN";
 static	int		TLanVersionMajor = 1;
-static	int		TLanVersionMinor = 2;
+static	int		TLanVersionMinor = 3;
 
 
-static	TLanAdapterEntry TLanAdapterList[] = {
+static TLanAdapterEntry TLanAdapterList[] __initdata = {
 	{ PCI_VENDOR_ID_COMPAQ, 
 	  PCI_DEVICE_ID_NETELLIGENT_10,
 	  "Compaq Netelligent 10 T PCI UTP",
@@ -183,7 +194,7 @@
 
 
 static int	TLan_PciProbe( u8 *, u8 *, u8 *, u32 *, u32 * );
-static int	TLan_Init( struct net_device * );
+static int      TLan_Init( struct net_device * );
 static int	TLan_Open(struct net_device *dev);
 static int	TLan_StartTx(struct sk_buff *, struct net_device *);
 static void	TLan_HandleInterrupt(int, void *, struct pt_regs *);
@@ -282,114 +293,9 @@
 *****************************************************************************/
 
 
-#ifdef MODULE
 
 	/***************************************************************
-	 *	init_module
-	 *
-	 *	Returns:
-	 *		0 if module installed ok, non-zero if not.
-	 *	Parms:
-	 *		None
-	 *
-	 *	This function begins the setup of the driver creating a
-	 *	pad buffer, finding all TLAN devices (matching
-	 *	TLanAdapterList entries), and creating and initializing a
-	 *	device structure for each adapter.
-	 *
-	 **************************************************************/
-
-extern int init_module(void)
-{
-	TLanPrivateInfo	*priv;
-	struct net_device	*dev;
-	size_t		dev_size;
-	u8		dfn;
-	u32		index;
-	int		failed;
-	int		found;
-	u32		io_base;
-	u8		irq;
-	u8		rev;
-
-	printk( "TLAN driver, v%d.%d, (C) 1997-8 Caldera, Inc.\n",
-		TLanVersionMajor,
-		TLanVersionMinor
-	      );
-	TLanPadBuffer = (u8 *) kmalloc( TLAN_MIN_FRAME_SIZE,
-					( GFP_KERNEL | GFP_DMA )
-				      );
-	if ( TLanPadBuffer == NULL ) {
-		printk( "TLAN:  Could not allocate memory for pad buffer.\n" );
-		return -ENOMEM;
-	}
-
-	memset( TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE );
-
-	dev_size = sizeof(struct net_device) + sizeof(TLanPrivateInfo);
-
-	while ( ( found = TLan_PciProbe( &dfn, &irq, &rev, &io_base, &index ) ) ) {
-		dev = (struct net_device *) kmalloc( dev_size, GFP_KERNEL );
-		if ( dev == NULL ) {
-			printk( "TLAN:  Could not allocate memory for device.\n" );
-			continue;
-		}
-		memset( dev, 0, dev_size );
-
-		dev->priv = priv = ( (void *) dev ) + sizeof(struct net_device);
-		dev->name = priv->devName;
-		strcpy( priv->devName, "    " );
-		dev->base_addr = io_base;
-		dev->irq = irq;
-		dev->init = TLan_Init;
-
-		priv->adapter =    &TLanAdapterList[index];
-		priv->adapterRev = rev;
-		priv->aui =        aui;
-		if ( ( duplex != 1 ) && ( duplex != 2 ) ) {
-			duplex = 0;
-		}
-		priv->duplex =     duplex;
-		if ( ( speed != 10 ) && ( speed != 100 ) ) {
-			speed = 0;
-		}
-		priv->speed =      speed;
-		priv->sa_int =     sa_int;
-		priv->debug =      debug;
-		
-		spin_lock_init(&priv->lock);
-
-		ether_setup( dev );
-
-		failed = register_netdev( dev );
-
-		if ( failed ) {
-			printk( "TLAN:  Could not register device.\n" );
-			kfree( dev );
-		} else {
-			priv->nextDevice = TLanDevices;
-			TLanDevices = dev;
-			TLanDevicesInstalled++;
-			printk("TLAN:  %s irq=%2d io=%04x, %s, Rev. %d\n",
-				dev->name,
-				(int) dev->irq,
-				(int) dev->base_addr,
-				priv->adapter->deviceLabel,
-				priv->adapterRev );
-		}
-	}
-	
-	/* printk( "TLAN:  Found %d device(s).\n", TLanDevicesInstalled ); */
-
-	return ( ( TLanDevicesInstalled > 0 ) ? 0 : -ENODEV );
-
-} /* init_module */
-
-
-
-
-	/***************************************************************
-	 *	cleanup_module
+	 *	tlan_exit
 	 *
 	 *	Returns:
 	 *		Nothing
@@ -403,7 +309,8 @@
 	 *
 	 **************************************************************/
 
-extern void cleanup_module(void)
+
+static void __exit tlan_exit(void)
 {
 	struct net_device	*dev;
 	TLanPrivateInfo	*priv;
@@ -422,108 +329,111 @@
 	}
 	kfree( TLanPadBuffer );
 
-} /* cleanup_module */
-
-
-#else /* MODULE */
+} 
 
 
-
-
-	/***************************************************************
+/*
+	***************************************************************
 	 *	tlan_probe
 	 *
 	 *	Returns:
 	 *		0 on success, error code on error
-	 *	Parms:
-	 *		dev	device struct to use if adapter is
-	 *			found.
+	 *	Parms: 
+	 *		none
 	 *
 	 *	The name is lower case to fit in with all the rest of
-	 *	the netcard_probe names.  This function looks for a/
+	 *	the netcard_probe names.  This function looks for 
 	 *	another TLan based adapter, setting it up with the
-	 *	provided device struct if one is found.
+	 *	allocated device struct if one is found.
+	 *	tlan_probe has been ported to the new net API and
+	 *	now allocates its own device structure. This function
+	 *	is also used by modules.
 	 *
 	 **************************************************************/
-	 
-extern int tlan_probe( struct net_device *dev )
+
+static int __init tlan_probe(void)
 {
-	TLanPrivateInfo	*priv;
-	static int	pad_allocated = 0;
-	int		found;
-	u8		dfn, irq, rev;
-	u32		io_base, index;
 
-	found = TLan_PciProbe( &dfn, &irq, &rev, &io_base, &index );
+	struct net_device  *dev;
+	TLanPrivateInfo    *priv;
+	static int         pad_allocated = 0;
+	u8		   dfn, irq, rev;
+	u32		   io_base, index;
+	int 		   found;
+	
+	printk(KERN_INFO "ThunderLAN driver v%d.%d:\n", 
+					TLanVersionMajor,
+					TLanVersionMinor);
+
+	TLanPadBuffer = (u8 *) kmalloc(TLAN_MIN_FRAME_SIZE, 
+					(GFP_KERNEL | GFP_DMA));
 
-	if ( ! found ) {
-		return -ENODEV;
+	if (TLanPadBuffer == NULL) {
+		printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n");
+		return -ENOMEM;
 	}
 
-	dev->priv = kmalloc( sizeof(TLanPrivateInfo), GFP_KERNEL );
-	
-	if ( dev->priv == NULL ) {
-		printk( "TLAN:  Could not allocate memory for device.\n" );
-		return  -ENOMEM;
-	}
+	memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE);
 
-	memset( dev->priv, 0, sizeof(TLanPrivateInfo) );
-
-	if ( ! pad_allocated ) {
-		TLanPadBuffer = (u8 *) kmalloc( TLAN_MIN_FRAME_SIZE, 
-//						( GFP_KERNEL | GFP_DMA )
-						( GFP_KERNEL )
-					      );
-		if ( TLanPadBuffer == NULL ) {
-			printk( "TLAN:  Could not allocate memory for padding.\n" );
-			kfree( dev->priv );
+	while((found = TLan_PciProbe( &dfn, &irq, &rev, &io_base, &index))) {
+		dev = init_etherdev(NULL, sizeof(TLanPrivateInfo));
+		if (dev == NULL) {
+			printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");
 			return -ENOMEM;
-		} else {
-			pad_allocated = 1;
-			memset( TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE );
 		}
-	}
-
-	priv = (TLanPrivateInfo *) dev->priv;
-
-	dev = init_etherdev( dev, sizeof(TLanPrivateInfo) );
-
-	dev->base_addr = io_base;
-	dev->irq = irq;
-
+		priv = dev->priv;
+		if (dev->priv == NULL) {
+			dev->priv = kmalloc(sizeof(TLanPrivateInfo), GFP_KERNEL);
+			priv = dev->priv;
+		}
+		memset(priv, 0, sizeof(TLanPrivateInfo));
+		
+		pad_allocated = 1;
+		
+		dev->base_addr = io_base;
+		dev->irq = irq;
+		priv->adapter = &TLanAdapterList[index];
+		priv->adapterRev = rev;
+		priv->aui = 	   aui;
+		
+		if ( ( duplex != 1 ) && ( duplex != 2 ) ) 
+			duplex = 0;
+		priv->duplex = duplex;
 
-	priv->adapter =    &TLanAdapterList[index];
-	priv->adapterRev = rev;
-	priv->aui =        dev->mem_start & 0x01;
-	priv->duplex =     ( ( dev->mem_start & 0x0C ) == 0x0C ) ? 0 : ( dev->mem_start & 0x0C ) >> 2;
-	priv->speed =      ( ( dev->mem_start & 0x30 ) == 0x30 ) ? 0 : ( dev->mem_start & 0x30 ) >> 4;
-	if ( priv->speed == 0x1 ) {
-		priv->speed = TLAN_SPEED_10;
-	} else if ( priv->speed == 0x2 ) {
-		priv->speed = TLAN_SPEED_100;
-	}
-	priv->sa_int =     dev->mem_start & 0x02;
-	priv->debug =      dev->mem_end;
-	spin_lock_init(&priv->lock);
-
-	printk("TLAN %d.%d:  %s irq=%2d io=%04x, %s, Rev. %d\n",
-		TLanVersionMajor,
-		TLanVersionMinor,
-		dev->name, 
-		(int) irq, 
-		io_base,
-		priv->adapter->deviceLabel,
-		priv->adapterRev );
+		if ( ( speed != 10 ) && ( speed != 100 ) )
+			speed = 0;
 
-	TLan_Init( dev );
+		priv->speed = speed;
+		priv->debug = debug;
+		spin_lock_init(&priv->lock);
+		
+		if (TLan_Init(dev)) {
+			printk(KERN_ERR "TLAN: Could not register device.\n");
+			unregister_netdev(dev);
+			kfree(dev);
+		} else {
 			
-   	return 0;
-
-} /* tlan_probe */
-
+		TLanDevicesInstalled++;
+		priv->nextDevice = TLanDevices;
+		TLanDevices = dev;
+		printk(KERN_INFO "TLAN: %s irq=%2d, io=%04x, %s, Rev. %d\n",
+				dev->name,
+				(int) dev->irq,
+				(int) dev->base_addr,
+				priv->adapter->deviceLabel,
+				priv->adapterRev);
+		}
 
-#endif /* MODULE */
+	}
+	
+	printk(KERN_INFO "TLAN: %d device(s) installed\n", TLanDevicesInstalled);
+	
+	return ((TLanDevicesInstalled > 0) ? 0 : -ENODEV);
+}
 
+/* Module loading/unloading */
+module_init(tlan_probe);
+module_exit(tlan_exit);
 
 
 
@@ -559,11 +469,6 @@
 	int	reg;
 
 
-	if ( ! pci_present() ) {
-		printk( "TLAN:   PCI Bios not present.\n" );
-		return 0;
-	}
-
 	for (; TLanAdapterList[dl_index].vendorId != 0; dl_index++) {
 
 		pdev = pci_find_device(
@@ -574,7 +479,7 @@
 
 			TLAN_DBG(
 				TLAN_DEBUG_GNRL,
-				"TLAN:  found: Vendor Id = 0x%hx, Device Id = 0x%hx\n",
+				"found: Vendor Id = 0x%hx, Device Id = 0x%hx\n",
 				TLanAdapterList[dl_index].vendorId,
 				TLanAdapterList[dl_index].deviceId
 			);
@@ -589,7 +494,7 @@
 				pci_read_config_dword( pdev, reg, pci_io_base);
 				if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) {
 					*pci_io_base &= PCI_BASE_ADDRESS_IO_MASK;
-					TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:    IO mapping is available at %x.\n", *pci_io_base);
+					TLAN_DBG( TLAN_DEBUG_GNRL, "IO mapping is available at %x.\n", *pci_io_base);
 					break;
 				} else {
 					*pci_io_base = 0;
@@ -597,7 +502,7 @@
 			}
 
 			if ( *pci_io_base == 0 )
-				printk("TLAN:    IO mapping not available, ignoring device.\n");
+				printk(KERN_INFO "TLAN:    IO mapping not available, ignoring device.\n");
 
 			pci_set_master(pdev);
 
@@ -635,7 +540,7 @@
 	 *	
 	 **************************************************************/
 
-int TLan_Init( struct net_device *dev )
+static int TLan_Init( struct net_device *dev )
 {
 	int		dma_size;
 	int		err;
@@ -643,17 +548,17 @@
 	TLanPrivateInfo	*priv;
 
 	priv = (TLanPrivateInfo *) dev->priv;
-
 	err = check_region( dev->base_addr, 0x10 );
 	if ( err ) {
-		printk( "TLAN:  %s: Io port region 0x%lx size 0x%x in use.\n",
+		printk(KERN_ERR "TLAN: %s: Io port region 0x%lx size 0x%x in use.\n",
 			dev->name,
 			dev->base_addr,
 			0x10 );
 		return -EIO;
 	}
+	
 	request_region( dev->base_addr, 0x10, TLanSignature );
-
+	
 	if ( bbuf ) {
 		dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
 	           * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE );
@@ -661,10 +566,9 @@
 		dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
 	           * ( sizeof(TLanList) );
 	}
-
-	priv->dmaStorage = kmalloc( dma_size, GFP_KERNEL | GFP_DMA );
+	priv->dmaStorage = kmalloc(dma_size, GFP_KERNEL | GFP_DMA);
 	if ( priv->dmaStorage == NULL ) {
-		printk( "TLAN:  Could not allocate lists and buffers for %s.\n",
+		printk(KERN_ERR "TLAN:  Could not allocate lists and buffers for %s.\n",
 			dev->name );
 		return -ENOMEM;
 	}
@@ -672,7 +576,6 @@
 	priv->rxList = (TLanList *) 
 		       ( ( ( (u32) priv->dmaStorage ) + 7 ) & 0xFFFFFFF8 );
 	priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;
-
 	if ( bbuf ) {
 		priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );
 		priv->txBuffer = priv->rxBuffer
@@ -685,13 +588,13 @@
 					(u8) priv->adapter->addrOfs + i,
 					(u8 *) &dev->dev_addr[i] );
 	if ( err ) {
-		printk( "TLAN:  %s: Error reading MAC from eeprom: %d\n",
+		printk(KERN_ERR "TLAN:  %s: Error reading MAC from eeprom: %d\n",
 			dev->name,
 			err );
 	}
-
 	dev->addr_len = 6;
-
+	
+	/* Device methods */
 	dev->open = &TLan_Open;
 	dev->hard_start_xmit = &TLan_StartTx;
 	dev->stop = &TLan_Close;
@@ -727,24 +630,18 @@
 {
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	int		err;
-
+	
+	MOD_INC_USE_COUNT;
+	
 	priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
-	if ( priv->sa_int ) {
-		TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:   Using SA_INTERRUPT\n" ); 
-		err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ | SA_INTERRUPT, TLanSignature, dev );
-	} else {
-		err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev );
-	}
+	err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev );
+	
 	if ( err ) {
-		printk( "TLAN:  Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq );
+		printk(KERN_ERR "TLAN:  Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq );
 		return -EAGAIN;
 	}
 	
-	MOD_INC_USE_COUNT;
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
 	/* NOTE: It might not be necessary to read the stats before a
 			 reset if you don't care what the values are.
@@ -753,7 +650,7 @@
 	TLan_ReadAndClearStats( dev, TLAN_IGNORE );
 	TLan_ResetAdapter( dev );
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Opened.  TLAN Chip Rev: %x\n", dev->name, priv->tlanRev );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Opened.  TLAN Chip Rev: %x\n", dev->name, priv->tlanRev );
 
 	return 0;
 
@@ -792,7 +689,7 @@
 	unsigned long	flags;
 
 	if ( ! priv->phyOnline ) {
-		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s PHY is not ready\n", dev->name );
+		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s PHY is not ready\n", dev->name );
 		dev_kfree_skb( skb );
 		return 0;
 	}
@@ -800,8 +697,8 @@
 	tail_list = priv->txList + priv->txTail;
 
 	if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
-		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );
-		dev->tbusy = 1;
+		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );
+		netif_stop_queue(dev);
 		priv->txBusyCount++;
 		return 1;
 	}
@@ -835,11 +732,11 @@
 	if ( ! priv->txInProgress ) {
 		priv->txInProgress = 1;
 		outw( 0x4, dev->base_addr + TLAN_HOST_INT );
-		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Starting TX on buffer %d\n", priv->txTail );
+		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Starting TX on buffer %d\n", priv->txTail );
 		outl( virt_to_bus( tail_list ), dev->base_addr + TLAN_CH_PARM );
 		outl( TLAN_HC_GO | TLAN_HC_ACK, dev->base_addr + TLAN_HOST_CMD );
 	} else {
-		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Adding buffer %d to TX channel\n", priv->txTail );
+		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Adding buffer %d to TX channel\n", priv->txTail );
 		if ( priv->txTail == 0 ) {
 			( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_list );
 		} else {
@@ -896,10 +793,6 @@
 	priv = (TLanPrivateInfo *) dev->priv;
 
 	spin_lock(&priv->lock);
-	if ( dev->interrupt ) {
-		printk( "TLAN:   Re-entering interrupt handler for %s: %ld.\n" , dev->name, dev->interrupt );
-	}
-	dev->interrupt++;
 
 	host_int = inw( dev->base_addr + TLAN_HOST_INT );
 	outw( host_int, dev->base_addr + TLAN_HOST_INT );
@@ -913,7 +806,6 @@
 		outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );
 	}
 
-	dev->interrupt--;
 	spin_unlock(&priv->lock);
 
 } /* TLan_HandleInterrupts */
@@ -940,8 +832,7 @@
 {
 	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	TLan_ReadAndClearStats( dev, TLAN_RECORD );
 	outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
@@ -949,7 +840,7 @@
 		del_timer( &priv->timer );
 	free_irq( dev->irq, dev );
 	TLan_FreeLists( dev );
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  Device %s closed.\n", dev->name );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name );
 
 	MOD_DEC_USE_COUNT;
 
@@ -983,8 +874,8 @@
 	/* Should only read stats if open ? */
 	TLan_ReadAndClearStats( dev, TLAN_RECORD );
 
-	TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  %s EOC count = %d\n", dev->name, priv->rxEocCount );
-	TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s Busy count = %d\n", dev->name, priv->txBusyCount );
+	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  %s EOC count = %d\n", dev->name, priv->rxEocCount );
+	TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s Busy count = %d\n", dev->name, priv->txBusyCount );
 	if ( debug & TLAN_DEBUG_GNRL ) {
 		TLan_PrintDio( dev->base_addr );
 		TLan_PhyPrint( dev );
@@ -1137,7 +1028,7 @@
 	TLanList	*head_list;
 	u32		ack = 1;
 
-	TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
+	TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
 	host_int = 0;
 	head_list = priv->txList + priv->txHead;
 
@@ -1155,10 +1046,10 @@
 	priv->stats.tx_bytes += head_list->frameSize;
 
 	head_list->cStat = TLAN_CSTAT_UNUSED;
-	dev->tbusy = 0;
+	netif_start_queue(dev);
 	CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
 	if ( eoc ) {
-		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
+		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
 		head_list = priv->txList + priv->txHead;
 		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
 			outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
@@ -1254,7 +1145,7 @@
 	TLanList	*tail_list;
 	void		*t;
 
-	TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  Handling RX EOF (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );
+	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  Handling RX EOF (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );
 	host_int = 0;
 	head_list = priv->rxList + priv->rxHead;
 	tail_list = priv->rxList + priv->rxTail;
@@ -1322,7 +1213,7 @@
 	CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );
 
 	if ( eoc ) { 
-		TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  Handling RX EOC (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );
+		TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  Handling RX EOC (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );
 		head_list = priv->rxList + priv->rxHead;
 		outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
 		ack |= TLAN_HC_GO | TLAN_HC_RT;
@@ -1408,7 +1299,7 @@
 
 	host_int = 0;
 	if ( priv->tlanRev < 0x30 ) {
-		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOC (Head=%d Tail=%d) -- IRQ\n", priv->txHead, priv->txTail );
+		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d) -- IRQ\n", priv->txHead, priv->txTail );
 		head_list = priv->txList + priv->txHead;
 		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
 			outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
@@ -1464,16 +1355,16 @@
 		TLan_FreeLists( dev );
 		TLan_ResetLists( dev );
 		TLan_ResetAdapter( dev );
-		dev->tbusy = 0;
+		netif_start_queue(dev);
 		ack = 0;
 	} else {
-		TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Status Check\n", dev->name );
+		TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name );
 		phy = priv->phy[priv->phyNum];
 
 		net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS );
 		if ( net_sts ) {
 			TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts );
-			TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s:    Net_Sts = %x\n", dev->name, (unsigned) net_sts );
+			TLAN_DBG( TLAN_DEBUG_GNRL, "%s:    Net_Sts = %x\n", dev->name, (unsigned) net_sts );
 		}
 		if ( ( net_sts & TLAN_NET_STS_MIRQ ) &&  ( priv->phyNum == 0 ) ) {
 			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_STS, &tlphy_sts );
@@ -1527,7 +1418,7 @@
 
 	host_int = 0;
 	if (  priv->tlanRev < 0x30 ) {
-		TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  Handling RX EOC (Head=%d Tail=%d) -- IRQ\n", priv->rxHead, priv->rxTail );
+		TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  Handling RX EOC (Head=%d Tail=%d) -- IRQ\n", priv->rxHead, priv->rxTail );
 		head_list = priv->rxList + priv->rxHead;
 		outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );
 		ack |= TLAN_HC_GO | TLAN_HC_RT;
@@ -2017,7 +1908,7 @@
 		udelay( 1000 );
 		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
 		if ( status & MII_GS_LINK ) {
-			printk( "TLAN:  %s: Link active.\n", dev->name );
+			printk( "TLAN: %s: Link active.\n", dev->name );
 			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
 		}
 	}
@@ -2042,7 +1933,7 @@
 		outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
 	} else {
 		printk( "TLAN:  %s: Link inactive, will retry in 10 secs...\n", dev->name );
-		TLan_SetTimer( dev, 1000, TLAN_TIMER_FINISH_RESET );
+		TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
 		return;
 	}
 
@@ -2190,7 +2081,7 @@
 		TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi );
 		TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo );
 		if ( ( control != 0xFFFF ) || ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) {
-			TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: PHY found at %02x %04x %04x %04x\n", phy, control, hi, lo );
+			TLAN_DBG( TLAN_DEBUG_GNRL, "PHY found at %02x %04x %04x %04x\n", phy, control, hi, lo );
 			if ( ( priv->phy[1] == TLAN_PHY_NONE ) && ( phy != TLAN_PHY_MAX_ADDR ) ) {
 				priv->phy[1] = phy;
 			}
@@ -2215,7 +2106,7 @@
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		value;
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Powering down PHY(s).\n", dev->name );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering down PHY(s).\n", dev->name );
 	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
 	TLan_MiiSync( dev->base_addr );
 	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
@@ -2228,7 +2119,7 @@
 	 * This is abitrary.  It is intended to make sure the
 	 * tranceiver settles.
 	 */
-	TLan_SetTimer( dev, (50/(1000/HZ)), TLAN_TIMER_PHY_PUP );
+	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP );
 
 } /* TLan_PhyPowerDown */
 
@@ -2240,7 +2131,7 @@
 	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;
 	u16		value;
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Powering up PHY.\n", dev->name );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering up PHY.\n", dev->name );
 	TLan_MiiSync( dev->base_addr );
 	value = MII_GC_LOOPBK;
 	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
@@ -2264,7 +2155,7 @@
 
 	phy = priv->phy[priv->phyNum];
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Reseting PHY.\n", dev->name );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name );
 	TLan_MiiSync( dev->base_addr );
 	value = MII_GC_LOOPBK | MII_GC_RESET;
 	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value );
@@ -2296,7 +2187,7 @@
 
 	phy = priv->phy[priv->phyNum];
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Trying to activate link.\n", dev->name );
+	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name );
 	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
 	if ( ( status & MII_GS_AUTONEG ) && 
 	     ( priv->duplex == TLAN_DUPLEX_DEFAULT ) && 
@@ -2325,7 +2216,7 @@
 		 * but the card need additional time to start AN.
 		 * .5 sec should be plenty extra.
 		 */
-		printk( "TLAN:  %s: Starting autonegotiation.\n", dev->name );
+		printk( "TLAN: %s: Starting autonegotiation.\n", dev->name );
 		TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_PHY_FINISH_AN );
 		return;
 	}
@@ -2334,7 +2225,7 @@
 		priv->phyNum = 0;
 		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
 		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, 4, TLAN_TIMER_PHY_PDOWN );
+		TLan_SetTimer( dev, (4*(HZ/1000)), TLAN_TIMER_PHY_PDOWN );
 		return;
 	} else if ( priv->phyNum == 0 ) {
         	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
@@ -2382,12 +2273,12 @@
 		/* Wait for 8 sec to give the process
 		 * more time.  Perhaps we should fail after a while.
 		 */
-		printk( "TLAN:  Giving autonegotiation more time.\n" );
+		printk( "TLAN: Giving autonegotiation more time.\n" );
 		TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN );
 		return;
 	}
 
-	printk( "TLAN:  %s: Autonegotiation complete.\n", dev->name );
+	printk( "TLAN: %s: Autonegotiation complete.\n", dev->name );
 	TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv );
 	TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa );
 	mode = an_adv & an_lpa & 0x03E0;
@@ -2401,7 +2292,7 @@
 		priv->phyNum = 0;
 		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
 		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, 40, TLAN_TIMER_PHY_PDOWN );
+		TLan_SetTimer( dev, (400*(HZ/1000)), TLAN_TIMER_PHY_PDOWN );
 		return;
 	}
 
@@ -2474,9 +2365,7 @@
 	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
 	sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	if ( dev->interrupt == 0 )
-		spin_lock_irqsave(&priv->lock, flags);
-	dev->interrupt++;
+	spin_lock_irqsave(&priv->lock, flags);
 
 	TLan_MiiSync(dev->base_addr);
 
@@ -2523,10 +2412,7 @@
 
 	*val = tmp;
 
-	dev->interrupt--;
-	if ( dev->interrupt == 0 )
-		spin_unlock_irqrestore(&priv->lock, flags);
-
+	spin_unlock_irqrestore(&priv->lock, flags);
 	return err;
 
 } /* TLan_MiiReadReg */
@@ -2643,9 +2529,7 @@
 	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
 	sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	if ( dev->interrupt == 0 )
-		spin_lock_irqsave(&priv->lock, flags);
-	dev->interrupt++;
+	spin_lock_irqsave(&priv->lock, flags);
 
 	TLan_MiiSync( dev->base_addr );
 
@@ -2667,10 +2551,7 @@
 	if ( minten )
 		TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
 
-	dev->interrupt--;
-	if ( dev->interrupt == 0 )
-		spin_unlock_irqrestore(&priv->lock, flags);
-
+	spin_unlock_irqrestore(&priv->lock, flags);
 } /* TLan_MiiWriteReg */
 
 
@@ -2871,9 +2752,7 @@
 	unsigned long flags = 0;
 	int ret=0;
 
-	if ( dev->interrupt == 0 )
-		spin_lock_irqsave(&priv->lock, flags);
-	dev->interrupt++;
+	spin_lock_irqsave(&priv->lock, flags);
 
 	TLan_EeSendStart( dev->base_addr );
 	err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK );
@@ -2896,15 +2775,12 @@
 		goto fail;
 	}
 	TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
-fail:
-	dev->interrupt--;
-	if ( dev->interrupt == 0 )
-		spin_unlock_irqrestore(&priv->lock, flags);
 
+fail:
+	spin_unlock_irqrestore(&priv->lock, flags);
 	return ret;
 
 } /* TLan_EeReadByte */
-
 
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/tlan.h linux/drivers/net/tlan.h
--- v2.3.42/linux/drivers/net/tlan.h	Tue Jan 11 22:31:40 2000
+++ linux/drivers/net/tlan.h	Mon Feb  7 09:53:21 2000
@@ -45,7 +45,7 @@
 #define TLAN_IGNORE		0
 #define TLAN_RECORD		1
 
-#define TLAN_DBG(lvl, format, args...)	if (debug&lvl) printk( format, ##args );
+#define TLAN_DBG(lvl, format, args...)	if (debug&lvl) printk(KERN_DEBUG "TLAN: " format, ##args );
 #define TLAN_DEBUG_GNRL		0x0001
 #define TLAN_DEBUG_TX		0x0002
 #define TLAN_DEBUG_RX		0x0004 
@@ -182,7 +182,6 @@
 	u32			duplex;
 	u32			phy[2];
 	u32			phyNum;
-	u32			sa_int;
 	u32			speed;
 	u8			tlanRev;
 	u8			tlanFullDuplex;
diff -u --recursive --new-file v2.3.42/linux/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c
--- v2.3.42/linux/drivers/net/tokenring/smctr.c	Fri Jan 28 15:09:07 2000
+++ linux/drivers/net/tokenring/smctr.c	Thu Feb 10 12:32:43 2000
@@ -3684,13 +3684,7 @@
                 int ioaddr = smctr_portlist[i];
                 if(check_region(ioaddr, SMCTR_IO_EXTENT))
                         continue;
-                if(smctr_probe1(dev, ioaddr))
-                {
-#ifndef MODULE
-                        tr_freedev(dev);
-#endif
-                }
-                else
+                if (!smctr_probe1(dev, ioaddr))
                         return (0);
         }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.3.42/linux/drivers/net/tulip.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/net/tulip.c	Thu Feb 10 12:28:01 2000
@@ -75,6 +75,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -101,10 +102,6 @@
 #define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
 #endif
 
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-
 /* This my implementation of shared IRQs, now only used for 1.2.13. */
 #ifdef HAVE_SHARED_IRQ
 #define USE_SHARED_IRQ
@@ -368,16 +365,9 @@
 	u32 setup_frame[48];		/* Pseudo-Tx frame to init address table. */
 	int chip_id;
 	int revision;
-#if LINUX_VERSION_CODE > 0x20139
 	struct net_device_stats stats;
-#else
-	struct enet_statistics stats;
-#endif
 	struct timer_list timer;	/* Media selection timer. */
-	int interrupt;				/* In-interrupt flag. */
-#ifdef SMP_CHECK
-	int smp_proc_id;			/* Which processor in IRQ handler. */
-#endif
+	spinlock_t tx_lock;       
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
@@ -435,7 +425,7 @@
    This allows the probe routine to use the old driver initialization
    interface. */
 
-int tulip_probe(void)
+static int __init tulip_probe(void)
 {
 	int cards_found = 0;
 	static int pci_index = 0;	/* Static, for multiple probe calls. */
@@ -446,17 +436,13 @@
 	   well with the current structure.  So instead we detect just the
 	   Tulip cards in slot order. */
 
-#if LINUX_VERSION_CODE >= 0x20155
 	if (! pci_present())
 		return -ENODEV;
-#else
-	if (! pcibios_present())
-		return -ENODEV;
-#endif
 	for (;pci_index < 0xff; pci_index++) {
 		u16 vendor, device, pci_command, new_command;
 		unsigned long pci_ioaddr = 0;
 		int chip_idx = 0;
+		struct pci_dev *pdev;
 
 		if (pcibios_find_class
 			(PCI_CLASS_NETWORK_ETHERNET << 8,
@@ -468,10 +454,10 @@
 			else
 				break;
 		}
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
+		
+		pdev = pci_find_slot (pci_bus, pci_device_fn);
+		vendor = pdev->vendor;
+		device = pdev->device;
 
 		for (chip_idx = 0; tulip_tbl[chip_idx].chip_name; chip_idx++)
 			if (vendor == tulip_tbl[chip_idx].vendor_id  &&
@@ -485,12 +471,7 @@
 					   vendor, device);
 			continue;
 		}
-#if LINUX_VERSION_CODE >= 0x20155
 		pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start;
-#else
-		pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0,
-								  &pci_ioaddr);
-#endif
 		/* Remove I/O space marker in bit 0. */
 		pci_ioaddr &= ~3;
 
@@ -501,37 +482,32 @@
 		if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size))
 			continue;
 
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_COMMAND, &pci_command);
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled this"
 				   " device!  Updating PCI command %4.4x->%4.4x.\n",
 				   pci_command, new_command);
-			pcibios_write_config_word(pci_bus, pci_device_fn,
-									  PCI_COMMAND, new_command);
+			pci_write_config_word(pdev, PCI_COMMAND, new_command);
 		}
 
 		if(tulip_probe1(pci_bus, pci_device_fn, chip_idx, cards_found))
 		{
 			/* Get and check the bus-master and latency values. */
 			unsigned char pci_latency;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_LATENCY_TIMER, &pci_latency);
+			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 			if (pci_latency < 10) {
 				printk(KERN_INFO "  PCI latency timer (CFLT) is "
 					   "unreasonably low at %d.  Setting to 64 clocks.\n",
 					   pci_latency);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										  PCI_LATENCY_TIMER, 64);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 			} else if (tulip_debug > 1)
 				printk(KERN_INFO "  PCI latency timer (CFLT) is %#x, "
 					   " PCI command is %4.4x.\n",
 					   pci_latency, new_command);
 			/* Bring the 21143 out power-down mode. */
 			if (device == PCI_DEVICE_ID_DEC_TULIP_21142)
-				pcibios_write_config_dword(pci_bus, pci_device_fn,
-										   0x40, 0x40000000);
+				pci_write_config_dword(pdev, 0x40, 0x40000000);
 			cards_found++;
 		}
 	}
@@ -753,6 +729,8 @@
 	/* The Tulip-specific entries in the device structure. */
 	dev->open = &tulip_open;
 	dev->hard_start_xmit = &tulip_start_xmit;
+	dev->tx_timeout = &tulip_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->stop = &tulip_close;
 	dev->get_stats = &tulip_get_stats;
 #ifdef HAVE_PRIVATE_IOCTL
@@ -1216,9 +1194,7 @@
 	/* When a module we don't have 'x86' to check. */
 	outl(0x01A00000 | 0x4800, ioaddr + CSR0);
 #else
-#if (LINUX_VERSION_CODE > 0x2014c)
 #define x86 boot_cpu_data.x86
-#endif
 	outl(0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0);
 	if (x86 <= 4)
 	  printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache "
@@ -1249,6 +1225,7 @@
 
 	MOD_INC_USE_COUNT;
 
+    spin_lock_init(&tp->tx_lock);
 	tulip_init_ring(dev);
 
 	/* This is set_rx_mode(), but without starting the transmitter. */
@@ -1329,10 +1306,6 @@
 	outl(tp->csr6, ioaddr + CSR6);
 	outl(tp->csr6 | 0x2000, ioaddr + CSR6);
 
-	dev->tbusy = 0;
-	tp->interrupt = 0;
-	dev->start = 1;
-
 	/* Enable interrupts by setting the interrupt mask. */
 	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
 	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
@@ -1352,6 +1325,8 @@
 	tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
 	add_timer(&tp->timer);
 
+	netif_start_queue(dev);
+
 	return 0;
 }
 
@@ -1958,9 +1933,13 @@
   struct tulip_private *tp = (struct tulip_private *)dev->priv;
   long ioaddr = dev->base_addr;
 
+  printk("%s: transmit timed out\n", dev->name);
+
   if (media_cap[dev->if_port] & MediaIsMII) {
 	  /* Do nothing -- the media monitor should handle this. */
+#if 0
 	  if (tulip_debug > 1)
+#endif
 		  printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
 				 dev->name);
 	  dev->trans_start = jiffies;
@@ -2090,19 +2069,13 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int entry;
 	u32 flag;
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		tulip_tx_timeout(dev);
-		return 1;
-	}
+	unsigned long cpuflags;
 
 	/* Caution: the write order is important here, set the base address
 	   with the "ownership" bits last. */
 
+	spin_lock_irqsave(&tp->tx_lock, cpuflags);
+
 	/* Calculate the next Tx descriptor entry. */
 	entry = tp->cur_tx % TX_RING_SIZE;
 
@@ -2111,17 +2084,15 @@
 
 	if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
 	  flag = 0x60000000; /* No interrupt */
-	  dev->tbusy = 0;
 	} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
 	  flag = 0xe0000000; /* Tx-done intr. */
-	  dev->tbusy = 0;
 	} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
 	  flag = 0x60000000; /* No Tx-done intr. */
-	  dev->tbusy = 0;
 	} else {
 	  /* Leave room for set_rx_mode() to fill entries. */
 	  flag = 0xe0000000; /* Tx-done intr. */
 	  tp->tx_full = 1;
+	  netif_stop_queue(dev);
 	}
 	if (entry == TX_RING_SIZE-1)
 		flag |= 0xe2000000;
@@ -2129,6 +2100,8 @@
 	tp->tx_ring[entry].length = skb->len | flag;
 	tp->tx_ring[entry].status = 0x80000000;	/* Pass ownership to the chip. */
 	tp->cur_tx++;
+	spin_unlock_irqrestore(&tp->tx_lock, cpuflags);
+
 	/* Trigger an immediate transmit demand. */
 	outl(0, dev->base_addr + CSR1);
 
@@ -2159,20 +2132,6 @@
 
 	ioaddr = dev->base_addr;
 	tp = (struct tulip_private *)dev->priv;
-	if (test_and_set_bit(0, (void*)&tp->interrupt)) {
-#ifdef SMP_CHECK
-		printk(KERN_ERR "%s: Re-entering the interrupt handler with proc %d,"
-			   " proc %d already handling.\n", dev->name,
-			   tp->smp_proc_id, smp_processor_id());
-#else
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-#endif
-		return;
-	}
-	dev->interrupt = 1;
-#ifdef SMP_CHECK
-	tp->smp_proc_id = smp_processor_id();
-#endif
 
 	do {
 		csr5 = inl(ioaddr + CSR5);
@@ -2189,6 +2148,8 @@
 		if (csr5 & (RxIntr | RxNoBuf))
 			work_budget -= tulip_rx(dev);
 
+		spin_lock(&tp->tx_lock);
+
 		if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
 			unsigned int dirty_tx;
 
@@ -2224,19 +2185,13 @@
 #ifdef ETHER_STATS
 					if (status & 0x0001) tp->stats.tx_deferred++;
 #endif
-#if LINUX_VERSION_CODE > 0x20127
 					tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
-#endif
 					tp->stats.collisions += (status >> 3) & 15;
 					tp->stats.tx_packets++;
 				}
 
 				/* Free the original skb. */
-#if (LINUX_VERSION_CODE > 0x20155)
-				dev_kfree_skb(tp->tx_skbuff[entry]);
-#else
-				dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE);
-#endif
+				dev_kfree_skb_irq(tp->tx_skbuff[entry]);
 				tp->tx_skbuff[entry] = 0;
 			}
 
@@ -2248,15 +2203,14 @@
 			}
 #endif
 
-			if (tp->tx_full && dev->tbusy
-				&& tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2) {
+			if (tp->tx_full && tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2) {
 				/* The ring is no longer full, clear tbusy. */
 				tp->tx_full = 0;
-				dev->tbusy = 0;
-				mark_bh(NET_BH);
+				netif_wake_queue(dev);
 			}
 
 			tp->dirty_tx = dirty_tx;
+
 			if (csr5 & TxDied) {
 				if (tulip_debug > 1)
 					printk(KERN_WARNING "%s: The transmitter stopped!"
@@ -2266,6 +2220,7 @@
 				outl(tp->csr6 | 0x2002, ioaddr + CSR6);
 			}
 		}
+		spin_unlock(&tp->tx_lock);
 
 		/* Log errors. */
 		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
@@ -2316,8 +2271,6 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
 			   dev->name, inl(ioaddr + CSR5));
 
-	dev->interrupt = 0;
-	clear_bit(0, (void*)&tp->interrupt);
 	return;
 }
 
@@ -2397,9 +2350,7 @@
 			netif_rx(skb);
 			dev->last_rx = jiffies;
 			tp->stats.rx_packets++;
-#if LINUX_VERSION_CODE > 0x20127
 			tp->stats.rx_bytes += pkt_len;
-#endif
 		}
 		entry = (++tp->cur_rx) % RX_RING_SIZE;
 	}
@@ -2429,8 +2380,7 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (tulip_debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
@@ -2463,23 +2413,12 @@
 		tp->rx_ring[i].length = 0;
 		tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
 		if (skb) {
-#if LINUX_VERSION_CODE < 0x20100
-			skb->free = 1;
-#endif
-#if (LINUX_VERSION_CODE > 0x20155)
 			dev_kfree_skb(skb);
-#else
-			dev_kfree_skb(skb, FREE_WRITE);
-#endif
 		}
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (tp->tx_skbuff[i])
-#if (LINUX_VERSION_CODE > 0x20155)
 			dev_kfree_skb(tp->tx_skbuff[i]);
-#else
-			dev_kfree_skb(tp->tx_skbuff[i], FREE_WRITE);
-#endif
 		tp->tx_skbuff[i] = 0;
 	}
 
@@ -2495,7 +2434,7 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
 
-	if (dev->start)
+	if (test_bit(LINK_STATE_START, &dev->state))
 		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
 
 	return &tp->stats;
@@ -2601,6 +2540,7 @@
 	long ioaddr = dev->base_addr;
 	int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	unsigned long cpuflags;
 
 	tp->csr6 &= ~0x00D5;
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
@@ -2660,13 +2600,12 @@
 			*setup_frm++ = eaddrs[2];
 		} while (++i < 15);
 		/* Now add this frame to the Tx list. */
+		spin_lock_irqsave(&tp->tx_lock, cpuflags);
 		if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
 			/* Same setup recently queued, we need not add it. */
 		} else {
-			unsigned long flags;
 			unsigned int entry, dummy = 0;
 
-			save_flags(flags); cli();
 			entry = tp->cur_tx++ % TX_RING_SIZE;
 
 			if (entry != 0) {
@@ -2688,12 +2627,12 @@
 			tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
 			tp->tx_ring[entry].status = 0x80000000;
 			if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
-				dev->tbusy = 1;
+				netif_stop_queue(dev);
 				tp->tx_full = 1;
 			}
 			if (dummy >= 0)
 				tp->tx_ring[dummy].status = DescOwned;
-			restore_flags(flags);
+			spin_unlock_irqrestore(&tp->tx_lock, cpuflags);
 			/* Trigger an immediate transmit demand. */
 			outl(0, ioaddr + CSR1);
 		}
@@ -2711,12 +2650,14 @@
 	u32 io;
 	u8 bus, devfn;
 	struct net_device *dev;
+	struct pci_dev *pdev;
 
 	if (loc->bus != LOC_PCI) return NULL;
-	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+	pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+	if (!pdev) return NULL;
 	printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn);
-	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
-	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	io = pdev->resource[0].start;
+	dev_id = pdev->device;
 	io &= ~3;
 	dev = tulip_probe1(bus, devfn, DC21142, -1);
 	if (dev) {
@@ -2753,9 +2694,6 @@
 
 #endif  /* Cardbus support */
 
-
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
 MODULE_PARM(debug, "i");
@@ -2764,13 +2702,11 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
 
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 
-int
-init_module(void)
+static int __init tulip_init_module (void)
 {
 	if (debug >= 0)
 		tulip_debug = debug;
@@ -2783,8 +2719,7 @@
 #endif
 }
 
-void
-cleanup_module(void)
+static void __exit tulip_cleanup_module (void)
 {
 	struct net_device *next_dev;
 
@@ -2802,8 +2737,10 @@
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(tulip_init_module);
+module_exit(tulip_cleanup_module);
+
+
 /*
  * Local variables:
  *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- v2.3.42/linux/drivers/net/via-rhine.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/net/via-rhine.c	Thu Feb 10 12:28:01 2000
@@ -66,7 +66,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
@@ -77,6 +76,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -109,10 +109,6 @@
 
 #define RUN_AT(x) (jiffies + (x))
 
-#ifdef MODULE
-char kernel_version[] = UTS_RELEASE;
-#endif
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
@@ -121,27 +117,6 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#else
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
-/* Grrrr, the PCI code changed, but did not consider CardBus... */
-#include <linux/bios32.h>
-#define PCI_SUPPORT_VER1
-#else
-#define PCI_SUPPORT_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-#endif
 
 
 /*
@@ -248,10 +223,10 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct net_device *via_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
+static struct net_device *via_probe1(struct pci_dev *pdev, long ioaddr, int irq,
 								 int chp_idx, int fnd_cnt);
 
 static struct pci_id_info pci_tbl[] = {
@@ -343,7 +318,7 @@
 	struct net_device *next_module;			/* Link for devices of this type. */
 	struct net_device_stats stats;
 	struct timer_list timer;	/* Media monitoring timer. */
-	unsigned char pci_bus, pci_devfn;
+	spinlock_t lock;
 	/* Frequently used values: keep some adjacent for cache effect. */
 	int chip_id;
 	long in_interrupt;			/* Word-long for SMP locks. */
@@ -398,23 +373,22 @@
 	unsigned char pci_bus, pci_device_fn;
 	struct net_device *dev;
 
-	if ( ! pcibios_present())
-		return -ENODEV;
-
 	for (;pci_index < 0xff; pci_index++) {
 		u16 vendor, device, pci_command, new_command;
 		int chip_idx, irq;
 		long pciaddr;
 		long ioaddr;
+		struct pci_dev *pdev;
 
 		if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
 								&pci_bus, &pci_device_fn)
 			!= PCIBIOS_SUCCESSFUL)
 			break;
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
+		
+		pdev = pci_find_slot (pci_bus, pci_device_fn);
+		if (!pdev) continue;
+		vendor = pdev->vendor;
+		device = pdev->device;
 
 		for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
 			if (vendor == pci_tbl[chip_idx].vendor_id
@@ -424,32 +398,12 @@
 		if (pci_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
 			continue;
 
-		{
-#if defined(PCI_SUPPORT_VER2)
-			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
 #ifdef VIA_USE_IO
-			pciaddr = pdev->resource[0].start;
+		pciaddr = pdev->resource[0].start;
 #else
-			pciaddr = pdev->resource[1].start;
+		pciaddr = pdev->resource[1].start;
 #endif
-			irq = pdev->irq;
-#else
-			u32 pci_memaddr;
-			u8 pci_irq_line;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_INTERRUPT_LINE, &pci_irq_line);
-#ifdef VIA_USE_IO
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_0, &pci_memaddr);
-			pciaddr = pci_memaddr;
-#else
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_1, &pci_memaddr);
-			pciaddr = pci_memaddr;
-#endif
-			irq = pci_irq_line;
-#endif
-		}
+		irq = pdev->irq;
 
 		if (debug > 2)
 			printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n",
@@ -466,30 +420,25 @@
 			continue;
 		}
 
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_COMMAND, &pci_command);
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 		new_command = pci_command | (pci_tbl[chip_idx].flags & 7);
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled the"
 				   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
-				   pci_bus, pci_device_fn, pci_command, new_command);
-			pcibios_write_config_word(pci_bus, pci_device_fn,
-									  PCI_COMMAND, new_command);
+				   pdev->bus->number, pdev->devfn, pci_command, new_command);
+			pci_write_config_word(pdev, PCI_COMMAND, new_command);
 		}
 
-		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr,
-									   irq, chip_idx, cards_found);
+		dev = pci_tbl[chip_idx].probe1(pdev, ioaddr, irq, chip_idx, cards_found);
 
 		if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
 			u8 pci_latency;
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_LATENCY_TIMER, &pci_latency);
+			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 			if (pci_latency < min_pci_latency) {
 				printk(KERN_INFO "  PCI latency timer (CFLT) is "
 					   "unreasonably low at %d.  Setting to %d clocks.\n",
 					   pci_latency, min_pci_latency);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										  PCI_LATENCY_TIMER, min_pci_latency);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency);
 			}
 		}
 		dev = 0;
@@ -499,17 +448,10 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-#ifndef MODULE
-int via_rhine_probe(void)
-{
-	printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
-	return pci_etherdev_probe(pci_tbl);
-}
-#endif
 
-static struct net_device *via_probe1(int pci_bus, int pci_devfn,
-								 long ioaddr, int irq,
-								 int chip_id, int card_idx)
+static struct net_device *via_probe1(struct pci_dev *pdev,
+					 long ioaddr, int irq,
+					 int chip_id, int card_idx)
 {
 	struct net_device *dev;
 	struct netdev_private *np;
@@ -522,6 +464,14 @@
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, pci_tbl[chip_id].name, ioaddr);
 
+#ifdef VIA_USE_IO
+	if (!request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name)) {
+		unregister_netdev (dev);
+		kfree (dev);
+		return NULL;
+	}
+#endif
+
 	/* Ideally we would be read the EEPROM but access may be locked. */
 	for (i = 0; i <6; i++)
 		dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
@@ -529,10 +479,6 @@
 			printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
 
-#ifdef VIA_USE_IO
-	request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name);
-#endif
-
 	/* Reset the chip to erase previous misconfiguration. */
 	writew(CmdReset, ioaddr + ChipCmd);
 
@@ -548,8 +494,7 @@
 	np->next_module = root_net_dev;
 	root_net_dev = dev;
 
-	np->pci_bus = pci_bus;
-	np->pci_devfn = pci_devfn;
+	np->lock = SPIN_LOCK_UNLOCKED;
 	np->chip_id = chip_id;
 
 	if (dev->mem_start)
@@ -576,6 +521,8 @@
 	dev->get_stats = &get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &mii_ioctl;
+	dev->tx_timeout = tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 
 	if (cap_tbl[np->chip_id].flags & CanHaveMII) {
 		int phy, phy_idx = 0;
@@ -671,14 +618,11 @@
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
+	netif_start_queue(dev);
 	np->in_interrupt = 0;
 
 	set_rx_mode(dev);
 
-	dev->start = 1;
-
 	/* Enable interrupts by setting the interrupt mask. */
 	writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow| IntrRxDropped|
 		   IntrTxDone | IntrTxAbort | IntrTxUnderrun |
@@ -824,15 +768,6 @@
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	unsigned entry;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		tx_timeout(dev);
-		return 1;
-	}
-
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
 
@@ -862,7 +797,7 @@
 	writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
 
 	if (np->cur_tx - np->dirty_tx < TX_RING_SIZE - 1)
-		clear_bit(0, (void*)&dev->tbusy);		/* Typical path */
+		netif_start_queue(dev);		/* Typical path */
 	else
 		np->tx_full = 1;
 	dev->trans_start = jiffies;
@@ -884,21 +819,8 @@
 
 	ioaddr = dev->base_addr;
 	np = (struct netdev_private *)dev->priv;
-#if defined(__i386__)
-	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-			   dev->name);
-		dev->interrupt = 0;	/* Avoid halting machine. */
-		return;
-	}
-#else
-	if (dev->interrupt) {
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
-	dev->interrupt = 1;
-#endif
+	
+	spin_lock (&np->lock);
 
 	do {
 		u32 intr_status = readw(ioaddr + IntrStatus);
@@ -936,30 +858,22 @@
 				if (txstatus & 0x0100) np->stats.tx_aborted_errors++;
 				if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++;
 				if (txstatus & 0x0002) np->stats.tx_fifo_errors++;
-#ifdef ETHER_STATS
-				if (txstatus & 0x0100) np->stats.collisions16++;
-#endif
 				/* Transmitter restarted in 'abnormal' handler. */
 			} else {
-#ifdef ETHER_STATS
-				if (txstatus & 0x0001) np->stats.tx_deferred++;
-#endif
 				np->stats.collisions += (txstatus >> 3) & 15;
-#if defined(NETSTATS_VER2)
 				np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff;
-#endif
 				np->stats.tx_packets++;
 			}
 			/* Free the original skb. */
-			dev_free_skb(np->tx_skbuff[entry]);
+			kfree_skb(np->tx_skbuff[entry]);
 			np->tx_skbuff[entry] = 0;
 		}
-		if (np->tx_full && dev->tbusy
-			&& np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
+		if (np->tx_full &&
+		    test_bit(LINK_STATE_XOFF, &dev->flags) &&
+		    np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
 			/* The ring is no longer full, clear tbusy. */
 			np->tx_full = 0;
-			clear_bit(0, (void*)&dev->tbusy);
-			mark_bh(NET_BH);
+			netif_wake_queue (dev);
 		}
 
 		/* Abnormal error summary/uncommon events handlers. */
@@ -979,12 +893,7 @@
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, readw(ioaddr + IntrStatus));
 
-#if defined(__i386__)
-	clear_bit(0, (void*)&dev->interrupt);
-#else
-	dev->interrupt = 0;
-#endif
-	return;
+	spin_unlock (&np->lock);
 }
 
 /* This routine is logically part of the interrupt handler, but isolated
@@ -1217,8 +1126,7 @@
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
@@ -1239,16 +1147,13 @@
 		np->rx_ring[i].rx_length = 0;
 		np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
 		if (np->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
-			np->rx_skbuff[i]->free = 1;
-#endif
-			dev_free_skb(np->rx_skbuff[i]);
+			kfree_skb(np->rx_skbuff[i]);
 		}
 		np->rx_skbuff[i] = 0;
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (np->tx_skbuff[i])
-			dev_free_skb(np->tx_skbuff[i]);
+			kfree_skb(np->tx_skbuff[i]);
 		np->tx_skbuff[i] = 0;
 	}
 
@@ -1257,9 +1162,7 @@
 	return 0;
 }
 
-
-#ifdef MODULE
-int init_module(void)
+static int __init via_rhine_init_module (void)
 {
 	if (debug)					/* Emit version even if no cards detected. */
 		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
@@ -1271,7 +1174,7 @@
 #endif
 }
 
-void cleanup_module(void)
+static void __exit via_rhine_cleanup_module (void)
 {
 
 #ifdef CARDBUS
@@ -1296,8 +1199,10 @@
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(via_rhine_init_module);
+module_exit(via_rhine_cleanup_module);
+
+
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c via-rhine.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
diff -u --recursive --new-file v2.3.42/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c
--- v2.3.42/linux/drivers/net/wan/cosa.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/net/wan/cosa.c	Wed Feb  9 11:42:35 2000
@@ -313,23 +313,16 @@
 #endif
 
 static struct file_operations cosa_fops = {
-	cosa_lseek,
-	cosa_read,
-	cosa_write,
-	NULL,	/* readdir */
-	cosa_poll,
-	cosa_chardev_ioctl,
-	NULL,	/* mmap */
-	cosa_open,
-	NULL,	/* flush */
-	cosa_release,
-	NULL,	/* fsync */
+	llseek:		cosa_lseek,
+	read:		cosa_read,
+	write:		cosa_write,
+	poll:		cosa_poll,
+	ioctl:		cosa_chardev_ioctl,
+	open:		cosa_open,
+	release:	cosa_release,
 #ifdef COSA_FASYNC_WORKING
-	cosa_fasync,
-#else
-	NULL,
+	fasync:		cosa_fasync,
 #endif
-	NULL	/* lock */
 };
 
 /* Ioctls */
diff -u --recursive --new-file v2.3.42/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- v2.3.42/linux/drivers/net/yellowfin.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/net/yellowfin.c	Thu Feb 10 12:28:01 2000
@@ -74,6 +74,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/unaligned.h>
@@ -83,27 +84,9 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-/* Kernel compatibility defines, most common to the PCCard package. */
-#include <linux/version.h>		/* Evil and unneccessary */
-
 #define RUN_AT(x) (jiffies + (x))
 
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define	net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20155
-#define PCI_SUPPORT_VER1
-#define pci_present pcibios_present
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
 #define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
 
 /* The PCI I/O space extent. */
 #define YELLOWFIN_TOTAL_SIZE 0x100
@@ -280,9 +263,9 @@
 	struct tx_status_words tx_status[TX_RING_SIZE];
 	struct timer_list timer;	/* Media selection timer. */
 	struct enet_statistics stats;
+	spinlock_t lock;
 	/* Frequently used and paired value: keep adjacent for cache effect. */
 	int chip_id;
-	int in_interrupt;
 	struct yellowfin_desc *rx_head_desc;
 	struct tx_status_words *tx_tail_desc;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
@@ -300,9 +283,6 @@
 	u32 pad[4];							/* Used for 32-byte alignment */
 };
 
-#ifdef MODULE
-
-#if LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
 MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
@@ -312,9 +292,6 @@
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
-
-#endif
 
 static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, int options);
 static int read_eeprom(long ioaddr, int location);
@@ -340,7 +317,7 @@
 /* A list of all installed Yellowfin devices, for removing the driver module. */
 static struct net_device *root_yellowfin_dev = NULL;
 
-int yellowfin_probe(void)
+static int __init yellowfin_probe(void)
 {
 	int cards_found = 0;
 	int pci_index = 0;
@@ -355,6 +332,7 @@
 		int chip_idx;
 		int irq;
 		long ioaddr;
+		struct pci_dev *pdev;
 
 		if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
 								pci_index,
@@ -362,10 +340,10 @@
 			!= PCIBIOS_SUCCESSFUL)
 			break;
 
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_VENDOR_ID, &vendor);
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_DEVICE_ID, &device);
+		pdev = pci_find_slot (pci_bus, pci_device_fn);
+		if (!pdev) break;
+		vendor = pdev->vendor;
+		device = pdev->device;
 
 		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
 			if (vendor == chip_tbl[chip_idx].vendor_id
@@ -388,28 +366,24 @@
 		if (check_region(ioaddr, YELLOWFIN_TOTAL_SIZE))
 			continue;
 
-		pcibios_read_config_word(pci_bus, pci_device_fn,
-								 PCI_COMMAND, &pci_command);
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
 		if (pci_command != new_command) {
 			printk(KERN_INFO "  The PCI BIOS has not enabled the"
 				   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
 				   pci_bus, pci_device_fn, pci_command, new_command);
-			pcibios_write_config_word(pci_bus, pci_device_fn,
-									  PCI_COMMAND, new_command);
+			pci_write_config_word(pdev, PCI_COMMAND, new_command);
 		}
 
 		if(yellowfin_probe1(ioaddr, irq, chip_idx, cards_found))
 		{
 			/* Get and check the bus-master and latency values. */
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_LATENCY_TIMER, &pci_latency);
+			pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 			if (pci_latency < min_pci_latency) {
 				printk(KERN_INFO "  PCI latency timer (CFLT) is "
 					   "unreasonably low at %d.  Setting to %d clocks.\n",
 					   pci_latency, min_pci_latency);
-				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										  PCI_LATENCY_TIMER, min_pci_latency);
+				pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency);
 			} else if (yellowfin_debug > 1)
 				printk(KERN_INFO "  PCI latency timer (CFLT) is %#x.\n",
 					   pci_latency);
@@ -465,6 +439,7 @@
 	root_yellowfin_dev = dev;
 
 	yp->chip_id = chip_id;
+	yp->lock = SPIN_LOCK_UNLOCKED;
 
 	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 	if (dev->mem_start)
@@ -493,6 +468,9 @@
 #ifdef HAVE_PRIVATE_IOCTL
 	dev->do_ioctl = &mii_ioctl;
 #endif
+	dev->tx_timeout = yellowfin_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
 	if (mtu)
 		dev->mtu = mtu;
 
@@ -602,9 +580,7 @@
 	if (dev->if_port == 0)
 		dev->if_port = yp->default_port;
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	yp->in_interrupt = 0;
+	netif_start_queue(dev);
 
 	/* Setting the Rx mode will start the Rx process. */
 	if (yp->chip_id == 0) {
@@ -618,8 +594,6 @@
 	}
 	set_rx_mode(dev);
 
-	dev->start = 1;
-
 	/* Enable interrupts by setting the interrupt mask. */
 	outw(0x81ff, ioaddr + IntrEnb);			/* See enum intr_status_bits */
 	outw(0x0000, ioaddr + EventStatus);		/* Clear non-interrupting events */
@@ -787,15 +761,6 @@
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	unsigned entry;
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		yellowfin_tx_timeout(dev);
-		return 1;
-	}
-
 	/* Caution: the write order is important here, set the base address
 	   with the "ownership" bits last. */
 
@@ -840,7 +805,7 @@
 	outl(0x10001000, dev->base_addr + TxCtrl);
 
 	if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1)
-		clear_bit(0, (void*)&dev->tbusy);		/* Typical path */
+		netif_start_queue(dev);		/* Typical path */
 	else
 		yp->tx_full = 1;
 	dev->trans_start = jiffies;
@@ -869,11 +834,8 @@
 
 	ioaddr = dev->base_addr;
 	yp = (struct yellowfin_private *)dev->priv;
-	if (test_and_set_bit(0, (void*)&yp->in_interrupt)) {
-		dev->interrupt = 1;
-		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-		return;
-	}
+	
+	spin_lock (&yp->lock);
 
 	do {
 		u16 intr_status = inw(ioaddr + IntrClear);
@@ -900,12 +862,12 @@
 			yp->tx_skbuff[entry] = 0;
 			yp->stats.tx_packets++;
 		}
-		if (yp->tx_full && dev->tbusy
-			&& yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) {
+		if (yp->tx_full &&
+		    test_bit(LINK_STATE_XOFF, &dev->flags) &&
+		    yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) {
 			/* The ring is no longer full, clear tbusy. */
 			yp->tx_full = 0;
-			clear_bit(0, (void*)&dev->tbusy);
-			mark_bh(NET_BH);
+			netif_wake_queue (dev);
 		}
 #else
 		if (intr_status & IntrTxDone
@@ -973,12 +935,12 @@
 			}
 #endif
 
-			if (yp->tx_full && dev->tbusy
-				&& yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
+			if (yp->tx_full &&
+			    test_bit(LINK_STATE_XOFF, &dev->flags) &&
+			    yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
 				/* The ring is no longer full, clear tbusy. */
 				yp->tx_full = 0;
-				clear_bit(0, (void*)&dev->tbusy);
-				mark_bh(NET_BH);
+				netif_wake_queue (dev);
 			}
 
 			yp->dirty_tx = dirty_tx;
@@ -1004,15 +966,14 @@
 	/* Code that should never be run!  Perhaps remove after testing.. */
 	{
 		static int stopit = 10;
-		if (dev->start == 0  &&  --stopit < 0) {
+		if ((!test_bit(LINK_STATE_START, &dev->state))  &&  --stopit < 0) {
 			printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
 				   dev->name);
 			free_irq(irq, dev);
 		}
 	}
 
-	dev->interrupt = 0;
-	clear_bit(0, (void*)&yp->in_interrupt);
+	spin_lock (&yp->lock);
 	return;
 }
 
@@ -1171,8 +1132,7 @@
 	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
 	int i;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 
 	if (yellowfin_debug > 1) {
 		printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",
@@ -1233,9 +1193,6 @@
 		yp->rx_ring[i].cmd = CMD_STOP;
 		yp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
 		if (yp->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
-			yp->rx_skbuff[i]->free = 1;
-#endif
 			DEV_FREE_SKB(yp->rx_skbuff[i]);
 		}
 		yp->rx_skbuff[i] = 0;
@@ -1358,13 +1315,11 @@
 }
 #endif  /* HAVE_PRIVATE_IOCTL */
 
-
-#ifdef MODULE
 
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 
-int init_module(void)
+static int __init yellowfin_init_module(void)
 {
 	if (debug >= 0)
 		yellowfin_debug = debug;
@@ -1372,7 +1327,7 @@
 	return yellowfin_probe();
 }
 
-void cleanup_module(void)
+static void __exit yellowfin_cleanup_module (void)
 {
 	struct net_device *next_dev;
 
@@ -1386,8 +1341,10 @@
 	}
 }
 
-#endif  /* MODULE */
-
+module_init(yellowfin_init_module);
+module_exit(yellowfin_cleanup_module);
+
+
 /*
  * Local variables:
  *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
diff -u --recursive --new-file v2.3.42/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- v2.3.42/linux/drivers/parport/ieee1284_ops.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/parport/ieee1284_ops.c	Wed Feb  9 19:51:24 2000
@@ -257,7 +257,7 @@
 		if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
 			port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
 			DPRINTK (KERN_DEBUG
-				 "%s: No more byte data (%d bytes)\n",
+				 "%s: No more byte data (%Zd bytes)\n",
 				 port->name, count);
 
 			/* Go to reverse idle phase. */
@@ -735,23 +735,29 @@
 			      PARPORT_CONTROL_SELECT);
 	port->ops->data_forward (port);
 	for (; len > 0; len--, bp++) {
+		/* Event 62: Write data and strobe data */
 		parport_write_data (port, *bp);
-
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-					     PARPORT_STATUS_BUSY))
-			break;
-
-		/* Strobe data */
 		parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
 				      PARPORT_CONTROL_AUTOFD);
 
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+		/* Event 58 */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 10))
 			break;
 
+		/* Event 63 */
 		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+
+		/* Event 60 */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+					     PARPORT_STATUS_BUSY, 5))
+			break;
+
 		ret++;
 	}
 
+	/* Event 61 */
+	parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
+
 	return ret;
 }
 
@@ -766,23 +772,24 @@
 
 	parport_frob_control (port,
 			      PARPORT_CONTROL_STROBE |
-			      PARPORT_CONTROL_AUTOFD |
 			      PARPORT_CONTROL_SELECT, 0);
 	port->ops->data_reverse (port);
 	for (; len > 0; len--, bp++) {
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-					     PARPORT_STATUS_BUSY))
+		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+
+		/* Event 58 */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+					     PARPORT_STATUS_BUSY, 10))
 			break;
 
+		*bp = parport_read_data (port);
+
 		parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
 				      PARPORT_CONTROL_AUTOFD);
 
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
 			break;
 
-		*bp = parport_read_data (port);
-
-		parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
 		ret++;
 	}
 	port->ops->data_forward (port);
@@ -807,23 +814,25 @@
 			      PARPORT_CONTROL_SELECT);
 	port->ops->data_forward (port);
 	for (; len > 0; len--, bp++) {
+		/* Write data and assert nAStrb. */
 		parport_write_data (port, *bp);
-
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-					     PARPORT_STATUS_BUSY))
-			break;
-
-		/* Strobe data */
 		parport_frob_control (port, PARPORT_CONTROL_SELECT,
 				      PARPORT_CONTROL_SELECT);
 
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+					     PARPORT_STATUS_BUSY, 10))
 			break;
 
 		parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
+
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
+			break;
+
 		ret++;
 	}
 
+	parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
+
 	return ret;
 }
 
@@ -838,23 +847,24 @@
 
 	parport_frob_control (port,
 			      PARPORT_CONTROL_STROBE |
-			      PARPORT_CONTROL_SELECT |
 			      PARPORT_CONTROL_AUTOFD, 0);
 	port->ops->data_reverse (port);
 	for (; len > 0; len--, bp++) {
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-					     PARPORT_STATUS_BUSY))
+		parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
+
+		/* Event 58 */
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY,
+					     PARPORT_STATUS_BUSY, 10))
 			break;
 
+		*bp = parport_read_data (port);
+
 		parport_frob_control (port, PARPORT_CONTROL_SELECT,
 				      PARPORT_CONTROL_SELECT);
 
-		if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+		if (parport_poll_peripheral (port, PARPORT_STATUS_BUSY, 0, 5))
 			break;
 
-		*bp = parport_read_data (port);
-
-		parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
 		ret++;
 	}
 	port->ops->data_forward (port);
diff -u --recursive --new-file v2.3.42/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.3.42/linux/drivers/parport/parport_pc.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/parport/parport_pc.c	Wed Feb  9 19:49:33 2000
@@ -551,21 +551,22 @@
 	unsigned long dmaflag;
 	size_t left = length;
 	const struct parport_pc_private *priv = port->physport->private_data;
-	unsigned long dma_addr;
+	dma_addr_t dma_addr, dma_handle;
 	size_t maxlen = 0x10000; /* max 64k per DMA transfer */
 	unsigned long start = (unsigned long) buf;
 	unsigned long end = (unsigned long) buf + length - 1;
 
-	/* above 16 MB we use a bounce buffer as ISA-DMA is not possible */
-	if (end <= MAX_DMA_ADDRESS) {
-                /* If it would cross a 64k boundary, cap it at the end. */
-                if ((start ^ end) & ~0xffff)
-                        maxlen = (0x10000 - start) & 0xffff;
+	if (end < MAX_DMA_ADDRESS) {
+		/* If it would cross a 64k boundary, cap it at the end. */
+		if ((start ^ end) & ~0xffffUL)
+			maxlen = (0x10000 - start) & 0xffff;
 
-		dma_addr = virt_to_bus(buf);
+		dma_addr = dma_handle = pci_map_single(priv->dev, (void *)buf, length);
         } else {
-		dma_addr = priv->dma_handle;
+		/* above 16 MB we use a bounce buffer as ISA-DMA is not possible */
 		maxlen   = PAGE_SIZE;          /* sizeof(priv->dma_buf) */
+		dma_addr = priv->dma_handle;
+		dma_handle = 0;
 	}
 
 	port = port->physport;
@@ -585,7 +586,7 @@
 		if (count > maxlen)
 			count = maxlen;
 
-		if (maxlen == PAGE_SIZE)   /* bounce buffer ! */
+		if (!dma_handle)   /* bounce buffer ! */
 			memcpy(priv->dma_buf, buf, count);
 
 		dmaflag = claim_dma_lock();
@@ -607,6 +608,7 @@
 		/* assume DMA will be successful */
 		left -= count;
 		buf  += count;
+		if (dma_handle) dma_addr += count;
 
 		/* Wait for interrupt. */
 	false_alarm:
@@ -645,6 +647,7 @@
 		/* update for possible DMA residue ! */
 		buf  -= count;
 		left += count;
+		if (dma_handle) dma_addr -= count;
 	}
 
 	/* Maybe got here through break, so adjust for DMA residue! */
@@ -656,6 +659,9 @@
 
 	/* Turn off DMA mode */
 	frob_econtrol (port, 1<<3, 0);
+	
+	if (dma_handle)
+		pci_unmap_single(priv->dev, dma_handle, length);
 
 	return length - left;
 }
@@ -1661,6 +1667,7 @@
 			p->dma = PARPORT_DMA_NONE;
 		}
 
+#ifdef CONFIG_PARPORT_PC_FIFO
 		if (p->dma != PARPORT_DMA_NONE) {
 			if (request_dma (p->dma, p->name)) {
 				printk (KERN_WARNING "%s: dma %d in use, "
@@ -1682,6 +1689,7 @@
 				}
 			}
 		}
+#endif /* CONFIG_PARPORT_PC_FIFO */
 	}
 
 	/* Done probing.  Now put the port into a sensible start-up state.
diff -u --recursive --new-file v2.3.42/linux/drivers/parport/probe.c linux/drivers/parport/probe.c
--- v2.3.42/linux/drivers/parport/probe.c	Wed Jul 28 11:22:46 1999
+++ linux/drivers/parport/probe.c	Wed Feb  9 19:51:24 2000
@@ -164,8 +164,9 @@
 		retval = parport_read (dev->port, buffer, len);
 
 		if (retval != len)
-			printk (KERN_DEBUG "%s: only read %d of %d ID bytes\n",
-				dev->port->name, retval, len);
+			printk (KERN_DEBUG "%s: only read %Zd of %Zd ID bytes\n",
+				dev->port->name, retval,
+				len);
 
 		/* Some printer manufacturers mistakenly believe that
                    the length field is supposed to be _exclusive_. */
@@ -179,7 +180,7 @@
 			if (diff)
 				printk (KERN_DEBUG
 					"%s: device reported incorrect "
-					"length field (%d, should be %d)\n",
+					"length field (%d, should be %Zd)\n",
 					dev->port->name, idlen, retval);
 			else {
 				/* One semi-colon short of a device ID. */
diff -u --recursive --new-file v2.3.42/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.3.42/linux/drivers/pci/pci.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/pci/pci.c	Thu Feb 10 12:24:54 2000
@@ -96,7 +96,17 @@
 	pci_read_config_word(dev, PCI_STATUS, &status);
 	if (!(status & PCI_STATUS_CAP_LIST))
 		return 0;
-	pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
+	switch (dev->hdr_type) {
+	case PCI_HEADER_TYPE_NORMAL:
+	case PCI_HEADER_TYPE_BRIDGE:
+		pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
+		break;
+	case PCI_HEADER_TYPE_CARDBUS:
+		pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos);
+		break;
+	default:
+		return 0;
+	}
 	while (ttl-- && pos >= 0x40) {
 		pos &= ~3;
 		pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
@@ -297,9 +307,11 @@
 void
 pci_remove_device(struct pci_dev *dev)
 {
-	if (dev->driver->remove)
-		dev->driver->remove(dev);
-	dev->driver = NULL;
+	if (dev->driver) {
+		if (dev->driver->remove)
+			dev->driver->remove(dev);
+		dev->driver = NULL;
+	}
 	list_del(&dev->bus_list);
 	list_del(&dev->global_list);
 	pci_free_resources(dev);
@@ -389,7 +401,7 @@
  * Translate the low bits of the PCI base
  * to the resource type
  */
-static inline unsigned int pci_resource_flags(unsigned int flags)
+static inline unsigned int pci_calc_resource_flags(unsigned int flags)
 {
 	if (flags & PCI_BASE_ADDRESS_SPACE_IO)
 		return IORESOURCE_IO;
@@ -433,7 +445,7 @@
 			sz = ~(sz & PCI_BASE_ADDRESS_IO_MASK) & 0xffff;
 		}
 		res->end = res->start + (unsigned long) sz;
-		res->flags |= (l & 0xf) | pci_resource_flags(l);
+		res->flags |= (l & 0xf) | pci_calc_resource_flags(l);
 		if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
 		    == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
 			pci_read_config_dword(dev, reg+4, &l);
diff -u --recursive --new-file v2.3.42/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.3.42/linux/drivers/pci/pci.ids	Fri Jan 21 18:19:16 2000
+++ linux/drivers/pci/pci.ids	Mon Feb  7 19:45:28 2000
@@ -4,7 +4,7 @@
 #	Maintained by Martin Mares <pci-ids@ucw.cz>
 #	If you have any new entries, send them to the maintainer.
 #
-#	$Id: pci.ids,v 1.46 2000/01/02 20:32:11 mj Exp $
+#	$Id: pci.ids,v 1.50 2000/01/23 05:57:06 mj Exp $
 #
 
 # Vendors, devices and subsystems. Please keep sorted.
@@ -356,12 +356,16 @@
 	2001  79c978 [HomePNA]
 	2020  53c974 [PCscsi]
 	2040  79c974
-	7006  IronGate Host
-	7403  Viper Power Management
-	7408  Viper ISA
-	7409  Viper IDE
-	740B  Viper ACPI
-	740C  Viper USB
+	7006  AMD-751 [Irongate] System Controller
+	7007  AMD-751 [Irongate] AGP Bridge
+	7400  AMD-755 [Cobra] ISA
+	7401  AMD-755 [Cobra] IDE
+	7403  AMD-755 [Cobra] ACPI
+	7404  AMD-755 [Cobra] USB
+	7408  AMD-756 [Viper] ISA
+	7409  AMD-756 [Viper] IDE
+	740b  AMD-756 [Viper] ACPI
+	740c  AMD-756 [Viper] USB
 1023  Trident Microsystems
 	0194  82C194
 	2000  4DWave DX
@@ -682,6 +686,7 @@
 	fe03  12C01A FireWire Host Controller
 104d  Sony Corporation
 	8039  CXD3222 iLINK Controller
+	8056  Rockwell HCF 56K modem
 104e  Oak Technology, Inc
 	0017  OTI-64017
 	0107  OTI-107 [Spitfire]
@@ -829,8 +834,10 @@
 	1022  ISP1022
 	1080  ISP1080
 	1240  ISP1240
+	1280  ISP1280
 	2020  ISP2020A
 	2100  ISP2100
+	2200  ISP2200
 1078  Cyrix Corporation
 	0000  5510 [Grappa]
 	0001  PCI Master
@@ -931,6 +938,16 @@
 	1330  PCI-6031E
 	1350  PCI-6071E
 	2a60  PCI-6023E
+	b001  IMAQ-PCI-1408
+	b011  IMAQ-PXI-1408
+	b021  IMAQ-PCI-1424
+	b031  IMAQ-PCI-1413
+	b041  IMAQ-PCI-1407
+	b051  IMAQ-PXI-1407
+	b061  IMAQ-PCI-1411
+	b071  IMAQ-PCI-1422
+	b081  IMAQ-PXI-1422
+	b091  IMAQ-PXI-1411
 	c801  PCI-GPIB
 1094  First International Computers [FIC]
 1095  CMD Technology Inc
@@ -2217,6 +2234,7 @@
 		127a 1005  PCI56RVP Modem 
 		13df 1005  PCI56RVP Modem 
 		1436 1005  WS-5614PS3G
+	2005  HCF 56k V90 FaxModem
 	8234  RapidFire 616X ATM155 Adapter
 127b  Pixera Corporation
 127c  Crosspoint Solutions, Inc.
@@ -3121,6 +3139,7 @@
 	0005  Permedia
 	0006  GLINT MX
 	0007  3D Extreme
+	0008  GLINT Gamma G1
 	0009  Permedia II 2D+3D
 		3d3d 0100  AccelStar II 3D Accelerator
 		3d3d 0111  Permedia 3:16
@@ -3130,6 +3149,7 @@
 		3d3d 0120  Santa Ana PCL
 		3d3d 0125  Oxygen VX1
 		3d3d 0127  Permedia3 Create!
+	000a  GLINT R3
 	0100  Permedia II 2D+3D
 	1004  Permedia
 	3d04  Permedia
@@ -3309,7 +3329,7 @@
 		0e11 b0dd  NC3131
 		0e11 b0de  NC3132
 		0e11 b0e1  NC3133
-		1014 005c  Ethernet Pro 10/100
+		1014 005c  82558B Ethernet Pro 10/100
 		1014 105c  Netfinity 10/100
 		1033 8000  PC-9821X-B06
 		1033 8016  PK-UG-X006
@@ -3363,13 +3383,13 @@
 		103c 10C7  MegaRaid T5
 		1111 1111  MegaRaid 466
 		113c 03A2  MegaRaid
-	2410  82801 82810 Chipset ISA Bridge (LPC)
-	2411  82801 82810 Chipset IDE
-	2412  82801 82810 Chipset USB
-	2413  82801 82810 Chipset SMBus
-	2415  82801 82810 AC'97 Audio
-	2416  82801 82810 AC'97 Modem
-	2418  82801 82810 PCI Bridge
+	2410  82801AA 82810 Chipset ISA Bridge (LPC)
+	2411  82801AA 82810 Chipset IDE
+	2412  82801AA 82810 Chipset USB
+	2413  82801AA 82810 Chipset SMBus
+	2415  82801AA 82810 AC'97 Audio
+	2416  82801AA 82810 AC'97 Modem
+	2418  82801AA 82810 PCI Bridge
 	2420  82801AB 82810 Chipset ISA Bridge (LPC)
 	2421  82801AB 82810 Chipset IDE
 	2422  82801AB 82810 Chipset USB
@@ -3392,6 +3412,8 @@
 	7121  82810 CGC [Chipset Graphics Controller]
 	7122  82810-DC100 GMCH [Graphics Memory Controller Hub]
 	7123  82810-DC100 CGC [Chipset Graphics Controller]
+	7124  82810E GMCH [Graphics Memory Controller Hub]
+	7125  82810E CGC [Chipset Graphics Controller]
 	7180  440LX/EX - 82443LX/EX Host bridge
 	7181  440LX/EX - 82443LX/EX AGP bridge
 	7190  440BX/ZX - 82443BX/ZX Host bridge
diff -u --recursive --new-file v2.3.42/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- v2.3.42/linux/drivers/pci/pcisyms.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/pci/pcisyms.c	Mon Feb  7 09:29:58 2000
@@ -3,7 +3,7 @@
  *
  *	PCI Bus Services -- Exported Symbols
  *
- *	Copyright 1998 Martin Mares
+ *	Copyright 1998--2000 Martin Mares <mj@suse.cz>
  */
 
 #include <linux/config.h>
@@ -29,6 +29,7 @@
 EXPORT_SYMBOL(pci_register_driver);
 EXPORT_SYMBOL(pci_unregister_driver);
 EXPORT_SYMBOL(pci_match_device);
+EXPORT_SYMBOL(pci_find_parent_resource);
 
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pci_setup_device);
diff -u --recursive --new-file v2.3.42/linux/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- v2.3.42/linux/drivers/pcmcia/bulkmem.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/pcmcia/bulkmem.c	Mon Feb  7 09:51:43 2000
@@ -62,7 +62,7 @@
 static int do_mtd_request(memory_handle_t handle, mtd_request_t *req,
 			  caddr_t buf)
 {
-    int ret, tries;
+    int ret=0, tries;
     client_t *mtd;
     socket_info_t *s;
     
diff -u --recursive --new-file v2.3.42/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.3.42/linux/drivers/pcmcia/cs.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/pcmcia/cs.c	Tue Feb  8 11:32:18 2000
@@ -62,10 +62,8 @@
 #include "cs_internal.h"
 #include "rsrc_mgr.h"
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-static int handle_apm_event(apm_event_t event);
-#endif
+#include <linux/pm.h>
+static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data);
 
 #ifdef PCMCIA_DEBUG
 int pc_debug = PCMCIA_DEBUG;
@@ -84,13 +82,13 @@
 #else
 #define CB_OPT ""
 #endif
-#ifdef CONFIG_APM
+#if defined(CONFIG_APM) || defined(CONFIG_ACPI)
 #define APM_OPT " [apm]"
 #else
 #define APM_OPT ""
 #endif
 #if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && \
-    !defined(CONFIG_APM)
+    !defined(CONFIG_APM) && !defined(CONFIG_ACPI)
 #define OPTIONS " none"
 #else
 #define OPTIONS PCI_OPT CB_OPT APM_OPT
@@ -126,9 +124,11 @@
 static int io_speed		= 0;	/* ns */
 
 /* Optional features */
-#ifdef CONFIG_APM
+#if defined(CONFIG_APM) || defined(CONFIG_ACPI)
 static int do_apm		= 1;
 MODULE_PARM(do_apm, "i");
+#else
+static int do_apm		= 0;
 #endif
 
 MODULE_PARM(setup_delay, "i");
@@ -678,22 +678,14 @@
     
 ======================================================================*/
 
-#ifdef CONFIG_APM
-static int handle_apm_event(apm_event_t event)
+static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
     int i, stat;
     socket_info_t *s;
-    static int down = 0;
     
-    switch (event) {
-    case APM_SYS_SUSPEND:
-    case APM_USER_SUSPEND:
+    switch (rqst) {
+    case PM_SUSPEND:
 	DEBUG(1, "cs: received suspend notification\n");
-	if (down) {
-	    printk(KERN_DEBUG "cs: received extra suspend event\n");
-	    break;
-	}
-	down = 1;
 	for (i = 0; i < sockets; i++) {
 	    s = socket_table[i];
 	    if ((s->state & SOCKET_PRESENT) &&
@@ -704,14 +696,8 @@
 	    }
 	}
 	break;
-    case APM_NORMAL_RESUME:
-    case APM_CRITICAL_RESUME:
+    case PM_RESUME:
 	DEBUG(1, "cs: received resume notification\n");
-	if (!down) {
-	    printk(KERN_DEBUG "cs: received bogus resume event\n");
-	    break;
-	}
-	down = 0;
 	for (i = 0; i < sockets; i++) {
 	    s = socket_table[i];
 	    /* Do this just to reinitialize the socket */
@@ -725,8 +711,7 @@
 	break;
     }
     return 0;
-} /* handle_apm_event */
-#endif
+} /* handle_pm_event */
 
 /*======================================================================
 
@@ -2287,23 +2272,32 @@
     OS-specific module glue goes here
     
 ======================================================================*/
+/* in alpha order */
 EXPORT_SYMBOL(pcmcia_access_configuration_register);
 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
+EXPORT_SYMBOL(pcmcia_bind_device);
+EXPORT_SYMBOL(pcmcia_bind_mtd);
 EXPORT_SYMBOL(pcmcia_check_erase_queue);
 EXPORT_SYMBOL(pcmcia_close_memory);
 EXPORT_SYMBOL(pcmcia_copy_memory);
 EXPORT_SYMBOL(pcmcia_deregister_client);
 EXPORT_SYMBOL(pcmcia_deregister_erase_queue);
+EXPORT_SYMBOL(pcmcia_eject_card);
 EXPORT_SYMBOL(pcmcia_get_first_client);
 EXPORT_SYMBOL(pcmcia_get_card_services_info);
 EXPORT_SYMBOL(pcmcia_get_configuration_info);
+EXPORT_SYMBOL(pcmcia_get_mem_page);
 EXPORT_SYMBOL(pcmcia_get_next_client);
 EXPORT_SYMBOL(pcmcia_get_first_region);
 EXPORT_SYMBOL(pcmcia_get_first_tuple);
+EXPORT_SYMBOL(pcmcia_get_first_window);
 EXPORT_SYMBOL(pcmcia_get_next_region);
 EXPORT_SYMBOL(pcmcia_get_next_tuple);
+EXPORT_SYMBOL(pcmcia_get_next_window);
 EXPORT_SYMBOL(pcmcia_get_status);
 EXPORT_SYMBOL(pcmcia_get_tuple_data);
+EXPORT_SYMBOL(pcmcia_insert_card);
+EXPORT_SYMBOL(pcmcia_lookup_bus);
 EXPORT_SYMBOL(pcmcia_map_mem_page);
 EXPORT_SYMBOL(pcmcia_modify_configuration);
 EXPORT_SYMBOL(pcmcia_modify_window);
@@ -2317,26 +2311,20 @@
 EXPORT_SYMBOL(pcmcia_release_io);
 EXPORT_SYMBOL(pcmcia_release_irq);
 EXPORT_SYMBOL(pcmcia_release_window);
+EXPORT_SYMBOL(pcmcia_replace_cis);
+EXPORT_SYMBOL(pcmcia_report_error);
 EXPORT_SYMBOL(pcmcia_request_configuration);
 EXPORT_SYMBOL(pcmcia_request_io);
 EXPORT_SYMBOL(pcmcia_request_irq);
 EXPORT_SYMBOL(pcmcia_request_window);
 EXPORT_SYMBOL(pcmcia_reset_card);
+EXPORT_SYMBOL(pcmcia_resume_card);
 EXPORT_SYMBOL(pcmcia_set_event_mask);
+EXPORT_SYMBOL(pcmcia_suspend_card);
 EXPORT_SYMBOL(pcmcia_validate_cis);
 EXPORT_SYMBOL(pcmcia_write_memory);
-EXPORT_SYMBOL(pcmcia_bind_device);
-EXPORT_SYMBOL(pcmcia_bind_mtd);
-EXPORT_SYMBOL(pcmcia_report_error);
-EXPORT_SYMBOL(pcmcia_suspend_card);
-EXPORT_SYMBOL(pcmcia_resume_card);
-EXPORT_SYMBOL(pcmcia_eject_card);
-EXPORT_SYMBOL(pcmcia_insert_card);
-EXPORT_SYMBOL(pcmcia_replace_cis);
-EXPORT_SYMBOL(pcmcia_get_first_window);
-EXPORT_SYMBOL(pcmcia_get_next_window);
-EXPORT_SYMBOL(pcmcia_get_mem_page);
 
+EXPORT_SYMBOL(dead_socket);
 EXPORT_SYMBOL(register_ss_entry);
 EXPORT_SYMBOL(unregister_ss_entry);
 EXPORT_SYMBOL(CardServices);
@@ -2353,10 +2341,8 @@
 #endif
     printk(KERN_INFO "  %s\n", options);
     DEBUG(0, "%s\n", version);
-#ifdef CONFIG_APM
     if (do_apm)
-	apm_register_callback(&handle_apm_event);
-#endif
+	pm_register(PM_SYS_DEV, PM_SYS_PCMCIA, handle_pm_event);
 #ifdef CONFIG_PROC_FS
     proc_pccard = proc_mkdir("pccard", proc_bus);
 #endif
@@ -2371,10 +2357,8 @@
 	remove_proc_entry("pccard", proc_bus);
     }
 #endif
-#ifdef CONFIG_APM
     if (do_apm)
-	apm_unregister_callback(&handle_apm_event);
-#endif
+	pm_unregister_all(handle_pm_event);
     release_resource_db();
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- v2.3.42/linux/drivers/pcmcia/ds.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/pcmcia/ds.c	Wed Feb  9 11:42:35 2000
@@ -853,12 +853,12 @@
 /*====================================================================*/
 
 static struct file_operations ds_fops = {
-    open:	ds_open,
-    release:	ds_release,
-    ioctl:	ds_ioctl,
-    read:	ds_read,
-    write:	ds_write,
-    poll:	ds_poll
+	 open:		ds_open,
+	 release:	ds_release,
+	 ioctl:		ds_ioctl,
+	 read:		ds_read,
+	 write:		ds_write,
+	 poll:		ds_poll,
 };
 
 EXPORT_SYMBOL(register_pccard_driver);
diff -u --recursive --new-file v2.3.42/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- v2.3.42/linux/drivers/pcmcia/yenta.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/pcmcia/yenta.c	Mon Feb  7 09:52:18 2000
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #include <pcmcia/ss.h>
 
@@ -739,6 +740,7 @@
 	yenta_set_mem_map,
 	yenta_proc_setup
 };
+EXPORT_SYMBOL(yenta_operations);
 
 /*
  * Ricoh cardbus bridge: standard cardbus, except it needs
diff -u --recursive --new-file v2.3.42/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- v2.3.42/linux/drivers/pnp/isapnp.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/pnp/isapnp.c	Mon Feb  7 09:51:43 2000
@@ -241,7 +241,7 @@
 static void __init isapnp_peek(unsigned char *data, int bytes)
 {
 	int i, j;
-	unsigned char d;
+	unsigned char d=0;
 
 	for (i = 1; i <= bytes; i++) {
 		for (j = 0; j < 10; j++) {
diff -u --recursive --new-file v2.3.42/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
--- v2.3.42/linux/drivers/pnp/isapnp_proc.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/pnp/isapnp_proc.c	Wed Feb  9 11:42:35 2000
@@ -202,19 +202,12 @@
 
 static struct file_operations isapnp_info_entry_operations =
 {
-	isapnp_info_entry_lseek,	/* lseek */
-	isapnp_info_entry_read,		/* read */
-	isapnp_info_entry_write,	/* write */
-	NULL,				/* readdir */
-	isapnp_info_entry_poll,		/* poll */
-	NULL,				/* ioctl - default */
-	NULL,				/* mmap */
-	isapnp_info_entry_open,		/* open */
-	NULL,				/* flush */
-	isapnp_info_entry_release,	/* release */
-	NULL,				/* can't fsync */
-	NULL,				/* fasync */
-	NULL,				/* lock */
+	llseek:		isapnp_info_entry_lseek,
+	read:		isapnp_info_entry_read,
+	write:		isapnp_info_entry_write,
+	poll:		isapnp_info_entry_poll,
+	open:		isapnp_info_entry_open,
+	release:	isapnp_info_entry_release,
 };
 
 static struct inode_operations isapnp_info_entry_inode_operations =
@@ -277,19 +270,8 @@
 
 static struct file_operations isapnp_proc_bus_file_operations =
 {
-	isapnp_proc_bus_lseek,		/* lseek */
-	isapnp_proc_bus_read,		/* read */
-	NULL,				/* write */
-	NULL,				/* readdir */
-	NULL,				/* poll */
-	NULL,				/* ioctl - default */
-	NULL,				/* mmap */
-	NULL,				/* open */
-	NULL,				/* flush */
-	NULL,				/* release */
-	NULL,				/* can't fsync */
-	NULL,				/* fasync */
-	NULL,				/* lock */
+	llseek:		isapnp_proc_bus_lseek,
+	read:		isapnp_proc_bus_read,
 };
 
 static struct inode_operations isapnp_proc_bus_inode_operations =
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/audio/Config.in linux/drivers/sbus/audio/Config.in
--- v2.3.42/linux/drivers/sbus/audio/Config.in	Mon Nov  1 13:56:26 1999
+++ linux/drivers/sbus/audio/Config.in	Tue Feb  8 18:23:13 2000
@@ -4,6 +4,7 @@
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
 
+   mainmenu_option next_comment
    comment 'Linux/SPARC audio subsystem (EXPERIMENTAL)'
 
    tristate 'Audio support (EXPERIMENTAL)' CONFIG_SPARCAUDIO
@@ -11,4 +12,5 @@
    dep_tristate '  CS4231 Lowlevel Driver' CONFIG_SPARCAUDIO_CS4231 $CONFIG_SPARCAUDIO
    dep_tristate '  DBRI Lowlevel Driver' CONFIG_SPARCAUDIO_DBRI $CONFIG_SPARCAUDIO
    dep_tristate '  Dummy Lowlevel Driver' CONFIG_SPARCAUDIO_DUMMY $CONFIG_SPARCAUDIO
+   endmenu
 fi
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.3.42/linux/drivers/sbus/audio/audio.c	Wed Dec 29 13:13:17 1999
+++ linux/drivers/sbus/audio/audio.c	Wed Feb  9 19:39:04 2000
@@ -1,4 +1,4 @@
-/* $Id: audio.c,v 1.47 1999/12/15 22:30:16 davem Exp $
+/* $Id: audio.c,v 1.48 2000/02/09 22:33:19 davem Exp $
  * drivers/sbus/audio/audio.c
  *
  * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
@@ -1959,18 +1959,9 @@
 #endif
 
 static struct file_operations sparcaudioctl_fops = {
-        NULL,
-        NULL,
-        NULL,
-        NULL,                   /* sparcaudio_readdir */
-        sparcaudio_select,
-        sparcaudio_ioctl,
-        NULL,                   /* sparcaudio_mmap */
-        NULL,
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
-        NULL,                   /* sparcaudio_flush */
-#endif
-        sparcaudioctl_release,
+	poll:		sparcaudio_select,
+	ioctl:		sparcaudio_ioctl,
+	release:	sparcaudioctl_release,
 };
 
 static int sparcaudio_open(struct inode * inode, struct file * file)
@@ -2170,18 +2161,13 @@
 #endif
 
 static struct file_operations sparcaudio_fops = {
-	sparcaudio_lseek,
-	sparcaudio_read,
-	sparcaudio_write,
-	NULL,			/* sparcaudio_readdir */
-	sparcaudio_select,
-	sparcaudio_ioctl,
-	NULL,			/* sparcaudio_mmap */
-	sparcaudio_open,
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
-        NULL,                   /* sparcaudio_flush */
-#endif
-	sparcaudio_release
+	llseek:		sparcaudio_lseek,
+	read:		sparcaudio_read,
+	write:		sparcaudio_write,
+	poll:		sparcaudio_select,
+	ioctl:		sparcaudio_ioctl,
+	open:		sparcaudio_open,
+	release:	sparcaudio_release,
 };
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.3.42/linux/drivers/sbus/char/Config.in	Wed Dec 29 13:13:17 1999
+++ linux/drivers/sbus/char/Config.in	Tue Feb  8 18:23:13 2000
@@ -1,3 +1,4 @@
+mainmenu_option next_comment
 comment 'Misc Linux/SPARC drivers'
 tristate '/dev/openprom device support' CONFIG_SUN_OPENPROMIO
 tristate 'Mostek real time clock support' CONFIG_SUN_MOSTEK_RTC
@@ -12,12 +13,16 @@
    tristate 'Bidirectional parallel port support (OBSOLETE)' CONFIG_SUN_BPP
    tristate 'Videopix Frame Grabber (EXPERIMENTAL)' CONFIG_SUN_VIDEOPIX
    tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA
-   tristate 'Tadpole TS102 Microcontroller support (EXPERIMENTAL)' CONFIG_TADPOLE_TS102_UCTRL
 
-   tristate 'JavaStation OS Flash SIMM (EXPERIMENTAL)' CONFIG_SUN_JSFLASH
-   # XXX Why don't we do "source drivers/char/Config.in" somewhere?
-   if [ "$CONFIG_PCI" = "y" ]; then
-      define_bool CONFIG_APM_RTC_IS_GMT y		# no shit
-      bool 'PC-style RTC' CONFIG_RTC
+   if [ "$ARCH" = "sparc" ]; then
+      tristate 'Tadpole TS102 Microcontroller support (EXPERIMENTAL)' CONFIG_TADPOLE_TS102_UCTRL
+
+      tristate 'JavaStation OS Flash SIMM (EXPERIMENTAL)' CONFIG_SUN_JSFLASH
+      # XXX Why don't we do "source drivers/char/Config.in" somewhere?
+      if [ "$CONFIG_PCI" = "y" ]; then
+	 define_bool CONFIG_APM_RTC_IS_GMT y		# no shit
+	 bool 'PC-style RTC' CONFIG_RTC
+      fi
    fi
 fi
+endmenu
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.3.42/linux/drivers/sbus/char/bpp.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sbus/char/bpp.c	Wed Feb  9 11:42:35 2000
@@ -834,19 +834,11 @@
 }
 
 static struct file_operations bpp_fops = {
-	NULL,		/* bpp_lseek */
-	bpp_read,
-	bpp_write,
-	NULL,		/* bpp_readdir */
-	NULL,		/* bpp_select */
-	bpp_ioctl,
-	NULL,		/* bpp_mmap */
-	bpp_open,
-	NULL,		/* flush */
-	bpp_release,
-  NULL,   /* fsync */
-  NULL,   /* fasync */
-  NULL,   /* lock */
+	read:		bpp_read,
+	write:		bpp_write,
+	ioctl:		bpp_ioctl,
+	open:		bpp_open,
+	release:	bpp_release,
 };
 
 #if defined(__i386__)
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- v2.3.42/linux/drivers/sbus/char/envctrl.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/sbus/char/envctrl.c	Wed Feb  9 19:39:04 2000
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.14 2000/01/09 15:43:45 ecd Exp $
+/* $Id: envctrl.c,v 1.15 2000/02/09 22:33:23 davem Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -1522,16 +1522,12 @@
 }
 
 static struct file_operations envctrl_fops = {
-	envctrl_llseek,
-	envctrl_read,
-	envctrl_write,
-	NULL,		/* readdir */
-	NULL,		/* poll */	
-	envctrl_ioctl,
-	NULL,		/* mmap */
-	envctrl_open,
-	NULL,		/* flush */
-	envctrl_release
+	llseek:		envctrl_llseek,
+	read:		envctrl_read,
+	write:		envctrl_write,
+	ioctl:		envctrl_ioctl,
+	open:		envctrl_open,
+	release:	envctrl_release,
 };
 
 static struct miscdevice envctrl_dev = {
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.3.42/linux/drivers/sbus/char/flash.c	Wed Dec 29 13:13:17 1999
+++ linux/drivers/sbus/char/flash.c	Thu Feb 10 12:16:38 2000
@@ -1,4 +1,4 @@
-/* $Id: flash.c,v 1.15 1999/12/09 00:44:22 davem Exp $
+/* $Id: flash.c,v 1.17 2000/02/10 02:51:35 davem Exp $
  * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -128,18 +128,14 @@
 }
 
 static struct file_operations flash_fops = {
-	flash_llseek,
-	flash_read,
-	NULL,		/* no write to the Flash, use mmap
-			 * and play flash dependent tricks.
-			 */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	flash_mmap,
-	flash_open,
-	NULL,		/* flush */
-	flash_release
+	/* no write to the Flash, use mmap
+	 * and play flash dependent tricks.
+	 */
+	llseek:		flash_llseek,
+	read:		flash_read,
+	mmap:		flash_mmap,
+	open:		flash_open,
+	release:	flash_release,
 };
 
 static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c
--- v2.3.42/linux/drivers/sbus/char/jsflash.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sbus/char/jsflash.c	Wed Feb  9 11:42:35 2000
@@ -30,6 +30,7 @@
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
+#include <linux/string.h>
 #if 0	/* P3 from mem.c */
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
@@ -47,6 +48,8 @@
 #include <asm/sbus.h>
 #include <asm/ebus.h>
 #endif
+#include <asm/pcic.h>
+#include <asm/oplib.h>
 
 #include <asm/jsflash.h>		/* ioctl arguments. <linux/> ?? */
 #define JSFIDSZ		(sizeof(struct jsflash_ident_arg))
@@ -357,17 +360,13 @@
 }
 
 static struct file_operations jsf_fops = {
-	jsf_lseek,
-	jsf_read,
-	jsf_write,
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	jsf_ioctl,
-	jsf_mmap,
-	jsf_open,
-	NULL,		/* flush */
-	jsf_release,
-	NULL		/* fsync */
+	llseek:		jsf_lseek,
+	read:		jsf_read,
+	write:		jsf_write,
+	ioctl:		jsf_ioctl,
+	mmap:		jsf_mmap,
+	open:		jsf_open,
+	release:	jsf_release,
 };
 
 static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops };
@@ -377,10 +376,16 @@
 #ifdef MODULE
 int init_module(void)
 #else
-int /* __init */ jsflash_init(void)
+int __init jsflash_init(void)
 #endif
 {
 	int rc;
+	char banner[128];
+
+	/* FIXME: Really autodetect things */
+	prom_getproperty(prom_root_node, "banner-name", banner, 128);
+	if (strcmp (banner, "JavaStation-NC") && strcmp (banner, "JavaStation-E"))
+		return -ENXIO;
 
 	/* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */
 	if (sparc_cpu_model == sun4m && jsf0.base == 0) {
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c
--- v2.3.42/linux/drivers/sbus/char/openprom.c	Wed Dec 29 13:13:17 1999
+++ linux/drivers/sbus/char/openprom.c	Wed Feb  9 11:42:35 2000
@@ -608,16 +608,10 @@
 }
 
 static struct file_operations openprom_fops = {
-	openprom_lseek,
-	NULL,			/* openprom_read */
-	NULL,			/* openprom_write */
-	NULL,			/* openprom_readdir */
-	NULL,			/* openprom_poll */
-	openprom_ioctl,
-	NULL,			/* openprom_mmap */
-	openprom_open,
-	NULL,			/* flush */
-	openprom_release
+	llseek:		openprom_lseek,
+	ioctl:		openprom_ioctl,
+	open:		openprom_open,
+	release:	openprom_release,
 };
 
 static struct miscdevice openprom_dev = {
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.3.42/linux/drivers/sbus/char/pcikbd.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/sbus/char/pcikbd.c	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.41 2000/01/08 07:01:20 davem Exp $
+/* $Id: pcikbd.c,v 1.43 2000/02/09 22:33:25 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -21,6 +21,7 @@
 #include <linux/random.h>
 #include <linux/miscdevice.h>
 #include <linux/kbd_ll.h>
+#include <linux/kbd_kern.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 
@@ -325,7 +326,7 @@
 			handle_scancode(scancode, !(scancode & 0x80));
 		status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
 	} while(status & KBD_STAT_OBF);
-	mark_bh(KEYBOARD_BH);
+	tasklet_schedule(&keyboard_tasklet);
 }
 
 static int send_data(unsigned char data)
@@ -713,12 +714,13 @@
 static inline void aux_start_atomic(void)
 {
 	down(&aux_sema4);
-	disable_bh(KEYBOARD_BH);
+	tasklet_disable_nosync(&keyboard_tasklet);
+	tasklet_unlock_wait(&keyboard_tasklet);
 }
 
 static inline void aux_end_atomic(void)
 {
-	enable_bh(KEYBOARD_BH);
+	tasklet_enable(&keyboard_tasklet);
 	up(&aux_sema4);
 }
 
@@ -889,18 +891,12 @@
 }
 
 struct file_operations psaux_fops = {
-	NULL,		/* seek */
-	aux_read,
-	aux_write,
-	NULL, 		/* readdir */
-	aux_poll,
-	NULL, 		/* ioctl */
-	NULL,		/* mmap */
-	aux_open,
-	NULL,		/* flush */
-	aux_release,
-	NULL,
-	aux_fasync,
+	read:		aux_read,
+	write:		aux_write,
+	poll:		aux_poll,
+	open:		aux_open,
+	release:	aux_release,
+	fasync:		aux_fasync,
 };
 
 static int aux_no_open(struct inode *inode, struct file *file)
@@ -909,14 +905,7 @@
 }
 
 struct file_operations psaux_no_fops = {
-	NULL,		/* seek */
-	NULL,
-	NULL,
-	NULL, 		/* readdir */
-	NULL,
-	NULL, 		/* ioctl */
-	NULL,		/* mmap */
-	aux_no_open,
+	open:		aux_no_open,
 };
 
 static struct miscdevice psaux_mouse = {
@@ -1035,6 +1024,9 @@
 		goto found;
 	}
 #endif
+	if (!pci_present())
+		goto do_enodev;
+
 	/*
 	 * Get the nodes for keyboard and mouse from aliases on normal systems.
 	 */
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/rtc.c linux/drivers/sbus/char/rtc.c
--- v2.3.42/linux/drivers/sbus/char/rtc.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/sbus/char/rtc.c	Wed Feb  9 19:39:04 2000
@@ -1,4 +1,4 @@
-/* $Id: rtc.c,v 1.18 1999/08/31 18:51:36 davem Exp $
+/* $Id: rtc.c,v 1.19 2000/02/09 22:33:26 davem Exp $
  *
  * Linux/SPARC Real Time Clock Driver
  * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -137,16 +137,10 @@
 }
 
 static struct file_operations rtc_fops = {
-	rtc_lseek,
-	NULL,		/* rtc_read */
-	NULL,		/* rtc_write */
-	NULL,		/* rtc_readdir */
-	NULL,		/* rtc_poll */
-	rtc_ioctl,
-	NULL,		/* rtc_mmap */
-	rtc_open,
-	NULL,		/* flush */
-	rtc_release
+	llseek:		rtc_lseek,
+	ioctl:		rtc_ioctl,
+	open:		rtc_open,
+	release:	rtc_release,
 };
 
 static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.3.42/linux/drivers/sbus/char/su.c	Wed Dec 29 13:13:18 1999
+++ linux/drivers/sbus/char/su.c	Wed Feb  9 19:39:04 2000
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.34 1999/12/02 09:55:21 davem Exp $
+/* $Id: su.c,v 1.36 2000/02/09 21:11:22 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -2223,7 +2223,7 @@
  */
 static __inline__ void __init show_su_version(void)
 {
-	char *revision = "$Revision: 1.34 $";
+	char *revision = "$Revision: 1.36 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.3.42/linux/drivers/sbus/char/sunkbd.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sbus/char/sunkbd.c	Wed Feb  9 20:08:09 2000
@@ -243,19 +243,13 @@
 #define KEY_ALT         0x86
 #define KEY_L1          0x87
 
-/* Do to sun_kbd_init() being called before rs_init(), and sun_kbd_init() doing:
+/* Due to sun_kbd_init() being called before rs_init(), and sun_kbd_init() doing:
  *
- *	init_bh(KEYBOARD_BH, kbd_bh);
- *	mark_bh(KEYBOARD_BH);
+ *	tasklet_enable(&keyboard_tasklet);
+ *	tasklet_schedule(&keyboard_tasklet);
  *
  * this might well be called before some driver has claimed interest in
  * handling the keyboard input/output. So we need to assign an initial nop.
- *
- * Otherwise this would lead to the following (DaveM might want to look at):
- *
- *	sparc64_dtlb_refbit_catch(),
- *	do_sparc64_fault(),
- *	kernel NULL pointer dereference at do_sparc64_fault + 0x2c0 ;-(
  */
 static void nop_kbd_put_char(unsigned char c) { }
 static void (*kbd_put_char)(unsigned char) = nop_kbd_put_char;
@@ -460,6 +454,10 @@
 	restore_flags(flags);
 }
 
+#ifndef CONFIG_PCI
+DECLARE_TASKLET_DISABLED(keyboard_tasklet, sun_kbd_bh, 0);
+#endif
+
 /* #define SKBD_DEBUG */
 /* This is our keyboard 'interrupt' routine. */
 void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
@@ -610,7 +608,7 @@
 		}
 	}
 out:
-	mark_bh(KEYBOARD_BH);
+	tasklet_schedule(&keyboard_tasklet);
 }
 
 static void put_queue(int ch)
@@ -1086,7 +1084,6 @@
  */
 
 static unsigned char ledstate = 0xff; /* undefined */
-static unsigned char sunkbd_ledstate = 0xff; /* undefined */
 static unsigned char ledioctl;
 
 unsigned char sun_getledstate(void) {
@@ -1163,7 +1160,8 @@
  * used, but this allows for easy and efficient race-condition
  * prevention later on.
  */
-static void kbd_bh(void)
+static unsigned char sunkbd_ledstate = 0xff; /* undefined */
+void sun_kbd_bh(unsigned long dummy)
 {
 	unsigned char leds = getleds();
 	unsigned char kbd_leds = vcleds_to_sunkbd(leds);
@@ -1247,8 +1245,12 @@
 	} else {
 		sunkbd_clickp = 0;
 	}
-	init_bh(KEYBOARD_BH, kbd_bh);
-	mark_bh(KEYBOARD_BH);
+
+	keyboard_tasklet.func = sun_kbd_bh;
+
+	tasklet_enable(&keyboard_tasklet);
+	tasklet_schedule(&keyboard_tasklet);
+
 	return 0;
 }
 
@@ -1486,21 +1488,14 @@
 	return 0;
 }
 
-static struct
-file_operations kbd_fops =
+static struct file_operations kbd_fops =
 {
-	NULL,			/* seek */
-	kbd_read,		/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	kbd_poll,		/* poll */
-	kbd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	kbd_open,		/* open */
-	NULL,			/* flush */
-	kbd_close,		/* close */
-	NULL,			/* fsync */
-	kbd_fasync,		/* fasync */
+	read:		kbd_read,
+	poll:		kbd_poll,
+	ioctl:		kbd_ioctl,
+	open:		kbd_open,
+	release:	kbd_close,
+	fasync:		kbd_fasync,
 };
 
 void __init keyboard_zsinit(void (*put_char)(unsigned char))
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/sunkbd.h linux/drivers/sbus/char/sunkbd.h
--- v2.3.42/linux/drivers/sbus/char/sunkbd.h	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/char/sunkbd.h	Wed Feb  9 20:08:09 2000
@@ -1,4 +1,4 @@
-/* $Id: sunkbd.h,v 1.3 1997/09/08 03:05:10 tdyas Exp $
+/* $Id: sunkbd.h,v 1.4 2000/02/09 11:15:54 davem Exp $
  * sunkbd.h: Defines needed by SUN Keyboard drivers
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -26,6 +26,7 @@
 extern void sunkbd_inchar(unsigned char, struct pt_regs *);
 extern void batten_down_hatches(void);
 
+extern void sun_kbd_bh(unsigned long);
 extern int sun_kbd_init(void);
 extern void sun_compute_shiftstate(void);
 extern void sun_setledstate(struct kbd_struct *, unsigned int);
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c
--- v2.3.42/linux/drivers/sbus/char/sunmouse.c	Wed Dec 29 13:13:18 1999
+++ linux/drivers/sbus/char/sunmouse.c	Wed Feb  9 11:42:35 2000
@@ -542,18 +542,13 @@
 }
 
 struct file_operations sun_mouse_fops = {
-	NULL,
-	sun_mouse_read,
-	sun_mouse_write,
-	NULL,
-	sun_mouse_poll,
-	sun_mouse_ioctl,
-	NULL,
-	sun_mouse_open,
-	NULL,		/* flush */
-	sun_mouse_close,
-	NULL,
-	sun_mouse_fasync,
+	read:		sun_mouse_read,
+	write:		sun_mouse_write,
+	poll:		sun_mouse_poll,
+	ioctl:		sun_mouse_ioctl,
+	open:		sun_mouse_open,
+	release:	sun_mouse_close,
+	fasync:		sun_mouse_fasync,
 };
 
 static struct miscdevice sun_mouse_mouse = {
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/uctrl.c linux/drivers/sbus/char/uctrl.c
--- v2.3.42/linux/drivers/sbus/char/uctrl.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sbus/char/uctrl.c	Wed Feb  9 19:39:04 2000
@@ -1,4 +1,4 @@
-/* $Id: uctrl.c,v 1.6 2000/01/22 05:22:07 anton Exp $
+/* $Id: uctrl.c,v 1.7 2000/02/09 22:33:28 davem Exp $
  * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3
  *
  * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
@@ -238,16 +238,10 @@
 }
 
 static struct file_operations uctrl_fops = {
-	uctrl_llseek,
-	NULL,           /* read */
-	NULL,           /* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */	
-	uctrl_ioctl,
-	NULL,		/* mmap */
-	uctrl_open,
-	NULL,		/* flush */
-	uctrl_release
+	llseek:		uctrl_llseek,
+	ioctl:		uctrl_ioctl,
+	open:		uctrl_open,
+	release:	uctrl_release,
 };
 
 static struct miscdevice uctrl_dev = {
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c
--- v2.3.42/linux/drivers/sbus/char/vfc_dev.c	Wed Dec 29 13:13:18 1999
+++ linux/drivers/sbus/char/vfc_dev.c	Wed Feb  9 11:42:35 2000
@@ -627,16 +627,11 @@
 }
 
 static struct file_operations vfc_fops = {
-	vfc_lseek,   /* vfc_lseek */
-	NULL,        /* vfc_write */
-	NULL,        /* vfc_read */
-	NULL,        /* vfc_readdir */
-	NULL,        /* vfc_select */
-	vfc_ioctl,   
-	vfc_mmap, 
-	vfc_open,
-	NULL,	     /* flush */
-	vfc_release,
+	llseek:		vfc_lseek,
+	ioctl:		vfc_ioctl,
+	mmap:		vfc_mmap,
+	open:		vfc_open,
+	release:	vfc_release,
 };
 
 static int vfc_probe(void)
diff -u --recursive --new-file v2.3.42/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- v2.3.42/linux/drivers/sbus/char/zs.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/sbus/char/zs.c	Wed Feb  9 19:39:04 2000
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.53 2000/01/29 01:29:38 anton Exp $
+/* $Id: zs.c,v 1.55 2000/02/09 21:11:24 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1928,7 +1928,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.53 $";
+	char *revision = "$Revision: 1.55 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.3.42/linux/drivers/scsi/Config.in	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/Config.in	Wed Feb  9 18:40:23 2000
@@ -1,10 +1,22 @@
 comment 'SCSI support type (disk, tape, CD-ROM)'
 
 dep_tristate '  SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+
+if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+   int  'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+fi
+
 dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+
+if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+   int  'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
+fi
+
 dep_tristate '  SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+
 if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
    bool '    Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+   int  'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
 fi
 dep_tristate '  SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
 
@@ -126,6 +138,7 @@
 if [ "$CONFIG_PCI" = "y" ]; then
    dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
    dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI
+   dep_tristate 'Qlogic QLA 1280 SCSI support' CONFIG_SCSI_QLOGIC_1280 $CONFIG_SCSI
 fi
 dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
 if [ "$CONFIG_PCI" = "y" ]; then
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.3.42/linux/drivers/scsi/Makefile	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/Makefile	Mon Feb  7 19:45:28 2000
@@ -322,6 +322,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_QLOGIC_1280),y)
+L_OBJS += qla1280.o 
+else
+  ifeq ($(CONFIG_SCSI_QLOGIC_1280),m)
+  M_OBJS += qla1280.o 
+  endif
+endif
+
 ifeq ($(CONFIG_SCSI_ACARD),y)
 L_OBJS += atp870u.o
 else
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v2.3.42/linux/drivers/scsi/advansys.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/scsi/advansys.c	Wed Feb  9 18:40:23 2000
@@ -10505,8 +10505,8 @@
         (ulong) s->host_queue, (ulong) s->hostt, (ulong) s->block);
 
     printk(
-" wish_block %d, base %lu, io_port %lu, n_io_port %u, irq %d,\n",
-        s->wish_block, (ulong) s->base, (ulong) s->io_port, s->n_io_port,
+" base %lu, io_port %lu, n_io_port %u, irq %d,\n",
+	(ulong) s->base, (ulong) s->io_port, s->n_io_port,
         s->irq);
 
     printk(
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.3.42/linux/drivers/scsi/eata.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/scsi/eata.c	Wed Feb  9 18:40:23 2000
@@ -1049,7 +1049,7 @@
       sh[j]->unchecked_isa_dma = FALSE;
    else {
       unsigned long flags;
-//FIXME//      sh[j]->wish_block = TRUE;
+      scsi_register_blocked_host(sh[j]);
       sh[j]->unchecked_isa_dma = TRUE;
       
       flags=claim_dma_lock();
@@ -2273,6 +2273,10 @@
 
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
+
+   if( sh[j]->unchecked_isa_dma ) {
+	   scsi_deregister_blocked_host(sh[j]);
+   }
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v2.3.42/linux/drivers/scsi/eata_dma.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/eata_dma.c	Wed Feb  9 18:40:23 2000
@@ -131,12 +131,11 @@
     if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq, NULL);
     else reg_IRQ[sh->irq]--;
     
-    scsi_init_free((void *)status, 512);
-    scsi_init_free((void *)dma_scratch - 4, 1024);
+    kfree((void *)status);
+    kfree((void *)dma_scratch - 4);
     for (i = 0; i < sh->can_queue; i++){ /* Free all SG arrays */
 	if(SD(sh)->ccb[i].sg_list != NULL)
-	    scsi_init_free((void *) SD(sh)->ccb[i].sg_list, 
-			   sh->sg_tablesize * sizeof(struct eata_sg_list));
+	    kfree((void *) SD(sh)->ccb[i].sg_list);
     }
     
     if (SD(sh)->channel == 0) {
@@ -908,9 +907,9 @@
     static char *buff;
     ulong i;
 
-    cp = (struct eata_ccb *) scsi_init_malloc(sizeof(struct eata_ccb),
-					      GFP_ATOMIC | GFP_DMA);
-    sp = (struct eata_sp *) scsi_init_malloc(sizeof(struct eata_sp), 
+    cp = (struct eata_ccb *) kmalloc(sizeof(struct eata_ccb),
+				     GFP_ATOMIC | GFP_DMA);
+    sp = (struct eata_sp *) kmalloc(sizeof(struct eata_sp), 
 					     GFP_ATOMIC | GFP_DMA);
 
     buff = dma_scratch;
@@ -954,8 +953,8 @@
 			  fake_int_result, (u32) (sp->hba_stat /*& 0x7f*/), 
 			  (u32) sp->scsi_stat, buff, sp));
 
-    scsi_init_free((void *)cp, sizeof(struct eata_ccb));
-    scsi_init_free((void *)sp, sizeof(struct eata_sp));
+    kfree((void *)cp);
+    kfree((void *)sp);
     
     if ((fake_int_result & HA_SERROR) || time_after(jiffies, i)){
 	printk(KERN_WARNING "eata_dma: trying to reset HBA at %x to clear "
@@ -1287,8 +1286,6 @@
     else
 	hd->primary = TRUE;
     
-//FIXME//    sh->wish_block = FALSE;	   
-    
     if (hd->bustype != IS_ISA) {
 	sh->unchecked_isa_dma = FALSE;
     } else {
@@ -1459,8 +1456,8 @@
 
     tpnt->proc_name = "eata_dma";
 
-    status = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA);
-    dma_scratch = scsi_init_malloc(1024, GFP_ATOMIC | GFP_DMA);
+    status = kmalloc(512, GFP_ATOMIC | GFP_DMA);
+    dma_scratch = kmalloc(1024, GFP_ATOMIC | GFP_DMA);
 
     if(status == NULL || dma_scratch == NULL) {
 	printk("eata_dma: can't allocate enough memory to probe for hosts !\n");
@@ -1511,10 +1508,10 @@
 	    HBA_ptr = SD(HBA_ptr)->next;
 	}
     } else {
-	scsi_init_free((void *)status, 512);
+	kfree((void *)status);
     }
 
-    scsi_init_free((void *)dma_scratch - 4, 1024);
+    kfree((void *)dma_scratch - 4);
 
     DBG(DPT_DEBUG, DELAY(12));
 
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.3.42/linux/drivers/scsi/hosts.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/hosts.c	Wed Feb  9 18:40:23 2000
@@ -9,6 +9,8 @@
  *  <drew@colorado.edu>
  *
  *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
+ *  Added QLOGIC QLA1280 SCSI controller kernel host support. 
+ *     August 4, 1999 Fred Lewis, Intel DuPont
  */
 
 
@@ -191,6 +193,10 @@
 #include "qlogicfc.h"
 #endif
 
+#ifdef CONFIG_SCSI_QLOGIC_1280
+#include "qla1280.h"
+#endif
+
 #ifdef CONFIG_SCSI_SEAGATE
 #include "seagate.h"
 #endif
@@ -528,6 +534,9 @@
 #ifdef CONFIG_SCSI_QLOGIC_FC
     QLOGICFC,
 #endif
+#ifdef CONFIG_SCSI_QLOGIC_1280
+    QLA1280_LINUX_TEMPLATE, 
+#endif
 #ifdef CONFIG_SCSI_PAS16
     MV_PAS16,
 #endif
@@ -689,7 +698,7 @@
 	}
     }
     next_scsi_host--;
-    scsi_init_free((char *) sh, sizeof(struct Scsi_Host) + sh->extra_bytes);
+    kfree((char *) sh);
 }
 
 /* We call this when we come across a new host adapter. We only do this
@@ -699,8 +708,9 @@
 
 struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){
     struct Scsi_Host * retval, *shpnt;
-    retval = (struct Scsi_Host *)scsi_init_malloc(sizeof(struct Scsi_Host) + j,
-						  (tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC);
+    retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j,
+					 (tpnt->unchecked_isa_dma && j ? GFP_DMA : 0) | GFP_ATOMIC);
+    memset(retval, 0, sizeof(struct Scsi_Host) + j);
     atomic_set(&retval->host_active,0);
     retval->host_busy = 0;
     retval->host_failed = 0;
@@ -745,7 +755,7 @@
     retval->unchecked_isa_dma = tpnt->unchecked_isa_dma;
     retval->use_clustering = tpnt->use_clustering;   
 
-    retval->select_queue_depths = NULL;
+    retval->select_queue_depths = tpnt->select_queue_depths;
 
     if(!scsi_hostlist)
 	scsi_hostlist = retval;
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.3.42/linux/drivers/scsi/hosts.h	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/hosts.h	Thu Feb 10 12:37:22 2000
@@ -25,6 +25,7 @@
     $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $
 */
 
+#include <linux/config.h>
 #include <linux/proc_fs.h>
 
 /* It is senseless to set SG_ALL any higher than this - the performance
@@ -210,6 +211,12 @@
      */
     int (* bios_param)(Disk *, kdev_t, int []);
 
+
+    /*
+     * Used to set the queue depth for a specific device.
+     */
+    void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *);
+
     /*
      * This determines if we will use a non-interrupt driven
      * or an interrupt driven scheme,  It is set to the maximum number
@@ -417,16 +424,6 @@
  *  scsi_init initializes the scsi hosts.
  */
 
-/*
- * We use these goofy things because the MM is not set up when we init
- * the scsi subsystem.	By using these functions we can write code that
- * looks normal.  Also, it makes it possible to use the same code for a
- * loadable module.
- */
-
-extern void * scsi_init_malloc(unsigned int size, int priority);
-extern void scsi_init_free(char * ptr, unsigned int size);
-
 extern int next_scsi_host;
 
 extern int scsi_loadable_module_flag;
@@ -434,7 +431,8 @@
 extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j);
 extern void scsi_unregister(struct Scsi_Host * i);
 
-extern request_fn_proc * scsi_get_request_handler(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
+extern void scsi_register_blocked_host(struct Scsi_Host * SHpnt);
+extern void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt);
 
 /*
  * Prototypes for functions/data in scsi_scan.c
@@ -473,6 +471,8 @@
                                            Selects command for blkdevs */
 };
 
+void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt);
+
 extern struct Scsi_Device_Template sd_template;
 extern struct Scsi_Device_Template st_template;
 extern struct Scsi_Device_Template sr_template;
@@ -499,10 +499,14 @@
  *
  * Even bigger hack for SparcSTORAGE arrays. Those are at least 6 disks, but
  * usually up to 30 disks, so everyone would need to change this. -jj
+ *
+ * Note: These things are all evil and all need to go away.  My plan is to
+ * tackle the character devices first, as there aren't any locking implications
+ * in the block device layer.   The block devices will require more work.
  */
-#define SD_EXTRA_DEVS 40
-#define ST_EXTRA_DEVS 2
-#define SR_EXTRA_DEVS 2
+#define SD_EXTRA_DEVS CONFIG_SD_EXTRA_DEVS
+#define ST_EXTRA_DEVS CONFIG_ST_EXTRA_DEVS
+#define SR_EXTRA_DEVS CONFIG_SR_EXTRA_DEVS
 #define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS)
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- v2.3.42/linux/drivers/scsi/ips.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/ips.c	Wed Feb  9 18:40:23 2000
@@ -459,7 +459,6 @@
       sh->cmd_per_lun = sh->hostt->cmd_per_lun;
       sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
       sh->use_clustering = sh->hostt->use_clustering;
-//FIXME//      sh->wish_block = FALSE;
 
       /* Store info in HA structure */
       ha->io_addr = io_addr;
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c
--- v2.3.42/linux/drivers/scsi/mesh.c	Thu Nov 11 20:11:48 1999
+++ linux/drivers/scsi/mesh.c	Wed Feb  9 19:43:57 2000
@@ -253,7 +253,7 @@
 			continue;
 		}
 		mesh_host->unique_id = nmeshes;
-#ifndef MODULE
+#if !defined(MODULE) && (defined(CONFIG_PMAC) || defined(CONFIG_ALL_PPC))
 		note_scsi_host(mesh, mesh_host);
 #endif
 
@@ -305,7 +305,9 @@
 		if (mesh_sync_period < minper)
 			mesh_sync_period = minper;
 
+#if defined(CONFIG_PMAC) || defined(CONFIG_ALL_PPC)
 		feature_set(mesh, FEATURE_MESH_enable);
+#endif
 		mdelay(200);
 
 		mesh_init(ms);
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c
--- v2.3.42/linux/drivers/scsi/pluto.c	Wed Dec 29 13:13:18 1999
+++ linux/drivers/scsi/pluto.c	Wed Feb  9 18:40:23 2000
@@ -112,7 +112,7 @@
 #endif
 			return 0;
 	}
-	fcs = (struct ctrl_inquiry *) scsi_init_malloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
+	fcs = (struct ctrl_inquiry *) kmalloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA);
 	if (!fcs) {
 		printk ("PLUTO: Not enough memory to probe\n");
 		return 0;
@@ -265,7 +265,7 @@
 		} else
 			fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
 	}
-	scsi_init_free((char *)fcs, sizeof (struct ctrl_inquiry) * fcscount);
+	kfree((char *)fcs);
 	if (nplutos)
 		printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos);
 	return nplutos;
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/ql12160_fw.h linux/drivers/scsi/ql12160_fw.h
--- v2.3.42/linux/drivers/scsi/ql12160_fw.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/ql12160_fw.h	Mon Feb  7 19:45:28 2000
@@ -0,0 +1,1704 @@
+/*
+ ************************************************************************
+ *									*
+ * 	           --- ISP12160 Initiator Firmware ---               	*
+ *			      32 LUN Support				*
+ *									*
+ ************************************************************************
+ *									*
+ * Copyright (C) 1999,2000 Qlogic, Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that the following conditions are met:
+ * 1. Redistribution of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *									*
+ ************************************************************************
+ */
+
+
+/*
+ *	Firmware Version 10.01.19 (12:38 Oct 12, 1999)
+ */
+
+#ifdef UNIQUE_FW_NAME
+unsigned short fw12160i_version = 10*1024+1;
+#else
+unsigned short risc_code_version = 10*1024+1;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+unsigned char fw12160i_version_str[] = {10,1,19};
+#else
+unsigned char firmware_version[] = {10,1,19};
+#endif
+
+#ifdef UNIQUE_FW_NAME
+#define fw12160i_VERSION_STRING "10.1.19"
+#else
+#define FW_VERSION_STRING "10.1.19"
+#endif
+
+#ifdef UNIQUE_FW_NAME
+unsigned short fw12160i_addr01 = 0x1000 ;
+#else
+unsigned short risc_code_addr01 = 0x1000 ;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+unsigned short fw12160i_code01[] = { 
+#else
+unsigned short risc_code01[] = { 
+#endif
+	0x0804, 0x1041, 0x0000, 0x32f8, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
+	0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
+	0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
+	0x3132, 0x3136, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
+	0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3031, 0x2020, 0x2043,
+	0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
+	0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
+	0x2400, 0x20c9, 0x8cff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
+	0x01ff, 0x2004, 0xd0fc, 0x1120, 0x2071, 0x0100, 0x70a0, 0x70a2,
+	0x20c1, 0x0020, 0x2089, 0x1223, 0x2071, 0x0010, 0x70c3, 0x0004,
+	0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x000a,
+	0x2001, 0x04fd, 0x2004, 0x70d6, 0x2009, 0xfeff, 0x2130, 0x2128,
+	0xa1a2, 0x4300, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+	0xa192, 0x8d00, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1d83,
+	0x2218, 0x2079, 0x4300, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+	0x0040, 0x42a4, 0x8109, 0x1dd8, 0x2009, 0xff00, 0x3400, 0xa102,
+	0x0218, 0x0110, 0x20a8, 0x42a4, 0x781b, 0x0064, 0x7814, 0xc0cd,
+	0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4340, 0x080c,
+	0x42d8, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4380,
+	0x2071, 0x0100, 0x080c, 0x42d8, 0x7814, 0xc0d4, 0x7816, 0x00de,
+	0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802,
+	0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002,
+	0x2009, 0x0002, 0x2069, 0x4340, 0x681b, 0x0003, 0x6823, 0x0007,
+	0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0000,
+	0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000, 0x8109, 0x0500,
+	0x68d3, 0x000a, 0x68c3, 0x43c0, 0x2079, 0x4300, 0x68d7, 0x762d,
+	0x68c7, 0x48c0, 0x68cb, 0x47c0, 0x68cf, 0x88c0, 0x68ab, 0x8b44,
+	0x68af, 0x8b49, 0x68b3, 0x8b44, 0x68b7, 0x8b44, 0x68a7, 0x0001,
+	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4380, 0x0860,
+	0x68d3, 0x000a, 0x68c3, 0x45c0, 0x68d7, 0x7839, 0x68c7, 0x68c0,
+	0x68cb, 0x4840, 0x68cf, 0x89d0, 0x68ab, 0x8b49, 0x68af, 0x8b4e,
+	0x68b3, 0x8b49, 0x68b7, 0x8b49, 0x68a7, 0x0001, 0x00e6, 0x2069,
+	0x47c0, 0x2071, 0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1c09, 0x2021,
+	0x0009, 0x1120, 0x2019, 0x1c0c, 0x2021, 0x000c, 0x080c, 0x1cf3,
+	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1188, 0x2069, 0x4840, 0x2071,
+	0x0100, 0x70ec, 0xd0e4, 0x2019, 0x1c09, 0x2021, 0x0009, 0x1120,
+	0x2019, 0x1c0c, 0x2021, 0x000c, 0x080c, 0x1cf3, 0x00ee, 0x2011,
+	0x0002, 0x2069, 0x48c0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837,
+	0x0000, 0x680b, 0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817,
+	0x0100, 0x681f, 0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002,
+	0xade8, 0x0010, 0x1f04, 0x1137, 0x8109, 0x1d38, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x1128, 0x8211, 0x0118, 0x2069, 0x68c0, 0x08d8,
+	0x080c, 0x2254, 0x080c, 0x3e39, 0x080c, 0x1b0f, 0x080c, 0x42a0,
+	0x2091, 0x2200, 0x2079, 0x4300, 0x2071, 0x0050, 0x2091, 0x2400,
+	0x2079, 0x4300, 0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200,
+	0x2071, 0x4340, 0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4380,
+	0x2091, 0x2000, 0x2079, 0x4300, 0x2071, 0x0010, 0x3200, 0xa085,
+	0x303d, 0x2090, 0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118e,
+	0x70c0, 0xa086, 0x0002, 0x1110, 0x080c, 0x13a3, 0x2039, 0x0000,
+	0x080c, 0x129c, 0x78ac, 0xa005, 0x1180, 0x0e04, 0x119c, 0x786c,
+	0xa065, 0x0110, 0x080c, 0x1ffe, 0x080c, 0x1da4, 0x0e04, 0x11b1,
+	0x786c, 0xa065, 0x0110, 0x080c, 0x1ffe, 0x0e04, 0x11b1, 0x2009,
+	0x4347, 0x2011, 0x4387, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c,
+	0x1c21, 0x2071, 0x4340, 0x70a4, 0xa005, 0x01e8, 0x7450, 0xa485,
+	0x0000, 0x01c8, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4, 0xa28c,
+	0x303d, 0x2190, 0x080c, 0x260d, 0x2091, 0x8000, 0x2091, 0x303d,
+	0x0e04, 0x11d3, 0x2079, 0x4300, 0x786c, 0xa065, 0x0120, 0x2071,
+	0x0010, 0x080c, 0x1ffe, 0x1d04, 0x11db, 0x2079, 0x4300, 0x2071,
+	0x0010, 0x080c, 0x40ed, 0x2071, 0x4380, 0x70a4, 0xa005, 0x0188,
+	0x7050, 0xa025, 0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d4,
+	0xa28c, 0x303d, 0x2190, 0x080c, 0x260d, 0x2091, 0x8000, 0x2091,
+	0x303d, 0x2079, 0x4300, 0x2071, 0x0010, 0x0e04, 0x11fc, 0x786c,
+	0xa065, 0x0110, 0x080c, 0x1ffe, 0x1d04, 0x1190, 0x080c, 0x40ed,
+	0x0804, 0x1190, 0x3c00, 0xa084, 0x0007, 0x0002, 0x120e, 0x120e,
+	0x1210, 0x1210, 0x1215, 0x1215, 0x121a, 0x121a, 0x080c, 0x243b,
+	0x2091, 0x2400, 0x080c, 0x3e9c, 0x0005, 0x2091, 0x2200, 0x080c,
+	0x3e9c, 0x0005, 0x2091, 0x2200, 0x080c, 0x3e9c, 0x2091, 0x2400,
+	0x080c, 0x3e9c, 0x0005, 0x1243, 0x1243, 0x1244, 0x1244, 0x124f,
+	0x124f, 0x124f, 0x124f, 0x1258, 0x1258, 0x1263, 0x1263, 0x124f,
+	0x124f, 0x124f, 0x124f, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272,
+	0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272,
+	0x1272, 0x1272, 0x1272, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091,
+	0x2800, 0x080c, 0x2458, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006,
+	0x0106, 0x0126, 0x080c, 0x1202, 0x012e, 0x010e, 0x000e, 0x000d,
+	0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2458, 0x012e,
+	0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600,
+	0x080c, 0x2458, 0x2091, 0x2800, 0x080c, 0x2458, 0x012e, 0x010e,
+	0x000e, 0x000d, 0x0006, 0x0106, 0x0126, 0x00e6, 0x00f6, 0x2079,
+	0x4300, 0x2071, 0x0200, 0x2069, 0x4340, 0x3d00, 0xd08c, 0x1120,
+	0x2069, 0x4380, 0x2071, 0x0100, 0x080c, 0x42d8, 0x00fe, 0x00ee,
+	0x012e, 0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007,
+	0x0002, 0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897,
+	0x70c3, 0x4002, 0x0804, 0x13a6, 0x0e04, 0x1308, 0x2061, 0x0000,
+	0x6018, 0xd084, 0x1904, 0x1308, 0x7828, 0xa005, 0x1120, 0x0004,
+	0x1309, 0x0804, 0x1308, 0xd0fc, 0x0148, 0x0006, 0x080c, 0x1aa9,
+	0x000e, 0x0168, 0x2001, 0x4007, 0x0804, 0x13a5, 0x0006, 0x080c,
+	0x1a9b, 0x000e, 0x0120, 0x2001, 0x4007, 0x0804, 0x13a5, 0x7910,
+	0xd0fc, 0x1128, 0x2061, 0x4340, 0xc19c, 0xc7fc, 0x0020, 0x2061,
+	0x4380, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x15d0, 0x7912, 0x6083,
+	0x0000, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x1120, 0x00c6, 0x080c,
+	0x18c9, 0x00ce, 0x782b, 0x0000, 0x607c, 0xa065, 0x0190, 0x00c6,
+	0x609c, 0x080c, 0x1b76, 0x00ce, 0x609f, 0x0000, 0x080c, 0x19db,
+	0x2009, 0x0018, 0x6087, 0x0103, 0x080c, 0x1ab7, 0x1198, 0x080c,
+	0x1b02, 0x7810, 0xd09c, 0x1118, 0x2061, 0x4340, 0x0020, 0x2061,
+	0x4380, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4, 0xd0c4, 0x0130,
+	0xc0c4, 0x60d6, 0x2001, 0x4005, 0x0804, 0x13a5, 0x0804, 0x13a3,
+	0x0005, 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0,
+	0xa08a, 0x0040, 0x1a04, 0x1355, 0x0002, 0x13a3, 0x13f1, 0x13bf,
+	0x1425, 0x1459, 0x1459, 0x13b7, 0x19f3, 0x1463, 0x13b1, 0x13c3,
+	0x13c4, 0x13c5, 0x13c6, 0x19f7, 0x13b1, 0x1470, 0x14c5, 0x18e4,
+	0x19ed, 0x13c7, 0x1795, 0x17cb, 0x17fa, 0x183d, 0x1752, 0x175f,
+	0x1772, 0x1784, 0x159a, 0x13b1, 0x14f7, 0x1502, 0x1510, 0x151e,
+	0x1535, 0x1543, 0x1546, 0x1554, 0x1562, 0x156c, 0x1580, 0x158c,
+	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x15a7, 0x15b8, 0x15d2, 0x1606,
+	0x162f, 0x1641, 0x1644, 0x1677, 0x16aa, 0x16bc, 0x1720, 0x1730,
+	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x1742, 0x2100, 0xa08a, 0x0040,
+	0x1a04, 0x13b1, 0x0002, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
+	0x1a19, 0x1a1f, 0x13b1, 0x13b1, 0x13b1, 0x1a23, 0x1a63, 0x13b1,
+	0x13b1, 0x13b1, 0x13b1, 0x13ec, 0x1454, 0x146b, 0x14c0, 0x18df,
+	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x1a67, 0x1a0b, 0x1a15, 0x13b1,
+	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
+	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
+	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
+	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
+	0x13b1, 0x13b1, 0x13b1, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0028,
+	0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0e04, 0x13a6,
+	0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
+	0x0005, 0x70c3, 0x4001, 0x0c90, 0x70c3, 0x4006, 0x0c78, 0x2099,
+	0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0c20, 0x70c4,
+	0x70c3, 0x0004, 0x0807, 0x08f8, 0x08f0, 0x08e8, 0x08e0, 0x2091,
+	0x8000, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf,
+	0x2020, 0x70d3, 0x000a, 0x2001, 0x0001, 0x70d6, 0x2079, 0x0000,
+	0x781b, 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a,
+	0x2051, 0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000,
+	0x2091, 0x4080, 0x0804, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de,
+	0x0018, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4,
+	0x20a0, 0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a,
+	0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0904, 0x13a3,
+	0xa182, 0x0040, 0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012,
+	0x7007, 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0x7007,
+	0x0002, 0xa084, 0x01e0, 0x0120, 0x70c3, 0x4002, 0x0804, 0x13a6,
+	0x24a8, 0x53a5, 0x0c10, 0x0804, 0x13a3, 0x2029, 0x0000, 0x2520,
+	0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003,
+	0x0000, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021,
+	0x0040, 0x7007, 0x0006, 0x81ff, 0x0904, 0x13a3, 0xa182, 0x0040,
+	0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6,
+	0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x0d48,
+	0x70c3, 0x4002, 0x0804, 0x13a6, 0x75d8, 0x74dc, 0x75da, 0x74de,
+	0x0878, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x1108, 0x200a,
+	0x72ca, 0x0804, 0x13a2, 0x70c7, 0x000a, 0x70cb, 0x0001, 0x70cf,
+	0x0013, 0x0804, 0x13a3, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018,
+	0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6,
+	0x72ca, 0x73ce, 0x74d2, 0xa005, 0x05f0, 0xa40a, 0x0110, 0x1a04,
+	0x13a5, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0138, 0x78ac, 0xc085,
+	0x78ae, 0x2001, 0x4005, 0x0804, 0x13a5, 0x7b7e, 0x7a7a, 0x7e86,
+	0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0170, 0x8407, 0x8004, 0x8004,
+	0x810c, 0x810c, 0x810f, 0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000,
+	0xa581, 0x0000, 0x0050, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291,
+	0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622,
+	0x7026, 0xa605, 0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084,
+	0xfffc, 0x78ae, 0x0018, 0x78ac, 0xc085, 0x78ae, 0x0804, 0x13a3,
+	0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029, 0x0000, 0x2530,
+	0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
+	0xa005, 0x0500, 0xa40a, 0x0110, 0x1a04, 0x13a5, 0x8001, 0x7892,
+	0xa084, 0xfc00, 0x0138, 0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005,
+	0x0804, 0x13a5, 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505,
+	0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff,
+	0x78ae, 0x0018, 0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13a3, 0x2009,
+	0x0000, 0x786c, 0xa065, 0x0118, 0x8108, 0x6000, 0x0cd8, 0x7ac4,
+	0x0804, 0x13a1, 0x2009, 0x4348, 0x210c, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1904, 0x13a2, 0x2011, 0x4388, 0x2214, 0x0804, 0x13a1,
+	0x2009, 0x4349, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
+	0x13a2, 0x2011, 0x4389, 0x2214, 0x0804, 0x13a1, 0x2061, 0x4340,
+	0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1148, 0x2061, 0x4380, 0x6328, 0x73da, 0x632c, 0x831c,
+	0x831c, 0x831c, 0x73de, 0x0804, 0x13a1, 0x2009, 0x434c, 0x210c,
+	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011, 0x438c,
+	0x2214, 0x0804, 0x13a1, 0x7918, 0x0804, 0x13a2, 0x2009, 0x434d,
+	0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011,
+	0x438d, 0x2214, 0x0804, 0x13a1, 0x2009, 0x434e, 0x210c, 0x2001,
+	0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011, 0x438e, 0x2214,
+	0x0804, 0x13a1, 0x7920, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
+	0x13a2, 0x7a24, 0x0804, 0x13a1, 0x2011, 0x4840, 0x71c4, 0xd1fc,
+	0x1110, 0x2011, 0x47c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xa268, 0x6a00, 0x6b08, 0x6c1c, 0x74da, 0x0804, 0x13a0,
+	0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091,
+	0x8001, 0x2708, 0x0804, 0x13a0, 0x2061, 0x4340, 0x6118, 0x2001,
+	0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2061, 0x4380, 0x6218,
+	0x0804, 0x13a1, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6908,
+	0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0804, 0x13a0, 0x71c4,
+	0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x1a04, 0x139c, 0x080c,
+	0x230e, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13a0,
+	0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x1a04, 0x139c, 0xd1bc,
+	0x1120, 0x2011, 0x4348, 0x2204, 0x0020, 0x2011, 0x4388, 0x2204,
+	0xc0bd, 0x0006, 0x2100, 0xc0bc, 0x2012, 0x080c, 0x22b4, 0x001e,
+	0x0804, 0x13a2, 0x71c4, 0x2021, 0x4349, 0x2404, 0x70c6, 0x2019,
+	0x0000, 0x0030, 0x71c8, 0x2021, 0x4389, 0x2404, 0x70ca, 0xc3fd,
+	0x2011, 0x15fe, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0138, 0x8210,
+	0x1f04, 0x15e4, 0x71c4, 0x72c8, 0x0804, 0x139b, 0xa292, 0x15fe,
+	0x0026, 0x2122, 0x001e, 0x080c, 0x22c6, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1110, 0xd3fc, 0x09f0, 0x0804, 0x13a3, 0x03e8, 0x00fa,
+	0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4340,
+	0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8,
+	0x8003, 0x8003, 0x8003, 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+	0x11a0, 0x0026, 0x0016, 0x2061, 0x4380, 0x6128, 0x622c, 0x8214,
+	0x8214, 0x8214, 0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003,
+	0x602e, 0x71da, 0x72de, 0x001e, 0x002e, 0x0804, 0x13a1, 0x2061,
+	0x4340, 0x6130, 0x70c4, 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+	0x1904, 0x13a2, 0x2061, 0x4380, 0x6230, 0x70c8, 0x6032, 0x0804,
+	0x13a1, 0x7918, 0x0804, 0x13a2, 0x71c4, 0xa184, 0xffcf, 0x0148,
+	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x139c, 0x72c8, 0x0804,
+	0x139b, 0x2011, 0x434d, 0x2204, 0x2112, 0x0006, 0x2019, 0x0000,
+	0x080c, 0x2302, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x001e,
+	0x0804, 0x13a2, 0x71c8, 0xa184, 0xffcf, 0x0128, 0x0006, 0x2110,
+	0x71c4, 0x0804, 0x139b, 0x2011, 0x438d, 0x2204, 0x2112, 0x0006,
+	0xc3fd, 0x080c, 0x2302, 0x002e, 0x001e, 0x0804, 0x13a1, 0x71c4,
+	0xa182, 0x0010, 0x0248, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
+	0x139c, 0x72c8, 0x0804, 0x139b, 0x2011, 0x434e, 0x2204, 0x0006,
+	0x2112, 0x2019, 0x0000, 0x080c, 0x22ef, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x0118, 0x001e, 0x0804, 0x13a2, 0x71c8, 0xa182, 0x0010,
+	0x0228, 0x0006, 0x2110, 0x71c4, 0x0804, 0x139b, 0x2011, 0x438e,
+	0x2204, 0x0006, 0x2112, 0xc3fd, 0x080c, 0x22ef, 0x002e, 0x001e,
+	0x0804, 0x13a1, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x1904, 0x139b,
+	0xa284, 0xfffd, 0x1904, 0x139b, 0x2100, 0x7920, 0x7822, 0x2200,
+	0x7a24, 0x7826, 0x0804, 0x13a1, 0x2011, 0x4840, 0x71c4, 0xd1fc,
+	0x1110, 0x2011, 0x47c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xa268, 0x72c8, 0x73cc, 0x74d8, 0x71c6, 0x6800, 0x70ca,
+	0x73ce, 0x74da, 0x2091, 0x8000, 0x6a02, 0xd2ac, 0x1118, 0x2021,
+	0x0000, 0x0078, 0xa484, 0x00ff, 0xa082, 0x0002, 0x16e8, 0x843f,
+	0xa7bc, 0x00ff, 0x0130, 0xa786, 0x0002, 0x15b0, 0xa484, 0x00ff,
+	0x0598, 0x2061, 0x0200, 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029,
+	0x0009, 0x2031, 0x0062, 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307,
+	0xa084, 0x00ff, 0x1110, 0xa73d, 0x11f8, 0x2041, 0x001d, 0x8307,
+	0xa084, 0x00ff, 0x0150, 0xa842, 0x02b8, 0xa3bc, 0x00ff, 0x2500,
+	0xa702, 0x0290, 0x2600, 0xa702, 0x1278, 0x2039, 0x003a, 0x6804,
+	0xa705, 0x6806, 0x6b0a, 0x6b0c, 0x73ce, 0x681c, 0x70da, 0x6c1e,
+	0x2091, 0x8001, 0x0804, 0x13a3, 0x2091, 0x8001, 0x0804, 0x139d,
+	0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091,
+	0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0804, 0x13a0,
+	0x70c4, 0x2061, 0x4340, 0x6118, 0x601a, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1904, 0x13a2, 0x70c8, 0x2061, 0x4380, 0x6218, 0x601a,
+	0x0804, 0x13a1, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x1a04,
+	0x139c, 0x080c, 0x2332, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020,
+	0x0804, 0x13a0, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08,
+	0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0804, 0x13a1, 0x77c4,
+	0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a,
+	0x6804, 0xa005, 0x0110, 0x080c, 0x2233, 0x2091, 0x8001, 0x2708,
+	0x0804, 0x13a1, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08,
+	0xc295, 0x6a0a, 0x6804, 0xa005, 0x0110, 0x080c, 0x2233, 0x2091,
+	0x8001, 0x2708, 0x0804, 0x13a1, 0x77c4, 0x2041, 0x0001, 0x2049,
+	0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1b35, 0x2091,
+	0x8001, 0x2708, 0x6a08, 0x0804, 0x13a1, 0x77c4, 0xd7fc, 0x0128,
+	0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110,
+	0x0804, 0x13a5, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x080c,
+	0x1bad, 0x11e8, 0x6818, 0xa005, 0x01a0, 0x2708, 0x0076, 0x080c,
+	0x2351, 0x007e, 0x1170, 0x2001, 0x0015, 0xd7fc, 0x1118, 0x2061,
+	0x4340, 0x0018, 0xc0fd, 0x2061, 0x4380, 0x782a, 0x2091, 0x8001,
+	0x0005, 0x2091, 0x8001, 0x2001, 0x4005, 0x0804, 0x13a5, 0x2091,
+	0x8001, 0x0804, 0x13a3, 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1aa9,
+	0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110, 0x0804, 0x13a5,
+	0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
+	0x8000, 0x080c, 0x1b35, 0x2009, 0x0016, 0xd7fc, 0x1118, 0x2061,
+	0x4340, 0x0018, 0x2061, 0x4380, 0xc1fd, 0x6067, 0x0003, 0x607f,
+	0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x080c, 0x2233, 0x2091,
+	0x8001, 0x0005, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128,
+	0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110,
+	0x0804, 0x13a5, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017,
+	0xd7fc, 0x1118, 0x2061, 0x4340, 0x0018, 0x2061, 0x4380, 0xc1fd,
+	0x607f, 0x0000, 0x6067, 0x0002, 0x6776, 0x6083, 0x000f, 0x792a,
+	0x080c, 0x2233, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0005,
+	0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0118, 0x60d4,
+	0xc0fd, 0x60d6, 0x080c, 0x1b35, 0x70c8, 0x6836, 0x8738, 0xa784,
+	0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005, 0x72c8, 0xd284, 0x0128,
+	0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110,
+	0x0804, 0x13a5, 0x72c8, 0x72ca, 0x78ac, 0xa084, 0x0003, 0x1508,
+	0x2039, 0x0000, 0xd284, 0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049,
+	0x0004, 0x2051, 0x0008, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6808,
+	0xc0d4, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f,
+	0x1d90, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
+	0x1d50, 0x2091, 0x8000, 0x72c8, 0x2069, 0x0100, 0xd284, 0x1110,
+	0x2069, 0x0200, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4,
+	0x01b0, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110,
+	0x1f04, 0x1885, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084,
+	0x0110, 0x1f04, 0x188e, 0x20a9, 0x00fa, 0x1f04, 0x1895, 0x2079,
+	0x4300, 0x2009, 0x0018, 0x72c8, 0xd284, 0x1118, 0x2061, 0x4340,
+	0x0018, 0x2061, 0x4380, 0xc1fd, 0x792a, 0x6067, 0x0001, 0x6083,
+	0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4,
+	0x0160, 0xc0b4, 0x60d6, 0x00c6, 0x60b8, 0xa065, 0x6008, 0xc0d4,
+	0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x60d4, 0xa084, 0x7eff,
+	0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x681b, 0x0054, 0x2091, 0x8001,
+	0x0005, 0xd7fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069, 0x4380,
+	0x71c4, 0x71c6, 0x6916, 0x81ff, 0x1110, 0x68a7, 0x0001, 0x78ac,
+	0xc08c, 0x78ae, 0xd084, 0x1110, 0x080c, 0x1c00, 0x0005, 0x75d8,
+	0x74dc, 0x75da, 0x74de, 0x0018, 0x2029, 0x0000, 0x2520, 0x71c4,
+	0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4300, 0x7dde,
+	0x7cda, 0x7bd6, 0x7ad2, 0x080c, 0x1afa, 0x0904, 0x19d7, 0x20a9,
+	0x0005, 0x20a1, 0x4314, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001,
+	0x2009, 0x0040, 0x080c, 0x1cbf, 0x0120, 0x080c, 0x1b02, 0x0804,
+	0x19d7, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x1120, 0x0006,
+	0x080c, 0x1fe3, 0x000e, 0xa084, 0xff00, 0x8007, 0x8009, 0x0904,
+	0x1981, 0x00c6, 0x2c68, 0x080c, 0x1afa, 0x05a8, 0x2c00, 0x689e,
+	0x8109, 0x1dc0, 0x609f, 0x0000, 0x00ce, 0x00c6, 0x7ddc, 0x7cd8,
+	0x7bd4, 0x7ad0, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000,
+	0xa5a9, 0x0000, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x2c68, 0x689c,
+	0xa065, 0x0904, 0x1980, 0x2009, 0x0040, 0x080c, 0x1cbf, 0x1550,
+	0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x1168, 0x6004, 0xa084,
+	0x00ff, 0xa086, 0x000a, 0x1120, 0x0016, 0x080c, 0x1fe0, 0x001e,
+	0x2d00, 0x6002, 0x0898, 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1b76,
+	0x00ce, 0x609f, 0x0000, 0x080c, 0x19db, 0x2009, 0x0018, 0x6008,
+	0xc0cd, 0x600a, 0x6004, 0x6086, 0x080c, 0x1ab7, 0x080c, 0x1b02,
+	0x0804, 0x19d7, 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1b76, 0x00ce,
+	0x609f, 0x0000, 0x080c, 0x19db, 0x2009, 0x0018, 0x6087, 0x0103,
+	0x601b, 0x0003, 0x080c, 0x1ab7, 0x080c, 0x1b02, 0x0804, 0x19d7,
+	0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1aa9, 0x01b8, 0x0018,
+	0x080c, 0x1a9b, 0x0198, 0x2029, 0x0000, 0x2520, 0x2009, 0x0018,
+	0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x080c, 0x1ab7,
+	0x080c, 0x1b02, 0x2001, 0x4007, 0x0804, 0x13a5, 0x74c4, 0x73c8,
+	0x72cc, 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc,
+	0x1118, 0x2071, 0x4340, 0x0018, 0x2071, 0x4380, 0xc1fd, 0x792a,
+	0x7067, 0x0005, 0x71d4, 0xa18c, 0xfe7f, 0x71d6, 0x736a, 0x726e,
+	0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e, 0xa02e, 0x2530,
+	0x611c, 0xa184, 0x0060, 0x0110, 0x080c, 0x3de5, 0x00ee, 0x6596,
+	0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714,
+	0x6023, 0x0000, 0x080c, 0x2233, 0x2091, 0x8001, 0x0005, 0x70c3,
+	0x4005, 0x0804, 0x13a6, 0x20a9, 0x0005, 0x2099, 0x4314, 0x2091,
+	0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210, 0xa399, 0x0000,
+	0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000,
+	0x791e, 0x0804, 0x13a3, 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069,
+	0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8,
+	0xa285, 0x0000, 0x1118, 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003,
+	0x70ca, 0x0804, 0x13a6, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003,
+	0x1a04, 0x139c, 0x7966, 0x0804, 0x13a3, 0x7964, 0x71c6, 0x0804,
+	0x13a3, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x0804, 0x13a3, 0x7900,
+	0x71c6, 0x0804, 0x13a3, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d,
+	0x0160, 0x810c, 0x0230, 0x8210, 0x810c, 0x810c, 0x0210, 0x8210,
+	0x810c, 0x81ff, 0x1904, 0x139d, 0x8210, 0x7a0e, 0xd28c, 0x0538,
+	0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019, 0x0003, 0xd284,
+	0x01c0, 0x8108, 0x2019, 0x0041, 0x2011, 0x8b4e, 0x2312, 0x2019,
+	0x0042, 0x8210, 0x2312, 0x2019, 0x0043, 0x8210, 0x2312, 0x2019,
+	0x0046, 0x8210, 0x2312, 0x2019, 0x0047, 0x8210, 0x2312, 0x2019,
+	0x0006, 0x2011, 0x8b53, 0x2112, 0x2011, 0x8b73, 0x2312, 0x7904,
+	0x7806, 0x0804, 0x13a2, 0x7804, 0x70c6, 0x0804, 0x13a3, 0x71c4,
+	0xd1fc, 0x1118, 0x2011, 0x47c0, 0x0010, 0x2011, 0x4840, 0x8107,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x2011, 0x0000,
+	0x6814, 0xd0fc, 0x0110, 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295,
+	0x0001, 0x6b0c, 0x0804, 0x13a0, 0x0016, 0x7814, 0xd0f4, 0x0138,
+	0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0050, 0xd0fc,
+	0x0138, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0008,
+	0xa006, 0x001e, 0x0005, 0x0016, 0x7814, 0xd0f4, 0x0138, 0x2001,
+	0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0008, 0xa006, 0x001e,
+	0x0005, 0x0016, 0x7814, 0xd0fc, 0x0138, 0x2001, 0x4007, 0x70db,
+	0x0001, 0xa18d, 0x0001, 0x0008, 0xa006, 0x001e, 0x0005, 0x7112,
+	0x721a, 0x731e, 0x7810, 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80,
+	0x0001, 0x8108, 0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003,
+	0x0000, 0x6084, 0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184,
+	0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
+	0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
+	0xa006, 0xa211, 0x7d10, 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80,
+	0xa421, 0x7008, 0xd0fc, 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006,
+	0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084,
+	0x01e0, 0x0005, 0x7848, 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063,
+	0x0000, 0x0005, 0x00f6, 0x2079, 0x4300, 0x7848, 0x2062, 0x2c00,
+	0xa005, 0x1110, 0x080c, 0x243b, 0x784a, 0x00fe, 0x0005, 0x2011,
+	0x8d00, 0x7a4a, 0x7bc4, 0x8319, 0x0128, 0xa280, 0x0032, 0x2012,
+	0x2010, 0x0cc8, 0x2013, 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc,
+	0x1118, 0x2011, 0x48c0, 0x0010, 0x2011, 0x68c0, 0xa784, 0x0f00,
+	0x800b, 0xa784, 0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003,
+	0xa105, 0xa268, 0x002e, 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a,
+	0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6,
+	0xd7fc, 0x1128, 0x2009, 0x4353, 0x2071, 0x4340, 0x0020, 0x2009,
+	0x4393, 0x2071, 0x4380, 0x210c, 0x6804, 0xa005, 0x0148, 0xa116,
+	0x1138, 0x2060, 0x6000, 0x6806, 0x0016, 0x200b, 0x0000, 0x0018,
+	0x2009, 0x0000, 0x0016, 0x6804, 0xa065, 0x0178, 0x6000, 0x6806,
+	0x0421, 0x080c, 0x1d30, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001,
+	0x6812, 0x1d88, 0x7910, 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906,
+	0x2d00, 0x2060, 0x080c, 0x2580, 0x00ee, 0x0005, 0xa065, 0x0160,
+	0x2008, 0x609c, 0xa005, 0x0128, 0x2062, 0x609f, 0x0000, 0xa065,
+	0x0cc0, 0x7848, 0x794a, 0x2062, 0x0005, 0x6007, 0x0103, 0x608f,
+	0x0000, 0x20a9, 0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000,
+	0x40a4, 0x6828, 0x601a, 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc,
+	0x1128, 0x2071, 0x4340, 0x2031, 0x43c0, 0x0020, 0x2071, 0x4380,
+	0x2031, 0x45c0, 0x7050, 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a,
+	0x8000, 0x7052, 0xa006, 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118,
+	0x2079, 0x4340, 0x0010, 0x2079, 0x4380, 0x080c, 0x1b1d, 0x2091,
+	0x8000, 0x6804, 0x780a, 0xa065, 0x0904, 0x1bfe, 0x0030, 0x2c00,
+	0x780a, 0x2060, 0x6000, 0xa065, 0x05c8, 0x6010, 0xa306, 0x1db8,
+	0x600c, 0xa206, 0x1da0, 0x2c28, 0x784c, 0xac06, 0x1108, 0x0458,
+	0x6804, 0xac06, 0x1140, 0x6000, 0x2060, 0x6806, 0xa005, 0x1118,
+	0x6803, 0x0000, 0x0048, 0x6400, 0x7808, 0x2060, 0x6402, 0xa486,
+	0x0000, 0x1110, 0x2c00, 0x6802, 0x2560, 0x00fe, 0x080c, 0x1b85,
+	0x00f6, 0x601b, 0x0005, 0x6023, 0x0020, 0x00fe, 0x080c, 0x1d30,
+	0x00f6, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001, 0x6812, 0x1118,
+	0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005, 0x00fe, 0x0005,
+	0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0108, 0xc7fd, 0x2041,
+	0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x080c,
+	0x1b35, 0x8738, 0xa784, 0x001f, 0x1dd0, 0xa7bc, 0xff00, 0x873f,
+	0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90, 0x2091, 0x8001, 0x007e,
+	0x0005, 0x786c, 0x2009, 0x8b74, 0x210c, 0xa10d, 0x0118, 0xa065,
+	0x0804, 0x1ffe, 0x2061, 0x0000, 0x6018, 0xd084, 0x11b8, 0x7810,
+	0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc, 0x2069, 0x4340, 0x0028,
+	0xc08d, 0x7812, 0x2069, 0x4380, 0xc7fd, 0x2091, 0x8000, 0x681c,
+	0x681f, 0x0000, 0x2091, 0x8001, 0xa005, 0x1108, 0x0005, 0xa08c,
+	0xfff0, 0x0110, 0x080c, 0x243b, 0x0002, 0x1c5d, 0x1c60, 0x1c66,
+	0x1c6a, 0x1c5e, 0x1c6e, 0x1c5e, 0x1c5e, 0x1c5e, 0x1c73, 0x1c9f,
+	0x1ca2, 0x1ca7, 0x1c5e, 0x1c5e, 0x1c5e, 0x0005, 0x080c, 0x243b,
+	0x080c, 0x1c00, 0x2001, 0x8001, 0x0804, 0x1cb0, 0x2001, 0x8003,
+	0x0804, 0x1cb0, 0x2001, 0x8004, 0x0804, 0x1cb0, 0x080c, 0x1c00,
+	0x2001, 0x8006, 0x04e8, 0x2091, 0x8000, 0x0076, 0xd7fc, 0x1128,
+	0x2069, 0x4340, 0x2039, 0x0009, 0x0020, 0x2069, 0x4380, 0x2039,
+	0x0009, 0x6800, 0xa086, 0x0000, 0x0128, 0x000e, 0x6f1e, 0x2091,
+	0x8001, 0x0005, 0x6874, 0x007e, 0xa0bc, 0xff00, 0x2041, 0x0021,
+	0x2049, 0x0004, 0x2051, 0x0010, 0x080c, 0x1b35, 0x8738, 0xa784,
+	0x001f, 0x1dd0, 0x2091, 0x8001, 0x2001, 0x800a, 0x0088, 0x2001,
+	0x800c, 0x0070, 0x080c, 0x1c00, 0x2001, 0x800d, 0x0048, 0xd7fc,
+	0x0110, 0x78ec, 0x0008, 0x78e4, 0x70c6, 0x2001, 0x800e, 0x0000,
+	0x70c2, 0xd7fc, 0x1118, 0x70db, 0x0000, 0x0010, 0x70db, 0x0001,
+	0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x0005, 0xac80,
+	0x0001, 0x81ff, 0x0518, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084,
+	0x07ff, 0x0100, 0x7018, 0x0006, 0x701c, 0x0006, 0x7020, 0x0006,
+	0x7024, 0x0006, 0x7112, 0x81ac, 0x721a, 0x731e, 0x7422, 0x7526,
+	0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b, 0x1ee8, 0x7007,
+	0x0002, 0xa08c, 0x01e0, 0x1110, 0x53a5, 0xa006, 0x7003, 0x0000,
+	0x7007, 0x0004, 0x000e, 0x7026, 0x000e, 0x7022, 0x000e, 0x701e,
+	0x000e, 0x701a, 0x0005, 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a,
+	0x6c0e, 0x681f, 0x0201, 0x6803, 0xfd20, 0x6807, 0x0038, 0x6a1a,
+	0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109, 0x1d80, 0x0005,
+	0x70ec, 0xd0dc, 0x1520, 0x2029, 0x0001, 0x7814, 0xd0cc, 0x1160,
+	0x70ec, 0xd0e4, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1120, 0x2019,
+	0x0c0c, 0x2021, 0x000c, 0x0070, 0x70ec, 0xd0e4, 0x1128, 0x2019,
+	0x1c0c, 0x2021, 0x000c, 0x0030, 0x2019, 0x1c09, 0x2021, 0x0009,
+	0xa5ad, 0x0200, 0x6b0a, 0x6c0e, 0x6d1e, 0x6807, 0x0038, 0x0005,
+	0x6004, 0x6086, 0x2c08, 0x2063, 0x0000, 0x7868, 0xa005, 0x796a,
+	0x0110, 0x2c02, 0x0008, 0x796e, 0x0005, 0x00c6, 0x2061, 0x4300,
+	0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a,
+	0x0110, 0x2d02, 0x0008, 0x616e, 0x00ce, 0x0005, 0x2091, 0x8000,
+	0x2c04, 0x786e, 0xa005, 0x1108, 0x786a, 0x2091, 0x8001, 0x609c,
+	0xa005, 0x0188, 0x00c6, 0x2060, 0x2008, 0x609c, 0xa005, 0x0138,
+	0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005, 0x1dc8, 0x7848,
+	0x794a, 0x2062, 0x00ce, 0x7848, 0x2062, 0x609f, 0x0000, 0xac85,
+	0x0000, 0x1110, 0x080c, 0x243b, 0x784a, 0x0005, 0x20a9, 0x0010,
+	0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x1d7a,
+	0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8,
+	0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04,
+	0x1d8a, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x1d8a, 0x0006,
+	0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006,
+	0x3200, 0xa085, 0x1000, 0x0cb8, 0x7d74, 0x70d0, 0xa506, 0x0904,
+	0x1e5b, 0x7810, 0x2050, 0x7800, 0xd08c, 0x0100, 0x080c, 0x1afa,
+	0x0904, 0x1e5b, 0xa046, 0x7970, 0x2500, 0x8000, 0xa112, 0x2009,
+	0x0040, 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118, 0x8840, 0x2009,
+	0x0080, 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9,
+	0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0110,
+	0x080c, 0x1afa, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002, 0x2091,
+	0x8001, 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff, 0x1120, 0x88ff,
+	0x0904, 0x1e48, 0x0050, 0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80,
+	0x0001, 0x20a0, 0x53a5, 0x0804, 0x1e48, 0xa046, 0x7218, 0x731c,
+	0xdac4, 0x0110, 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000,
+	0xa4a3, 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0118,
+	0x7422, 0x7526, 0xa006, 0x7007, 0x0004, 0x0904, 0x1e48, 0x8cff,
+	0x0110, 0x080c, 0x1b02, 0x00ce, 0x080c, 0x1b02, 0xa046, 0x7888,
+	0x8000, 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c, 0x7b78, 0xdac4,
+	0x0110, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210,
+	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e,
+	0xdac4, 0x0588, 0x7422, 0x7526, 0x0470, 0x6014, 0xd0fc, 0x1118,
+	0x2069, 0x4340, 0x0010, 0x2069, 0x4380, 0x2091, 0x8000, 0x681f,
+	0x0002, 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060, 0x0c70, 0x788b,
+	0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0098,
+	0x00ce, 0x788b, 0x0000, 0x080c, 0x1fb9, 0x6004, 0xa084, 0x000f,
+	0x0059, 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004, 0xa084, 0x000f,
+	0x0019, 0x0804, 0x1da4, 0x0005, 0x0002, 0x1e6d, 0x1e88, 0x1ea1,
+	0x1e6d, 0x1eae, 0x1e7e, 0x1e6d, 0x1e6d, 0x1e6d, 0x1e86, 0x1e9f,
+	0x1e6d, 0x1e6d, 0x1e6d, 0x1e6d, 0x1e6d, 0x2039, 0x0400, 0x78bc,
+	0xa705, 0x78be, 0x6008, 0xa705, 0x600a, 0x080c, 0x1eea, 0x609c,
+	0x78ba, 0x609f, 0x0000, 0x080c, 0x1fa5, 0x0005, 0x78bc, 0xd0c4,
+	0x0108, 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030, 0x080c, 0x1fe3,
+	0x78bc, 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000, 0x6004, 0x8007,
+	0xa084, 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c, 0x1eea, 0x0120,
+	0x78bc, 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f05, 0x0005, 0x080c,
+	0x1fe0, 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4, 0x1108, 0x0828,
+	0x080c, 0x1eea, 0x1110, 0x0804, 0x1f05, 0x0005, 0x78bc, 0xd0c4,
+	0x0110, 0x0804, 0x1e6d, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001,
+	0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188, 0xa7bc, 0xff00,
+	0x20a9, 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc, 0x8000, 0x2011,
+	0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108, 0x00c0, 0x080c,
+	0x1b1d, 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000,
+	0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001,
+	0x1f04, 0x1ed2, 0x8211, 0x0118, 0x20a9, 0x0100, 0x0c58, 0x080c,
+	0x1b02, 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6,
+	0x1110, 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06,
+	0x1108, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130, 0x78bc, 0xc0c4,
+	0x78be, 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6, 0xa02e, 0x2530,
+	0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, 0x2048, 0xa984,
+	0xe1ff, 0x601e, 0xa984, 0x0060, 0x0110, 0x080c, 0x3de5, 0x6596,
+	0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4380, 0xd7fc, 0x1110,
+	0x2071, 0x4340, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x0120,
+	0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700,
+	0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100,
+	0x60c2, 0x2091, 0x8000, 0x6e08, 0xd684, 0x0170, 0xd9fc, 0x1160,
+	0x2091, 0x8001, 0x080c, 0x1b85, 0x2091, 0x8000, 0x080c, 0x1d30,
+	0x2091, 0x8001, 0x0804, 0x1fa3, 0x6024, 0xa096, 0x0001, 0x1110,
+	0x8000, 0x6026, 0x6a10, 0x6814, 0xa202, 0x0268, 0x0160, 0x2091,
+	0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x080c,
+	0x1fa5, 0x0804, 0x1fa3, 0x2c08, 0xd9fc, 0x01f0, 0x6800, 0xa065,
+	0x01d8, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0168, 0x704c, 0xa206,
+	0x1150, 0x6b04, 0x2160, 0x2304, 0x6002, 0xa005, 0x1108, 0x6902,
+	0x2260, 0x6102, 0x0098, 0x2d00, 0x2060, 0x080c, 0x2580, 0x6e08,
+	0x2160, 0x6202, 0x6906, 0x0050, 0x6800, 0x6902, 0xa065, 0x0110,
+	0x6102, 0x0008, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0xd9fc,
+	0x0118, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08, 0x8528, 0x7d0a,
+	0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0128, 0xa6b6, 0x0040,
+	0x6e0a, 0x080c, 0x1b96, 0x00ee, 0x0005, 0x6008, 0xa705, 0x600a,
+	0x2091, 0x8000, 0x080c, 0x1d30, 0x2091, 0x8001, 0x78b8, 0xa065,
+	0x0128, 0x609c, 0x78ba, 0x609f, 0x0000, 0x0c78, 0x78b6, 0x78ba,
+	0x0005, 0x7970, 0x7874, 0x2818, 0xd384, 0x0118, 0x8000, 0xa112,
+	0x0220, 0x8000, 0xa112, 0x1278, 0xc384, 0x7a7c, 0x721a, 0x7a78,
+	0x721e, 0xdac4, 0x0120, 0x7a84, 0x7222, 0x7a80, 0x7226, 0xa006,
+	0xd384, 0x0108, 0x8000, 0x7876, 0x70d2, 0x781c, 0xa005, 0x0138,
+	0x8001, 0x781e, 0x1120, 0x0e04, 0x1fdf, 0x2091, 0x4080, 0x0005,
+	0x2039, 0x1ff5, 0x0010, 0x2039, 0x1ffb, 0x2704, 0xa005, 0x0160,
+	0xac00, 0x2068, 0x6908, 0x6810, 0x6912, 0x680a, 0x690c, 0x6814,
+	0x6916, 0x680e, 0x8738, 0x0c88, 0x0005, 0x0003, 0x0009, 0x000f,
+	0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000,
+	0x780c, 0x0002, 0x21a7, 0x2182, 0x2006, 0x2076, 0x2039, 0x8b74,
+	0x2734, 0x7d10, 0x00c0, 0x6084, 0xa086, 0x0103, 0x1904, 0x2060,
+	0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, 0x11d8, 0x0804, 0x2060,
+	0x8603, 0xa080, 0x8b55, 0x620c, 0x2202, 0x8000, 0x6210, 0x2202,
+	0x080c, 0x1d4e, 0x8630, 0xa68e, 0x000f, 0x0904, 0x20e1, 0x786c,
+	0xa065, 0x1d08, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a,
+	0x0005, 0xa682, 0x0003, 0x1a04, 0x20e1, 0x2091, 0x8000, 0x2069,
+	0x0000, 0x6818, 0xd084, 0x11f8, 0x2011, 0x8b55, 0x2204, 0x70c6,
+	0x8210, 0x2204, 0x70ca, 0xd684, 0x1130, 0x8210, 0x2204, 0x70da,
+	0x8210, 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001,
+	0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001,
+	0x203b, 0x0000, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x0804, 0x20e1,
+	0x263a, 0x080c, 0x21ad, 0x1904, 0x21c9, 0x786c, 0xa065, 0x1904,
+	0x200b, 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108,
+	0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804, 0x21c9, 0x2039, 0x8b74,
+	0x2734, 0x7d10, 0x00a0, 0x6084, 0xa086, 0x0103, 0x1904, 0x20cb,
+	0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, 0x11b8, 0x0804, 0x20cb,
+	0xa680, 0x8b55, 0x620c, 0x2202, 0x080c, 0x1d4e, 0x8630, 0xa68e,
+	0x001e, 0x0904, 0x20e1, 0x786c, 0xa065, 0x1d28, 0x7808, 0xa602,
+	0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0006, 0x1a04,
+	0x20e1, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8,
+	0x2011, 0x8b55, 0x2009, 0x8b4e, 0x26a8, 0x211c, 0x2204, 0x201a,
+	0x8108, 0x8210, 0x1f04, 0x20ad, 0xa685, 0x8030, 0x70c2, 0x681b,
+	0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091,
+	0x8001, 0xa006, 0x2009, 0x8b75, 0x200a, 0x203a, 0x0005, 0x7810,
+	0xc0ad, 0x7812, 0x00b0, 0x263a, 0x080c, 0x21ad, 0x1904, 0x21c9,
+	0x786c, 0xa065, 0x1904, 0x207b, 0x2091, 0x8000, 0x7810, 0xa084,
+	0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804,
+	0x21c9, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994, 0x70d4, 0xa102,
+	0x0228, 0x0168, 0x7b90, 0xa302, 0x1150, 0x0010, 0x8002, 0x1138,
+	0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0005, 0xa184,
+	0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
+	0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210, 0x721a,
+	0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0130, 0x7aa4, 0xa211,
+	0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030, 0x7003, 0x0000,
+	0x2009, 0x8b54, 0x260a, 0x8109, 0x2198, 0x2104, 0xd084, 0x0108,
+	0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, 0x8603, 0x7012, 0x7007,
+	0x0001, 0x7990, 0x7894, 0x8000, 0xa10a, 0x1208, 0xa006, 0x2028,
+	0x7974, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004,
+	0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x797c,
+	0xa108, 0x7a78, 0xa006, 0xa211, 0xd4c4, 0x0120, 0x7b84, 0xa319,
+	0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x01d0,
+	0x7d10, 0x2031, 0x8b54, 0x2634, 0x78a8, 0x8000, 0x78aa, 0xd08c,
+	0x1138, 0x7007, 0x0006, 0x7004, 0xd094, 0x1de8, 0x0804, 0x20e3,
+	0x2069, 0x4347, 0x206b, 0x0003, 0x78ac, 0xa085, 0x0300, 0x78ae,
+	0xa006, 0x0048, 0x2030, 0x75d6, 0x2091, 0x4080, 0x7d96, 0x7d10,
+	0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001, 0x78aa, 0x7007, 0x0006,
+	0x263a, 0x7003, 0x0001, 0x711a, 0x721e, 0xd5c4, 0x0110, 0x7322,
+	0x7426, 0x0005, 0x6084, 0xa086, 0x0103, 0x11d8, 0x6114, 0x6018,
+	0xa105, 0x11b8, 0x2069, 0x0000, 0x6818, 0xd084, 0x1190, 0x600c,
+	0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091,
+	0x4080, 0x080c, 0x1d4e, 0x0e04, 0x21a0, 0x786c, 0xa065, 0x1d10,
+	0x0005, 0x0059, 0x1530, 0x786c, 0xa065, 0x19e0, 0x0410, 0x0029,
+	0x1500, 0x786c, 0xa065, 0x1dd8, 0x00e0, 0x6084, 0xa086, 0x0103,
+	0x1168, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004, 0x1138, 0x7804,
+	0xd0a4, 0x0120, 0x080c, 0x1d4e, 0xa006, 0x0005, 0x0079, 0x1118,
+	0xa085, 0x0001, 0x0005, 0x00b9, 0x1110, 0x2041, 0x0001, 0x7d10,
+	0x0005, 0x88ff, 0x0110, 0x2091, 0x4080, 0x0005, 0x7b90, 0x7994,
+	0x70d4, 0xa102, 0x1118, 0xa385, 0x0000, 0x0005, 0x0210, 0xa302,
+	0x0005, 0x8002, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c,
+	0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004,
+	0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa210, 0xa006, 0xa319,
+	0xa421, 0xa529, 0x2009, 0x0018, 0x6028, 0xa005, 0x0110, 0x2009,
+	0x0040, 0x080c, 0x1ab7, 0x01d0, 0x78a8, 0x8000, 0x78aa, 0xd08c,
+	0x1510, 0x6014, 0xd0fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069,
+	0x4380, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000, 0x78ac,
+	0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0068, 0x78ab, 0x0000,
+	0x080c, 0x1d4e, 0x7990, 0x7894, 0x8000, 0xa10a, 0x1208, 0xa006,
+	0x7896, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091, 0x8001, 0x0005,
+	0x2138, 0xd7fc, 0x1118, 0x2009, 0x4359, 0x0010, 0x2009, 0x4399,
+	0x2091, 0x8000, 0x200a, 0x00f6, 0x2009, 0x4380, 0x2079, 0x0100,
+	0xd7fc, 0x1120, 0x2009, 0x4340, 0x2079, 0x0200, 0x2104, 0xa086,
+	0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009, 0x4345, 0x0010, 0x2009,
+	0x4385, 0x2104, 0xa005, 0x1130, 0x7830, 0xa084, 0x00c0, 0x1110,
+	0x781b, 0x0052, 0x00fe, 0x0005, 0x2009, 0x0002, 0x2069, 0x4300,
+	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x22a9, 0x2071, 0x4380,
+	0x2079, 0x0100, 0x2021, 0x45bf, 0x784b, 0x000f, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x0118, 0x2019, 0x3c3b, 0x0030, 0x20a1, 0x012b,
+	0x2019, 0x3c3b, 0xd184, 0x0110, 0x20a1, 0x022b, 0x2304, 0xa005,
+	0x0140, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318,
+	0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af,
+	0x0000, 0x78af, 0x2020, 0x1f04, 0x2287, 0x7003, 0x0000, 0x0016,
+	0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd, 0x080c, 0x23bd, 0x001e,
+	0x7020, 0xa084, 0x000f, 0xa085, 0x6300, 0x7806, 0x780f, 0x9000,
+	0x7843, 0x00d8, 0x7853, 0x0090, 0x780b, 0x0308, 0x7456, 0x7053,
+	0x0000, 0x8109, 0x0140, 0x2071, 0x4340, 0x2079, 0x0200, 0x2021,
+	0x43bf, 0x0804, 0x2264, 0x0005, 0x0016, 0x2011, 0x0101, 0xd1bc,
+	0x1110, 0x2011, 0x0201, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0,
+	0xa105, 0x2012, 0x001e, 0x080c, 0x23bd, 0x0005, 0x2011, 0x0101,
+	0xd3fc, 0x1110, 0x2011, 0x0201, 0x20a9, 0x0009, 0x810b, 0x1f04,
+	0x22ce, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012,
+	0x0005, 0x2019, 0x0002, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213,
+	0x1f04, 0x22df, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205,
+	0x200a, 0x8319, 0x0118, 0x2009, 0x0201, 0x0c78, 0x0005, 0x2011,
+	0x0101, 0xd3fc, 0x1110, 0x2011, 0x0201, 0x20a9, 0x000c, 0x810b,
+	0x1f04, 0x22f7, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105,
+	0x2012, 0x0005, 0x2011, 0x0102, 0xd3fc, 0x1110, 0x2011, 0x0202,
+	0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061,
+	0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003,
+	0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6,
+	0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103,
+	0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae,
+	0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061,
+	0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4,
+	0xa28c, 0x0020, 0x0118, 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4,
+	0x1108, 0xc3ed, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce,
+	0x0005, 0x2091, 0x8000, 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904,
+	0x23a1, 0xd1fc, 0x0118, 0x2061, 0x8ad0, 0x0010, 0x2061, 0x89c0,
+	0x080c, 0x23a9, 0x0538, 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061,
+	0x89d0, 0x0010, 0x2061, 0x88c0, 0x00c6, 0x04d9, 0x0128, 0x00ce,
+	0x8c60, 0x1f04, 0x236c, 0x0468, 0x000e, 0xd1fc, 0x0128, 0xa082,
+	0x89d0, 0x2071, 0x4380, 0x0020, 0xa082, 0x88c0, 0x2071, 0x4340,
+	0x707a, 0x7176, 0x2001, 0x0004, 0x7066, 0x7083, 0x000f, 0x080c,
+	0x2228, 0x00a0, 0xd1fc, 0x1118, 0x2071, 0x4340, 0x0010, 0x2071,
+	0x4380, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2c00, 0x707e, 0x2001,
+	0x0006, 0x7066, 0x7083, 0x000f, 0x080c, 0x2228, 0x2001, 0x0000,
+	0x0010, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce,
+	0x0005, 0x2c04, 0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140,
+	0x600c, 0xa206, 0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020,
+	0x6000, 0x0c80, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016,
+	0x2079, 0x4380, 0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4340,
+	0x2071, 0x0200, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110,
+	0x001e, 0x0060, 0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d,
+	0x0800, 0xd0bc, 0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe,
+	0x0005, 0x00e6, 0x2001, 0x4301, 0x2004, 0xd0ac, 0x1904, 0x2439,
+	0x68e4, 0xd0ac, 0x0904, 0x2439, 0xa084, 0x0006, 0x1904, 0x2439,
+	0x6014, 0xd0fc, 0x1118, 0x2071, 0x47c0, 0x0010, 0x2071, 0x4840,
+	0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004,
+	0xa084, 0x000a, 0x15b0, 0x7108, 0xa194, 0xff00, 0x0590, 0xa18c,
+	0x00ff, 0x2001, 0x000a, 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106,
+	0x01a0, 0x2001, 0x0012, 0xa106, 0x0198, 0x2001, 0x0014, 0xa106,
+	0x0190, 0x2001, 0x0019, 0xa106, 0x0188, 0x2001, 0x0032, 0xa106,
+	0x0180, 0x0090, 0x2009, 0x000c, 0x0088, 0x2009, 0x0012, 0x0070,
+	0x2009, 0x0014, 0x0058, 0x2009, 0x0019, 0x0040, 0x2009, 0x0020,
+	0x0028, 0x2009, 0x003f, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205,
+	0x700a, 0x00ee, 0x0005, 0x0e04, 0x243b, 0x2091, 0x8000, 0x2071,
+	0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e, 0x2071, 0x0010,
+	0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x0a01, 0x70df,
+	0x0013, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0cf8,
+	0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e, 0x7592, 0x7496,
+	0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0138, 0xd7bc, 0x1128,
+	0xa784, 0x007d, 0x1904, 0x3ace, 0x0871, 0xa49c, 0x000f, 0xa382,
+	0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418, 0x8507, 0xa084,
+	0x000f, 0x0002, 0x2a4f, 0x2b10, 0x2b38, 0x2d71, 0x30cc, 0x3112,
+	0x31a7, 0x3220, 0x32db, 0x33a6, 0x248d, 0x248a, 0x285b, 0x295c,
+	0x30a0, 0x248a, 0x080c, 0x243b, 0x0005, 0xa006, 0x0038, 0x7808,
+	0xc08d, 0x780a, 0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060,
+	0xa005, 0x1904, 0x25d9, 0x7064, 0xa084, 0x0007, 0x0002, 0x24a7,
+	0x2513, 0x251b, 0x2524, 0x252d, 0x25bf, 0x2536, 0x2513, 0x7830,
+	0xd0bc, 0x1d10, 0x71d4, 0xd1b4, 0x1904, 0x24f0, 0x70a4, 0xa086,
+	0x0001, 0x09d0, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b,
+	0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d,
+	0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0,
+	0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0804, 0x270a, 0x7060, 0xa005,
+	0x1904, 0x248c, 0x00c6, 0x00d6, 0x70b4, 0xa06d, 0x6800, 0xa065,
+	0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10,
+	0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa,
+	0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0804, 0x270a,
+	0x080c, 0x3a8d, 0x1904, 0x248c, 0x781b, 0x0068, 0x70bc, 0xa06d,
+	0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
+	0x7808, 0xc08d, 0x780a, 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8,
+	0xa065, 0x68c0, 0x705a, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80,
+	0x0009, 0x7046, 0x0005, 0x080c, 0x3a8d, 0x1120, 0x781b, 0x0054,
+	0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128, 0x2011, 0x000c,
+	0x0419, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128, 0x2011,
+	0x0006, 0x00d1, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128,
+	0x2011, 0x000d, 0x0089, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d,
+	0x1150, 0x2011, 0x0006, 0x0041, 0x707c, 0x707f, 0x0000, 0x2068,
+	0x704e, 0x7003, 0x0001, 0x0005, 0x7174, 0xc1fc, 0x8107, 0x7882,
+	0x789b, 0x0080, 0xa286, 0x000c, 0x1120, 0x7aaa, 0x2001, 0x0001,
+	0x0098, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d,
+	0x0120, 0x7aaa, 0x2001, 0x0002, 0x0038, 0x78ab, 0x0020, 0x7178,
+	0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa, 0x785b,
+	0x0004, 0x781b, 0x0113, 0x080c, 0x3aa0, 0x7083, 0x000f, 0x70d4,
+	0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6, 0x70b8, 0xa065, 0x6008,
+	0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005,
+	0x7014, 0xa005, 0x1138, 0x70d4, 0xd0b4, 0x0128, 0x70b8, 0xac06,
+	0x1110, 0x0c29, 0x0005, 0x0016, 0x71a4, 0xa186, 0x0001, 0x0528,
+	0x00d6, 0x0026, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068,
+	0x6800, 0xac06, 0x0120, 0x8211, 0x01b0, 0x00c9, 0x0cc8, 0x00c6,
+	0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068, 0x6800, 0x2060,
+	0x6008, 0xa084, 0xfbef, 0x600a, 0x8211, 0x0110, 0x0041, 0x0cb0,
+	0x70a7, 0x0001, 0x00ce, 0x002e, 0x00de, 0x001e, 0x0005, 0xade8,
+	0x0005, 0x70ac, 0xad06, 0x1110, 0x70a8, 0x2068, 0x0005, 0x080c,
+	0x3a8d, 0x1904, 0x248c, 0x707c, 0x2068, 0x7774, 0x080c, 0x396d,
+	0x2c50, 0x080c, 0x3b28, 0x789b, 0x0080, 0x6814, 0xa084, 0x001f,
+	0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0804,
+	0x270f, 0x080c, 0x3a8d, 0x1904, 0x248c, 0x789b, 0x0080, 0x7060,
+	0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6,
+	0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
+	0x601a, 0x00ce, 0x080c, 0x396d, 0x2c50, 0x080c, 0x3b28, 0x6824,
+	0xa005, 0x0130, 0xa082, 0x0006, 0x0208, 0x0010, 0x6827, 0x0005,
+	0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041,
+	0x0001, 0x2001, 0x0003, 0x0804, 0x270f, 0xc28d, 0x72d6, 0x72c0,
+	0xa200, 0xa015, 0x7154, 0x8108, 0xa12a, 0x0208, 0x71c0, 0x2164,
+	0x6504, 0x85ff, 0x1170, 0x7156, 0x8421, 0x1da8, 0x70d4, 0xd08c,
+	0x0128, 0x70d0, 0xa005, 0x1110, 0x70d3, 0x000a, 0x0005, 0x2200,
+	0x0c90, 0x70d4, 0xc08c, 0x70d6, 0x70d3, 0x0000, 0x6034, 0xa005,
+	0x1db0, 0x6708, 0xa784, 0x073f, 0x01d0, 0xd7d4, 0x1d80, 0xa784,
+	0x0021, 0x1d68, 0xa784, 0x0002, 0x0130, 0xa784, 0x0004, 0x0d38,
+	0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x1d08, 0xa784, 0x0100,
+	0x0130, 0x6018, 0xa005, 0x19d8, 0xa7bc, 0xfeff, 0x670a, 0x2568,
+	0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6318, 0x0128, 0x601c,
+	0xa302, 0x0220, 0x0118, 0x0858, 0x83ff, 0x1948, 0x2d58, 0x2c50,
+	0x7156, 0xd7bc, 0x1110, 0x7028, 0x6022, 0xc7bc, 0x670a, 0x68c0,
+	0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001, 0x6b14, 0xa39c,
+	0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0110, 0xd684, 0x0110, 0xa39c,
+	0xffbf, 0xd6a4, 0x0110, 0xa39d, 0x0020, 0xa684, 0x000e, 0x1904,
+	0x26c1, 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001,
+	0x1178, 0x70d4, 0xd0b4, 0x1160, 0x7000, 0xa082, 0x0002, 0x1240,
+	0x7830, 0xd0bc, 0x1128, 0x789b, 0x0080, 0x7baa, 0x0804, 0x2708,
+	0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005, 0x70ac, 0xa606,
+	0x1108, 0x76a8, 0x76b2, 0x2c3a, 0x8738, 0x2d3a, 0x8738, 0x283a,
+	0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc, 0x0150, 0x2091,
+	0x8000, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000,
+	0x2090, 0xaad5, 0x0000, 0x0120, 0x8421, 0x2200, 0x1904, 0x2612,
+	0x0005, 0xd1dc, 0x0904, 0x35d5, 0x2029, 0x0020, 0xd69c, 0x1120,
+	0x8528, 0xd68c, 0x1108, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108,
+	0xa18c, 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0188, 0x6014,
+	0xa706, 0x1dd0, 0x60b8, 0x8001, 0x60ba, 0x1d88, 0x2a60, 0x6008,
+	0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x1904, 0x2612, 0x0005,
+	0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008, 0xc0d5,
+	0x600a, 0x77a4, 0xa786, 0x0001, 0x1904, 0x2698, 0x70d4, 0xd0b4,
+	0x1904, 0x2698, 0x7000, 0xa082, 0x0002, 0x1a04, 0x2698, 0x7830,
+	0xd0bc, 0x1904, 0x2698, 0x789b, 0x0080, 0x7baa, 0x7daa, 0x79aa,
+	0x2001, 0x0002, 0x0006, 0x6018, 0x8000, 0x601a, 0x0008, 0x0006,
+	0x2960, 0x6104, 0x2a60, 0x080c, 0x3b3b, 0x1590, 0xa184, 0x0018,
+	0x0180, 0xa184, 0x0010, 0x0118, 0x080c, 0x3776, 0x1548, 0xa184,
+	0x0008, 0x0138, 0x69a0, 0xa184, 0x0600, 0x1118, 0x080c, 0x3696,
+	0x00f8, 0x69a0, 0xa184, 0x1e00, 0x0528, 0xa184, 0x0800, 0x0178,
+	0x00c6, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d,
+	0x0010, 0x6106, 0x00ce, 0x080c, 0x3776, 0x1150, 0x69a0, 0xa184,
+	0x0200, 0x0118, 0x080c, 0x36d9, 0x0018, 0xa184, 0x0400, 0x19f0,
+	0x69a0, 0xa184, 0x1000, 0x0130, 0x6914, 0xa18c, 0xff00, 0x810f,
+	0x080c, 0x231f, 0x002e, 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0128,
+	0xa086, 0x0060, 0x1110, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6,
+	0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc,
+	0x0168, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0328, 0xa08a,
+	0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa, 0x3518,
+	0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b,
+	0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0,
+	0xa286, 0x0020, 0x1508, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba,
+	0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286, 0x0002,
+	0x0904, 0x27e0, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa498, 0x0005,
+	0x70ac, 0xa306, 0x1108, 0x73a8, 0x73b6, 0xa286, 0x0010, 0x0904,
+	0x248c, 0x00de, 0x00ce, 0x0005, 0x7000, 0xa005, 0x19e0, 0xa286,
+	0x0002, 0x1904, 0x27f7, 0x080c, 0x3a8d, 0x19a8, 0x6814, 0xc0fc,
+	0x8007, 0x7882, 0x2091, 0x8000, 0x781b, 0x0068, 0x68b4, 0x785a,
+	0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001,
+	0x7808, 0xc08d, 0x780a, 0x0126, 0x00d6, 0x00c6, 0x70d4, 0xa084,
+	0x2e00, 0x2090, 0x00ce, 0x00de, 0x012e, 0x2900, 0x705a, 0x68bc,
+	0x7042, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046,
+	0x7830, 0xd0bc, 0x0140, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d,
+	0x2091, 0x8000, 0x2090, 0x70a4, 0xa005, 0x1108, 0x0005, 0x8421,
+	0x0de8, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0804, 0x2612, 0xa286,
+	0x0010, 0x1560, 0x080c, 0x3a8d, 0x1904, 0x278b, 0x6814, 0xc0fc,
+	0x8007, 0x7882, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x70a4,
+	0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206, 0x1108,
+	0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002,
+	0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005, 0x6bb4, 0xa39d,
+	0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94, 0x7bd6,
+	0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x0068, 0x2900, 0x705a,
+	0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0170, 0x70d4,
+	0xa084, 0x2e00, 0xa086, 0x2600, 0x1118, 0x2009, 0x0000, 0x0010,
+	0x2009, 0x0001, 0xa284, 0x000f, 0x0023, 0xad80, 0x0009, 0x7046,
+	0x0005, 0x2859, 0x3fb8, 0x3fb8, 0x3fa6, 0x3fb8, 0x2859, 0x2859,
+	0x2859, 0x080c, 0x243b, 0x7808, 0xa084, 0xfffd, 0x780a, 0x00f6,
+	0x2079, 0x4300, 0x78ac, 0x00fe, 0xd084, 0x01c0, 0x7064, 0xa086,
+	0x0001, 0x1118, 0x7066, 0x0804, 0x293a, 0x7064, 0xa086, 0x0005,
+	0x1158, 0x707c, 0x2068, 0x681b, 0x0004, 0x6817, 0x0000, 0x6820,
+	0xa084, 0x00ff, 0xc09d, 0x6822, 0x7067, 0x0000, 0x70a7, 0x0000,
+	0x70a8, 0x70b2, 0x70b6, 0x080c, 0x256f, 0x0156, 0x2011, 0x0004,
+	0x7164, 0xa186, 0x0001, 0x0170, 0xa186, 0x0007, 0x1118, 0x701f,
+	0x0005, 0x0040, 0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0c5,
+	0x70d6, 0x0010, 0x7067, 0x0000, 0x2001, 0x430a, 0x2004, 0xa084,
+	0x00ff, 0xa086, 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110,
+	0x70a7, 0x0001, 0x0066, 0x080c, 0x3d52, 0x20a9, 0x0010, 0x2039,
+	0x0000, 0x080c, 0x3861, 0xa7b8, 0x0100, 0x1f04, 0x28b1, 0x006e,
+	0x7000, 0x0002, 0x28ee, 0x28cc, 0x28cc, 0x28c4, 0x28ee, 0x28ee,
+	0x28ee, 0x28c2, 0x080c, 0x243b, 0x7060, 0xa005, 0x0538, 0xad06,
+	0x1118, 0x6800, 0x7062, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14,
+	0x080c, 0x396d, 0x6008, 0xc0d4, 0x600a, 0x080c, 0x35ab, 0x0020,
+	0x705c, 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818,
+	0xd0fc, 0x0108, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820,
+	0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1d3d, 0xb284, 0x0800,
+	0x0118, 0x2021, 0x8ad0, 0x0010, 0x2021, 0x89c0, 0x080c, 0x293f,
+	0xb284, 0x0800, 0x0118, 0x2021, 0x4398, 0x0010, 0x2021, 0x4358,
+	0x04f1, 0x20a9, 0x0101, 0xb284, 0x0800, 0x0118, 0x2021, 0x89d0,
+	0x0010, 0x2021, 0x88c0, 0x0499, 0x8420, 0x1f04, 0x290b, 0xb284,
+	0x0600, 0x0118, 0x2061, 0x48c0, 0x0010, 0x2061, 0x68c0, 0x2021,
+	0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016,
+	0x0006, 0x2011, 0x4302, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e,
+	0xa102, 0x0338, 0x6012, 0x1128, 0x2011, 0x4304, 0x2204, 0xc0a5,
+	0x2012, 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x291b, 0x8421,
+	0x1d00, 0x015e, 0x7003, 0x0000, 0x704f, 0x0000, 0x0005, 0x0046,
+	0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006, 0x6a1a, 0x6817,
+	0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820,
+	0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1d3d, 0x000e, 0x0c48,
+	0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003, 0x0310, 0x080c,
+	0x243b, 0x2300, 0x0002, 0x2966, 0x29e3, 0x29fd, 0xa282, 0x0002,
+	0x0110, 0x080c, 0x243b, 0x7064, 0x7067, 0x0000, 0x7083, 0x0000,
+	0x0022, 0x77d4, 0xc7c5, 0x77d6, 0x0002, 0x297d, 0x297d, 0x297f,
+	0x29b7, 0x35df, 0x297d, 0x29b7, 0x297d, 0x080c, 0x243b, 0x7774,
+	0x080c, 0x3861, 0x7774, 0xa7bc, 0x8f00, 0x080c, 0x396d, 0x6018,
+	0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x89c0, 0x0010, 0x2021,
+	0x8ad0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, 0x2a17, 0x01b8,
+	0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021, 0x88c0, 0x0010,
+	0x2021, 0x89d0, 0x0046, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c,
+	0x2a17, 0x004e, 0x0118, 0x8420, 0x1f04, 0x29a2, 0x015e, 0x8738,
+	0xa784, 0x001f, 0x1990, 0x0804, 0x248f, 0x0804, 0x248f, 0x7774,
+	0x080c, 0x396d, 0x6018, 0xa005, 0x0520, 0xd7fc, 0x1118, 0x2021,
+	0x89c0, 0x0010, 0x2021, 0x8ad0, 0x2009, 0x0005, 0x2011, 0x0020,
+	0x080c, 0x2a17, 0x01b0, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118,
+	0x2021, 0x88c0, 0x0010, 0x2021, 0x89d0, 0x0046, 0x2009, 0x0005,
+	0x2011, 0x0020, 0x04e1, 0x004e, 0x0118, 0x8420, 0x1f04, 0x29d5,
+	0x015e, 0x0804, 0x248f, 0x2200, 0x0002, 0x29e8, 0x29ea, 0x29ea,
+	0x080c, 0x243b, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002, 0x0110,
+	0x2009, 0x000e, 0x6818, 0xd0fc, 0x0108, 0x691a, 0x7067, 0x0000,
+	0x70d4, 0xc0c5, 0x70d6, 0x0804, 0x3a3f, 0x2200, 0x0002, 0x2a04,
+	0x29ea, 0x2a02, 0x080c, 0x243b, 0x080c, 0x3d52, 0x7000, 0xa086,
+	0x0002, 0x1904, 0x356d, 0x080c, 0x35c5, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x080c, 0x355f, 0x0904, 0x356d, 0x0804, 0x248f, 0x2404,
+	0xa005, 0x0590, 0x2068, 0x2d04, 0x0006, 0x6814, 0xa706, 0x0118,
+	0x2d20, 0x000e, 0x0ca8, 0x000e, 0x2022, 0x691a, 0x6817, 0x0000,
+	0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084,
+	0x00ff, 0xa205, 0x6822, 0x080c, 0x1d3d, 0x2021, 0x4302, 0x241c,
+	0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x1128, 0x2021, 0x4304,
+	0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x080c,
+	0x258b, 0x080c, 0x35c5, 0x0005, 0xa085, 0x0001, 0x0ce0, 0x2300,
+	0x0002, 0x2a56, 0x2a54, 0x2abc, 0x080c, 0x243b, 0x78e4, 0xa005,
+	0x1708, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, 0x248c, 0x0010,
+	0x0304, 0x248c, 0x2008, 0xa084, 0x0030, 0x1110, 0x0804, 0x30a0,
+	0x78ec, 0xa084, 0x0003, 0x0dd0, 0x2100, 0xa084, 0x0007, 0x0002,
+	0x2a9f, 0x2aa8, 0x2a95, 0x2a78, 0x3a83, 0x3a83, 0x2a78, 0x2ab2,
+	0x080c, 0x243b, 0x7000, 0xa086, 0x0004, 0x1190, 0x7064, 0xa086,
+	0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x295c,
+	0x7064, 0xa086, 0x0006, 0x0db0, 0x7064, 0xa086, 0x0004, 0x0d90,
+	0x79e4, 0x2001, 0x0003, 0x0804, 0x2daa, 0x6818, 0xd0fc, 0x0110,
+	0x681b, 0x001d, 0x080c, 0x3837, 0x781b, 0x006e, 0x0005, 0x6818,
+	0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3837, 0x0804, 0x3a61,
+	0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3837, 0x781b,
+	0x00fa, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c,
+	0x3837, 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f, 0x11c0, 0x7000,
+	0x0002, 0x248f, 0x2ac9, 0x2acb, 0x356d, 0x356d, 0x356d, 0x2ac9,
+	0x2ac9, 0x080c, 0x243b, 0x080c, 0x35c5, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x080c, 0x355f, 0x0904, 0x356d, 0x0804, 0x248f, 0x78e4,
+	0xa005, 0x1b04, 0x2a7a, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104,
+	0x2a7a, 0x0010, 0x0304, 0x2a7a, 0x2008, 0xa084, 0x0030, 0x1118,
+	0x781b, 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003, 0x0dc8, 0x2100,
+	0xa184, 0x0007, 0x0002, 0x2b02, 0x2b06, 0x2afd, 0x2afb, 0x3a83,
+	0x3a83, 0x2afb, 0x3a7d, 0x080c, 0x243b, 0x080c, 0x383d, 0x781b,
+	0x006e, 0x0005, 0x080c, 0x383d, 0x0804, 0x3a61, 0x080c, 0x383d,
+	0x781b, 0x00fa, 0x0005, 0x080c, 0x383d, 0x781b, 0x00cb, 0x0005,
+	0x2300, 0x0002, 0x2b17, 0x2b15, 0x2b19, 0x080c, 0x243b, 0x0804,
+	0x3220, 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030,
+	0x0904, 0x3220, 0x78ec, 0xa084, 0x0003, 0x0904, 0x3220, 0xa184,
+	0x0100, 0x0d98, 0xa184, 0x0007, 0x0002, 0x2b35, 0x2b06, 0x2a95,
+	0x3a3f, 0x3a83, 0x3a83, 0x3a3f, 0x3a7d, 0x080c, 0x3a4b, 0x0005,
+	0xa282, 0x0005, 0x0310, 0x080c, 0x243b, 0x7898, 0x2040, 0x2300,
+	0x0002, 0x2b44, 0x2d41, 0x2d4b, 0x2200, 0x0002, 0x2b60, 0x2b4d,
+	0x2b60, 0x2b4b, 0x2d25, 0x080c, 0x243b, 0x789b, 0x0018, 0x78a8,
+	0x2010, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0a04, 0x3809, 0xa08a,
+	0x0004, 0x1a04, 0x3809, 0x0002, 0x3809, 0x3809, 0x3809, 0x37bf,
+	0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0148, 0x0804, 0x3809,
+	0x7000, 0xa005, 0x1dd8, 0x2011, 0x0004, 0x0804, 0x33b2, 0xa184,
+	0x00ff, 0xa08a, 0x0010, 0x1a04, 0x3809, 0x0002, 0x2b88, 0x2b86,
+	0x2b9a, 0x2b9e, 0x2c3c, 0x3809, 0x3809, 0x2c3e, 0x3809, 0x3809,
+	0x2d21, 0x2d21, 0x3809, 0x3809, 0x3809, 0x2d23, 0x080c, 0x243b,
+	0xd6e4, 0x0140, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, 0x781b,
+	0x00c6, 0x0005, 0x6818, 0xd0fc, 0x0118, 0x681b, 0x001d, 0x0c90,
+	0x0804, 0x3a3f, 0x681b, 0x001d, 0x0804, 0x3831, 0x6920, 0x6922,
+	0xa684, 0x1800, 0x15e0, 0x6820, 0xd084, 0x1904, 0x2be7, 0x6818,
+	0xa086, 0x0008, 0x1110, 0x681b, 0x0000, 0xd6d4, 0x0568, 0xd6bc,
+	0x0558, 0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d,
+	0x0718, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a,
+	0x789b, 0x0061, 0x78aa, 0x0156, 0x0136, 0x0146, 0x0016, 0x3208,
+	0xa18c, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b,
+	0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098,
+	0x53a6, 0x014e, 0x013e, 0x015e, 0x781b, 0x0071, 0x0005, 0xd6e4,
+	0x0130, 0x781b, 0x0083, 0x0005, 0x781b, 0x0083, 0x0005, 0xa684,
+	0x0060, 0x0dd0, 0xd6dc, 0x0dc0, 0xd6fc, 0x01a0, 0xc6fc, 0x7e5a,
+	0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x8007, 0xa084, 0x007f, 0xa108,
+	0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
+	0xa303, 0x68ae, 0xd6f4, 0x0118, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000,
+	0xa086, 0x0003, 0x1148, 0x0006, 0x080c, 0x3d52, 0x080c, 0x3fb8,
+	0x000e, 0x781b, 0x0080, 0x0005, 0xa006, 0x080c, 0x4083, 0x6ab0,
+	0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0120, 0x2200, 0xa422,
+	0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde,
+	0x2300, 0xa405, 0x1130, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b, 0x0080,
+	0x0005, 0x781b, 0x0080, 0x2200, 0xa115, 0x1118, 0x080c, 0x3fb8,
+	0x0005, 0x080c, 0x3fe5, 0x0005, 0x080c, 0x243b, 0x0804, 0x2cbd,
+	0x00c6, 0x7058, 0x2060, 0x7aa8, 0xa294, 0x00ff, 0xa286, 0x0004,
+	0x11d8, 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000, 0x2041, 0x0000,
+	0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x36f6, 0x080c, 0x379a,
+	0x0804, 0x2cb1, 0xa18c, 0xecff, 0x6922, 0x6104, 0xa18c, 0xffdd,
+	0x6106, 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003, 0x01d0, 0x6104,
+	0xa18c, 0x0010, 0x0548, 0x080c, 0x3969, 0x080c, 0x3776, 0x88ff,
+	0x0518, 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695,
+	0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082,
+	0x0005, 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff, 0x6922, 0x6000,
+	0xc0ec, 0x6002, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, 0x0000,
+	0xa006, 0x2010, 0x080c, 0x379a, 0xa286, 0x0001, 0x0158, 0x6104,
+	0xa18c, 0x0008, 0x01b0, 0x080c, 0x3969, 0x080c, 0x3696, 0x88ff,
+	0x1980, 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c, 0xfeff, 0x6922,
+	0x6000, 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c,
+	0x36f6, 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005,
+	0x781b, 0x0083, 0x0005, 0x0804, 0x382d, 0x2808, 0x789b, 0x0080,
+	0x2019, 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x1188,
+	0x7ca8, 0xa4a4, 0x00ff, 0xa480, 0x0002, 0xa300, 0x2018, 0xa102,
+	0x0a04, 0x2c40, 0x0904, 0x2c40, 0x24a8, 0x7aa8, 0x1f04, 0x2cd5,
+	0x0c48, 0xa284, 0x00f0, 0xa082, 0x0020, 0x06b8, 0x2200, 0xa082,
+	0x0021, 0x1698, 0x7aa8, 0x8318, 0x8318, 0x2100, 0xa302, 0x0ad0,
+	0xa286, 0x0023, 0x0980, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
+	0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a,
+	0x78a0, 0x8001, 0x0904, 0x2cb1, 0x20a8, 0x7998, 0x789b, 0x0060,
+	0x78aa, 0x2011, 0x0080, 0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa,
+	0x7a98, 0x1f04, 0x2d03, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
+	0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x8318, 0x2100, 0xa302,
+	0x0a04, 0x2cc2, 0xa284, 0x0080, 0x1904, 0x3831, 0x78a0, 0xa005,
+	0x08c8, 0x0804, 0x3831, 0x0804, 0x3809, 0x7058, 0xa04d, 0x789b,
+	0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c,
+	0x243b, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a,
+	0x0005, 0x1a04, 0x3809, 0x0002, 0x3809, 0x3615, 0x3809, 0x3726,
+	0x3b83, 0xa282, 0x0000, 0x1110, 0x080c, 0x243b, 0x080c, 0x3837,
+	0x781b, 0x0082, 0x0005, 0xa282, 0x0003, 0x1110, 0x080c, 0x243b,
+	0xd4fc, 0x11d0, 0x7064, 0xa005, 0x0110, 0x080c, 0x243b, 0x6f14,
+	0x7776, 0xa7bc, 0x8f00, 0x080c, 0x396d, 0x6008, 0xa085, 0x0021,
+	0x600a, 0x8738, 0xa784, 0x001f, 0x1db0, 0x080c, 0x383a, 0x7067,
+	0x0002, 0x701f, 0x0009, 0x0010, 0x080c, 0x3846, 0x781b, 0x0082,
+	0x0005, 0xa282, 0x0004, 0x0310, 0x080c, 0x243b, 0x2300, 0x0002,
+	0x2d7b, 0x2eff, 0x2f3b, 0xa286, 0x0003, 0x0560, 0x7200, 0x7cd8,
+	0x7ddc, 0x7fd0, 0x71d4, 0xd1b4, 0x00f0, 0x7868, 0xa084, 0x00ff,
+	0x11d0, 0xa282, 0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300, 0x781b,
+	0x0059, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
+	0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x00de,
+	0x2001, 0x0000, 0x0058, 0x783b, 0x1300, 0x781b, 0x0057, 0x2001,
+	0x0000, 0x0020, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a, 0x68a0,
+	0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f, 0x0002,
+	0x2ee0, 0x2dc5, 0x2dc2, 0x3012, 0x3085, 0x248f, 0x2dc0, 0x2dc0,
+	0x080c, 0x243b, 0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120, 0x7048,
+	0xa086, 0x0014, 0x11e8, 0x080c, 0x3d52, 0x2009, 0x0000, 0x6818,
+	0xd0fc, 0x0108, 0x7048, 0xa086, 0x0014, 0x0168, 0x6818, 0xa086,
+	0x0008, 0x1904, 0x2ea2, 0x7858, 0xd09c, 0x0904, 0x2ea2, 0x6820,
+	0xd0ac, 0x0904, 0x2ea2, 0x681b, 0x0014, 0x2009, 0x0002, 0x04a8,
+	0x7868, 0xa08c, 0x00ff, 0x0588, 0xa186, 0x0008, 0x1158, 0x6008,
+	0xc0a4, 0x600a, 0x080c, 0x355f, 0x0540, 0x080c, 0x35c5, 0x080c,
+	0x3d52, 0x0060, 0xa186, 0x0028, 0x1500, 0x6018, 0xa005, 0x0d78,
+	0x8001, 0x0d68, 0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820, 0xd084,
+	0x0904, 0x248f, 0xc084, 0x6822, 0x080c, 0x2580, 0x705c, 0x00c6,
+	0x2060, 0x6800, 0x6002, 0x00ce, 0x6004, 0x6802, 0xa005, 0x2d00,
+	0x1108, 0x6002, 0x6006, 0x0804, 0x248f, 0x0016, 0x81ff, 0x15e0,
+	0x7000, 0xa086, 0x0030, 0x05c0, 0x71d4, 0xd1b4, 0x11e8, 0x7060,
+	0xa005, 0x1590, 0x70a4, 0xa086, 0x0001, 0x0570, 0x7003, 0x0000,
+	0x0046, 0x0056, 0x0076, 0x0066, 0x00c6, 0x00d6, 0x080c, 0x24b2,
+	0x00de, 0x00ce, 0x006e, 0x007e, 0x005e, 0x004e, 0x71d4, 0xd1b4,
+	0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c, 0x3a8d, 0x11a8, 0x781b,
+	0x0068, 0x00d6, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030,
+	0x7808, 0xc08d, 0x780a, 0x00de, 0x080c, 0x2f63, 0x001e, 0x81ff,
+	0x0904, 0x2ea2, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14,
+	0xa186, 0x0002, 0x15c0, 0x6818, 0xa086, 0x0014, 0x1130, 0x2008,
+	0xd6e4, 0x0118, 0x7868, 0xa08c, 0x00ff, 0x080c, 0x3850, 0x080c,
+	0x258b, 0x6820, 0xd0dc, 0x1538, 0x8717, 0xa294, 0x000f, 0x8213,
+	0x8213, 0x8213, 0xb284, 0x0600, 0x0118, 0xa290, 0x47c0, 0x0010,
+	0xa290, 0x4840, 0xa290, 0x0000, 0x221c, 0xd3c4, 0x0130, 0x8210,
+	0x2204, 0xa085, 0x0038, 0x2012, 0x8211, 0xd3d4, 0x0138, 0x68a0,
+	0xd0c4, 0x1120, 0x080c, 0x2fcb, 0x0804, 0x248f, 0x6008, 0xc08d,
+	0x600a, 0x0008, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7048,
+	0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0168, 0x2009,
+	0x4302, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128, 0x2021,
+	0x4304, 0x2404, 0xc0a5, 0x2022, 0x6018, 0xa005, 0x0118, 0x8001,
+	0x601a, 0x1118, 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x1130,
+	0x6800, 0xa005, 0x1108, 0x6002, 0x6006, 0x0020, 0x705c, 0x2060,
+	0x6800, 0x6002, 0x2061, 0x4300, 0x6887, 0x0103, 0x2d08, 0x206b,
+	0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e,
+	0x7200, 0xa286, 0x0030, 0x0158, 0xa286, 0x0040, 0x1904, 0x248f,
+	0x7003, 0x0002, 0x704c, 0x2068, 0x68c4, 0x2060, 0x0005, 0x7003,
+	0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0,
+	0x705a, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005, 0xa282,
+	0x0004, 0x0210, 0x080c, 0x243b, 0x2200, 0x0002, 0x2f0a, 0x2f19,
+	0x2f25, 0x2f19, 0xa586, 0x1300, 0x0160, 0xa586, 0x8300, 0x1d90,
+	0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x7000, 0xa086, 0x0005, 0x0128, 0x080c, 0x3837, 0x781b,
+	0x0082, 0x0005, 0x781b, 0x0083, 0x0005, 0x7890, 0x8007, 0x8001,
+	0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff,
+	0xa186, 0x0003, 0x0128, 0xa186, 0x0000, 0x0110, 0x0804, 0x3809,
+	0x781b, 0x0083, 0x0005, 0x6820, 0xc095, 0x6822, 0x82ff, 0x1118,
+	0x080c, 0x3837, 0x0030, 0x8211, 0x0110, 0x080c, 0x243b, 0x080c,
+	0x3846, 0x781b, 0x0082, 0x0005, 0x080c, 0x3aa0, 0x7830, 0xa084,
+	0x00c0, 0x1170, 0x0016, 0x3208, 0xa18c, 0x0800, 0x001e, 0x0118,
+	0x0104, 0x2f60, 0x0010, 0x0304, 0x2f60, 0x791a, 0xa006, 0x0005,
+	0xa085, 0x0001, 0x0005, 0xa684, 0x0060, 0x1130, 0x682f, 0x0000,
+	0x6833, 0x0000, 0x0804, 0x2fca, 0xd6dc, 0x1198, 0x68b4, 0xd0dc,
+	0x1180, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x1130,
+	0x2200, 0xa105, 0x0904, 0x3d52, 0x704b, 0x0015, 0x0804, 0x3d52,
+	0x0005, 0xd6ac, 0x01f0, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833,
+	0x0000, 0x0804, 0x3d52, 0x68b4, 0xa084, 0x4000, 0xa635, 0xd6f4,
+	0x1da0, 0x7048, 0xa005, 0x1110, 0x704b, 0x0015, 0xd6dc, 0x1128,
+	0x68b4, 0xd0dc, 0x0110, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0804,
+	0x3d52, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804,
+	0x3d52, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x1da0, 0x7048,
+	0xa005, 0x1110, 0x704b, 0x0015, 0x2408, 0x2510, 0x2700, 0x8007,
+	0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100,
+	0xa205, 0x1110, 0x0804, 0x3d52, 0x7000, 0xa086, 0x0006, 0x0110,
+	0x0804, 0x3d52, 0x0005, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0108,
+	0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000,
+	0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003,
+	0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020,
+	0x7000, 0x0002, 0x248f, 0x2ffa, 0x2ff4, 0x2ff2, 0x2ff2, 0x2ff2,
+	0x2ff2, 0x2ff2, 0x080c, 0x243b, 0x6820, 0xd084, 0x1118, 0x080c,
+	0x35ab, 0x0030, 0x705c, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60,
+	0x3208, 0xa18c, 0x0600, 0x0118, 0x2021, 0x4358, 0x0010, 0x2021,
+	0x4398, 0x2404, 0xa005, 0x0110, 0x2020, 0x0cd8, 0x2d22, 0x206b,
+	0x0000, 0x0005, 0x080c, 0x35b1, 0x080c, 0x35c5, 0x6008, 0xc0cc,
+	0x600a, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a,
+	0x6944, 0x6916, 0x3208, 0xa18c, 0x0600, 0x0118, 0x2009, 0x0000,
+	0x0010, 0x2009, 0x0001, 0x080c, 0x40b1, 0xd6dc, 0x0118, 0x691c,
+	0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0148, 0x7868, 0xa08c, 0x00ff,
+	0x0118, 0x681b, 0x001e, 0x0010, 0x681b, 0x0000, 0xb284, 0x0600,
+	0x1118, 0x2021, 0x4398, 0x0010, 0x2021, 0x4358, 0x6800, 0x2022,
+	0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4,
+	0x0580, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x00d6,
+	0x00f6, 0x0156, 0x0146, 0x2079, 0x4300, 0x080c, 0x1b35, 0x014e,
+	0x015e, 0x00fe, 0x70cc, 0x2010, 0x2009, 0x0101, 0x0026, 0x2204,
+	0xa06d, 0x0140, 0x6814, 0xa706, 0x0110, 0x6800, 0x0cc8, 0x6820,
+	0xc0d5, 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80, 0x00de, 0x7067,
+	0x0003, 0x707f, 0x0000, 0x7776, 0x7083, 0x000f, 0x71d4, 0xc1c4,
+	0x71d6, 0x080c, 0x1d3d, 0x0804, 0x248f, 0x7cd8, 0x7ddc, 0x7fd0,
+	0x080c, 0x2f63, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x080c,
+	0x3aa4, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7048,
+	0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0804, 0x248f,
+	0x7000, 0xa005, 0x1110, 0x0804, 0x248f, 0xa006, 0x080c, 0x3d52,
+	0x6920, 0xd1ac, 0x1110, 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e,
+	0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822, 0x7000, 0x0002,
+	0x248f, 0x30c2, 0x30c2, 0x30c5, 0x30c5, 0x30c5, 0x30c0, 0x30c0,
+	0x080c, 0x243b, 0x6818, 0x0804, 0x2daa, 0x6008, 0xc0a4, 0x600a,
+	0x6817, 0x0000, 0x0804, 0x357a, 0x2300, 0x0002, 0x30d1, 0x30d3,
+	0x3110, 0x080c, 0x243b, 0xd6fc, 0x1904, 0x2bee, 0x7000, 0xa00d,
+	0x0002, 0x248f, 0x30e3, 0x30e3, 0x3104, 0x30e3, 0x310d, 0x30e1,
+	0x30e1, 0x080c, 0x243b, 0xa684, 0x0060, 0xa086, 0x0060, 0x11d0,
+	0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x681c, 0xc0ac, 0x681e, 0xa186,
+	0x0002, 0x0110, 0x080c, 0x3d52, 0x080c, 0x3fb8, 0x781b, 0x0083,
+	0x71d4, 0xd1b4, 0x1904, 0x248c, 0x70a4, 0xa086, 0x0001, 0x1904,
+	0x24ce, 0x0005, 0xd6ec, 0x0d30, 0x6818, 0xd0fc, 0x0130, 0x681b,
+	0x0015, 0xd6f4, 0x0110, 0x681b, 0x0007, 0x080c, 0x3a4b, 0x0005,
+	0x080c, 0x243b, 0x2300, 0x0002, 0x3119, 0x3134, 0x3182, 0x080c,
+	0x243b, 0x7000, 0x0002, 0x3123, 0x3125, 0x3125, 0x3123, 0x3123,
+	0x3123, 0x3123, 0x3123, 0x080c, 0x243b, 0x080c, 0x3fb8, 0x681c,
+	0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x1904, 0x248c, 0x70a4, 0xa086,
+	0x0001, 0x1904, 0x24ce, 0x0005, 0xd6fc, 0x15e0, 0x7000, 0xa00d,
+	0x0002, 0x248f, 0x3149, 0x3143, 0x316a, 0x3149, 0x316f, 0x3141,
+	0x3141, 0x080c, 0x243b, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
+	0x78da, 0xa684, 0x0060, 0xa086, 0x0060, 0x11d0, 0xa6b4, 0xbfbf,
+	0xc6ed, 0x7e5a, 0xa186, 0x0002, 0x0110, 0x080c, 0x3d52, 0x080c,
+	0x3fb8, 0x781b, 0x0083, 0x681c, 0xc0b4, 0x681e, 0x71d4, 0xd1b4,
+	0x1904, 0x248c, 0x70a4, 0xa086, 0x0001, 0x1904, 0x24ce, 0x0005,
+	0xd6ec, 0x0d30, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0007, 0x781b,
+	0x00fb, 0x0005, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100,
+	0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b,
+	0x0083, 0x0005, 0xd6dc, 0x0130, 0x782b, 0x3009, 0x781b, 0x0083,
+	0x0804, 0x248c, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008,
+	0x1150, 0xa484, 0x0200, 0x0108, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b,
+	0x0083, 0x0804, 0x248c, 0x6820, 0xc095, 0x6822, 0x080c, 0x39ca,
+	0xc6dd, 0x080c, 0x3837, 0x781b, 0x0082, 0x0804, 0x248c, 0x2300,
+	0x0002, 0x31ac, 0x31ae, 0x31b0, 0x080c, 0x243b, 0x0804, 0x3831,
+	0x7d98, 0xd6d4, 0x11f8, 0x79e4, 0xd1ac, 0x0130, 0x78ec, 0xa084,
+	0x0003, 0x0110, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000,
+	0xa684, 0xfffb, 0x785a, 0x7d9a, 0x79e4, 0xd1ac, 0x0120, 0x78ec,
+	0xa084, 0x0003, 0x1120, 0x2001, 0x0014, 0x0804, 0x2daa, 0xa184,
+	0x0007, 0x04c2, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8,
+	0x81ff, 0x0568, 0x789b, 0x0080, 0x7ba8, 0xa384, 0x0001, 0x11d0,
+	0x7ba8, 0x7ba8, 0xa386, 0x0004, 0x1118, 0x2009, 0xffdf, 0x0058,
+	0xa386, 0x0001, 0x1118, 0x2009, 0xfff7, 0x0028, 0xa386, 0x0003,
+	0x1148, 0x2009, 0xffef, 0x00c6, 0x7058, 0x2060, 0x6004, 0xa104,
+	0x6006, 0x00ce, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
+	0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xecff, 0x6922, 0x7d9a,
+	0x0804, 0x3a3f, 0x2a9f, 0x2aa8, 0x3214, 0x321a, 0x3212, 0x3212,
+	0x3a3f, 0x3a3f, 0x080c, 0x243b, 0x6920, 0xa18c, 0xfcff, 0x6922,
+	0x0804, 0x3a45, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3a3f,
+	0x79e4, 0xa184, 0x0030, 0x0120, 0x78ec, 0xa084, 0x0003, 0x1558,
+	0x7000, 0xa086, 0x0004, 0x1190, 0x7064, 0xa086, 0x0002, 0x1130,
+	0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x295c, 0x7064, 0xa086,
+	0x0006, 0x0db0, 0x7064, 0xa086, 0x0004, 0x0d90, 0x7000, 0xa086,
+	0x0000, 0x0904, 0x248c, 0x6920, 0xa184, 0x0420, 0x0128, 0xc1d4,
+	0x6922, 0x6818, 0x0804, 0x2daa, 0x6818, 0xc0fd, 0x681a, 0x2001,
+	0x0014, 0x0804, 0x2daa, 0xa184, 0x0007, 0x0002, 0x3a3f, 0x3a3f,
+	0x325e, 0x3a3f, 0x3a83, 0x3a83, 0x3a3f, 0x3a3f, 0xd6bc, 0x0570,
+	0x7184, 0x81ff, 0x0558, 0xa182, 0x000d, 0x1318, 0x7087, 0x0000,
+	0x0028, 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061,
+	0x79aa, 0x0156, 0x0136, 0x0146, 0x7088, 0x8114, 0xa210, 0x728a,
+	0xa080, 0x000b, 0xad00, 0x2098, 0xb284, 0x0600, 0x0118, 0x20a1,
+	0x022b, 0x0010, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac,
+	0x53a6, 0x014e, 0x013e, 0x015e, 0x0804, 0x3a45, 0xd6d4, 0x1904,
+	0x32d1, 0x6820, 0xd084, 0x0904, 0x3a45, 0xa68c, 0x0060, 0xa684,
+	0x0060, 0x0120, 0xa086, 0x0060, 0x1108, 0xc1f5, 0xc194, 0x795a,
+	0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818,
+	0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0904, 0x35da, 0xa18c,
+	0x00f8, 0x1904, 0x35da, 0x0156, 0x0136, 0x0146, 0x0016, 0x20a1,
+	0x012b, 0x3208, 0xa18c, 0x0600, 0x0110, 0x20a1, 0x022b, 0x001e,
+	0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6,
+	0x014e, 0x013e, 0x015e, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0804,
+	0x3a45, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0008, 0x080c, 0x3837,
+	0x781b, 0x00ed, 0x0005, 0x2300, 0x0002, 0x32e2, 0x3398, 0x32e0,
+	0x080c, 0x243b, 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x11f0, 0x7200,
+	0xa286, 0x0003, 0x0904, 0x2d7f, 0x71d4, 0xd1b4, 0x00c0, 0x00d6,
+	0x783b, 0x8800, 0x781b, 0x0059, 0x70bc, 0xa06d, 0x68b4, 0xc0a5,
+	0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
+	0x71d6, 0x7003, 0x0030, 0x00de, 0x0030, 0x7200, 0x0020, 0x783b,
+	0x1800, 0x781b, 0x0057, 0xa284, 0x000f, 0x0002, 0x3383, 0x3344,
+	0x3318, 0x2da7, 0x3316, 0x3383, 0x3316, 0x3316, 0x080c, 0x243b,
+	0x681c, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185,
+	0x6922, 0x6800, 0x6006, 0xa005, 0x1108, 0x6002, 0x6008, 0xc0d4,
+	0x600a, 0x681c, 0xa084, 0x000e, 0x1148, 0xb284, 0x0600, 0x0118,
+	0x2009, 0x89c0, 0x0040, 0x2009, 0x8ad0, 0x0028, 0x7030, 0x68ba,
+	0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715e, 0xd6dc,
+	0x1118, 0xc6fc, 0x6eb6, 0x04f8, 0x6eb6, 0xa684, 0x0060, 0x05d8,
+	0xd6dc, 0x1150, 0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898,
+	0x68aa, 0x080c, 0x3d52, 0x0478, 0xd6ac, 0x0140, 0xa006, 0x080c,
+	0x3d52, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0068, 0x2408, 0x2510,
+	0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x69aa,
+	0x6aa6, 0x080c, 0x3d52, 0xd6fc, 0x01b0, 0xa684, 0x7fff, 0x68b6,
+	0x2510, 0x2408, 0xd6ac, 0x1138, 0x2700, 0x8007, 0xa084, 0x007f,
+	0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
+	0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, 0x0030, 0x1904, 0x248f,
+	0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065,
+	0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005,
+	0xa586, 0x8800, 0x1148, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a,
+	0x6008, 0xa084, 0xfbef, 0x600a, 0x0804, 0x3831, 0x7047, 0x0000,
+	0xa282, 0x0006, 0x0310, 0x080c, 0x243b, 0x2300, 0x0002, 0x33b2,
+	0x33e4, 0x340f, 0x2200, 0x0002, 0x33ba, 0x3831, 0x33bc, 0x33ba,
+	0x343f, 0x349d, 0x080c, 0x243b, 0x7003, 0x0005, 0xb284, 0x0600,
+	0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12, 0x2068, 0x704e,
+	0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x33cb,
+	0x015e, 0xb284, 0x0600, 0x0118, 0x6817, 0x0000, 0x0010, 0x6817,
+	0x8000, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
+	0x6827, 0x0003, 0x0804, 0x3809, 0x7000, 0xa086, 0x0002, 0x1150,
+	0x080c, 0x35c5, 0x0010, 0x080c, 0x3d52, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x0020, 0x7000, 0xa086, 0x0003, 0x0da8, 0x7003, 0x0005,
+	0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12,
+	0x2068, 0x704e, 0xad80, 0x0009, 0x7046, 0x2200, 0x0002, 0x3831,
+	0x340d, 0x340d, 0x343f, 0x340d, 0x3831, 0x080c, 0x243b, 0x7000,
+	0xa086, 0x0002, 0x1150, 0x080c, 0x35c5, 0x0010, 0x080c, 0x3d52,
+	0x6008, 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000, 0xa086, 0x0003,
+	0x0da8, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0,
+	0x0010, 0x2001, 0x8b12, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046,
+	0x2200, 0x0002, 0x343a, 0x3438, 0x3438, 0x343a, 0x3438, 0x343a,
+	0x080c, 0x243b, 0x080c, 0x3846, 0x781b, 0x0082, 0x0005, 0x7000,
+	0xa086, 0x0002, 0x1158, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba,
+	0x2d00, 0x70be, 0x0038, 0x080c, 0x3d52, 0x0020, 0x7000, 0xa086,
+	0x0003, 0x0dc8, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b,
+	0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x89c0, 0xb284,
+	0x0600, 0x1118, 0xc2fd, 0x2069, 0x8ad0, 0x2d04, 0x2d08, 0x715e,
+	0xa06d, 0x0128, 0x6814, 0xa206, 0x0500, 0x6800, 0x0cb8, 0x7003,
+	0x0005, 0xd2fc, 0x1118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12,
+	0x2068, 0x704e, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000,
+	0x1f04, 0x347d, 0x015e, 0xad80, 0x0009, 0x7046, 0x6a16, 0x68b7,
+	0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6920,
+	0xa184, 0x0c00, 0x0904, 0x3507, 0x681b, 0x0005, 0xc1ad, 0xc1d4,
+	0x6922, 0x080c, 0x383d, 0x0804, 0x3507, 0x7200, 0xa286, 0x0002,
+	0x1158, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be,
+	0x0030, 0x080c, 0x3d52, 0x0018, 0xa286, 0x0003, 0x0dd0, 0x7003,
+	0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484,
+	0x001f, 0xa215, 0xb284, 0x0600, 0x1108, 0xc2fd, 0x79a8, 0x79a8,
+	0xa18c, 0x00ff, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e, 0xa06d,
+	0x0128, 0x6814, 0xa206, 0x0538, 0x6800, 0x0cb8, 0x7003, 0x0005,
+	0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12,
+	0x2068, 0x704e, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000,
+	0x1f04, 0x34dd, 0x015e, 0xb284, 0x0600, 0x0110, 0xc2fc, 0x0008,
+	0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
+	0x0800, 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0178,
+	0xd0dc, 0x0118, 0x080c, 0x3843, 0x0050, 0x681b, 0x0005, 0xc1ad,
+	0xc1d4, 0x6922, 0x080c, 0x383d, 0x707f, 0x0000, 0x0000, 0xa6ac,
+	0x0060, 0x05c8, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x11c0,
+	0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0xa586, 0x0060,
+	0x0550, 0xc6ed, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009,
+	0x0082, 0x2019, 0x0000, 0x2320, 0x791a, 0x080c, 0x3fb8, 0x0418,
+	0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x01a0, 0x7bd2,
+	0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xc6f4, 0x7e5a, 0x2011, 0x0083,
+	0xd69c, 0x0128, 0x2011, 0x0082, 0x2019, 0x0000, 0x2320, 0x7a1a,
+	0x080c, 0x3fe5, 0x0040, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0110,
+	0x2009, 0x0082, 0x791a, 0x68c0, 0x705a, 0x2d00, 0x704e, 0x68c4,
+	0x2060, 0x71d4, 0xd1b4, 0x1904, 0x248c, 0x2300, 0xa405, 0x0904,
+	0x248c, 0x70a4, 0xa086, 0x0001, 0x1904, 0x24ce, 0x0005, 0x6020,
+	0xa005, 0x0150, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a,
+	0x700f, 0x0100, 0x702c, 0x6026, 0x0005, 0xa006, 0x080c, 0x3d52,
+	0x682b, 0x0000, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
+	0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0002, 0x248f, 0x358b,
+	0x3588, 0x35a7, 0x3594, 0x248f, 0x3586, 0x3586, 0x080c, 0x243b,
+	0x0441, 0x0409, 0x0028, 0x0429, 0x705c, 0x2060, 0x6800, 0x6002,
+	0x080c, 0x1d3d, 0x0804, 0x248f, 0x7064, 0x7067, 0x0000, 0x7083,
+	0x0000, 0x0002, 0x35a3, 0x35a3, 0x35a2, 0x35a2, 0x35a2, 0x35a3,
+	0x35a2, 0x35a3, 0x2971, 0x7067, 0x0000, 0x0804, 0x248f, 0x681b,
+	0x0000, 0x0804, 0x3012, 0x6800, 0xa005, 0x1108, 0x6002, 0x6006,
+	0x0005, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4302, 0x2104, 0x8001,
+	0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4304, 0x2404, 0xc0a5,
+	0x2022, 0x6008, 0xc0a4, 0x600a, 0x0005, 0x6018, 0xa005, 0x0110,
+	0x8001, 0x601a, 0x0005, 0x080c, 0x3aa0, 0x681b, 0x0018, 0x04a0,
+	0x080c, 0x3aa0, 0x681b, 0x0019, 0x0478, 0x080c, 0x3aa0, 0x681b,
+	0x001a, 0x0450, 0x080c, 0x3aa0, 0x681b, 0x0003, 0x0428, 0x7774,
+	0x080c, 0x396d, 0x7178, 0xa18c, 0x00ff, 0x3210, 0xa294, 0x0600,
+	0x0118, 0xa1e8, 0x88c0, 0x0010, 0xa1e8, 0x89d0, 0x2d04, 0x2d08,
+	0x2068, 0xa005, 0x1118, 0x707e, 0x0804, 0x248f, 0x6814, 0xc0fc,
+	0x7274, 0xc2fc, 0xa206, 0x0110, 0x6800, 0x0c88, 0x6800, 0x200a,
+	0x681b, 0x0005, 0x707f, 0x0000, 0x080c, 0x35b1, 0x6820, 0xd084,
+	0x1110, 0x080c, 0x35ab, 0x080c, 0x35c5, 0x681f, 0x0000, 0x6823,
+	0x0020, 0x080c, 0x1d3d, 0x0804, 0x248f, 0xa282, 0x0003, 0x1904,
+	0x380d, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920,
+	0xc1bd, 0x6922, 0xd1c4, 0x0590, 0xc1c4, 0x6922, 0xa6b4, 0x00ff,
+	0x0510, 0xa682, 0x001c, 0x0218, 0x0110, 0x2031, 0x001c, 0x852b,
+	0x852b, 0x2041, 0x0000, 0x080c, 0x38c6, 0x0118, 0x080c, 0x36f6,
+	0x00a0, 0x080c, 0x3892, 0x080c, 0x36f3, 0x6920, 0xc1c5, 0x6922,
+	0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005,
+	0x781b, 0x0082, 0x0005, 0x080c, 0x36f3, 0x7e58, 0xd6d4, 0x1118,
+	0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x00c6, 0x7058,
+	0x2060, 0x6100, 0xd1e4, 0x0578, 0x6208, 0x8217, 0xa294, 0x00ff,
+	0xa282, 0x001c, 0x0218, 0x0110, 0x2011, 0x001c, 0x2600, 0xa202,
+	0x1208, 0x2230, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130,
+	0xa282, 0x000a, 0x1240, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c,
+	0x1210, 0x2011, 0x000c, 0x2200, 0xa502, 0x1208, 0x2228, 0x080c,
+	0x3896, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x38c6, 0x0118,
+	0x080c, 0x36f6, 0x0020, 0x080c, 0x3892, 0x080c, 0x36f3, 0x7858,
+	0xc095, 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005, 0x00c6, 0x2960,
+	0x6000, 0xd0e4, 0x1178, 0x6010, 0xa084, 0x000f, 0x1130, 0x6104,
+	0xa18c, 0xfff5, 0x6106, 0x00ce, 0x0005, 0x2011, 0x0032, 0x2019,
+	0x0000, 0x00f0, 0x68a0, 0xd0cc, 0x1dc0, 0x6208, 0xa294, 0x00ff,
+	0x78ec, 0xd0e4, 0x0130, 0xa282, 0x000b, 0x1218, 0x2011, 0x000a,
+	0x0028, 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x6308, 0x831f,
+	0xa39c, 0x00ff, 0xa382, 0x001c, 0x0218, 0x0110, 0x2019, 0x001c,
+	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
+	0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x080c, 0x3850, 0x00ce,
+	0x0005, 0x00c6, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011,
+	0x0032, 0x2019, 0x0000, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0003,
+	0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5,
+	0x6822, 0x00ce, 0x0005, 0xa006, 0x2030, 0x2010, 0x00c6, 0x7158,
+	0x2160, 0x2018, 0x2008, 0xa084, 0xffe0, 0xa635, 0x7e86, 0x6018,
+	0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, 0x7770, 0xa18c, 0x000f,
+	0xa105, 0x2029, 0x4305, 0x252c, 0xd5cc, 0x0140, 0xd3a4, 0x0110,
+	0xa085, 0x0800, 0xd3fc, 0x0110, 0xa085, 0x8080, 0x78a6, 0x6016,
+	0x788a, 0xa6b4, 0x001f, 0x8637, 0x8204, 0x8004, 0xa605, 0x600e,
+	0x6004, 0xa084, 0xffd5, 0x6006, 0x00ce, 0x0005, 0xa282, 0x0002,
+	0x1904, 0x3816, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0568,
+	0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x1a04, 0x3809,
+	0x080c, 0x379c, 0x080c, 0x36f3, 0xa980, 0x0001, 0x200c, 0x080c,
+	0x3969, 0x080c, 0x3696, 0x88ff, 0x0178, 0x789b, 0x0060, 0x2800,
+	0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e,
+	0x0005, 0x781b, 0x0082, 0x0005, 0x7e58, 0xd6d4, 0x1118, 0x781b,
+	0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0xa282, 0x0002, 0x1218,
+	0xa284, 0x0001, 0x0140, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec,
+	0x1110, 0x2011, 0x0000, 0x080c, 0x3883, 0x0471, 0x080c, 0x36f3,
+	0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x00c6, 0x0026,
+	0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x1150, 0x6014, 0xa084,
+	0x0040, 0x1120, 0xc1a4, 0x6106, 0xa006, 0x0088, 0x2011, 0x0000,
+	0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0,
+	0x0004, 0x080c, 0x3850, 0x6820, 0xa085, 0x0200, 0x6822, 0x002e,
+	0x00ce, 0x0005, 0x8807, 0xa715, 0x00c6, 0x2009, 0x0000, 0x7058,
+	0x2060, 0x82ff, 0x0110, 0x2009, 0x0040, 0x6018, 0xa080, 0x0002,
+	0x789a, 0x78a4, 0xa084, 0xff9f, 0xa105, 0xc0ec, 0xd0b4, 0x1108,
+	0xc0ed, 0x6100, 0xd1f4, 0x0110, 0xa085, 0x0020, 0x78a6, 0x6016,
+	0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x00ce, 0x0005, 0x0006,
+	0x7000, 0xa086, 0x0003, 0x0110, 0x000e, 0x0010, 0x000e, 0x0488,
+	0xd6ac, 0x0578, 0x7888, 0xa084, 0x0040, 0x0558, 0x7bb8, 0x8307,
+	0xa084, 0x007f, 0x1508, 0x8207, 0xa084, 0x00ff, 0xa09e, 0x0001,
+	0x1904, 0x382d, 0xd6f4, 0x11d0, 0x79d8, 0x7adc, 0xa108, 0xa291,
+	0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c, 0x4083, 0x781b,
+	0x0080, 0xb284, 0x0600, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001,
+	0x0001, 0x080c, 0x3f50, 0x0005, 0x080c, 0x243b, 0x781b, 0x0080,
+	0x0005, 0x781b, 0x0083, 0x0005, 0x2039, 0x0000, 0x2041, 0x0000,
+	0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x36f6, 0x080c, 0x379a,
+	0x7e58, 0x04f9, 0x781b, 0x0082, 0x0005, 0x0cd9, 0x6820, 0xc0c4,
+	0x6822, 0x00c6, 0x7058, 0x2060, 0x0804, 0x3720, 0x0c91, 0x6820,
+	0xc0cc, 0x6822, 0x00c6, 0x7058, 0x2060, 0x0804, 0x37b9, 0x0c49,
+	0x6820, 0xa084, 0xecff, 0x6822, 0x00c6, 0x7058, 0x2060, 0x6004,
+	0xa084, 0xffc5, 0x6006, 0x00ce, 0x0005, 0x0049, 0x781b, 0x0082,
+	0x0005, 0x6827, 0x0002, 0x0049, 0x781b, 0x0082, 0x0005, 0x2001,
+	0x0005, 0x0088, 0x2001, 0x000c, 0x0070, 0x6820, 0xc0d5, 0x6822,
+	0x2001, 0x0006, 0x0040, 0x2001, 0x000d, 0x0028, 0x2001, 0x0009,
+	0x0010, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a,
+	0x70d4, 0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6, 0x70b8, 0xa065,
+	0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce,
+	0x0005, 0x0076, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703,
+	0xb28c, 0x0600, 0x0118, 0xa0e0, 0x47c0, 0x0010, 0xa0e0, 0x4840,
+	0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x7fe0, 0x78ae, 0x6012,
+	0x79a4, 0xa184, 0x773f, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0038,
+	0x6006, 0x007e, 0x0005, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab,
+	0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004,
+	0x0804, 0x3850, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0080,
+	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
+	0x789b, 0x0060, 0x78ab, 0x0005, 0x0804, 0x3850, 0x0156, 0x8007,
+	0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
+	0xa18c, 0xffe0, 0x2021, 0x3952, 0x2019, 0x0011, 0x20a9, 0x000e,
+	0x2011, 0x0032, 0x2404, 0xa084, 0xffe0, 0xa106, 0x0128, 0x8420,
+	0x2300, 0xa210, 0x1f04, 0x38ba, 0x015e, 0x0005, 0x0156, 0x0804,
+	0x3908, 0x2021, 0x3960, 0x20a9, 0x0009, 0x2011, 0x0029, 0xa582,
+	0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033, 0xa582, 0x0033,
+	0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0065, 0x2200,
+	0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04, 0x38df, 0x015e,
+	0x0088, 0x2021, 0x3952, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
+	0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300, 0xa210, 0x1f04,
+	0x38f1, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e, 0xa582, 0x0064,
+	0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x0005,
+	0xa886, 0x0002, 0x01e8, 0x2021, 0x393e, 0x20a9, 0x000d, 0x2011,
+	0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019, 0x0019, 0x2011,
+	0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300, 0xa210, 0x1f04,
+	0x3919, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185, 0x0ab0, 0x0890,
+	0x2021, 0x394d, 0x20a9, 0x0003, 0x2011, 0x0024, 0xa586, 0x0024,
+	0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028, 0x0930, 0x8420,
+	0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x38f1, 0x1021, 0x2202,
+	0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610, 0x4612, 0x5812,
+	0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021, 0xb002, 0xe204,
+	0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
+	0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
+	0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07, 0x7e07,
+	0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784, 0x0f00, 0x800b,
+	0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xd7fc,
+	0x0118, 0xa0e0, 0x68c0, 0x0010, 0xa0e0, 0x48c0, 0x0005, 0x00e6,
+	0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009, 0x4380, 0x2071,
+	0x4380, 0x0030, 0x2009, 0x4340, 0x2079, 0x0200, 0x2071, 0x4340,
+	0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002, 0x39c5, 0x39a0,
+	0x39a0, 0x39a0, 0x39a0, 0x39a0, 0x399e, 0x399e, 0x080c, 0x243b,
+	0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x1de0, 0x784b, 0x0008,
+	0x7848, 0xa084, 0x0008, 0x1de0, 0x68b4, 0xc0f5, 0x68b6, 0x7858,
+	0xc0f5, 0x785a, 0x7830, 0xd0bc, 0x1180, 0xb284, 0x0800, 0x0118,
+	0x0104, 0x39c5, 0x0010, 0x0304, 0x39c5, 0x681c, 0xd0ac, 0x1118,
+	0x080c, 0x3a4b, 0x0010, 0x781b, 0x00fb, 0x2091, 0x8001, 0x00fe,
+	0x00ee, 0x0005, 0x00c6, 0x2001, 0x4301, 0x2004, 0xd0ac, 0x1904,
+	0x3a3d, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0xb28c, 0x0600, 0x0118, 0xa0e0, 0x47c0, 0x0010, 0xa0e0, 0x4840,
+	0x6004, 0xa084, 0x000a, 0x1904, 0x3a3d, 0x6108, 0xa194, 0xff00,
+	0x0904, 0x3a3d, 0xa18c, 0x00ff, 0x601c, 0xa084, 0xff00, 0x0180,
+	0x2001, 0x0009, 0xa102, 0x16b8, 0x2001, 0x000a, 0xa102, 0x16b0,
+	0x2001, 0x000c, 0xa102, 0x16a8, 0x601c, 0xa084, 0x00ff, 0x601e,
+	0x2001, 0x000a, 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0,
+	0x2001, 0x0012, 0xa106, 0x0198, 0x2001, 0x0014, 0xa106, 0x0190,
+	0x2001, 0x0019, 0xa106, 0x0188, 0x2001, 0x0032, 0xa106, 0x0180,
+	0x00d8, 0x2009, 0x000c, 0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009,
+	0x0014, 0x00a0, 0x2009, 0x0019, 0x0088, 0x2009, 0x0020, 0x0070,
+	0x2009, 0x003f, 0x0058, 0x2009, 0x000a, 0x0040, 0x2009, 0x000c,
+	0x0028, 0x2009, 0x0019, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205,
+	0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x00ce, 0x0005, 0x781b,
+	0x0083, 0x0005, 0x781b, 0x0082, 0x0005, 0x781b, 0x0071, 0x0005,
+	0x781b, 0x006e, 0x0005, 0x2009, 0x4319, 0x210c, 0xa186, 0x0000,
+	0x0150, 0xa186, 0x0001, 0x0150, 0x701f, 0x000b, 0x7067, 0x0001,
+	0x781b, 0x0054, 0x0005, 0x781b, 0x00f3, 0x0005, 0x701f, 0x000a,
+	0x0005, 0x2009, 0x4319, 0x210c, 0xa186, 0x0000, 0x0168, 0xa186,
+	0x0001, 0x0138, 0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0054,
+	0x0005, 0x701f, 0x000a, 0x0005, 0x781b, 0x00f2, 0x0005, 0x781b,
+	0x00fb, 0x0005, 0x781b, 0x00fa, 0x0005, 0x781b, 0x00cc, 0x0005,
+	0x781b, 0x00cb, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d,
+	0x7067, 0x0001, 0x781b, 0x0054, 0x0005, 0x7830, 0xa084, 0x00c0,
+	0x1170, 0x7808, 0xc08c, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000,
+	0x78ec, 0xa084, 0x0021, 0x0118, 0x7808, 0xc08d, 0x780a, 0x0005,
+	0x7808, 0xc08d, 0x780a, 0x0005, 0x7830, 0xa084, 0x0040, 0x1de0,
+	0xb284, 0x0800, 0x0118, 0x1104, 0x3ab2, 0x0010, 0x1304, 0x3ab2,
+	0x78ac, 0x0005, 0x7808, 0xa084, 0xfffd, 0x780a, 0xe000, 0xe000,
+	0xe000, 0xe000, 0x78ec, 0xa084, 0x0021, 0x0140, 0xb284, 0x0800,
+	0x0118, 0x1104, 0x3ac1, 0x0010, 0x1304, 0x3ac4, 0x78ac, 0x0006,
+	0x7808, 0xa085, 0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001,
+	0x1904, 0x30a0, 0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68,
+	0x080c, 0x23e1, 0x2d78, 0x2c68, 0x00ce, 0xa784, 0x0008, 0x0148,
+	0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x248f, 0x0804,
+	0x3a3f, 0xa784, 0x0004, 0x01c8, 0x78b8, 0xa084, 0x8000, 0x01a8,
+	0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x248f, 0x78e4,
+	0xa084, 0x0007, 0xa086, 0x0001, 0x1140, 0x78c0, 0xa685, 0x4800,
+	0x2030, 0x7e5a, 0x781b, 0x00fb, 0x0005, 0xa784, 0x0080, 0x0140,
+	0x7884, 0xd0fc, 0x0128, 0x080c, 0x382d, 0x681b, 0x0022, 0x0005,
+	0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000,
+	0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904,
+	0x2a7a, 0xb284, 0x0800, 0x0110, 0x0104, 0x248c, 0x0304, 0x248c,
+	0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc,
+	0x0118, 0xa080, 0x4840, 0x0010, 0xa080, 0x47c0, 0x2060, 0x2048,
+	0x705a, 0x2a60, 0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904,
+	0x3b81, 0xd1ac, 0x05e0, 0x6108, 0x8117, 0xa18c, 0x00ff, 0x631c,
+	0x832f, 0x68a0, 0xd0cc, 0x11c8, 0xa584, 0x00ff, 0x0138, 0x78ec,
+	0xd0e4, 0x0110, 0x8213, 0x00b8, 0x2029, 0x0000, 0xa182, 0x000c,
+	0x1290, 0x78ec, 0xd0e4, 0x1118, 0x2009, 0x000c, 0x0060, 0xa182,
+	0x000b, 0x1248, 0x2009, 0x000a, 0x0030, 0x2009, 0x0032, 0x2011,
+	0x0000, 0x2029, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
+	0x0004, 0x79aa, 0x78ab, 0x0000, 0x7aaa, 0x7baa, 0x7daa, 0xa8c0,
+	0x0008, 0x6820, 0xa085, 0x1000, 0x6822, 0x080c, 0x3850, 0xa085,
+	0x0001, 0x00ce, 0x0005, 0xa282, 0x0006, 0x1904, 0x381f, 0x7da8,
+	0x7eac, 0x8637, 0xa5ac, 0x00ff, 0xa6b4, 0x00ff, 0x7fac, 0x8747,
+	0xa7bc, 0x00ff, 0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4,
+	0x05c8, 0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x37fc,
+	0xa6b4, 0x00ff, 0x0560, 0xa682, 0x0039, 0x1a04, 0x37fc, 0xa582,
+	0x0009, 0x0a04, 0x37fc, 0xa882, 0x0003, 0x1a04, 0x37fc, 0xa886,
+	0x0002, 0x0128, 0xa886, 0x0000, 0x0138, 0x0804, 0x37fc, 0xa786,
+	0x0000, 0x0904, 0x37fc, 0x8634, 0x852b, 0x852b, 0x080c, 0x38c6,
+	0x0904, 0x37fc, 0x080c, 0x36f6, 0x080c, 0x379a, 0x7e58, 0xd6d4,
+	0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x080c,
+	0x36f3, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7158, 0xa188,
+	0x0000, 0x210c, 0xd1ac, 0x0904, 0x37fc, 0xd1ec, 0x1120, 0x2039,
+	0x0000, 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000, 0x2041,
+	0x0000, 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff, 0xa706,
+	0x0110, 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f, 0xa39c,
+	0x00ff, 0x0168, 0xa302, 0x1208, 0x2330, 0x8807, 0xa705, 0xa086,
+	0x0201, 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000, 0x2041,
+	0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284, 0xff00,
+	0x1108, 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128, 0x852b,
+	0x852b, 0x080c, 0x38c6, 0x0d58, 0x080c, 0x36f6, 0x080c, 0x379a,
+	0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004,
+	0x78ab, 0x0000, 0x7daa, 0x7eaa, 0x7faa, 0x2800, 0x78aa, 0x789b,
+	0x0060, 0x78ab, 0x0005, 0x080c, 0x3850, 0x7858, 0xc095, 0x785a,
+	0x781b, 0x0082, 0x0005, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014,
+	0x0014, 0x9855, 0x984d, 0x0014, 0x9911, 0x98ff, 0x0014, 0x0014,
+	0x0090, 0x00e7, 0x0100, 0x0402, 0x2008, 0xf880, 0x0018, 0x0017,
+	0x840f, 0xd8c1, 0x0014, 0x0016, 0xa20a, 0x0014, 0x300b, 0xa20c,
+	0x0014, 0x2500, 0x0013, 0x2500, 0x0010, 0x0010, 0x0010, 0x0010,
+	0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
+	0x0010, 0x0010, 0xa200, 0x3806, 0x8839, 0x20c4, 0x0864, 0xa84f,
+	0x3008, 0x28c1, 0x9d18, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a,
+	0x8000, 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9cce, 0xa8f3,
+	0x0864, 0xa83d, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9cce, 0x2021,
+	0xa818, 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x67a4,
+	0x6c80, 0x0212, 0xa205, 0x883d, 0x882b, 0x1814, 0x883b, 0x7027,
+	0x85f2, 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa814, 0x883e,
+	0xa812, 0x280a, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x1814,
+	0x883b, 0x7027, 0x8576, 0x8677, 0xa806, 0x796d, 0xa8da, 0x796b,
+	0xa8f1, 0x7861, 0x883e, 0x206b, 0x28c1, 0x9d18, 0x2044, 0x2103,
+	0x20b4, 0x2095, 0xa8ca, 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203,
+	0x8000, 0x85a4, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208,
+	0x856e, 0x866f, 0x7121, 0x0014, 0x0704, 0x3008, 0x9cce, 0x0014,
+	0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, 0x856e,
+	0x883f, 0x08e6, 0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014, 0xf881,
+	0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532,
+	0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0x3008,
+	0x8000, 0x2849, 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2081,
+	0x2802, 0x1011, 0xa8fc, 0xa889, 0x3008, 0x20a1, 0x283c, 0x1011,
+	0xa8fc, 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1,
+	0x0014, 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2,
+	0x26e0, 0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210,
+	0x9d22, 0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823,
+	0x0016, 0x6042, 0x8008, 0xa8fa, 0x8160, 0x842a, 0x8180, 0xf021,
+	0x3008, 0x84a8, 0x11d7, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822,
+	0x0016, 0x0000, 0x0126, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090,
+	0x7204, 0x7008, 0xc09c, 0xa205, 0x1178, 0x720c, 0x82ff, 0x0128,
+	0x8aff, 0x1150, 0x7200, 0xd284, 0x1138, 0x7007, 0x0004, 0x7003,
+	0x0008, 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003, 0x7002,
+	0xc69c, 0xd084, 0x05b8, 0x2001, 0x4301, 0x2004, 0xd0b4, 0x0904,
+	0x3dcf, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, 0xa184, 0x0003,
+	0x0904, 0x3dcf, 0xa184, 0x01e0, 0x1904, 0x3dcf, 0xd1f4, 0x1d88,
+	0xa184, 0x3000, 0xa086, 0x1000, 0x0d60, 0x2011, 0x0180, 0x710c,
+	0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20, 0x700c, 0xa106, 0x0dc0,
+	0x7007, 0x0012, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, 0xa184,
+	0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4, 0x0548, 0x7007, 0x0002,
+	0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130, 0x080c, 0x3e9e, 0x8aff,
+	0x0904, 0x3d58, 0x0cb8, 0x700c, 0xa08c, 0x07ff, 0x01e8, 0x7004,
+	0xd084, 0x0178, 0x7014, 0xa005, 0x1148, 0x7010, 0x7310, 0xa306,
+	0x1de0, 0x2300, 0xa005, 0x0128, 0xa102, 0x1e20, 0x7007, 0x0010,
+	0x0030, 0x8aff, 0x0148, 0x080c, 0x4046, 0x1de8, 0x09d8, 0x080c,
+	0x3e58, 0x012e, 0x2000, 0x0005, 0x7204, 0x7108, 0xc19c, 0x8103,
+	0x1218, 0x080c, 0x3e9e, 0x0cc0, 0xa205, 0x1d88, 0x7007, 0x0004,
+	0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x6428, 0x84ff, 0x0508,
+	0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb,
+	0x1148, 0x0210, 0x080c, 0x243b, 0x609c, 0xa075, 0x0190, 0x0c88,
+	0x2039, 0x3e0e, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529,
+	0x8421, 0x0138, 0x8738, 0x2704, 0xa005, 0x1da8, 0x709c, 0xa075,
+	0x1d00, 0x0005, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011, 0x0015,
+	0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b,
+	0x0000, 0x0000, 0x3e0e, 0x3e0b, 0x0000, 0x0000, 0x8000, 0x0000,
+	0x3e0e, 0x0000, 0x3e16, 0x3e13, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x3e16, 0x0000, 0x3e11, 0x3e11, 0x0000, 0x0000, 0x8000, 0x0000,
+	0x3e11, 0x0000, 0x3e17, 0x3e17, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x3e17, 0x2079, 0x4300, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007,
+	0x0002, 0x7003, 0x0001, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007,
+	0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1128, 0x8109, 0x0118, 0x2071, 0x0020, 0x0c80, 0x0005,
+	0x7004, 0x8004, 0x1690, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
+	0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110, 0x080c, 0x243b,
+	0xa19c, 0x300c, 0xa386, 0x2004, 0x0130, 0xa386, 0x0008, 0x0160,
+	0xa386, 0x200c, 0x1d60, 0x7200, 0x8204, 0x0230, 0x730c, 0xa384,
+	0x07ff, 0x0110, 0x080c, 0x243b, 0x7007, 0x0012, 0x7000, 0xd084,
+	0x1160, 0x7008, 0xa084, 0x01e0, 0x1140, 0x7310, 0x7014, 0xa305,
+	0x0120, 0x710c, 0xa184, 0x07ff, 0x1958, 0x7007, 0x0012, 0x7007,
+	0x0008, 0x7004, 0xd09c, 0x1de8, 0x7007, 0x0012, 0x7108, 0x8103,
+	0x0ed8, 0x7003, 0x0008, 0x0005, 0x7108, 0x0000, 0xa184, 0x01e0,
+	0x1550, 0x7108, 0xa184, 0x01e0, 0x1530, 0xa184, 0x0007, 0x0002,
+	0x3eb2, 0x3ec0, 0x3eb0, 0x3ec0, 0x3eb0, 0x3f06, 0x3eb0, 0x3f05,
+	0x080c, 0x243b, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
+	0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x4046, 0x1de8, 0x0005,
+	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x0118, 0x080c,
+	0x4046, 0x1de8, 0x0005, 0x7007, 0x0012, 0x7108, 0x1d04, 0x3ece,
+	0x2091, 0x6000, 0x1d04, 0x3ed2, 0x2091, 0x6000, 0x7007, 0x0012,
+	0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8, 0x7007, 0x0012, 0x7108,
+	0xd1fc, 0x1dd8, 0x7003, 0x0000, 0x7000, 0xa005, 0x1130, 0x7004,
+	0xa005, 0x1118, 0x700c, 0xa005, 0x0108, 0x0c40, 0x2049, 0x0000,
+	0xb284, 0x0200, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001,
+	0x080c, 0x397f, 0x6818, 0xa084, 0x8000, 0x0110, 0x681b, 0x0002,
+	0x0005, 0x080c, 0x243b, 0x080c, 0x243b, 0x04b9, 0x7210, 0x7114,
+	0x700c, 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000,
+	0x0461, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c,
+	0x2100, 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238, 0x8412, 0x8210,
+	0x830a, 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60, 0x8a07, 0x0006,
+	0x6004, 0xa084, 0x0008, 0x0118, 0xa7ba, 0x3e13, 0x0010, 0xa7ba,
+	0x3e0b, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e,
+	0x7007, 0x0012, 0x080c, 0x3e58, 0x0005, 0x8a50, 0x8739, 0x2704,
+	0xa004, 0x1168, 0x6000, 0xa064, 0x1108, 0x2d60, 0x6004, 0xa084,
+	0x000f, 0xa080, 0x3e29, 0x203c, 0x87fb, 0x090c, 0x243b, 0x0005,
+	0x0126, 0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
+	0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff,
+	0xa084, 0x00ff, 0x0006, 0x6804, 0xa084, 0x0008, 0x000e, 0x0118,
+	0xa0b8, 0x3e13, 0x0010, 0xa0b8, 0x3e0b, 0xb284, 0x0200, 0x0110,
+	0x7e20, 0x0008, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0108,
+	0xc685, 0x2400, 0xa305, 0x0520, 0x2c58, 0x2704, 0x6104, 0xac60,
+	0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184, 0x0008,
+	0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000,
+	0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203,
+	0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x4067, 0x0010,
+	0x080c, 0x4046, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x00d6,
+	0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007, 0x0004,
+	0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000, 0x0005,
+	0x0126, 0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
+	0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+	0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050, 0x2d60,
+	0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb, 0x1138,
+	0x0210, 0x080c, 0x243b, 0x689c, 0xa065, 0x0120, 0x0c88, 0x080c,
+	0x4046, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006, 0x0016,
+	0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20, 0xb284,
+	0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5, 0x000c,
+	0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
+	0x2049, 0x3fe5, 0x6828, 0xa055, 0x05f0, 0x2d70, 0x2e60, 0x7004,
+	0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb, 0x1140, 0x0210,
+	0x080c, 0x243b, 0x709c, 0xa075, 0x2060, 0x0568, 0x0c80, 0x2704,
+	0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0268, 0x8a51, 0x1110,
+	0x080c, 0x243b, 0x8738, 0x2704, 0xa005, 0x1d90, 0x709c, 0xa075,
+	0x2060, 0x01c8, 0x08e0, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000,
+	0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1210, 0x080c,
+	0x243b, 0xb284, 0x0200, 0x0118, 0x2071, 0x0050, 0x0010, 0x2071,
+	0x0020, 0x0804, 0x3f79, 0x012e, 0x2000, 0x0005, 0x7008, 0xa084,
+	0x0003, 0xa086, 0x0003, 0x1108, 0x0005, 0x2704, 0xac78, 0x7800,
+	0x701a, 0x7804, 0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004,
+	0xa084, 0x0008, 0x0120, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602,
+	0x7004, 0xa084, 0x0010, 0xc085, 0x7006, 0x2079, 0x4300, 0x8a51,
+	0x01b0, 0x8738, 0x2704, 0xa005, 0x1168, 0x609c, 0xa005, 0x0180,
+	0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x3e19, 0x203c, 0x87fb,
+	0x090c, 0x243b, 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x0005,
+	0x2051, 0x0000, 0x0005, 0x0126, 0x0006, 0x00d6, 0x70d4, 0xa084,
+	0x4c00, 0x8004, 0x2090, 0x00de, 0x008e, 0x7108, 0xa184, 0x0003,
+	0x1128, 0x6828, 0xa005, 0x0178, 0x0804, 0x3d6c, 0x7108, 0xd1fc,
+	0x0118, 0x080c, 0x3e9e, 0x0c88, 0x7007, 0x0010, 0x7108, 0xd1fc,
+	0x0de8, 0x080c, 0x3e9e, 0x7008, 0xa086, 0x0008, 0x1d30, 0x7000,
+	0xa005, 0x1d18, 0x7003, 0x0000, 0x2049, 0x0000, 0x012e, 0x2000,
+	0x0005, 0x0126, 0x0146, 0x0136, 0x0156, 0x00c6, 0x00d6, 0x70d4,
+	0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x2049, 0x40b1, 0xad80,
+	0x0011, 0x20a0, 0xb284, 0x0200, 0x0118, 0x2099, 0x0032, 0x0010,
+	0x2099, 0x0031, 0x700c, 0xa084, 0x07ff, 0x682a, 0x7007, 0x0008,
+	0x7007, 0x0002, 0x7003, 0x0001, 0x0118, 0x8000, 0x80ac, 0x53a5,
+	0x700c, 0xa084, 0x07ff, 0x0130, 0x7007, 0x0004, 0x7004, 0xa084,
+	0x0004, 0x1de0, 0x00ce, 0x2049, 0x0000, 0x7003, 0x0000, 0x015e,
+	0x013e, 0x014e, 0x012e, 0x2000, 0x0005, 0x2091, 0x8000, 0x2091,
+	0x6000, 0x78ac, 0xa005, 0x1168, 0x7974, 0x70d0, 0xa106, 0x1148,
+	0x781c, 0xa005, 0x0130, 0x781f, 0x0000, 0x0e04, 0x4101, 0x2091,
+	0x4080, 0x7830, 0x8001, 0x7832, 0x1904, 0x416b, 0x7834, 0x7832,
+	0x2061, 0x68c0, 0x2069, 0x4380, 0xc7fd, 0x68d0, 0xa005, 0x0128,
+	0x8001, 0x68d2, 0x1110, 0x080c, 0x42c4, 0x6800, 0xa084, 0x000f,
+	0x0168, 0xa086, 0x0001, 0x0150, 0x6844, 0xa00d, 0x0138, 0x2104,
+	0xa005, 0x0120, 0x8001, 0x200a, 0x0904, 0x425f, 0x6814, 0xa005,
+	0x01a8, 0x8001, 0x6816, 0x1190, 0x68a7, 0x0001, 0x00f6, 0xd7fc,
+	0x1118, 0x2079, 0x0200, 0x0010, 0x2079, 0x0100, 0x080c, 0x3aa0,
+	0x00fe, 0x6864, 0xa005, 0x0110, 0x080c, 0x2233, 0x6880, 0xa005,
+	0x0140, 0x8001, 0x6882, 0x1128, 0x6867, 0x0000, 0x68d4, 0xc0c5,
+	0x68d6, 0x68d4, 0xd0fc, 0x01b0, 0xc0fc, 0x68d6, 0x20a9, 0x0200,
+	0x6034, 0xa005, 0x0158, 0x8001, 0x6036, 0x68d4, 0xc0fd, 0x68d6,
+	0x1128, 0x6010, 0xa005, 0x0110, 0x080c, 0x2233, 0xace0, 0x0010,
+	0x1f04, 0x4150, 0xd7fc, 0x0138, 0x2061, 0x48c0, 0x2069, 0x4340,
+	0xc7fc, 0x0804, 0x410d, 0x0459, 0x7838, 0x8001, 0x783a, 0x11a0,
+	0x783c, 0x783a, 0x2061, 0x48c0, 0x2069, 0x4340, 0xc7fc, 0x680c,
+	0xa005, 0x0110, 0x080c, 0x41c9, 0xd7fc, 0x1130, 0x2061, 0x68c0,
+	0x2069, 0x4380, 0xc7fd, 0x0c98, 0x7810, 0xd0cc, 0x0168, 0xd0ac,
+	0x1120, 0xd0a4, 0x0148, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0e04,
+	0x4193, 0x080c, 0x1ffe, 0x0005, 0x2091, 0x8001, 0x0005, 0x7840,
+	0x8001, 0x7842, 0x1568, 0x7844, 0x7842, 0x2091, 0x8000, 0x2061,
+	0x48c0, 0x2069, 0x4340, 0xc7fc, 0x6810, 0xa005, 0x1110, 0x2001,
+	0x0101, 0x8001, 0x6812, 0xd7fc, 0x0118, 0xa080, 0x89d0, 0x0010,
+	0xa080, 0x88c0, 0x2040, 0x2004, 0xa065, 0x0150, 0x6024, 0xa005,
+	0x0120, 0x8001, 0x6026, 0x0904, 0x4207, 0x6000, 0x2c40, 0x0ca0,
+	0xd7fc, 0x1130, 0x2061, 0x68c0, 0x2069, 0x4380, 0xc7fd, 0x08e0,
+	0x0005, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0540,
+	0x6024, 0xa005, 0x0118, 0x8001, 0x6026, 0x0400, 0x6008, 0xc09c,
+	0xd084, 0x1110, 0xd0ac, 0x01a8, 0x600a, 0x6004, 0xa06d, 0x01c0,
+	0x00c6, 0x0016, 0x6010, 0x8001, 0x6012, 0x080c, 0x35ab, 0x2d00,
+	0x2c68, 0x2060, 0x080c, 0x1b85, 0x080c, 0x1d30, 0x001e, 0x00ce,
+	0x0038, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0010, 0xa18d, 0x0100,
+	0xace0, 0x0010, 0x1f04, 0x41cd, 0xa184, 0x0001, 0x0130, 0xa18c,
+	0xfffe, 0x690e, 0x080c, 0x2233, 0x0008, 0x690e, 0x0005, 0x6800,
+	0xa005, 0x0120, 0x684c, 0xac06, 0x0904, 0x425f, 0x6864, 0xa005,
+	0x0120, 0x6027, 0x0001, 0x0804, 0x425c, 0x2c00, 0x687e, 0x6714,
+	0x6f76, 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4,
+	0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060,
+	0x6022, 0x6000, 0x2042, 0x080c, 0x1b1d, 0x6818, 0xa005, 0x0110,
+	0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109,
+	0x790a, 0x8001, 0x1310, 0x080c, 0x243b, 0x6812, 0x1118, 0x7910,
+	0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x080c,
+	0x1d3d, 0xd7fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069, 0x4380,
+	0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118, 0x697a, 0x2001,
+	0x0004, 0x2708, 0x080c, 0x2228, 0x2091, 0x8001, 0x0005, 0x00d6,
+	0x694c, 0x2160, 0xd7fc, 0x1118, 0x2069, 0x0200, 0x0010, 0x2069,
+	0x0100, 0x080c, 0x23e1, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00,
+	0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f,
+	0x0000, 0x6033, 0x0000, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004,
+	0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x4282, 0x684b,
+	0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x428b,
+	0x20a9, 0x00fa, 0x1f04, 0x4292, 0x6808, 0xa084, 0xfffd, 0x680a,
+	0x681b, 0x0054, 0x00de, 0x6867, 0x0007, 0x2091, 0x8001, 0x0005,
+	0x2079, 0x4300, 0x00e1, 0x0089, 0x00a9, 0x2009, 0x0002, 0x2069,
+	0x4380, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817, 0x0000, 0x8109,
+	0x0118, 0x2069, 0x4340, 0x0ca8, 0x0005, 0x2019, 0x00a3, 0x7b3a,
+	0x7b3e, 0x0005, 0x2019, 0x0033, 0x7b42, 0x7b46, 0x0005, 0x2019,
+	0x32dd, 0x7b32, 0x7b36, 0x0005, 0x6950, 0xa185, 0x0000, 0x0178,
+	0x00c6, 0x6ac0, 0x2264, 0x602b, 0x0000, 0x602f, 0x0000, 0x6008,
+	0xc0b5, 0x600a, 0x8210, 0x8109, 0x1da8, 0x6952, 0x00ce, 0x0005,
+	0x70ec, 0xd0dc, 0x1118, 0xd0d4, 0x0180, 0x0088, 0xae8e, 0x0100,
+	0x0130, 0x7814, 0xc0f5, 0x7816, 0xd0d4, 0x1170, 0x0050, 0x7814,
+	0xc0fd, 0x7816, 0xd0d4, 0x1140, 0x0020, 0xd0e4, 0x0138, 0x70a0,
+	0x70a2, 0x7804, 0xd08c, 0x0110, 0x681f, 0x000c, 0x0005, 0xaf67
+};
+#ifdef UNIQUE_FW_NAME
+unsigned short   fw12160i_length01 = 0x32f8;
+#else
+unsigned short   risc_code_length01 = 0x32f8;
+#endif
+
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/ql1280_fw.h linux/drivers/scsi/ql1280_fw.h
--- v2.3.42/linux/drivers/scsi/ql1280_fw.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/ql1280_fw.h	Mon Feb  7 19:45:28 2000
@@ -0,0 +1,1898 @@
+/************************************************************************
+ *									*
+ * 	         --- ISP1240/1080/1280 Initiator Firmware ---           *
+ *			      32 LUN Support				*
+ *									*
+ ************************************************************************
+ * Copyright (C) 1999,2000 Qlogic, Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that the following conditions are met:
+ * 1. Redistribution of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *									*
+ ************************************************************************
+ */
+
+
+/*
+ *	Firmware Version 8.09.00 (18:29 Apr 16, 1999)
+ */
+
+unsigned short fw1280ei_version = 8*1024+9;
+
+unsigned char fw1280ei_version_str[] = {8,9,0};
+
+unsigned short fw1280ei_addr01 = 0x1000 ;
+
+unsigned short fw1280ei_code01[] = { 
+	0x0078, 0x1041, 0x0000, 0x39e3, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
+	0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
+	0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
+	0x3132, 0x3430, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
+	0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3039, 0x2020, 0x2043,
+	0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
+	0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
+	0x2400, 0x20c9, 0x93ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
+	0x00c0, 0x1054, 0x2071, 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010,
+	0x2089, 0x136a, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086,
+	0x1280, 0x00c0, 0x1069, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2071,
+	0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010, 0x2089, 0x13ea, 0x0078,
+	0x106d, 0x20c1, 0x0020, 0x2089, 0x1312, 0x2071, 0x0010, 0x70c3,
+	0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
+	0x0008, 0x2001, 0x04fe, 0x70d6, 0x20c1, 0x0021, 0x2019, 0x0000,
+	0x2009, 0xfeff, 0x2100, 0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64,
+	0x206b, 0x0a0a, 0xaddc, 0x3fff, 0x2b54, 0x205b, 0x5050, 0x2114,
+	0xa286, 0xa5a5, 0x0040, 0x10a4, 0xa386, 0x000f, 0x0040, 0x10a0,
+	0x2c6a, 0x2a5a, 0x20c1, 0x0020, 0x2019, 0x000f, 0x0078, 0x1080,
+	0x2c6a, 0x2a5a, 0x0078, 0x10a2, 0x2c6a, 0x2a5a, 0x2130, 0x2128,
+	0xa1a2, 0x4a00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+	0xa192, 0x9400, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x2078,
+	0x2218, 0x2079, 0x4a00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+	0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2001, 0x04fc, 0x2004,
+	0xa086, 0x1080, 0x00c0, 0x10db, 0x2071, 0x0100, 0x0d7e, 0x2069,
+	0x4a40, 0x1078, 0x49ae, 0x0d7f, 0x7810, 0xc0ed, 0x7812, 0x781b,
+	0x0064, 0x0078, 0x1100, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1280,
+	0x00c0, 0x10fb, 0x7814, 0xc0ed, 0xc0d5, 0x7816, 0x781b, 0x0064,
+	0x2071, 0x0200, 0x0d7e, 0x2069, 0x4a40, 0x1078, 0x49ae, 0x2069,
+	0x4a80, 0x2071, 0x0100, 0x1078, 0x49ae, 0x7814, 0xc0d4, 0x7816,
+	0x0d7f, 0x0078, 0x1100, 0x7814, 0xc0e5, 0x7816, 0x781b, 0x003c,
+	0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802,
+	0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002,
+	0x2009, 0x0002, 0x2069, 0x4a40, 0x681b, 0x0003, 0x6823, 0x0007,
+	0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0000,
+	0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000, 0x8109, 0x0040,
+	0x1154, 0x68d3, 0x000a, 0x68c3, 0x4ac0, 0x2079, 0x4a00, 0x7814,
+	0xd0e4, 0x00c0, 0x113a, 0xd0ec, 0x00c0, 0x113e, 0x68d7, 0x7329,
+	0x0078, 0x1140, 0x68d7, 0x730d, 0x0078, 0x1140, 0x68d7, 0x7329,
+	0x68c7, 0x4fc0, 0x68cb, 0x4ec0, 0x68cf, 0x8fc0, 0x68ab, 0x9244,
+	0x68af, 0x9249, 0x68b3, 0x9244, 0x68b7, 0x9244, 0x68a7, 0x0001,
+	0x2069, 0x4a80, 0x0078, 0x1114, 0x68d3, 0x000a, 0x68c3, 0x4cc0,
+	0x7814, 0xd0e4, 0x00c0, 0x1160, 0x68d7, 0x7439, 0x0078, 0x1162,
+	0x68d7, 0x7419, 0x68c7, 0x6fc0, 0x68cb, 0x4f40, 0x68cf, 0x90d0,
+	0x68ab, 0x9249, 0x68af, 0x924e, 0x68b3, 0x9249, 0x68b7, 0x9249,
+	0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11b8, 0x7814, 0xd0e4,
+	0x00c0, 0x11aa, 0x0e7e, 0x2069, 0x4ec0, 0x2071, 0x0200, 0x70ec,
+	0xd0e4, 0x00c0, 0x118b, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
+	0x2007, 0x0078, 0x1191, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
+	0x2007, 0x2069, 0x4f40, 0x2071, 0x0100, 0x70ec, 0xd0e4, 0x00c0,
+	0x11a1, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, 0x2007, 0x0078,
+	0x11a7, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, 0x2007, 0x0e7f,
+	0x0078, 0x11d1, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x2069, 0x4ec0,
+	0x1078, 0x2007, 0x2069, 0x4f40, 0x1078, 0x2007, 0x0078, 0x11d1,
+	0x2069, 0x4ec0, 0x0e7e, 0x2071, 0x0100, 0x70ec, 0xd0e4, 0x00c0,
+	0x11ca, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, 0x2007, 0x0e7f,
+	0x0078, 0x11d1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, 0x2007,
+	0x0e7f, 0x2011, 0x0002, 0x2069, 0x4fc0, 0x2009, 0x0002, 0x20a9,
+	0x0100, 0x683f, 0x0000, 0x680b, 0x0040, 0x7bc8, 0xa386, 0xfeff,
+	0x00c0, 0x11e8, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x11ec,
+	0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x00f0, 0x11d9,
+	0x8109, 0x00c0, 0x11d7, 0x8211, 0x0040, 0x11fa, 0x2069, 0x6fc0,
+	0x0078, 0x11d5, 0x1078, 0x2611, 0x1078, 0x441d, 0x1078, 0x1df2,
+	0x1078, 0x4957, 0x2091, 0x2100, 0x2079, 0x4a00, 0x7810, 0xd0ec,
+	0x0040, 0x120e, 0x2071, 0x0020, 0x0078, 0x1210, 0x2071, 0x0050,
+	0x2091, 0x2200, 0x2079, 0x4a00, 0x2071, 0x0020, 0x2091, 0x2300,
+	0x2079, 0x4a00, 0x7810, 0xd0ec, 0x0040, 0x1222, 0x2079, 0x0100,
+	0x0078, 0x1224, 0x2079, 0x0200, 0x2071, 0x4a40, 0x2091, 0x2400,
+	0x2079, 0x0100, 0x2071, 0x4a80, 0x2091, 0x2000, 0x2079, 0x4a00,
+	0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090, 0x2071, 0x0010,
+	0x70c3, 0x0000, 0x0090, 0x1243, 0x70c0, 0xa086, 0x0002, 0x00c0,
+	0x1243, 0x1078, 0x159d, 0x2039, 0x0000, 0x7810, 0xd0ec, 0x00c0,
+	0x12c5, 0x1078, 0x1472, 0x78ac, 0xa005, 0x00c0, 0x1261, 0x0068,
+	0x1257, 0x786c, 0xa065, 0x0040, 0x1257, 0x1078, 0x2368, 0x1078,
+	0x209f, 0x0068, 0x126e, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078,
+	0x2368, 0x0068, 0x126e, 0x2009, 0x4a47, 0x2011, 0x4a87, 0x2104,
+	0x220c, 0xa105, 0x0040, 0x126e, 0x1078, 0x1f1e, 0x2071, 0x4a40,
+	0x70a4, 0xa005, 0x0040, 0x1293, 0x7450, 0xa485, 0x0000, 0x0040,
+	0x1293, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d,
+	0x2190, 0x1078, 0x2a9c, 0x2091, 0x8000, 0x2091, 0x303d, 0x0068,
+	0x1293, 0x2079, 0x4a00, 0x786c, 0xa065, 0x0040, 0x1293, 0x2071,
+	0x0010, 0x1078, 0x2368, 0x00e0, 0x129b, 0x2079, 0x4a00, 0x2071,
+	0x0010, 0x1078, 0x4765, 0x2071, 0x4a80, 0x70a4, 0xa005, 0x0040,
+	0x12b3, 0x7050, 0xa025, 0x0040, 0x12b3, 0x2079, 0x0100, 0x2091,
+	0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2a9c, 0x2091,
+	0x8000, 0x2091, 0x303d, 0x2079, 0x4a00, 0x2071, 0x0010, 0x0068,
+	0x12bf, 0x786c, 0xa065, 0x0040, 0x12bf, 0x1078, 0x2368, 0x00e0,
+	0x1249, 0x1078, 0x4765, 0x0078, 0x1249, 0x1078, 0x1472, 0x78ac,
+	0xa005, 0x00c0, 0x12dd, 0x0068, 0x12d3, 0x786c, 0xa065, 0x0040,
+	0x12d3, 0x1078, 0x2368, 0x1078, 0x209f, 0x0068, 0x12e7, 0x786c,
+	0xa065, 0x0040, 0x12dd, 0x1078, 0x2368, 0x0068, 0x12e7, 0x2009,
+	0x4a47, 0x2104, 0xa005, 0x0040, 0x12e7, 0x1078, 0x1f1e, 0x2071,
+	0x4a40, 0x70a4, 0xa005, 0x0040, 0x1302, 0x7450, 0xa485, 0x0000,
+	0x0040, 0x1302, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c,
+	0x303d, 0x2190, 0x1078, 0x2a9c, 0x2091, 0x8000, 0x2091, 0x303d,
+	0x2079, 0x4a00, 0x2071, 0x0010, 0x0068, 0x130c, 0x786c, 0xa065,
+	0x0040, 0x130c, 0x1078, 0x2368, 0x00e0, 0x12c5, 0x1078, 0x4765,
+	0x0078, 0x12c5, 0x1332, 0x1332, 0x1334, 0x1334, 0x1341, 0x1341,
+	0x1341, 0x1341, 0x134c, 0x134c, 0x1359, 0x1359, 0x1341, 0x1341,
+	0x1341, 0x1341, 0x1332, 0x1332, 0x1334, 0x1334, 0x1341, 0x1341,
+	0x1341, 0x1341, 0x134c, 0x134c, 0x1359, 0x1359, 0x1341, 0x1341,
+	0x1341, 0x1341, 0x0078, 0x1332, 0x007e, 0x107e, 0x127e, 0x2091,
+	0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
+	0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13ba, 0x127f, 0x107f,
+	0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091,
+	0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
+	0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x290b,
+	0x2091, 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091,
+	0x8001, 0x007c, 0x138a, 0x138a, 0x138c, 0x138c, 0x1399, 0x1399,
+	0x1399, 0x1399, 0x13a4, 0x13a4, 0x138c, 0x138c, 0x1399, 0x1399,
+	0x1399, 0x1399, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5,
+	0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5,
+	0x13a5, 0x13a5, 0x0078, 0x138a, 0x007e, 0x107e, 0x127e, 0x2091,
+	0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
+	0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c7, 0x127f, 0x107f,
+	0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e, 0x127e, 0x0d7e,
+	0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069, 0x4a40, 0x2079,
+	0x4a00, 0x1078, 0x49ae, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
+	0x107f, 0x007c, 0x3c00, 0xa084, 0x0007, 0x0079, 0x13bf, 0x13d0,
+	0x13d0, 0x13d2, 0x13d2, 0x13d7, 0x13d7, 0x13dc, 0x13dc, 0x3c00,
+	0xa084, 0x0003, 0x0079, 0x13cc, 0x13d0, 0x13d0, 0x13e5, 0x13e5,
+	0x1078, 0x28ec, 0x2091, 0x2200, 0x1078, 0x44b7, 0x007c, 0x2091,
+	0x2100, 0x1078, 0x44b7, 0x007c, 0x2091, 0x2100, 0x1078, 0x44b7,
+	0x2091, 0x2200, 0x1078, 0x44b7, 0x007c, 0x2091, 0x2100, 0x1078,
+	0x44b7, 0x007c, 0x140a, 0x140a, 0x140c, 0x140c, 0x1419, 0x1419,
+	0x1419, 0x1419, 0x1424, 0x1424, 0x1431, 0x1431, 0x1419, 0x1419,
+	0x1419, 0x1419, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442,
+	0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442,
+	0x1442, 0x1442, 0x0078, 0x140a, 0x007e, 0x107e, 0x127e, 0x2091,
+	0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
+	0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13ba, 0x127f, 0x107f,
+	0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091,
+	0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
+	0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x290b,
+	0x2091, 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091,
+	0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e,
+	0x2079, 0x4a00, 0x2071, 0x0200, 0x2069, 0x4a40, 0x3d00, 0xd08c,
+	0x00c0, 0x1456, 0x2069, 0x4a80, 0x2071, 0x0100, 0x1078, 0x49ae,
+	0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007f, 0x007c, 0x7008,
+	0x800b, 0x00c8, 0x146d, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
+	0x146e, 0xd09c, 0x0040, 0x146d, 0x087a, 0x097a, 0x70c3, 0x4002,
+	0x0078, 0x15a0, 0x0068, 0x14f7, 0x2061, 0x0000, 0x6018, 0xd084,
+	0x00c0, 0x14f7, 0x7828, 0xa005, 0x00c0, 0x1482, 0x0010, 0x14f8,
+	0x0078, 0x14f7, 0x7910, 0xd1f4, 0x0040, 0x148a, 0x2001, 0x4007,
+	0x0078, 0x159f, 0x7914, 0xd1ec, 0x0040, 0x14a5, 0xd0fc, 0x0040,
+	0x149b, 0x007e, 0x1078, 0x1d82, 0x007f, 0x0040, 0x14a5, 0x2001,
+	0x4007, 0x0078, 0x159f, 0x007e, 0x1078, 0x1d72, 0x007f, 0x0040,
+	0x14a5, 0x2001, 0x4007, 0x0078, 0x159f, 0x7910, 0xd0fc, 0x00c0,
+	0x14af, 0x2061, 0x4a40, 0xc19c, 0xc7fc, 0x0078, 0x14b3, 0x2061,
+	0x4a80, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x00c0, 0x14f7, 0x7912,
+	0x6083, 0x0000, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x00c0, 0x14c4,
+	0x0c7e, 0x1078, 0x1b13, 0x0c7f, 0x782b, 0x0000, 0x607c, 0xa065,
+	0x0040, 0x14dd, 0x0c7e, 0x609c, 0x1078, 0x1e5d, 0x0c7f, 0x609f,
+	0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018, 0x6087, 0x0103, 0x1078,
+	0x1d92, 0x00c0, 0x14f1, 0x1078, 0x1de4, 0x7810, 0xd09c, 0x00c0,
+	0x14e5, 0x2061, 0x4a40, 0x0078, 0x14e9, 0x2061, 0x4a80, 0xc09c,
+	0x7812, 0x607f, 0x0000, 0x60d4, 0xd0dc, 0x0040, 0x14f5, 0xc0dc,
+	0x60d6, 0x2001, 0x4005, 0x0078, 0x159f, 0x0078, 0x159d, 0x007c,
+	0x7810, 0xd0f4, 0x0040, 0x1500, 0x2001, 0x4007, 0x0078, 0x159f,
+	0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa08a,
+	0x0040, 0x00c8, 0x150d, 0x0079, 0x1514, 0x2100, 0xa08a, 0x0040,
+	0x00c8, 0x15ab, 0x0079, 0x1554, 0x159d, 0x15f3, 0x15bc, 0x162b,
+	0x1663, 0x1663, 0x15b3, 0x1c57, 0x166e, 0x15ab, 0x15c0, 0x15c2,
+	0x15c4, 0x15c6, 0x1c5c, 0x15ab, 0x167c, 0x16d4, 0x1b35, 0x1c51,
+	0x15c8, 0x19a7, 0x19e9, 0x1a1f, 0x1a6b, 0x1962, 0x196f, 0x1983,
+	0x1996, 0x17a4, 0x1cdc, 0x1706, 0x1713, 0x171f, 0x172b, 0x1741,
+	0x174d, 0x1750, 0x175c, 0x1768, 0x1770, 0x178c, 0x1798, 0x15ab,
+	0x15ab, 0x15ab, 0x15ab, 0x17b1, 0x17c3, 0x17df, 0x1815, 0x183d,
+	0x184d, 0x1850, 0x1881, 0x18b2, 0x18c4, 0x1931, 0x1941, 0x1d32,
+	0x15ab, 0x15ab, 0x15ab, 0x1951, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
+	0x15ab, 0x1c81, 0x1c87, 0x15ab, 0x15ab, 0x15ab, 0x1c8b, 0x1cd8,
+	0x15ab, 0x15ab, 0x1ce8, 0x1cf7, 0x15ed, 0x165d, 0x1676, 0x16ce,
+	0x1b2f, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x1d39, 0x1c73, 0x1c7d,
+	0x15ab, 0x15ab, 0x1d02, 0x1d1b, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
+	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
+	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
+	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
+	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x72ca, 0x71c6, 0x2001, 0x4006,
+	0x0078, 0x159f, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2,
+	0x0068, 0x15a0, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000,
+	0x2091, 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x15a0, 0x70c3,
+	0x4006, 0x0078, 0x15a0, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9,
+	0x0005, 0x53a3, 0x0078, 0x159d, 0x70c4, 0x70c3, 0x0004, 0x007a,
+	0x0078, 0x159d, 0x0078, 0x159d, 0x0078, 0x159d, 0x0078, 0x159d,
+	0x2091, 0x8000, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020,
+	0x70cf, 0x2020, 0x70d3, 0x0008, 0x2001, 0x0009, 0x70d6, 0x2079,
+	0x0000, 0x781b, 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029,
+	0x041a, 0x2051, 0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091,
+	0x5000, 0x2091, 0x4080, 0x0078, 0x0418, 0x75d8, 0x74dc, 0x75da,
+	0x74de, 0x0078, 0x15f6, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8,
+	0x73cc, 0x70c4, 0x20a0, 0x2099, 0x0030, 0x7003, 0x0001, 0x7007,
+	0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff,
+	0x0040, 0x159d, 0xa182, 0x0040, 0x00c8, 0x1610, 0x2120, 0xa006,
+	0x2008, 0x8403, 0x7012, 0x7007, 0x0004, 0x7007, 0x0001, 0x7008,
+	0xd0fc, 0x0040, 0x1617, 0x7007, 0x0002, 0xa084, 0x01e0, 0x0040,
+	0x1625, 0x70c3, 0x4002, 0x0078, 0x15a0, 0x24a8, 0x53a5, 0x0078,
+	0x1607, 0x0078, 0x159d, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8,
+	0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x7007,
+	0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x7007,
+	0x0006, 0x81ff, 0x0040, 0x159d, 0xa182, 0x0040, 0x00c8, 0x164a,
+	0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007,
+	0x0001, 0x7008, 0xd0fc, 0x0040, 0x1651, 0xa084, 0x01e0, 0x0040,
+	0x163f, 0x70c3, 0x4002, 0x0078, 0x15a0, 0x75d8, 0x74dc, 0x75da,
+	0x74de, 0x0078, 0x162e, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004,
+	0x00c0, 0x166b, 0x200a, 0x72ca, 0x0078, 0x159c, 0x70c7, 0x0008,
+	0x70cb, 0x0009, 0x70cf, 0x0000, 0x0078, 0x159d, 0x75d8, 0x76dc,
+	0x75da, 0x76de, 0x0078, 0x167f, 0x2029, 0x0000, 0x2530, 0x70c4,
+	0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005,
+	0x0040, 0x16c9, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0040, 0x1697,
+	0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078, 0x159f, 0x7b7e,
+	0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0040, 0x16af,
+	0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, 0xa118, 0xa291,
+	0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078, 0x16b9, 0x8407,
+	0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581,
+	0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, 0x0040, 0x16c3,
+	0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae, 0x0078,
+	0x16cc, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x159d, 0x75d8, 0x76dc,
+	0x75da, 0x76de, 0x0078, 0x16d7, 0x2029, 0x0000, 0x2530, 0x70c4,
+	0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005,
+	0x0040, 0x1701, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x16ef,
+	0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0078, 0x159f, 0x7a9a,
+	0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0040, 0x16fa, 0x7a10,
+	0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078,
+	0x1704, 0x78ac, 0xc0c5, 0x78ae, 0x0078, 0x159d, 0x2009, 0x0000,
+	0x786c, 0xa065, 0x0040, 0x1710, 0x8108, 0x6000, 0x0078, 0x1709,
+	0x7ac4, 0x0078, 0x159b, 0x2009, 0x4a48, 0x210c, 0x7810, 0xd0ec,
+	0x00c0, 0x159c, 0x2011, 0x4a88, 0x2214, 0x0078, 0x159b, 0x2009,
+	0x4a49, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2011, 0x4a89,
+	0x2214, 0x0078, 0x159b, 0x2061, 0x4a40, 0x6128, 0x622c, 0x8214,
+	0x8214, 0x8214, 0x7810, 0xd0ec, 0x00c0, 0x173f, 0x2061, 0x4a80,
+	0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078,
+	0x159b, 0x2009, 0x4a4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c,
+	0x2011, 0x4a8c, 0x2214, 0x0078, 0x159b, 0x7918, 0x0078, 0x159c,
+	0x2009, 0x4a4d, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2011,
+	0x4a8d, 0x2214, 0x0078, 0x159b, 0x2009, 0x4a4e, 0x210c, 0x7810,
+	0xd0ec, 0x00c0, 0x159c, 0x2011, 0x4a8e, 0x2214, 0x0078, 0x159b,
+	0x7920, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x7a24, 0x0078, 0x159b,
+	0x71c4, 0xd1fc, 0x00c0, 0x1778, 0x2011, 0x4ec0, 0x0078, 0x177a,
+	0x2011, 0x4f40, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0xa268, 0x6a00, 0x6804, 0xd09c, 0x0040, 0x1789, 0x6b08, 0x0078,
+	0x178a, 0x6b0c, 0x0078, 0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091,
+	0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x159a,
+	0x2061, 0x4a40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2061,
+	0x4a80, 0x6218, 0x0078, 0x159b, 0x77c4, 0x1078, 0x1e02, 0x2091,
+	0x8000, 0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078,
+	0x159a, 0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8,
+	0x1595, 0x1078, 0x2729, 0xa384, 0x4000, 0x0040, 0x17c1, 0xa295,
+	0x0020, 0x0078, 0x159a, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010,
+	0x00c8, 0x1595, 0xd1bc, 0x00c0, 0x17d2, 0x2011, 0x4a48, 0x2204,
+	0x0078, 0x17d6, 0x2011, 0x4a88, 0x2204, 0xc0bd, 0x007e, 0x2100,
+	0xc0bc, 0x2012, 0x1078, 0x2686, 0x017f, 0x0078, 0x159c, 0x71c4,
+	0x2021, 0x4a49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x17ee,
+	0x71c8, 0x2021, 0x4a89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x180d,
+	0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x17fd, 0x8210, 0x00f0,
+	0x17f2, 0x71c4, 0x72c8, 0x0078, 0x1594, 0xa292, 0x180d, 0x027e,
+	0x2122, 0x017f, 0x1078, 0x26a7, 0x7810, 0xd0ec, 0x00c0, 0x180b,
+	0xd3fc, 0x0040, 0x17e8, 0x0078, 0x159d, 0x03e8, 0x00fa, 0x01f4,
+	0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4a40, 0x6128,
+	0x622c, 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003,
+	0x8003, 0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x183b, 0x027e,
+	0x017e, 0x2061, 0x4a80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
+	0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da,
+	0x72de, 0x017f, 0x027f, 0x0078, 0x159b, 0x2061, 0x4a40, 0x6130,
+	0x70c4, 0x6032, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2061, 0x4a80,
+	0x6230, 0x70c8, 0x6032, 0x0078, 0x159b, 0x7918, 0x0078, 0x159c,
+	0x71c4, 0xa184, 0xffcf, 0x0040, 0x185c, 0x7810, 0xd0ec, 0x00c0,
+	0x1595, 0x72c8, 0x0078, 0x1594, 0x2011, 0x4a4d, 0x2204, 0x2112,
+	0x007e, 0x2019, 0x0000, 0x1078, 0x270e, 0x7810, 0xd0ec, 0x0040,
+	0x186c, 0x017f, 0x0078, 0x159c, 0x71c8, 0xa184, 0xffcf, 0x0040,
+	0x1875, 0x2110, 0x71c4, 0x0078, 0x1594, 0x2011, 0x4a8d, 0x2204,
+	0x2112, 0x007e, 0xc3fd, 0x1078, 0x270e, 0x027f, 0x017f, 0x0078,
+	0x159b, 0x71c4, 0xa182, 0x0010, 0x0048, 0x188d, 0x7810, 0xd0ec,
+	0x00c0, 0x1595, 0x72c8, 0x0078, 0x1594, 0x2011, 0x4a4e, 0x2204,
+	0x007e, 0x2112, 0x2019, 0x0000, 0x1078, 0x26ec, 0x7810, 0xd0ec,
+	0x0040, 0x189d, 0x017f, 0x0078, 0x159c, 0x71c8, 0xa182, 0x0010,
+	0x0048, 0x18a6, 0x2110, 0x71c4, 0x0078, 0x1594, 0x2011, 0x4a8e,
+	0x2204, 0x007e, 0x2112, 0xc3fd, 0x1078, 0x26ec, 0x027f, 0x017f,
+	0x0078, 0x159b, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x1594,
+	0xa284, 0xfffd, 0x00c0, 0x1594, 0x2100, 0x7920, 0x7822, 0x2200,
+	0x7a24, 0x7826, 0x0078, 0x159b, 0x71c4, 0xd1fc, 0x00c0, 0x18cc,
+	0x2011, 0x4ec0, 0x0078, 0x18ce, 0x2011, 0x4f40, 0x8107, 0xa084,
+	0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8,
+	0xa284, 0x0080, 0x0040, 0x18e2, 0x6c14, 0x84ff, 0x00c0, 0x18e2,
+	0x6817, 0x0040, 0xa284, 0x0040, 0x0040, 0x18ec, 0x6c10, 0x84ff,
+	0x00c0, 0x18ec, 0x6813, 0x0001, 0x6800, 0x007e, 0xa226, 0x0040,
+	0x1909, 0x6a02, 0xd4ec, 0x0040, 0x18f6, 0xc3a5, 0xd4e4, 0x0040,
+	0x18fa, 0xc39d, 0xd4f4, 0x0040, 0x1909, 0x810f, 0xd2f4, 0x0040,
+	0x1905, 0x1078, 0x276b, 0x0078, 0x1909, 0x1078, 0x2749, 0x0078,
+	0x1909, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1929, 0xa2a4, 0x00ff,
+	0x7814, 0xd0e4, 0x00c0, 0x191c, 0xa482, 0x0028, 0x0048, 0x1926,
+	0x0040, 0x1926, 0x0078, 0x1920, 0xa482, 0x0043, 0x0048, 0x1926,
+	0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x1596, 0x6a0a, 0xa39d,
+	0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078,
+	0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a14, 0x6b1c,
+	0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078,
+	0x159a, 0x70c4, 0x2061, 0x4a40, 0x6118, 0x601a, 0x7810, 0xd0ec,
+	0x00c0, 0x159c, 0x70c8, 0x2061, 0x4a80, 0x6218, 0x601a, 0x0078,
+	0x159b, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x1595,
+	0x1078, 0x278d, 0xa384, 0x4000, 0x0040, 0x1960, 0xa295, 0x0020,
+	0x0078, 0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a08,
+	0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4,
+	0x1078, 0x1e02, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a,
+	0x6804, 0xa005, 0x0040, 0x197e, 0x1078, 0x25de, 0x2091, 0x8001,
+	0x2708, 0x0078, 0x159b, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000,
+	0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1991, 0x1078,
+	0x25de, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4, 0x2041,
+	0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
+	0x1e1d, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x159b, 0x77c4,
+	0x7814, 0xd0e4, 0x00c0, 0x19bb, 0xd7fc, 0x0040, 0x19b5, 0x1078,
+	0x1d82, 0x0040, 0x19bb, 0x0078, 0x159f, 0x1078, 0x1d72, 0x0040,
+	0x19bb, 0x0078, 0x159f, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce,
+	0x1078, 0x1e9a, 0x00c0, 0x19e5, 0x6818, 0xa005, 0x0040, 0x19df,
+	0x2708, 0x077e, 0x1078, 0x27bd, 0x077f, 0x00c0, 0x19df, 0x2001,
+	0x0015, 0xd7fc, 0x00c0, 0x19d8, 0x2061, 0x4a40, 0x0078, 0x19db,
+	0xc0fd, 0x2061, 0x4a80, 0x782a, 0x2091, 0x8001, 0x007c, 0x2091,
+	0x8001, 0x2001, 0x4005, 0x0078, 0x159f, 0x2091, 0x8001, 0x0078,
+	0x159d, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19fd, 0xd7fc, 0x0040,
+	0x19f7, 0x1078, 0x1d82, 0x0040, 0x19fd, 0x0078, 0x159f, 0x1078,
+	0x1d72, 0x0040, 0x19fd, 0x0078, 0x159f, 0x77c6, 0x2041, 0x0021,
+	0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x1e1d,
+	0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a11, 0x2061, 0x4a40, 0x0078,
+	0x1a14, 0x2061, 0x4a80, 0xc1fd, 0x6067, 0x0003, 0x6776, 0x6083,
+	0x000f, 0x792a, 0x1078, 0x25de, 0x2091, 0x8001, 0x007c, 0x77c8,
+	0x77ca, 0x77c4, 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a36, 0xd7fc,
+	0x0040, 0x1a30, 0x1078, 0x1d82, 0x0040, 0x1a36, 0x0078, 0x159f,
+	0x1078, 0x1d72, 0x0040, 0x1a36, 0x0078, 0x159f, 0xa7bc, 0xff00,
+	0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a43, 0x2061,
+	0x4a40, 0x0078, 0x1a46, 0x2061, 0x4a80, 0xc1fd, 0x6067, 0x0002,
+	0x6776, 0x6083, 0x000f, 0x792a, 0x1078, 0x25de, 0x2091, 0x8001,
+	0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0010, 0x2091, 0x8000,
+	0x70c8, 0xa005, 0x0040, 0x1a5f, 0x60d4, 0xc0fd, 0x60d6, 0x1078,
+	0x1e1d, 0x70c8, 0x683e, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1a5f,
+	0x2091, 0x8001, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x1a7f, 0x72c8,
+	0xd284, 0x0040, 0x1a79, 0x1078, 0x1d82, 0x0040, 0x1a7f, 0x0078,
+	0x159f, 0x1078, 0x1d72, 0x0040, 0x1a7f, 0x0078, 0x159f, 0x72c8,
+	0x72ca, 0x78ac, 0xa084, 0x0003, 0x00c0, 0x1aaa, 0x2039, 0x0000,
+	0xd284, 0x0040, 0x1a8c, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004,
+	0x2051, 0x0008, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6808, 0xc0d4,
+	0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0,
+	0x1a92, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
+	0x00c0, 0x1a92, 0x2091, 0x8000, 0x72c8, 0xd284, 0x00c0, 0x1abc,
+	0x7810, 0xd0ec, 0x0040, 0x1ab8, 0x2069, 0x0100, 0x0078, 0x1abe,
+	0x2069, 0x0200, 0x0078, 0x1abe, 0x2069, 0x0100, 0x6830, 0xd0b4,
+	0x0040, 0x1ada, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094,
+	0x0040, 0x1acc, 0x00f0, 0x1ac6, 0x684b, 0x0009, 0x20a9, 0x0014,
+	0x6848, 0xd084, 0x0040, 0x1ad6, 0x00f0, 0x1ad0, 0x20a9, 0x00fa,
+	0x00f0, 0x1ad8, 0x2079, 0x4a00, 0x2009, 0x0018, 0x72c8, 0xd284,
+	0x00c0, 0x1ae6, 0x2061, 0x4a40, 0x0078, 0x1ae9, 0x2061, 0x4a80,
+	0xc1fd, 0x792a, 0x6067, 0x0001, 0x6083, 0x000f, 0x60a7, 0x0000,
+	0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4, 0x0040, 0x1b03, 0xc0b4,
+	0x60d6, 0x0c7e, 0x60b8, 0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018,
+	0x8001, 0x601a, 0x0c7f, 0x60d4, 0xa084, 0x77ff, 0x60d6, 0x78ac,
+	0xc08d, 0x78ae, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0047,
+	0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b1a, 0x2069, 0x4a40,
+	0x0078, 0x1b1c, 0x2069, 0x4a80, 0x78ac, 0xc08c, 0x78ae, 0xd084,
+	0x00c0, 0x1b26, 0x0d7e, 0x1078, 0x1efa, 0x0d7f, 0x71c4, 0x71c6,
+	0x6916, 0x81ff, 0x00c0, 0x1b2e, 0x68a7, 0x0001, 0x007c, 0x75d8,
+	0x74dc, 0x75da, 0x74de, 0x0078, 0x1b38, 0x2029, 0x0000, 0x2520,
+	0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4a00,
+	0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x1078, 0x1ddb, 0x0040, 0x1c3b,
+	0x20a9, 0x0005, 0x20a1, 0x4a14, 0x2091, 0x8000, 0x41a1, 0x2091,
+	0x8001, 0x2009, 0x0040, 0x1078, 0x1fcf, 0x0040, 0x1b5b, 0x1078,
+	0x1de4, 0x0078, 0x1c3b, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009,
+	0x00c0, 0x1b66, 0x007e, 0x1078, 0x234b, 0x007f, 0xa084, 0xff00,
+	0x8007, 0x8009, 0x0040, 0x1bda, 0x0c7e, 0x2c68, 0x1078, 0x1ddb,
+	0x0040, 0x1bac, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1b6d, 0x609f,
+	0x0000, 0x0c7f, 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290,
+	0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde,
+	0x7cda, 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1bd9,
+	0x2009, 0x0040, 0x1078, 0x1fcf, 0x00c0, 0x1bc3, 0x6004, 0xa084,
+	0x00ff, 0xa086, 0x0002, 0x00c0, 0x1bac, 0x6004, 0xa084, 0x00ff,
+	0xa086, 0x000a, 0x00c0, 0x1ba8, 0x017e, 0x1078, 0x2347, 0x017f,
+	0x2d00, 0x6002, 0x0078, 0x1b7b, 0x0c7f, 0x0c7e, 0x609c, 0x1078,
+	0x1e5d, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018,
+	0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086, 0x1078, 0x1d92, 0x1078,
+	0x1de4, 0x0078, 0x1c3b, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e5d,
+	0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018, 0x6087,
+	0x0103, 0x601b, 0x0003, 0x1078, 0x1d92, 0x1078, 0x1de4, 0x0078,
+	0x1c3b, 0x0c7f, 0x7814, 0xd0e4, 0x00c0, 0x1bff, 0x6114, 0xd1fc,
+	0x0040, 0x1be8, 0x1078, 0x1d82, 0x0040, 0x1bff, 0x0078, 0x1bec,
+	0x1078, 0x1d72, 0x0040, 0x1bff, 0x2029, 0x0000, 0x2520, 0x2009,
+	0x0018, 0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x1078,
+	0x1d92, 0x1078, 0x1de4, 0x2001, 0x4007, 0x0078, 0x159f, 0x74c4,
+	0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012,
+	0xd0fc, 0x00c0, 0x1c0f, 0x2071, 0x4a40, 0x0078, 0x1c12, 0x2071,
+	0x4a80, 0xc1fd, 0x792a, 0x7067, 0x0005, 0x71d4, 0xa18c, 0xf77f,
+	0x71d6, 0x736a, 0x726e, 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00,
+	0x707e, 0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x1c2a,
+	0x1078, 0x43c1, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af,
+	0x0000, 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000, 0x1078, 0x25de,
+	0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x15a0, 0x20a9,
+	0x0005, 0x2099, 0x4a14, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001,
+	0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
+	0x007c, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0078, 0x159d, 0x71c4,
+	0x71c6, 0x2168, 0x0078, 0x1c5e, 0x2069, 0x1000, 0x690c, 0xa016,
+	0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1c60, 0xa285, 0x0000,
+	0x00c0, 0x1c6e, 0x70c3, 0x4000, 0x0078, 0x1c70, 0x70c3, 0x4003,
+	0x70ca, 0x0078, 0x15a0, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003,
+	0x00c8, 0x1595, 0x7966, 0x0078, 0x159d, 0x7964, 0x71c6, 0x0078,
+	0x159d, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x0078, 0x159d, 0x7900,
+	0x71c6, 0x0078, 0x159d, 0x70c4, 0xd08c, 0x0040, 0x1c94, 0x7a10,
+	0xd2ec, 0x00c0, 0x1c94, 0xc08c, 0x2011, 0x0000, 0xa08c, 0x000d,
+	0x0040, 0x1ca8, 0x810c, 0x0048, 0x1ca4, 0x8210, 0x810c, 0x810c,
+	0x0048, 0x1ca4, 0x8210, 0x810c, 0x81ff, 0x00c0, 0x1596, 0x8210,
+	0x7a0e, 0xd28c, 0x0040, 0x1cd4, 0x7910, 0xc1cd, 0x7912, 0x2009,
+	0x0021, 0x2019, 0x0003, 0xd284, 0x0040, 0x1cce, 0x8108, 0x2019,
+	0x0041, 0x2011, 0x924e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312,
+	0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312,
+	0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x9253,
+	0x2112, 0x2011, 0x9273, 0x2312, 0x7904, 0x7806, 0x0078, 0x159c,
+	0x7804, 0x70c6, 0x0078, 0x159d, 0x2091, 0x8000, 0x2019, 0x0000,
+	0x2011, 0x0000, 0x2009, 0x0000, 0x2091, 0x8001, 0x0078, 0x159a,
+	0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6830, 0xa084, 0xff00,
+	0x8007, 0x2010, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4,
+	0x1078, 0x1e02, 0x2091, 0x8000, 0x6a34, 0x2091, 0x8001, 0x2708,
+	0x0078, 0x159b, 0x77c4, 0x077e, 0xa7bc, 0xff00, 0x20a9, 0x0008,
+	0x72c8, 0x8217, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6c30, 0x6a32,
+	0x2091, 0x8001, 0x8738, 0x00f0, 0x1d0a, 0x077f, 0x2708, 0x8427,
+	0x2410, 0x0078, 0x159b, 0x77c4, 0x077e, 0xa7bc, 0xff00, 0x20a9,
+	0x0008, 0x72c8, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6c34, 0x6a36,
+	0x2091, 0x8001, 0x8738, 0x00f0, 0x1d22, 0x077f, 0x2708, 0x2410,
+	0x0078, 0x159b, 0x2011, 0x4a3c, 0x220c, 0x70c4, 0x2012, 0x0078,
+	0x159c, 0x71c4, 0xd1fc, 0x00c0, 0x1d41, 0x2011, 0x4ec0, 0x0078,
+	0x1d43, 0x2011, 0x4f40, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d52, 0x2011, 0x0001,
+	0x0078, 0x1d54, 0x2011, 0x0000, 0x6b0c, 0x0078, 0x159a, 0x017e,
+	0x7814, 0xd0f4, 0x0040, 0x1d64, 0x2001, 0x4007, 0x70db, 0x0000,
+	0xa18d, 0x0001, 0x0078, 0x1d70, 0xd0fc, 0x0040, 0x1d6f, 0x2001,
+	0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d70, 0xa006,
+	0x017f, 0x007c, 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d7f, 0x2001,
+	0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d80, 0xa006,
+	0x017f, 0x007c, 0x017e, 0x7814, 0xd0fc, 0x0040, 0x1d8f, 0x2001,
+	0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d90, 0xa006,
+	0x017f, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4, 0x0040,
+	0x1d9b, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c, 0x81a9,
+	0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2, 0x53a6,
+	0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040, 0x1db8, 0x810f,
+	0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078, 0x1dbb,
+	0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
+	0x7d10, 0xd5c4, 0x0040, 0x1dc8, 0x7b84, 0xa319, 0x7c80, 0xa421,
+	0x7008, 0xd0fc, 0x0040, 0x1dc8, 0x7003, 0x0001, 0x7007, 0x0006,
+	0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1dd8, 0x7322, 0x7426,
+	0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040, 0x1de3, 0x2c04,
+	0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x4a00, 0x7848,
+	0x2062, 0x2c00, 0xa005, 0x00c0, 0x1def, 0x1078, 0x28ec, 0x784a,
+	0x0f7f, 0x007c, 0x2011, 0x9400, 0x7a4a, 0x7bc4, 0x8319, 0x0040,
+	0x1dff, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078, 0x1df6, 0x2013,
+	0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0, 0x1e0b, 0x2011,
+	0x4fc0, 0x0078, 0x1e0d, 0x2011, 0x6fc0, 0xa784, 0x0f00, 0x800b,
+	0xa784, 0x001f, 0x0040, 0x1e18, 0x8003, 0x8003, 0x8003, 0x8003,
+	0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078, 0x1e02, 0x2900,
+	0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a,
+	0xd7fc, 0x00c0, 0x1e2f, 0x2009, 0x4a53, 0x0078, 0x1e31, 0x2009,
+	0x4a93, 0x210c, 0x6804, 0xa005, 0x0040, 0x1e41, 0xa116, 0x00c0,
+	0x1e41, 0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078,
+	0x1e44, 0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e59,
+	0x6000, 0x6806, 0x1078, 0x1e6f, 0x1078, 0x201b, 0x6810, 0x7908,
+	0x8109, 0x790a, 0x8001, 0x6812, 0x00c0, 0x1e44, 0x7910, 0xc1a5,
+	0x7912, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x1e6e,
+	0x2008, 0x609c, 0xa005, 0x0040, 0x1e6b, 0x2062, 0x609f, 0x0000,
+	0xa065, 0x0078, 0x1e61, 0x7848, 0x794a, 0x2062, 0x007c, 0x6007,
+	0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80, 0x0005, 0x20a0,
+	0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c, 0x6022, 0x007c,
+	0x0e7e, 0xd7fc, 0x00c0, 0x1e8a, 0x2071, 0x4a40, 0x2031, 0x4ac0,
+	0x0078, 0x1e8e, 0x2071, 0x4a80, 0x2031, 0x4cc0, 0x7050, 0xa08c,
+	0x0200, 0x00c0, 0x1e98, 0xa608, 0x2d0a, 0x8000, 0x7052, 0xa006,
+	0x0e7f, 0x007c, 0x0f7e, 0xd7fc, 0x00c0, 0x1ea2, 0x2079, 0x4a40,
+	0x0078, 0x1ea4, 0x2079, 0x4a80, 0x1078, 0x1e02, 0x2091, 0x8000,
+	0x6804, 0x780a, 0xa065, 0x0040, 0x1ef8, 0x0078, 0x1eb6, 0x2c00,
+	0x780a, 0x2060, 0x6000, 0xa065, 0x0040, 0x1ef8, 0x6010, 0xa306,
+	0x00c0, 0x1eaf, 0x600c, 0xa206, 0x00c0, 0x1eaf, 0x2c28, 0x784c,
+	0xac06, 0x00c0, 0x1ec5, 0x0078, 0x1ef5, 0x6804, 0xac06, 0x00c0,
+	0x1ed3, 0x6000, 0x2060, 0x6806, 0xa005, 0x00c0, 0x1ed3, 0x6803,
+	0x0000, 0x0078, 0x1edd, 0x6400, 0x7808, 0x2060, 0x6402, 0xa486,
+	0x0000, 0x00c0, 0x1edd, 0x2c00, 0x6802, 0x2560, 0x0f7f, 0x1078,
+	0x1e6f, 0x0f7e, 0x601b, 0x0005, 0x6023, 0x0020, 0x0f7f, 0x1078,
+	0x201b, 0x0f7e, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001, 0x6812,
+	0x00c0, 0x1ef5, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005,
+	0x0f7f, 0x007c, 0x077e, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0040,
+	0x1f02, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
+	0x2091, 0x8000, 0x1078, 0x1e1d, 0x8738, 0xa784, 0x001f, 0x00c0,
+	0x1f0a, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
+	0x00c0, 0x1f0a, 0x2091, 0x8001, 0x077f, 0x007c, 0x2061, 0x0000,
+	0x6018, 0xd084, 0x00c0, 0x1f3e, 0x7810, 0xd08c, 0x0040, 0x1f2f,
+	0xc08c, 0x7812, 0xc7fc, 0x2069, 0x4a40, 0x0078, 0x1f34, 0xc08d,
+	0x7812, 0x2069, 0x4a80, 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f,
+	0x0000, 0x2091, 0x8001, 0xa005, 0x00c0, 0x1f3f, 0x007c, 0xa08c,
+	0xfff0, 0x0040, 0x1f45, 0x1078, 0x28ec, 0x0079, 0x1f47, 0x1f57,
+	0x1f5a, 0x1f60, 0x1f64, 0x1f58, 0x1f68, 0x1f58, 0x1f58, 0x1f58,
+	0x1f6e, 0x1f9f, 0x1fa3, 0x1fa9, 0x1f58, 0x1f58, 0x1f58, 0x007c,
+	0x1078, 0x28ec, 0x1078, 0x1efa, 0x2001, 0x8001, 0x0078, 0x1fbe,
+	0x2001, 0x8003, 0x0078, 0x1fbe, 0x2001, 0x8004, 0x0078, 0x1fbe,
+	0x1078, 0x1efa, 0x2001, 0x8006, 0x0078, 0x1fbe, 0x2091, 0x8000,
+	0x077e, 0xd7fc, 0x00c0, 0x1f7a, 0x2069, 0x4a40, 0x2039, 0x0009,
+	0x0078, 0x1f7e, 0x2069, 0x4a80, 0x2039, 0x0009, 0x6800, 0xa086,
+	0x0000, 0x0040, 0x1f88, 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c,
+	0x6874, 0x077f, 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004,
+	0x2051, 0x0010, 0x1078, 0x1e1d, 0x8738, 0xa784, 0x001f, 0x00c0,
+	0x1f92, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078, 0x1fbe, 0x2001,
+	0x800c, 0x0078, 0x1fbe, 0x1078, 0x1efa, 0x2001, 0x800d, 0x0078,
+	0x1fbe, 0x7814, 0xd0e4, 0x00c0, 0x1fbc, 0xd0ec, 0x0040, 0x1fb6,
+	0xd7fc, 0x0040, 0x1fb6, 0x78ec, 0x0078, 0x1fb7, 0x78e4, 0x70c6,
+	0x2001, 0x800e, 0x0078, 0x1fbe, 0x0078, 0x1f58, 0x70c2, 0xd7fc,
+	0x00c0, 0x1fc6, 0x70db, 0x0000, 0x0078, 0x1fc8, 0x70db, 0x0001,
+	0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0xac80,
+	0x0001, 0x81ff, 0x0040, 0x1ffa, 0x2099, 0x0030, 0x20a0, 0x700c,
+	0xa084, 0x03ff, 0x0040, 0x1fdc, 0x7018, 0x007e, 0x701c, 0x007e,
+	0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac, 0x721a, 0x731e,
+	0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b,
+	0x00c8, 0x1fee, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0, 0x1ffa,
+	0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x007f, 0x7026,
+	0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a, 0x007c, 0x2011,
+	0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803, 0xfd00, 0x6807,
+	0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109,
+	0x00c0, 0x200b, 0x007c, 0x6004, 0x6086, 0x2c08, 0x2063, 0x0000,
+	0x7868, 0xa005, 0x796a, 0x0040, 0x2028, 0x2c02, 0x0078, 0x2029,
+	0x796e, 0x007c, 0x0c7e, 0x2061, 0x4a00, 0x6887, 0x0103, 0x2d08,
+	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x203a, 0x2d02,
+	0x0078, 0x203b, 0x616e, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x2c04,
+	0x786e, 0xa005, 0x00c0, 0x2045, 0x786a, 0x2091, 0x8001, 0x609c,
+	0xa005, 0x0040, 0x205e, 0x0c7e, 0x2060, 0x2008, 0x609c, 0xa005,
+	0x0040, 0x205a, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005,
+	0x00c0, 0x2052, 0x7848, 0x794a, 0x2062, 0x0c7f, 0x7848, 0x2062,
+	0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x2068, 0x1078, 0x28ec,
+	0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
+	0x00c8, 0x2073, 0xa200, 0x00f0, 0x206e, 0x8086, 0x818e, 0x007c,
+	0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x2099, 0xa11a, 0x00c8,
+	0x2099, 0x8213, 0x818d, 0x0048, 0x208c, 0xa11a, 0x00c8, 0x208d,
+	0x00f0, 0x2081, 0x0078, 0x2091, 0xa11a, 0x2308, 0x8210, 0x00f0,
+	0x2081, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
+	0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x2095, 0x7d74,
+	0x70d0, 0xa506, 0x0040, 0x2185, 0x7810, 0x2050, 0x7800, 0xd08c,
+	0x0040, 0x20c1, 0xdaec, 0x0040, 0x20c1, 0x0e7e, 0x2091, 0x8000,
+	0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x20be, 0x7008, 0x0e7f,
+	0xa086, 0x0008, 0x0040, 0x20c1, 0x0078, 0x2185, 0x0e7f, 0x0078,
+	0x2185, 0x1078, 0x1ddb, 0x0040, 0x2185, 0xa046, 0x7970, 0x2500,
+	0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x20d0, 0x0078, 0x20d7,
+	0x72d0, 0xa206, 0x0040, 0x20d7, 0x8840, 0x2009, 0x0080, 0x0c7e,
+	0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020, 0xac80,
+	0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040, 0x20e9, 0x1078,
+	0x1ddb, 0x7008, 0xd0fc, 0x0040, 0x20e9, 0x7007, 0x0002, 0x2091,
+	0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2120, 0x53a5, 0x8cff, 0x00c0,
+	0x20fe, 0x88ff, 0x0040, 0x216f, 0x0078, 0x2108, 0x2c00, 0x788e,
+	0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0078, 0x216f,
+	0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2110, 0x7420, 0x7524,
+	0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab, 0x0000,
+	0x721a, 0x731e, 0xdac4, 0x0040, 0x2120, 0x7422, 0x7526, 0xa006,
+	0x7007, 0x0004, 0x0040, 0x216f, 0x8cff, 0x0040, 0x2129, 0x1078,
+	0x1de4, 0x0c7f, 0x1078, 0x1de4, 0xa046, 0x7888, 0x8000, 0x788a,
+	0xa086, 0x0002, 0x0040, 0x214f, 0x7a7c, 0x7b78, 0xdac4, 0x0040,
+	0x213b, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210,
+	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e,
+	0xdac4, 0x0040, 0x2185, 0x7422, 0x7526, 0x0078, 0x2185, 0x6014,
+	0xd0fc, 0x00c0, 0x2157, 0x2069, 0x4a40, 0x0078, 0x2159, 0x2069,
+	0x4a80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff, 0x0040, 0x2165,
+	0xa046, 0x788c, 0x2060, 0x0078, 0x214f, 0x788b, 0x0000, 0x78ac,
+	0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078, 0x2185, 0x0c7f,
+	0x788b, 0x0000, 0x1078, 0x2319, 0x6004, 0xa084, 0x000f, 0x1078,
+	0x2186, 0x88ff, 0x0040, 0x2183, 0x788c, 0x2060, 0x6004, 0xa084,
+	0x000f, 0x1078, 0x2186, 0x0078, 0x209f, 0x007c, 0x0079, 0x2188,
+	0x2198, 0x21b6, 0x21d4, 0x2198, 0x21e5, 0x21a9, 0x2198, 0x2198,
+	0x2198, 0x21b4, 0x21d2, 0x2198, 0x2198, 0x2198, 0x2198, 0x2198,
+	0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, 0x600a,
+	0x1078, 0x2228, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, 0x2303,
+	0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21af, 0x0078, 0x2198, 0x601c,
+	0xc0bd, 0x601e, 0x0078, 0x21bc, 0x1078, 0x234b, 0x78bc, 0xd0c4,
+	0x0040, 0x21bc, 0x0078, 0x2198, 0x78bf, 0x0000, 0x6004, 0x8007,
+	0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x21cf, 0x1078, 0x2228,
+	0x0040, 0x21cf, 0x78bc, 0xc0c5, 0x78be, 0x0078, 0x21d1, 0x0078,
+	0x2247, 0x007c, 0x1078, 0x2347, 0x78bc, 0xa08c, 0x0e00, 0x00c0,
+	0x21dc, 0xd0c4, 0x00c0, 0x21de, 0x0078, 0x2198, 0x1078, 0x2228,
+	0x00c0, 0x21e4, 0x0078, 0x2247, 0x007c, 0x78bc, 0xd0c4, 0x0040,
+	0x21eb, 0x0078, 0x2198, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001,
+	0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x220b, 0xa7bc,
+	0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040, 0x220b, 0xa7bc,
+	0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040,
+	0x220b, 0x0078, 0x2225, 0x1078, 0x1e02, 0x2d00, 0x2091, 0x8000,
+	0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a,
+	0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x220e, 0x8211, 0x0040,
+	0x2225, 0x20a9, 0x0100, 0x0078, 0x220e, 0x1078, 0x1de4, 0x007c,
+	0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x00c0, 0x2233,
+	0x78ba, 0x0078, 0x223b, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06,
+	0x00c0, 0x223b, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x00c0, 0x2246,
+	0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x007c, 0x0e7e,
+	0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2,
+	0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0040, 0x225a,
+	0x1078, 0x43c1, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071,
+	0x4a80, 0xd7fc, 0x00c0, 0x2266, 0x2071, 0x4a40, 0xa784, 0x0f00,
+	0x800b, 0xa784, 0x001f, 0x0040, 0x2271, 0x8003, 0x8003, 0x8003,
+	0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007, 0xa084, 0x000f,
+	0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2, 0x2091, 0x8000,
+	0x7810, 0xd0f4, 0x00c0, 0x228b, 0x6e08, 0xd684, 0x0040, 0x22a1,
+	0xd9fc, 0x00c0, 0x22a1, 0x2091, 0x8001, 0x1078, 0x1e6f, 0x2091,
+	0x8000, 0x1078, 0x201b, 0x2091, 0x8001, 0x7814, 0xd0e4, 0x00c0,
+	0x2301, 0x7810, 0xd0f4, 0x0040, 0x2301, 0x601b, 0x0021, 0x0078,
+	0x2301, 0x6024, 0xa096, 0x0001, 0x00c0, 0x22a8, 0x8000, 0x6026,
+	0x6a10, 0x6814, 0xa202, 0x0048, 0x22bb, 0x0040, 0x22bb, 0x2091,
+	0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078,
+	0x2303, 0x0078, 0x2301, 0x2c08, 0xd9fc, 0x0040, 0x22de, 0x6800,
+	0xa065, 0x0040, 0x22de, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040,
+	0x22d9, 0x704c, 0xa206, 0x00c0, 0x22d9, 0x6b04, 0x2160, 0x2304,
+	0x6002, 0xa005, 0x00c0, 0x22d5, 0x6902, 0x2260, 0x6102, 0x0078,
+	0x22ea, 0x2160, 0x6202, 0x6906, 0x0078, 0x22ea, 0x6800, 0x6902,
+	0xa065, 0x0040, 0x22e6, 0x6102, 0x0078, 0x22e7, 0x6906, 0x2160,
+	0x6003, 0x0000, 0x2160, 0xd9fc, 0x0040, 0x22f1, 0xa6b4, 0xfffc,
+	0x6e0a, 0x6810, 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091,
+	0x8001, 0xd6b4, 0x0040, 0x2301, 0xa6b6, 0x0040, 0x6e0a, 0x1078,
+	0x1e80, 0x0e7f, 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000,
+	0x1078, 0x201b, 0x2091, 0x8001, 0x78b8, 0xa065, 0x0040, 0x2316,
+	0x609c, 0x78ba, 0x609f, 0x0000, 0x0078, 0x2303, 0x78b6, 0x78ba,
+	0x007c, 0x7970, 0x7874, 0x2818, 0xd384, 0x0040, 0x2323, 0x8000,
+	0xa112, 0x0048, 0x2328, 0x8000, 0xa112, 0x00c8, 0x2338, 0xc384,
+	0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0040, 0x2333, 0x7a84,
+	0x7222, 0x7a80, 0x7226, 0xa006, 0xd384, 0x0040, 0x2338, 0x8000,
+	0x7876, 0x70d2, 0x781c, 0xa005, 0x0040, 0x2346, 0x8001, 0x781e,
+	0x00c0, 0x2346, 0x0068, 0x2346, 0x2091, 0x4080, 0x007c, 0x2039,
+	0x235f, 0x0078, 0x234d, 0x2039, 0x2365, 0x2704, 0xa005, 0x0040,
+	0x235e, 0xac00, 0x2068, 0x6908, 0x6810, 0x6912, 0x680a, 0x690c,
+	0x6814, 0x6916, 0x680e, 0x8738, 0x0078, 0x234d, 0x007c, 0x0003,
+	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000,
+	0x2041, 0x0000, 0x780c, 0x0079, 0x236d, 0x2535, 0x2508, 0x2371,
+	0x23e5, 0x2039, 0x9274, 0x2734, 0x7d10, 0x0078, 0x238c, 0x6084,
+	0xa086, 0x0103, 0x00c0, 0x23ce, 0x6114, 0x6018, 0xa105, 0x00c0,
+	0x23ce, 0x8603, 0xa080, 0x9255, 0x620c, 0x2202, 0x8000, 0x6210,
+	0x2202, 0x1078, 0x203d, 0x8630, 0xa68e, 0x000f, 0x0040, 0x2454,
+	0x786c, 0xa065, 0x00c0, 0x2377, 0x7808, 0xa602, 0x00c8, 0x239d,
+	0xd5ac, 0x00c0, 0x239d, 0x263a, 0x007c, 0xa682, 0x0003, 0x00c8,
+	0x2454, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0,
+	0x23c9, 0x2011, 0x9255, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca,
+	0xd684, 0x00c0, 0x23b9, 0x8210, 0x2204, 0x70da, 0x8210, 0x2204,
+	0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080,
+	0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0x203b, 0x0000,
+	0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x2454, 0x263a, 0x1078,
+	0x253f, 0x00c0, 0x254e, 0x786c, 0xa065, 0x00c0, 0x2377, 0x2091,
+	0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x23e0, 0xc0ad,
+	0x7812, 0x2091, 0x8001, 0x0078, 0x254e, 0x2039, 0x9274, 0x2734,
+	0x7d10, 0x0078, 0x23fc, 0x6084, 0xa086, 0x0103, 0x00c0, 0x243d,
+	0x6114, 0x6018, 0xa105, 0x00c0, 0x243d, 0xa680, 0x9255, 0x620c,
+	0x2202, 0x1078, 0x203d, 0x8630, 0xa68e, 0x001e, 0x0040, 0x2454,
+	0x786c, 0xa065, 0x00c0, 0x23eb, 0x7808, 0xa602, 0x00c8, 0x240d,
+	0xd5ac, 0x00c0, 0x240d, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8,
+	0x2454, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0,
+	0x2438, 0x2011, 0x9255, 0x2009, 0x924e, 0x26a8, 0x211c, 0x2204,
+	0x201a, 0x8108, 0x8210, 0x00f0, 0x241e, 0xa685, 0x8030, 0x70c2,
+	0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812,
+	0x2091, 0x8001, 0xa006, 0x2009, 0x9275, 0x200a, 0x203a, 0x007c,
+	0x7810, 0xc0ad, 0x7812, 0x0078, 0x2454, 0x263a, 0x1078, 0x253f,
+	0x00c0, 0x254e, 0x786c, 0xa065, 0x00c0, 0x23eb, 0x2091, 0x8000,
+	0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x244f, 0xc0ad, 0x7812,
+	0x2091, 0x8001, 0x0078, 0x254e, 0x2091, 0x8000, 0x7007, 0x0004,
+	0x7994, 0x70d4, 0xa102, 0x0048, 0x2465, 0x0040, 0x246f, 0x7b90,
+	0xa302, 0x00c0, 0x246f, 0x0078, 0x2468, 0x8002, 0x00c0, 0x246f,
+	0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184,
+	0xff00, 0x0040, 0x247c, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004,
+	0x8007, 0xa100, 0x0078, 0x247f, 0x8107, 0x8004, 0x8004, 0x7a9c,
+	0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040,
+	0x248f, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1,
+	0x0030, 0x7003, 0x0000, 0x2009, 0x9254, 0x260a, 0x8109, 0x2198,
+	0x2104, 0xd084, 0x0040, 0x249d, 0x8633, 0xa6b0, 0x0002, 0x26a8,
+	0x53a6, 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000,
+	0xa10a, 0x00c8, 0x24ac, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00,
+	0x0040, 0x24bb, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
+	0xa100, 0x0078, 0x24be, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108,
+	0x7a78, 0xa006, 0xa211, 0xd4c4, 0x0040, 0x24ca, 0x7b84, 0xa319,
+	0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0040, 0x24ca, 0xa084, 0x01e0,
+	0x0040, 0x24ef, 0x7d10, 0x2031, 0x9254, 0x2634, 0x78a8, 0x8000,
+	0x78aa, 0xd08c, 0x00c0, 0x24e4, 0x7007, 0x0006, 0x7004, 0xd094,
+	0x00c0, 0x24de, 0x0078, 0x2456, 0x2069, 0x4a47, 0x206b, 0x0003,
+	0x78ac, 0xa085, 0x0300, 0x78ae, 0xa006, 0x0078, 0x24f8, 0x2030,
+	0x75d6, 0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12,
+	0x2091, 0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001,
+	0x711a, 0x721e, 0xd5c4, 0x0040, 0x2507, 0x7322, 0x7426, 0x007c,
+	0x6084, 0xa086, 0x0103, 0x00c0, 0x252b, 0x6114, 0x6018, 0xa105,
+	0x00c0, 0x252b, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x252b,
+	0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001,
+	0x2091, 0x4080, 0x1078, 0x203d, 0x0068, 0x252a, 0x786c, 0xa065,
+	0x00c0, 0x2508, 0x007c, 0x1078, 0x253f, 0x00c0, 0x254e, 0x786c,
+	0xa065, 0x00c0, 0x2508, 0x0078, 0x254e, 0x1078, 0x253f, 0x00c0,
+	0x254e, 0x786c, 0xa065, 0x00c0, 0x2535, 0x0078, 0x254e, 0x1078,
+	0x2554, 0x00c0, 0x2546, 0xa085, 0x0001, 0x007c, 0x1078, 0x2563,
+	0x00c0, 0x254c, 0x2041, 0x0001, 0x7d10, 0x007c, 0x88ff, 0x0040,
+	0x2553, 0x2091, 0x4080, 0x007c, 0x7b90, 0x7994, 0x70d4, 0xa102,
+	0x00c0, 0x255d, 0xa385, 0x0000, 0x007c, 0x0048, 0x2561, 0xa302,
+	0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec, 0x0040, 0x257b, 0x0e7e,
+	0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2578,
+	0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x257b, 0x0078, 0x25cc,
+	0x0e7f, 0x0078, 0x25cc, 0xa184, 0xff00, 0x0040, 0x2588, 0x810f,
+	0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078, 0x258b,
+	0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa210,
+	0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018, 0x6028, 0xa005,
+	0x0040, 0x259c, 0x2009, 0x0040, 0x1078, 0x1d92, 0x0040, 0x25be,
+	0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0, 0x25cc, 0x6014, 0xd0fc,
+	0x00c0, 0x25ae, 0x2069, 0x4a40, 0x0078, 0x25b0, 0x2069, 0x4a80,
+	0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000, 0x78ac, 0xa085,
+	0x0300, 0x78ae, 0x2091, 0x8001, 0x0078, 0x25cc, 0x78ab, 0x0000,
+	0x1078, 0x203d, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8, 0x25c9,
+	0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091, 0x8001,
+	0x007c, 0x2138, 0xd7fc, 0x00c0, 0x25d9, 0x2009, 0x4a59, 0x0078,
+	0x25db, 0x2009, 0x4a99, 0x2091, 0x8000, 0x200a, 0x0f7e, 0xd7fc,
+	0x00c0, 0x25f2, 0x2009, 0x4a40, 0x2001, 0x4a04, 0x2004, 0xd0ec,
+	0x0040, 0x25ee, 0x2079, 0x0100, 0x0078, 0x25f6, 0x2079, 0x0200,
+	0x0078, 0x25f6, 0x2009, 0x4a80, 0x2079, 0x0100, 0x2104, 0xa086,
+	0x0000, 0x00c0, 0x260f, 0xd7fc, 0x00c0, 0x2602, 0x2009, 0x4a45,
+	0x0078, 0x2604, 0x2009, 0x4a85, 0x2104, 0xa005, 0x00c0, 0x260f,
+	0x7830, 0xa084, 0x00c0, 0x00c0, 0x260f, 0x781b, 0x0045, 0x0f7f,
+	0x007c, 0x2009, 0x0002, 0x2069, 0x4a00, 0x6810, 0xd0ec, 0x00c0,
+	0x2672, 0x2071, 0x4a80, 0x2079, 0x0100, 0x2021, 0x4cbf, 0x784b,
+	0x000f, 0x2019, 0x4205, 0xd184, 0x0040, 0x2632, 0x6810, 0xd0ec,
+	0x0040, 0x262e, 0x20a1, 0x012b, 0x0078, 0x2634, 0x20a1, 0x022b,
+	0x0078, 0x2634, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x2641,
+	0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078,
+	0x2634, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af,
+	0x8020, 0x00f0, 0x2645, 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009,
+	0x0000, 0x0040, 0x2654, 0xc1bd, 0x1078, 0x283d, 0x017f, 0x7020,
+	0xa084, 0x000f, 0x007e, 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x2664,
+	0xa085, 0x6340, 0x0078, 0x2666, 0xa085, 0x62c0, 0x7806, 0x780f,
+	0x9200, 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7456,
+	0x7053, 0x0000, 0x8109, 0x0040, 0x2685, 0x2071, 0x4a40, 0x6810,
+	0xd0ec, 0x0040, 0x267f, 0x2079, 0x0100, 0x0078, 0x2681, 0x2079,
+	0x0200, 0x2021, 0x4abf, 0x0078, 0x261f, 0x007c, 0x017e, 0xd1bc,
+	0x00c0, 0x269a, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x2696, 0x2011, 0x0101, 0x0078, 0x269c, 0x2011, 0x0201,
+	0x0078, 0x269c, 0x2011, 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084,
+	0xfff0, 0xa105, 0x2012, 0x017f, 0x1078, 0x283d, 0x007c, 0xd3fc,
+	0x00c0, 0x26ba, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x26b6, 0x2011, 0x0101, 0x0078, 0x26bc, 0x2011, 0x0201,
+	0x0078, 0x26bc, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0,
+	0x26be, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012,
+	0x007c, 0x2019, 0x0002, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x0040,
+	0x26d6, 0x8319, 0x2009, 0x0101, 0x0078, 0x26d8, 0x2009, 0x0101,
+	0x20a9, 0x0005, 0x8213, 0x00f0, 0x26da, 0xa294, 0x00e0, 0x2104,
+	0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0040, 0x26eb, 0x2009,
+	0x0201, 0x0078, 0x26d8, 0x007c, 0xd3fc, 0x00c0, 0x26ff, 0x007e,
+	0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26fb, 0x2011,
+	0x0101, 0x0078, 0x2701, 0x2011, 0x0201, 0x0078, 0x2701, 0x2011,
+	0x0101, 0x20a9, 0x000c, 0x810b, 0x00f0, 0x2703, 0xa18c, 0xf000,
+	0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0,
+	0x2721, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040,
+	0x271d, 0x2011, 0x0102, 0x0078, 0x2723, 0x2011, 0x0202, 0x0078,
+	0x2723, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012,
+	0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x273d, 0x007e, 0x2001, 0x4a04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2739, 0x2061, 0x0100, 0x0078,
+	0x273f, 0x2061, 0x0200, 0x0078, 0x273f, 0x2061, 0x0100, 0xc1bc,
+	0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f,
+	0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x275d, 0x007e, 0x2001, 0x4a04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2759, 0x2061, 0x0100, 0x0078,
+	0x275f, 0x2061, 0x0200, 0x0078, 0x275f, 0x2061, 0x0100, 0xc1bc,
+	0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf,
+	0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x277f, 0x007e,
+	0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x277b, 0x2061,
+	0x0100, 0x0078, 0x2781, 0x2061, 0x0200, 0x0078, 0x2781, 0x2061,
+	0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4,
+	0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0,
+	0x27a1, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040,
+	0x279d, 0x2061, 0x0100, 0x0078, 0x27a3, 0x2061, 0x0200, 0x0078,
+	0x27a3, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020,
+	0x609a, 0x60a4, 0xa28c, 0x0020, 0x0040, 0x27b1, 0xc2ac, 0xa39d,
+	0x4000, 0xc3fc, 0xd3b4, 0x00c0, 0x27b6, 0xc3fd, 0x62ae, 0x2010,
+	0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e,
+	0x0e7e, 0x6818, 0xa005, 0x0040, 0x281b, 0xd1fc, 0x0040, 0x27cc,
+	0x2061, 0x91d0, 0x0078, 0x27ce, 0x2061, 0x90c0, 0x1078, 0x2823,
+	0x0040, 0x2801, 0x20a9, 0x0101, 0xd1fc, 0x0040, 0x27db, 0x2061,
+	0x90d0, 0x0078, 0x27dd, 0x2061, 0x8fc0, 0x0c7e, 0x1078, 0x2823,
+	0x0040, 0x27e8, 0x0c7f, 0x8c60, 0x00f0, 0x27dd, 0x0078, 0x281b,
+	0x007f, 0xd1fc, 0x0040, 0x27f2, 0xa082, 0x90d0, 0x2071, 0x4a80,
+	0x0078, 0x27f6, 0xa082, 0x8fc0, 0x2071, 0x4a40, 0x707a, 0x7176,
+	0x2001, 0x0004, 0x7066, 0x7083, 0x000f, 0x1078, 0x25d1, 0x0078,
+	0x2817, 0xd1fc, 0x00c0, 0x2808, 0x2071, 0x4a40, 0x0078, 0x280a,
+	0x2071, 0x4a80, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2c00, 0x707e,
+	0x2001, 0x0006, 0x7066, 0x7083, 0x000f, 0x1078, 0x25d1, 0x2001,
+	0x0000, 0x0078, 0x281d, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005,
+	0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x283a, 0x2060,
+	0x6010, 0xa306, 0x00c0, 0x2837, 0x600c, 0xa206, 0x00c0, 0x2837,
+	0x6014, 0xa106, 0x00c0, 0x2837, 0xa006, 0x0078, 0x283c, 0x6000,
+	0x0078, 0x2824, 0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e,
+	0xd1bc, 0x00c0, 0x2855, 0x2079, 0x4a40, 0x007e, 0x2001, 0x4a04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2851, 0x2071, 0x0100, 0x0078,
+	0x2859, 0x2071, 0x0200, 0x0078, 0x2859, 0x2079, 0x4a80, 0x2071,
+	0x0100, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x2863,
+	0x017f, 0x0078, 0x287e, 0x810b, 0x810b, 0x810b, 0x810b, 0x007f,
+	0xd0bc, 0x00c0, 0x287b, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x2877, 0xa18d, 0x0f00, 0x0078, 0x287d, 0xa18d,
+	0x0f00, 0x0078, 0x287d, 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f,
+	0x007c, 0x0e7e, 0x2001, 0x4a01, 0x2004, 0xd0ac, 0x00c0, 0x28ea,
+	0x68e4, 0xd0ac, 0x0040, 0x28ea, 0xa084, 0x0006, 0x00c0, 0x28ea,
+	0x6014, 0xd0fc, 0x00c0, 0x2898, 0x2071, 0x4ec0, 0x0078, 0x289a,
+	0x2071, 0x4f40, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0xae70, 0x7004, 0xa084, 0x000a, 0x00c0, 0x28ea, 0x7108, 0xa194,
+	0xff00, 0x0040, 0x28ea, 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106,
+	0x0040, 0x28cd, 0x2001, 0x000c, 0xa106, 0x0040, 0x28d1, 0x2001,
+	0x0012, 0xa106, 0x0040, 0x28d5, 0x2001, 0x0014, 0xa106, 0x0040,
+	0x28d9, 0x2001, 0x0019, 0xa106, 0x0040, 0x28dd, 0x2001, 0x0032,
+	0xa106, 0x0040, 0x28e1, 0x0078, 0x28e5, 0x2009, 0x000c, 0x0078,
+	0x28e7, 0x2009, 0x0012, 0x0078, 0x28e7, 0x2009, 0x0014, 0x0078,
+	0x28e7, 0x2009, 0x0019, 0x0078, 0x28e7, 0x2009, 0x0020, 0x0078,
+	0x28e7, 0x2009, 0x003f, 0x0078, 0x28e7, 0x2011, 0x0000, 0x2100,
+	0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x28ec, 0x2091, 0x8000,
+	0x2071, 0x0000, 0x007e, 0x7018, 0xd084, 0x00c0, 0x28f3, 0x007f,
+	0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db,
+	0x0809, 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
+	0x4080, 0x0078, 0x2909, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0,
+	0x708e, 0x7592, 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4,
+	0x0040, 0x2920, 0xa784, 0x007d, 0x00c0, 0x417b, 0x1078, 0x28ec,
+	0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x292b, 0xa3a6, 0x0007,
+	0x00c0, 0x28ec, 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x2930,
+	0x2f45, 0x3035, 0x3060, 0x32c1, 0x363b, 0x36a1, 0x3741, 0x37bd,
+	0x38a1, 0x398a, 0x2943, 0x2940, 0x2d2a, 0x2e43, 0x360e, 0x2940,
+	0x1078, 0x28ec, 0x007c, 0xa006, 0x0078, 0x294d, 0x7808, 0xc08d,
+	0x780a, 0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005,
+	0x00c0, 0x2a64, 0x7064, 0xa084, 0x0007, 0x0079, 0x2957, 0x295f,
+	0x29cf, 0x29d8, 0x29e3, 0x29ee, 0x2a4a, 0x29f9, 0x29cf, 0x7830,
+	0xd0bc, 0x00c0, 0x2942, 0x71d4, 0xd1b4, 0x00c0, 0x29ac, 0x70a4,
+	0xa086, 0x0001, 0x0040, 0x2942, 0x70b4, 0xa06d, 0x6800, 0xa065,
+	0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10,
+	0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040, 0x2982, 0x69bc,
+	0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0078,
+	0x2bbd, 0x7060, 0xa005, 0x00c0, 0x2942, 0x0c7e, 0x0d7e, 0x70b4,
+	0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa,
+	0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001,
+	0x0040, 0x29a5, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c,
+	0x2001, 0x0020, 0x0078, 0x2bbd, 0x1078, 0x411c, 0x00c0, 0x2942,
+	0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x68bc,
+	0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x7003,
+	0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0x1078,
+	0x411c, 0x00c0, 0x29d7, 0x781b, 0x0047, 0x7003, 0x0004, 0x007c,
+	0x1078, 0x411c, 0x00c0, 0x29e2, 0x2011, 0x000c, 0x1078, 0x2a09,
+	0x7003, 0x0004, 0x007c, 0x1078, 0x411c, 0x00c0, 0x29ed, 0x2011,
+	0x0006, 0x1078, 0x2a09, 0x7003, 0x0004, 0x007c, 0x1078, 0x411c,
+	0x00c0, 0x29f8, 0x2011, 0x000d, 0x1078, 0x2a09, 0x7003, 0x0004,
+	0x007c, 0x1078, 0x411c, 0x00c0, 0x2a08, 0x2011, 0x0006, 0x1078,
+	0x2a09, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e, 0x7003, 0x0001,
+	0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b, 0x0010, 0xa286,
+	0x000c, 0x00c0, 0x2a18, 0x7aaa, 0x2001, 0x0001, 0x0078, 0x2a2d,
+	0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d, 0x0040,
+	0x2a26, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2a2d, 0x78ab, 0x0020,
+	0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa,
+	0x785b, 0x0004, 0x781b, 0x0108, 0x1078, 0x4131, 0x7083, 0x000f,
+	0x70d4, 0xd0b4, 0x0040, 0x2a49, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8,
+	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
+	0x0c7f, 0x007c, 0x1078, 0x411c, 0x00c0, 0x2942, 0x707c, 0x2068,
+	0x7774, 0x1078, 0x3fe1, 0x2c50, 0x1078, 0x41f0, 0x789b, 0x0010,
+	0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001,
+	0x2001, 0x0004, 0x0078, 0x2bc3, 0x1078, 0x411c, 0x00c0, 0x2942,
+	0x789b, 0x0010, 0x7060, 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040,
+	0x2a7e, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
+	0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x1078, 0x3fe1,
+	0x2c50, 0x1078, 0x41f0, 0x6824, 0xa005, 0x0040, 0x2a8f, 0xa082,
+	0x0006, 0x0048, 0x2a8d, 0x0078, 0x2a8f, 0x6827, 0x0005, 0x6814,
+	0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001,
+	0x2001, 0x0003, 0x0078, 0x2bc3, 0xc28d, 0x72d6, 0x72c0, 0xa200,
+	0xa015, 0x7154, 0x8108, 0xa12a, 0x0048, 0x2aa7, 0x71c0, 0x2164,
+	0x6504, 0x85ff, 0x00c0, 0x2abe, 0x7156, 0x8421, 0x00c0, 0x2aa2,
+	0x70d4, 0xd08c, 0x0040, 0x2aba, 0x70d0, 0xa005, 0x00c0, 0x2aba,
+	0x70d3, 0x000a, 0x007c, 0x2200, 0x0078, 0x2aac, 0x70d4, 0xc08c,
+	0x70d6, 0x70d3, 0x0000, 0x603c, 0xa005, 0x00c0, 0x2abb, 0x6708,
+	0xa784, 0x073f, 0x0040, 0x2aed, 0xd7d4, 0x00c0, 0x2abb, 0xa784,
+	0x0021, 0x00c0, 0x2abb, 0xa784, 0x0002, 0x0040, 0x2ade, 0xa784,
+	0x0004, 0x0040, 0x2abb, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218,
+	0x00c0, 0x2abb, 0xa784, 0x0100, 0x0040, 0x2aed, 0x6018, 0xa005,
+	0x00c0, 0x2abb, 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000,
+	0x6e1c, 0xa684, 0x000e, 0x6318, 0x0040, 0x2afe, 0x601c, 0xa302,
+	0x0048, 0x2b01, 0x0040, 0x2b01, 0x0078, 0x2abb, 0x83ff, 0x00c0,
+	0x2abb, 0x2d58, 0x2c50, 0x7156, 0xd7bc, 0x00c0, 0x2b09, 0x7028,
+	0x6022, 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60,
+	0x2041, 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc,
+	0x0040, 0x2b1d, 0xd684, 0x0040, 0x2b1f, 0xa39c, 0xffbf, 0xd6a4,
+	0x0040, 0x2b24, 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2b6f,
+	0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0,
+	0x2b43, 0x70d4, 0xd0b4, 0x00c0, 0x2b43, 0x7000, 0xa082, 0x0002,
+	0x00c8, 0x2b43, 0x7830, 0xd0bc, 0x00c0, 0x2b43, 0x789b, 0x0010,
+	0x7baa, 0x0078, 0x2bbb, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0,
+	0x0005, 0x70ac, 0xa606, 0x00c0, 0x2b4e, 0x76a8, 0x76b2, 0x2c3a,
+	0x8738, 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a,
+	0x7830, 0xd0bc, 0x0040, 0x2b66, 0x2091, 0x8000, 0x2091, 0x303d,
+	0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000,
+	0x0040, 0x2b6e, 0x8421, 0x2200, 0x00c0, 0x2aa1, 0x007c, 0xd1dc,
+	0x0040, 0x3be5, 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2b7c, 0x8528,
+	0xd68c, 0x00c0, 0x2b7c, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108,
+	0xa18c, 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2b9b,
+	0x6014, 0xa706, 0x00c0, 0x2b84, 0x60b8, 0x8001, 0x60ba, 0x00c0,
+	0x2b7f, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421,
+	0x00c0, 0x2aa1, 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6,
+	0x8840, 0x6008, 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0,
+	0x2b43, 0x70d4, 0xd0b4, 0x00c0, 0x2b43, 0x7000, 0xa082, 0x0002,
+	0x00c8, 0x2b43, 0x7830, 0xd0bc, 0x00c0, 0x2b43, 0x789b, 0x0010,
+	0x7baa, 0x7daa, 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000,
+	0x601a, 0x0078, 0x2bc4, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184,
+	0x0018, 0x0040, 0x2be0, 0xa184, 0x0010, 0x0040, 0x2bd3, 0x1078,
+	0x3df6, 0x00c0, 0x2c05, 0xa184, 0x0008, 0x0040, 0x2be0, 0x69a0,
+	0xa184, 0x0600, 0x00c0, 0x2be0, 0x1078, 0x3cda, 0x0078, 0x2c05,
+	0x69a0, 0xa184, 0x1e00, 0x0040, 0x2c10, 0xa184, 0x0800, 0x0040,
+	0x2bf9, 0x0c7e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104,
+	0xa18d, 0x0010, 0x6106, 0x0c7f, 0x1078, 0x3df6, 0x00c0, 0x2c05,
+	0x69a0, 0xa184, 0x0200, 0x0040, 0x2c01, 0x1078, 0x3d3a, 0x0078,
+	0x2c05, 0xa184, 0x0400, 0x00c0, 0x2bdc, 0x69a0, 0xa184, 0x1000,
+	0x0040, 0x2c10, 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x2749,
+	0x027f, 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2c1d, 0xa086,
+	0x0060, 0x00c0, 0x2c1d, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6,
+	0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc,
+	0x0040, 0x2c38, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050,
+	0x2c36, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a,
+	0x78aa, 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b,
+	0x20a0, 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8,
+	0x2898, 0x25a0, 0xa286, 0x0020, 0x00c0, 0x2c70, 0x70d4, 0xc0b5,
+	0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007,
+	0x7882, 0xa286, 0x0002, 0x0040, 0x2ca6, 0x70a4, 0x8000, 0x70a6,
+	0x74b4, 0xa498, 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2c68, 0x73a8,
+	0x73b6, 0xa286, 0x0010, 0x0040, 0x2942, 0x0d7f, 0x0c7f, 0x007c,
+	0x7000, 0xa005, 0x00c0, 0x2c4e, 0xa286, 0x0002, 0x00c0, 0x2cc0,
+	0x1078, 0x411c, 0x00c0, 0x2c4e, 0x6814, 0xc0fc, 0x8007, 0x7882,
+	0x2091, 0x8000, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d,
+	0x780a, 0x127e, 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090,
+	0x0c7f, 0x0d7f, 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003,
+	0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc,
+	0x0040, 0x2cb2, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091,
+	0x8000, 0x2090, 0x70a4, 0xa005, 0x00c0, 0x2cb7, 0x007c, 0x8421,
+	0x0040, 0x2cb6, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2aa1,
+	0xa286, 0x0010, 0x00c0, 0x2cf1, 0x1078, 0x411c, 0x00c0, 0x2c4e,
+	0x6814, 0xc0fc, 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a,
+	0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d,
+	0x780a, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac,
+	0xa206, 0x00c0, 0x2ce4, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc,
+	0x7042, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046,
+	0x007c, 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007,
+	0x7882, 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b,
+	0x005b, 0x2900, 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300,
+	0xa605, 0x0040, 0x2d1c, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300,
+	0x00c0, 0x2d16, 0x2009, 0x0000, 0x0078, 0x2d18, 0x2009, 0x0001,
+	0xa284, 0x000f, 0x1079, 0x2d20, 0xad80, 0x0009, 0x7046, 0x007c,
+	0x2d28, 0x45f7, 0x45f7, 0x45e4, 0x45f7, 0x2d28, 0x2d28, 0x2d28,
+	0x1078, 0x28ec, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e, 0x2079,
+	0x4a00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2d4e, 0x7064, 0xa086,
+	0x0001, 0x00c0, 0x2d3e, 0x7066, 0x0078, 0x2e27, 0x7064, 0xa086,
+	0x0005, 0x00c0, 0x2d4c, 0x707c, 0x2068, 0x681b, 0x0004, 0x6817,
+	0x0000, 0x6820, 0xc09d, 0x6822, 0x7067, 0x0000, 0x70a7, 0x0000,
+	0x70a8, 0x70b2, 0x70b6, 0x70d4, 0xd0b4, 0x0040, 0x2d64, 0xc0b4,
+	0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a,
+	0x6018, 0x8001, 0x601a, 0x0c7f, 0x157e, 0x2011, 0x0004, 0x7164,
+	0xa186, 0x0001, 0x0040, 0x2d7d, 0xa186, 0x0007, 0x00c0, 0x2d74,
+	0x701f, 0x0005, 0x0078, 0x2d7d, 0x701f, 0x0001, 0x7067, 0x0000,
+	0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x2d7f, 0x7067, 0x0000, 0x2001,
+	0x4a0a, 0x2004, 0xa084, 0x00ff, 0xa086, 0x0018, 0x0040, 0x2d8f,
+	0x7018, 0x7016, 0xa005, 0x00c0, 0x2d8f, 0x70a7, 0x0001, 0x1078,
+	0x4326, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, 0x3edb, 0xa7b8,
+	0x0100, 0x00f0, 0x2d95, 0x7000, 0x0079, 0x2d9e, 0x2dcd, 0x2db3,
+	0x2db3, 0x2da8, 0x2dcd, 0x2dcd, 0x2dcd, 0x2da6, 0x1078, 0x28ec,
+	0x7060, 0xa005, 0x0040, 0x2dcd, 0xad06, 0x00c0, 0x2db3, 0x6800,
+	0x7062, 0x0078, 0x2dc5, 0x6820, 0xd084, 0x00c0, 0x2dc1, 0x6f14,
+	0x1078, 0x3fe1, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3bb5, 0x0078,
+	0x2dc5, 0x705c, 0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000,
+	0x6820, 0xc09d, 0x6822, 0x1078, 0x202a, 0xb284, 0x0400, 0x0040,
+	0x2dd5, 0x2021, 0x91d0, 0x0078, 0x2dd7, 0x2021, 0x90c0, 0x1078,
+	0x2e2c, 0xb284, 0x0400, 0x0040, 0x2de1, 0x2021, 0x4a98, 0x0078,
+	0x2de3, 0x2021, 0x4a58, 0x1078, 0x2e2c, 0x20a9, 0x0101, 0xb284,
+	0x0400, 0x0040, 0x2def, 0x2021, 0x90d0, 0x0078, 0x2df1, 0x2021,
+	0x8fc0, 0x1078, 0x2e2c, 0x8420, 0x00f0, 0x2df1, 0xb284, 0x0300,
+	0x0040, 0x2dfe, 0x2061, 0x4fc0, 0x0078, 0x2e00, 0x2061, 0x6fc0,
+	0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0040, 0x2e1d,
+	0x6018, 0x017e, 0x007e, 0x2011, 0x4a02, 0x220c, 0xa102, 0x2012,
+	0x007f, 0x017f, 0xa102, 0x0050, 0x2e1d, 0x6012, 0x00c0, 0x2e1d,
+	0x2011, 0x4a04, 0x2204, 0xc0a5, 0x2012, 0x601b, 0x0000, 0xace0,
+	0x0010, 0x00f0, 0x2e04, 0x8421, 0x00c0, 0x2e02, 0x157f, 0x7003,
+	0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404, 0xa005, 0x0040,
+	0x2e3f, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817, 0x0000, 0x6820,
+	0xc09d, 0x6822, 0x1078, 0x202a, 0x007f, 0x0078, 0x2e2e, 0x047f,
+	0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, 0x2e49, 0x1078,
+	0x28ec, 0x2300, 0x0079, 0x2e4c, 0x2e4f, 0x2eda, 0x2ef7, 0xa282,
+	0x0002, 0x0040, 0x2e55, 0x1078, 0x28ec, 0x7064, 0x7067, 0x0000,
+	0x7083, 0x0000, 0x0079, 0x2e5c, 0x2e64, 0x2e64, 0x2e66, 0x2ea6,
+	0x3bf1, 0x2e64, 0x2ea6, 0x2e64, 0x1078, 0x28ec, 0x7774, 0x1078,
+	0x3edb, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x3fe1, 0x6018, 0xa005,
+	0x0040, 0x2e9d, 0xd7fc, 0x00c0, 0x2e79, 0x2021, 0x90c0, 0x0078,
+	0x2e7b, 0x2021, 0x91d0, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078,
+	0x2f12, 0x0040, 0x2e9d, 0x157e, 0x20a9, 0x0101, 0xd7fc, 0x00c0,
+	0x2e8d, 0x2021, 0x8fc0, 0x0078, 0x2e8f, 0x2021, 0x90d0, 0x047e,
+	0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x2f12, 0x047f, 0x0040,
+	0x2e9c, 0x8420, 0x00f0, 0x2e8f, 0x157f, 0x8738, 0xa784, 0x001f,
+	0x00c0, 0x2e6c, 0x0078, 0x2946, 0x0078, 0x2946, 0x7774, 0x1078,
+	0x3fe1, 0x6018, 0xa005, 0x0040, 0x2ed8, 0xd7fc, 0x00c0, 0x2eb4,
+	0x2021, 0x90c0, 0x0078, 0x2eb6, 0x2021, 0x91d0, 0x2009, 0x0005,
+	0x2011, 0x0020, 0x1078, 0x2f12, 0x0040, 0x2ed8, 0x157e, 0x20a9,
+	0x0101, 0xd7fc, 0x00c0, 0x2ec8, 0x2021, 0x8fc0, 0x0078, 0x2eca,
+	0x2021, 0x90d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078,
+	0x2f12, 0x047f, 0x0040, 0x2ed7, 0x8420, 0x00f0, 0x2eca, 0x157f,
+	0x0078, 0x2946, 0x2200, 0x0079, 0x2edd, 0x2ee0, 0x2ee2, 0x2ee2,
+	0x1078, 0x28ec, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002, 0x0040,
+	0x2eeb, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040, 0x2ef0, 0x691a,
+	0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x40c9, 0x2200,
+	0x0079, 0x2efa, 0x2eff, 0x2ee2, 0x2efd, 0x1078, 0x28ec, 0x1078,
+	0x4326, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b7a, 0x1078, 0x3bd2,
+	0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3b6b, 0x0040, 0x3b7a,
+	0x0078, 0x2946, 0x2404, 0xa005, 0x0040, 0x2f41, 0x2068, 0x2d04,
+	0x007e, 0x6814, 0xa706, 0x0040, 0x2f21, 0x2d20, 0x007f, 0x0078,
+	0x2f13, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000, 0x6820, 0xa205,
+	0x6822, 0x1078, 0x202a, 0x2021, 0x4a02, 0x241c, 0x8319, 0x2322,
+	0x6010, 0x8001, 0x6012, 0x00c0, 0x2f3a, 0x2021, 0x4a04, 0x2404,
+	0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x1078, 0x3bd2,
+	0x007c, 0xa085, 0x0001, 0x0078, 0x2f40, 0x2300, 0x0079, 0x2f48,
+	0x2f4d, 0x2f4b, 0x2fce, 0x1078, 0x28ec, 0x78e4, 0xa005, 0x00d0,
+	0x2f84, 0x3208, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x2f5e, 0xa18c, 0x0300, 0x0078, 0x2f60, 0xa18c, 0x0400,
+	0x0040, 0x2f66, 0x0018, 0x2942, 0x0078, 0x2f68, 0x0028, 0x2942,
+	0x2008, 0xa084, 0x0030, 0x00c0, 0x2f70, 0x781b, 0x005b, 0x007c,
+	0x78ec, 0xa084, 0x0003, 0x0040, 0x2f6d, 0x2100, 0xa084, 0x0007,
+	0x0079, 0x2f7a, 0x2fae, 0x2fb8, 0x2fa3, 0x2f82, 0x4111, 0x4111,
+	0x2f82, 0x2fc3, 0x1078, 0x28ec, 0x7000, 0xa086, 0x0004, 0x00c0,
+	0x2f9e, 0x7064, 0xa086, 0x0002, 0x00c0, 0x2f94, 0x2011, 0x0002,
+	0x2019, 0x0000, 0x0078, 0x2e43, 0x7064, 0xa086, 0x0006, 0x0040,
+	0x2f8e, 0x7064, 0xa086, 0x0004, 0x0040, 0x2f8e, 0x79e4, 0x2001,
+	0x0003, 0x0078, 0x3304, 0x6818, 0xd0fc, 0x0040, 0x2fa9, 0x681b,
+	0x001d, 0x1078, 0x3eae, 0x781b, 0x0061, 0x007c, 0x6818, 0xd0fc,
+	0x0040, 0x2fb4, 0x681b, 0x001d, 0x1078, 0x3eae, 0x0078, 0x40ed,
+	0x6818, 0xd0fc, 0x0040, 0x2fbe, 0x681b, 0x001d, 0x1078, 0x3eae,
+	0x781b, 0x00ef, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x2fc9, 0x681b,
+	0x001d, 0x1078, 0x3eae, 0x781b, 0x00bf, 0x007c, 0xa584, 0x000f,
+	0x00c0, 0x2feb, 0x7000, 0x0079, 0x2fd5, 0x2946, 0x2fdd, 0x2fdf,
+	0x3b7a, 0x3b7a, 0x3b7a, 0x2fdd, 0x2fdd, 0x1078, 0x28ec, 0x1078,
+	0x3bd2, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3b6b, 0x0040,
+	0x3b7a, 0x0078, 0x2946, 0x78e4, 0xa005, 0x00d0, 0x2f84, 0x3208,
+	0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2ffc,
+	0xa18c, 0x0300, 0x0078, 0x2ffe, 0xa18c, 0x0400, 0x0040, 0x3004,
+	0x0018, 0x2f84, 0x0078, 0x3006, 0x0028, 0x2f84, 0x2008, 0xa084,
+	0x0030, 0x00c0, 0x300e, 0x781b, 0x005b, 0x007c, 0x78ec, 0xa084,
+	0x0003, 0x0040, 0x300b, 0x2100, 0xa184, 0x0007, 0x0079, 0x3018,
+	0x3027, 0x302b, 0x3022, 0x3020, 0x4111, 0x4111, 0x3020, 0x410b,
+	0x1078, 0x28ec, 0x1078, 0x3eb6, 0x781b, 0x0061, 0x007c, 0x1078,
+	0x3eb6, 0x0078, 0x40ed, 0x1078, 0x3eb6, 0x781b, 0x00ef, 0x007c,
+	0x1078, 0x3eb6, 0x781b, 0x00bf, 0x007c, 0x2300, 0x0079, 0x3038,
+	0x303d, 0x303b, 0x303f, 0x1078, 0x28ec, 0x0078, 0x37bd, 0x681b,
+	0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x37bd,
+	0x78ec, 0xa084, 0x0003, 0x0040, 0x37bd, 0xa184, 0x0100, 0x0040,
+	0x3043, 0xa184, 0x0007, 0x0079, 0x3055, 0x305d, 0x302b, 0x2fa3,
+	0x40c9, 0x4111, 0x4111, 0x40c9, 0x410b, 0x1078, 0x40d5, 0x007c,
+	0xa282, 0x0005, 0x0050, 0x3066, 0x1078, 0x28ec, 0x2300, 0x0079,
+	0x3069, 0x306c, 0x328b, 0x3296, 0x2200, 0x0079, 0x306f, 0x3089,
+	0x3076, 0x3089, 0x3074, 0x326e, 0x1078, 0x28ec, 0x789b, 0x0018,
+	0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, 0x3e9d, 0xa08a,
+	0x0004, 0x00c8, 0x3e9d, 0x0079, 0x3085, 0x3e9d, 0x3e9d, 0x3e9d,
+	0x3e47, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x309a,
+	0x0078, 0x3e9d, 0x7000, 0xa005, 0x00c0, 0x3090, 0x2011, 0x0004,
+	0x0078, 0x3998, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x3e9d,
+	0x0079, 0x30a2, 0x30b4, 0x30b2, 0x30c9, 0x30cd, 0x318f, 0x3e9d,
+	0x3e9d, 0x3191, 0x3e9d, 0x3e9d, 0x326a, 0x326a, 0x3e9d, 0x3e9d,
+	0x3e9d, 0x326c, 0x1078, 0x28ec, 0xd6e4, 0x0040, 0x30bf, 0x2001,
+	0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x00ba, 0x007c, 0x6818,
+	0xd0fc, 0x0040, 0x30c7, 0x681b, 0x001d, 0x0078, 0x30b7, 0x0078,
+	0x40c9, 0x681b, 0x001d, 0x0078, 0x3ea7, 0x6920, 0x6922, 0xa684,
+	0x1800, 0x00c0, 0x3121, 0x6820, 0xd084, 0x00c0, 0x3127, 0x6818,
+	0xa086, 0x0008, 0x00c0, 0x30de, 0x681b, 0x0000, 0xd6d4, 0x0040,
+	0x318c, 0xd6bc, 0x0040, 0x311e, 0x7087, 0x0000, 0x6818, 0xa084,
+	0x003f, 0xa08a, 0x000d, 0x0050, 0x311e, 0xa08a, 0x000c, 0x7186,
+	0x2001, 0x000c, 0x800c, 0x718a, 0x789b, 0x0061, 0x78aa, 0x157e,
+	0x137e, 0x147e, 0x017e, 0x3208, 0xa18c, 0x0300, 0x0040, 0x3110,
+	0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x310c,
+	0x20a1, 0x012b, 0x0078, 0x3112, 0x20a1, 0x022b, 0x0078, 0x3112,
+	0x20a1, 0x012b, 0x017f, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80,
+	0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x781b, 0x0064,
+	0x007c, 0xd6e4, 0x0040, 0x3127, 0x781b, 0x0076, 0x007c, 0xa684,
+	0x0060, 0x0040, 0x3189, 0xd6dc, 0x0040, 0x3189, 0xd6fc, 0x00c0,
+	0x3133, 0x0078, 0x314a, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8,
+	0x78d0, 0x801b, 0x00c8, 0x313d, 0x8000, 0xa084, 0x003f, 0xa108,
+	0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
+	0xa303, 0x68ae, 0xd6f4, 0x0040, 0x3150, 0xc6f4, 0x7e5a, 0x6eb6,
+	0x7000, 0xa086, 0x0003, 0x00c0, 0x315e, 0x007e, 0x1078, 0x4326,
+	0x1078, 0x45f7, 0x007f, 0x781b, 0x0073, 0x007c, 0xa006, 0x1078,
+	0x46e5, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040,
+	0x316d, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda,
+	0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0, 0x317d, 0xc6f5,
+	0x7e5a, 0x6eb6, 0x781b, 0x0073, 0x007c, 0x781b, 0x0073, 0x2200,
+	0xa115, 0x00c0, 0x3186, 0x1078, 0x45f7, 0x007c, 0x1078, 0x462d,
+	0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0064, 0x007c, 0x1078,
+	0x28ec, 0x0078, 0x31dd, 0x6920, 0xd1c4, 0x0040, 0x31a6, 0xc1c4,
+	0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004,
+	0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x31d1, 0xd1cc, 0x0040,
+	0x31d1, 0xc1cc, 0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec,
+	0x6002, 0x6004, 0xc0a4, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c,
+	0x0040, 0x31d1, 0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040,
+	0x31d1, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
+	0xd6d4, 0x00c0, 0x31ce, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075,
+	0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x31d8, 0x781b, 0x0064, 0x007c,
+	0x781b, 0x0076, 0x007c, 0x0078, 0x3ea2, 0x2019, 0x0000, 0x7990,
+	0xa18c, 0x0007, 0x00c0, 0x31eb, 0x6820, 0xa084, 0x0100, 0x0040,
+	0x31db, 0x2009, 0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff,
+	0xa286, 0x0001, 0x00c0, 0x3207, 0x2300, 0x7ca8, 0xa400, 0x2018,
+	0xa102, 0x0040, 0x31ff, 0x0048, 0x31ff, 0x0078, 0x3201, 0x0078,
+	0x3193, 0x24a8, 0x7aa8, 0x00f0, 0x3201, 0x0078, 0x31ed, 0xa284,
+	0x00f0, 0xa086, 0x0020, 0x00c0, 0x325b, 0x8318, 0x8318, 0x2300,
+	0xa102, 0x0040, 0x3217, 0x0048, 0x3217, 0x0078, 0x3258, 0xa286,
+	0x0023, 0x0040, 0x31db, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
+	0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a,
+	0x0c7e, 0x7058, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4,
+	0x0040, 0x3238, 0x1078, 0x3fdd, 0x1078, 0x3df6, 0x0078, 0x3246,
+	0x0c7e, 0x7058, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c,
+	0x0040, 0x31d1, 0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040,
+	0x31d1, 0x789b, 0x0060, 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4,
+	0x00c0, 0x3255, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, 0x007c,
+	0x7aa8, 0x0078, 0x31ed, 0x8318, 0x2300, 0xa102, 0x0040, 0x3264,
+	0x0048, 0x3264, 0x0078, 0x31ed, 0xa284, 0x0080, 0x00c0, 0x3ea7,
+	0x0078, 0x3ea2, 0x0078, 0x3ea7, 0x0078, 0x3e9d, 0x7058, 0xa04d,
+	0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040,
+	0x327b, 0x1078, 0x28ec, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084,
+	0x00ff, 0xa08a, 0x0004, 0x00c8, 0x3e9d, 0x0079, 0x3287, 0x3e9d,
+	0x3c2c, 0x3e9d, 0x3d9e, 0xa282, 0x0000, 0x00c0, 0x3291, 0x1078,
+	0x28ec, 0x1078, 0x3eae, 0x781b, 0x0075, 0x007c, 0xa282, 0x0003,
+	0x00c0, 0x329c, 0x1078, 0x28ec, 0xd4fc, 0x00c0, 0x32bc, 0x7064,
+	0xa005, 0x0040, 0x32a5, 0x1078, 0x28ec, 0x6f14, 0x7776, 0xa7bc,
+	0x8f00, 0x1078, 0x3fe1, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738,
+	0xa784, 0x001f, 0x00c0, 0x32a9, 0x1078, 0x3eb2, 0x7067, 0x0002,
+	0x701f, 0x0009, 0x0078, 0x32be, 0x1078, 0x3ebe, 0x781b, 0x0075,
+	0x007c, 0xa282, 0x0004, 0x0050, 0x32c7, 0x1078, 0x28ec, 0x2300,
+	0x0079, 0x32ca, 0x32cd, 0x346b, 0x34ae, 0xa286, 0x0003, 0x0040,
+	0x3304, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d4, 0xd1b4, 0x0078,
+	0x32fc, 0x0040, 0x32fc, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x32fc,
+	0xa282, 0x0002, 0x00c8, 0x32fc, 0x0d7e, 0x783b, 0x8300, 0x781b,
+	0x004c, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
+	0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f,
+	0x2001, 0x0000, 0x0078, 0x3308, 0x783b, 0x1300, 0x781b, 0x004a,
+	0x2001, 0x0000, 0x0078, 0x3308, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0,
+	0x704a, 0x68a0, 0xd0ec, 0x0040, 0x3310, 0x6008, 0xc08d, 0x600a,
+	0xa284, 0x000f, 0x0079, 0x3314, 0x344b, 0x3321, 0x331e, 0x35ae,
+	0x35f2, 0x2946, 0x331c, 0x331c, 0x1078, 0x28ec, 0x6008, 0xc0d4,
+	0x600a, 0xd6e4, 0x00c0, 0x3328, 0x1078, 0x4326, 0x0040, 0x3404,
+	0x7868, 0xa08c, 0x00ff, 0x0040, 0x3369, 0xa186, 0x0008, 0x00c0,
+	0x333e, 0x1078, 0x3bd2, 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3b6b,
+	0x0040, 0x3369, 0x1078, 0x4326, 0x0078, 0x3353, 0xa186, 0x0028,
+	0x00c0, 0x3369, 0x1078, 0x4326, 0x6008, 0xc0a4, 0x600a, 0x6018,
+	0xa005, 0x0040, 0x3353, 0x8001, 0x601a, 0x0040, 0x3353, 0x8001,
+	0x0040, 0x3353, 0x601e, 0x6820, 0xd084, 0x0040, 0x2946, 0xc084,
+	0x6822, 0x705c, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004,
+	0x6802, 0xa005, 0x2d00, 0x00c0, 0x3366, 0x6002, 0x6006, 0x0078,
+	0x2946, 0x017e, 0x81ff, 0x00c0, 0x33b0, 0x7000, 0xa086, 0x0030,
+	0x0040, 0x33b0, 0x71d4, 0xd1b4, 0x00c0, 0x3397, 0x7060, 0xa005,
+	0x00c0, 0x33b0, 0x70a4, 0xa086, 0x0001, 0x0040, 0x33b0, 0x7003,
+	0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e, 0x1078,
+	0x296c, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f, 0x71d4,
+	0xd1b4, 0x00c0, 0x33b0, 0x7003, 0x0040, 0x0078, 0x33b0, 0x1078,
+	0x411c, 0x00c0, 0x33b0, 0x781b, 0x005b, 0x0d7e, 0x70bc, 0xa06d,
+	0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
+	0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x0d7f,
+	0x1078, 0x34e8, 0x017f, 0x81ff, 0x0040, 0x3403, 0xa684, 0xdf00,
+	0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0, 0x3404,
+	0x70d4, 0xd0b4, 0x0040, 0x33d1, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8,
+	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
+	0x0c7f, 0x6820, 0xd0dc, 0x00c0, 0x3404, 0x8717, 0xa294, 0x000f,
+	0x8213, 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x33e3, 0xa290,
+	0x4ec0, 0x0078, 0x33e5, 0xa290, 0x4f40, 0xa290, 0x0000, 0x221c,
+	0xd3c4, 0x00c0, 0x33ed, 0x0078, 0x33f3, 0x8210, 0x2204, 0xa085,
+	0x0018, 0x2012, 0x8211, 0xd3d4, 0x0040, 0x33fe, 0x68a0, 0xd0c4,
+	0x00c0, 0x33fe, 0x1078, 0x3562, 0x0078, 0x2946, 0x6008, 0xc08d,
+	0x600a, 0x0078, 0x3404, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040,
+	0x340b, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff,
+	0x0040, 0x3420, 0x2009, 0x4a02, 0x2104, 0x8001, 0x200a, 0x8421,
+	0x6412, 0x00c0, 0x3420, 0x2021, 0x4a04, 0x2404, 0xc0a5, 0x2022,
+	0x6018, 0xa005, 0x0040, 0x3428, 0x8001, 0x601a, 0x00c0, 0x342b,
+	0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x3437, 0x6800,
+	0xa005, 0x00c0, 0x3434, 0x6002, 0x6006, 0x0078, 0x343b, 0x705c,
+	0x2060, 0x6800, 0x6002, 0x2061, 0x4a00, 0x6887, 0x0103, 0x2d08,
+	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x344a, 0x2d02,
+	0x0078, 0x344b, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x345b,
+	0xa286, 0x0040, 0x00c0, 0x2946, 0x7003, 0x0002, 0x704c, 0x2068,
+	0x68c4, 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc,
+	0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80,
+	0x0009, 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x3471, 0x1078,
+	0x28ec, 0x2200, 0x0079, 0x3474, 0x3478, 0x3489, 0x3496, 0x3489,
+	0xa586, 0x1300, 0x0040, 0x3489, 0xa586, 0x8300, 0x00c0, 0x346f,
+	0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x7000, 0xa086, 0x0005, 0x0040, 0x3493, 0x1078, 0x3eae,
+	0x781b, 0x0075, 0x007c, 0x781b, 0x0076, 0x007c, 0x7890, 0x8007,
+	0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
+	0x00ff, 0xa186, 0x0003, 0x0040, 0x34ab, 0xa186, 0x0000, 0x0040,
+	0x34ab, 0x0078, 0x3e9d, 0x781b, 0x0076, 0x007c, 0x6820, 0xc095,
+	0x6822, 0x82ff, 0x00c0, 0x34b8, 0x1078, 0x3eae, 0x0078, 0x34bf,
+	0x8211, 0x0040, 0x34bd, 0x1078, 0x28ec, 0x1078, 0x3ebe, 0x781b,
+	0x0075, 0x007c, 0x1078, 0x4131, 0x7830, 0xa084, 0x00c0, 0x00c0,
+	0x34e5, 0x017e, 0x3208, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x34d7, 0xa18c, 0x0300, 0x0078, 0x34d9, 0xa18c,
+	0x0400, 0x017f, 0x0040, 0x34e0, 0x0018, 0x34e5, 0x0078, 0x34e2,
+	0x0028, 0x34e5, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
+	0xa684, 0x0060, 0x00c0, 0x34f2, 0x682f, 0x0000, 0x6833, 0x0000,
+	0x0078, 0x3561, 0xd6dc, 0x00c0, 0x350a, 0x68b4, 0xd0dc, 0x00c0,
+	0x350a, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0,
+	0x3507, 0x2200, 0xa105, 0x0040, 0x4326, 0x704b, 0x0015, 0x0078,
+	0x4326, 0x007c, 0xd6ac, 0x0040, 0x3530, 0xd6f4, 0x0040, 0x3516,
+	0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x4326, 0x68b4, 0xa084,
+	0x4000, 0xa635, 0xd6f4, 0x00c0, 0x3510, 0x7048, 0xa005, 0x00c0,
+	0x3523, 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x352c, 0x68b4, 0xd0dc,
+	0x0040, 0x352c, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x4326,
+	0xd6f4, 0x0040, 0x3539, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
+	0x4326, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x3533,
+	0x7048, 0xa005, 0x00c0, 0x3546, 0x704b, 0x0015, 0x2408, 0x2510,
+	0x2700, 0x80fb, 0x00c8, 0x354d, 0x8000, 0xa084, 0x003f, 0xa108,
+	0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x355a,
+	0x0078, 0x4326, 0x7000, 0xa086, 0x0006, 0x0040, 0x3561, 0x0078,
+	0x4326, 0x007c, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x3568, 0xc08d,
+	0x600a, 0x681b, 0x0006, 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30,
+	0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837,
+	0x0020, 0x6897, 0x0000, 0x689b, 0x0020, 0x7000, 0x0079, 0x3580,
+	0x2946, 0x3592, 0x358a, 0x3588, 0x3588, 0x3588, 0x3588, 0x3588,
+	0x1078, 0x28ec, 0x6820, 0xd084, 0x00c0, 0x3592, 0x1078, 0x3bb5,
+	0x0078, 0x3598, 0x705c, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60,
+	0x3208, 0xa18c, 0x0300, 0x0040, 0x35a1, 0x2021, 0x4a58, 0x0078,
+	0x35a3, 0x2021, 0x4a98, 0x2404, 0xa005, 0x0040, 0x35aa, 0x2020,
+	0x0078, 0x35a3, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x3bbc,
+	0x1078, 0x3bd2, 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000, 0x789b,
+	0x000e, 0x6f14, 0x6817, 0x0002, 0x3208, 0xa18c, 0x0300, 0x0040,
+	0x35c5, 0x2009, 0x0000, 0x0078, 0x35c7, 0x2009, 0x0001, 0x1078,
+	0x471a, 0xd6dc, 0x0040, 0x35cf, 0x691c, 0xc1ed, 0x691e, 0x6818,
+	0xd0fc, 0x0040, 0x35de, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x35dc,
+	0x681b, 0x001e, 0x0078, 0x35de, 0x681b, 0x0000, 0xb284, 0x0300,
+	0x00c0, 0x35e6, 0x2021, 0x4a98, 0x0078, 0x35e8, 0x2021, 0x4a58,
+	0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x202a,
+	0x0078, 0x2946, 0x7cd8, 0x7ddc, 0x7fd0, 0x1078, 0x34e8, 0x682b,
+	0x0000, 0x789b, 0x000e, 0x6f14, 0x1078, 0x4135, 0xa08c, 0x00ff,
+	0x6916, 0x6818, 0xd0fc, 0x0040, 0x3607, 0x7048, 0x681a, 0xa68c,
+	0xdf00, 0x691e, 0x7067, 0x0000, 0x0078, 0x2946, 0x7000, 0xa005,
+	0x00c0, 0x3614, 0x0078, 0x2946, 0xa006, 0x1078, 0x4326, 0x6817,
+	0x0000, 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000,
+	0x6820, 0xa084, 0x00ff, 0x6822, 0x7000, 0x0079, 0x3627, 0x2946,
+	0x3634, 0x3631, 0x3636, 0x3636, 0x3636, 0x362f, 0x362f, 0x1078,
+	0x28ec, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3bd2, 0x6008, 0xc0a4,
+	0x600a, 0x0078, 0x3b85, 0x2300, 0x0079, 0x363e, 0x3641, 0x3643,
+	0x369f, 0x1078, 0x28ec, 0xd6fc, 0x00c0, 0x3686, 0x7000, 0xa00d,
+	0x0079, 0x364a, 0x2946, 0x3654, 0x3654, 0x3678, 0x3654, 0x3683,
+	0x3652, 0x3652, 0x1078, 0x28ec, 0xa684, 0x0060, 0xa086, 0x0060,
+	0x00c0, 0x3675, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x681c, 0xc0ac,
+	0x681e, 0xa186, 0x0002, 0x0040, 0x3667, 0x1078, 0x4326, 0x1078,
+	0x45f7, 0x781b, 0x0076, 0x71d4, 0xd1b4, 0x00c0, 0x2942, 0x70a4,
+	0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6ec, 0x0040, 0x365c,
+	0x6818, 0xd0fc, 0x0040, 0x3683, 0x681b, 0x0015, 0xd6f4, 0x0040,
+	0x3683, 0x681b, 0x0007, 0x1078, 0x40d5, 0x007c, 0xc6fc, 0x7e5a,
+	0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x368f, 0x8000, 0xa084,
+	0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
+	0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0076, 0x007c, 0x1078,
+	0x28ec, 0x2300, 0x0079, 0x36a4, 0x36a9, 0x36c5, 0x3719, 0x1078,
+	0x28ec, 0x7000, 0x0079, 0x36ac, 0x36b4, 0x36b6, 0x36b6, 0x36b4,
+	0x36b4, 0x36b4, 0x36b4, 0x36b4, 0x1078, 0x28ec, 0x1078, 0x45f7,
+	0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0, 0x2942, 0x70a4,
+	0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6fc, 0x00c0, 0x3709,
+	0x7000, 0xa00d, 0x0079, 0x36cc, 0x2946, 0x36dc, 0x36d6, 0x3700,
+	0x36dc, 0x3706, 0x36d4, 0x36d4, 0x1078, 0x28ec, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0xa086, 0x0060,
+	0x00c0, 0x36fd, 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0xa186, 0x0002,
+	0x0040, 0x36ec, 0x1078, 0x4326, 0x1078, 0x45f7, 0x781b, 0x0076,
+	0x681c, 0xc0b4, 0x681e, 0x71d4, 0xd1b4, 0x00c0, 0x2942, 0x70a4,
+	0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6ec, 0x0040, 0x36e4,
+	0x6818, 0xd0fc, 0x0040, 0x3706, 0x681b, 0x0007, 0x781b, 0x00f0,
+	0x007c, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302,
+	0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0076,
+	0x007c, 0xd6dc, 0x0040, 0x3722, 0x782b, 0x3009, 0x781b, 0x0076,
+	0x0078, 0x2942, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008,
+	0x00c0, 0x3735, 0xa484, 0x0200, 0x0040, 0x372f, 0xc6f5, 0xc6dd,
+	0x7e5a, 0x781b, 0x0076, 0x0078, 0x2942, 0x6820, 0xc095, 0x6822,
+	0x1078, 0x4062, 0xc6dd, 0x1078, 0x3eae, 0x781b, 0x0075, 0x0078,
+	0x2942, 0x2300, 0x0079, 0x3744, 0x3747, 0x3749, 0x374b, 0x1078,
+	0x28ec, 0x0078, 0x3ea7, 0xd6d4, 0x00c0, 0x3771, 0x79e4, 0xd1ac,
+	0x0040, 0x3759, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3759, 0x782b,
+	0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a,
+	0x79e4, 0xd1ac, 0x0040, 0x3769, 0x78ec, 0xa084, 0x0003, 0x00c0,
+	0x376d, 0x2001, 0x0014, 0x0078, 0x3304, 0xa184, 0x0007, 0x0079,
+	0x37a7, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff,
+	0x0040, 0x37a5, 0x789b, 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0,
+	0x3798, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0, 0x378b, 0x2009,
+	0xfff7, 0x0078, 0x3791, 0xa386, 0x0003, 0x00c0, 0x3798, 0x2009,
+	0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f,
+	0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b,
+	0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x40c9, 0x2fae,
+	0x2fb8, 0x37b1, 0x37b7, 0x37af, 0x37af, 0x40c9, 0x40c9, 0x1078,
+	0x28ec, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x40cf, 0x6920,
+	0xa18c, 0xfcff, 0x6922, 0x0078, 0x40c9, 0x79e4, 0xa184, 0x0030,
+	0x0040, 0x37c7, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x37f1, 0x7000,
+	0xa086, 0x0004, 0x00c0, 0x37e1, 0x7064, 0xa086, 0x0002, 0x00c0,
+	0x37d7, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2e43, 0x7064,
+	0xa086, 0x0006, 0x0040, 0x37d1, 0x7064, 0xa086, 0x0004, 0x0040,
+	0x37d1, 0x7000, 0xa086, 0x0000, 0x0040, 0x2942, 0x6820, 0xd0ac,
+	0x00c0, 0x37ed, 0x6818, 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0078,
+	0x3304, 0xa184, 0x0007, 0x0079, 0x37f5, 0x40c9, 0x40c9, 0x37fd,
+	0x40c9, 0x4111, 0x4111, 0x40c9, 0x40c9, 0xd6bc, 0x0040, 0x383f,
+	0x7184, 0x81ff, 0x0040, 0x383f, 0xa182, 0x000d, 0x00d0, 0x380c,
+	0x7087, 0x0000, 0x0078, 0x3811, 0xa182, 0x000c, 0x7086, 0x2009,
+	0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e, 0x7088,
+	0x8114, 0xa210, 0x728a, 0xa080, 0x000b, 0xad00, 0x2098, 0xb284,
+	0x0300, 0x0040, 0x3833, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x382f, 0x20a1, 0x012b, 0x0078, 0x3835, 0x20a1,
+	0x022b, 0x0078, 0x3835, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108,
+	0x81ac, 0x53a6, 0x147f, 0x137f, 0x157f, 0x0078, 0x40cf, 0xd6d4,
+	0x00c0, 0x3893, 0x6820, 0xd084, 0x0040, 0x40cf, 0xa68c, 0x0060,
+	0xa684, 0x0060, 0x0040, 0x3851, 0xa086, 0x0060, 0x00c0, 0x3851,
+	0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000,
+	0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c,
+	0x0040, 0x3beb, 0xa18c, 0x00f8, 0x00c0, 0x3beb, 0x157e, 0x137e,
+	0x147e, 0x017e, 0x3208, 0xa18c, 0x0300, 0x0040, 0x387f, 0x007e,
+	0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x387b, 0x20a1,
+	0x012b, 0x0078, 0x3881, 0x20a1, 0x022b, 0x0078, 0x3881, 0x20a1,
+	0x012b, 0x017f, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b,
+	0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, 0xc0fc, 0x8007,
+	0x7882, 0x0078, 0x40cf, 0x6818, 0xd0fc, 0x0040, 0x3899, 0x681b,
+	0x0008, 0x6820, 0xc0ad, 0x6822, 0x1078, 0x3eb6, 0x781b, 0x00e1,
+	0x007c, 0x2300, 0x0079, 0x38a4, 0x38a9, 0x397b, 0x38a7, 0x1078,
+	0x28ec, 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x00c0, 0x38d1, 0x7200,
+	0xa286, 0x0003, 0x0040, 0x32d2, 0x71d4, 0xd1b4, 0x0078, 0x38d4,
+	0x0040, 0x38d4, 0x0d7e, 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc,
+	0xa06d, 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
+	0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078,
+	0x38d8, 0x7200, 0x0078, 0x38d8, 0x783b, 0x1800, 0x781b, 0x004a,
+	0xa284, 0x000f, 0x0079, 0x38dc, 0x3966, 0x391a, 0x38e6, 0x3300,
+	0x38e4, 0x3966, 0x38e4, 0x38e4, 0x1078, 0x28ec, 0x681c, 0xd0ec,
+	0x0040, 0x38ed, 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922,
+	0x6800, 0x6006, 0xa005, 0x00c0, 0x38f6, 0x6002, 0x6008, 0xc0d4,
+	0x600a, 0x681c, 0xa084, 0x000e, 0x00c0, 0x390a, 0xb284, 0x0300,
+	0x0040, 0x3906, 0x2009, 0x90c0, 0x0078, 0x390f, 0x2009, 0x91d0,
+	0x0078, 0x390f, 0x7030, 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104,
+	0x6802, 0x2d0a, 0x715e, 0xd6dc, 0x00c0, 0x391a, 0xc6fc, 0x6eb6,
+	0x0078, 0x3966, 0x6eb6, 0xa684, 0x0060, 0x0040, 0x3966, 0xd6dc,
+	0x00c0, 0x392d, 0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898,
+	0x68aa, 0x1078, 0x4326, 0x0078, 0x3966, 0xd6ac, 0x0040, 0x3939,
+	0xa006, 0x1078, 0x4326, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0078,
+	0x3949, 0x2408, 0x2510, 0x2700, 0x801b, 0x00c8, 0x3940, 0x8000,
+	0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x69aa, 0x6aa6, 0x1078,
+	0x4326, 0xd6fc, 0x0040, 0x3966, 0xa684, 0x7fff, 0x68b6, 0x2510,
+	0x2408, 0xd6ac, 0x00c0, 0x395e, 0x2700, 0x801b, 0x00c8, 0x3959,
+	0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100,
+	0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086,
+	0x0030, 0x00c0, 0x2946, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc,
+	0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80,
+	0x0009, 0x7046, 0x007c, 0xa586, 0x8800, 0x00c0, 0x3988, 0x7003,
+	0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a,
+	0x0078, 0x3ea7, 0x7047, 0x0000, 0xa282, 0x0006, 0x0050, 0x3992,
+	0x1078, 0x28ec, 0x2300, 0x0079, 0x3995, 0x3998, 0x39cf, 0x3a01,
+	0x2200, 0x0079, 0x399b, 0x39a1, 0x3ea7, 0x39a3, 0x39a1, 0x3a38,
+	0x3a9b, 0x1078, 0x28ec, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040,
+	0x39ad, 0x2001, 0x91e0, 0x0078, 0x39af, 0x2001, 0x9212, 0x2068,
+	0x704e, 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0,
+	0x39b4, 0x157f, 0xb284, 0x0300, 0x0040, 0x39c2, 0x6817, 0x0000,
+	0x0078, 0x39c4, 0x6817, 0x8000, 0xad80, 0x0009, 0x7046, 0x68b7,
+	0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x3e9d, 0x7000,
+	0xa086, 0x0002, 0x00c0, 0x39e0, 0x1078, 0x3bd2, 0x0078, 0x39da,
+	0x1078, 0x4326, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0078, 0x39e5,
+	0x7000, 0xa086, 0x0003, 0x0040, 0x39d8, 0x7003, 0x0005, 0xb284,
+	0x0300, 0x0040, 0x39ef, 0x2001, 0x91e0, 0x0078, 0x39f1, 0x2001,
+	0x9212, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046, 0x2200, 0x0079,
+	0x39f9, 0x3ea7, 0x39ff, 0x39ff, 0x3a38, 0x39ff, 0x3ea7, 0x1078,
+	0x28ec, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3a12, 0x1078, 0x3bd2,
+	0x0078, 0x3a0c, 0x1078, 0x4326, 0x6008, 0xa084, 0xfbef, 0x600a,
+	0x0078, 0x3a17, 0x7000, 0xa086, 0x0003, 0x0040, 0x3a0a, 0x7003,
+	0x0005, 0xb284, 0x0300, 0x0040, 0x3a21, 0x2001, 0x91e0, 0x0078,
+	0x3a23, 0x2001, 0x9212, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046,
+	0x2200, 0x0079, 0x3a2b, 0x3a33, 0x3a31, 0x3a31, 0x3a33, 0x3a31,
+	0x3a33, 0x1078, 0x28ec, 0x1078, 0x3ebe, 0x781b, 0x0075, 0x007c,
+	0x7000, 0xa086, 0x0002, 0x00c0, 0x3a4a, 0x70d4, 0xc0b5, 0x70d6,
+	0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3a4f, 0x1078, 0x4326,
+	0x0078, 0x3a4f, 0x7000, 0xa086, 0x0003, 0x0040, 0x3a46, 0x7003,
+	0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484,
+	0x001f, 0xa215, 0x2069, 0x90c0, 0xb284, 0x0300, 0x00c0, 0x3a63,
+	0xc2fd, 0x2069, 0x91d0, 0x2d04, 0x2d08, 0x715e, 0xa06d, 0x0040,
+	0x3a70, 0x6814, 0xa206, 0x0040, 0x3a90, 0x6800, 0x0078, 0x3a64,
+	0x7003, 0x0005, 0xd2fc, 0x00c0, 0x3a79, 0x2001, 0x91e0, 0x0078,
+	0x3a7b, 0x2001, 0x9212, 0x2068, 0x704e, 0x157e, 0x20a9, 0x0032,
+	0x2003, 0x0000, 0x8000, 0x00f0, 0x3a80, 0x157f, 0xad80, 0x0009,
+	0x7046, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003,
+	0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x3b10, 0x1078,
+	0x3eb6, 0x0078, 0x3b10, 0x7200, 0xa286, 0x0002, 0x00c0, 0x3aad,
+	0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078,
+	0x3ab1, 0x1078, 0x4326, 0x0078, 0x3ab1, 0xa286, 0x0003, 0x0040,
+	0x3aa9, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018,
+	0x7ca8, 0xa484, 0x001f, 0xa215, 0xb284, 0x0300, 0x00c0, 0x3ac1,
+	0xc2fd, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x70cc, 0xa168, 0x2d04,
+	0x2d08, 0x715e, 0xa06d, 0x0040, 0x3ad4, 0x6814, 0xa206, 0x0040,
+	0x3afd, 0x6800, 0x0078, 0x3ac8, 0x7003, 0x0005, 0xb284, 0x0300,
+	0x0040, 0x3ade, 0x2001, 0x91e0, 0x0078, 0x3ae0, 0x2001, 0x9212,
+	0x2068, 0x704e, 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000,
+	0x00f0, 0x3ae5, 0x157f, 0xb284, 0x0300, 0x0040, 0x3af2, 0xc2fc,
+	0x0078, 0x3af3, 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7,
+	0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x6820, 0xa084,
+	0x0c00, 0x0040, 0x3b10, 0xd0dc, 0x0040, 0x3b0a, 0x1078, 0x3eba,
+	0x0078, 0x3b10, 0x1078, 0x3eb6, 0x707f, 0x0000, 0x0078, 0x3b10,
+	0xa6ac, 0x0060, 0x0040, 0x3b4e, 0x6b98, 0x6c94, 0x69ac, 0x68b0,
+	0xa105, 0x00c0, 0x3b33, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4,
+	0xb7ff, 0xa586, 0x0060, 0x0040, 0x3b4e, 0xc6ed, 0x7e5a, 0x2009,
+	0x0076, 0xd69c, 0x0040, 0x3b2e, 0x2009, 0x0075, 0x791a, 0x1078,
+	0x45f7, 0x0078, 0x3b57, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400,
+	0xa305, 0x0040, 0x3b4e, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0,
+	0xc6f4, 0x7e5a, 0x2011, 0x0076, 0xd69c, 0x0040, 0x3b49, 0x2011,
+	0x0075, 0x7a1a, 0x1078, 0x462d, 0x0078, 0x3b57, 0x7e5a, 0x2009,
+	0x0076, 0xd69c, 0x0040, 0x3b56, 0x2009, 0x0075, 0x791a, 0x68c0,
+	0x705a, 0x2d00, 0x704e, 0x68c4, 0x2060, 0x71d4, 0xd1b4, 0x00c0,
+	0x2942, 0x2300, 0xa405, 0x0040, 0x2942, 0x70a4, 0xa086, 0x0001,
+	0x00c0, 0x2989, 0x007c, 0x6020, 0xa005, 0x0040, 0x3b79, 0x8001,
+	0x6022, 0x6008, 0xa085, 0x0008, 0x600a, 0x700f, 0x0100, 0x702c,
+	0x6026, 0x007c, 0xa006, 0x1078, 0x4326, 0x6817, 0x0000, 0x681b,
+	0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f,
+	0x0079, 0x3b8a, 0x2946, 0x3b94, 0x3b94, 0x3bb1, 0x3b9c, 0x2946,
+	0x3b92, 0x3b92, 0x1078, 0x28ec, 0x1078, 0x3bbc, 0x1078, 0x3bb5,
+	0x1078, 0x202a, 0x0078, 0x2946, 0x7064, 0x7067, 0x0000, 0x7083,
+	0x0000, 0x0079, 0x3ba3, 0x3bad, 0x3bad, 0x3bab, 0x3bab, 0x3bab,
+	0x3bad, 0x3bab, 0x3bad, 0x0079, 0x2e5c, 0x7067, 0x0000, 0x0078,
+	0x2946, 0x681b, 0x0000, 0x0078, 0x35ae, 0x6800, 0xa005, 0x00c0,
+	0x3bba, 0x6002, 0x6006, 0x007c, 0x6410, 0x84ff, 0x0040, 0x3bce,
+	0x2009, 0x4a02, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x00c0,
+	0x3bce, 0x2021, 0x4a04, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xc0a4,
+	0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x3bd8, 0x8001, 0x601a,
+	0x007c, 0x1078, 0x4131, 0x681b, 0x0018, 0x0078, 0x3c1a, 0x1078,
+	0x4131, 0x681b, 0x0019, 0x0078, 0x3c1a, 0x1078, 0x4131, 0x681b,
+	0x001a, 0x0078, 0x3c1a, 0x1078, 0x4131, 0x681b, 0x0003, 0x0078,
+	0x3c1a, 0x7774, 0x1078, 0x3fe1, 0x7178, 0xa18c, 0x00ff, 0x3210,
+	0xa294, 0x0300, 0x0040, 0x3c00, 0xa1e8, 0x8fc0, 0x0078, 0x3c02,
+	0xa1e8, 0x90d0, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x3c0a,
+	0x0078, 0x2946, 0x6814, 0xc0fc, 0x7274, 0xc2fc, 0xa206, 0x0040,
+	0x3c14, 0x6800, 0x0078, 0x3c03, 0x6800, 0x200a, 0x681b, 0x0005,
+	0x707f, 0x0000, 0x1078, 0x3bbc, 0x6820, 0xd084, 0x00c0, 0x3c22,
+	0x1078, 0x3bb5, 0x1078, 0x3bd2, 0x681f, 0x0000, 0x6823, 0x0020,
+	0x1078, 0x202a, 0x0078, 0x2946, 0xa282, 0x0003, 0x00c0, 0x3e9d,
+	0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xc1bd,
+	0x6922, 0xd1c4, 0x0040, 0x3c86, 0xc1c4, 0x6922, 0xa6b4, 0x00ff,
+	0x0040, 0x3c73, 0xa682, 0x000c, 0x0048, 0x3c4a, 0x0040, 0x3c4a,
+	0x2031, 0x000c, 0x2500, 0xa086, 0x000a, 0x0040, 0x3c51, 0x852b,
+	0x852b, 0x1078, 0x3f73, 0x0040, 0x3c59, 0x1078, 0x3d55, 0x0078,
+	0x3c7c, 0x1078, 0x3f2e, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
+	0x6006, 0x1078, 0x3d8a, 0x0c7f, 0x6920, 0xc1c5, 0x6922, 0x7e58,
+	0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3c70, 0x781b, 0x0061, 0x007c,
+	0x781b, 0x0075, 0x007c, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
+	0x6006, 0x1078, 0x3d8a, 0x0c7f, 0x7e58, 0xd6d4, 0x00c0, 0x3c83,
+	0x781b, 0x0064, 0x007c, 0x781b, 0x0076, 0x007c, 0x0c7e, 0x7058,
+	0x2060, 0x6100, 0xd1e4, 0x0040, 0x3ccf, 0x6208, 0x8217, 0xa294,
+	0x00ff, 0xa282, 0x000c, 0x0048, 0x3c99, 0x0040, 0x3c99, 0x2011,
+	0x000c, 0x2600, 0xa202, 0x00c8, 0x3c9e, 0x2230, 0x6208, 0xa294,
+	0x00ff, 0x2001, 0x4a05, 0x2004, 0xd0e4, 0x00c0, 0x3cb3, 0x78ec,
+	0xd0e4, 0x0040, 0x3cb3, 0xa282, 0x000a, 0x00c8, 0x3cb9, 0x2011,
+	0x000a, 0x0078, 0x3cb9, 0xa282, 0x000c, 0x00c8, 0x3cb9, 0x2011,
+	0x000c, 0x2200, 0xa502, 0x00c8, 0x3cbe, 0x2228, 0x1078, 0x3f32,
+	0x2500, 0xa086, 0x000a, 0x0040, 0x3cc7, 0x852b, 0x852b, 0x1078,
+	0x3f73, 0x0040, 0x3ccf, 0x1078, 0x3d55, 0x0078, 0x3cd3, 0x1078,
+	0x3f2e, 0x1078, 0x3d8a, 0x7858, 0xc095, 0x785a, 0x0c7f, 0x781b,
+	0x0075, 0x007c, 0x0c7e, 0x2960, 0x6000, 0xd0e4, 0x00c0, 0x3cf1,
+	0x6010, 0xa084, 0x000f, 0x00c0, 0x3ceb, 0x6104, 0xa18c, 0xfff5,
+	0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078,
+	0x3d1c, 0x68a0, 0xd0cc, 0x00c0, 0x3ceb, 0x6208, 0xa294, 0x00ff,
+	0x2001, 0x4a05, 0x2004, 0xd0e4, 0x00c0, 0x3d0a, 0x78ec, 0xd0e4,
+	0x0040, 0x3d0a, 0xa282, 0x000a, 0x00c0, 0x3d0a, 0x2011, 0x000a,
+	0x0078, 0x3d10, 0xa282, 0x000c, 0x00c8, 0x3d10, 0x2011, 0x000c,
+	0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x3d1c,
+	0x0040, 0x3d1c, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003,
+	0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5,
+	0x6822, 0x70d4, 0xd0b4, 0x0040, 0x3d38, 0xc0b4, 0x70d6, 0x70b8,
+	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
+	0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106,
+	0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3d46, 0x78ab, 0x0001,
+	0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005,
+	0x6820, 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7158, 0x2160,
+	0x2018, 0xa08c, 0x0020, 0x0040, 0x3d5e, 0xc0ac, 0x2008, 0xa084,
+	0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4,
+	0xa084, 0xfff0, 0xa18c, 0x000f, 0xa105, 0xa39c, 0x0020, 0x0040,
+	0x3d73, 0xa085, 0x4000, 0xc0fc, 0xd0b4, 0x00c0, 0x3d78, 0xc0fd,
+	0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004,
+	0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006,
+	0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6018, 0x789a, 0x78a4,
+	0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
+	0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f, 0x007c, 0xa282, 0x0002,
+	0x00c0, 0x3e9d, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0040,
+	0x3dd9, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8,
+	0x3e9d, 0x1078, 0x3e2a, 0x1078, 0x3d8a, 0xa980, 0x0001, 0x200c,
+	0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040, 0x3dcf, 0x789b,
+	0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
+	0x3dcc, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, 0x007c, 0x7e58,
+	0xd6d4, 0x00c0, 0x3dd6, 0x781b, 0x0064, 0x007c, 0x781b, 0x0076,
+	0x007c, 0xa282, 0x0002, 0x00c8, 0x3de1, 0xa284, 0x0001, 0x0040,
+	0x3dea, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec, 0x00c0, 0x3dea,
+	0x2011, 0x0000, 0x1078, 0x3f0f, 0x1078, 0x3e2a, 0x1078, 0x3d8a,
+	0x7858, 0xc095, 0x785a, 0x781b, 0x0075, 0x007c, 0x0c7e, 0x027e,
+	0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0, 0x3e0b, 0x6014,
+	0xa084, 0x0040, 0x00c0, 0x3e09, 0xc1a4, 0x6106, 0xa006, 0x0078,
+	0x3e27, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
+	0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x3e23,
+	0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a,
+	0x6018, 0x8001, 0x601a, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f,
+	0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x82ff, 0x0040, 0x3e32,
+	0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084,
+	0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x3e3f, 0xc0fd, 0x78a6,
+	0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, 0x0c7f, 0x007c, 0x007e,
+	0x7000, 0xa086, 0x0003, 0x0040, 0x3e50, 0x007f, 0x0078, 0x3e53,
+	0x007f, 0x0078, 0x3e9a, 0xd6ac, 0x0040, 0x3e9a, 0x7888, 0xa084,
+	0x0040, 0x0040, 0x3e9a, 0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8,
+	0x3e62, 0x8000, 0xa005, 0x0040, 0x3e77, 0x831b, 0x00c8, 0x3e6b,
+	0x8001, 0x0040, 0x3e97, 0xd6f4, 0x0040, 0x3e77, 0x78b8, 0x801b,
+	0x00c8, 0x3e73, 0x8000, 0xa084, 0x003f, 0x00c0, 0x3e97, 0xc6f4,
+	0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x3e82,
+	0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x46e5,
+	0x781b, 0x0073, 0xb284, 0x0300, 0x0040, 0x3e92, 0x2001, 0x0000,
+	0x0078, 0x3e94, 0x2001, 0x0001, 0x1078, 0x4585, 0x007c, 0x781b,
+	0x0073, 0x007c, 0x781b, 0x0076, 0x007c, 0x1078, 0x3ec2, 0x781b,
+	0x0075, 0x007c, 0x1078, 0x3eae, 0x781b, 0x0075, 0x007c, 0x6827,
+	0x0002, 0x1078, 0x3eb6, 0x781b, 0x0075, 0x007c, 0x2001, 0x0005,
+	0x0078, 0x3ec4, 0x2001, 0x000c, 0x0078, 0x3ec4, 0x2001, 0x0006,
+	0x0078, 0x3ec4, 0x2001, 0x000d, 0x0078, 0x3ec4, 0x2001, 0x0009,
+	0x0078, 0x3ec4, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d,
+	0x7e5a, 0x70d4, 0xd0b4, 0x0040, 0x3eda, 0xc0b4, 0x70d6, 0x0c7e,
+	0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
+	0x601a, 0x0c7f, 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b,
+	0x873b, 0x8703, 0x017e, 0xb28c, 0x0300, 0x0040, 0x3eeb, 0xa0e0,
+	0x4ec0, 0x0078, 0x3eed, 0xa0e0, 0x4f40, 0x017f, 0xa7b8, 0x0020,
+	0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040, 0x3efd, 0xa184, 0xfff0,
+	0x78a6, 0x6012, 0x6004, 0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a,
+	0x79a4, 0xa184, 0x0040, 0x0040, 0x3f0d, 0xa184, 0xffbf, 0xc0fd,
+	0x78a6, 0x6016, 0x6004, 0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b,
+	0x0010, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
+	0x789b, 0x0060, 0x78ab, 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x3f2d,
+	0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000,
+	0x2029, 0x0032, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003,
+	0x78ab, 0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005,
+	0x70d4, 0xd0b4, 0x0040, 0x3f51, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8,
+	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
+	0x0c7f, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003,
+	0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0, 0x2021, 0x3fc6,
+	0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084,
+	0xfff0, 0xa106, 0x0040, 0x3f71, 0x8420, 0x2300, 0xa210, 0x00f0,
+	0x3f66, 0x157f, 0x007c, 0x157e, 0x2001, 0x4a05, 0x2004, 0xd0e4,
+	0x00c0, 0x3fa4, 0x2021, 0x3fd4, 0x20a9, 0x0009, 0x2011, 0x0028,
+	0xa582, 0x0019, 0x0040, 0x3fba, 0x0048, 0x3fba, 0x8420, 0x95a9,
+	0x2011, 0x0032, 0xa582, 0x0032, 0x0040, 0x3fba, 0x0048, 0x3fba,
+	0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0064, 0x2200, 0xa502,
+	0x0040, 0x3fba, 0x0048, 0x3fba, 0x8420, 0x2300, 0xa210, 0x00f0,
+	0x3f96, 0x157f, 0x0078, 0x3fb8, 0x2021, 0x3fc6, 0x2019, 0x0011,
+	0x20a9, 0x000e, 0x2011, 0x0032, 0x2200, 0xa502, 0x0040, 0x3fba,
+	0x0048, 0x3fba, 0x8420, 0x2300, 0xa210, 0x00f0, 0x3fac, 0x157f,
+	0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8, 0x3fc3, 0x7808,
+	0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x007c, 0x1209, 0x3002,
+	0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806,
+	0x7a06, 0x0c07, 0x0c07, 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05,
+	0x6a06, 0x6c06, 0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046,
+	0x007c, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003,
+	0x8003, 0x8003, 0xa105, 0xd7fc, 0x0040, 0x3ff2, 0xa0e0, 0x6fc0,
+	0x0078, 0x3ff4, 0xa0e0, 0x4fc0, 0x007c, 0x0e7e, 0x0f7e, 0xd084,
+	0x0040, 0x4002, 0x2079, 0x0100, 0x2009, 0x4a80, 0x2071, 0x4a80,
+	0x0078, 0x4014, 0x2009, 0x4a40, 0x007e, 0x2001, 0x4a04, 0x2004,
+	0xd0ec, 0x007f, 0x0040, 0x4010, 0x2079, 0x0100, 0x0078, 0x4014,
+	0x2079, 0x0200, 0x2071, 0x4a40, 0x2091, 0x8000, 0x2104, 0xa084,
+	0x000f, 0x0079, 0x401b, 0x405d, 0x4025, 0x4025, 0x4025, 0x4025,
+	0x4025, 0x4023, 0x4023, 0x1078, 0x28ec, 0x784b, 0x0004, 0x7848,
+	0xa084, 0x0004, 0x00c0, 0x4027, 0x784b, 0x0008, 0x7848, 0xa084,
+	0x0008, 0x00c0, 0x402e, 0x68b4, 0xc0f5, 0x68b6, 0x7858, 0xc0f5,
+	0x785a, 0x7830, 0xd0bc, 0x00c0, 0x405d, 0x007e, 0x2001, 0x4a04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x4049, 0xb284, 0x0300, 0x0078,
+	0x404b, 0xb284, 0x0400, 0x0040, 0x4051, 0x0018, 0x405d, 0x0078,
+	0x4053, 0x0028, 0x405d, 0x681c, 0xd0ac, 0x00c0, 0x405b, 0x1078,
+	0x40d5, 0x0078, 0x405d, 0x781b, 0x00f0, 0x2091, 0x8001, 0x0f7f,
+	0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4a01, 0x2004, 0xd0ac, 0x00c0,
+	0x40c7, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0xb28c, 0x0300, 0x0040, 0x4078, 0xa0e0, 0x4ec0, 0x0078, 0x407a,
+	0xa0e0, 0x4f40, 0x6004, 0xa084, 0x000a, 0x00c0, 0x40c7, 0x6108,
+	0xa194, 0xff00, 0x0040, 0x40c7, 0xa18c, 0x00ff, 0x2001, 0x000a,
+	0xa106, 0x0040, 0x40a6, 0x2001, 0x000c, 0xa106, 0x0040, 0x40aa,
+	0x2001, 0x0012, 0xa106, 0x0040, 0x40ae, 0x2001, 0x0014, 0xa106,
+	0x0040, 0x40b2, 0x2001, 0x0019, 0xa106, 0x0040, 0x40b6, 0x2001,
+	0x0032, 0xa106, 0x0040, 0x40ba, 0x0078, 0x40be, 0x2009, 0x000c,
+	0x0078, 0x40c0, 0x2009, 0x0012, 0x0078, 0x40c0, 0x2009, 0x0014,
+	0x0078, 0x40c0, 0x2009, 0x0019, 0x0078, 0x40c0, 0x2009, 0x0020,
+	0x0078, 0x40c0, 0x2009, 0x003f, 0x0078, 0x40c0, 0x2011, 0x0000,
+	0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f,
+	0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0075, 0x007c, 0x781b,
+	0x0064, 0x007c, 0x781b, 0x0061, 0x007c, 0x2009, 0x4a19, 0x210c,
+	0xa186, 0x0000, 0x0040, 0x40e7, 0xa186, 0x0001, 0x0040, 0x40ea,
+	0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c, 0x781b,
+	0x00e7, 0x007c, 0x701f, 0x000a, 0x007c, 0x2009, 0x4a19, 0x210c,
+	0xa186, 0x0000, 0x0040, 0x4102, 0xa186, 0x0001, 0x0040, 0x40ff,
+	0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c, 0x701f,
+	0x000a, 0x007c, 0x781b, 0x00e6, 0x007c, 0x781b, 0x00f0, 0x007c,
+	0x781b, 0x00ef, 0x007c, 0x781b, 0x00c0, 0x007c, 0x781b, 0x00bf,
+	0x007c, 0x6818, 0xd0fc, 0x0040, 0x4117, 0x681b, 0x001d, 0x7067,
+	0x0001, 0x781b, 0x0047, 0x007c, 0x7830, 0xa084, 0x00c0, 0x00c0,
+	0x4130, 0x7808, 0xc08c, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
+	0x78ec, 0xa084, 0x0021, 0x0040, 0x4130, 0x7808, 0xc08d, 0x780a,
+	0x007c, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040,
+	0x00c0, 0x4135, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x0040, 0x4144,
+	0xb284, 0x0300, 0x0078, 0x4146, 0xb284, 0x0400, 0x0040, 0x414c,
+	0x0098, 0x4150, 0x0078, 0x414e, 0x00a8, 0x4150, 0x78ac, 0x007c,
+	0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
+	0x78ec, 0xa084, 0x0021, 0x0040, 0x4173, 0x007e, 0x2001, 0x4a04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x4169, 0xb284, 0x0300, 0x0078,
+	0x416b, 0xb284, 0x0400, 0x0040, 0x4171, 0x0098, 0x416d, 0x0078,
+	0x4173, 0x00a8, 0x4171, 0x78ac, 0x007e, 0x7808, 0xa085, 0x0002,
+	0x780a, 0x007f, 0x007c, 0xa784, 0x0001, 0x00c0, 0x360e, 0xa784,
+	0x0070, 0x0040, 0x418b, 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x2881,
+	0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040, 0x4198, 0x784b,
+	0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2946, 0x0078, 0x40c9,
+	0xa784, 0x0004, 0x0040, 0x41c7, 0x78b8, 0xa084, 0x4001, 0x0040,
+	0x41c7, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2946,
+	0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0, 0x41c7, 0x78c0,
+	0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f0, 0x007c, 0x784b,
+	0x0008, 0x6818, 0xd0fc, 0x0040, 0x41c4, 0x681b, 0x0015, 0xd6f4,
+	0x0040, 0x41c4, 0x681b, 0x0007, 0x1078, 0x40d5, 0x007c, 0x681b,
+	0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833,
+	0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2f84,
+	0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x41e4,
+	0xb284, 0x0300, 0x0078, 0x41e6, 0xb284, 0x0400, 0x0040, 0x41ec,
+	0x0018, 0x2942, 0x0078, 0x41ee, 0x0028, 0x2942, 0x0078, 0x3ea2,
+	0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc,
+	0x0040, 0x41fe, 0xa080, 0x4f40, 0x0078, 0x4200, 0xa080, 0x4ec0,
+	0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062,
+	0x0009, 0x0014, 0x0014, 0x9848, 0x0014, 0x0014, 0x9906, 0x98f4,
+	0x0014, 0x0014, 0x0080, 0x00f1, 0x0100, 0x0402, 0x2008, 0xf880,
+	0x0018, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0x2500, 0x0013,
+	0x2500, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
+	0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0xa200,
+	0x3806, 0x8839, 0x20c4, 0x0864, 0xa850, 0x3008, 0x28c1, 0x9d0d,
+	0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856,
+	0x883a, 0xa808, 0x28e2, 0x9cc2, 0xa8f3, 0x0864, 0xa83e, 0x300c,
+	0xa801, 0x3008, 0x28e1, 0x9cc2, 0x2021, 0xa81b, 0xa205, 0x870c,
+	0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x63a4, 0x6c80, 0x0212, 0xa205,
+	0x883d, 0x9d25, 0x882b, 0x1814, 0x883b, 0x9d2b, 0x883b, 0x7027,
+	0x85f2, 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa812, 0x883e,
+	0xa810, 0x280c, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x9d25,
+	0x1814, 0x9d2b, 0x883b, 0x7023, 0x8576, 0x8677, 0xa802, 0x7861,
+	0x883e, 0x206b, 0x28c1, 0x9d0d, 0x2044, 0x2103, 0x20a2, 0x2081,
+	0xa8c9, 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203, 0x8000, 0x85a4,
+	0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f,
+	0x7161, 0x0014, 0x0704, 0x3008, 0x9cc2, 0x0014, 0xa202, 0x8000,
+	0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, 0x856e, 0x883f, 0x08e6,
+	0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2,
+	0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014,
+	0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0x3008, 0x8000, 0x284a,
+	0x1011, 0xa8fc, 0x3008, 0x9d25, 0x8000, 0xa000, 0x2802, 0x1011,
+	0xa8fd, 0x9d2b, 0xa887, 0x3008, 0x9d25, 0x283b, 0x1011, 0xa8fd,
+	0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014,
+	0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0,
+	0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d17,
+	0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016,
+	0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021,
+	0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d4, 0x8822,
+	0x0016, 0x7944, 0x8421, 0xa020, 0xa532, 0x84a1, 0x0016, 0x7944,
+	0x8421, 0xa0df, 0x9532, 0x84a1, 0x0016, 0x0000, 0x127e, 0x70d4,
+	0xa084, 0x4600, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
+	0x00c0, 0x4342, 0x720c, 0x82ff, 0x0040, 0x433d, 0x8aff, 0x00c0,
+	0x4342, 0x7200, 0xd284, 0x00c0, 0x4342, 0x7003, 0x0008, 0x127f,
+	0x2000, 0x007c, 0x7000, 0xa084, 0x0003, 0x7002, 0xc69c, 0xd084,
+	0x0040, 0x4374, 0x2001, 0x4a05, 0x2004, 0xd0ec, 0x00c0, 0x43a5,
+	0xd0e4, 0x00c0, 0x435a, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003,
+	0x0040, 0x43a5, 0x0e7e, 0x2071, 0x0010, 0x2009, 0x0007, 0x7008,
+	0xa084, 0x3000, 0x00c0, 0x435d, 0x8109, 0x00c0, 0x435f, 0x0e7f,
+	0x2009, 0x0007, 0x7008, 0xa084, 0x3000, 0x00c0, 0x435a, 0x8109,
+	0x00c0, 0x436a, 0x0078, 0x43a5, 0x7108, 0xd1fc, 0x0040, 0x437f,
+	0x1078, 0x44ba, 0x8aff, 0x0040, 0x432c, 0x0078, 0x4374, 0x700c,
+	0xa08c, 0x03ff, 0x0040, 0x43aa, 0x7004, 0xd084, 0x0040, 0x439c,
+	0x7014, 0xa005, 0x00c0, 0x4398, 0x7010, 0x7310, 0xa306, 0x00c0,
+	0x438c, 0x2300, 0xa005, 0x0040, 0x439c, 0xa102, 0x00c8, 0x4374,
+	0x7007, 0x0010, 0x0078, 0x43a5, 0x8aff, 0x0040, 0x43aa, 0x1078,
+	0x46a3, 0x00c0, 0x439f, 0x0040, 0x4374, 0x1078, 0x4443, 0x127f,
+	0x2000, 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8, 0x43b9,
+	0x1078, 0x44ba, 0x0078, 0x43aa, 0x7003, 0x0008, 0x127f, 0x2000,
+	0x007c, 0xa205, 0x00c0, 0x43a5, 0x7003, 0x0008, 0x127f, 0x2000,
+	0x007c, 0x6428, 0x84ff, 0x0040, 0x43ed, 0x2c70, 0x7004, 0xa0bc,
+	0x000f, 0xa7b8, 0x43fd, 0x273c, 0x87fb, 0x00c0, 0x43db, 0x0048,
+	0x43d3, 0x1078, 0x28ec, 0x609c, 0xa075, 0x0040, 0x43ed, 0x0078,
+	0x43c6, 0x2039, 0x43f2, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c,
+	0xa529, 0x8421, 0x0040, 0x43ed, 0x8738, 0x2704, 0xa005, 0x00c0,
+	0x43dc, 0x709c, 0xa075, 0x00c0, 0x43c6, 0x007c, 0x0000, 0x0005,
+	0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
+	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x43f2, 0x43ef,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x43f2, 0x0000, 0x43fa, 0x43f7,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x43fa, 0x0000, 0x43f5, 0x43f5,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x43f5, 0x0000, 0x43fb, 0x43fb,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x43fb, 0x2079, 0x4a00, 0x2071,
+	0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x7810,
+	0xd0ec, 0x0040, 0x4431, 0x2009, 0x0001, 0x2071, 0x0020, 0x0078,
+	0x4435, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007,
+	0x0002, 0x7003, 0x0000, 0x8109, 0x0040, 0x4442, 0x2071, 0x0020,
+	0x0078, 0x4435, 0x007c, 0x7004, 0x8004, 0x00c8, 0x44a6, 0x7007,
+	0x0012, 0x2019, 0x0000, 0x7108, 0x7008, 0xa106, 0x00c0, 0x444b,
+	0xa184, 0x01e0, 0x0040, 0x4456, 0x1078, 0x28ec, 0x7810, 0xd0ec,
+	0x0040, 0x4470, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003, 0x00c0,
+	0x4474, 0xa184, 0x4000, 0x0040, 0x4478, 0xa382, 0x0003, 0x00c8,
+	0x4478, 0xa184, 0x0004, 0x0040, 0x444b, 0x8318, 0x0078, 0x444b,
+	0x7814, 0xd0ec, 0x00c0, 0x4478, 0xa184, 0x4000, 0x00c0, 0x444b,
+	0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x4486, 0xa386, 0x0008,
+	0x0040, 0x4491, 0xa386, 0x200c, 0x00c0, 0x444b, 0x7200, 0x8204,
+	0x0048, 0x4491, 0x730c, 0xa384, 0x03ff, 0x0040, 0x4491, 0x1078,
+	0x28ec, 0x7007, 0x0012, 0x7000, 0xd084, 0x00c0, 0x44a6, 0x7008,
+	0xa084, 0x01e0, 0x00c0, 0x44a6, 0x7310, 0x7014, 0xa305, 0x0040,
+	0x44a6, 0x710c, 0xa184, 0x03ff, 0x00c0, 0x4443, 0x7007, 0x0012,
+	0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x44aa, 0x7007, 0x0012,
+	0x7108, 0x8103, 0x0048, 0x44ae, 0x7003, 0x0008, 0x007c, 0x7108,
+	0x0078, 0x44ba, 0xa184, 0x01e0, 0x00c0, 0x44ee, 0x7108, 0xa184,
+	0x01e0, 0x00c0, 0x44ee, 0xa184, 0x0007, 0x0079, 0x44c7, 0x44d1,
+	0x44e1, 0x44cf, 0x44e1, 0x44cf, 0x4533, 0x44cf, 0x4531, 0x1078,
+	0x28ec, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x00c0,
+	0x44dc, 0x2049, 0x0000, 0x007c, 0x1078, 0x46a3, 0x00c0, 0x44dc,
+	0x007c, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x0040,
+	0x44ed, 0x1078, 0x46a3, 0x00c0, 0x44e9, 0x007c, 0x7007, 0x0012,
+	0x7108, 0x00e0, 0x44f1, 0x2091, 0x6000, 0x00e0, 0x44f5, 0x2091,
+	0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0,
+	0x44fd, 0x7007, 0x0012, 0x7108, 0xd1fc, 0x00c0, 0x4501, 0x7003,
+	0x0000, 0x7000, 0xa005, 0x00c0, 0x4515, 0x7004, 0xa005, 0x00c0,
+	0x4515, 0x700c, 0xa005, 0x0040, 0x4517, 0x0078, 0x44f9, 0x2049,
+	0x0000, 0xb284, 0x0100, 0x0040, 0x4521, 0x2001, 0x0000, 0x0078,
+	0x4523, 0x2001, 0x0001, 0x1078, 0x3ff5, 0x6818, 0xa084, 0x8000,
+	0x0040, 0x452c, 0x681b, 0x0002, 0x007c, 0x1078, 0x28ec, 0x1078,
+	0x28ec, 0x1078, 0x4570, 0x7210, 0x7114, 0x700c, 0xa09c, 0x03ff,
+	0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x4570, 0x2704,
+	0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b,
+	0x2400, 0xa305, 0x0040, 0x4556, 0x00c8, 0x4556, 0x8412, 0x8210,
+	0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x453d, 0x2b60, 0x8a07,
+	0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4562, 0xa7ba, 0x43f7,
+	0x0078, 0x4564, 0xa7ba, 0x43ef, 0x007f, 0xa73d, 0x2c00, 0x6886,
+	0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078, 0x4443, 0x007c,
+	0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x4584, 0x6000, 0xa064,
+	0x00c0, 0x457b, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x440d,
+	0x203c, 0x87fb, 0x1040, 0x28ec, 0x007c, 0x127e, 0x0d7e, 0x70d4,
+	0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060, 0x6888,
+	0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e,
+	0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x45a2, 0xa0b8, 0x43f7,
+	0x0078, 0x45a4, 0xa0b8, 0x43ef, 0xb284, 0x0100, 0x0040, 0x45ab,
+	0x7e20, 0x0078, 0x45ac, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4,
+	0x0040, 0x45b3, 0xc685, 0x2400, 0xa305, 0x0040, 0x45dd, 0x2c58,
+	0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301,
+	0x701e, 0xa184, 0x0008, 0x0040, 0x45cd, 0x6010, 0xa081, 0x0000,
+	0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202,
+	0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001,
+	0x2b60, 0x1078, 0x46c6, 0x0078, 0x45df, 0x1078, 0x46a3, 0x00c0,
+	0x45dd, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084,
+	0x4600, 0x8004, 0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094,
+	0x00c0, 0x45ee, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e,
+	0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x7e20,
+	0xb284, 0x0100, 0x00c0, 0x4605, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+	0xd0ac, 0x00c0, 0x4610, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
+	0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x43fd,
+	0x273c, 0x87fb, 0x00c0, 0x4626, 0x0048, 0x4620, 0x1078, 0x28ec,
+	0x689c, 0xa065, 0x0040, 0x462a, 0x0078, 0x4613, 0x1078, 0x46a3,
+	0x00c0, 0x4626, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
+	0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x7e20, 0xb284,
+	0x0100, 0x00c0, 0x463c, 0x7e24, 0x0d7f, 0x037f, 0x047f, 0xa6b5,
+	0x000c, 0x681c, 0xd0b4, 0x0040, 0x464a, 0xc685, 0x7003, 0x0000,
+	0x7007, 0x0004, 0x2049, 0x462d, 0x6828, 0xa055, 0x0040, 0x46a0,
+	0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x43fd, 0x273c,
+	0x87fb, 0x00c0, 0x4666, 0x0048, 0x465f, 0x1078, 0x28ec, 0x709c,
+	0xa075, 0x2060, 0x0040, 0x46a0, 0x0078, 0x4652, 0x2704, 0xae68,
+	0x6808, 0xa422, 0x680c, 0xa31b, 0x0048, 0x467f, 0x8a51, 0x00c0,
+	0x4673, 0x1078, 0x28ec, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4667,
+	0x709c, 0xa075, 0x2060, 0x0040, 0x46a0, 0x0078, 0x4652, 0x8422,
+	0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c,
+	0x2300, 0xa11b, 0x00c8, 0x468e, 0x1078, 0x28ec, 0xb284, 0x0100,
+	0x0040, 0x469c, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x00c0, 0x469c,
+	0x2071, 0x0050, 0x0078, 0x469e, 0x2071, 0x0020, 0x0078, 0x45b3,
+	0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x0003, 0xa086, 0x0003,
+	0x00c0, 0x46ab, 0x007c, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804,
+	0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xa084, 0x0008,
+	0x0040, 0x46be, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004,
+	0xa084, 0x0010, 0xc085, 0x7006, 0x2079, 0x4a00, 0x8a51, 0x0040,
+	0x46e1, 0x8738, 0x2704, 0xa005, 0x00c0, 0x46dc, 0x609c, 0xa005,
+	0x0040, 0x46e2, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x43fd,
+	0x203c, 0x87fb, 0x1040, 0x28ec, 0x7008, 0xa084, 0x0003, 0xa086,
+	0x0003, 0x007c, 0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e,
+	0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108,
+	0xa184, 0x0003, 0x00c0, 0x46fa, 0x6828, 0xa005, 0x0040, 0x470a,
+	0x0078, 0x4342, 0x7108, 0xd1fc, 0x0040, 0x4702, 0x1078, 0x44ba,
+	0x0078, 0x46ef, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x4704,
+	0x1078, 0x44ba, 0x7008, 0xa086, 0x0008, 0x00c0, 0x46ef, 0x7000,
+	0xa005, 0x00c0, 0x46ef, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f,
+	0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e,
+	0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x471a,
+	0xad80, 0x0011, 0x20a0, 0xb284, 0x0100, 0x0040, 0x473d, 0x2001,
+	0x4a04, 0x2004, 0xd0ec, 0x0040, 0x4739, 0x2099, 0x0031, 0x0078,
+	0x473f, 0x2099, 0x0032, 0x0078, 0x473f, 0x2099, 0x0031, 0x700c,
+	0xa084, 0x03ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003,
+	0x0001, 0x0040, 0x474e, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084,
+	0x03ff, 0x0040, 0x475a, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+	0x00c0, 0x4755, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f,
+	0x137f, 0x147f, 0x127f, 0x2000, 0x007c, 0x2091, 0x8000, 0x2091,
+	0x6000, 0x78ac, 0xa005, 0x00c0, 0x477c, 0x7974, 0x70d0, 0xa106,
+	0x00c0, 0x477c, 0x781c, 0xa005, 0x0040, 0x477c, 0x781f, 0x0000,
+	0x0068, 0x477c, 0x2091, 0x4080, 0x7830, 0x8001, 0x7832, 0x00c0,
+	0x4804, 0x7834, 0x7832, 0x7810, 0xd0ec, 0x00c0, 0x47fd, 0x2061,
+	0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x68d0, 0xa005, 0x0040, 0x4796,
+	0x8001, 0x68d2, 0x00c0, 0x4796, 0x1078, 0x4998, 0x6800, 0xa084,
+	0x000f, 0x0040, 0x47ab, 0xa086, 0x0001, 0x0040, 0x47ab, 0x6844,
+	0xa00d, 0x0040, 0x47ab, 0x2104, 0xa005, 0x0040, 0x47ab, 0x8001,
+	0x200a, 0x0040, 0x4909, 0x6814, 0xa005, 0x0040, 0x47d0, 0x8001,
+	0x6816, 0x00c0, 0x47d0, 0x68a7, 0x0001, 0x0f7e, 0xd7fc, 0x00c0,
+	0x47c5, 0x7810, 0xd0ec, 0x0040, 0x47c1, 0x2079, 0x0100, 0x0078,
+	0x47c7, 0x2079, 0x0200, 0x0078, 0x47c7, 0x2079, 0x0100, 0x1078,
+	0x4131, 0x0f7f, 0x6864, 0xa005, 0x0040, 0x47d0, 0x1078, 0x25de,
+	0x6880, 0xa005, 0x0040, 0x47dd, 0x8001, 0x6882, 0x00c0, 0x47dd,
+	0x6867, 0x0000, 0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc, 0x0040,
+	0x47fa, 0xc0fc, 0x68d6, 0x20a9, 0x0200, 0x603c, 0xa005, 0x0040,
+	0x47f6, 0x8001, 0x603e, 0x68d4, 0xc0fd, 0x68d6, 0x00c0, 0x47f6,
+	0x6010, 0xa005, 0x0040, 0x47f6, 0x1078, 0x25de, 0xace0, 0x0010,
+	0x00f0, 0x47e5, 0xd7fc, 0x0040, 0x4804, 0x2061, 0x4fc0, 0x2069,
+	0x4a40, 0xc7fc, 0x0078, 0x478c, 0x1078, 0x4840, 0x7838, 0x8001,
+	0x783a, 0x00c0, 0x4826, 0x783c, 0x783a, 0x2061, 0x4fc0, 0x2069,
+	0x4a40, 0xc7fc, 0x680c, 0xa005, 0x0040, 0x4818, 0x1078, 0x487f,
+	0xd7fc, 0x00c0, 0x4826, 0x7810, 0xd0ec, 0x00c0, 0x4826, 0x2061,
+	0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x0078, 0x4812, 0x7814, 0xd0e4,
+	0x00c0, 0x482a, 0x7810, 0xd0cc, 0x0040, 0x483d, 0xd0ac, 0x00c0,
+	0x4836, 0xd0a4, 0x0040, 0x483d, 0xc0ad, 0x7812, 0x2091, 0x8001,
+	0x0068, 0x483c, 0x1078, 0x2368, 0x007c, 0x2091, 0x8001, 0x007c,
+	0x7840, 0x8001, 0x7842, 0x00c0, 0x487e, 0x7844, 0x7842, 0x2091,
+	0x8000, 0x2061, 0x4fc0, 0x2069, 0x4a40, 0xc7fc, 0x6810, 0xa005,
+	0x00c0, 0x4854, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0040,
+	0x485d, 0xa080, 0x90d0, 0x0078, 0x485f, 0xa080, 0x8fc0, 0x2040,
+	0x2004, 0xa065, 0x0040, 0x4870, 0x6024, 0xa005, 0x0040, 0x486c,
+	0x8001, 0x6026, 0x0040, 0x48ad, 0x6000, 0x2c40, 0x0078, 0x4861,
+	0xd7fc, 0x00c0, 0x487e, 0x7810, 0xd0ec, 0x00c0, 0x487e, 0x2061,
+	0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x0078, 0x484e, 0x007c, 0x2009,
+	0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0040, 0x4899, 0x6024,
+	0xa005, 0x0040, 0x488f, 0x8001, 0x6026, 0x0078, 0x4897, 0x6008,
+	0xc09c, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0078, 0x4899, 0xa18d,
+	0x0100, 0xace0, 0x0010, 0x00f0, 0x4883, 0xa184, 0x0001, 0x0040,
+	0x48a8, 0xa18c, 0xfffe, 0x690e, 0x1078, 0x25de, 0x0078, 0x48a9,
+	0x690e, 0x007c, 0x00c0, 0x48a9, 0x786c, 0x6800, 0xa005, 0x0040,
+	0x48b5, 0x684c, 0xac06, 0x0040, 0x4909, 0x6864, 0xa005, 0x0040,
+	0x48bd, 0x6027, 0x0001, 0x0078, 0x4906, 0x2c00, 0x687e, 0x601b,
+	0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
+	0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f76, 0x1078,
+	0x1e02, 0x6818, 0xa005, 0x0040, 0x48d7, 0x8001, 0x681a, 0x6808,
+	0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0,
+	0x48e3, 0x1078, 0x28ec, 0x6812, 0x00c0, 0x48e9, 0x7910, 0xc1a5,
+	0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x202a,
+	0xd7fc, 0x00c0, 0x48f7, 0x2069, 0x4a40, 0x0078, 0x48f9, 0x2069,
+	0x4a80, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x00c0, 0x4903,
+	0x697a, 0x2001, 0x0004, 0x2708, 0x1078, 0x25d1, 0x2091, 0x8001,
+	0x007c, 0x0d7e, 0x694c, 0x2160, 0xd7fc, 0x00c0, 0x491b, 0x7810,
+	0xd0ec, 0x0040, 0x4917, 0x2069, 0x0100, 0x0078, 0x491d, 0x2069,
+	0x0200, 0x0078, 0x491d, 0x2069, 0x0100, 0x1078, 0x2881, 0x601b,
+	0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
+	0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830,
+	0xd0b4, 0x0040, 0x494b, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
+	0xd094, 0x0040, 0x493d, 0x00f0, 0x4937, 0x684b, 0x0009, 0x20a9,
+	0x0014, 0x6848, 0xd084, 0x0040, 0x4947, 0x00f0, 0x4941, 0x20a9,
+	0x00fa, 0x00f0, 0x4949, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b,
+	0x0047, 0x0d7f, 0x6867, 0x0007, 0x2091, 0x8001, 0x007c, 0x2079,
+	0x4a00, 0x1078, 0x498b, 0x1078, 0x4971, 0x1078, 0x497e, 0x2009,
+	0x0002, 0x2069, 0x4a80, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817,
+	0x0000, 0x8109, 0x0040, 0x4970, 0x2069, 0x4a40, 0x0078, 0x4963,
+	0x007c, 0x7810, 0xd0ec, 0x0040, 0x4979, 0x2019, 0x00cc, 0x0078,
+	0x497b, 0x2019, 0x007b, 0x7b3a, 0x7b3e, 0x007c, 0x7814, 0xd0e4,
+	0x00c0, 0x4986, 0x2019, 0x0040, 0x0078, 0x4988, 0x2019, 0x0026,
+	0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4993, 0x2019,
+	0x3f94, 0x0078, 0x4995, 0x2019, 0x2624, 0x7b32, 0x7b36, 0x007c,
+	0x6950, 0xa185, 0x0000, 0x0040, 0x49ad, 0x0c7e, 0x6ac0, 0x2264,
+	0x602b, 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5, 0x600a, 0x8210,
+	0x8109, 0x00c0, 0x499f, 0x6952, 0x0c7f, 0x007c, 0x70ec, 0xd0dc,
+	0x00c0, 0x49b7, 0xd0d4, 0x0040, 0x49d6, 0x0078, 0x49d9, 0x7810,
+	0xd0ec, 0x0040, 0x49c2, 0xc0f5, 0x7812, 0xd0ec, 0x0040, 0x49dd,
+	0x0078, 0x49d9, 0xae8e, 0x0100, 0x0040, 0x49ce, 0x7814, 0xc0f5,
+	0x7816, 0xd0d4, 0x00c0, 0x49dd, 0x0078, 0x49d9, 0x7814, 0xc0fd,
+	0x7816, 0xd0d4, 0x00c0, 0x49dd, 0x0078, 0x49d9, 0xd0e4, 0x0040,
+	0x49df, 0x7804, 0xd08c, 0x0040, 0x49df, 0x681f, 0x000c, 0x70a0,
+	0x70a2, 0x007c, 0x699a
+};
+unsigned short   fw1280ei_length01 = 0x39e3;
+
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/qla1280.c linux/drivers/scsi/qla1280.c
--- v2.3.42/linux/drivers/scsi/qla1280.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/qla1280.c	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,6850 @@
+/********************************************************************************
+ *                  QLOGIC LINUX SOFTWARE
+ *
+ * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.X).
+ *
+ * COPYRIGHT (C) 1999-2000 QLOGIC CORPORATION    
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the Qlogic's Linux Software License. See below.
+ *
+ * This program is WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistribution's or source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ ********************************************************************************/
+ 
+/*****************************************************************************************
+			QLOGIC CORPORATION SOFTWARE
+           "GNU" GENERAL PUBLIC LICENSE
+    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
+                 AND MODIFICATION
+
+This GNU General Public License ("License") applies solely to QLogic Linux 
+Software ("Software") and may be distributed under the terms of this License.  
+ 
+1. You may copy and distribute verbatim copies of the Software's source code as 
+you receive it, in any medium, provided that you conspicuously and appropriately 
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Software a copy of this License along
+with the Software. 
+
+You may charge a fee for the physical act of transferring a copy, and you may at your
+option offer warranty protection in exchange for a fee.
+ 
+2. You may modify your copy or copies of the Software or any portion of it, thus forming
+a work based on the Software, and copy and distribute such modifications or work under
+the terms of Section 1 above, provided that you also meet all of these conditions:
+ 
+* a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change. 
+
+* b) You must cause any work that you distribute or publish that in whole or in part
+contains or is derived from the Software or any part thereof, to be licensed as a
+whole at no charge to all third parties under the terms of this License. 
+
+* c) If the modified Software normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary way,
+to print or display an announcement including an appropriate copyright notice and a 
+notice that there is no warranty (or else, saying that you provide a warranty) and that
+users may redistribute the Software under these conditions, and telling the user how to
+view a copy of this License. (Exception:if the Software itself is interactive but does 
+not normally print such an announcement, your work based on the Software is not required
+to print an announcement.) 
+
+These requirements apply to the modified work as a whole. If identifiable sections of
+that work are not derived from the Software, and can be reasonably considered independent
+and separate works in themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you distribute the same
+sections as part of a whole which is a work based on the Software, the distribution of the
+whole must be on the terms of this License, whose permissions for other licensees extend
+to the entire whole, and thus to each and every part regardless of who wrote it. 
+
+3. You may copy and distribute the Software (or a work based on it, under Section 2) in 
+object code or executable form under the terms of Sections 1 and 2 above provided that
+you also do one of the following: 
+
+* a) Accompany it with the complete corresponding machine-readable source code, which must
+be distributed under the terms of Sections 1 and 2 above on a medium customarily used for
+software interchange; or, 
+
+* b) Accompany it with a written offer, valid for at least three years, to give any third
+party, for a charge no more than your cost of physically performing source distribution,
+a complete machine-readable copy of the corresponding source code, to be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
+or,
+
+* c) Accompany it with the information you received as to the offer to distribute 
+corresponding source code. (This alternative is allowed only for noncommercial distribution
+and only if you received the Software in object code or executable form with such an offer,
+in accord with Subsection b above.) 
+
+The source code for a work means the preferred form of the work for making modifications
+to it. For an executable work, complete source code means all the source code for all 
+modules it contains, plus any associated interface definition files, plus the scripts used
+to control compilation and installation of the executable.     
+
+If distribution of executable or object code is made by offering access to copy from a 
+designated place, then offering equivalent access to copy the source code from the same
+place counts as distribution of the source code, even though third parties are not 
+compelled to copy the source along with the object code. 
+
+4. You may not copy, modify, sublicense, or distribute the Software except as expressly 
+provided under this License. Any attempt otherwise to copy, modify, sublicense or 
+distribute the Software is void, and will automatically terminate your rights under this
+License. However, parties who have received copies, or rights, from you under this License
+will not have their licenses terminated so long as such parties remain in full compliance. 
+
+5. This license grants you world wide, royalty free non-exclusive rights to modify or 
+distribute the Software or its derivative works. These actions are prohibited by law 
+if you do not accept this License. Therefore, by modifying or distributing the Software
+(or any work based on the Software), you indicate your acceptance of this License to do
+so, and all its terms and conditions for copying, distributing or modifying the Software
+or works based on it.
+ 
+6. Each time you redistribute the Software (or any work based on the Software), the 
+recipient automatically receives a license from the original licensor to copy, distribute
+or modify the Software subject to these terms and conditions. You may not impose any 
+further restrictions on the recipients' exercise of the rights granted herein. You are
+not responsible for enforcing compliance by third parties to this License.
+ 
+7. If, as a consequence of a court judgment or allegation of patent infringement or for
+any other reason (not limited to patent issues), conditions are imposed on you 
+(whether by court order, agreement or otherwise) that contradict the conditions of this
+License, they do not excuse you from the conditions of this License. If you cannot 
+distribute so as to satisfy simultaneously your obligations under this License 
+and any other pertinent obligations, then as a consequence you may not distribute the
+Software at all.    
+
+If any portion of this section is held invalid or unenforceable under any particular 
+circumstance, the balance of the section is intended to apply and the section as a whole
+is intended to apply in other circumstances. 
+NO WARRANTY
+
+11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO 
+WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
+OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, 
+EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. 
+SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+ 
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
+REDISTRIBUTE THE SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
+DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
+DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING 
+BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO 
+OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS 
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+END OF TERMS AND CONDITIONS 
+
+*******************************************************************************************/ 
+
+/****************************************************************************
+    Revision History:
+    Rev. 3.00       Jan 17, 1999    DG  Qlogic
+	   - Added 64-bit support.
+    Rev. 2.07       Nov 9, 1999     DG  Qlogic
+	   - Added new routine to set target parameters for ISP12160. 
+    Rev. 2.06       Sept 10, 1999     DG  Qlogic
+       - Added support for ISP12160 Ultra 3 chip.
+    Rev. 2.03       August 3, 1999    Fred Lewis, Intel DuPont
+	- Modified code to remove errors generated when compiling with
+	  Cygnus IA64 Compiler.
+        - Changed conversion of pointers to unsigned longs instead of integers.
+        - Changed type of I/O port variables from uint32_t to unsigned long.
+        - Modified OFFSET macro to work with 64-bit as well as 32-bit.
+        - Changed sprintf and printk format specifiers for pointers to %p.
+        - Changed some int to long type casts where needed in sprintf & printk.
+        - Added l modifiers to sprintf and printk format specifiers for longs.
+        - Removed unused local variables.
+    Rev. 1.20       June 8, 1999      DG,  Qlogic
+         Changes to support RedHat release 6.0 (kernel 2.2.5).  
+       - Added SCSI exclusive access lock (io_request_lock) when accessing 
+         the adapter.
+       - Added changes for the new LINUX interface template. Some new error
+         handling routines have been added to the template, but for now we
+         will use the old ones.
+    -   Initial Beta Release.  
+*****************************************************************************/
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#define QLA1280_VERSION      " 3.00-Beta"
+
+#include <stdarg.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/segment.h>
+#include <asm/byteorder.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/blk.h>
+#include <linux/tqueue.h>
+/* MRS #include <linux/tasks.h> */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+# include <linux/bios32.h>
+#endif
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+#define UNIQUE_FW_NAME
+#include "qla1280.h"
+#include "ql12160_fw.h"                     /* ISP RISC code */
+#include "ql1280_fw.h"
+
+#include <linux/stat.h>
+#include <linux/malloc.h>        /* for kmalloc() */
+
+
+#ifndef KERNEL_VERSION
+#  define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+
+/*
+ * Compile time Options: 
+ *            0 - Disable and 1 - Enable 
+ */
+#define  QLA1280_64BIT_SUPPORT         1   /* 64-bit Support */
+#define  QL1280_TARGET_MODE_SUPPORT    0   /* Target mode support */
+#define  WATCHDOGTIMER                 0
+#define  MEMORY_MAPPED_IO              0
+#define  DEBUG_QLA1280_INTR            0
+#define  USE_NVRAM_DEFAULTS	       0
+#define  DEBUG_PRINT_NVRAM             0
+#define  LOADING_RISC_ACTIVITY         0
+#define  AUTO_ESCALATE_RESET           0   /* Automatically escalate resets */
+#define  AUTO_ESCALATE_ABORT           0   /* Automatically escalate aborts */
+#define  STOP_ON_ERROR                 0   /* Stop on aborts and resets  */
+#define  STOP_ON_RESET                 0 
+#define  STOP_ON_ABORT                 0 
+#undef   DYNAMIC_MEM_ALLOC
+
+#define  DEBUG_QLA1280                 0    /* Debugging  */
+/* #define CHECKSRBSIZE */
+
+/*
+ * These macros to assist programming
+ */
+
+#define	BZERO(ptr, amt)		memset(ptr, 0, amt)
+#define	BCOPY(src, dst, amt)	memcpy(dst, src, amt)
+#define	KMALLOC(siz)	kmalloc((siz), GFP_ATOMIC)
+#define	KMFREE(ip,siz)	kfree((ip))
+#define	SYS_DELAY(x)		udelay(x);barrier()
+#define QLA1280_DELAY(sec)  mdelay(sec * 1000)
+#define VIRT_TO_BUS(a) virt_to_bus((a))
+#if  QLA1280_64BIT_SUPPORT
+#if  BITS_PER_LONG <= 32
+#define  VIRT_TO_BUS_LOW(a) (uint32_t)virt_to_bus((a))
+#define  VIRT_TO_BUS_HIGH(a) (uint32_t)(0x0)
+#else
+#define  VIRT_TO_BUS_LOW(a) (uint32_t)(0xffffffff & virt_to_bus((a)))
+#define  VIRT_TO_BUS_HIGH(a) (uint32_t)(0xffffffff & (virt_to_bus((a))>>32))
+#endif
+#endif  /* QLA1280_64BIT_SUPPORT */
+
+#define STATIC     
+
+#define NVRAM_DELAY() udelay(500) /* 2 microsecond delay */
+void qla1280_device_queue_depth(scsi_qla_host_t *, Scsi_Device *);
+
+#define  CACHE_FLUSH(a) (RD_REG_WORD(a))
+#define  INVALID_HANDLE    (MAX_OUTSTANDING_COMMANDS+1)
+
+#define  MSW(x)          (uint16_t)((uint32_t)(x) >> 16)
+#define  LSW(x)          (uint16_t)(x)
+#define  MSB(x)          (uint8_t)((uint16_t)(x) >> 8)
+#define  LSB(x)          (uint8_t)(x)
+
+#if  BITS_PER_LONG <= 32
+#define  LS_64BITS(x) (uint32_t)(x)
+#define  MS_64BITS(x) (uint32_t)(0x0)
+#else
+#define  LS_64BITS(x) (uint32_t)(0xffffffff & (x))
+#define  MS_64BITS(x) (uint32_t)(0xffffffff & ((x)>>32) )
+#endif
+
+/*
+ *  QLogic Driver Support Function Prototypes.
+ */
+STATIC void   qla1280_done(scsi_qla_host_t *, srb_t **, srb_t **);
+STATIC void   qla1280_next(scsi_qla_host_t *, scsi_lu_t *, uint8_t);
+STATIC void   qla1280_putq_t(scsi_lu_t *, srb_t *);
+STATIC void   qla1280_done_q_put(srb_t *, srb_t **, srb_t **);
+STATIC void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
+#ifdef  QLA1280_UNUSED 
+static void qla1280_dump_regs(struct Scsi_Host *host);
+#endif
+#if  STOP_ON_ERROR 
+static void qla1280_panic(char *, struct Scsi_Host *host);
+#endif
+void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd);
+STATIC void qla1280_abort_queue_single(scsi_qla_host_t *,uint32_t,uint32_t,uint32_t,uint32_t);
+
+STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd       *cp);
+STATIC void qla1280_removeq(scsi_lu_t *q, srb_t *sp);
+STATIC void qla1280_mem_free(scsi_qla_host_t *ha);
+void qla1280_do_dpc(void *p);
+#ifdef  QLA1280_UNUSED 
+static void qla1280_set_flags(char * s);
+#endif
+static char	*qla1280_get_token(char *, char *);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+STATIC inline void mdelay(int);
+#endif
+static inline void qla1280_enable_intrs(scsi_qla_host_t *);
+static inline void qla1280_disable_intrs(scsi_qla_host_t *);
+
+/*
+ *  QLogic ISP1280 Hardware Support Function Prototypes.
+ */
+STATIC uint8_t   qla1280_initialize_adapter(struct scsi_qla_host   *ha);
+STATIC uint8_t   qla1280_enable_tgt(scsi_qla_host_t *, uint8_t);
+STATIC uint8_t   qla1280_isp_firmware(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_pci_config(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_chip_diag(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_setup_chip(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_init_rings(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_nvram_config(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_mailbox_command(scsi_qla_host_t *, uint8_t, uint16_t *);
+STATIC uint8_t   qla1280_bus_reset(scsi_qla_host_t *, uint8_t);
+STATIC uint8_t   qla1280_device_reset(scsi_qla_host_t *, uint8_t, uint32_t);
+STATIC uint8_t   qla1280_abort_device(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t);
+STATIC uint8_t   qla1280_abort_command(scsi_qla_host_t *, srb_t *),
+#if  QLA1280_64BIT_SUPPORT
+                 qla1280_64bit_start_scsi(scsi_qla_host_t *, srb_t *),
+#endif
+                 qla1280_32bit_start_scsi(scsi_qla_host_t *, srb_t *),
+                 qla1280_abort_isp(scsi_qla_host_t *);
+STATIC void      qla1280_nv_write(scsi_qla_host_t *, uint16_t),
+                 qla1280_nv_delay(scsi_qla_host_t *),
+                 qla1280_poll(scsi_qla_host_t *),
+                 qla1280_reset_adapter(scsi_qla_host_t *),
+                 qla1280_marker(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t, uint8_t),
+                 qla1280_isp_cmd(scsi_qla_host_t *),
+                 qla1280_isr(scsi_qla_host_t *, srb_t **, srb_t **),
+                 qla1280_rst_aen(scsi_qla_host_t *),
+                 qla1280_status_entry(scsi_qla_host_t *, sts_entry_t *, srb_t **,
+                                      srb_t **),
+                 qla1280_error_entry(scsi_qla_host_t *, response_t *, srb_t **,
+                                     srb_t **),
+                 qla1280_restart_queues(scsi_qla_host_t *),
+                 qla1280_abort_queues(scsi_qla_host_t *);
+STATIC uint16_t  qla1280_get_nvram_word(scsi_qla_host_t *, uint32_t),
+                 qla1280_nvram_request(scsi_qla_host_t *, uint32_t),
+                 qla1280_debounce_register(volatile uint16_t *);
+STATIC request_t *qla1280_req_pkt(scsi_qla_host_t *);
+int  qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp);
+STATIC uint8_t qla1280_mem_alloc(scsi_qla_host_t *ha);
+STATIC uint8_t  qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels);
+
+STATIC uint8_t qla12160_set_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t, nvram160_t *);
+STATIC void qla12160_get_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t);
+
+#if QL1280_TARGET_MODE_SUPPORT
+STATIC void      qla1280_enable_lun(scsi_qla_host_t *, uint8_t, uint32_t),
+                 qla1280_notify_ack(scsi_qla_host_t *, notify_entry_t *),
+                 qla1280_immed_notify(scsi_qla_host_t *, notify_entry_t *),
+                 qla1280_accept_io(scsi_qla_host_t *, ctio_ret_entry_t *),
+#if  QLA1280_64BIT_SUPPORT
+                 qla1280_64bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t,
+                                     paddr32_t *),
+#endif
+                 qla1280_32bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t,
+                                     paddr32_t *),
+                 qla1280_atio_entry(scsi_qla_host_t *, atio_entry_t *),
+                 qla1280_notify_entry(scsi_qla_host_t *, notify_entry_t *);
+#endif  /* QLA1280_TARGET_MODE_SUPPORT */
+
+#ifdef QL_DEBUG_ROUTINES
+/*
+ *  Driver Debug Function Prototypes.
+ */
+STATIC uint8_t  qla1280_getbyte(uint8_t *);
+STATIC uint16_t qla1280_getword(uint16_t *);
+STATIC uint32_t qla1280_getdword(uint32_t *);
+STATIC void     qla1280_putbyte(uint8_t *, uint8_t),
+                qla1280_putword(uint16_t *, uint16_t),
+                qla1280_putdword(uint32_t *, uint32_t),
+                qla1280_print(caddr_t),
+                qla1280_output_number(uint32_t, uint8_t),
+                qla1280_putc(uint8_t),
+                qla1280_dump_buffer(caddr_t, uint32_t);
+
+char          debug_buff[80];
+#if DEBUG_QLA1280 
+STATIC uint8_t ql_debug_print = 1;
+#else
+STATIC uint8_t ql_debug_print = 0;
+#endif
+#endif
+
+/*
+ * insmod needs to find the variable and make it point to something
+ */
+#ifdef MODULE
+static char *options = NULL;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18)
+
+/* insmod qla1280 options=verbose" */
+MODULE_PARM(options, "s");  
+#endif
+/*
+ * Just in case someone uses commas to separate items on the insmod
+ * command line, we define a dummy buffer here to avoid having insmod
+ * write wild stuff into our code segment
+ */
+static char dummy_buffer[60] = "Please don't add commas in your insmod command!!\n";
+
+#endif
+
+
+/*
+ * Our directory Entry in /proc/scsi for the user to 
+ * access the driver. 
+ */
+
+#if 0
+
+/* Need to add in proc_fs.h     PROC_SCSI_QL1280 */
+#define PROC_SCSI_QL1280  PROC_SCSI_QLOGICISP
+
+struct proc_dir_entry proc_scsi_qla1280 = {
+    PROC_SCSI_QL1280, 7, "qla1280",                           
+    S_IFDIR | S_IRUGO | S_IXUGO, 2,
+    0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#endif
+
+/* We use the Scsi_Pointer structure that's included with each command
+ * SCSI_Cmnd as a scratchpad for our SRB.
+ *
+ * SCp will always point to the SRB structure (defined in qla1280.h).
+ * It is define as follows:
+ *  - SCp.ptr  -- > pointer back to the cmd
+ *  - SCp.this_residual --> used as forward pointer to next srb
+ *  - SCp.buffer --> used as backward pointer to next srb
+ *  - SCp.buffers_residual --> used as flags field
+ *  - SCp.have_data_in --> not used
+ *  - SCp.sent_command --> not used
+ *  - SCp.phase --> not used
+ */
+
+#define	CMD_SP(Cmnd)		(&(Cmnd)->SCp)
+#define	CMD_XFRLEN(Cmnd)	(Cmnd)->request_bufflen
+#define	CMD_CDBLEN(Cmnd)	(Cmnd)->cmd_len
+#define	CMD_CDBP(Cmnd)		(Cmnd)->cmnd
+#define	CMD_SNSP(Cmnd)		(Cmnd)->sense_buffer
+#define	CMD_SNSLEN(Cmnd)	(sizeof (Cmnd)->sense_buffer)
+#define	CMD_RESULT(Cmnd)	((Cmnd)->result)
+#define	CMD_HANDLE(Cmnd)	((Cmnd)->host_scribble)
+
+/*****************************************/
+/*   ISP Boards supported by this driver */
+/*****************************************/
+#define QLA1280_VENDOR_ID   0x1077
+#define QLA1080_DEVICE_ID   0x1080
+#define QLA1240_DEVICE_ID   0x1240
+#define QLA1280_DEVICE_ID   0x1280
+#define QLA12160_DEVICE_ID  0x1216
+#define QLA10160_DEVICE_ID  0x1016
+#define NUM_OF_ISP_DEVICES        6
+
+typedef struct _qlaboards 
+{
+   unsigned char   bdName[9];       /* Board ID String */
+   unsigned long   device_id;       /* Device PCI ID   */
+   int   numPorts;                  /* Number of SCSI ports */
+   unsigned short   *fwcode;        /* pointer to FW array         */
+   unsigned long    *fwlen;         /* number of words in array    */
+   unsigned short   *fwstart;       /* start address for F/W       */
+   unsigned char   *fwver;          /* Ptr to F/W version array    */
+} qla_boards_t;
+
+struct _qlaboards   QLBoardTbl[NUM_OF_ISP_DEVICES] = 
+{
+   /* Name ,  Board PCI Device ID,         Number of ports */
+  {"QLA1080 ", QLA1080_DEVICE_ID,           1,        
+               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
+  {"QLA1240 ", QLA1240_DEVICE_ID,           2,       
+               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
+  {"QLA1280 ", QLA1280_DEVICE_ID,           2,      
+               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
+  {"QLA12160 ", QLA12160_DEVICE_ID,          2,      
+               &fw12160i_code01[0],  (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },       
+  {"QLA10160 ", QLA10160_DEVICE_ID,          1,      
+               &fw12160i_code01[0],  (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },       
+  {"        ",                 0,           0}
+};
+
+static unsigned long qla1280_verbose = 1L;
+static scsi_qla_host_t *qla1280_hostlist = NULL;
+#ifdef QLA1280_PROFILE
+static int qla1280_buffer_size = 0;
+static char *qla1280_buffer = NULL;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3 
+#define ENTER(x)	sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define LEAVE(x)	sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define ENTER_INTR(x)	sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define LEAVE_INTR(x)	sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define DEBUG3(x)	x
+#else
+#define ENTER(x)
+#define LEAVE(x)
+#define ENTER_INTR(x)
+#define LEAVE_INTR(x)
+#define DEBUG3(x)
+#endif
+
+#if  DEBUG_QLA1280  
+#define COMTRACE(x)
+/* #define COMTRACE(x)     qla1280_putc(x); */
+#define DEBUG(x)	x
+#else
+#define DEBUG(x)
+#define COMTRACE(x)
+#endif
+
+#ifdef QL_DEBUG_LEVEL_2 
+#define DEBUG2(x)	x
+#else
+#define DEBUG2(x)
+#endif
+#define DEBUG5(x)
+
+#if (BITS_PER_LONG==64)
+#   define OFFSET(w)   (((uint64_t) &w) & 0xFF)   /* 256 byte offsets */
+#else
+#   define OFFSET(w)   (((uint32_t) &w) & 0xFF)   /* 256 byte offsets */
+#endif
+
+#define SCSI_BUS_32(scp)   ((scp)->channel)
+#define SCSI_TCN_32(scp)    ((scp)->target)
+#define SCSI_LUN_32(scp)    ((scp)->lun)
+
+/****************************************************************************/
+/*  LINUX -  Loadable Module Functions.                                     */
+/****************************************************************************/
+
+
+/*************************************************************************
+ *   qla1280_set_info
+ *
+ * Description:
+ *   Set parameters for the driver from the /proc filesystem.
+ *
+ * Returns:
+ *************************************************************************/
+int
+qla1280_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
+{
+  return (-ENOSYS);  /* Currently this is a no-op */
+}
+
+/*************************************************************************
+ * qla1280_proc_info
+ *
+ * Description:
+ *   Return information to handle /proc support for the driver.
+ *
+ * buffer - ptrs to a page buffer
+ *
+ * Returns:
+ *************************************************************************/
+#ifdef QLA1280_PROFILE
+#define	PROC_BUF	(&qla1280_buffer[size])
+#define LUN_ID       (targ_lun>>(MAX_T_BITS+MAX_L_BITS)),((targ_lun>>MAX_L_BITS)&0xf), targ_lun&0x7 
+#endif
+int
+qla1280_proc_info ( char *buffer, char **start, off_t offset, int length, 
+                    int hostno, int inout)
+{
+#ifdef QLA1280_PROFILE
+  struct Scsi_Host *host;
+  scsi_qla_host_t *ha;
+  int    size = 0;
+  int  targ_lun;
+  scsi_lu_t  *up;
+  int   no_devices;
+
+  printk("Entering proc_info 0x%p,0x%lx,0x%x,0x%x\n",buffer,offset,length,hostno);
+  host = NULL;
+  /* find the host they want to look at */
+  for(ha=qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno; ha=ha->next)
+    ;
+
+  if (!ha)
+  {
+    size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
+    if (size > length)
+    {
+      return (size);
+    }
+    else
+    {
+      return (length);
+    }
+  }
+
+  host = ha->host;
+  if (inout == TRUE) /* Has data been written to the file? */ 
+  {
+    return (qla1280_set_info(buffer, length, host));
+  }
+
+  /* compute number of active devices */
+  no_devices = 0;
+  for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++)
+  {
+          if( (up = ha->dev[targ_lun]) == NULL )
+              continue;
+          no_devices++;
+  }
+  /* size = 112 * no_devices; */
+  size = 4096;
+  /* round up to the next page */
+  
+  /* 
+   * if our old buffer is the right size use it otherwise 
+   * allocate a new one.
+   */
+  if (qla1280_buffer_size != size)
+  {
+    /* deallocate this buffer and get a new one */
+    if (qla1280_buffer != NULL) 
+    {
+      kfree(qla1280_buffer);
+      qla1280_buffer_size = 0;
+    }
+    qla1280_buffer = kmalloc(size, GFP_KERNEL);
+  }
+  if (qla1280_buffer == NULL)
+  {
+    size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n",
+        __LINE__);
+    return size;
+  }
+  qla1280_buffer_size = size;
+
+  size = 0;
+  size += sprintf(PROC_BUF, "Qlogic 1280/1080 SCSI driver version: ");   /* 43 bytes */
+  size += sprintf(PROC_BUF, "%5s, ", QLA1280_VERSION);                         /* 5        */
+  size += sprintf(PROC_BUF, "Qlogic Firmware version: ");                     /* 25       */
+  size += sprintf(PROC_BUF, "%2d.%2d.%2d",_firmware_version[0],           /* 8        */
+                                          ql12_firmware_version[1],
+                                          ql12_firmware_version[2]);
+  size += sprintf(PROC_BUF, "\n");                                             /* 1       */
+                           
+  size += sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", QLBoardTbl[ha->devnum].bdName);
+  size += sprintf(PROC_BUF, "Request Queue = 0x%lx, Response Queue = 0x%lx\n",
+                        ha->request_dma,
+                        ha->response_dma);
+  size += sprintf(PROC_BUF, "Request Queue count= 0x%x, Response Queue count= 0x%x\n",
+                        REQUEST_ENTRY_CNT,
+                        RESPONSE_ENTRY_CNT);
+  size += sprintf(PROC_BUF,"Number of pending commands = 0x%lx\n", ha->actthreads);
+  size += sprintf(PROC_BUF,"Number of queued commands = 0x%lx\n", ha->qthreads);
+  size += sprintf(PROC_BUF,"Number of free request entries = %d\n",ha->req_q_cnt);
+  size += sprintf(PROC_BUF, "\n");                                             /* 1       */
+                        
+  size += sprintf(PROC_BUF, "Attached devices:\n");
+  /* scan for all equipment stats */ 
+  for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++)
+  {
+      if( (up = ha->dev[targ_lun]) == NULL )
+           continue;
+      if( up->io_cnt == 0 )
+      {
+          size += sprintf(PROC_BUF,"(%2d:%2d:%2d) No stats\n",LUN_ID);
+           continue;
+      }
+      /* total reads since boot */
+      /* total writes since boot */
+      /* total requests since boot  */
+      size += sprintf(PROC_BUF, "Total requests %ld,",up->io_cnt);
+      /* current number of pending requests */
+      size += sprintf(PROC_BUF, "(%2d:%2d:%2d) pending requests %d,",LUN_ID,up->q_outcnt);
+      /* avg response time */
+      size += sprintf(PROC_BUF, "Avg response time %ld%%,",(up->resp_time/up->io_cnt)*100);
+      
+      /* avg active time */
+      size += sprintf(PROC_BUF, "Avg active time %ld%%\n",(up->act_time/up->io_cnt)*100);
+  }
+
+  if (size >= qla1280_buffer_size)
+  {
+    printk(KERN_WARNING "qla1280: Overflow buffer in qla1280_proc.c\n");
+  }
+
+  if (offset > size - 1)
+  {
+    kfree(qla1280_buffer);
+    qla1280_buffer = NULL;
+    qla1280_buffer_size = length = 0;
+    *start = NULL;
+  }
+  else
+  {
+    *start = &qla1280_buffer[offset];   /* Start of wanted data */
+    if (size - offset < length)
+    {
+      length = size - offset;
+    }
+  }
+#endif
+
+  return (length);
+}
+
+
+/**************************************************************************
+ * qla1280_detect
+ *    This routine will probe for Qlogic 1280 SCSI host adapters.
+ *    It returns the number of host adapters of a particular
+ *    type that were found.	 It also initialize all data necessary for 
+ *    the driver.  It is passed-in the host number, so that it
+ *    knows where its first entry is in the scsi_hosts[] array.
+ *
+ * Input:
+ *     template - pointer to SCSI template
+ *
+ * Returns:
+ *  num - number of host adapters found.  
+ **************************************************************************/
+int
+qla1280_detect(Scsi_Host_Template *template)
+{
+    int num_hosts = 0;
+    struct Scsi_Host *host;
+    scsi_qla_host_t *ha, *cur_ha;
+    struct _qlaboards  *bdp;
+    int i, j;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,95)
+    unsigned int piobase;
+    unsigned char pci_bus, pci_devfn, pci_irq;
+    config_reg_t   *cfgp = 0;
+#endif
+    device_reg_t   *reg;
+    char   *cp;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    struct pci_dev *pdev = NULL;
+#else
+    int index;
+#endif
+
+    ENTER("qla1280_detect");
+
+#ifdef CHECKSRBSIZE
+    if (sizeof(srb_t) > sizeof(Scsi_Pointer) )
+    {
+      printk("Redefine SRB - its too big");
+      return 0;
+    }
+#endif
+
+#ifdef MODULE
+	DEBUG(sprintf(debug_buff,"DEBUG: qla1280_detect starts at address = %p\n",qla1280_detect);)
+	DEBUG(qla1280_print(debug_buff);)
+    /*
+    * If we are called as a module, the qla1280 pointer may not be null
+    * and it would point to our bootup string, just like on the lilo
+    * command line.  IF not NULL, then process this config string with
+    * qla1280_setup
+    *
+    * Boot time Options
+    * To add options at boot time add a line to your lilo.conf file like:
+    * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"
+    * which will result in the first four devices on the first two
+    * controllers being set to a tagged queue depth of 32.
+    */
+    if(options)
+        qla1280_setup(options, NULL);
+    if(dummy_buffer[0] != 'P')
+        printk(KERN_WARNING "qla1280: Please read the file /usr/src/linux/drivers"
+                "/scsi/README.qla1280\n"
+                "qla1280: to see the proper way to specify options to the qla1280 "
+                "module\n"
+                "qla1280: Specifically, don't use any commas when passing arguments to\n"
+                "qla1280: insmod or else it might trash certain memory areas.\n");
+#endif
+
+    if ((int) !pcibios_present())
+    {
+		printk("scsi: PCI not present\n");
+		return 0;
+    } /* end of IF */
+    bdp = &QLBoardTbl[0];
+    qla1280_hostlist = NULL;
+#if 0
+    template->proc_dir = &proc_scsi_qla1280;
+#else
+    template->proc_name = "qla1280";
+#endif
+    
+	/* Try and find each different type of adapter we support */
+	for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+		while ((pdev = pci_find_device(QLA1280_VENDOR_ID,
+			bdp->device_id, pdev ) ))  
+#else
+		while (!(pcibios_find_device(QLA1280_VENDOR_ID,
+			bdp->device_id,
+			index++, &pci_bus, &pci_devfn)) )  
+#endif
+                {
+                /* found a adapter */
+		host = scsi_register(template, sizeof(scsi_qla_host_t));
+		ha = (scsi_qla_host_t *) host->hostdata;
+		/* Clear our data area */
+		for( j =0, cp = (char *)ha;  j < sizeof(scsi_qla_host_t); j++)
+			*cp = 0;
+		/* Sanitize the information from PCI BIOS.  */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+		host->irq = pdev->irq;
+/* this depends on release 2.3.18 */
+		host->io_port = pdev->resource[0].start;
+/* MRS	host->io_port = (unsigned int) pdev->base_address[0]; */
+		ha->pci_bus = pdev->bus->number;
+		ha->pci_device_fn = pdev->devfn;
+		ha->pdev = pdev;
+#else
+		pcibios_read_config_byte(pci_bus, pci_devfn, OFFSET(cfgp->interrupt_line), &pci_irq);
+		pcibios_read_config_dword(pci_bus, pci_devfn, OFFSET(cfgp->base_port), &piobase);
+		host->irq = pci_irq;
+		host->io_port = (unsigned int) piobase;
+		ha->pci_bus = pci_bus;
+		ha->pci_device_fn = pci_devfn;
+#endif
+		ha->device_id = bdp->device_id;
+		host->io_port &= PCI_BASE_ADDRESS_IO_MASK;
+    
+                ha->devnum = i;
+                host->io_port &= PCI_BASE_ADDRESS_IO_MASK;
+		if( qla1280_mem_alloc(ha) ) {
+			printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n");
+		}
+                
+                ha->ports = bdp->numPorts; 
+                ha->iobase = (device_reg_t *) host->io_port;
+                ha->host = host;
+                ha->host_no = host->host_no;
+
+                /* load the F/W, read paramaters, and init the H/W */
+                if (qla1280_initialize_adapter(ha))
+                {
+
+                    printk(KERN_INFO "qla1280: Failed to initialized adapter\n");
+                    qla1280_mem_free(ha);
+                    scsi_unregister(host);
+                    continue;
+                }
+                
+                host->max_channel = bdp->numPorts-1; 
+                ha->instance = num_hosts;
+		/* Register our resources with Linux */
+		if( qla1280_register_with_Linux(ha, bdp->numPorts-1) ) {
+			printk(KERN_INFO "qla1280: Failed to register our resources\n");
+			qla1280_mem_free(ha);
+			scsi_unregister(host);
+			continue;
+		}
+
+
+                reg = ha->iobase;
+                /* Disable ISP interrupts. */
+		qla1280_disable_intrs(ha);
+
+                /* Insure mailbox registers are free. */
+                WRT_REG_WORD(&reg->semaphore, 0);
+                WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+                WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
+
+                /* Enable chip interrupts. */
+		qla1280_enable_intrs(ha);
+               
+                /* Insert new entry into the list of adapters */
+                ha->next = NULL;
+                if( qla1280_hostlist == NULL )
+                {
+                    cur_ha = qla1280_hostlist = ha;
+                }
+                else
+                {
+                    cur_ha = qla1280_hostlist;
+                    while( cur_ha->next != NULL )
+                        cur_ha = cur_ha->next;
+                    cur_ha->next = ha;
+                }
+                num_hosts++;
+            }  /* end of WHILE */
+        } /* end of FOR */
+
+    LEAVE("qla1280_detect");
+    return num_hosts; 
+}
+
+/**************************************************************************
+*   qla1280_register_with_Linux
+*
+* Description:
+*   Free the passed in Scsi_Host memory structures prior to unloading the
+*   module.
+*
+* Input:
+*     ha - pointer to host adapter structure
+*     maxchannels - MAX number of channels.
+*
+* Returns:
+*  0 - Sucessfully reserved resources.
+*  1 - Failed to reserved a resource.
+**************************************************************************/
+STATIC uint8_t  qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels)
+{
+
+	struct Scsi_Host *host = ha->host;
+
+	host->can_queue = 0xfffff;  /* unlimited  */
+	host->cmd_per_lun = 1;
+       host->select_queue_depths = qla1280_select_queue_depth;
+	host->n_io_port = 0xFF;
+	host->base = (unsigned long) ha->mmpbase;
+	host->max_channel = maxchannels; 
+       host->max_lun = MAX_LUNS-1; 
+	host->unique_id = ha->instance;
+       host->max_id = MAX_TARGETS; 
+       host->unique_id = ha->instance;
+
+	/* set our host ID  (need to do something about our two IDs) */
+       host->this_id = ha->bus_settings[0].id;
+       /* Register the IRQ with Linux (sharable) */
+       if ( request_irq(host->irq, qla1280_intr_handler, SA_INTERRUPT| SA_SHIRQ, "qla1280", ha))
+       {
+          printk("qla1280 : Failed to reserved interrupt %d already in use\n", host->irq);
+          qla1280_mem_free(ha);
+          scsi_unregister(host);
+	     return 1;
+       }
+
+       /* Register the I/O space with Linux */
+       if (check_region(host->io_port, 0xff))
+       {
+           printk("qla1280 : Failed to reserved i/o region 0x%04lx-0x%04lx already in use\n",
+              host->io_port, host->io_port + 0xff);
+           free_irq(host->irq, NULL);
+           qla1280_mem_free(ha);
+           scsi_unregister(host);
+	     return 1;
+       }
+
+       request_region(host->io_port, 0xff, "qla1280");
+
+	return 0;
+}
+
+
+/**************************************************************************
+ *   qla1280_release
+ *   Free the passed in Scsi_Host memory structures prior to unloading the
+ *   module.
+ **************************************************************************/
+int
+qla1280_release(struct Scsi_Host *host)
+{
+    scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata;
+
+    ENTER("qla1280_release");
+
+    if( !ha->flags.online )
+        return(0);
+
+    /* turn-off interrupts on the card */
+    WRT_REG_WORD(&ha->iobase->ictrl, 0);
+
+    /* Detach interrupts */
+    if(host->irq)
+        free_irq(host->irq, ha);
+
+    /* release io space registers  */
+    if( host->io_port )
+        release_region(host->io_port, 0xff);
+
+#if MEMORY_MAPPED_IO
+    if(ha->mmpbase)
+    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+        vfree((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));
+#else
+        iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));
+#endif
+    }
+#endif /* MEMORY_MAPPED_IO */
+    qla1280_mem_free(ha);
+
+    ENTER("qla1280_release");
+    return(0);
+}
+
+/**************************************************************************
+ *   qla1280_info
+ *     Return a string describing the driver.
+ **************************************************************************/
+const char *
+qla1280_info(struct Scsi_Host *host)
+{
+    static char qla1280_buffer[125];
+    char *bp;
+    scsi_qla_host_t *ha;
+    qla_boards_t   *bdp; 
+
+    bp = &qla1280_buffer[0];
+    ha = (scsi_qla_host_t *)host->hostdata;
+    bdp = &QLBoardTbl[ha->devnum];
+    memset(bp, 0, sizeof(qla1280_buffer));
+    sprintf(bp,
+            "QLogic %sPCI to SCSI Host Adapter: bus %d device %d irq %d\n"
+            "       Firmware version: %2d.%02d.%02d, Driver version %s",
+            (char *)&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq,
+            bdp->fwver[0],bdp->fwver[1],bdp->fwver[2],
+            QLA1280_VERSION);
+    return(bp);
+}
+
+/**************************************************************************
+ *   qla1200_queuecommand
+ *     Queue a command to the controller.
+ *
+ * Note:
+ * The mid-level driver tries to ensures that queuecommand never gets invoked
+ * concurrently with itself or the interrupt handler (although the
+ * interrupt handler may call this routine as part of request-completion
+ * handling).   Unfortunely, it sometimes calls the scheduler in interrupt
+ * context which is a big NO! NO!.
+ **************************************************************************/
+int
+qla1280_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
+{
+    scsi_qla_host_t *ha;
+    srb_t  *sp;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    struct Scsi_Host *host;
+    uint32_t        b, t, l;
+    scsi_lu_t       *q;
+    u_long          handle;
+
+    ENTER("qla1280_queuecommand");
+    COMTRACE('C') 
+
+    host = cmd->host;
+    ha = (scsi_qla_host_t *) host->hostdata;
+
+    /* send command to adapter */
+    sp = (srb_t *) CMD_SP(cmd);
+    sp->cmd =  cmd;
+    cmd->scsi_done = fn;
+    if (cmd->flags == 0)  /* new command */
+    {
+        sp->flags = 0;
+    }
+
+    DEBUG5(qla1280_print_scsi_cmd(cmd));
+
+    /* Generate LU queue on bus, target, LUN */
+    b = SCSI_BUS_32(cmd);
+    t = SCSI_TCN_32(cmd);
+    l = SCSI_LUN_32(cmd);
+    if((q = LU_Q(ha, b, t, l)) == NULL )
+    {
+        DRIVER_LOCK
+        if( (q = (scsi_lu_t *)KMALLOC(sizeof(struct scsi_lu))) )
+        {
+           LU_Q(ha, b, t, l) = q;
+           BZERO(q,sizeof(struct scsi_lu));
+           DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n",q));
+           DEBUG(qla1280_print(debug_buff));
+           DRIVER_UNLOCK
+        }
+        else
+        {
+            CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16);
+            qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
+            queue_task(&ha->run_qla_bh,&tq_scheduler); 
+            ha->flags.dpc_sched = TRUE;
+            DRIVER_UNLOCK
+            return(0);
+        }
+    }
+    /* Set an invalid handle until we issue the command to ISP */
+    /* then we will set the real handle value.                 */
+    handle = INVALID_HANDLE;  
+    CMD_HANDLE(cmd) = (unsigned char *)handle;
+
+    /* Bookkeeping information */
+    sp->r_start = jiffies;       /* time the request was recieved */
+    sp->u_start = 0;              
+
+    /* add the command to our queue */
+    ha->qthreads++;
+    qla1280_putq_t(q,sp);
+    
+    DEBUG(sprintf(debug_buff,"qla1280_queuecmd: queue pid=%d, hndl=0x%x\n\r",cmd->pid,handle));
+    DEBUG(qla1280_print(debug_buff));
+
+    /* send command to adapter */
+    DRIVER_LOCK
+        if (q->q_outcnt == 0)
+            qla1280_restart_queues(ha);
+    DRIVER_UNLOCK
+    
+    
+    LEAVE("qla1280_queuecommand");
+    return (0);
+}
+
+/**************************************************************************
+ *   qla1200_abort
+ *     Abort the speciifed SCSI command(s).
+ **************************************************************************/
+int
+qla1280_abort(Scsi_Cmnd *cmd)
+{
+    scsi_qla_host_t *ha;
+    srb_t  *sp;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    struct Scsi_Host *host;
+    uint32_t        b, t, l;
+    scsi_lu_t       *q;
+    int return_status = SCSI_ABORT_SUCCESS;
+    int found = 0;
+    int i;
+    u_long     handle;
+    u_short    data;
+
+    ENTER("qla1280_abort");
+    COMTRACE('A')
+    ha = (scsi_qla_host_t *) cmd->host->hostdata;
+    host = cmd->host;
+    DRIVER_LOCK
+
+    /* Get the SCSI request ptr */
+    sp = (srb_t *) CMD_SP(cmd);
+    handle = (u_long) CMD_HANDLE(cmd);
+    if (qla1280_verbose)
+        printk("scsi(%d): ABORT Command=0x%lx, handle=0x%lx\n",(int)ha->host_no,(long)cmd,handle);
+
+    /* Check for pending interrupts. */
+    if( handle == 0L )
+    {
+    COMTRACE('a')
+        /* we never got this command */
+        printk(KERN_INFO "qla1280: Aborting a NULL handle\n");
+        DRIVER_UNLOCK
+                return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */
+    }
+    data = qla1280_debounce_register(&ha->iobase->istatus);
+    if( !(ha->flags.in_isr) && (data & RISC_INT) )
+    {
+        /* put any pending command in done queue */
+        qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    }
+
+    handle = (u_long) CMD_HANDLE(cmd);
+
+    /* Generate LU queue on bus, target, LUN */
+    b = SCSI_BUS_32(cmd);
+    t = SCSI_TCN_32(cmd);
+    l = SCSI_LUN_32(cmd);
+    if((q = LU_Q(ha, b, t, l)) == NULL )
+    {
+    COMTRACE('a')
+        /* No lun queue -- command must not be active */
+        DRIVER_UNLOCK
+        printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the specified device\n",(int)b,(int)t,(int)l);
+        return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */
+    }
+
+#if AUTO_ESCALATE_ABORT
+    if ( (sp->flags & SRB_ABORTED) )
+    {
+        DRIVER_UNLOCK
+        DEBUG(qla1280_print("qla1280_abort: Abort escalayted - returning SCSI_ABORT_SNOOZE.\n\r"));
+        return(SCSI_ABORT_SNOOZE);
+    }
+#endif
+
+    if ( (sp->flags & SRB_ABORT_PENDING) )
+    {
+    COMTRACE('a')
+        DRIVER_UNLOCK
+        if( qla1280_verbose  )
+            printk("scsi(): Command has a pending abort message - ABORT_PENDING.\n");
+        DEBUG(qla1280_print("qla1280: Command has a pending abort message - ABORT_PENDING.\n\r"));
+        return(SCSI_ABORT_PENDING);
+    }
+
+#if  STOP_ON_ABORT 
+    printk("Scsi layer issued a ABORT command= 0x%x\n",(int)cmd);
+    DEBUG2(qla1280_print_scsi_cmd(cmd));
+#endif
+
+    ha->flags.in_abort = TRUE;
+    /*
+    * Normally, would would need to search our queue for the specified command
+    * but; since our sp contains the cmd ptr, we can just remove it from our
+    * LUN queue.
+    */
+    if( !(sp->flags&SRB_SENT) )
+    { 
+        found++;
+        if( qla1280_verbose  )
+            printk("scsi(): Command returned from queue aborted.\n");
+        DEBUG(qla1280_print("qla1280: Command returned from queue aborted.\n\r"));
+        /* Remove srb from SCSI LU queue. */
+        qla1280_removeq(q, sp);
+        sp->flags |=  SRB_ABORTED;
+        CMD_RESULT(cmd) = DID_ABORT << 16; 
+        qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
+        return_status = SCSI_ABORT_SUCCESS;
+    }
+    else
+    {  /* find the command in our active list */
+        for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++)
+        {
+            if( sp == ha->outstanding_cmds[i] )
+            {
+                found++;
+                DEBUG(qla1280_print("qla1280: RISC aborting command.\n\r"));
+                qla1280_abort_command(ha,sp);
+                return_status = SCSI_ABORT_PENDING;
+                break;
+            }
+        }
+    }
+
+#if  STOP_ON_ABORT 
+    qla1280_panic("qla1280_abort",ha->host);
+#endif
+    if ( found == 0 )
+        return_status = SCSI_ABORT_NOT_RUNNING;  /* no action - we don't have command */
+
+    DEBUG(sprintf(debug_buff, "qla1280_abort: Aborted status returned = 0x%x.\n\r",return_status));
+    DEBUG(qla1280_print(debug_buff));
+
+    if( ha->done_q_first )
+       qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    if ( found )
+    {
+        qla1280_restart_queues(ha);
+    }
+    ha->flags.in_abort = FALSE;
+    DRIVER_UNLOCK
+
+    LEAVE("qla1280_abort");
+    COMTRACE('a')
+    return(return_status);
+}
+
+/**************************************************************************
+ * qla1200_reset
+ *    The reset function will reset the SCSI bus and abort any executing
+ *    commands. 
+ *
+ * Input:
+ *      cmd = Linux SCSI command packet of the command that cause the
+ *            bus reset.
+ *      flags = SCSI bus reset option flags (see scsi.h)
+ *
+ * Returns:
+ *      DID_RESET in cmd.host_byte of aborted command(s) 
+ *
+ * Note:
+ *      Resetting the bus always succeeds - is has to, otherwise the
+ *      kernel will panic! Try a surgical technique - sending a BUS
+ *      DEVICE RESET message - on the offending target before pulling
+ *      the SCSI bus reset line.
+ **************************************************************************/
+int
+qla1280_reset(Scsi_Cmnd *cmd, unsigned int flags)
+{
+    scsi_qla_host_t *ha;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    uint32_t        b, t, l;
+    srb_t  *sp;
+    typedef enum
+    {
+        ABORT_DEVICE = 1, 
+                DEVICE_RESET = 2, 
+                BUS_RESET    = 3, 
+                ADAPTER_RESET= 4,
+                RESET_DELAYED= 5,
+                FAIL         = 6
+    } action_t;
+    action_t     action = ADAPTER_RESET;
+    u_short    data;
+    scsi_lu_t       *q;
+    int result;
+
+
+    ENTER("qla1280_reset");
+    COMTRACE('R')
+    if (qla1280_verbose)
+        printk("scsi(): Resetting Cmnd=0x%lx, Handle=0x%lx, flags=0x%x\n",(long)cmd,(long)CMD_HANDLE(cmd),flags);
+    if ( cmd == NULL )
+    {
+        printk(KERN_WARNING "(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd "
+                "pointer, failing.\n");
+        return(SCSI_RESET_SNOOZE);
+    }
+    ha = (scsi_qla_host_t *) cmd->host->hostdata;
+    sp = (srb_t *) CMD_SP(cmd);
+
+#if  STOP_ON_RESET 
+    qla1280_panic("qla1280_reset",ha->host);
+#endif 
+
+    DRIVER_LOCK
+    /* Check for pending interrupts. */
+    data = qla1280_debounce_register(&ha->iobase->istatus);
+    if( !(ha->flags.in_isr) && (data & RISC_INT) )
+    {
+        qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    }
+    DRIVER_UNLOCK
+
+    /*
+    * Determine the suggested action that the mid-level driver wants
+    * us to perform.
+    */
+    if( CMD_HANDLE(cmd) == (unsigned char *) 0  )
+    {
+        /* 
+        * if mid-level driver called reset with a orphan SCSI_Cmnd 
+        * (i.e. a command that's not pending ), so perform the 
+        * function specified.
+        */
+        if( (flags & SCSI_RESET_SUGGEST_HOST_RESET) )
+            action = ADAPTER_RESET;
+        else 
+            action = BUS_RESET;
+    }
+    else
+    { /* 
+        * Mid-level driver has called reset with this SCSI_Cmnd and 
+        * its pending.
+        */
+        if( flags & SCSI_RESET_SUGGEST_HOST_RESET )
+            action = ADAPTER_RESET;
+        else if( flags & SCSI_RESET_SUGGEST_BUS_RESET )
+            action = BUS_RESET;
+        else 
+            action = DEVICE_RESET;
+    }
+
+    b = SCSI_BUS_32(cmd);
+    t = SCSI_TCN_32(cmd);
+    l = SCSI_LUN_32(cmd);
+    q = LU_Q(ha, b, t, l);
+
+#if AUTO_ESCALATE_RESET
+    if ( (action & DEVICE_RESET) && (q->q_flag & QLA1280_QRESET) )
+    {
+        printk(KERN_INFO "qla1280(%d): Bus device reset already sent to " "device, escalating.\n", (int)ha->host_no);
+        action = BUS_RESET;
+    }
+    if ( (action & DEVICE_RESET) && (sp->flags & SRB_ABORT_PENDING) )
+    {
+        printk(KERN_INFO "qla1280(%d):Have already attempted to reach " "device with abort device\n", (int)ha->host_no);
+        printk(KERN_INFO "qla1280(%d):message, will escalate to BUS " "RESET.\n",(int) ha->host_no);
+        action = BUS_RESET;
+    }
+#endif
+
+    /*
+    *  By this point, we want to already know what we are going to do,
+    *  so we only need to perform the course of action.
+    */
+    DRIVER_LOCK
+    result = SCSI_RESET_ERROR;
+    switch (action)
+    {
+        case FAIL:
+            break;
+
+        case RESET_DELAYED:
+            result = SCSI_RESET_PENDING;
+            break;
+
+        case ABORT_DEVICE:
+            ha->flags.in_reset = TRUE;
+            if (qla1280_verbose)
+                printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing abort device command.\n", (int)ha->host_no,(int)b,(int)t,(int)l); 
+            qla1280_abort_queue_single(ha,b,t,l,DID_ABORT);
+            if( qla1280_abort_device(ha, b, t, l) == 0)
+                result = SCSI_RESET_PENDING;
+            break;
+
+        case DEVICE_RESET:
+            if (qla1280_verbose)
+                printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing device reset command.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+            ha->flags.in_reset = TRUE;
+            for (l = 0; l < MAX_LUNS; l++)
+                qla1280_abort_queue_single(ha,b,t,l,DID_ABORT);
+            if( qla1280_device_reset(ha, b, t) == 0 ) 
+                result = SCSI_RESET_PENDING;
+            q->q_flag |= QLA1280_QRESET;
+            break;
+
+        case BUS_RESET:
+                if (qla1280_verbose)
+                    printk(KERN_INFO "qla1280(%d:%d:%d:%d): Issuing BUS DEVICE RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+            ha->flags.in_reset = TRUE;
+            for (t = 0; t < MAX_TARGETS; t++)
+                for (l = 0; l < MAX_LUNS; l++)
+                    qla1280_abort_queue_single(ha,b,t,l,DID_RESET);
+                qla1280_bus_reset(ha, b);
+                /*
+                * The bus reset routine returns all the outstanding commands back
+                * with "DID_RESET" in the status field after a short delay
+                * by the firmware. If the mid-level time out the SCSI reset before
+                * our delay we may need to ignore it.
+                */
+                /* result = SCSI_RESET_PENDING | SCSI_RESET_BUS_RESET; */
+                result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+                mdelay(4 * 1000); barrier();
+                if( flags & SCSI_RESET_SYNCHRONOUS )
+                {
+                  CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16);
+                  (*(cmd)->scsi_done)(cmd); 
+                }
+                /* ha->reset_start = jiffies; */
+                break;
+
+            case ADAPTER_RESET:
+            default:
+                if (qla1280_verbose)
+                {
+                    printk(KERN_INFO "scsi(%d:%d:%d:%d): Issued an ADAPTER RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+                    printk(KERN_INFO "scsi(%d:%d:%d:%d): I/O processing will continue automatically.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+                }
+                ha->flags.reset_active = TRUE;
+                /* 
+                * We restarted all of the commands automatically, so the mid-level code can expect 
+                * completions momentitarily.
+                */
+                if( qla1280_abort_isp(ha) == 0 )
+                    result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
+
+                        ha->flags.reset_active = FALSE;
+    }
+
+    if( ha->done_q_first ) 
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    qla1280_restart_queues(ha);
+    ha->flags.in_reset = FALSE;
+    
+DRIVER_UNLOCK
+    DEBUG(printk("RESET returning %d\n", result)); 
+
+    COMTRACE('r')
+    LEAVE("qla1280_reset");
+    return( result );
+}
+
+/**************************************************************************
+ * qla1200_biosparam
+ *   Return the disk geometry for the given SCSI device.
+ **************************************************************************/
+int
+qla1280_biosparam(Disk *disk, kdev_t dev, int geom[])
+{
+    int heads, sectors, cylinders;
+
+            heads = 64;
+    sectors = 32;
+    cylinders = disk->capacity / (heads * sectors);
+    if (cylinders > 1024)
+    {
+        heads = 255;
+        sectors = 63;
+        cylinders = disk->capacity / (heads * sectors);
+        /* if (cylinders > 1023)
+        cylinders = 1023; */
+    }
+
+    geom[0] = heads;
+    geom[1] = sectors;
+    geom[2] = cylinders;
+
+    return (0);
+}
+/**************************************************************************
+ * qla1280_intr_handler
+ *   Handles the H/W interrupt
+ **************************************************************************/
+void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    scsi_qla_host_t *ha;
+    u_short    data;
+    device_reg_t *reg;
+
+    ENTER_INTR("qla1280_intr_handler");
+    COMTRACE('I')
+    ha = (scsi_qla_host_t *) dev_id;
+    if(!ha)
+    {
+        printk(KERN_INFO "scsi(): Interrupt with NULL host ptr\n");
+        COMTRACE('X')
+        return;
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
+    spin_lock_irqsave(&io_request_lock, cpu_flags);
+    if(test_and_set_bit(QLA1280_IN_ISR_BIT, &ha->flags))
+    {
+        COMTRACE('X')
+        return;
+    }
+    ha->isr_count++;
+    reg = ha->iobase;
+     /* disable our interrupt. */
+    WRT_REG_WORD(&reg->ictrl, 0); 
+    data = qla1280_debounce_register(&reg->istatus);
+    /* Check for pending interrupts. */
+    if ( !(data & RISC_INT) )
+    {
+        /* spurious interrupts can happen legally */
+        DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no));
+        COMTRACE('X')
+    }
+    else
+      qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    if (ha->done_q_first)
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+
+    clear_bit(QLA1280_IN_ISR_BIT, &ha->flags);
+    spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+#else  /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) */
+
+    if( test_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags) )
+    {
+          COMTRACE('X')
+          printk(KERN_INFO "scsi(%d): Already in interrupt - returning \n", (int)ha->host_no);
+          return;
+    }
+    set_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags);
+    ha->isr_count++;
+    reg = ha->iobase;
+     /* disable our interrupt. */
+    WRT_REG_WORD(&reg->ictrl, 0); 
+
+    data = qla1280_debounce_register(&reg->istatus);
+    /* Check for pending interrupts. */
+    if ( !(data & RISC_INT) )
+    {
+        /* spurious interrupts can happen legally */
+        DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no));
+        COMTRACE('X')
+    }
+    else
+     qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+
+    /* if no work to do then call the SCSI mid-level right away */
+    if( ha->done_q_first )
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+
+    /* Schedule the DPC routine */
+    if (ha->flags.isp_abort_needed || ha->flags.reset_marker ||
+            ha->done_q_first        )
+        {
+            ha->run_qla_bh.data = (void *) ha;
+            ha->run_qla_bh.routine = qla1280_do_dpc; 
+
+             COMTRACE('P') 
+            queue_task_irq(&ha->run_qla_bh,&tq_scheduler); 
+            ha->flags.dpc_sched = TRUE;
+        }
+        clear_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags);
+#endif
+     /* enable our interrupt. */
+        WRT_REG_WORD(&reg->ictrl, ISP_EN_INT + ISP_EN_RISC);
+
+        COMTRACE('i')  
+        LEAVE_INTR("qla1280_intr_handler");
+}
+
+/**************************************************************************
+ *   qla1280_do_dpc
+ *
+ * Description:
+ * This routine is a task that is schedule by the interrupt handler 
+ * to perform the background processing for interrupts.  We put it 
+ * on a task queue that is consumed whenever the scheduler runs; that's
+ * so you can do anything (i.e. put the process to sleep etc).  In fact, the 
+ * mid-level tries to sleep when it reaches the driver threshold 
+ * "host->can_queue". This can cause a panic if we were in our interrupt
+ * code .
+ **************************************************************************/
+void qla1280_do_dpc(void *p)
+{
+    scsi_qla_host_t *ha = (scsi_qla_host_t *) p;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+    COMTRACE('p')  
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    spin_lock_irqsave(&io_request_lock, cpu_flags);
+#endif
+    if (ha->flags.isp_abort_needed)
+        qla1280_abort_isp(ha);
+
+    if (ha->flags.reset_marker)
+        qla1280_rst_aen(ha);
+
+    if (ha->done_q_first)
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    ha->flags.dpc_sched = FALSE;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+#endif
+}
+
+/**************************************************************************
+ *   qla1280_device_queue_depth
+ *
+ * Description:
+ *   Determines the queue depth for a given device.  There are two ways
+ *   a queue depth can be obtained for a tagged queueing device.  One
+ *   way is the default queue depth which is determined by whether
+ *   If it is defined, then it is used
+ *   as the default queue depth.  Otherwise, we use either 4 or 8 as the
+ *   default queue depth (dependent on the number of hardware SCBs).
+ **************************************************************************/
+STATIC void qla1280_device_queue_depth(scsi_qla_host_t *p, Scsi_Device *device)
+{
+    int default_depth = 3;
+    int bus = device->channel;
+    int target = device->id;
+
+    device->queue_depth = default_depth;
+
+    if (device->tagged_supported &&
+        (p->bus_settings[bus].qtag_enables & (BIT_0 << target)) )
+    {
+        device->tagged_queue = 1;
+        device->current_tag = 0;
+        device->queue_depth = p->bus_settings[bus].hiwat; 
+        /* device->queue_depth = 20; */
+        printk(KERN_INFO "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue depth %d.\n",
+                (int)p->host_no, device->channel, device->id,
+                device->lun, device->queue_depth);
+    }
+    qla12160_get_target_parameters(p, bus, target, device->lun);
+
+}
+
+/**************************************************************************
+ *   qla1280_select_queue_depth
+ *
+ *   Sets the queue depth for each SCSI device hanging off the input
+ *   host adapter.  We use a queue depth of 2 for devices that do not
+ *   support tagged queueing.
+ **************************************************************************/
+STATIC void
+qla1280_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs)
+{
+    Scsi_Device *device;
+    scsi_qla_host_t  *p = (scsi_qla_host_t *) host->hostdata;
+
+    ENTER("qla1280_select_queue_depth");
+    for (device = scsi_devs; device != NULL; device = device->next)
+    {
+        if (device->host == host)
+            qla1280_device_queue_depth(p, device);
+    }
+    LEAVE("qla1280_select_queue_depth");
+}
+
+/*--------------------------**
+** Driver Support Routines  **
+**--------------------------*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+/*
+ * mdelay
+ *      Delay in milliseconds 
+ *
+ * Input:
+ *      milliseconds  = delay 
+ */
+STATIC inline void mdelay(int milliseconds)
+{
+    int i;
+
+    for(i=0; i<milliseconds; i++)
+        udelay(1000);
+}
+#endif
+
+/*
+ * qla1280_done
+ *      Process completed commands.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_done(scsi_qla_host_t *ha, srb_t **done_q_first, srb_t **done_q_last)
+{
+    srb_t           *sp;
+    scsi_lu_t       *q;
+    uint32_t        b, t, l;
+    Scsi_Cmnd  *cmd;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+    ENTER("qla1280_done");
+    COMTRACE('D') 
+
+    DRIVER_LOCK 
+    while (*done_q_first !=  NULL)
+    {
+        /* remove command from done list */
+                sp = *done_q_first;
+        if (!(*done_q_first = sp->s_next))
+            *done_q_last = NULL;
+        else
+            (*done_q_first)->s_prev = NULL;
+                cmd = sp->cmd;
+        b = SCSI_BUS_32(cmd);
+        t = SCSI_TCN_32(cmd);
+        l = SCSI_LUN_32(cmd);
+        q = LU_Q(ha, b, t, l);
+
+        /* Decrement outstanding commands on device. */
+        if (q->q_outcnt)
+            q->q_outcnt--;
+        if (q->q_outcnt < ha->bus_settings[b].hiwat)
+        {
+            q->q_flag &= ~QLA1280_QBUSY;
+        }
+        
+        q->resp_time += jiffies - sp->r_start;                /* Lun bookkeeping information */
+        q->act_time += jiffies - sp->u_start;
+        q->io_cnt++;
+        if( sp->dir & BIT_5 )
+         q->r_cnt++;
+        else
+         q->w_cnt++;
+
+        switch ( (CMD_RESULT(cmd)>>16))
+        {
+            case DID_RESET:
+                q->q_flag &= ~QLA1280_QRESET;
+                /* Issue marker command. */
+                qla1280_marker(ha, b, t, 0, MK_SYNC_ID); 
+                break;
+            case DID_ABORT:
+                sp->flags &= ~SRB_ABORT_PENDING;
+                sp->flags |= SRB_ABORTED;
+                if (sp->flags & SRB_TIMEOUT)
+                    CMD_RESULT(sp->cmd)= DID_TIME_OUT << 16;
+                break;
+            default:
+                break;
+        }
+
+        /* Call the mid-level driver interrupt handler */
+        CMD_HANDLE(sp->cmd) = (unsigned char *) 0;
+        ha->actthreads--;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+        sti(); 
+        (*(cmd)->scsi_done)(cmd);
+        cli(); 
+#else
+        (*(cmd)->scsi_done)(cmd);
+#endif
+        qla1280_next(ha, q, b);
+    }
+    DRIVER_UNLOCK 
+
+
+    COMTRACE('d') 
+    LEAVE("qla1280_done");
+}
+
+/*
+ * Translates a ISP error to a Linux SCSI error
+ */
+STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd       *cp)
+{
+    int host_status = DID_ERROR;
+#if DEBUG_QLA1280_INTR
+    STATIC char *reason[] =
+    {
+        "DID_OK",
+                "DID_NO_CONNECT",
+                "DID_BUS_BUSY",
+                "DID_TIME_OUT",
+                "DID_BAD_TARGET",
+                "DID_ABORT",
+                "DID_PARITY",
+                "DID_ERROR",
+                "DID_RESET",
+                "DID_BAD_INTR"
+    };
+#endif /* DEBUG_QLA1280_INTR */
+
+    ENTER("qla1280_return_status");
+
+#if DEBUG_QLA1280_INTR
+    /*
+    DEBUG(printk("qla1280_return_status: compl status = 0x%04x\n", sts->comp_status));
+    */
+#endif
+    switch(sts->comp_status)
+    {
+        case CS_COMPLETE:
+            host_status = DID_OK;
+            break;
+        case CS_INCOMPLETE:
+            if (!(sts->state_flags & SF_GOT_BUS))
+                host_status = DID_NO_CONNECT;
+            else if (!(sts->state_flags & SF_GOT_TARGET))
+                host_status = DID_BAD_TARGET;
+            else if (!(sts->state_flags & SF_SENT_CDB))
+                host_status = DID_ERROR;
+            else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
+                host_status = DID_ERROR;
+            else if (!(sts->state_flags & SF_GOT_STATUS))
+                host_status = DID_ERROR;
+            else if (!(sts->state_flags & SF_GOT_SENSE))
+                host_status = DID_ERROR;
+            break;
+        case CS_RESET:
+            host_status = DID_RESET;
+            break;
+        case CS_ABORTED:
+            host_status = DID_ABORT;
+            break;
+        case CS_TIMEOUT:
+            host_status = DID_TIME_OUT;
+            break;
+        case CS_DATA_OVERRUN:
+#ifdef QL_DEBUG_LEVEL_2 
+            printk("Data overrun 0x%x\n",(int)sts->residual_length);
+            qla1280_print(
+                        "\n\rqla1280_isr: response packet data\n\r");
+                        qla1280_dump_buffer((caddr_t)sts,
+                        RESPONSE_ENTRY_SIZE); 
+#endif
+            host_status = DID_ERROR;
+            break;
+        case CS_DATA_UNDERRUN:
+            if ( (CMD_XFRLEN(cp) - sts->residual_length) < cp->underflow)    
+            { 
+              printk("scsi: Underflow detected - retrying command.\n");
+              host_status = DID_ERROR;
+            }
+            else
+                host_status = DID_OK;
+            break;
+        default:
+            host_status = DID_ERROR;
+            break;
+    }
+
+#if DEBUG_QLA1280_INTR
+    sprintf(debug_buff, "qla1280 ISP status: host status (%s) scsi status %x\n\r", reason[host_status], sts->scsi_status);
+    qla1280_print(debug_buff);
+#endif
+
+    LEAVE("qla1280_return_status");
+
+    return (sts->scsi_status & 0xff) | (host_status << 16);
+}
+
+/*
+ * qla1280_done_q_put
+ *      Place SRB command on done queue.
+ *
+ * Input:
+ *      sp           = srb pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_done_q_put(srb_t *sp, srb_t **done_q_first, srb_t **done_q_last)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_put_done_q");
+#endif
+    /* Place block on done queue */
+    DRIVER_LOCK
+            sp->s_next = NULL;
+    sp->s_prev = *done_q_last;
+    if (!*done_q_first)
+        *done_q_first = sp;
+    else
+        (*done_q_last)->s_next = sp;
+    *done_q_last = sp;
+
+    DRIVER_UNLOCK
+#ifdef QL_DEBUG_LEVEL_3
+            LEAVE("qla1280_put_done_q");
+#endif
+}
+
+/*
+ * qla1280_next
+ *      Retrieve and process next job in the queue.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      q  = SCSI LU pointer.
+ *      b  = SCSI bus number.
+ *      SCSI_LU_Q lock must be already obtained and no other locks.
+ *
+ * Output:
+ *      Releases SCSI_LU_Q upon exit.
+ */
+STATIC void
+qla1280_next(scsi_qla_host_t *ha, scsi_lu_t *q, uint8_t b)
+{
+    srb_t   *sp;
+    uint32_t cnt;
+    uint8_t status;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+    ENTER("qla1280_next");
+
+    DRIVER_LOCK
+    while ( ((sp = q->q_first) != NULL) &&     /* we have a queue pending */
+        !(q->q_flag &  QLA1280_QBUSY) &&      /* device not busy */
+        !ha->flags.abort_isp_active &&      /* not resetting the adapter */
+        !(q->q_flag & QLA1280_QSUSP) )      /* device not suspended */
+    {
+        /* Remove srb from SCSI LU queue. */
+        qla1280_removeq(q, sp);
+
+        DEBUG(sprintf(debug_buff,"starting request 0x%p<-(0x%p)\n\r",q,sp));
+        DEBUG(qla1280_print(debug_buff));
+        {
+            /* Set busy flag if reached high water mark. */
+            q->q_outcnt++;
+            if (q->q_outcnt >= ha->bus_settings[b].hiwat)
+                q->q_flag |= QLA1280_QBUSY;
+
+#if  QLA1280_64BIT_SUPPORT
+            if (ha->flags.enable_64bit_addressing)
+                status = qla1280_64bit_start_scsi(ha, sp);
+            else
+#endif
+                status = qla1280_32bit_start_scsi(ha, sp);
+
+            if (status)  /* if couldn't start the request */
+            {
+                if (q->q_outcnt == 1)
+                {
+                    /* Release SCSI LU queue specific lock */
+                    QLA1280_SCSILU_UNLOCK(q);
+
+                    /* Wait for 30 sec for command to be accepted. */
+                    for (cnt = 6000000; cnt; cnt--)
+                    {
+#if  QLA1280_64BIT_SUPPORT
+                        if (ha->flags.enable_64bit_addressing)
+                            status = qla1280_64bit_start_scsi(ha, sp);
+                        else
+#endif
+                            status = qla1280_32bit_start_scsi(ha, sp);
+
+                        if (!status)
+                        {
+                            break;
+                        }
+
+                        /* Go check for pending interrupts. */
+                        qla1280_poll(ha);
+
+                        SYS_DELAY(5);  /* 10 */
+                    }
+                    if (!cnt)
+                    {
+                        /* Set timeout status */
+                        CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16;
+
+#if WATCHDOGTIMER
+                        /* Remove command from watchdog queue. */
+                        if (sp->flags & SRB_WATCHDOG)
+                            qla1280_timeout_remove(ha, sp);
+#endif
+                        COMTRACE('M') 
+                        CMD_HANDLE(sp->cmd) = (unsigned char *) 0;
+
+                        /* Call the mid-level driver interrupt handler */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+                        sti(); 
+                        (*(sp->cmd)->scsi_done)(sp->cmd);
+                        cli(); 
+#else
+                        (*(sp->cmd)->scsi_done)(sp->cmd);
+#endif
+
+                        /* Acquire LU queue specific lock */
+                        QLA1280_SCSILU_LOCK(q);
+
+                        if (q->q_outcnt)
+                            q->q_outcnt--;
+                    }
+                    else
+                        /* Acquire LU queue specific lock */
+                        QLA1280_SCSILU_LOCK(q);
+                }
+                else
+                {   /* Place request back on top of device queue. */
+                    qla1280_putq_t(q, sp);
+
+                    if (q->q_outcnt)
+                        q->q_outcnt--;
+                    if (q->q_outcnt < ha->bus_settings[b].hiwat)
+                        q->q_flag &= ~QLA1280_QBUSY;
+                    break;
+                }
+            }
+        }
+    }
+   DRIVER_UNLOCK
+
+    /* Release SCSI LU queue specific lock */
+    QLA1280_SCSILU_UNLOCK(q);
+
+    LEAVE("qla1280_next");
+}
+
+/*
+ * qla1280_putq_t
+ *      Add the standard SCB job to the top of standard SCB commands.
+ *
+ * Input:
+ *      q  = SCSI LU pointer.
+ *      sp = srb pointer.
+ *      SCSI_LU_Q lock must be already obtained.
+ */
+STATIC void
+qla1280_putq_t(scsi_lu_t *q, srb_t *sp)
+{
+    srb_t *srb_p;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_putq_t");
+#endif
+    DRIVER_LOCK
+    DEBUG(sprintf(debug_buff,"Adding to device 0x%p<-(0x%p)\n\r",q,sp));
+    DEBUG(qla1280_print(debug_buff));
+    sp->s_next = NULL;
+    if (!q->q_first)                  /* If queue empty */
+    {
+        sp->s_prev = NULL;
+        q->q_first = sp;
+        q->q_last = sp;
+    }
+    else
+    {      
+        srb_p = q->q_first;
+        while (srb_p )
+            srb_p = srb_p->s_next;
+
+        if (srb_p)
+        {
+            sp->s_prev = srb_p->s_prev;
+            if (srb_p->s_prev)
+                srb_p->s_prev->s_next = sp;
+            else
+                q->q_first = sp;
+            srb_p->s_prev = sp;
+            sp->s_next = srb_p;
+        }
+        else
+        {
+            sp->s_prev = q->q_last;
+            q->q_last->s_next = sp;
+            q->q_last = sp;
+        }
+    }
+
+    DRIVER_UNLOCK
+#ifdef QL_DEBUG_LEVEL_3
+            LEAVE("qla1280_putq_t");
+#endif
+}
+
+/*
+ * qla1280_removeq
+ *      Function used to remove a command block from the
+ *      LU queue.
+ *
+ * Input:
+ *      q  = SCSI LU pointer.
+ *      sp = srb pointer.
+ *      SCSI_LU_Q lock must be already obtained.
+ */
+STATIC void
+qla1280_removeq(scsi_lu_t *q, srb_t *sp)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    DEBUG(sprintf(debug_buff,"Removing from device_q (0x%p)->(0x%p)\n\r",q,sp));
+    DEBUG(qla1280_print(debug_buff));
+    DRIVER_LOCK
+            if (sp->s_prev)
+    {
+        if ((sp->s_prev->s_next = sp->s_next) != NULL)
+            sp->s_next->s_prev = sp->s_prev;
+        else
+            q->q_last = sp->s_prev;
+    }
+    else if (!(q->q_first = sp->s_next))
+        q->q_last = NULL;
+    else
+        q->q_first->s_prev = NULL;
+    DRIVER_UNLOCK
+}
+
+/*
+* qla1280_mem_alloc
+*      Allocates adapter memory.
+*
+* Returns:
+*      0  = success.
+*      1  = failure.
+*/
+STATIC uint8_t
+qla1280_mem_alloc(scsi_qla_host_t *ha)
+{
+
+	uint8_t   status = 1;
+
+#ifdef QL_DEBUG_LEVEL_3
+	ENTER("qla1280_mem_alloc");
+#endif
+
+#ifdef DYNAMIC_MEM_ALLOC
+	ha->request_ring = qla1280_alloc_phys(REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT,
+	&ha->request_dma);
+	if(ha->request_ring) {
+		ha->response_ring = qla1280_alloc_phys(RESPONSE_ENTRY_SIZE * RESPONSE_ENTRY_CNT,
+		&ha->response_dma);
+		if(ha->response_ring) {
+			status = 0;
+		}
+	}
+#else
+	ha->request_ring = &ha->req[0];
+	ha->request_dma = VIRT_TO_BUS(&ha->req[0]);
+	ha->response_ring = &ha->res[0];
+	ha->response_dma = VIRT_TO_BUS(&ha->res[0]);
+	status = 0;
+#endif
+
+	if(status) {
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+		qla1280_print("qla1280_mem_alloc: **** FAILED ****\n");
+#endif
+	}
+#ifdef QL_DEBUG_LEVEL_3
+	else
+		LEAVE("qla1280_mem_alloc");
+#endif
+	return(status);
+}
+
+/*
+ * qla1280_mem_free
+ *      Frees adapter allocated memory.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_mem_free(scsi_qla_host_t *ha)
+{
+    scsi_lu_t *q;
+    uint32_t  b, t, l;
+
+    ENTER("qlc1280_mem_free");
+    if (ha)
+    {
+        /* Free device queues. */
+        for (b = 0; b < MAX_BUSES; b++)
+        {
+            q = LU_Q(ha, b, ha->bus_settings[b].id, 0);
+            for (t = 0; t < MAX_TARGETS; t++)
+                for (l = 0; l < MAX_LUNS; l++)
+                    if (LU_Q(ha, b, t, l) != NULL && LU_Q(ha, b, t, l) != q)
+                        KMFREE(LU_Q(ha, b, t, l),sizeof(struct scsi_lu));
+                    KMFREE(q, sizeof(struct scsi_lu));
+        }
+        for( b =0; b < MAX_EQ; b++ )
+            ha->dev[b] =  (scsi_lu_t  *)NULL;
+    }
+
+    LEAVE("qlc1280_mem_free");
+}
+
+
+
+
+/****************************************************************************/
+/*                QLogic ISP1280 Hardware Support Functions.                */
+/****************************************************************************/
+
+ /*
+ * qla2100_enable_intrs
+ * qla2100_disable_intrs
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      None      
+ */
+    static inline void qla1280_enable_intrs(scsi_qla_host_t *ha) {
+        device_reg_t *reg;
+
+        reg = ha->iobase;
+        ha->flags.interrupts_on = 1;
+        /* enable risc and host interrupts */
+        WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT+ ISP_EN_RISC));
+    }
+
+    static inline void qla1280_disable_intrs(scsi_qla_host_t *ha) {
+        device_reg_t *reg;
+
+        reg = ha->iobase;
+        ha->flags.interrupts_on = 0;
+        /* disable risc and host interrupts */
+        WRT_REG_WORD(&reg->ictrl, 0);
+    }
+
+/*
+ * qla1280_initialize_adapter
+ *      Initialize board.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_initialize_adapter(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg;
+    uint8_t      status;
+    /* uint8_t      cnt; */
+    uint8_t      b;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_initialize_adapter");
+#endif
+
+    /* Clear adapter flags. */
+    ha->flags.online = FALSE;
+    ha->flags.isp_abort_needed = FALSE;
+    ha->flags.disable_host_adapter = FALSE;
+    ha->flags.reset_active = FALSE;
+    ha->flags.abort_isp_active = FALSE;
+    ha->flags.watchdog_enabled = FALSE;
+
+    DEBUG(printk("Configure PCI space for adapter...\n"));
+    if (!(status = qla1280_pci_config(ha)))
+    {
+        reg = ha->iobase;
+
+        /* Disable ISP interrupts. */
+        WRT_REG_WORD(&reg->ictrl, 0);
+
+        /* Insure mailbox registers are free. */
+        WRT_REG_WORD(&reg->semaphore, 0);
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
+
+        /* If firmware needs to be loaded */
+        if (qla1280_verbose)
+         printk("scsi(%d): Determining if RISC is loaded...\n",(int)ha->host_no);
+        if (qla1280_isp_firmware(ha))
+        {
+            if (qla1280_verbose)
+              printk("scsi(%d): Verifying chip...\n",(int)ha->host_no);
+            if (!(status = qla1280_chip_diag(ha)))
+            {
+                if (qla1280_verbose)
+                  printk("scsi(%d): Setup chip...\n",(int)ha->host_no);
+                status = qla1280_setup_chip(ha); 
+            }
+        }
+
+        if (!status)
+        {
+            /* Setup adapter based on NVRAM parameters. */
+            if (qla1280_verbose)
+              printk("scsi(%d): Configure NVRAM parameters...\n",(int)ha->host_no);
+            qla1280_nvram_config(ha);
+
+            if (!ha->flags.disable_host_adapter &&
+                !qla1280_init_rings(ha))
+            {
+                /* Issue SCSI reset. */
+                for (b = 0; b < ha->ports; b++)
+                    if (!ha->bus_settings[b].disable_scsi_reset)
+                    {
+                      /* dg 03/13 if we can't reset twice then bus is dead */
+                        if( qla1280_bus_reset(ha, b) )
+                           if( qla1280_bus_reset(ha, b) )
+                           {
+                               ha->bus_settings[b].scsi_bus_dead = TRUE;
+                            }
+                    }
+
+                    do
+                    {
+                        /* Issue marker command. */
+                        ha->flags.reset_marker = FALSE;
+                        for (b = 0; b < ha->ports; b++)
+                        {
+                            ha->bus_settings[b].reset_marker = FALSE;
+                            qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+                        }
+                    }while (ha->flags.reset_marker);
+
+                    ha->flags.online = TRUE;
+
+                    /* Enable host adapter target mode. */
+                    for (b = 0; b < ha->ports; b++)
+                    {
+                        if (!(status = qla1280_enable_tgt(ha, b)))
+                        {
+                            /* for (cnt = 0; cnt < MAX_LUNS; cnt++)
+                            {
+                                qla1280_enable_lun(ha, b, cnt);
+                                 qla1280_poll(ha);
+                            }*/
+                        }
+                        else
+                            break;
+                    }
+            }
+            else
+                status = 1;
+        }
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_initialize_adapter: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_initialize_adapter");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_enable_tgt
+ *      Enable target mode.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI bus number.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_enable_tgt(scsi_qla_host_t *ha, uint8_t b)
+{
+    uint8_t     status = 0;
+    /*  uint16_t    mb[MAILBOX_REGISTER_COUNT]; */
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_enable_tgt: entered\n\r");
+#endif
+
+    /* Enable target mode. */
+    /*
+    mb[0] = MBC_ENABLE_TARGET_MODE;
+    mb[1] = BIT_15;
+    mb[2] = (uint16_t)(b << 15);
+    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+    */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_enable_tgt: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_enable_tgt: exiting normally\n\r");
+#endif
+    return(status);
+}
+
+/*
+ * ISP Firmware Test
+ *      Checks if present version of RISC firmware is older than
+ *      driver firmware.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = firmware does not need to be loaded.
+ */
+STATIC uint8_t
+qla1280_isp_firmware(scsi_qla_host_t *ha)
+{
+    nvram_t     *nv    = (nvram_t *)ha->response_ring; 
+    uint16_t    *wptr;
+    uint8_t     chksum;
+    uint8_t     cnt;
+    uint8_t     status = 0;    /* dg 2/27 always loads RISC */
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+    ENTER("qla1280_isp_firmware");
+
+    /* Verify valid NVRAM checksum. */
+    wptr = (uint16_t *)ha->response_ring;
+    DEBUG(printk("qla1280_isp_firmware: Reading NVRAM\n"));
+    chksum = 0;
+    for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++)
+    {
+        *wptr = qla1280_get_nvram_word(ha, cnt);
+        chksum += (uint8_t)*wptr;
+        chksum += (uint8_t)(*wptr >> 8);
+        wptr++;
+    }
+    DEBUG(printk("qla1280_isp_firmware: Completed Reading NVRAM\n"));
+
+#if defined(QL_DEBUG_LEVEL_3)
+    sprintf(debug_buff,"qla1280_isp_firmware: NVRAM Magic ID= %c %c %c\n\r",(char *) nv->id[0],nv->id[1],nv->id[2]);
+    qla1280_print(debug_buff);
+#endif
+
+    /* Bad NVRAM data, load RISC code. */
+    if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
+        nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1)
+    {
+        printk(KERN_INFO "qla1280_isp_firmware: Bad checksum or magic number or version in NVRAM.\n");
+        ha->flags.disable_risc_code_load = FALSE;
+    }
+    else
+        ha->flags.disable_risc_code_load = nv->cntr_flags_1.disable_loading_risc_code;
+
+    if (ha->flags.disable_risc_code_load)
+    {
+#if defined(QL_DEBUG_LEVEL_3)
+        qla1280_print("qla1280_isp_firmware: Telling RISC to verify checksum of loaded BIOS code.\n\r");
+#endif
+        /* Verify checksum of loaded RISC code. */
+        mb[0] = MBC_VERIFY_CHECKSUM;
+        /* mb[1] = ql12_risc_code_addr01; */
+        mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+
+        if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0])))
+        {
+            /* Start firmware execution. */
+#if defined(QL_DEBUG_LEVEL_3)
+            qla1280_print("qla1280_isp_firmware: Startng F/W execution.\n\r");
+#endif
+            mb[0] = MBC_EXECUTE_FIRMWARE;
+            /* mb[1] = ql12_risc_code_addr01; */
+            mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+            qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+        }
+        else
+            printk(KERN_INFO "qla1280: RISC checksum failed.\n");
+    }
+    else
+    {
+        DEBUG(printk("qla1280: NVRAM configured to load RISC load.\n"));
+        status = 1;
+     }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print(
+                "qla1280_isp_firmware: **** Load RISC code ****\n\r");
+#endif
+    LEAVE("qla1280_isp_firmware");
+    return(status);
+}
+
+/*
+ * PCI configuration
+ *      Setup device PCI configuration registers.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_pci_config(scsi_qla_host_t *ha)
+{
+    uint8_t      status = 1;
+    uint32_t     command;
+#if MEMORY_MAPPED_IO
+    uint32_t  page_offset, base;
+    uint32_t   mmapbase;
+#endif
+    config_reg_t *creg = 0;
+    uint16_t     buf_wd;
+
+    ENTER("qla1280_pci_config");
+
+    /* Get command register. */
+    if (pci_read_config_word(ha->pdev,OFFSET(creg->command), &buf_wd) == PCIBIOS_SUCCESSFUL)
+    {
+        command = buf_wd;
+        /*
+        * Set Bus Master Enable, Memory Address Space Enable and
+        * reset any error bits.
+        */
+        buf_wd &= ~0x7;
+#if MEMORY_MAPPED_IO
+        DEBUG(printk("qla1280: MEMORY MAPPED IO is enabled.\n"));
+        buf_wd |= BIT_2 + BIT_1 + BIT_0;
+#else
+        buf_wd |= BIT_2 + BIT_0;
+#endif
+        if( pci_write_config_word(ha->pdev,OFFSET(creg->command), buf_wd) )
+        {
+            printk(KERN_WARNING "qla1280: Could not write config word.\n");
+        }
+        /* Get expansion ROM address. */
+        if (pci_read_config_word(ha->pdev,OFFSET(creg->expansion_rom), &buf_wd) == PCIBIOS_SUCCESSFUL)
+        {
+            /* Reset expansion ROM address decode enable. */
+            buf_wd &= ~BIT_0;
+            if (pci_write_config_word(ha->pdev,OFFSET(creg->expansion_rom), buf_wd) == PCIBIOS_SUCCESSFUL)
+            {
+#if MEMORY_MAPPED_IO
+                /* Get memory mapped I/O address. */
+                pci_read_config_dword(ha->pdev,OFFSET(cfgp->mem_base_addr), &mmapbase);
+                mmapbase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+                /* Find proper memory chunk for memory map I/O reg. */
+                base = mmapbase & PAGE_MASK;
+                page_offset = mmapbase - base;
+                /* Get virtual address for I/O registers. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+                ha->mmpbase = ioremap_nocache(base, page_offset + 256);
+#else
+                ha->mmpbase = vremap(base,page_offset + 256);
+#endif
+                if( ha->mmpbase )
+                {
+                    ha->mmpbase += page_offset;
+                    /* ha->iobase = ha->mmpbase; */
+                    status = 0;
+                }
+#else /* MEMORY_MAPPED_IO */
+                status = 0;
+#endif /* MEMORY_MAPPED_IO */
+            }
+        }
+    }
+
+    LEAVE("qla1280_pci_config");
+    return(status);
+}
+
+/*
+ * Chip diagnostics
+ *      Test chip for proper operation.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_chip_diag(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg   = ha->iobase;
+    uint8_t      status = 0;
+    uint16_t     data;
+    uint32_t     cnt;
+    uint16_t     mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    sprintf(debug_buff, "qla1280_chip_diag: testing device at 0x%p \n\r",&reg->id_l);
+    qla1280_print(debug_buff);
+#endif
+
+    /* Soft reset chip and wait for it to finish. */
+    WRT_REG_WORD(&reg->ictrl, ISP_RESET); 
+    data = qla1280_debounce_register(&reg->ictrl);
+    for (cnt = 6000000; cnt && data & ISP_RESET; cnt--)
+    {
+        SYS_DELAY(5);
+        data = RD_REG_WORD(&reg->ictrl);
+    }
+    if (cnt)
+    {
+        /* Reset register not cleared by chip reset. */
+#if defined(QL_DEBUG_LEVEL_3)
+        qla1280_print("qla1280_chip_diag: reset register cleared by chip reset\n\r");
+#endif
+        WRT_REG_WORD(&reg->cfg_1, 0);
+
+        /* Reset RISC and disable BIOS which
+        allows RISC to execute out of RAM. */
+        WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
+        WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+        WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
+        data = qla1280_debounce_register(&reg->mailbox0);
+        for (cnt = 6000000; cnt && data == MBS_BUSY; cnt--)
+        {
+            SYS_DELAY(5);
+            data = RD_REG_WORD(&reg->mailbox0);
+        }
+
+        if (cnt)
+        {
+            /* Check product ID of chip */
+#if defined(QL_DEBUG_LEVEL_3)
+            qla1280_print("qla1280_chip_diag: Checking product ID of chip\n\r");
+#endif
+            if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
+                (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
+                RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
+                RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
+                RD_REG_WORD(&reg->mailbox4) != PROD_ID_4)
+            {
+                printk(KERN_INFO "qla1280: Wrong product ID = 0x%x,0x%x,0x%x,0x%x\n",
+                        RD_REG_WORD(&reg->mailbox1),
+                        RD_REG_WORD(&reg->mailbox2),
+                        RD_REG_WORD(&reg->mailbox3),
+                        RD_REG_WORD(&reg->mailbox4) );
+                status = 1;
+            }
+            else
+            {
+                DEBUG(printk("qla1280_chip_diag: Checking mailboxes of chip\n"));
+                /* Wrap Incoming Mailboxes Test. */
+                mb[0] = MBC_MAILBOX_REGISTER_TEST;
+                mb[1] = 0xAAAA;
+                mb[2] = 0x5555;
+                mb[3] = 0xAA55;
+                mb[4] = 0x55AA;
+                mb[5] = 0xA5A5;
+                mb[6] = 0x5A5A;
+                mb[7] = 0x2525;
+                if (!(status = qla1280_mailbox_command(ha,
+                    (BIT_7|BIT_6|BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0),
+                    &mb[0])))
+                {
+                    if (mb[1] != 0xAAAA || mb[2] != 0x5555 ||
+                        mb[3] != 0xAA55 || mb[4] != 0x55AA)
+                        status = 1;
+                    if (mb[5] != 0xA5A5 || mb[6] != 0x5A5A ||
+                        mb[7] != 0x2525)
+                        status = 1;
+                    if( status == 1 )
+                        printk(KERN_INFO "qla1280: Failed mailbox check\n");
+                }
+            }
+        }
+        else
+            status = 1;
+    }
+    else
+        status = 1;
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_chip_diag: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_chip_diag: exiting normally\n\r");
+#endif
+    return(status);
+}
+
+/*
+ * Setup chip
+ *      Load and start RISC firmware.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_setup_chip(scsi_qla_host_t *ha)
+{
+    uint8_t      status = 0;
+    uint16_t     risc_address;
+    uint16_t     *risc_code_address;
+    long         risc_code_size;
+    uint16_t     mb[MAILBOX_REGISTER_COUNT];
+#ifdef QLA1280_UNUSED
+    int i;
+#endif
+    uint16_t     cnt;
+    int          num;
+    uint8_t    *tbuf, *sp;
+    u_long     p_tbuf;
+    int i;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_setup_chip");
+#endif
+
+	if( (tbuf = (uint8_t *)KMALLOC(8000) ) == NULL )
+        {
+            printk("setup_chip: couldn't alloacte memory\n");
+            return(1);
+        }
+        p_tbuf =  VIRT_TO_BUS(tbuf);
+    /* Load RISC code. */
+    /* 
+    risc_address      = ql12_risc_code_addr01;
+    risc_code_address = &ql12_risc_code01[0];
+    risc_code_size    = ql12_risc_code_length01;
+    */
+    risc_address = *QLBoardTbl[ha->devnum].fwstart;  
+    risc_code_address = QLBoardTbl[ha->devnum].fwcode;  
+    risc_code_size    = (long)(*QLBoardTbl[ha->devnum].fwlen & 0xffff);  
+
+    DEBUG(printk("qla1280: DMAing RISC code (%d) words.\n",(int)risc_code_size));
+    DEBUG(sprintf(debug_buff,"qla1280_setup_chip:  Loading RISC code size =(%ld).\n\r",risc_code_size);)
+    DEBUG(qla1280_print(debug_buff));
+    num =0;
+    while (risc_code_size > 0 && !status)
+    {
+        cnt = 2000 >> 1;
+
+        if ( cnt > risc_code_size ) 
+            cnt = risc_code_size;
+
+        DEBUG(sprintf(debug_buff,"qla1280_setup_chip:  loading risc @ =(0x%p),%d,%d(0x%x).\n\r",risc_code_address,cnt,num,risc_address);)
+        DEBUG(qla1280_print(debug_buff));
+        printk("qla1280_setup_chip:  loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address);
+        BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, (cnt <<1));
+        mb[0] = MBC_LOAD_RAM; 
+        /* mb[0] = MBC_LOAD_RAM_A64; */
+        mb[1] = risc_address;
+        mb[4] = cnt;
+        mb[3] = (uint16_t)  ha->request_dma & 0xffff;
+        mb[2] = (uint16_t) (ha->request_dma >> 16) & 0xffff;
+        mb[7] = (uint16_t) (MS_64BITS(ha->request_dma) & 0xffff);
+        mb[6] = (uint16_t) (MS_64BITS(ha->request_dma) >> 16) & 0xffff;
+        printk("qla1280_setup_chip: op=%d  0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3]);
+        if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
+            &mb[0]))  )
+        {
+            printk("Failed to load partial segment of f/w\n");
+            break;
+        }
+        /* dump it back */
+
+#if 0
+        mb[0] = MBC_DUMP_RAM_A64;
+        mb[1] = risc_address;
+        mb[4] = cnt;
+        mb[3] = (uint16_t)  p_tbuf & 0xffff;
+        mb[2] = (uint16_t) (p_tbuf >> 16) & 0xffff;
+        mb[7] = (uint16_t) (p_tbuf >> 32) & 0xffff;
+        mb[6] = (uint16_t) (p_tbuf >> 48) & 0xffff;
+
+        if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
+            &mb[0]))  )
+        {
+            printk("Failed to dump partial segment of f/w\n");
+            break;
+        }
+        sp =  (uint8_t *)ha->request_ring;
+        for (i = 0; i < (cnt<< 1) ; i++)
+        {
+            if( tbuf[i] != sp[i] )
+            {
+               printk("qla1280 : firmware compare error @ byte (0x%x)\n",i);
+                break;
+            }
+        }
+
+#endif
+        risc_address += cnt;
+        risc_code_size = risc_code_size - cnt;
+        risc_code_address = risc_code_address + cnt;
+        num++;
+    }
+#ifdef QLA1280_UNUSED
+    DEBUG(ql_debug_print = 0;)
+    {
+        for (i = 0; i < ql12_risc_code_length01; i++)
+        {
+            mb[0] = 0x4;
+            mb[1] = ql12_risc_code_addr01 + i;
+            mb[2] = ql12_risc_code01[i];
+
+            status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0,
+                    &mb[0]);
+            if (status)
+            {
+                printk("qla1280 : firmware load failure\n");
+                break;
+            }
+
+            mb[0] = 0x5;
+            mb[1] = ql12_risc_code_addr01 + i;
+            mb[2] = 0;
+
+            status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0,
+                    &mb[0]);
+            if (status)
+            {
+                printk("qla1280 : firmware dump failure\n");
+                break;
+            }
+            if( mb[2] != ql12_risc_code01[i] )
+                printk("qla1280 : firmware compare error @ (0x%x)\n",ql12_risc_code_addr01+i);
+        }
+    }
+    DEBUG(ql_debug_print = 1;)
+#endif
+
+    /* Verify checksum of loaded RISC code. */
+    if (!status)
+    {
+        DEBUG(printk("qla1280_setup_chip: Verifying checksum of loaded RISC code.\n");)
+        mb[0] = MBC_VERIFY_CHECKSUM;
+        /* mb[1] = ql12_risc_code_addr01; */
+        mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+        
+        if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0])))
+        {
+            /* Start firmware execution. */
+            DEBUG(qla1280_print("qla1280_setup_chip: start firmware running.\n\r");)
+            mb[0] = MBC_EXECUTE_FIRMWARE;
+            /* mb[1] = ql12_risc_code_addr01; */
+            mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+            qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+        }
+        else
+            printk("qla1280_setup_chip: Failed checksum.\n");
+    }
+
+	KMFREE(tbuf,8000);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_setup_chip: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_setup_chip");
+#endif
+    return(status);
+}
+
+/*
+ * Initialize rings
+ *
+ * Input:
+ *      ha                = adapter block pointer.
+ *      ha->request_ring  = request ring virtual address
+ *      ha->response_ring = response ring virtual address
+ *      ha->request_dma   = request ring physical address
+ *      ha->response_dma  = response ring physical address
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_init_rings(scsi_qla_host_t *ha)
+{
+    uint8_t     status = 0;
+    uint16_t    cnt;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_init_rings");
+#endif
+    /* Clear outstanding commands array. */
+    for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+        ha->outstanding_cmds[cnt] = 0;
+
+    /* Initialize request queue. */
+    ha->request_ring_ptr = ha->request_ring;
+    ha->req_ring_index   = 0;
+    ha->req_q_cnt        = REQUEST_ENTRY_CNT;
+    /* mb[0] = MBC_INIT_REQUEST_QUEUE; */
+    mb[0] = MBC_INIT_REQUEST_QUEUE_A64;
+    mb[1] = REQUEST_ENTRY_CNT;
+    mb[3] = (uint16_t)LS_64BITS(ha->request_dma);
+    mb[2] = (uint16_t)( LS_64BITS(ha->request_dma) >> 16);
+    mb[4] = 0;
+    mb[7] = (uint16_t)MS_64BITS(ha->request_dma);
+    mb[6] = (uint16_t)( MS_64BITS(ha->request_dma) >> 16);
+    if (!(status = qla1280_mailbox_command(ha,
+        BIT_7|BIT_6|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
+        &mb[0])))
+    {
+        /* Initialize response queue. */
+        ha->response_ring_ptr = ha->response_ring;
+        ha->rsp_ring_index    = 0;
+        /* mb[0] = MBC_INIT_RESPONSE_QUEUE; */
+        mb[0] = MBC_INIT_RESPONSE_QUEUE_A64;
+        mb[1] = RESPONSE_ENTRY_CNT;
+        mb[3] = (uint16_t)LS_64BITS(ha->response_dma);
+        mb[2] = (uint16_t)(LS_64BITS(ha->response_dma) >> 16);
+        mb[5] = 0;
+        mb[7] = (uint16_t)MS_64BITS(ha->response_dma);
+        mb[6] = (uint16_t)(MS_64BITS(ha->response_dma) >> 16);
+        status = qla1280_mailbox_command(ha,
+                BIT_7|BIT_6|BIT_5|BIT_3|BIT_2|BIT_1|BIT_0,
+                &mb[0]);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_init_rings: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_init_rings");
+#endif
+    return(status);
+}
+
+/*
+ * NVRAM configuration.
+ *
+ * Input:
+ *      ha                = adapter block pointer.
+ *      ha->request_ring  = request ring virtual address
+ *
+ * Output:
+ *      host adapters parameters in host adapter block
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_nvram_config(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg   = ha->iobase;
+    nvram_t      *nv    = (nvram_t *)ha->response_ring; 
+    uint8_t      status = 0;
+    uint32_t     b, t, l;
+    uint16_t     *wptr;
+    uint16_t     mb[MAILBOX_REGISTER_COUNT];
+    uint8_t      cnt;
+    uint8_t      chksum;
+    uint32_t     nvsize;
+
+#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
+    uint8_t      saved_print_status = ql_debug_print;
+#endif
+    ENTER("qla1280_nvram_config");
+#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
+    ql_debug_print = FALSE;
+#endif
+
+    /* Verify valid NVRAM checksum. */
+#if  USE_NVRAM_DEFAULTS
+    chksum = 1;
+#else
+    wptr = (uint16_t *)ha->response_ring;
+    chksum = 0;
+    if( ha->device_id == QLA12160_DEVICE_ID ||  
+        ha->device_id == QLA10160_DEVICE_ID )  
+    nvsize = sizeof(nvram160_t)/2;
+    else
+    nvsize = sizeof(nvram_t)/2;
+    for( cnt = 0; cnt < nvsize; cnt++ ) 
+    {
+        *wptr = qla1280_get_nvram_word(ha, cnt); 
+        chksum += (uint8_t)*wptr;
+        chksum += (uint8_t)(*wptr >> 8);
+        wptr++;
+    }
+#endif
+
+
+    /* Bad NVRAM data, set defaults parameters. */
+    if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
+        nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1)
+    {
+#if  USE_NVRAM_DEFAULTS
+        DEBUG(printk("Using defaults for NVRAM\n"));
+#else
+        DEBUG(printk("Using defaults for NVRAM: \n"));
+        DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n",chksum,nv->id[0],nv->version));
+#if defined(QL_DEBUG_LEVEL_3)
+        /* ql_debug_print = 1;
+        qla1280_dump_buffer((caddr_t)ha->response_ring, REQUEST_ENTRY_SIZE);
+        ql_debug_print = 0; */
+#endif
+                wptr = (uint16_t *)ha->response_ring;
+        for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++)
+            *wptr++ = 0;
+#endif
+
+
+        /* nv->cntr_flags_1.disable_loading_risc_code = 1; */
+        nv->firmware_feature.w = BIT_0;
+        nv->termination.f.scsi_bus_0_control = 3;
+        nv->termination.f.scsi_bus_1_control = 3;
+        nv->termination.f.auto_term_support = 1;
+
+        for (b = 0; b < MAX_BUSES; b++)
+        {
+            nv->bus[b].config_1.initiator_id = 7;
+            nv->bus[b].bus_reset_delay = 5;
+            nv->bus[b].config_2.async_data_setup_time = 9;
+            nv->bus[b].config_2.req_ack_active_negation = 1;
+            nv->bus[b].config_2.data_line_active_negation = 1;
+            nv->bus[b].selection_timeout = 250;
+            nv->bus[b].max_queue_depth = 256;
+
+            for (t = 0; t < MAX_TARGETS; t++)
+            {
+                nv->bus[b].target[t].parameter.f.auto_request_sense = 1;
+                nv->bus[b].target[t].parameter.f.disconnect_allowed = 1;
+                nv->bus[b].target[t].parameter.f.tag_queuing = 1;
+                nv->bus[b].target[t].flags.device_enable = 1;
+            }
+        }
+
+#if  USE_NVRAM_DEFAULTS
+        status = 0;
+#else
+        status = 1;
+#endif
+    }
+    else
+    {
+        /* Always force AUTO sense for LINUX SCSI */
+        for (b = 0; b < MAX_BUSES; b++)
+            for (t = 0; t < MAX_TARGETS; t++)
+            {
+                nv->bus[b].target[t].parameter.f.auto_request_sense = 1;
+            }
+    }
+#if  DEBUG_PRINT_NVRAM
+    ql_debug_print = 1;
+    sprintf(debug_buff,"qla1280 : initiator scsi id bus[0]=%d\n\r",
+            nv->bus[0].config_1.initiator_id);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : initiator scsi id bus[1]=%d\n\r",
+            nv->bus[1].config_1.initiator_id);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : bus reset delay[0]=%d\n\r",
+            nv->bus[0].bus_reset_delay);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : bus reset delay[1]=%d\n\r",
+            nv->bus[1].bus_reset_delay);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : retry count[0]=%d\n\r",
+            nv->bus[0].retry_count);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : retry delay[0]=%d\n\r",
+            nv->bus[0].retry_delay);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : retry count[1]=%d\n\r",
+            nv->bus[1].retry_count);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : retry delay[1]=%d\n\r",
+            nv->bus[1].retry_delay);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : async data setup time[0]=%d\n\r",
+            nv->bus[0].config_2.async_data_setup_time);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : async data setup time[1]=%d\n\r",
+            nv->bus[1].config_2.async_data_setup_time);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : req/ack active negation[0]=%d\n\r",
+            nv->bus[0].config_2.req_ack_active_negation);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : req/ack active negation[1]=%d\n\r",
+            nv->bus[1].config_2.req_ack_active_negation);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : data line active negation[0]=%d\n\r",
+            nv->bus[0].config_2.data_line_active_negation);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : data line active negation[1]=%d\n\r",
+            nv->bus[1].config_2.data_line_active_negation);
+    qla1280_print(debug_buff);
+
+
+    sprintf(debug_buff,"qla1280 : disable loading risc code=%d\n\r",
+            nv->cntr_flags_1.disable_loading_risc_code);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : enable 64bit addressing=%d\n\r",
+            nv->cntr_flags_1.enable_64bit_addressing);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : selection timeout limit[0]=%d\n\r",
+            nv->bus[0].selection_timeout);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : selection timeout limit[1]=%d\n\r",
+            nv->bus[1].selection_timeout);
+
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : max queue depth[0]=%d\n\r",
+            nv->bus[0].max_queue_depth);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : max queue depth[1]=%d\n\r",
+            nv->bus[1].max_queue_depth);
+    qla1280_print(debug_buff);
+#endif
+
+    DEBUG(ql_debug_print = 0;)
+
+    /* Disable RISC load of firmware. */
+    ha->flags.disable_risc_code_load =
+            nv->cntr_flags_1.disable_loading_risc_code;
+    /* Enable 64bit addressing. */
+    ha->flags.enable_64bit_addressing =
+            nv->cntr_flags_1.enable_64bit_addressing;
+
+    /* Set ISP hardware DMA burst */
+    mb[0] = nv->isp_config.c;
+    WRT_REG_WORD(&reg->cfg_1, mb[0]);
+
+    /* Set SCSI termination. */
+    WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
+    mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
+    WRT_REG_WORD(&reg->gpio_data, mb[0]);
+
+    /* ISP parameter word. */
+    mb[0] = MBC_SET_SYSTEM_PARAMETER;
+    mb[1] = nv->isp_parameter;
+    status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+    /* Firmware feature word. */
+    mb[0] = MBC_SET_FIRMWARE_FEATURES;
+    mb[1] = nv->firmware_feature.w & (BIT_1|BIT_0);
+    status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+    /* Retry count and delay. */
+    mb[0] = MBC_SET_RETRY_COUNT;
+    mb[1] = nv->bus[0].retry_count;
+    mb[2] = nv->bus[0].retry_delay;
+    mb[6] = nv->bus[1].retry_count;
+    mb[7] = nv->bus[1].retry_delay;
+    status |= qla1280_mailbox_command(ha, BIT_7|BIT_6|BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* ASYNC data setup time. */
+    mb[0] = MBC_SET_ASYNC_DATA_SETUP;
+    mb[1] = nv->bus[0].config_2.async_data_setup_time;
+    mb[2] = nv->bus[1].config_2.async_data_setup_time;
+    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* Active negation states. */
+    mb[0] = MBC_SET_ACTIVE_NEGATION;
+    mb[1] = 0;
+    if (nv->bus[0].config_2.req_ack_active_negation)
+        mb[1] |= BIT_5;
+    if (nv->bus[0].config_2.data_line_active_negation)
+        mb[1] |= BIT_4;
+    mb[2] = 0;
+    if (nv->bus[1].config_2.req_ack_active_negation)
+        mb[2] |= BIT_5;
+    if (nv->bus[1].config_2.data_line_active_negation)
+        mb[2] |= BIT_4;
+    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* Selection timeout. */
+    mb[0] = MBC_SET_SELECTION_TIMEOUT;
+    mb[1] = nv->bus[0].selection_timeout;
+    mb[2] = nv->bus[1].selection_timeout;
+    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    for (b = 0; b < ha->ports; b++)
+    {
+        /* SCSI Reset Disable. */
+        ha->bus_settings[b].disable_scsi_reset = nv->bus[b].config_1.scsi_reset_disable;
+
+        /* Initiator ID. */
+        ha->bus_settings[b].id = nv->bus[b].config_1.initiator_id;
+        mb[0] = MBC_SET_INITIATOR_ID;
+        mb[1] = b ? ha->bus_settings[b].id | BIT_7 : ha->bus_settings[b].id;
+        status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+        /* Reset Delay. */
+        ha->bus_settings[b].bus_reset_delay = nv->bus[b].bus_reset_delay;
+
+        /* Command queue depth per device. */
+        ha->bus_settings[b].hiwat = nv->bus[b].max_queue_depth - 1;
+
+        /* Set target parameters. */
+        for (t = 0; t < MAX_TARGETS; t++)
+        {
+            if( ha->device_id == QLA12160_DEVICE_ID ||  
+                ha->device_id == QLA10160_DEVICE_ID )  
+            {
+                status = qla12160_set_target_parameters(ha,b,t,0,(nvram160_t *)nv);
+            }
+			else
+            {
+                /* Set Target Parameters. */
+                mb[0] = MBC_SET_TARGET_PARAMETERS;
+                mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+                mb[1] <<= 8;
+                mb[2] = nv->bus[b].target[t].parameter.c << 8;
+                mb[2] |= TP_AUTO_REQUEST_SENSE;
+                mb[2] &= ~TP_STOP_QUEUE;
+                mb[3] = nv->bus[b].target[t].flags.sync_offset << 8;
+                mb[3] |= nv->bus[b].target[t].sync_period;
+                status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0,
+                    &mb[0]);
+            }
+
+            /* Save Tag queuing enable flag. */
+            mb[0] = BIT_0 << t;
+            if (nv->bus[b].target[t].parameter.f.tag_queuing)
+                ha->bus_settings[b].qtag_enables |= mb[0];
+
+            /* Save Device enable flag. */
+            if (nv->bus[b].target[t].flags.device_enable)
+                ha->bus_settings[b].device_enables |= mb[0];
+
+            /* Save LUN disable flag. */
+            if (nv->bus[b].target[t].flags.lun_disable)
+                ha->bus_settings[b].lun_disables |= mb[0];
+
+            /* Set Device Queue Parameters. */
+            for (l = 0; l < MAX_LUNS; l++)
+            {
+                mb[0] = MBC_SET_DEVICE_QUEUE;
+                mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+                mb[1] = mb[1] << 8 | l;
+                mb[2] = nv->bus[b].max_queue_depth;
+                mb[3] = nv->bus[b].target[t].execution_throttle;
+                status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0,
+                        &mb[0]);
+            }
+        }
+    }
+    DEBUG(ql_debug_print = 0;)
+
+#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
+    ql_debug_print = saved_print_status;
+#endif
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    DEBUG(if (status))
+        DEBUG(qla1280_print("qla1280_nvram_config: **** FAILED ****\n\r");)
+#endif
+    LEAVE("qla1280_nvram_config");
+    return(status);
+}
+
+/*
+ * Get NVRAM data word
+ *      Calculates word position in NVRAM and calls request routine to
+ *      get the word from NVRAM.
+ *
+ * Input:
+ *      ha      = adapter block pointer.
+ *      address = NVRAM word address.
+ *
+ * Returns:
+ *      data word.
+ */
+STATIC uint16_t
+qla1280_get_nvram_word(scsi_qla_host_t *ha, uint32_t address)
+{
+    uint32_t nv_cmd;
+    uint16_t data;
+
+#ifdef QL_DEBUG_ROUTINES
+    uint8_t  saved_print_status = ql_debug_print;
+#endif
+#ifdef QL_DEBUG_LEVEL_4
+    ENTER("qla1280_get_nvram_word");
+#endif
+
+    nv_cmd = address << 16;
+    nv_cmd |= NV_READ_OP;
+
+#ifdef QL_DEBUG_ROUTINES
+    ql_debug_print = FALSE;
+#endif
+    data = qla1280_nvram_request(ha, nv_cmd);
+#ifdef QL_DEBUG_ROUTINES
+    ql_debug_print = saved_print_status;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_4
+    qla1280_print("qla1280_get_nvram_word: exiting normally NVRAM data = ");
+    qla1280_output_number((uint32_t)data, 16);
+    qla1280_print("\n\r");
+#endif
+    return(data);
+}
+
+/*
+ * NVRAM request
+ *      Sends read command to NVRAM and gets data from NVRAM.
+ *
+ * Input:
+ *      ha     = adapter block pointer.
+ *      nv_cmd = Bit 26     = start bit
+ *               Bit 25, 24 = opcode
+ *               Bit 23-16  = address
+ *               Bit 15-0   = write data
+ *
+ * Returns:
+ *      data word.
+ */
+STATIC uint16_t
+qla1280_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
+{
+    uint8_t      cnt;
+    device_reg_t *reg = ha->iobase;
+    uint16_t     data = 0;
+    uint16_t     reg_data;
+
+    /* Send command to NVRAM. */
+
+    nv_cmd <<= 5;
+    for (cnt = 0; cnt < 11; cnt++)
+    {
+        if (nv_cmd & BIT_31)
+            qla1280_nv_write(ha, NV_DATA_OUT);
+        else
+            qla1280_nv_write(ha, 0);
+        nv_cmd <<= 1;
+    }
+
+    /* Read data from NVRAM. */
+
+    for (cnt = 0; cnt < 16; cnt++)
+    {
+        WRT_REG_WORD(&reg->nvram, NV_SELECT+NV_CLOCK);
+        /* qla1280_nv_delay(ha); */
+        NVRAM_DELAY();
+        data <<= 1;
+        reg_data = RD_REG_WORD(&reg->nvram);
+        if (reg_data & NV_DATA_IN)
+            data |= BIT_0;
+        WRT_REG_WORD(&reg->nvram, NV_SELECT);
+        /* qla1280_nv_delay(ha); */
+        NVRAM_DELAY();
+    }
+
+    /* Deselect chip. */
+
+    WRT_REG_WORD(&reg->nvram, NV_DESELECT);
+    /* qla1280_nv_delay(ha); */
+    NVRAM_DELAY();
+
+    return(data);
+}
+
+STATIC void
+qla1280_nv_write(scsi_qla_host_t *ha, uint16_t data)
+{
+    device_reg_t *reg = ha->iobase;
+
+    WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
+    NVRAM_DELAY();
+    /* qla1280_nv_delay(ha); */
+    WRT_REG_WORD(&reg->nvram, data | NV_SELECT | NV_CLOCK);
+    /* qla1280_nv_delay(ha); */
+    NVRAM_DELAY();
+    WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
+    /* qla1280_nv_delay(ha); */
+    NVRAM_DELAY();
+}
+
+STATIC void
+qla1280_nv_delay(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg = ha->iobase;
+    int          cnt  = NV_DELAY_COUNT;
+    uint16_t     data = 0;
+
+    while (cnt--)
+        data |= RD_REG_WORD(&reg->nvram);
+}
+
+/*
+ * Mailbox Command
+ *      Issue mailbox command and waits for completion.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      mr = mailbox registers to load.
+ *      mb = data pointer for mailbox registers.
+ *
+ * Output:
+ *      mb[MAILBOX_REGISTER_COUNT] = returned mailbox data.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_mailbox_command(scsi_qla_host_t *ha, uint8_t mr, uint16_t *mb)
+{
+    device_reg_t *reg   = ha->iobase;
+    uint8_t      status = 0;
+    uint32_t     cnt;
+    uint16_t     *optr, *iptr;
+    uint16_t     data;
+    srb_t        *done_q_first = 0;
+    srb_t        *done_q_last = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_mailbox_command");
+#endif
+
+    /* Acquire interrupt specific lock */
+    QLA1280_INTR_LOCK(ha);
+    DRIVER_LOCK
+            ha->flags.mbox_busy = TRUE;
+
+    /* Load mailbox registers. */
+    optr = (uint16_t *)&reg->mailbox0;
+    iptr = mb;
+    for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++)
+    {
+        if (mr & BIT_0)
+        {
+            WRT_REG_WORD(optr, (*iptr));
+        }
+
+        mr >>= 1;
+        optr++;
+        iptr++;
+    }
+    /* Issue set host interrupt command. */
+    ha->flags.mbox_int = FALSE;
+    WRT_REG_WORD(&reg->host_cmd, HC_SET_HOST_INT);
+    data = qla1280_debounce_register(&reg->istatus);
+
+    /* Wait for 30 seconds for command to finish. */
+    for (cnt = 30000000; cnt > 0 && !ha->flags.mbox_int; cnt--)
+    {
+        /* Check for pending interrupts. */
+        if (data & RISC_INT)
+        {
+            qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+        }
+        SYS_DELAY(1);
+        data = RD_REG_WORD(&reg->istatus);
+    }
+
+    /* Check for mailbox command timeout. */
+    if ( !cnt )
+    {
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print(
+                "qla1280_mailbox_command: **** Command Timeout, mailbox0 = ");
+        qla1280_output_number((uint32_t)mb[0], 16);
+        qla1280_print(" ****\n\r");
+#endif
+        ha->flags.isp_abort_needed = TRUE; 
+        status = 1;
+    }
+    else if (ha->mailbox_out[0] != MBS_CMD_CMP)
+        status = 1;
+
+    /* Load return mailbox registers. */
+    optr = mb;
+    iptr = (uint16_t *)&ha->mailbox_out[0];
+    mr = MAILBOX_REGISTER_COUNT;
+    while (mr--)
+        *optr++ = *iptr++;
+
+    /* Go check for any response interrupts pending. */
+    ha->flags.mbox_busy = FALSE;
+    qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+    /* Release interrupt specific lock */
+    QLA1280_INTR_UNLOCK(ha);
+    DRIVER_UNLOCK
+
+            if (ha->flags.isp_abort_needed)
+        qla1280_abort_isp(ha);
+
+    if (ha->flags.reset_marker)
+        qla1280_rst_aen(ha);
+
+    if (done_q_first)
+        qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+    {
+        qla1280_print("qla1280_mailbox_command: **** FAILED, mailbox0 = ");
+        qla1280_output_number((uint32_t)mb[0], 16);
+        qla1280_print(" ****\n\r");
+    }
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_mailbox_command");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_poll
+ *      Polls ISP for interrupts.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_poll(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg   = ha->iobase;
+    uint16_t        data;
+    srb_t           *done_q_first = 0;
+    srb_t           *done_q_last = 0;
+
+#ifdef QL_DEBUG_LEVEL_3
+    /* ENTER("qla1280_poll"); */
+#endif
+
+    /* Acquire interrupt specific lock */
+    QLA1280_INTR_LOCK(ha);
+
+    /* Check for pending interrupts. */
+    data = RD_REG_WORD(&reg->istatus);
+    if (data & RISC_INT)
+        qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+    /* Release interrupt specific lock */
+    QLA1280_INTR_UNLOCK(ha);
+
+    if (!ha->flags.mbox_busy)
+    {
+        if (ha->flags.isp_abort_needed)
+            qla1280_abort_isp(ha);
+        if (ha->flags.reset_marker)
+            qla1280_rst_aen(ha);
+    }
+
+    if (done_q_first)
+        qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+#ifdef QL_DEBUG_LEVEL_3
+    /* LEAVE("qla1280_poll"); */
+#endif
+}
+
+/*
+ * qla1280_bus_reset
+ *      Issue SCSI bus reset.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI bus number.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_bus_reset(scsi_qla_host_t *ha, uint8_t b)
+{
+    uint8_t     status;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_bus_reset: entered\n\r");
+#endif
+   if( qla1280_verbose )
+   {
+    printk("scsi(%d): Resetting SCSI BUS (%d)\n",(int)ha->host_no,b);
+   }
+
+    mb[0] = MBC_BUS_RESET;
+    mb[1] = ha->bus_settings[b].bus_reset_delay;
+    mb[2] = (uint16_t)b;
+    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    if (status)
+    {
+        if (ha->bus_settings[b].failed_reset_count > 2)                  /* dg - 03/13/99 */
+            ha->bus_settings[b].scsi_bus_dead = TRUE;
+        ha->bus_settings[b].failed_reset_count++;
+    }
+	else
+    {
+       QLA1280_DELAY(4);
+       ha->bus_settings[b].scsi_bus_dead = FALSE;                         /* dg - 03/13/99 */
+       ha->bus_settings[b].failed_reset_count = 0;
+       /* Issue marker command. */
+       qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+    }
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_bus_reset: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_bus_reset: exiting normally\n\r");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_device_reset
+ *      Issue bus device reset message to the target.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI BUS number.
+ *      t  = SCSI ID.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_device_reset(scsi_qla_host_t *ha, uint8_t b, uint32_t t)
+{
+    uint8_t     status;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_device_reset");
+#endif
+
+    mb[0] = MBC_ABORT_TARGET;
+    mb[1] = (b ? (t | BIT_7) : t) << 8;
+    mb[2] = 1;
+    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* Issue marker command. */
+    qla1280_marker(ha, b, t, 0, MK_SYNC_ID);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_device_reset: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_device_reset");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_abort_device
+ *      Issue an abort message to the device
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI BUS.
+ *      t  = SCSI ID.
+ *      l  = SCSI LUN.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_abort_device(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l)
+{
+    uint8_t     status;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_abort_device");
+#endif
+
+    mb[0] = MBC_ABORT_DEVICE;
+    mb[1] = (b ? t | BIT_7 : t) << 8 | l;
+    status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+    /* Issue marker command. */
+    qla1280_marker(ha, b, t, l, MK_SYNC_ID_LUN);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_abort_device: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_abort_device");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_abort_command
+ *      Abort command aborts a specified IOCB.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      sp = SB structure pointer.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+{
+    uint8_t         status;
+    uint16_t        mb[MAILBOX_REGISTER_COUNT];
+    uint32_t        b, t, l;
+    uint32_t        handle;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_abort_command");
+#endif
+
+    /* Locate handle number. */
+    for (handle = 0; handle < MAX_OUTSTANDING_COMMANDS; handle++)
+        if (ha->outstanding_cmds[handle] == sp)
+            break;
+
+                b  = SCSI_BUS_32(sp->cmd);
+        t  = SCSI_TCN_32(sp->cmd);
+        l  = SCSI_LUN_32(sp->cmd);
+
+        mb[0] = MBC_ABORT_COMMAND;
+        mb[1] = (b ? t | BIT_7 : t) << 8 | l;
+        mb[2] = handle >> 16;
+        mb[3] = (uint16_t)handle;
+        status = qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+        if (status)
+            qla1280_print("qla1280_abort_command: **** FAILED ****\n\r");
+#endif
+        sp->flags |= SRB_ABORT_PENDING;
+
+        LEAVE("qla1280_abort_command");
+        return(status);
+}
+
+/*
+ * qla1280_reset_adapter
+ *      Reset adapter.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_reset_adapter(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg = ha->iobase;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_reset_adapter");
+#endif
+
+    /* Disable ISP chip */
+    ha->flags.online = FALSE;
+    WRT_REG_WORD(&reg->ictrl, ISP_RESET);
+    WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
+    WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+    WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_reset_adapter");
+#endif
+}
+
+/*
+ *  Issue marker command.
+ *      Function issues marker IOCB.
+ *
+ * Input:
+ *      ha   = adapter block pointer.
+ *      b    = SCSI BUS number
+ *      t    = SCSI ID
+ *      l    = SCSI LUN
+ *      type = marker modifier
+ */
+STATIC void
+qla1280_marker(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l, uint8_t type)
+{
+    mrk_entry_t     *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_marker");
+#endif
+
+    /* Get request packet. */
+    if ( (pkt = (mrk_entry_t *)qla1280_req_pkt(ha)) )
+    {
+        pkt->entry_type = MARKER_TYPE;
+        pkt->lun = (uint8_t)l;
+        pkt->target = (uint8_t)(b ? (t | BIT_7) : t);
+        pkt->modifier = type;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_marker");
+#endif
+}
+
+#if  QLA1280_64BIT_SUPPORT
+/*
+ * qla1280_64bit_start_scsi
+ *      The start SCSI is responsible for building request packets on
+ *      request ring and modifying ISP input pointer.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      sp = SB structure pointer.
+ *
+ * Returns:
+ *      0 = success, was able to issue command.
+ */
+STATIC uint8_t
+qla1280_64bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp)
+{
+    device_reg_t    *reg   = ha->iobase;
+    uint8_t         status = 0;
+    Scsi_Cmnd       *cmd = sp->cmd;
+    uint32_t        cnt;
+    cmd_a64_entry_t     *pkt;
+    uint16_t        req_cnt;
+    uint16_t        seg_cnt;
+    struct scatterlist    *sg = (struct scatterlist *) NULL;
+    uint32_t        *dword_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_64bit_start_scsi:");
+#endif
+
+    if( qla1280_check_for_dead_scsi_bus(ha, sp) )
+    {
+        return(0);
+    }
+
+    /* Calculate number of entries and segments required. */
+    seg_cnt = 0;
+    req_cnt = 1;
+    if (cmd->use_sg)
+    {
+        seg_cnt =  cmd->use_sg;
+        sg = (struct scatterlist *) cmd->request_buffer;
+            
+        if (seg_cnt > 2)
+        {
+           req_cnt += (uint16_t)(seg_cnt - 2) / 5;
+           if ((uint16_t)(seg_cnt - 2) % 5)
+               req_cnt++;
+        }
+    }
+    else if (cmd->request_bufflen)  /* If data transfer. */
+    {
+        DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen));
+        seg_cnt = 1;
+    }
+
+    /* Acquire ring specific lock */
+    QLA1280_RING_LOCK(ha);
+
+    if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt)
+    {
+        /* Calculate number of free request entries. */
+        cnt = RD_REG_WORD(&reg->mailbox4);
+        if (ha->req_ring_index < cnt)
+            ha->req_q_cnt = cnt - ha->req_ring_index;
+        else
+            ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+    }
+
+    /* If room for request in request ring. */
+    if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt)
+    {
+        /* Check for room in outstanding command list. */
+        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
+            ha->outstanding_cmds[cnt] != 0; cnt++)
+            ;
+
+        if (cnt < MAX_OUTSTANDING_COMMANDS)
+        {
+            ha->outstanding_cmds[cnt] = sp;
+            ha->req_q_cnt -= req_cnt;
+            CMD_HANDLE(sp->cmd) = (unsigned char *) (u_long) cnt;
+
+            /*
+            * Build command packet.
+            */
+            pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
+
+            pkt->entry_type = COMMAND_A64_TYPE;
+            pkt->entry_count = (uint8_t)req_cnt;
+            pkt->sys_define = (uint8_t)ha->req_ring_index;
+            pkt->handle = (uint32_t)cnt;
+
+            /* Zero out remaining portion of packet. */
+            dword_ptr = (uint32_t *)pkt + 2;
+            for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                *dword_ptr++ = 0;
+
+            /* Set ISP command timeout. */
+            pkt->timeout = (uint16_t)30;
+
+            /* Set device target ID and LUN */
+            pkt->lun = SCSI_LUN_32(cmd);
+            pkt->target = SCSI_BUS_32(cmd) ?
+                    (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+            /* Enable simple tag queuing if device supports it. */
+            if (cmd->device->tagged_queue )
+                pkt->control_flags |= BIT_3;
+
+            /* Load SCSI command packet. */
+            pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
+            BCOPY(&(CMD_CDBP(cmd)), pkt->scsi_cdb, pkt->cdb_len);
+            DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]));
+
+            /*
+            * Load data segments.
+            */
+            if (seg_cnt)                /* If data transfer. */
+            {
+                /* Set transfer direction. */
+                if ( (cmd->data_cmnd[0] == WRITE_6) )
+                    pkt->control_flags |= BIT_6;
+                else
+                    pkt->control_flags |= (BIT_5|BIT_6);
+                    
+                sp->dir = pkt->control_flags & (BIT_5|BIT_6);
+
+                /* Set total data segment count. */
+                pkt->dseg_count = seg_cnt;
+
+                /* Setup packet address segment pointer. */
+                dword_ptr = (uint32_t *)&pkt->dseg_0_address;
+
+                if (cmd->use_sg)              /* If scatter gather */
+                {
+                    /* Load command entry data segments. */
+                    for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--)
+                    {
+                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
+                        DEBUG(qla1280_print(debug_buff));
+                        *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address));
+                        *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address));
+                        *dword_ptr++ = sg->length;
+                        sg++;
+                    }
+#ifdef QL_DEBUG_LEVEL_5
+                    qla1280_print(
+                            "qla1280_64bit_start_scsi: Scatter/gather command packet data - ");
+                    qla1280_print("b ");
+                    qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                    qla1280_print(" t ");
+                    qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                    qla1280_print(" d ");
+                    qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                    qla1280_print("\n\r");
+                    qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                    /*
+                    * Build continuation packets.
+                    */
+                    while (seg_cnt > 0)
+                    {
+                        /* Adjust ring index. */
+                        ha->req_ring_index++;
+                        if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+                        {
+                            ha->req_ring_index = 0;
+                            ha->request_ring_ptr = ha->request_ring;
+                        }
+                        else
+                            ha->request_ring_ptr++;
+
+                        pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
+
+                        /* Zero out packet. */
+                        dword_ptr = (uint32_t *)pkt;
+                        for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                            *dword_ptr++ = 0;
+
+                        /* Load packet defaults. */
+                        ((cont_a64_entry_t *)pkt)->entry_type =
+                                CONTINUE_A64_TYPE;
+                        ((cont_a64_entry_t *)pkt)->entry_count = 1;
+                        ((cont_a64_entry_t *)pkt)->sys_define = (uint8_t)
+                                ha->req_ring_index;
+
+                        /* Setup packet address segment pointer. */
+                        dword_ptr = (uint32_t *)
+                                &((cont_a64_entry_t *)pkt)->dseg_0_address;
+
+                        /* Load continuation entry data segments. */
+                        for (cnt = 0; cnt < 5 && seg_cnt; cnt++, seg_cnt--)
+                        {
+                            *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address));
+                            *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address));
+                            *dword_ptr++ = sg->length;
+                            sg++;
+                        }
+#ifdef QL_DEBUG_LEVEL_5
+                        qla1280_print(
+                                "qla1280_64bit_start_scsi: continuation packet data - c");
+                        qla1280_print(" b ");
+                        qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+
+                        qla1280_print(" t ");
+                        qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                        qla1280_print(" d ");
+                        qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                        qla1280_print("\n\r");
+                        qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                    }
+                }
+                else                    /* No scatter gather data transfer */
+                {
+                    *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(cmd->request_buffer));
+                    *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(cmd->request_buffer));
+                    *dword_ptr = (uint32_t) cmd->request_bufflen;
+#ifdef QL_DEBUG_LEVEL_5
+                    qla1280_print(
+                            "qla1280_64bit_start_scsi: No scatter/gather command packet data - c");
+                    qla1280_print(" b ");
+                    qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                    qla1280_print(" t ");
+                    qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                    qla1280_print(" d ");
+                    qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                    qla1280_print("\n\r");
+                    qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                }
+            }
+#ifdef QL_DEBUG_LEVEL_5
+            else                            /* No data transfer */
+            {
+                *dword_ptr++ = (uint32_t) 0;
+                *dword_ptr++ = (uint32_t) 0;
+                *dword_ptr = (uint32_t)  0;
+                qla1280_print(
+                        "qla1280_64bit_start_scsi: No data, command packet data - c");
+                qla1280_print(" b ");
+                qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                qla1280_print(" t ");
+                qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                qla1280_print(" d ");
+                qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                qla1280_print("\n\r");
+                qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+            }
+#endif
+            /* Adjust ring index. */
+            ha->req_ring_index++;
+            if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+            {
+                ha->req_ring_index = 0;
+                ha->request_ring_ptr = ha->request_ring;
+            }
+            else
+                ha->request_ring_ptr++;
+
+            /* Set chip new ring index. */
+            WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+        }
+        else
+        {
+            status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+            qla1280_print(
+                    "qla1280_64bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r");
+            qla1280_print(" req_q_cnt=");
+            qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+#endif
+        }
+    }
+    else
+    {
+        status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print("qla1280_64bit_start_scsi: in-ptr=");
+        qla1280_output_number((uint32_t)ha->req_ring_index, 16);
+        qla1280_print(" req_q_cnt=");
+        qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+        qla1280_print(" req_cnt=");
+        qla1280_output_number((uint32_t)req_cnt, 16);
+        qla1280_print("\n\r");
+#endif
+    }
+
+    /* Release ring specific lock */
+    QLA1280_RING_UNLOCK(ha);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_64bit_start_scsi: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_64bit_start_scsi: exiting normally\n\r");
+#endif
+    return(status);
+}
+#endif  /* QLA1280_64BIT_SUPPORT */
+
+/*
+ * qla1280_32bit_start_scsi
+ *      The start SCSI is responsible for building request packets on
+ *      request ring and modifying ISP input pointer.
+ *
+ *      The Qlogic firmware interface allows every queue slot to have a SCSI
+ *      command and up to 4 scatter/gather (SG) entries.  If we need more
+ *      than 4 SG entries, then continuation entries are used that can 
+ *      hold another 7 entries each.  The start routine determines if there
+ *      is eought empty slots then build the combination of requests to 
+ *      fulfill the OS request.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      sp = SCSI Request Block structure pointer.
+ *
+ * Returns:
+ *      0 = success, was able to issue command.
+ */
+STATIC uint8_t
+qla1280_32bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp)
+{
+    device_reg_t    *reg   = ha->iobase;
+    uint8_t         status = 0;
+    Scsi_Cmnd       *cmd = sp->cmd;
+    uint32_t        cnt;
+    cmd_entry_t     *pkt;
+    uint16_t        req_cnt;
+    uint16_t        seg_cnt;
+    struct scatterlist    *sg = (struct scatterlist *) NULL;
+    uint8_t        *data_ptr;
+    uint32_t        *dword_ptr;
+
+    ENTER("qla1280_32bit_start_scsi");
+
+
+    if( qla1280_check_for_dead_scsi_bus(ha, sp) )
+    {
+        return(0);
+    }
+
+    /* Calculate number of entries and segments required. */
+    req_cnt = 1;
+    if (cmd->use_sg)
+    {
+        /*
+        * We must build an SG list in adapter format, as the kernel's SG list
+        * cannot be used directly because of data field size (__alpha__)
+        * differences and the kernel SG list uses virtual addresses where
+        * we need physical addresses.
+        */
+        seg_cnt =  cmd->use_sg;
+        sg = (struct scatterlist *) cmd->request_buffer;
+        /* 
+        * if greater than four sg entries then we need to allocate
+        * continuation entries
+        */
+        if (seg_cnt > 4)
+        {
+            req_cnt += (uint16_t)(seg_cnt - 4) / 7;
+            if ((uint16_t)(seg_cnt - 4) % 7)
+                req_cnt++;
+        }
+        DEBUG(sprintf(debug_buff,"S/G for data transfer -num segs(%d), req blk cnt(%d)\n\r",seg_cnt,req_cnt));
+        DEBUG(qla1280_print(debug_buff));
+    }
+    else if (cmd->request_bufflen)  /* If data transfer. */
+    {
+        DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen));
+        seg_cnt = 1;
+    }
+    else
+    {
+        DEBUG(printk("No data transfer \n"));
+        seg_cnt = 0;
+    }
+
+    /* Acquire ring specific lock */
+    QLA1280_RING_LOCK(ha);
+
+    if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt)
+    {
+        /* Calculate number of free request entries. */
+        cnt = RD_REG_WORD(&reg->mailbox4);
+        if (ha->req_ring_index < cnt)
+            ha->req_q_cnt = cnt - ha->req_ring_index;
+        else
+            ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+    }
+
+    DEBUG(sprintf(debug_buff,"Number of free entries = (%d)\n\r",ha->req_q_cnt));
+    DEBUG(qla1280_print(debug_buff));
+    /* If room for request in request ring. */
+    if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt)
+    {
+        /* Check for empty slot in outstanding command list. */
+        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
+            (ha->outstanding_cmds[cnt] != 0); cnt++)
+            ;
+
+        if (cnt < MAX_OUTSTANDING_COMMANDS)
+        {
+            CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)cnt;
+            ha->outstanding_cmds[cnt] = sp;
+            ha->req_q_cnt -= req_cnt;
+
+            /*
+            * Build command packet.
+            */
+            pkt = (cmd_entry_t *)ha->request_ring_ptr;
+
+            pkt->entry_type = COMMAND_TYPE;
+            pkt->entry_count = (uint8_t)req_cnt;
+            pkt->sys_define = (uint8_t)ha->req_ring_index;
+            pkt->handle = (uint32_t)cnt;
+
+            /* Zero out remaining portion of packet. */
+            dword_ptr = (uint32_t *)pkt + 2;
+            for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                *dword_ptr++ = 0;
+
+            /* Set ISP command timeout. */
+            pkt->timeout = (uint16_t)30;
+
+            /* Set device target ID and LUN */
+            pkt->lun = SCSI_LUN_32(cmd);
+            pkt->target = SCSI_BUS_32(cmd) ?
+                    (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+            /* Enable simple tag queuing if device supports it. */
+            if (cmd->device->tagged_queue )
+                pkt->control_flags |= BIT_3;
+
+            /* Load SCSI command packet. */
+            pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
+            data_ptr = (uint8_t *) &(CMD_CDBP(cmd));
+            for (cnt = 0; cnt < pkt->cdb_len; cnt++)
+                pkt->scsi_cdb[cnt] = *data_ptr++;
+            DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]));
+            /*
+            * Load data segments.
+            */
+            if (seg_cnt)
+            {
+                DEBUG(printk("loading data segments..\n"));
+                /* Set transfer direction (READ and WRITE) */
+                /* Linux doesn't tell us                   */
+
+                /*
+                * 3/10 dg - Normally, we should need this check with our F/W
+                * but because of a small issue with it we do.
+                *
+                * For block devices, cmd->request.cmd has the operation 
+                * For character devices, this isn't always set properly, so
+                * we need to check data_cmnd[0].  This catches the conditions
+                * for st.c, but not sg. Generic commands are pass down to us.
+                */
+                if ( (cmd->data_cmnd[0] == WRITE_6) )
+                    pkt->control_flags |= BIT_6;
+                else
+                    pkt->control_flags |= (BIT_5|BIT_6);
+                    
+                sp->dir = pkt->control_flags & (BIT_5|BIT_6);
+
+                /* Set total data segment count. */
+                pkt->dseg_count = seg_cnt;
+
+                /* Setup packet address segment pointer. */
+                dword_ptr = (uint32_t *)&pkt->dseg_0_address;
+
+                if (cmd->use_sg)     /* If scatter gather */
+                {
+                    DEBUG(qla1280_print("Building S/G data segments..\n\r"));
+                    DEBUG(qla1280_dump_buffer((caddr_t)sg, 4*16 ));
+                    /* Load command entry data segments. */
+                    for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--)
+                    {
+                        *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(sg->address));
+                        *dword_ptr++ = sg->length;
+                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
+                        DEBUG(qla1280_print(debug_buff));
+                        sg++;
+                    }
+                    /*
+                    * Build continuation packets.
+                    */
+                    while (seg_cnt > 0)
+                    {
+                        /* Adjust ring index. */
+                        ha->req_ring_index++;
+                        if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+                        {
+                            ha->req_ring_index = 0;
+                            ha->request_ring_ptr = ha->request_ring;
+                        }
+                        else
+                            ha->request_ring_ptr++;
+
+                        pkt = (cmd_entry_t *)ha->request_ring_ptr;
+
+                        /* Zero out packet. */
+                        dword_ptr = (uint32_t *)pkt;
+                        for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                            *dword_ptr++ = 0;
+
+                        /* Load packet defaults. */
+                        ((cont_entry_t *)pkt)->entry_type =
+                                CONTINUE_TYPE;
+                        ((cont_entry_t *)pkt)->entry_count = 1;
+
+                        ((cont_entry_t *)pkt)->sys_define = (uint8_t)
+                                ha->req_ring_index;
+
+                        /* Setup packet address segment pointer. */
+                        dword_ptr = (uint32_t *)
+                                &((cont_entry_t *)pkt)->dseg_0_address;
+
+                        /* Load continuation entry data segments. */
+                        for (cnt = 0; cnt < 7 && seg_cnt; cnt++, seg_cnt--)
+                        {
+                            *dword_ptr++ = (u_int) cpu_to_le32(VIRT_TO_BUS(sg->address));
+                            *dword_ptr++ = sg->length;
+                            sg++;
+                        }
+#ifdef QL_DEBUG_LEVEL_5
+                        qla1280_print(
+                                "qla1280_32bit_start_scsi: continuation packet data - scsi(");
+                        qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                        qla1280_print(":");
+                        qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                        qla1280_print(":");
+                        qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                        qla1280_print(")\n\r");
+                        qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                    }
+                }
+                else                    /* No scatter gather data transfer */
+                {
+                    *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer));
+                    *dword_ptr = (uint32_t) cmd->request_bufflen;
+                    DEBUG(printk("Single Segment ap=0x%p, len=0x%x\n",cmd->request_buffer,cmd->request_bufflen));
+                }
+            }
+            else                            /* No data transfer */
+            {
+                *dword_ptr++ = (uint32_t) 0;
+                *dword_ptr = (uint32_t)  0;
+#ifdef QL_DEBUG_LEVEL_5
+                qla1280_print(
+                        "qla1280_32bit_start_scsi: No data, command packet data - ");
+                qla1280_print("\n\r");
+                qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+            }
+#ifdef QL_DEBUG_LEVEL_5
+            qla1280_print("qla1280_32bit_start_scsi: First IOCB block:\n\r");
+            qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE);
+#endif
+            /* Adjust ring index. */
+            ha->req_ring_index++;
+            if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+            {
+                ha->req_ring_index = 0;
+                ha->request_ring_ptr = ha->request_ring;
+            }
+            else
+                ha->request_ring_ptr++;
+
+            /* Set chip new ring index. */
+            DEBUG(qla1280_print("qla1280_32bit_start_scsi: Wakeup RISC for pending command\n\r"));
+            ha->qthreads--;
+            sp->u_start = jiffies;
+            sp->flags |= SRB_SENT;
+            ha->actthreads++;
+            /* qla1280_output_number((uint32_t)ha->actthreads++, 16); */
+            WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+        }
+        else
+        {
+            status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+            qla1280_print(
+                    "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r");
+            qla1280_print(" req_q_cnt=");
+            qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+            qla1280_print("\n\r");
+#endif
+        }
+    }
+    else
+    {
+        status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+        /*  qla1280_print("qla1280_32bit_start_scsi: in-ptr=");
+        qla1280_output_number((uint32_t)ha->req_ring_index, 16);
+        qla1280_print(" req_q_cnt=");
+        qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+        qla1280_print(" req_cnt=");
+        qla1280_output_number((uint32_t)req_cnt, 16);
+        qla1280_print("\n\r"); */
+#endif
+    }
+
+    /* Release ring specific lock */
+    QLA1280_RING_UNLOCK(ha);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    /* if (status)
+    qla1280_print("qla1280_32bit_start_scsi: **** FAILED ****\n\r"); */
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+            LEAVE("qla1280_32bit_start_scsi");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_req_pkt
+ *      Function is responsible for locking ring and
+ *      getting a zeroed out request packet.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ *
+ * Returns:
+ *      0 = failed to get slot.
+ */
+STATIC request_t *
+qla1280_req_pkt(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg = ha->iobase;
+    request_t       *pkt = 0;
+    uint16_t        cnt;
+    uint32_t        *dword_ptr;
+    uint32_t        timer;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_req_pkt");
+#endif
+
+    /* Wait for 30 seconds for slot. */
+    for (timer = 15000000; timer; timer--)
+    {
+        /* Acquire ring specific lock */
+        QLA1280_RING_LOCK(ha);
+
+        if (ha->req_q_cnt > 0)
+        {
+            /* Calculate number of free request entries. */
+            cnt = RD_REG_WORD(&reg->mailbox4);
+            if (ha->req_ring_index < cnt)
+                ha->req_q_cnt = cnt - ha->req_ring_index;
+            else
+                ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+        }
+
+        /* Found empty request ring slot? */
+        if (ha->req_q_cnt > 0)
+        {
+            ha->req_q_cnt--;
+            pkt = ha->request_ring_ptr;
+
+            /* Zero out packet. */
+            dword_ptr = (uint32_t *)pkt;
+            for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                *dword_ptr++ = 0;
+
+            /* Set system defined field. */
+            pkt->sys_define = (uint8_t)ha->req_ring_index;
+
+            /* Set entry count. */
+            pkt->entry_count = 1;
+
+            break;
+        }
+
+        /* Release ring specific lock */
+        QLA1280_RING_UNLOCK(ha);
+
+        SYS_DELAY(2);   /* 10 */ 
+
+        /* Check for pending interrupts. */
+        qla1280_poll(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_req_pkt: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_req_pkt: exiting normally\n\r");
+#endif
+    return(pkt);
+}
+
+/*
+ * qla1280_isp_cmd
+ *      Function is responsible for modifying ISP input pointer.
+ *      Releases ring lock.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ */
+STATIC void
+qla1280_isp_cmd(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg = ha->iobase;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_isp_cmd");
+#endif
+
+#ifdef QL_DEBUG_LEVEL_5
+    qla1280_print("qla1280_isp_cmd: IOCB data:\n\r");
+    qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE); 
+#endif
+
+    /* Adjust ring index. */
+    ha->req_ring_index++;
+    if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+    {
+        ha->req_ring_index = 0;
+        ha->request_ring_ptr = ha->request_ring;
+    }
+    else
+        ha->request_ring_ptr++;
+
+    /* Set chip new ring index. */
+    WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+
+    /* Release ring specific lock */
+    QLA1280_RING_UNLOCK(ha);
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_isp_cmd");
+#endif
+}
+
+/*
+ * qla1280_enable_lun
+ *      Issue enable LUN entry IOCB.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI BUS number.
+ *      l  = LUN number.
+ */
+STATIC void
+qla1280_enable_lun(scsi_qla_host_t *ha, uint8_t b, uint32_t l)
+{
+    elun_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_enable_lun: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    /*
+    if (pkt = (elun_entry_t *)qla1280_req_pkt(ha))
+    {
+    pkt->entry_type = ENABLE_LUN_TYPE;
+    pkt->lun = (uint16_t)(b ? l | BIT_15 : l);
+    pkt->command_count = 32;
+    pkt->immed_notify_count = 1;
+    pkt->group_6_length = MAX_CMDSZ;
+    pkt->group_7_length = MAX_CMDSZ;
+    pkt->timeout = 0x30;
+
+    qla1280_isp_cmd(ha);
+    }
+    */
+    pkt = (elun_entry_t *)1;
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_enable_lun: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_enable_lun: exiting normally\n\r");
+#endif
+}
+
+#if QL1280_TARGET_MODE_SUPPORT
+/****************************************************************************/
+/*                      Target Mode Support Functions.                      */
+/****************************************************************************/
+
+/*
+ * qla1280_notify_ack
+ *      Issue notify acknowledge IOCB.
+ *      If sequence ID is zero, acknowledgement of
+ *      SCSI bus reset or bus device reset is assumed.
+ *
+ * Input:
+ *      ha      = adapter block pointer.
+ *      inotify = immediate notify entry pointer.
+ */
+STATIC void
+qla1280_notify_ack(scsi_qla_host_t *ha, notify_entry_t *inotify)
+{
+    nack_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_notify_ack: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (nack_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = NOTIFY_ACK_TYPE;
+        pkt->lun = inotify->lun;
+        pkt->initiator_id = inotify->initiator_id;
+        pkt->target_id = inotify->target_id;
+        if (inotify->seq_id == 0)
+            pkt->event = BIT_7;
+        else
+            pkt->seq_id = inotify->seq_id;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_notify_ack: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_notify_ack: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_immed_notify
+ *      Issue immediate notify IOCB for LUN 0.
+ *
+ * Input:
+ *      ha      = adapter block pointer.
+ *      inotify = immediate notify entry pointer.
+ */
+STATIC void
+qla1280_immed_notify(scsi_qla_host_t *ha, notify_entry_t *inotify)
+{
+    notify_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_immed_notify: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (notify_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = IMMED_NOTIFY_TYPE;
+        pkt->lun = inotify->lun;
+        pkt->initiator_id = inotify->initiator_id;
+        pkt->target_id = inotify->target_id;
+        pkt->status = 1;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_immed_notify: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_immed_notify: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_accept_io
+ *      Issue accept target I/O IOCB for LUN 0.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      ctio = ctio returned entry pointer.
+ */
+STATIC void
+qla1280_accept_io(scsi_qla_host_t *ha, ctio_ret_entry_t *ctio)
+{
+    atio_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_accept_io: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (atio_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = ACCEPT_TGT_IO_TYPE;
+        pkt->lun = ctio->lun;
+        pkt->initiator_id = ctio->initiator_id;
+        pkt->target_id = ctio->target_id;
+        pkt->tag_value = ctio->tag_value;
+        pkt->status = 1;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_accept_io: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_accept_io: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_64bit_continue_io
+ *      Issue continue target I/O IOCB.
+ *
+ * Input:
+ *      ha   = adapter block pointer.
+ *      atio = atio pointer.
+ *      len  = total bytecount.
+ *      addr = physical address pointer.
+ */
+STATIC void
+qla1280_64bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len,
+                    paddr32_t *addr)
+{
+    ctio_a64_entry_t *pkt;
+    uint32_t         *dword_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_64bit_continue_io: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (ctio_a64_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = CTIO_A64_TYPE;
+        pkt->lun = atio->lun;
+        pkt->initiator_id = atio->initiator_id;
+        pkt->target_id = atio->target_id;
+        pkt->option_flags = atio->option_flags;
+        pkt->tag_value = atio->tag_value;
+        pkt->scsi_status = atio->scsi_status;
+
+        if (len)
+        {
+            pkt->dseg_count = 1;
+            pkt->transfer_length = len;
+            pkt->dseg_0_length = len;
+            dword_ptr = (uint32_t *)addr;
+            pkt->dseg_0_address[0] = *dword_ptr++;
+            pkt->dseg_0_address[1] = *dword_ptr;
+        }
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_64bit_continue_io: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_64bit_continue_io: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_32bit_continue_io
+ *      Issue continue target I/O IOCB.
+ *
+ * Input:
+ *      ha   = adapter block pointer.
+ *      atio = atio pointer.
+ *      len  = total bytecount.
+ *      addr = physical address pointer.
+ */
+STATIC void
+qla1280_32bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len,
+                    paddr32_t *addr)
+{
+    ctio_entry_t *pkt;
+    uint32_t     *dword_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_32bit_continue_io: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (ctio_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = CONTINUE_TGT_IO_TYPE;
+        pkt->lun = atio->lun;
+        pkt->initiator_id = atio->initiator_id;
+        pkt->target_id = atio->target_id;
+        pkt->option_flags = atio->option_flags;
+        pkt->tag_value = atio->tag_value;
+        pkt->scsi_status = atio->scsi_status;
+
+        if (len)
+        {
+            pkt->dseg_count = 1;
+            pkt->transfer_length = len;
+            pkt->dseg_0_length = len;
+            dword_ptr = (uint32_t *)addr;
+            pkt->dseg_0_address = *dword_ptr;
+        }
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_32bit_continue_io: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_32bit_continue_io: exiting normally\n\r");
+#endif
+}
+#endif /* QL1280_TARGET_MODE_SUPPORT */
+
+/****************************************************************************/
+/*                        Interrupt Service Routine.                        */
+/****************************************************************************/
+
+/****************************************************************************
+ *  qla1280_isr
+ *      Calls I/O done on command completion.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ *      INTR_LOCK must be already obtained.
+ ****************************************************************************/
+STATIC void
+qla1280_isr(scsi_qla_host_t *ha, srb_t **done_q_first, srb_t **done_q_last)
+{
+    device_reg_t    *reg = ha->iobase;
+    response_t      *pkt;
+    srb_t           *sp;
+    uint16_t        mailbox[MAILBOX_REGISTER_COUNT];
+    uint16_t        *wptr;
+    uint32_t        index;
+
+    ENTER("qla1280_isr");
+
+
+    /* Save mailbox register 5 */
+    mailbox[5] = RD_REG_WORD(&reg->mailbox5);
+
+    /* Check for mailbox interrupt. */
+
+    mailbox[0] = RD_REG_WORD(&reg->semaphore);
+    if (mailbox[0] & BIT_0)
+    {
+        /* Get mailbox data. */
+
+        wptr = &mailbox[0];
+        *wptr++ = RD_REG_WORD(&reg->mailbox0);
+        *wptr++ = RD_REG_WORD(&reg->mailbox1);
+        *wptr = RD_REG_WORD(&reg->mailbox2);
+        if (mailbox[0] != MBA_SCSI_COMPLETION)
+        {
+            wptr++;
+            *wptr++ = RD_REG_WORD(&reg->mailbox3);
+            *wptr++ = RD_REG_WORD(&reg->mailbox4);
+            wptr++;
+            *wptr++ = RD_REG_WORD(&reg->mailbox6);
+            *wptr   = RD_REG_WORD(&reg->mailbox7);
+        }
+
+        /* Release mailbox registers. */
+
+        WRT_REG_WORD(&reg->semaphore, 0);
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+
+#ifdef QL_DEBUG_LEVEL_5
+        qla1280_print("qla1280_isr: mailbox interrupt mailbox[0] = ");
+        qla1280_output_number((uint32_t)mailbox[0], 16);
+        qla1280_print("\n\r");
+#endif
+
+        /* Handle asynchronous event */
+
+        switch (mailbox[0])
+        {
+            case MBA_SCSI_COMPLETION:   /* Response completion */
+#ifdef QL_DEBUG_LEVEL_5
+                qla1280_print("qla1280_isr: mailbox response completion\n\r");
+#endif
+                if (ha->flags.online)
+                {
+                    /* Get outstanding command index. */
+                    index = (uint32_t)(mailbox[2] << 16 | mailbox[1]);
+
+                    /* Validate handle. */
+                    if (index < MAX_OUTSTANDING_COMMANDS)
+                        sp = ha->outstanding_cmds[index];
+                    else
+                        sp = 0;
+
+                    if (sp)
+                    {
+                        /* Free outstanding command slot. */
+                        ha->outstanding_cmds[index] = 0;
+
+                        /* Save ISP completion status */
+                        CMD_RESULT(sp->cmd) = 0;
+
+                        /* Place block on done queue */
+                        sp->s_next = NULL;
+                        sp->s_prev = *done_q_last;
+                        if (!*done_q_first)
+                            *done_q_first = sp;
+                        else
+                            (*done_q_last)->s_next = sp;
+                        *done_q_last = sp;
+                    }
+                    else
+                    {
+#ifdef QL_DEBUG_LEVEL_2
+                            qla1280_print("qla1280_isr: ISP invalid handle\n\r");
+#endif
+                            printk(KERN_WARNING "qla1280: ISP invalid handle");
+                            ha->flags.isp_abort_needed = TRUE;
+                    }
+                }
+                break;
+            case MBA_BUS_RESET:         /* SCSI Bus Reset */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: asynchronous BUS_RESET\n\r");
+#endif
+                ha->flags.reset_marker = TRUE;
+                index = mailbox[6] & BIT_0;
+                ha->bus_settings[index].reset_marker = TRUE;
+                break;
+            case MBA_SYSTEM_ERR:        /* System Error */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: ISP System Error - mbx1=");
+                qla1280_output_number((uint32_t)mailbox[1], 16);
+                qla1280_print(", mbx2=");
+                qla1280_output_number((uint32_t)mailbox[2], 16);
+                qla1280_print(", mbx3=");
+                qla1280_output_number((uint32_t)mailbox[3], 16);
+                qla1280_print("\n\r");
+#endif
+                printk(KERN_WARNING
+                        "qla1280: ISP System Error - mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
+                        mailbox[1], mailbox[2], mailbox[3]);
+                ha->flags.isp_abort_needed = TRUE;
+                break;
+            case MBA_REQ_TRANSFER_ERR:  /* Request Transfer Error */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: ISP Request Transfer Error\n\r");
+#endif
+                printk(KERN_WARNING "qla1280: ISP Request Transfer Error\n");
+                ha->flags.isp_abort_needed = TRUE;
+                break;
+            case MBA_RSP_TRANSFER_ERR:  /* Response Transfer Error */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: ISP Response Transfer Error\n\r");
+#endif
+                printk(KERN_WARNING "qla1280: ISP Response Transfer Error\n");
+                ha->flags.isp_abort_needed = TRUE;
+                break;
+            case MBA_WAKEUP_THRES:      /* Request Queue Wake-up */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: asynchronous WAKEUP_THRES\n\r");
+#endif
+                break;
+            case MBA_TIMEOUT_RESET:     /* Execution Timeout Reset */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: asynchronous TIMEOUT_RESET\n\r");
+#endif
+                break;
+            case MBA_DEVICE_RESET:         /* Bus Device Reset */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print(
+                        "qla1280_isr: asynchronous BUS_DEVICE_RESET\n\r");
+#endif
+                ha->flags.reset_marker = TRUE;
+                index = mailbox[6] & BIT_0;
+                ha->bus_settings[index].reset_marker = TRUE;
+                break;
+            case MBA_BUS_MODE_CHANGE:
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print(
+                        "qla1280_isr: asynchronous BUS_MODE_CHANGE\n\r");
+#endif
+                break;
+            default:
+                if (mailbox[0] < MBA_ASYNC_EVENT)
+                {
+                        wptr = &mailbox[0];
+                        ha->mailbox_out[0] = *wptr++;
+                        ha->mailbox_out[1] = *wptr++;
+                        ha->mailbox_out[2] = *wptr++;
+                        ha->mailbox_out[3] = *wptr++;
+                        ha->mailbox_out[4] = *wptr++;
+                        ha->mailbox_out[5] = *wptr++;
+                        ha->mailbox_out[6] = *wptr++;
+                        ha->mailbox_out[7] = *wptr;
+                        ha->flags.mbox_int = TRUE;
+                }
+                break;
+        }
+    }
+    else
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+
+    /*
+    * Response ring
+    */
+    if (ha->flags.online && !ha->flags.mbox_busy)
+    {
+        if (mailbox[5] < RESPONSE_ENTRY_CNT)
+        {
+            while (ha->rsp_ring_index != mailbox[5])
+            {
+                pkt = ha->response_ring_ptr;
+
+#ifdef QL_DEBUG_LEVEL_5
+                qla1280_print("qla1280_isr: ha->rsp_ring_index = ");
+                qla1280_output_number((uint32_t)ha->rsp_ring_index, 16);
+                qla1280_print(" mailbox[5] = ");
+                qla1280_output_number((uint32_t)mailbox[5], 16);
+                qla1280_print("\n\rqla1280_isr: response packet data\n\r");
+                qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE);
+#endif
+
+#if defined(QL_DEBUG_LEVEL_2) && !defined(QL_DEBUG_LEVEL_5)
+                if (pkt->entry_type == STATUS_TYPE)
+                {
+                    if ((uint8_t)(pkt->scsi_status) || pkt->comp_status ||
+                        pkt->entry_status)
+                    {
+                        DEBUG(qla1280_print("qla1280_isr: ha->rsp_ring_index = ");)
+                        DEBUG(qla1280_output_number((uint32_t)ha->rsp_ring_index,
+                                16);)
+                        DEBUG(qla1280_print(" mailbox[5] = ");)
+                        DEBUG(qla1280_output_number((uint32_t)mailbox[5], 16);)
+                        DEBUG(qla1280_print( "\n\r comp_status = ");)
+                        DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);)
+                        DEBUG(qla1280_print( ", ");)
+                        DEBUG(qla1280_print( " scsi_status = ");)
+                        DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);)
+                        DEBUG(qla1280_print( "\n\r");)
+                        /* qla1280_print(
+                        "\n\rqla1280_isr: response packet data\n\r");
+                        qla1280_dump_buffer((caddr_t)pkt,
+                        RESPONSE_ENTRY_SIZE); */
+                    }
+                }
+                else
+                {
+                    qla1280_print("qla1280_isr: ha->rsp_ring_index = ");
+                    qla1280_output_number((uint32_t)ha->rsp_ring_index, 16);
+                    qla1280_print(" mailbox[5] = ");
+                    qla1280_output_number((uint32_t)mailbox[5], 16);
+                    qla1280_print(
+                            "\n\rqla1280_isr: response packet data\n\r");
+                    qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE);
+                }
+#endif
+                if (pkt->entry_type == STATUS_TYPE || pkt->entry_status)
+                {
+                    if (pkt->entry_type == STATUS_TYPE)
+                        qla1280_status_entry(ha, (sts_entry_t *)pkt,
+                                done_q_first, done_q_last);
+                    else
+                        qla1280_error_entry(ha, pkt,
+                                done_q_first, done_q_last);
+
+                    /* Adjust ring index. */
+                    ha->rsp_ring_index++;
+                    if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT)
+                    {
+                        ha->rsp_ring_index = 0;
+                        ha->response_ring_ptr = ha->response_ring;
+                    }
+                    else
+                        ha->response_ring_ptr++;
+                    WRT_REG_WORD(&reg->mailbox5, ha->rsp_ring_index);
+                }
+#if QLA1280_TARGET_MODE_SUPPORT
+                else
+                {
+                    pkt = &response_entry;
+
+                    /* Copy packet. */
+                    dptr1 = (uint32_t *)ha->response_ring_ptr;
+                    dptr2 = (uint32_t *)pkt;
+                    for (index = 0; index < RESPONSE_ENTRY_SIZE/4; index++)
+                        *dptr2++ = *dptr1++;
+
+                    /* Adjust ring index. */
+                    ha->rsp_ring_index++;
+                    if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT)
+                    {
+                        ha->rsp_ring_index = 0;
+                        ha->response_ring_ptr = ha->response_ring;
+                    }
+                    else
+                        ha->response_ring_ptr++;
+                    WRT_REG_WORD(&reg->mailbox5, ha->rsp_ring_index);
+
+                    /* Release interrupt specific lock */
+                    QLA1280_INTR_UNLOCK(ha);
+
+                    switch (pkt->entry_type)
+                    {
+                        case ACCEPT_TGT_IO_TYPE:
+                            qla1280_atio_entry(ha, (atio_entry_t *)pkt);
+                            break;
+                        case IMMED_NOTIFY_TYPE:
+                            qla1280_notify_entry(ha, (notify_entry_t *)pkt);
+                            break;
+                        case CTIO_RET_TYPE:
+                            qla1280_accept_io(ha, (ctio_ret_entry_t *)pkt);
+                            break;
+                        default:
+                            break;
+                    }
+
+                    /* Acquire interrupt specific lock */
+                    QLA1280_INTR_LOCK(ha);
+                }
+#endif
+            }
+        }
+        else
+        {
+            ha->flags.isp_abort_needed = TRUE;
+#ifdef QL_DEBUG_LEVEL_2
+            qla1280_print("qla1280_isr: Response pointer Error\n");
+#endif
+        }
+    }
+
+    LEAVE("qla1280_isr");
+}
+
+/*
+ *  qla1280_rst_aen
+ *      Processes asynchronous reset.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ */
+STATIC void
+qla1280_rst_aen(scsi_qla_host_t *ha)
+{
+#if QL1280_TARGET_MODE_SUPPORT
+    notify_entry_t  nentry;
+#endif
+    uint8_t         b;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_rst_aen");
+#endif
+
+    if (ha->flags.online && !ha->flags.reset_active &&
+        !ha->flags.abort_isp_active)
+    {
+        ha->flags.reset_active = TRUE;
+        while (ha->flags.reset_marker)
+        {
+            /* Issue marker command. */
+            ha->flags.reset_marker = FALSE;
+            for (b = 0; b < ha->ports && !ha->flags.reset_marker; b++)
+            {
+                if (ha->bus_settings[b].reset_marker)
+                {
+                    ha->bus_settings[b].reset_marker = FALSE;
+                    qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+
+                    if (!ha->flags.reset_marker)
+                    {
+#if QL1280_TARGET_MODE_SUPPORT
+                        /* Issue notify acknowledgement command. */
+                        bzero((caddr_t)&nentry, sizeof(notify_entry_t));
+
+                        nentry.initiator_id = nentry.target_id = b ?
+                                ha->bus_settings[b].id | BIT_7 :
+                        ha->bus_settings[b].id;
+                        qla1280_notify_entry(ha, &nentry);
+#endif
+
+                        /* Asynchronous event notification */
+                    }
+                }
+            }
+        }
+    }
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_rst_aen");
+#endif
+}
+
+#if QL1280_TARGET_MODE_SUPPORT
+/*
+ *  qla1280_atio_entry
+ *      Processes received ISP accept target I/O entry.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ *      pkt = entry pointer.
+ */
+STATIC void
+qla1280_atio_entry(scsi_qla_host_t *ha, atio_entry_t *pkt)
+{
+    uint64_t    *a64;
+    uint64_t    *end_a64;
+    paddr32_t   phy_addr[2];
+    paddr32_t   end_addr[2];
+    uint32_t    len;
+    uint32_t    offset;
+    uint8_t     t;
+    uint8_t     *sense_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_atio_entry: entered\n\r");
+#endif
+
+    t = pkt->initiator_id;
+    sense_ptr = ha->tsense + t * TARGET_SENSE_SIZE;
+    a64 = (uint64_t *)&phy_addr[0];
+    end_a64 = (uint64_t *)&end_addr[0];
+
+    switch (pkt->status & ~BIT_7)
+    {
+        case 7:                         /* Path invalid */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print("qla1280_atio_entry: Path invalid\n\r");
+#endif
+            break;
+        case 0x14:                  /* Target Bus Phase Sequence Failure */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print(
+                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
+#endif
+            if (pkt->status & BIT_7)
+            {
+                BCOPY((caddr_t)&pkt->sense_data, sense_ptr,TARGET_SENSE_SIZE);
+            }
+            else
+            {
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    *sense_ptr = 0x70;
+                    *(sense_ptr+2) = SD_HARDERR;
+                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                    *(sense_ptr+12) = SC_SELFAIL;
+            }
+            pkt->scsi_status = S_CKCON;
+            pkt->option_flags |= (uint32_t)OF_SSTS | (uint32_t)OF_NO_DATA;
+            if (ha->flags.enable_64bit_addressing)
+                qla1280_64bit_continue_io(ha, pkt, 0, 0);
+            else
+                qla1280_32bit_continue_io(ha, pkt, 0, 0);
+            break;
+        case 0x16:                  /* Requested Capability Not Available */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print(
+                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
+#endif
+            break;
+        case 0x17:                  /* Bus Device Reset Message Received */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print(
+                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
+#endif
+            break;
+        case 0x3D:                  /* CDB Received */
+
+            /* Check for invalid LUN */
+            if (pkt->lun && pkt->cdb[0] != SS_INQUIR &&
+                pkt->cdb[0] != SS_REQSEN)
+                pkt->cdb[0] = SS_TEST;
+
+            switch (pkt->cdb[0])
+            {
+                case SS_TEST:
+#ifdef QL_DEBUG_LEVEL_3
+                    qla1280_print("qla1280_atio_entry: SS_TEST\n\r");
+#endif
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    len = 0;
+                    if (pkt->lun == 0)
+                        pkt->scsi_status = S_GOOD;
+                    else
+                    {
+                        *sense_ptr = 0x70;
+                        *(sense_ptr+2) = SD_ILLREQ;
+                        *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                        *(sense_ptr+12) = SC_INVLUN;
+                        pkt->scsi_status = S_CKCON;
+                    }
+
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_NO_DATA;
+                    break;
+                case SS_REQSEN:
+#ifdef QL_DEBUG_LEVEL_3
+                    qla1280_print("qla1280_atio_entry: SS_REQSEN\n\r");
+#endif
+                    phy_addr[0] = ha->tsense_dma;
+                    phy_addr[1] = 0;
+                    *a64 += t * TARGET_SENSE_SIZE;
+                    if (pkt->cdb[4] > TARGET_SENSE_SIZE)
+                        len = TARGET_SENSE_SIZE;
+                    else
+                        len = pkt->cdb[4];
+                    pkt->scsi_status = S_GOOD;
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_DATA_IN;
+                    break;
+                case SS_INQUIR:
+#ifdef QL_DEBUG_LEVEL_3
+                    qla1280_print("qla1280_atio_entry: SS_INQUIR\n\r");
+#endif
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    phy_addr[0] = ha->tbuf_dma;
+                    phy_addr[1] = 0;
+                    *a64 += TARGET_INQ_OFFSET;
+
+                    if (pkt->lun == 0)
+                    {
+                            ha->tbuf->inq.id_type = ID_PROCESOR;
+                            ha->tbuf->inq.id_pqual = ID_QOK;
+                    }
+                    else
+                    {
+                            ha->tbuf->inq.id_type = ID_NODEV;
+                            ha->tbuf->inq.id_pqual = ID_QNOLU;
+                    }
+
+                    if (pkt->cdb[4] > sizeof(struct ident))
+                        len = sizeof(struct ident);
+                    else
+                        len = pkt->cdb[4];
+                    pkt->scsi_status = S_GOOD;
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_DATA_IN;
+                    break;
+                case SM_WRDB:
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    offset = pkt->cdb[5];
+                    offset |= pkt->cdb[4] << 8;
+                    offset |= pkt->cdb[3] << 16;
+                    len = pkt->cdb[8];
+                    len |= pkt->cdb[7] << 8;
+                    len |= pkt->cdb[6] << 16;
+                    end_addr[0] = phy_addr[0] = ha->tbuf_dma;
+                    end_addr[1] = phy_addr[1] = 0;
+                    *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
+                    switch (pkt->cdb[1] & 7)
+                    {
+                        case RW_BUF_HDATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_HDATA\n\r");
+#endif
+                            if (len > TARGET_DATA_SIZE + 4)
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                qla1280_print("qla1280_atio_entry: SM_WRDB, length > buffer size\n\r");
+#endif
+                                *sense_ptr = 0x70;
+                                *(sense_ptr+2) = SD_ILLREQ;
+                                *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                                *(sense_ptr+12) = SC_ILLCDB;
+                                pkt->scsi_status = S_CKCON;
+                                pkt->option_flags |= (uint32_t)OF_SSTS |
+                                        (uint32_t)OF_NO_DATA;
+                                len = 0;
+                            }
+                            else if (len)
+                            {
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_DATA_OUT;
+#ifdef QL_DEBUG_LEVEL_3
+                                    qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r");
+#endif
+                                    sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
+                                            pkt->target_id, pkt->lun, 0, offset);
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+
+                            break;
+                        case RW_BUF_DATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA\n\r");
+#endif
+                            *a64 += offset + TARGET_DATA_OFFSET;
+                            if (pkt->cdb[2] != 0 || *a64 >= *end_a64 ||
+                                *a64 + len > *end_a64)
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA BAD\n\r");
+                                    qla1280_print("buf_id=");
+                                    qla1280_output_number((uint32_t)pkt->cdb[2], 16);
+                                    qla1280_print(", offset=");
+                                    qla1280_output_number((uint32_t)offset, 16);
+                                    qla1280_print(", length=");
+                                    qla1280_output_number((uint32_t)len, 16);
+                                    qla1280_print("\n\r");
+#endif
+                                    *sense_ptr = 0x70;
+                                    *(sense_ptr+2) = SD_ILLREQ;
+                                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                                    *(sense_ptr+12) = SC_ILLCDB;
+                                    len = 0;
+                                    pkt->scsi_status = S_CKCON;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            else if (len)
+                            {
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_DATA_OUT;
+#ifdef QL_DEBUG_LEVEL_3
+                                    qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r");
+#endif
+                                    sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
+                                            pkt->target_id, pkt->lun, 0, offset);
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            break;
+                        default:
+#ifdef QL_DEBUG_LEVEL_2
+                            qla1280_print("qla1280_atio_entry: SM_WRDB unknown mode\n\r");
+#endif
+                            *sense_ptr = 0x70;
+                            *(sense_ptr+2) = SD_ILLREQ;
+                            *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                            *(sense_ptr+12) = SC_ILLCDB;
+                            len = 0;
+                            pkt->scsi_status = S_CKCON;
+                            pkt->option_flags |= (uint32_t)OF_SSTS |
+                                    (uint32_t)OF_NO_DATA;
+                            break;
+                    }
+                    break;
+                case SM_RDDB:
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    offset = pkt->cdb[5];
+                    offset |= pkt->cdb[4] << 8;
+                    offset |= pkt->cdb[3] << 16;
+                    len = pkt->cdb[8];
+                    len |= pkt->cdb[7] << 8;
+                    len |= pkt->cdb[6] << 16;
+                    end_addr[0] = phy_addr[0] = ha->tbuf_dma;
+                    end_addr[1] = phy_addr[1] = 0;
+                    *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
+                    switch (pkt->cdb[1] & 7)
+                    {
+                        case RW_BUF_HDATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_HDATA\n\r");
+#endif
+                            if (len)
+                            {
+                                ha->tbuf->hdr[0] = 0;
+                                ha->tbuf->hdr[1] =
+                                        (uint8_t)(TARGET_DATA_SIZE >> 16);
+                                ha->tbuf->hdr[2] =
+                                        (uint8_t)(TARGET_DATA_SIZE >> 8);
+                                ha->tbuf->hdr[3] = (uint8_t)TARGET_DATA_SIZE;
+                                if (len > TARGET_DATA_SIZE + 4)
+                                    len = TARGET_DATA_SIZE + 4;
+                                pkt->scsi_status = S_GOOD;
+                                pkt->option_flags |= (uint32_t)OF_SSTS |
+                                        (uint32_t)OF_DATA_IN;
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            break;
+                        case RW_BUF_DATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA\n\r");
+#endif
+                            *a64 += offset + TARGET_DATA_OFFSET;
+                            if (pkt->cdb[2] != 0 || *a64 >= *end_a64)
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA BAD\n\r");
+                                    qla1280_print("buf_id=");
+                                    qla1280_output_number((uint32_t)pkt->cdb[2], 16);
+                                    qla1280_print(", offset=");
+                                    qla1280_output_number((uint32_t)offset, 16);
+                                    qla1280_print("\n\r");
+#endif
+                                    *sense_ptr = 0x70;
+                                    *(sense_ptr+2) = SD_ILLREQ;
+                                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                                    *(sense_ptr+12) = SC_ILLCDB;
+                                    len = 0;
+                                    pkt->scsi_status = S_CKCON;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            else
+                            {
+                                    if (*a64 + len > *end_a64)
+                                        len = *end_a64 - *a64;
+                                    if (len)
+                                    {
+                                        pkt->scsi_status = S_GOOD;
+                                        pkt->option_flags |= (uint32_t)OF_SSTS |
+                                                (uint32_t)OF_DATA_IN;
+                                    }
+                                    else
+                                    {
+#ifdef QL_DEBUG_LEVEL_2
+                                            qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
+#endif
+                                            pkt->scsi_status = S_GOOD;
+                                            pkt->option_flags |= (uint32_t)OF_SSTS |
+                                                    (uint32_t)OF_NO_DATA;
+                                    }
+                            }
+                            break;
+                        case RW_BUF_DESC:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DESC\n\r");
+#endif
+                            if (len)
+                            {
+                                    if (len > 4)
+                                        len = 4;
+
+                                    ha->tbuf->hdr[0] = 0;
+                                    if (pkt->cdb[2] != 0)
+                                    {
+                                        ha->tbuf->hdr[1] = 0;
+                                        ha->tbuf->hdr[2] = 0;
+                                        ha->tbuf->hdr[3] = 0;
+                                    }
+                                    else
+                                    {
+                                            ha->tbuf->hdr[1] =
+                                                    (uint8_t)(TARGET_DATA_SIZE >> 16);
+                                            ha->tbuf->hdr[2] =
+                                                    (uint8_t)(TARGET_DATA_SIZE >> 8);
+                                            ha->tbuf->hdr[3] =
+                                                    (uint8_t)TARGET_DATA_SIZE;
+                                    }
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_DATA_IN;
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            break;
+                        default:
+#ifdef QL_DEBUG_LEVEL_2
+                            qla1280_print("qla1280_atio_entry: SM_RDDB unknown mode\n\r");
+#endif
+                            *sense_ptr = 0x70;
+                            *(sense_ptr+2) = SD_ILLREQ;
+                            *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                            *(sense_ptr+12) = SC_ILLCDB;
+                            len = 0;
+                            pkt->scsi_status = S_CKCON;
+                            pkt->option_flags |= (uint32_t)OF_SSTS |
+                                    (uint32_t)OF_NO_DATA;
+                            break;
+                    }
+                    break;
+                default:
+#ifdef QL_DEBUG_LEVEL_2
+                    qla1280_print("qla1280_atio_entry: Unknown SCSI command\n\r");
+                    qla1280_dump_buffer((caddr_t)&pkt->cdb[0], pkt->cdb_len);
+#endif
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    *sense_ptr = 0x70;
+                    *(sense_ptr+2) = SD_ILLREQ;
+                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                    *(sense_ptr+12) = SC_INVOPCODE;
+                    len = 0;
+                    pkt->scsi_status = S_CKCON;
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_NO_DATA;
+                    break;
+            }
+            if (ha->flags.enable_64bit_addressing)
+                qla1280_64bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr);
+            else
+                qla1280_32bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr);
+            break;
+        default:
+            break;
+    }
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_atio_entry: exiting normally\n\r");
+#endif
+}
+
+/*
+ *  qla1280_notify_entry
+ *      Processes received ISP immediate notify entry.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ *      pkt = entry pointer.
+ */
+STATIC void
+qla1280_notify_entry(scsi_qla_host_t *ha, notify_entry_t *pkt)
+{
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_notify_entry: entered\n\r");
+#endif
+
+    /* Acknowledge immediate notify */
+    qla1280_notify_ack(ha, pkt);
+
+    /* Issue notify entry to increment resource count */
+    qla1280_immed_notify(ha, pkt);
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_notify_entry: exiting normally\n\r");
+#endif
+}
+
+#endif  /* QLA1280_TARGET_MODE_SUPPORT */
+/*
+ *  qla1280_status_entry
+ *      Processes received ISP status entry.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      pkt          = entry pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt, srb_t **done_q_first,
+                     srb_t **done_q_last)
+{
+    uint32_t        b, t, l;
+    uint8_t         sense_sz = 0;
+    srb_t           *sp;
+    scsi_lu_t       *q;
+    Scsi_Cmnd       *cp;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_status_entry");
+#endif
+
+    /* Validate handle. */
+    if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+        sp = ha->outstanding_cmds[pkt->handle];
+    else
+        sp = 0;
+
+    if (sp)
+    {
+        /* Free outstanding command slot. */
+        ha->outstanding_cmds[pkt->handle] = 0;
+
+        cp = sp->cmd;
+        /* Generate LU queue on cntrl, target, LUN */
+        b = SCSI_BUS_32(cp);
+        t = SCSI_TCN_32(cp);
+        l = SCSI_LUN_32(cp);
+        q = LU_Q(ha, b, t, l);
+        if( pkt->comp_status || pkt->scsi_status )
+        {
+            DEBUG(qla1280_print( "scsi: comp_status = ");)
+            DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);)
+            DEBUG(qla1280_print( ", ");)
+            DEBUG(qla1280_print( " scsi_status = ");)
+            DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);)
+            DEBUG(qla1280_print( "\n\r");)
+            DEBUG(qla1280_print(", handle = ");)
+            DEBUG(qla1280_output_number((uint32_t)pkt->handle, 16);)
+            DEBUG(qla1280_print("\n\r");)
+        }
+
+        /* Target busy */
+        if ( pkt->scsi_status & SS_BUSY_CONDITION &&
+            pkt->scsi_status != SS_RESERVE_CONFLICT   )
+        {
+            CMD_RESULT(cp) = (int) (DID_BUS_BUSY << 16) |
+                    (pkt->scsi_status & 0xff);
+        }
+        else
+        {
+
+            /* Save ISP completion status */
+            CMD_RESULT(cp) = qla1280_return_status( pkt, cp );
+
+            if (pkt->scsi_status & SS_CHECK_CONDITION)
+            {
+                BZERO(cp->sense_buffer, CMD_SNSLEN(cp));
+                if (pkt->comp_status != CS_ARS_FAILED)
+                {
+                    if ( pkt->req_sense_length < CMD_SNSLEN(cp)  )
+                        sense_sz = pkt->req_sense_length;
+                    else
+                        sense_sz = CMD_SNSLEN(cp) - 1;
+
+                    BCOPY((caddr_t)&pkt->req_sense_data, cp->sense_buffer, sense_sz);
+
+                }
+#ifdef QL_DEBUG_LEVEL_2
+                DEBUG(qla1280_print(
+                        "qla1280_status_entry: Check condition Sense data, b");)
+                DEBUG(qla1280_output_number((uint32_t)b, 10);)
+                DEBUG(qla1280_print("t");)
+                DEBUG(qla1280_output_number((uint32_t)t, 10);)
+                DEBUG(qla1280_print("d");)
+                DEBUG(qla1280_output_number((uint32_t)l, 10);)
+                DEBUG(qla1280_print("\n\r");)
+                DEBUG(if (sense_sz))
+                    DEBUG(qla1280_dump_buffer(cp->sense_buffer, sense_sz);)
+#endif
+            }
+        }
+        /* Place command on done queue. */
+        qla1280_done_q_put(sp, done_q_first, done_q_last);
+    }
+    else
+    {
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print("qla1280_status_entry: ISP Invalid handle\n\r");
+#endif
+        printk(KERN_WARNING "qla1280: Status Entry invalid handle\n");
+        ha->flags.isp_abort_needed = TRUE;
+    }
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_status_entry");
+#endif
+}
+
+/*
+ *  qla1280_error_entry
+ *      Processes error entry.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      pkt          = entry pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_error_entry(scsi_qla_host_t *ha, response_t *pkt, srb_t **done_q_first,
+                    srb_t **done_q_last)
+{
+    srb_t   *sp;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_error_entry");
+#endif
+
+#ifdef QL_DEBUG_LEVEL_2
+    if (pkt->entry_status & BIT_3)
+        qla1280_print("qla1280_error_entry: BAD PAYLOAD flag error\n\r");
+    else if (pkt->entry_status & BIT_2)
+        qla1280_print("qla1280_error_entry: BAD HEADER flag error\n\r");
+    else if (pkt->entry_status & BIT_1)
+        qla1280_print("qla1280_error_entry: FULL flag error\n\r");
+    else
+        qla1280_print("qla1280_error_entry: UNKNOWN flag error\n\r");
+#endif
+
+    /* Validate handle. */
+    if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+        sp = ha->outstanding_cmds[pkt->handle];
+    else
+        sp = 0;
+
+    if (sp)
+    {
+        /* Free outstanding command slot. */
+        ha->outstanding_cmds[pkt->handle] = 0;
+
+        /* Bad payload or header */
+        if (pkt->entry_status & (BIT_3 + BIT_2))
+        {
+            /* Bad payload or header, set error status. */
+            /* CMD_RESULT(sp->cmd) = CS_BAD_PAYLOAD; */
+            CMD_RESULT(sp->cmd) = (int) DID_ERROR << 16;
+        }
+        else if (pkt->entry_status & BIT_1 ) /* FULL flag */
+        {
+            CMD_RESULT(sp->cmd) = (int) DID_BUS_BUSY << 16;
+        }
+        else
+        {
+            /* Set error status. */
+            CMD_RESULT(sp->cmd) =(int)  DID_ERROR << 16;
+        }
+        /* Place command on done queue. */
+        qla1280_done_q_put(sp, done_q_first, done_q_last);
+    }
+#if  QLA1280_64BIT_SUPPORT
+    else if (pkt->entry_type == COMMAND_A64_TYPE)
+    {
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print("qla1280_error_entry: ISP Invalid handle\n\r");
+#endif
+        printk(KERN_WARNING "!qla1280: Error Entry invalid handle");
+        ha->flags.isp_abort_needed = TRUE;
+    }
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_error_entry");
+#endif
+}
+
+/*
+ *  qla1280_abort_isp
+ *      Resets ISP and aborts all outstanding commands.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_abort_isp(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg = ha->iobase;
+    uint8_t         status = 0;
+    uint16_t        cnt;
+    srb_t           *sp;
+    scsi_lu_t       *q;
+    uint32_t        b, t, l;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_abort_isp");
+#endif
+
+    DRIVER_LOCK
+            ha->flags.isp_abort_needed = FALSE;
+    if (!ha->flags.abort_isp_active && ha->flags.online)
+    {
+        ha->flags.abort_isp_active = TRUE;
+
+        /* Disable ISP interrupts. */
+        WRT_REG_WORD(&reg->ictrl, 0);
+
+        /* Dequeue all commands in outstanding command list. */
+        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+        {
+            sp = ha->outstanding_cmds[cnt];
+            if (sp)
+            {
+                ha->outstanding_cmds[cnt] = 0;
+
+                /* Generate LU queue on controller, target, LUN */
+                b = SCSI_BUS_32(sp->cmd);
+                t = SCSI_TCN_32(sp->cmd);
+                l = SCSI_LUN_32(sp->cmd);
+
+                q = (scsi_lu_t       *)LU_Q(ha, b, t, l);
+
+                /* Reset outstanding command count. */
+                q->q_outcnt = 0;
+                q->q_flag &= ~QLA1280_QBUSY;
+                q->q_flag =  0;
+
+                /* Adjust watchdog timer for command. */
+                /* if (sp->flags & SRB_WATCHDOG)
+                sp->timeout += 2; */
+
+                /* Place request back on top of device queue. */
+                /* sp->flags &= ~(SRB_SENT | SRB_TIMEOUT); */ 
+                sp->flags = 0;
+                qla1280_putq_t(q, sp);
+            }
+        }
+
+        /* If firmware needs to be loaded */
+        if (qla1280_isp_firmware(ha))
+        {
+            if (!(status = qla1280_chip_diag(ha)))
+                status = qla1280_setup_chip(ha); 
+        }
+
+        if (!status)
+        {
+            /* Setup adapter based on NVRAM parameters. */
+            qla1280_nvram_config(ha); 
+
+            if (!(status = qla1280_init_rings(ha)))
+            {
+                /* Issue SCSI reset. */
+                for (b = 0; b < ha->ports; b++)
+                {
+                    qla1280_bus_reset(ha, b);
+                }
+                do
+                {
+                    /* Issue marker command. */
+                    ha->flags.reset_marker = FALSE;
+                    for (b = 0; b < ha->ports; b++)
+                    {
+                        ha->bus_settings[b].reset_marker = FALSE;
+                        qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+                    }
+                }while (ha->flags.reset_marker);
+
+                /* Enable host adapter target mode. */
+                for (b = 0; b < ha->ports; b++)
+                {
+                    if (!(status = qla1280_enable_tgt(ha, b)))
+                    {
+                        for (cnt = 0; cnt < MAX_LUNS; cnt++)
+                        {
+                            /* qla1280_enable_lun(ha, b, cnt); */
+                            qla1280_poll(ha);
+                        }
+                    }
+                    else
+                        break;
+                }
+
+                if (!status)
+                { 
+                    /* Enable ISP interrupts. */
+                    WRT_REG_WORD(&reg->ictrl, ISP_EN_INT + ISP_EN_RISC);
+                    ha->flags.abort_isp_active = FALSE;
+                    /* Restart queues that may have been stopped. */
+                    qla1280_restart_queues(ha);
+                }
+            }
+        }
+    }
+
+    if (status)
+    {
+        printk(KERN_WARNING
+                "qla1280: ISP error recovery failed, board disabled");
+        qla1280_reset_adapter(ha);
+        qla1280_abort_queues(ha);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+        qla1280_print("qla1280_abort_isp: **** FAILED ****\n\r");
+#endif
+    }
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_abort_isp");
+#endif
+    DRIVER_UNLOCK
+
+            return(status);
+}
+
+/*
+ *  qla1280_restart_queues
+ *      Restart all device queues.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_restart_queues(scsi_qla_host_t *ha)
+{
+    scsi_lu_t *q;
+    uint32_t  b, t, l;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_restart_queues");
+#endif
+
+    for (b = 0; b < ha->ports; b++)
+        for (t = 0; t < MAX_TARGETS; t++)
+            for (l = 0; l < MAX_LUNS; l++)
+            {
+                q = (scsi_lu_t *) LU_Q(ha, b, t, l);
+                if (q != NULL)
+                {
+                    /* Acquire LU queue specific lock */
+                    QLA1280_SCSILU_LOCK(q);
+
+                    if (q->q_first)
+                        qla1280_next(ha, q, b);
+                    else
+                        /* Release LU queue specific lock */
+                        QLA1280_SCSILU_UNLOCK(q);
+                }
+            }
+#ifdef QL_DEBUG_LEVEL_3
+            qla1280_print("qla1280_restart_queues: exiting normally\n");
+#endif
+}
+
+/*
+ *  qla1280_abort_queue_single
+ *      Abort all commands on a device queues.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void qla1280_abort_queue_single(scsi_qla_host_t *ha,uint32_t b,uint32_t t,uint32_t l,uint32_t stat)
+{
+    scsi_lu_t *q;
+    srb_t     *sp, *sp_next; 
+
+    ENTER("qla1280_abort_queue_single");
+    q = (scsi_lu_t * )LU_Q(ha, b, t, l);
+    if (q != NULL)
+    {
+        /* Acquire LU queue specific lock */
+        QLA1280_SCSILU_LOCK(q);
+
+        sp = q->q_first;
+        q->q_first = q->q_last = NULL;
+
+        QLA1280_SCSILU_UNLOCK(q);
+
+        while (sp)
+        {
+            sp_next = sp->s_next;
+            CMD_RESULT(sp->cmd) = stat;
+            qla1280_done_q_put(sp, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+            sp = sp_next;
+        }
+    }
+    LEAVE("qla1280_abort_queue_single");
+}
+
+/*
+ *  qla1280_abort_queues
+ *      Abort all commands on device queues.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_abort_queues(scsi_qla_host_t *ha)
+{
+    uint32_t  b, t, l;
+
+    ENTER("qla1280_abort_queues");
+
+    for (b = 0; b < ha->ports; b++)
+        for (t = 0; t < MAX_TARGETS; t++)
+            for (l = 0; l < MAX_LUNS; l++)
+                qla1280_abort_queue_single(ha,b,t,l,DID_RESET);
+
+            LEAVE("qla1280_abort_queues");
+}
+
+/*
+ * qla1280_debounce_register
+ *      Debounce register.
+ *
+ * Input:
+ *      port = register address.
+ *
+ * Returns:
+ *      register value.
+ */
+STATIC uint16_t
+qla1280_debounce_register(volatile uint16_t *addr)
+{
+    volatile uint16_t ret;
+    volatile uint16_t ret2;
+
+    do
+    {
+        ret = RD_REG_WORD(addr);
+        ret2 = RD_REG_WORD(addr);
+    }while (ret != ret2);
+
+    return(ret);
+}
+
+
+/*
+ * Declarations for load module
+ */
+#ifdef MODULE
+Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
+
+#include "scsi_module.c"
+#endif
+
+/************************************************************************
+ * qla1280_check_for_dead_scsi_bus                                      *
+ *                                                                      *
+ *    This routine checks for a dead SCSI bus                           *
+ ************************************************************************/
+#define SET_SXP_BANK            0x0100
+#define SCSI_PHASE_INVALID      0x87FF
+int  qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp)
+{
+    uint16_t  config_reg, scsi_control;
+    device_reg_t    *reg = ha->iobase;
+    uint32_t  b;
+    Scsi_Cmnd       *cp;
+
+    /*
+     * If SCSI Bus is Dead because of bad termination,
+     * we will return a status of Selection timeout.
+     */
+ 
+     cp = sp->cmd;
+     b = SCSI_BUS_32(cp);
+    if (ha->bus_settings[b].scsi_bus_dead)
+    {
+        WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
+        config_reg = RD_REG_WORD(&reg->cfg_1);
+        WRT_REG_WORD(&reg->cfg_1,SET_SXP_BANK);
+        scsi_control = RD_REG_WORD(&reg->scsiControlPins);
+        WRT_REG_WORD(&reg->cfg_1,config_reg);
+        WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+
+        if (scsi_control == SCSI_PHASE_INVALID)
+        {
+            CMD_RESULT(cp) = DID_NO_CONNECT << 16;
+            CMD_HANDLE(cp) = (unsigned char *) 0;
+            /* ha->actthreads--; */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+            sti(); 
+            (*(cp)->scsi_done)(cp);
+            cli(); 
+#else
+            (*(cp)->scsi_done)(cp);
+#endif
+            return(TRUE);   /* bus is dead */
+        }
+        else
+        {
+            ha->bus_settings[b].scsi_bus_dead = FALSE;
+            ha->bus_settings[b].failed_reset_count= 0; 
+        }
+    }
+    return(FALSE);   /* bus is not dead */
+}
+
+STATIC uint8_t
+qla12160_set_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l, nvram160_t *nv)
+{
+    uint16_t        mb[MAILBOX_REGISTER_COUNT];
+
+    /* Set Target Parameters. */
+    mb[0] = MBC_SET_TARGET_PARAMETERS;
+    mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+    mb[1] <<= 8;
+    mb[2] = nv->bus[b].target[t].parameter.c << 8;
+    mb[2] |= TP_AUTO_REQUEST_SENSE;
+    mb[2] &= ~TP_STOP_QUEUE;
+    mb[2] |=  (nv->bus[b].target[t].flags.enable_ppr << 5);
+    mb[3] = nv->bus[b].target[t].flags.sync_offset << 8;
+    mb[3] |= nv->bus[b].target[t].sync_period;
+
+    mb[6] = nv->bus[b].target[t].flags.ppr_options << 8;
+    mb[6] |= nv->bus[b].target[t].flags.ppr_bus_width;
+    return( qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]) ) ;
+}
+
+STATIC void
+qla12160_get_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l)
+{
+    uint16_t        mb[MAILBOX_REGISTER_COUNT];
+
+    mb[0] = MBC_GET_TARGET_PARAMETERS;
+    mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+    mb[1] <<= 8;
+    qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]);
+    if( mb[3] != 0 )
+    printk(KERN_INFO "scsi(%d:%d:%d:%d): Synchronous tranfer at period %d, offset %d. \n",
+        (int)ha->host_no, b, t, l, (mb[3] &0xff), (mb[3] >> 8));
+
+    if ( (mb[2] & BIT_5) &&  ((mb[6] >> 8) & 0xff) >= 2 )
+            printk(KERN_INFO "scsi(%d:%d:%d:%d): Dual Transition enabled.\n",
+                          (int)ha->host_no, b, t, l);
+}
+
+
+#ifdef QL_DEBUG_ROUTINES
+/****************************************************************************/
+/*                         Driver Debug Functions.                          */
+/****************************************************************************/
+
+/*
+ *  Get byte from I/O port
+ */
+STATIC uint8_t
+qla1280_getbyte(uint8_t *port)
+{
+    uint8_t ret;
+
+#if MEMORY_MAPPED_IO
+    ret = *port;
+#else
+    ret = inb((int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_getbyte: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)ret, 16);
+        qla1280_print("\n\r");
+    }
+
+    return(ret);
+}
+
+/*
+ *  Get word from I/O port
+ */
+STATIC uint16_t
+qla1280_getword(uint16_t *port)
+{
+    uint16_t ret;
+
+#if MEMORY_MAPPED_IO
+    ret = *port;
+#else
+    ret = inw((int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_getword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)ret, 16);
+        qla1280_print("\n\r");
+    }
+
+    return(ret);
+}
+
+/*
+ *  Get double word from I/O port
+ */
+STATIC uint32_t
+qla1280_getdword(uint32_t *port)
+{
+    uint32_t ret;
+
+#if MEMORY_MAPPED_IO
+    ret = *port;
+#else
+    ret = inl((int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_getdword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)ret, 16);
+        qla1280_print("\n\r");
+    }
+
+    return(ret);
+}
+
+/*
+ *  Send byte to I/O port
+ */
+STATIC void
+qla1280_putbyte(uint8_t *port, uint8_t data)
+{
+#if MEMORY_MAPPED_IO
+    *port = data;
+#else
+    outb(data, (int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_putbyte: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)data, 16);
+        qla1280_print("\n\r");
+    }
+}
+
+/*
+ *  Send word to I/O port
+ */
+STATIC void
+qla1280_putword(uint16_t *port, uint16_t data)
+{
+#if MEMORY_MAPPED_IO
+    *port = data;
+#else
+#ifdef _LINUX_IOPORTS
+    outw(data, (int)port);
+#else
+    outw((int)port, data);
+#endif
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_putword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)data, 16);
+        qla1280_print("\n\r");
+    }
+}
+
+/*
+ *  Send double word to I/O port
+ */
+STATIC void
+qla1280_putdword(uint32_t *port, uint32_t data)
+{
+#if MEMORY_MAPPED_IO
+    *port = data;
+#else
+#ifdef _LINUX_IOPORTS
+    outl(data,(int)port);
+#else
+    outl((int)port, data);
+#endif
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_putdword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)data, 16);
+        qla1280_print("\n\r");
+    }
+}
+
+/*
+ * Dummy function to prevent warnings for
+ * declared and unused debug functions
+ */
+void
+qla1280_debug(void)
+{
+    qla1280_getbyte(0);
+    qla1280_getword(0);
+    qla1280_getdword(0);
+    qla1280_putbyte(0, 0);
+    qla1280_putword(0, 0);
+    qla1280_putdword(0, 0);
+}
+
+/*
+ *  Out character to COM2 port.
+ *      PORT must be at standard address for COM2 = 0x2F8,
+ *      or COM1 = 0x3F8
+ */
+#define OUTB(addr,data)   outb((data),(addr))
+
+STATIC void
+qla1280_putc(uint8_t c)
+{
+#ifdef QL_DEBUG_CONSOLE
+    printk("%c", c);
+#else
+    int     com_addr              = 0x2f8;
+    int     hardware_flow_control = 1;
+    int     software_flow_control = 0;
+    uint8_t data;
+
+    /* Wait for transmitter holding and shift registers for empty. */
+    do
+    {
+        data = inb(com_addr+5);
+    }while (!(data & BIT_6));
+
+    /*
+    * Set BAUD rate for COM2 to 19200 (0x6)
+    */
+
+    /* Select rate divisor. */
+    OUTB(com_addr+3, 0x83); 
+
+    /* BAUD rate divisor LSB. */
+    OUTB(com_addr, 0xc);                    /* 0xC = 9600 baud */
+
+    /* BAUD rate divisor MSB. */
+    OUTB(com_addr+1, 0);
+
+    /* Set No parity, 8 bits, 1 stop bit and
+    select interrupt enable register. */
+    OUTB(com_addr+3, 3);
+
+    /* Disable interrupts. */
+    OUTB(com_addr+1, 0);
+
+    /* Set data terminal ready and request to send */
+    OUTB(com_addr+4,3);
+
+    if (hardware_flow_control)
+    {
+        /* Wait for clear-to-send and data-set-ready */
+        do
+        {
+            data = inb(com_addr+6) & (BIT_5 + BIT_4);
+        }while (data != (BIT_5 + BIT_4));
+    }
+    else if (software_flow_control)
+    {
+        /* Test for data ready. */
+        data = inb(com_addr+5);
+        if (data & BIT_0)
+        {
+            /* If XOFF */
+            data = inb(com_addr);
+            if (data == '\023')
+            {
+                /* Wait for XON */
+                do
+                {
+                    /* Wait for char */
+                    do
+                    {
+                        data = inb(com_addr+5);
+                    }while (!(data & BIT_0));
+                    data = inb(com_addr);
+                }while (data != '\021');
+            }
+        }
+    }
+
+    /* Output character. */
+    OUTB(com_addr, c);
+#endif
+}
+
+/*
+ *  Out NULL terminated string to COM port.
+ */
+STATIC void
+qla1280_print(caddr_t s)
+{
+    if (ql_debug_print)
+    {
+#ifdef QL_DEBUG_CONSOLE
+        printk("%s",s);
+#else
+        /* Output string. */
+        while (*s)
+            qla1280_putc(*s++);
+#endif
+    }
+}
+
+/*
+ *  Output long number to COM port.
+ */
+STATIC void
+qla1280_output_number(uint32_t n, uint8_t base)
+{
+    int8_t str[12];
+    int8_t *s     = &str[11];
+    int8_t output = 0;
+    int8_t hex    = FALSE;
+
+    if (ql_debug_print)
+    {
+        if (base == 10 || base == 16)
+        {
+            if (base == 16 && n > 9)
+                hex = TRUE;
+
+            *s = 0;
+            do
+            {
+                s--;
+                *s = n % base;
+                if (*s > 9)
+                    *s += 55;
+                else
+                    *s += '0';
+                n /= base;
+            }while (n);
+
+            for (; *s; s++)
+            {
+                if (*s != '0')
+                    output = 1;
+                if (output)
+                    qla1280_putc(*s);
+            }
+            if (!output)
+                qla1280_putc(*--s);
+
+            if (hex)
+                qla1280_putc('h');
+        }
+    }
+}
+
+STATIC void
+qla1280_dump_buffer(caddr_t b, uint32_t size)
+{
+    uint32_t cnt;
+    uint8_t c;
+
+    if (ql_debug_print)
+    {
+        qla1280_print(
+                " 0   1   2   3   4   5   6   7   8   9   Ah  Bh  Ch  Dh  Eh  Fh\n\r");
+        qla1280_print(
+                "---------------------------------------------------------------\n\r");
+
+        for (cnt = 0; cnt < size; )
+        {
+            c = *b++;
+            if (c < 16)
+                qla1280_putc(' ');
+            qla1280_output_number((uint32_t)c, 16);
+            cnt++;
+            if (!(cnt % 16))
+                qla1280_print("\n\r");
+            else if (c < 10)
+                qla1280_print("  ");
+            else
+                qla1280_putc(' ');
+        }
+        if (cnt % 16)
+            qla1280_print("\n\r");
+    }
+}
+/**************************************************************************
+ *   ql1280_print_scsi_cmd
+ *
+ **************************************************************************/
+void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd)
+{
+    scsi_qla_host_t *ha;
+    struct Scsi_Host  *host = cmd->host;
+    srb_t           *sp;
+   /* struct scatterlist *sg; */
+
+    int i;
+    ha = (scsi_qla_host_t *) host->hostdata;
+
+    ql_debug_print = 1;
+    sp = (srb_t *) CMD_SP(cmd);
+    sprintf(debug_buff,"SCSI Command @= 0x%p, Handle=0x%p\n\r", cmd, CMD_HANDLE(cmd));
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n\r",
+            cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
+    qla1280_print(debug_buff);
+    qla1280_print(" CDB = ");
+    for (i = 0; i < cmd->cmd_len; i++)
+    {
+        sprintf(debug_buff,"0x%02x ", cmd->cmnd[i]);
+        qla1280_print(debug_buff);
+    }
+    sprintf(debug_buff,"  seg_cnt =%d\n\r",cmd->use_sg);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  request buffer=0x%p, request buffer len=0x%x\n\r",cmd->request_buffer,cmd->request_bufflen);
+    qla1280_print(debug_buff);
+    /* if( cmd->use_sg )
+    {
+       sg = (struct scatterlist *) cmd->request_buffer;
+       qla1280_print("  SG buffer: \n\r");
+       qla1280_dump_buffer((caddr_t)sg, (cmd->use_sg*sizeof(struct scatterlist)) );
+    } */
+    sprintf(debug_buff,"  tag=%d, flags=0x%x, transfersize=0x%x \n\r", 
+            cmd->tag, cmd->flags,cmd->transfersize );
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  Pid=%d, SP=0x%p\n\r", (int)cmd->pid, CMD_SP(cmd));
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  r_start=0x%lx, u_start=0x%lx\n\r",sp->r_start,sp->u_start);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff," underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n\r", cmd->underflow, sp->dir,cmd->request.cmd);    
+    qla1280_print(debug_buff);
+}
+/**************************************************************************
+ *   ql1280_dump_device
+ *
+ **************************************************************************/
+void
+ql1280_dump_device(scsi_qla_host_t *ha)
+{
+
+    Scsi_Cmnd       *cp;
+    srb_t           *sp;
+    int i;
+    qla1280_print("Outstanding Commands on controller:\n\r");   
+    for ( i=0; i < MAX_OUTSTANDING_COMMANDS; i++ )
+    {
+        if( (sp = ha->outstanding_cmds[i]) == NULL )
+            continue;
+        if( (cp = sp->cmd) == NULL )
+            continue;
+        qla1280_print_scsi_cmd(cp);
+    }
+
+}
+#endif
+
+#ifdef  QLA1280_UNUSED 
+/**************************************************************************
+ *   ql1280_dump_regs
+ *
+ **************************************************************************/
+static void qla1280_dump_regs(struct Scsi_Host *host)
+{
+    printk("Mailbox registers:\n");
+    printk("qla1280 : mbox 0 0x%04x \n", inw(host->io_port + 0x70));
+    printk("qla1280 : mbox 1 0x%04x \n", inw(host->io_port + 0x72));
+    printk("qla1280 : mbox 2 0x%04x \n", inw(host->io_port + 0x74));
+    printk("qla1280 : mbox 3 0x%04x \n", inw(host->io_port + 0x76));
+    printk("qla1280 : mbox 4 0x%04x \n", inw(host->io_port + 0x78));
+    printk("qla1280 : mbox 5 0x%04x \n", inw(host->io_port + 0x7a));
+}
+#endif
+
+
+
+#if  STOP_ON_ERROR 
+/**************************************************************************
+ *   ql1280_panic
+ *
+ **************************************************************************/
+static void qla1280_panic(char *cp, struct Scsi_Host *host)
+{
+    scsi_qla_host_t *ha;
+    long  *fp;
+
+    ha = (scsi_qla_host_t *) host->hostdata;
+    printk("qla1280 - PANIC:  %s\n",cp);
+    printk("Current time=0x%lx\n", jiffies);
+    printk("Number of pending commands =0x%lx\n", ha->actthreads);
+    printk("Number of SCSI queued commands =0x%lx\n", ha->qthreads);
+    printk("Number of free entries = (%d)\n",ha->req_q_cnt);
+    printk("Request Queue @ 0x%lx, Response Queue @ 0x%lx\n",
+                        ha->request_dma,
+                        ha->response_dma);
+    printk("Request In Ptr %d\n", ha->req_ring_index );
+    fp = (long *) &ha->flags;
+    printk("HA flags =0x%lx\n", *fp);
+    DEBUG2(ql_debug_print = 1;)
+    /* DEBUG2(ql1280_dump_device((scsi_qla_host_t *) host->hostdata)); */
+#ifdef  QLA1280_UNUSED 
+    qla1280_dump_regs(host);
+#endif
+    sti();  
+    panic("Ooops");  
+    /* cli(); 
+    for(;;)
+    { 
+        barrier();
+    sti();  
+    }
+    */
+}
+#endif
+
+#ifdef  QLA1280_UNUSED 
+static void qla1280_set_flags(char * s)
+{
+}
+#endif
+
+/**************************************************************************
+ *   qla1280_setup
+ *
+ *   Handle Linux boot parameters. This routine allows for assigning a value
+ *   to a parameter with a ':' between the parameter and the value.
+ *   ie. qla1280=max_reqs:0x0A,verbose
+ **************************************************************************/
+void
+qla1280_setup(char *s, int *dummy)
+{
+    char *end, *str, *cp;
+
+#ifdef  QLA1280_UNUSED 
+    static struct
+    {
+        const char *name;
+        int      siz;
+        void  (*func)();
+        int   arg;
+    } options[] =
+    {
+        { "dump_regs", 9,  &qla1280_dump_regs, 0 
+        },
+        { "verbose", 7, &qla1280_set_flags, 0x1 
+        },
+        { "",    0, NULL, 0 
+        }
+    };
+#endif
+
+    printk("scsi: Processing Option str = %s\n", s);
+    end = strchr(s, '\0');
+    /* locate command */
+    str = s;
+    for( cp = s; *cp && cp != end; cp++ ) 
+    {
+       cp = qla1280_get_token(cp, str);
+       printk("scsi: token str = %s\n", str);
+       /* if found execute routine */
+
+    }
+    
+}
+
+static char	*qla1280_get_token(char *cmdline, char *str )
+{
+    register	char 	*cp = cmdline;
+
+        /* skip preceeding spaces */
+        while(strchr(cp,' '))
+            ++cp;
+        /* symbol starts here */
+        str = cp;
+        /* skip char if not a space or : */
+        while (*cp && !( strchr(cp,' ') || strchr(cp,':'))  )
+            cp++;
+        *cp = '\0';
+        return( cp );
+}
+
+/*
+ * Overrides for Emacs so that we almost follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 2
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -2
+ * c-argdecl-indent: 2
+ * c-label-offset: -2
+ * c-continued-statement-offset: 2
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
+
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/qla1280.h linux/drivers/scsi/qla1280.h
--- v2.3.42/linux/drivers/scsi/qla1280.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/qla1280.h	Wed Feb  9 21:34:55 2000
@@ -0,0 +1,1737 @@
+/*************************************************************************
+ *                  QLOGIC LINUX SOFTWARE
+ *
+ * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.x).
+ *
+ * COPYRIGHT (C) 1996-2000 QLOGIC CORPORATION    
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the Qlogic's Linux Software License.
+ *
+ * This program is WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistribution's or source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ *****************************************************************************/
+ 
+/*************************************************************************************
+			QLOGIC CORPORATION SOFTWARE
+           "GNU" GENERAL PUBLIC LICENSE
+    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
+                 AND MODIFICATION
+
+This GNU General Public License ("License") applies solely to QLogic Linux 
+Software ("Software") and may be distributed under the terms of this License.  
+ 
+1. You may copy and distribute verbatim copies of the Software's source code as 
+you receive it, in any medium, provided that you conspicuously and appropriately 
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Software a copy of this License along
+with the Software. 
+
+You may charge a fee for the physical act of transferring a copy, and you may at your
+option offer warranty protection in exchange for a fee.
+ 
+2. You may modify your copy or copies of the Software or any portion of it, thus forming
+a work based on the Software, and copy and distribute such modifications or work under
+the terms of Section 1 above, provided that you also meet all of these conditions:
+ 
+* a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change. 
+
+* b) You must cause any work that you distribute or publish that in whole or in part
+contains or is derived from the Software or any part thereof, to be licensed as a
+whole at no charge to all third parties under the terms of this License. 
+
+* c) If the modified Software normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary way,
+to print or display an announcement including an appropriate copyright notice and a 
+notice that there is no warranty (or else, saying that you provide a warranty) and that
+users may redistribute the Software under these conditions, and telling the user how to
+view a copy of this License. (Exception:if the Software itself is interactive but does 
+not normally print such an announcement, your work based on the Software is not required
+to print an announcement.) 
+
+These requirements apply to the modified work as a whole. If identifiable sections of
+that work are not derived from the Software, and can be reasonably considered independent
+and separate works in themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you distribute the same
+sections as part of a whole which is a work based on the Software, the distribution of the
+whole must be on the terms of this License, whose permissions for other licensees extend
+to the entire whole, and thus to each and every part regardless of who wrote it. 
+
+3. You may copy and distribute the Software (or a work based on it, under Section 2) in 
+object code or executable form under the terms of Sections 1 and 2 above provided that
+you also do one of the following: 
+
+* a) Accompany it with the complete corresponding machine-readable source code, which must
+be distributed under the terms of Sections 1 and 2 above on a medium customarily used for
+software interchange; or, 
+
+* b) Accompany it with a written offer, valid for at least three years, to give any third
+party, for a charge no more than your cost of physically performing source distribution,
+a complete machine-readable copy of the corresponding source code, to be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
+or,
+
+* c) Accompany it with the information you received as to the offer to distribute 
+corresponding source code. (This alternative is allowed only for noncommercial distribution
+and only if you received the Software in object code or executable form with such an offer,
+in accord with Subsection b above.) 
+
+The source code for a work means the preferred form of the work for making modifications
+to it. For an executable work, complete source code means all the source code for all 
+modules it contains, plus any associated interface definition files, plus the scripts used
+to control compilation and installation of the executable.     
+
+If distribution of executable or object code is made by offering access to copy from a 
+designated place, then offering equivalent access to copy the source code from the same
+place counts as distribution of the source code, even though third parties are not 
+compelled to copy the source along with the object code. 
+
+4. You may not copy, modify, sublicense, or distribute the Software except as expressly 
+provided under this License. Any attempt otherwise to copy, modify, sublicense or 
+distribute the Software is void, and will automatically terminate your rights under this
+License. However, parties who have received copies, or rights, from you under this License
+will not have their licenses terminated so long as such parties remain in full compliance. 
+
+5. This license grants you world wide, royalty free non-exclusive rights to modify or 
+distribute the Software or its derivative works. These actions are prohibited by law 
+if you do not accept this License. Therefore, by modifying or distributing the Software
+(or any work based on the Software), you indicate your acceptance of this License to do
+so, and all its terms and conditions for copying, distributing or modifying the Software
+or works based on it.
+ 
+6. Each time you redistribute the Software (or any work based on the Software), the 
+recipient automatically receives a license from the original licensor to copy, distribute
+or modify the Software subject to these terms and conditions. You may not impose any 
+further restrictions on the recipients' exercise of the rights granted herein. You are
+not responsible for enforcing compliance by third parties to this License.
+ 
+7. If, as a consequence of a court judgment or allegation of patent infringement or for
+any other reason (not limited to patent issues), conditions are imposed on you 
+(whether by court order, agreement or otherwise) that contradict the conditions of this
+License, they do not excuse you from the conditions of this License. If you cannot 
+distribute so as to satisfy simultaneously your obligations under this License 
+and any other pertinent obligations, then as a consequence you may not distribute the
+Software at all.    
+
+If any portion of this section is held invalid or unenforceable under any particular 
+circumstance, the balance of the section is intended to apply and the section as a whole
+is intended to apply in other circumstances. 
+NO WARRANTY
+
+11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO 
+WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
+OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, 
+EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. 
+SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+ 
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
+REDISTRIBUTE THE SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
+DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
+DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING 
+BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO 
+OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS 
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+END OF TERMS AND CONDITIONS 
+
+*************************************************************************************/ 
+
+ 
+#ifndef _IO_HBA_QLA1280_H           /* wrapper symbol for kernel use */
+#define _IO_HBA_QLA1280_H           /* subject to change without notice */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <linux/version.h>
+
+/*
+ * Enable define statement to ignore Data Underrun Errors,
+ * remove define statement to enable detection.
+ */
+/* #define  DATA_UNDERRUN_ERROR_DISABLE */
+
+/*
+ * Driver debug definitions.
+ */
+/* #define QL_DEBUG_LEVEL_1 */       /* Output register accesses to COM2. */
+/* #define QL_DEBUG_LEVEL_2 */           /* Output error msgs to COM2. */
+/* #define QL_DEBUG_LEVEL_3 */          /* Output function trace msgs to COM2. */
+/* #define QL_DEBUG_LEVEL_4 */       /* Output NVRAM trace msgs to COM2. */
+/* #define QL_DEBUG_LEVEL_5 */         /* Output ring trace msgs to COM2. */
+/* #define QL_DEBUG_LEVEL_6 */      /* Output WATCHDOG timer trace to COM2. */
+/* #define QL_DEBUG_LEVEL_7 */      /* Output RISC load trace msgs to COM2. */
+
+#define QL_DEBUG_CONSOLE              /* Output to console instead of COM2. */
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+
+#ifndef KERNEL_VERSION
+#  define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)
+#  if defined(__sparc_v9__) || defined(__powerpc__)
+#    error "PPC and Sparc platforms are only support under 2.1.92 and above"
+#  endif
+#endif
+
+
+/* 
+ * Locking
+ */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+#  include <linux/spinlock.h>
+#  include <linux/smp.h>
+#  define cpuid smp_processor_id()
+#  if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+#    define DRIVER_LOCK_INIT \
+       spin_lock_init(&ha->spin_lock);
+#    define DRIVER_LOCK \
+       if(!ha->cpu_lock_count[cpuid]) { \
+         spin_lock_irqsave(&ha->spin_lock, cpu_flags); \
+         ha->cpu_lock_count[cpuid]++; \
+       } else { \
+         ha->cpu_lock_count[cpuid]++; \
+       }
+#    define DRIVER_UNLOCK \
+       if(--ha->cpu_lock_count[cpuid] == 0) \
+         spin_unlock_irqrestore(&ha->spin_lock, cpu_flags);
+#  else
+#    define DRIVER_LOCK_INIT
+#    define DRIVER_LOCK
+#    define DRIVER_UNLOCK
+#  endif 
+#else
+#  define cpuid 0
+#  define DRIVER_LOCK_INIT
+#  define DRIVER_LOCK \
+       save_flags(cpu_flags); \
+       cli();
+#  define DRIVER_UNLOCK \
+       restore_flags(cpu_flags);
+#  define le32_to_cpu(x) (x)
+#  define cpu_to_le32(x) (x)
+#endif
+
+/*
+ * Data bit definitions.
+ */
+#define BIT_0   0x1
+#define BIT_1   0x2
+#define BIT_2   0x4
+#define BIT_3   0x8
+#define BIT_4   0x10
+#define BIT_5   0x20
+#define BIT_6   0x40
+#define BIT_7   0x80
+#define BIT_8   0x100
+#define BIT_9   0x200
+#define BIT_10  0x400
+#define BIT_11  0x800
+#define BIT_12  0x1000
+#define BIT_13  0x2000
+#define BIT_14  0x4000
+#define BIT_15  0x8000
+#define BIT_16  0x10000
+#define BIT_17  0x20000
+#define BIT_18  0x40000
+#define BIT_19  0x80000
+#define BIT_20  0x100000
+#define BIT_21  0x200000
+#define BIT_22  0x400000
+#define BIT_23  0x800000
+#define BIT_24  0x1000000
+#define BIT_25  0x2000000
+#define BIT_26  0x4000000
+#define BIT_27  0x8000000
+#define BIT_28  0x10000000
+#define BIT_29  0x20000000
+#define BIT_30  0x40000000
+#define BIT_31  0x80000000
+
+/*
+ * Common size type definitions
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+typedef unsigned char  uint8_t; 
+typedef unsigned short uint16_t; 
+typedef unsigned long  uint32_t; 
+typedef char  int8_t; 
+typedef short int16_t; 
+typedef long  int32_t; 
+#endif
+
+/*
+ *  Local Macro Definitions.
+ */
+#if defined(QL_DEBUG_LEVEL_1) || defined(QL_DEBUG_LEVEL_2) || \
+    defined(QL_DEBUG_LEVEL_3) || defined(QL_DEBUG_LEVEL_4) || \
+    defined(QL_DEBUG_LEVEL_5) || defined(QL_DEBUG_LEVEL_6) || \
+    defined(QL_DEBUG_LEVEL_7)
+    #define QL_DEBUG_ROUTINES
+#endif
+
+/*
+ * I/O port macros
+*/
+#define LINUX_IOPORTS                     /* Linux in/out routines are define*/
+                                          /* differently from other OSs      */
+/* #define MEMORY_MAPPED_IO */            /* Enable memory mapped I/O */
+#undef MEMORY_MAPPED_IO            /* Disable memory mapped I/O */
+
+#ifdef QL_DEBUG_LEVEL_1
+#define RD_REG_BYTE(addr)         qla1280_getbyte((uint8_t *)addr)
+#define RD_REG_WORD(addr)         qla1280_getword((uint16_t *)addr)
+#define RD_REG_DWORD(addr)        qla1280_getdword((uint32_t *)addr)
+#define WRT_REG_BYTE(addr, data)  qla1280_putbyte((uint8_t *)addr, data)
+#define WRT_REG_WORD(addr, data)  qla1280_putword((uint16_t *)addr, data)
+#define WRT_REG_DWORD(addr, data) qla1280_putdword((uint32_t *)addr, data)
+#else  /* QL_DEBUG_LEVEL_1 */
+#ifdef MEMORY_MAPPED_IO
+       #define RD_REG_BYTE(addr)         readb((unsigned long) (addr)
+       #define RD_REG_WORD(addr)         readw((unsigned long) (addr)
+       #define RD_REG_DWORD(addr)        readl((unsigned long) (addr)
+       #define WRT_REG_BYTE(addr, data)  writeb((data), (unsigned long) (addr))
+       #define WRT_REG_WORD(addr, data)  writew((data), (unsigned long) (addr))
+       #define WRT_REG_DWORD(addr, data) writel((data), (unsigned long) (addr))
+#else   /* MEMORY_MAPPED_IO */
+#define RD_REG_BYTE(addr)         (inb((unsigned long)addr))
+#define RD_REG_WORD(addr)         (inw((unsigned long)addr))
+#define RD_REG_DWORD(addr)        (inl((unsigned long)addr))
+#ifdef LINUX_IOPORTS
+/* Parameters are reversed in Linux */
+#define WRT_REG_BYTE(addr, data)  (outb(data,(unsigned long)addr))
+#define WRT_REG_WORD(addr, data)  (outw(data,(unsigned long)addr))
+#define WRT_REG_DWORD(addr, data) (outl(data,(unsigned long)addr))
+#else
+#define WRT_REG_BYTE(addr, data)  (outb((unsigned long)addr, data))
+#define WRT_REG_WORD(addr, data)  (outw((unsigned long)addr, data))
+#define WRT_REG_DWORD(addr, data) (outl((unsigned long)addr, data))
+#endif
+#endif  /* MEMORY_MAPPED_IO */
+#endif    /* QL_DEBUG_LEVEL_1 */
+
+/*
+ * Host adapter default definitions.
+ */
+#define MAX_BUSES       2             /* 2 */
+#define MAX_B_BITS      1
+
+#define MAX_TARGETS     16             /* 16 */
+#define MAX_T_BITS      4              /* 4 */
+
+#define MAX_LUNS        8              /* 32 */
+#define MAX_L_BITS      3               /* 5 */
+
+/*
+ * Watchdog time quantum
+ */
+#define QLA1280_WDG_TIME_QUANTUM   5    /* In seconds */
+
+/* Command retry count (0-65535) */
+#define COMMAND_RETRY_COUNT   255
+
+/* Maximum outstanding commands in ISP queues (1-65535) */
+#define MAX_OUTSTANDING_COMMANDS   512
+
+/* ISP request and response entry counts (37-65535) */
+#define REQUEST_ENTRY_CNT       256     /* Number of request entries. */
+#define RESPONSE_ENTRY_CNT      16      /* Number of response entries. */
+
+/* Maximum equipage per controller */
+#define MAX_EQ          (MAX_BUSES * MAX_TARGETS * MAX_LUNS)
+
+/* Number of segments 1 - 65535 */
+#define SG_SEGMENTS     32             /* Cmd entry + 6 continuations */
+
+
+typedef struct timer_list   timer_t;         /* timer */
+
+/*
+ * SCSI Request Block structure
+ */
+typedef struct srb
+{
+    Scsi_Cmnd  *cmd;                 /* (4) SCSI command block */
+    struct srb  *s_next;             /* (4) Next block on LU queue */
+    struct srb  *s_prev;             /* (4) Previous block on LU queue */
+    uint8_t     flags;               /* (1) Status flags. */
+    uint8_t     dir;                 /* direction of transfer */
+    uint8_t     unused[2];
+    u_long      r_start;             /* jiffies at start of request */
+    u_long      u_start;             /* jiffies when sent to F/W    */
+}srb_t;
+
+/*
+ * SRB flag definitions
+ */
+#define SRB_TIMEOUT     BIT_0           /* Command timed out */
+#define SRB_SENT        BIT_1           /* Command sent to ISP */
+#define SRB_ABORT_PENDING     BIT_2     /* Command abort sent to device */
+#define SRB_ABORTED     BIT_3           /* Command aborted command already */
+
+
+/*
+ * Logical Unit Queue structure
+ */
+typedef struct scsi_lu
+{
+    srb_t           *q_first;           /* First block on LU queue */
+    srb_t           *q_last;            /* Last block on LU queue */
+    uint8_t         q_flag;             /* LU queue state flags */
+    uint8_t         q_sense[16];        /* sense data */
+    u_long          io_cnt;             /* total xfer count */
+    u_long          resp_time;          /* total response time (start - finish) */
+    u_long          act_time;           /* total actived time (minus queuing time) */
+    u_long          w_cnt;              /* total writes */
+    u_long          r_cnt;              /* total reads */
+    uint16_t        q_outcnt;           /* Pending jobs for this LU */
+#if QL1280_TARGET_MODE_SUPPORT
+    void            (*q_func)();        /* Target driver event handler */
+    int32_t         q_param;            /* Target driver event param */
+    uint8_t         q_lock;            /* Device Queue Lock */
+#endif
+}scsi_lu_t;
+
+/*
+ * Logical Unit flags 
+ */
+#define QLA1280_QBUSY   BIT_0
+#define QLA1280_QWAIT   BIT_1
+#define QLA1280_QSUSP   BIT_2
+#define QLA1280_QSENSE  BIT_3           /* Sense data cache valid */
+#define QLA1280_QRESET  BIT_4
+#define QLA1280_QHBA    BIT_5
+#define QLA1280_BSUSP   BIT_6           /* controller is suspended */
+#define QLA1280_BREM    BIT_7           /* controller is removed */
+
+/*
+ *  ISP PCI Configuration Register Set
+ */
+typedef volatile struct
+{
+    uint16_t vendor_id;                 /* 0x0 */
+    uint16_t device_id;                 /* 0x2 */
+    uint16_t command;                   /* 0x4 */
+    uint16_t status;                    /* 0x6 */
+    uint8_t revision_id;                /* 0x8 */
+    uint8_t programming_interface;      /* 0x9 */
+    uint8_t sub_class;                  /* 0xa */
+    uint8_t base_class;                 /* 0xb */
+    uint8_t cache_line;                 /* 0xc */
+    uint8_t latency_timer;              /* 0xd */
+    uint8_t header_type;                /* 0xe */
+    uint8_t bist;                       /* 0xf */
+    uint32_t base_port;                  /* 0x10 */
+    uint32_t mem_base_addr;              /* 0x14 */
+    uint32_t base_addr[4];               /* 0x18-0x24 */
+    uint32_t reserved_1[2];              /* 0x28-0x2c */
+    uint16_t expansion_rom;             /* 0x30 */
+    uint32_t reserved_2[2];              /* 0x34-0x38 */
+    uint8_t interrupt_line;             /* 0x3c */
+    uint8_t interrupt_pin;              /* 0x3d */
+    uint8_t min_grant;                  /* 0x3e */
+    uint8_t max_latency;                /* 0x3f */
+}config_reg_t;
+
+/*
+ *  ISP I/O Register Set structure definitions.
+ */
+typedef volatile struct
+{
+    uint16_t id_l;                      /* ID low */
+    uint16_t id_h;                      /* ID high */
+    uint16_t cfg_0;                     /* Configuration 0 */
+    uint16_t cfg_1;                     /* Configuration 1 */
+    uint16_t ictrl;                     /* Interface control */
+        #define ISP_RESET       BIT_0   /* ISP soft reset */
+        #define ISP_EN_INT      BIT_1   /* ISP enable interrupts. */
+        #define ISP_EN_RISC     BIT_2   /* ISP enable RISC interrupts. */
+    uint16_t istatus;                   /* Interface status */
+        #define PCI_64BIT_SLOT  BIT_14  /* PCI 64-bit slot indicator. */
+        #define RISC_INT        BIT_2   /* RISC interrupt */
+        #define PCI_INT         BIT_1   /* PCI interrupt */
+    uint16_t semaphore;                 /* Semaphore */
+    uint16_t nvram;                     /* NVRAM register. */
+        #define NV_DESELECT     0
+        #define NV_CLOCK        BIT_0
+        #define NV_SELECT       BIT_1
+        #define NV_DATA_OUT     BIT_2
+        #define NV_DATA_IN      BIT_3
+    uint16_t flash_data;                /* Flash BIOS data */
+    uint16_t flash_address;             /* Flash BIOS address */
+
+    uint16_t unused_1[0x2e];            /* 0x14-0x6f Gap */
+
+    uint16_t mailbox0;                  /* Mailbox 0 */
+    uint16_t mailbox1;                  /* Mailbox 1 */
+    uint16_t mailbox2;                  /* Mailbox 2 */
+    uint16_t mailbox3;                  /* Mailbox 3 */
+    uint16_t mailbox4;                  /* Mailbox 4 */
+    uint16_t mailbox5;                  /* Mailbox 5 */
+    uint16_t mailbox6;                  /* Mailbox 6 */
+    uint16_t mailbox7;                  /* Mailbox 7 */
+
+    uint16_t unused_2[0x20];            /* 0x80-0xbf Gap */
+
+    uint16_t host_cmd;                  /* Host command and control */
+        #define HOST_INT      BIT_7     /* host interrupt bit */
+        #define BIOS_ENABLE   BIT_0
+
+    uint16_t unused_6[0x5];             /* 0xc2-0xcb Gap */
+
+    uint16_t gpio_data;
+    uint16_t gpio_enable;
+
+    uint16_t unused_7[0x11];			/* d0-f0	*/
+    uint16_t scsiControlPins;           /* f2 */
+
+}device_reg_t;
+
+#define MAILBOX_REGISTER_COUNT  8
+
+/*
+ *  ISP product identification definitions in mailboxes after reset.
+ */
+#define PROD_ID_1           0x4953
+#define PROD_ID_2           0x0000
+#define PROD_ID_2a          0x5020
+#define PROD_ID_3           0x2020
+#define PROD_ID_4           0x1
+
+/*
+ * ISP host command and control register command definitions
+ */
+#define HC_RESET_RISC       0x1000      /* Reset RISC */
+#define HC_PAUSE_RISC       0x2000      /* Pause RISC */
+#define HC_RELEASE_RISC     0x3000      /* Release RISC from reset. */
+#define HC_SET_HOST_INT     0x5000      /* Set host interrupt */
+#define HC_CLR_HOST_INT     0x6000      /* Clear HOST interrupt */
+#define HC_CLR_RISC_INT     0x7000      /* Clear RISC interrupt */
+#define HC_DISABLE_BIOS     0x9000      /* Disable BIOS. */
+
+/*
+ * ISP mailbox Self-Test status codes
+ */
+#define MBS_FRM_ALIVE       0           /* Firmware Alive. */
+#define MBS_CHKSUM_ERR      1           /* Checksum Error. */
+#define MBS_SHADOW_LD_ERR   2           /* Shadow Load Error. */
+#define MBS_BUSY            4           /* Busy. */
+
+/*
+ * ISP mailbox command complete status codes
+ */
+#define MBS_CMD_CMP         0x4000      /* Command Complete. */
+#define MBS_INV_CMD         0x4001      /* Invalid Command. */
+#define MBS_HOST_INF_ERR    0x4002      /* Host Interface Error. */
+#define MBS_TEST_FAILED     0x4003      /* Test Failed. */
+#define MBS_CMD_ERR         0x4005      /* Command Error. */
+#define MBS_CMD_PARAM_ERR   0x4006      /* Command Parameter Error. */
+
+/*
+ * ISP mailbox asynchronous event status codes
+ */
+#define MBA_ASYNC_EVENT         0x8000  /* Asynchronous event. */
+#define MBA_BUS_RESET           0x8001  /* SCSI Bus Reset. */
+#define MBA_SYSTEM_ERR          0x8002  /* System Error. */
+#define MBA_REQ_TRANSFER_ERR    0x8003  /* Request Transfer Error. */
+#define MBA_RSP_TRANSFER_ERR    0x8004  /* Response Transfer Error. */
+#define MBA_WAKEUP_THRES        0x8005  /* Request Queue Wake-up. */
+#define MBA_TIMEOUT_RESET       0x8006  /* Execution Timeout Reset. */
+#define MBA_DEVICE_RESET        0x8007  /* Bus Device Reset. */
+#define MBA_BUS_MODE_CHANGE     0x800E  /* SCSI bus mode transition. */
+#define MBA_SCSI_COMPLETION     0x8020  /* Completion response. */
+
+/*
+ * ISP mailbox commands
+ */
+#define MBC_NOP                     0       /* No Operation. */
+#define MBC_LOAD_RAM                1       /* Load RAM. */
+#define MBC_EXECUTE_FIRMWARE        2       /* Execute firmware. */
+#define MBC_WRITE_RAM_WORD          4       /* Write ram word. */
+#define MBC_READ_RAM_WORD           5       /* Read ram word. */
+#define MBC_MAILBOX_REGISTER_TEST   6       /* Wrap incoming mailboxes */
+#define MBC_VERIFY_CHECKSUM         7       /* Verify checksum. */
+#define MBC_ABOUT_FIRMWARE          8       /* Get firmware revision. */
+#define MBC_INIT_REQUEST_QUEUE      0x10    /* Initialize request queue. */
+#define MBC_INIT_RESPONSE_QUEUE     0x11    /* Initialize response queue. */
+#define MBC_EXECUTE_IOCB            0x12    /* Execute IOCB command. */
+#define MBC_ABORT_COMMAND           0x15    /* Abort IOCB command. */
+#define MBC_ABORT_DEVICE            0x16    /* Abort device (ID/LUN). */
+#define MBC_ABORT_TARGET            0x17    /* Abort target (ID). */
+#define MBC_BUS_RESET               0x18    /* SCSI bus reset. */
+#define MBC_GET_RETRY_COUNT         0x22    /* Get retry count and delay. */
+#define MBC_GET_TARGET_PARAMETERS   0x28    /* Get target parameters. */
+#define MBC_SET_INITIATOR_ID        0x30    /* Set initiator SCSI ID. */
+#define MBC_SET_SELECTION_TIMEOUT   0x31    /* Set selection timeout. */
+#define MBC_SET_RETRY_COUNT         0x32    /* Set retry count and delay. */
+#define MBC_SET_TAG_AGE_LIMIT       0x33    /* Set tag age limit. */
+#define MBC_SET_CLOCK_RATE          0x34    /* Set clock rate. */
+#define MBC_SET_ACTIVE_NEGATION     0x35    /* Set active negation state. */
+#define MBC_SET_ASYNC_DATA_SETUP    0x36    /* Set async data setup time. */
+#define MBC_SET_PCI_CONTROL         0x37    /* Set BUS control parameters. */
+#define MBC_SET_TARGET_PARAMETERS   0x38    /* Set target parameters. */
+#define MBC_SET_DEVICE_QUEUE        0x39    /* Set device queue parameters */
+#define MBC_SET_SYSTEM_PARAMETER    0x45    /* Set system parameter word. */
+#define MBC_SET_FIRMWARE_FEATURES   0x4A    /* Set firmware feature word. */
+#define MBC_INIT_REQUEST_QUEUE_A64  0x52    /* Initialize request queue A64 */
+#define MBC_INIT_RESPONSE_QUEUE_A64 0x53    /* Initialize response q A64. */
+#define MBC_ENABLE_TARGET_MODE      0x55    /* Enable target mode. */
+
+/*
+ * ISP Get/Set Target Parameters mailbox command control flags.
+ */
+#define TP_RENEGOTIATE          BIT_8   /* Renegotiate on error. */
+#define TP_STOP_QUEUE           BIT_9   /* Stop que on check condition */
+#define TP_AUTO_REQUEST_SENSE   BIT_10  /* Automatic request sense. */
+#define TP_TAGGED_QUEUE         BIT_11  /* Tagged queuing. */
+#define TP_SYNC                 BIT_12  /* Synchronous data transfers. */
+#define TP_WIDE                 BIT_13  /* Wide data transfers. */
+#define TP_PARITY               BIT_14  /* Parity checking. */
+#define TP_DISCONNECT           BIT_15  /* Disconnect privilege. */
+
+/*
+ * NVRAM Command values.
+ */
+#define NV_START_BIT            BIT_2
+#define NV_WRITE_OP             (BIT_26+BIT_24)
+#define NV_READ_OP              (BIT_26+BIT_25)
+#define NV_ERASE_OP             (BIT_26+BIT_25+BIT_24)
+#define NV_MASK_OP              (BIT_26+BIT_25+BIT_24)
+#define NV_DELAY_COUNT          10
+
+/*
+ *  QLogic ISP1280 NVRAM structure definition.
+ */
+typedef struct
+{
+    uint8_t id[4];                                  /* 0, 1, 2, 3 */
+    uint8_t version;                                /* 4 */
+
+    struct
+    {
+        uint8_t bios_configuration_mode     :2;
+        uint8_t bios_disable                :1;
+        uint8_t selectable_scsi_boot_enable :1;
+        uint8_t cd_rom_boot_enable          :1;
+        uint8_t disable_loading_risc_code   :1;
+        uint8_t enable_64bit_addressing     :1;
+        uint8_t unused_7                    :1;
+    }cntr_flags_1;                                  /* 5 */
+
+    struct
+    {
+        uint8_t boot_lun_number    :5;
+        uint8_t scsi_bus_number    :1;
+        uint8_t unused_6           :1;
+        uint8_t unused_7           :1;
+        uint8_t boot_target_number :4;
+        uint8_t unused_12          :1;
+        uint8_t unused_13          :1;
+        uint8_t unused_14          :1;
+        uint8_t unused_15          :1;
+    }cntr_flags_2;                                  /* 6, 7 */
+
+    uint16_t unused_8;                              /* 8, 9 */
+    uint16_t unused_10;                             /* 10, 11 */
+    uint16_t unused_12;                             /* 12, 13 */
+    uint16_t unused_14;                              /* 14, 15 */
+
+    union
+    {
+        uint8_t c;
+        struct
+        {
+            uint8_t reserved        :2;
+            uint8_t burst_enable    :1;
+            uint8_t reserved_1      :1;
+            uint8_t fifo_threshold  :4;
+        }f;
+    }isp_config;                                    /* 16 */
+
+    /* Termination
+     * 0 = Disable, 1 = high only, 3 = Auto term
+     */
+    union
+    {
+        uint8_t c;
+        struct
+        {
+            uint8_t scsi_bus_1_control  :2;
+            uint8_t scsi_bus_0_control  :2;
+            uint8_t unused_0            :1;
+            uint8_t unused_1            :1;
+            uint8_t unused_2            :1;
+            uint8_t auto_term_support   :1;
+        }f;
+    }termination;                                   /* 17 */
+
+    uint16_t isp_parameter;                         /* 18, 19 */
+
+    union
+    {
+        uint16_t w;
+        struct
+        {
+            uint8_t enable_fast_posting       :1;
+            uint8_t report_lvd_bus_transition :1;
+            uint8_t unused_2                  :1;
+            uint8_t unused_3                  :1;
+            uint8_t unused_4                  :1;
+            uint8_t unused_5                  :1;
+            uint8_t unused_6                  :1;
+            uint8_t unused_7                  :1;
+            uint8_t unused_8                  :1;
+            uint8_t unused_9                  :1;
+            uint8_t unused_10                 :1;
+            uint8_t unused_11                 :1;
+            uint8_t unused_12                 :1;
+            uint8_t unused_13                 :1;
+            uint8_t unused_14                 :1;
+            uint8_t unused_15                 :1;
+        }f;
+    }firmware_feature;                              /* 20, 21 */
+
+    uint16_t unused_22;                             /* 22, 23 */
+
+    struct
+    {
+        struct
+        {
+            uint8_t initiator_id       :4;
+            uint8_t scsi_reset_disable :1;
+            uint8_t scsi_bus_size      :1;
+            uint8_t scsi_bus_type      :1;
+            uint8_t unused_7           :1;
+        }config_1;                                  /* 24 */
+
+        uint8_t bus_reset_delay;                    /* 25 */
+        uint8_t retry_count;                        /* 26 */
+        uint8_t retry_delay;                        /* 27 */
+
+        struct
+        {
+            uint8_t async_data_setup_time     :4;
+            uint8_t req_ack_active_negation   :1;
+            uint8_t data_line_active_negation :1;
+            uint8_t unused_6                  :1;
+            uint8_t unused_7                  :1;
+        }config_2;                                  /* 28 */
+
+        uint8_t unused_29;                          /* 29 */
+
+        uint16_t selection_timeout;                 /* 30, 31 */
+        uint16_t max_queue_depth;                   /* 32, 33 */
+
+        uint16_t unused_34;                         /* 34, 35 */
+        uint16_t unused_36;                         /* 36, 37 */
+        uint16_t unused_38;                         /* 38, 39 */
+
+        struct
+        {
+            union
+            {
+                uint8_t c;
+                struct
+                {
+                    uint8_t renegotiate_on_error :1;
+                    uint8_t stop_queue_on_check  :1;
+                    uint8_t auto_request_sense   :1;
+                    uint8_t tag_queuing          :1;
+                    uint8_t sync_data_transfers  :1;
+                    uint8_t wide_data_transfers  :1;
+                    uint8_t parity_checking      :1;
+                    uint8_t disconnect_allowed   :1;
+                }f;
+            }parameter;                             /* 40 */
+
+            uint8_t execution_throttle;             /* 41 */
+            uint8_t sync_period;                    /* 42 */
+
+            struct
+            {
+                uint8_t sync_offset   :4;
+                uint8_t device_enable :1;
+                uint8_t lun_disable   :1;
+                uint8_t unused_6      :1;
+                uint8_t unused_7      :1;
+            }flags;                                 /* 43 */
+
+            uint16_t unused_44;                     /* 44, 45 */
+        }target[MAX_TARGETS];
+    }bus[MAX_BUSES];
+
+    uint16_t unused_248;                        /* 248, 249 */
+
+    uint16_t subsystem_id[2];                   /* 250, 251, 252, 253 */
+
+    uint8_t  unused_254;                        /* 254 */
+
+    uint8_t chksum;                             /* 255 */
+}nvram_t;
+
+/*
+ *  QLogic ISP12160 NVRAM structure definition.
+ */
+typedef struct
+{
+    uint8_t id[4];                                  /* 0, 1, 2, 3 */
+    uint8_t version;                                /* 4 */
+    /* Host/Bios Flags */ 
+    struct
+    {
+        uint8_t bios_configuration_mode     :2;
+        uint8_t bios_disable                :1;
+        uint8_t selectable_scsi_boot_enable :1;
+        uint8_t cd_rom_boot_enable          :1;
+        uint8_t disable_loading_risc_code   :1;
+        uint8_t unused_6                    :1;
+        uint8_t unused_7                    :1;
+    }cntr_flags_1;                                  /* 5 */
+    /* Selectable Boot Support */
+    struct
+    {
+        uint8_t boot_lun_number    :5;
+        uint8_t scsi_bus_number    :1;
+        uint8_t unused_6           :1;
+        uint8_t unused_7           :1;
+        uint8_t boot_target_number :4;
+        uint8_t unused_12          :1;
+        uint8_t unused_13          :1;
+        uint8_t unused_14          :1;
+        uint8_t unused_15          :1;
+    }cntr_flags_2;                                  /* 6, 7 */
+
+    uint16_t unused_8;                              /* 8, 9 */
+    uint16_t unused_10;                             /* 10, 11 */
+    uint16_t unused_12;                             /* 12, 13 */
+    uint16_t unused_14;                              /* 14, 15 */
+
+    /* ISP Config Parameters */
+    union
+    {
+        uint8_t c;  
+        struct
+        {
+            uint8_t reserved        :2;
+            uint8_t burst_enable    :1;
+            uint8_t reserved_1      :1;
+            uint8_t fifo_threshold  :4;
+        }f;
+    }isp_config;                                    /* 16 */
+
+    /* Termination
+     * 0 = Disable, 1 = high only, 3 = Auto term
+     */
+    union
+    {
+        uint8_t c;
+        struct
+        {
+            uint8_t scsi_bus_1_control  :2;
+            uint8_t scsi_bus_0_control  :2;
+            uint8_t unused_0            :1;
+            uint8_t unused_1            :1;
+            uint8_t unused_2            :1;
+            uint8_t auto_term_support   :1;
+        }f;
+    }termination;                                   /* 17 */
+								/* Auto Term - 3                          */
+								/* High Only - 1 (GPIO2 = 1 & GPIO3 = 0)  */
+								/* Disable - 0 (GPIO2 = 0 & GPIO3 = X)    */
+
+    uint16_t isp_parameter;                         /* 18, 19 */
+
+    union
+    {
+        uint16_t w;
+        struct
+        {
+            uint8_t enable_fast_posting       :1;
+            uint8_t report_lvd_bus_transition :1;
+            uint8_t unused_2                  :1;
+            uint8_t unused_3                  :1;
+            uint8_t unused_4                  :1;
+            uint8_t unused_5                  :1;
+            uint8_t unused_6                  :1;
+            uint8_t unused_7                  :1;
+            uint8_t unused_8                  :1;
+            uint8_t unused_9                  :1;
+            uint8_t unused_10                 :1;
+            uint8_t unused_11                 :1;
+            uint8_t unused_12                 :1;
+            uint8_t unused_13                 :1;
+            uint8_t unused_14                 :1;
+            uint8_t unused_15                 :1;
+        }f;
+    }firmware_feature;                              /* 20, 21 */
+
+    uint16_t unused_22;                             /* 22, 23 */
+
+    struct
+    {
+        struct
+        {
+            uint8_t initiator_id       :4;
+            uint8_t scsi_reset_disable :1;
+            uint8_t scsi_bus_size      :1;
+            uint8_t scsi_bus_type      :1;
+            uint8_t unused_7           :1;
+        }config_1;                                  /* 24 */
+
+        uint8_t bus_reset_delay;                    /* 25 */
+        uint8_t retry_count;                        /* 26 */
+        uint8_t retry_delay;                        /* 27 */
+                /* Adapter Capabilities bits */
+        struct
+        {
+            uint8_t async_data_setup_time     :4;
+            uint8_t req_ack_active_negation   :1;
+            uint8_t data_line_active_negation :1;
+            uint8_t unused_6                  :1;
+            uint8_t unused_7                  :1;
+        }config_2;                                  /* 28 */
+
+        uint8_t unused_29;                          /* 29 */
+
+        uint16_t selection_timeout;                 /* 30, 31 */
+        uint16_t max_queue_depth;                   /* 32, 33 */
+
+        uint16_t unused_34;                         /* 34, 35 */
+        uint16_t unused_36;                         /* 36, 37 */
+        uint16_t unused_38;                         /* 38, 39 */
+
+        struct
+        {
+            union
+            {
+                uint8_t c;
+                struct
+                {
+                    uint8_t renegotiate_on_error :1;
+                    uint8_t stop_queue_on_check  :1;
+                    uint8_t auto_request_sense   :1;
+                    uint8_t tag_queuing          :1;
+                    uint8_t sync_data_transfers  :1;
+                    uint8_t wide_data_transfers  :1;
+                    uint8_t parity_checking      :1;
+                    uint8_t disconnect_allowed   :1;
+                }f;
+            }parameter;                             /* 40 */
+
+            uint8_t execution_throttle;             /* 41 */
+            uint8_t sync_period;                    /* 42 */
+
+            struct
+            {
+                uint8_t sync_offset   :5;
+                uint8_t device_enable :1;
+                uint8_t unused_6      :1;
+                uint8_t unused_7      :1;
+                uint8_t	ppr_options	  :4;
+                uint8_t	ppr_bus_width :2;
+	            uint8_t	unused_8	  :1;
+	            uint8_t	enable_ppr	  :1;  
+            }flags;                                 /* 43, 44 */
+
+            uint8_t unused_45;                     /* 45 */
+        }target[MAX_TARGETS];
+    }bus[MAX_BUSES];
+
+    uint16_t unused_248;                        /* 248, 249 */
+
+    uint16_t subsystem_id[2];                   /* 250, 251, 252, 253 */
+
+    uint8_t  System_Id_Pointer;                   /* 254 */
+
+    uint8_t chksum;                             /* 255 */
+}nvram160_t;
+
+/*
+ * ISP queue - command entry structure definition.
+ */
+#define MAX_CMDSZ   12                  /* SCSI maximum CDB size. */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define COMMAND_TYPE    1       /* Command entry */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  sys_define;                /* System defined. */
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t handle;                    /* System handle. */
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  target;                    /* SCSI ID */
+    uint16_t cdb_len;                   /* SCSI command length. */
+    uint16_t control_flags;             /* Control flags. */
+    uint16_t reserved;
+    uint16_t timeout;                   /* Command timeout. */
+    uint16_t dseg_count;                /* Data segment count. */
+    uint8_t  scsi_cdb[MAX_CMDSZ];       /* SCSI command words. */
+    uint32_t dseg_0_address;            /* Data segment 0 address. */
+    uint32_t dseg_0_length;             /* Data segment 0 length. */
+    uint32_t dseg_1_address;            /* Data segment 1 address. */
+    uint32_t dseg_1_length;             /* Data segment 1 length. */
+    uint32_t dseg_2_address;            /* Data segment 2 address. */
+    uint32_t dseg_2_length;             /* Data segment 2 length. */
+    uint32_t dseg_3_address;            /* Data segment 3 address. */
+    uint32_t dseg_3_length;             /* Data segment 3 length. */
+}cmd_entry_t;
+
+/*
+ * ISP queue - continuation entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define CONTINUE_TYPE   2       /* Continuation entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  sys_define;                /* System defined. */
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved;                  /* Reserved */
+    uint32_t dseg_0_address;            /* Data segment 0 address. */
+    uint32_t dseg_0_length;             /* Data segment 0 length. */
+    uint32_t dseg_1_address;            /* Data segment 1 address. */
+    uint32_t dseg_1_length;             /* Data segment 1 length. */
+    uint32_t dseg_2_address;            /* Data segment 2 address. */
+    uint32_t dseg_2_length;             /* Data segment 2 length. */
+    uint32_t dseg_3_address;            /* Data segment 3 address. */
+    uint32_t dseg_3_length;             /* Data segment 3 length. */
+    uint32_t dseg_4_address;            /* Data segment 4 address. */
+    uint32_t dseg_4_length;             /* Data segment 4 length. */
+    uint32_t dseg_5_address;            /* Data segment 5 address. */
+    uint32_t dseg_5_length;             /* Data segment 5 length. */
+    uint32_t dseg_6_address;            /* Data segment 6 address. */
+    uint32_t dseg_6_length;             /* Data segment 6 length. */
+}cont_entry_t;
+
+/*
+ * ISP queue - status entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define STATUS_TYPE     3       /* Status entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  sys_define;                /* System defined. */
+    uint8_t  entry_status;              /* Entry Status. */
+        #define RF_CONT         BIT_0   /* Continuation. */
+        #define RF_FULL         BIT_1   /* Full */
+        #define RF_BAD_HEADER   BIT_2   /* Bad header. */
+        #define RF_BAD_PAYLOAD  BIT_3   /* Bad payload. */
+    uint32_t handle;                    /* System handle. */
+    uint16_t scsi_status;               /* SCSI status. */
+    uint16_t comp_status;               /* Completion status. */
+    uint16_t state_flags;               /* State flags. */
+        #define SF_TRANSFER_CMPL BIT_14  /* Transfer Complete. */
+        #define SF_GOT_SENSE    BIT_13   /* Got Sense */
+        #define SF_GOT_STATUS    BIT_12   /* Got Status */
+        #define SF_TRANSFERRED_DATA BIT_11  /* Transferred data */
+        #define SF_SENT_CDB   BIT_10     /* Send CDB */
+        #define SF_GOT_TARGET  BIT_9   /*  */
+        #define SF_GOT_BUS     BIT_8   /*  */
+    uint16_t status_flags;              /* Status flags. */
+    uint16_t time;                      /* Time. */
+    uint16_t req_sense_length;          /* Request sense data length. */
+    uint32_t residual_length;           /* Residual transfer length. */
+    uint16_t reserved[4];
+    uint8_t  req_sense_data[32];        /* Request sense data. */
+}sts_entry_t, response_t;
+
+/*
+ * ISP queue - marker entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define MARKER_TYPE     4       /* Marker entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  sys_define;                /* System defined. */
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved;
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  target;                    /* SCSI ID */
+    uint8_t  modifier;                  /* Modifier (7-0). */
+        #define MK_SYNC_ID_LUN      0   /* Synchronize ID/LUN */
+        #define MK_SYNC_ID          1   /* Synchronize ID */
+        #define MK_SYNC_ALL         2   /* Synchronize all ID/LUN */
+    uint8_t  reserved_1[53];
+}mrk_entry_t;
+
+/*
+ * ISP queue - extended command entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define EXTENDED_CMD_TYPE  5    /* Extended command entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  sys_define;                /* System defined. */
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t handle;                    /* System handle. */
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  target;                    /* SCSI ID */
+    uint16_t cdb_len;                   /* SCSI command length. */
+    uint16_t control_flags;             /* Control flags. */
+    uint16_t reserved;
+    uint16_t timeout;                   /* Command timeout. */
+    uint16_t dseg_count;                /* Data segment count. */
+    uint8_t  scsi_cdb[88];              /* SCSI command words. */
+}ecmd_entry_t;
+
+/*
+ * ISP queue - 64-Bit addressing, command entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define COMMAND_A64_TYPE 9      /* Command A64 entry */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  sys_define;                /* System defined. */
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t handle;                    /* System handle. */
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  target;                    /* SCSI ID */
+    uint16_t cdb_len;                   /* SCSI command length. */
+    uint16_t control_flags;             /* Control flags. */
+    uint16_t reserved;
+    uint16_t timeout;                   /* Command timeout. */
+    uint16_t dseg_count;                /* Data segment count. */
+    uint8_t  scsi_cdb[MAX_CMDSZ];       /* SCSI command words. */
+    uint32_t reserved_1[2];             /* unused */
+    uint32_t dseg_0_address[2];         /* Data segment 0 address. */
+    uint32_t dseg_0_length;             /* Data segment 0 length. */
+    uint32_t dseg_1_address[2];         /* Data segment 1 address. */
+    uint32_t dseg_1_length;             /* Data segment 1 length. */
+}cmd_a64_entry_t, request_t;
+
+/*
+ * ISP queue - 64-Bit addressing, continuation entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define CONTINUE_A64_TYPE 0xA   /* Continuation A64 entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  sys_define;                /* System defined. */
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t dseg_0_address[2];         /* Data segment 0 address. */
+    uint32_t dseg_0_length;             /* Data segment 0 length. */
+    uint32_t dseg_1_address[2];         /* Data segment 1 address. */
+    uint32_t dseg_1_length;             /* Data segment 1 length. */
+    uint32_t dseg_2_address[2];         /* Data segment 2 address. */
+    uint32_t dseg_2_length;             /* Data segment 2 length. */
+    uint32_t dseg_3_address[2];         /* Data segment 3 address. */
+    uint32_t dseg_3_length;             /* Data segment 3 length. */
+    uint32_t dseg_4_address[2];         /* Data segment 4 address. */
+    uint32_t dseg_4_length;             /* Data segment 4 length. */
+}cont_a64_entry_t;
+
+/*
+ * ISP queue - enable LUN entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define ENABLE_LUN_TYPE 0xB     /* Enable LUN entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status not used. */
+    uint32_t reserved_2;
+    uint16_t lun;                       /* Bit 15 is bus number. */
+    uint16_t reserved_4;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  reserved_5;
+    uint8_t  command_count;             /* Number of ATIOs allocated. */
+    uint8_t  immed_notify_count;        /* Number of Immediate Notify */
+                                        /* entries allocated. */
+    uint8_t  group_6_length;            /* SCSI CDB length for group 6 */
+                                        /* commands (2-26). */
+    uint8_t  group_7_length;            /* SCSI CDB length for group 7 */
+                                        /* commands (2-26). */
+    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
+    uint16_t reserved_6[20];
+}elun_entry_t;
+
+/*
+ * ISP queue - modify LUN entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define MODIFY_LUN_TYPE 0xC     /* Modify LUN entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  reserved_3;
+    uint8_t  operators;
+    uint8_t  reserved_4;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  reserved_5;
+    uint8_t  command_count;             /* Number of ATIOs allocated. */
+    uint8_t  immed_notify_count;        /* Number of Immediate Notify */
+                                        /* entries allocated. */
+    uint16_t reserved_6;
+    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
+    uint16_t reserved_7[20];
+}modify_lun_entry_t;
+
+/*
+ * ISP queue - immediate notify entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define IMMED_NOTIFY_TYPE 0xD   /* Immediate notify entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;
+    uint8_t  initiator_id;
+    uint8_t  reserved_3;
+    uint8_t  target_id;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  reserved_4;
+    uint8_t  tag_value;                 /* Received queue tag message value */
+    uint8_t  tag_type;                  /* Received queue tag message type */
+                                        /* entries allocated. */
+    uint16_t seq_id;
+    uint8_t  scsi_msg[8];               /* SCSI message not handled by ISP */
+    uint16_t reserved_5[8];
+    uint8_t  sense_data[18];
+}notify_entry_t;
+
+/*
+ * ISP queue - notify acknowledge entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define NOTIFY_ACK_TYPE 0xE     /* Notify acknowledge entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;
+    uint8_t  initiator_id;
+    uint8_t  reserved_3;
+    uint8_t  target_id;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  event;
+    uint16_t seq_id;
+    uint16_t reserved_4[22];
+}nack_entry_t;
+
+/*
+ * ISP queue - Accept Target I/O (ATIO) entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define ACCEPT_TGT_IO_TYPE 6    /* Accept target I/O entry. */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;
+    uint8_t  initiator_id;
+    uint8_t  cdb_len;
+    uint8_t  target_id;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  scsi_status;
+    uint8_t  tag_value;                 /* Received queue tag message value */
+    uint8_t  tag_type;                  /* Received queue tag message type */
+    uint8_t  cdb[26];
+    uint8_t  sense_data[18];
+}atio_entry_t;
+
+/*
+ * ISP queue - Continue Target I/O (CTIO) entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define CONTINUE_TGT_IO_TYPE 7  /* CTIO entry */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  initiator_id;
+    uint8_t  reserved_3;
+    uint8_t  target_id;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  scsi_status;
+    uint8_t  tag_value;                 /* Received queue tag message value */
+    uint8_t  tag_type;                  /* Received queue tag message type */
+    uint32_t transfer_length;
+    uint32_t residual;
+    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
+    uint16_t dseg_count;                /* Data segment count. */
+    uint32_t dseg_0_address;            /* Data segment 0 address. */
+    uint32_t dseg_0_length;             /* Data segment 0 length. */
+    uint32_t dseg_1_address;            /* Data segment 1 address. */
+    uint32_t dseg_1_length;             /* Data segment 1 length. */
+    uint32_t dseg_2_address;            /* Data segment 2 address. */
+    uint32_t dseg_2_length;             /* Data segment 2 length. */
+    uint32_t dseg_3_address;            /* Data segment 3 address. */
+    uint32_t dseg_3_length;             /* Data segment 3 length. */
+}ctio_entry_t;
+
+/*
+ * ISP queue - CTIO returned entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define CTIO_RET_TYPE   7       /* CTIO return entry */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  initiator_id;
+    uint8_t  reserved_3;
+    uint8_t  target_id;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  scsi_status;
+    uint8_t  tag_value;                 /* Received queue tag message value */
+    uint8_t  tag_type;                  /* Received queue tag message type */
+    uint32_t transfer_length;
+    uint32_t residual;
+    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
+    uint16_t dseg_count;                /* Data segment count. */
+    uint32_t dseg_0_address;            /* Data segment 0 address. */
+    uint32_t dseg_0_length;             /* Data segment 0 length. */
+    uint32_t dseg_1_address;            /* Data segment 1 address. */
+    uint16_t dseg_1_length;             /* Data segment 1 length. */
+    uint8_t  sense_data[18];
+}ctio_ret_entry_t;
+
+/*
+ * ISP queue - CTIO A64 entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define CTIO_A64_TYPE 0xF       /* CTIO A64 entry */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  initiator_id;
+    uint8_t  reserved_3;
+    uint8_t  target_id;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  scsi_status;
+    uint8_t  tag_value;                 /* Received queue tag message value */
+    uint8_t  tag_type;                  /* Received queue tag message type */
+    uint32_t transfer_length;
+    uint32_t residual;
+    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
+    uint16_t dseg_count;                /* Data segment count. */
+    uint32_t reserved_4[2];
+    uint32_t dseg_0_address[2];         /* Data segment 0 address. */
+    uint32_t dseg_0_length;             /* Data segment 0 length. */
+    uint32_t dseg_1_address[2];         /* Data segment 1 address. */
+    uint32_t dseg_1_length;             /* Data segment 1 length. */
+}ctio_a64_entry_t;
+
+/*
+ * ISP queue - CTIO returned entry structure definition.
+ */
+typedef struct
+{
+    uint8_t  entry_type;                /* Entry type. */
+        #define CTIO_A64_RET_TYPE 0xF   /* CTIO A64 returned entry */
+    uint8_t  entry_count;               /* Entry count. */
+    uint8_t  reserved_1;
+    uint8_t  entry_status;              /* Entry Status. */
+    uint32_t reserved_2;
+    uint8_t  lun;                       /* SCSI LUN */
+    uint8_t  initiator_id;
+    uint8_t  reserved_3;
+    uint8_t  target_id;
+    uint32_t option_flags;
+    uint8_t  status;
+    uint8_t  scsi_status;
+    uint8_t  tag_value;                 /* Received queue tag message value */
+    uint8_t  tag_type;                  /* Received queue tag message type */
+    uint32_t transfer_length;
+    uint32_t residual;
+    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
+    uint16_t dseg_count;                /* Data segment count. */
+    uint16_t reserved_4[7];
+    uint8_t  sense_data[18];
+}ctio_a64_ret_entry_t;
+
+/*
+ * ISP request and response queue entry sizes
+ */
+#define RESPONSE_ENTRY_SIZE     (sizeof(response_t))
+#define REQUEST_ENTRY_SIZE      (sizeof(request_t))
+
+/*
+ * ISP status entry - completion status definitions.
+ */
+#define CS_COMPLETE         0x0         /* No errors */
+#define CS_INCOMPLETE       0x1         /* Incomplete transfer of cmd. */
+#define CS_DMA              0x2         /* A DMA direction error. */
+#define CS_TRANSPORT        0x3         /* Transport error. */
+#define CS_RESET            0x4         /* SCSI bus reset occurred */
+#define CS_ABORTED          0x5         /* System aborted command. */
+#define CS_TIMEOUT          0x6         /* Timeout error. */
+#define CS_DATA_OVERRUN     0x7         /* Data overrun. */
+#define CS_COMMAND_OVERRUN  0x8         /* Command Overrun. */
+#define CS_STATUS_OVERRUN   0x9         /* Status Overrun. */
+#define CS_BAD_MSG          0xA         /* Bad msg after status phase. */
+#define CS_NO_MSG_OUT       0xB         /* No msg out after selection. */
+#define CS_EXTENDED_ID      0xC         /* Extended ID failed. */
+#define CS_IDE_MSG          0xD         /* Target rejected IDE msg. */
+#define CS_ABORT_MSG        0xE         /* Target rejected abort msg. */
+#define CS_REJECT_MSG       0xF         /* Target rejected reject msg. */
+#define CS_NOP_MSG          0x10        /* Target rejected NOP msg. */
+#define CS_PARITY_MSG       0x11        /* Target rejected parity msg. */
+#define CS_DEV_RESET_MSG    0x12        /* Target rejected dev rst msg. */
+#define CS_ID_MSG           0x13        /* Target rejected ID msg. */
+#define CS_FREE             0x14        /* Unexpected bus free. */
+#define CS_DATA_UNDERRUN    0x15        /* Data Underrun. */
+#define CS_TRANACTION_1     0x18        /* Transaction error 1 */
+#define CS_TRANACTION_2     0x19        /* Transaction error 2 */
+#define CS_TRANACTION_3     0x1a        /* Transaction error 3 */
+#define CS_INV_ENTRY_TYPE   0x1b        /* Invalid entry type */
+#define CS_DEV_QUEUE_FULL   0x1c        /* Device queue full */
+#define CS_PHASED_SKIPPED   0x1d        /* SCSI phase skipped */
+#define CS_ARS_FAILED       0x1e        /* ARS failed */
+#define CS_LVD_BUS_ERROR    0x21        /* LVD bus error */
+#define CS_BAD_PAYLOAD      0x80        /* Driver defined */
+#define CS_UNKNOWN          0x81        /* Driver defined */
+#define CS_RETRY            0x82        /* Driver defined */
+
+/*
+ * ISP status entry - SCSI status byte bit definitions.
+ */
+#define SS_CHECK_CONDITION  BIT_1
+#define SS_CONDITION_MET    BIT_2
+#define SS_BUSY_CONDITION   BIT_3
+#define SS_RESERVE_CONFLICT (BIT_4 | BIT_3)
+
+/*
+ * ISP target entries - Option flags bit definitions.
+ */
+#define OF_ENABLE_TAG       BIT_1       /* Tagged queue action enable */
+#define OF_DATA_IN          BIT_6       /* Data in to initiator */
+                                        /*  (data from target to initiator) */
+#define OF_DATA_OUT         BIT_7       /* Data out from initiator */
+                                        /*  (data from initiator to target) */
+#define OF_NO_DATA          (BIT_7 | BIT_6)
+#define OF_DISC_DISABLED    BIT_15      /* Disconnects disabled */
+#define OF_DISABLE_SDP      BIT_24      /* Disable sending save data ptr */
+#define OF_SEND_RDP         BIT_26      /* Send restore data pointers msg */
+#define OF_FORCE_DISC       BIT_30      /* Disconnects mandatory */
+#define OF_SSTS             BIT_31      /* Send SCSI status */
+
+#if QL1280_TARGET_MODE_SUPPORT
+/*
+ * Target Read/Write buffer structure.
+ */
+#define TARGET_DATA_OFFSET  4
+#define TARGET_DATA_SIZE    0x2000      /* 8K */
+#define TARGET_INQ_OFFSET   (TARGET_DATA_OFFSET + TARGET_DATA_SIZE)
+#define TARGET_SENSE_SIZE   18
+#define TARGET_BUF_SIZE     36
+
+typedef struct
+{
+    uint8_t         hdr[4];
+    uint8_t         data[TARGET_DATA_SIZE];
+    struct ident    inq;
+}tgt_t;
+#endif
+
+/*
+ * BUS parameters/settings structure
+ */
+typedef struct
+{
+    uint8_t     id;                    /* Host adapter SCSI id */
+    uint8_t     bus_reset_delay;       /* SCSI bus reset delay. */
+    uint8_t     failed_reset_count;    /* number of time reset failed */
+	uint8_t     unused;
+    uint16_t    device_enables;        /* Device enable bits. */
+    uint16_t    lun_disables;          /* LUN disable bits. */
+    uint16_t    qtag_enables;          /* Tag queue enables. */
+    uint16_t    hiwat;                 /* High water mark per device. */
+    uint8_t     reset_marker       :1;
+    uint8_t     disable_scsi_reset :1;
+    uint8_t     scsi_bus_dead      :1; /* SCSI Bus is Dead, when 5 back to back resets failed */
+
+}bus_param_t;
+
+/*
+ * Linux Host Adapter structure
+ */
+typedef struct scsi_qla_host
+{
+    /* Linux adapter configuration data */
+    struct Scsi_Host *host;             /* pointer to host data */
+    struct scsi_qla_host   *next;
+    device_reg_t     *iobase;           /* Base Memory-mapped I/O address */
+    uint8_t          pci_bus;
+    uint8_t          pci_device_fn;
+    uint8_t          devnum;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    struct pci_dev *pdev;
+#endif
+    volatile unsigned char  *mmpbase;      /* memory mapped address */
+    unsigned long            host_no;
+    unsigned long            instance;
+    uint8_t           revision;
+    uint8_t           ports;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+    spinlock_t               spin_lock;
+#endif
+    volatile unsigned char   cpu_lock_count[NR_CPUS];
+    unsigned long            actthreads;
+    unsigned long            qthreads;
+    unsigned long            isr_count;        /* Interrupt count */
+    unsigned long            spurious_int;
+
+    uint32_t           device_id;
+
+    /* Outstandings ISP commands. */
+    srb_t           *outstanding_cmds[MAX_OUTSTANDING_COMMANDS];
+
+    /* BUS configuration data */
+    bus_param_t bus_settings[MAX_BUSES];
+
+    /* Device LUN queues. */
+    scsi_lu_t       *dev[MAX_EQ];      /* Logical unit queues */
+
+#ifdef UNUSED
+    /* Interrupt lock, and data */
+    uint8_t          intr_lock;         /* Lock for interrupt locking */
+#endif
+
+    /* bottom half run queue */
+    struct tq_struct run_qla_bh;
+
+    /* Received ISP mailbox data. */
+    volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
+
+#ifdef UNUSED
+    /* ISP ring lock, rings, and indexes */
+    uint8_t          ring_lock;         /* ISP ring lock */
+    struct timer_list        dev_timer[MAX_TARGETS];
+#endif
+
+    request_t       req[REQUEST_ENTRY_CNT+1];
+    response_t      res[RESPONSE_ENTRY_CNT+1];
+    unsigned long   request_dma;        /* Physical address. */
+    request_t       *request_ring;      /* Base virtual address */
+    request_t       *request_ring_ptr;  /* Current address. */
+    uint16_t        req_ring_index;     /* Current index. */
+    uint16_t        req_q_cnt;          /* Number of available entries. */
+
+    unsigned long   response_dma;       /* Physical address. */
+    response_t      *response_ring;     /* Base virtual address */
+    response_t      *response_ring_ptr; /* Current address. */
+    uint16_t        rsp_ring_index;     /* Current index. */
+
+#if QL1280_TARGET_MODE_SUPPORT
+    /* Target buffer and sense data. */
+    uint32_t        tbuf_dma;           /* Physical address. */
+    tgt_t           *tbuf;
+    uint32_t        tsense_dma;         /* Physical address. */
+    uint8_t         *tsense;
+#endif
+
+#if  WATCHDOGTIMER
+    /* Watchdog queue, lock and total timer */
+    uint8_t          watchdog_q_lock;   /* Lock for watchdog queue */
+    srb_t           *wdg_q_first;       /* First job on watchdog queue */
+    srb_t           *wdg_q_last;        /* Last job on watchdog queue */
+    uint32_t         total_timeout;     /* Total timeout (quantum count) */
+    uint32_t         watchdogactive;
+#endif
+
+    srb_t           *done_q_first;       /* First job on done queue */
+    srb_t           *done_q_last;        /* Last job on done queue */
+
+    volatile struct
+    {
+        uint32_t     watchdog_enabled        :1;   /* 0 */
+        uint32_t     mbox_int                :1;   /* 1 */
+        uint32_t     mbox_busy               :1;   /* 2 */
+        uint32_t     online                  :1;   /* 3 */
+        uint32_t     reset_marker            :1;   /* 4 */
+        uint32_t     isp_abort_needed        :1;   /* 5 */
+        uint32_t     pci_64bit_slot          :1;   /* 6 */
+        uint32_t     disable_host_adapter    :1;   /* 7 */
+        uint32_t     reset_active            :1;   /* 8 */
+        uint32_t     abort_isp_active        :1;   /* 9 */
+        uint32_t     disable_risc_code_load  :1;   /* 10 */
+        uint32_t     enable_64bit_addressing :1;   /* 11 */
+#define QLA1280_IN_ISR_BIT      12
+        uint32_t     in_isr                  :1;   /* 12 */
+        uint32_t     in_abort                :1;   /* 13 */
+        uint32_t     in_reset                :1;   /* 14 */
+       uint32_t     dpc                     :1;   /* 15 */
+       uint32_t     dpc_sched               :1;   /* 16 */
+       uint32_t     interrupts_on               :1;   /* 17 */
+    }flags;
+
+}scsi_qla_host_t;
+
+/*
+ * Macros to help code, maintain, etc.
+ */
+#define SUBDEV(b, t, l)  ( (b << (MAX_T_BITS + MAX_L_BITS)) | (t << MAX_L_BITS) | l)
+#define LU_Q(ha, b, t, l)  (ha->dev[SUBDEV(b, t, l)])
+
+/*
+ * Locking Macro Definitions
+ *
+ * LOCK/UNLOCK definitions are lock/unlock primitives for multi-processor
+ * or spl/splx for uniprocessor.
+ */
+#define QLA1280_HIER   HBA_HIER_BASE  /* Locking hierarchy base for hba */
+
+#define QLA1280_WATCHDOG_Q_LOCK(ha, p)   
+#define QLA1280_WATCHDOG_Q_UNLOCK(ha, p) 
+
+#define QLA1280_SCSILU_LOCK(q)  
+#define QLA1280_SCSILU_UNLOCK(q) 
+
+#define QLA1280_INTR_LOCK(ha)
+#define QLA1280_INTR_UNLOCK(ha)     
+
+#define QLA1280_RING_LOCK(ha)  
+#define QLA1280_RING_UNLOCK(ha)   
+
+#if defined(__cplusplus)
+}
+#endif
+/*
+ *  Linux - SCSI Driver Interface Function Prototypes.
+ */
+int qla1280_proc_info ( char *, char **, off_t, int, int, int);
+const char * qla1280_info(struct Scsi_Host *host);
+int qla1280_detect(Scsi_Host_Template *);
+int qla1280_release(struct Scsi_Host *);
+const char * qla1280_info(struct Scsi_Host *);
+int qla1280_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+int qla1280_abort(Scsi_Cmnd *);
+int qla1280_reset(Scsi_Cmnd *, unsigned int);
+int qla1280_biosparam(Disk *, kdev_t, int[]);
+void qla1280_intr_handler(int, void *, struct pt_regs *);
+void qla1280_setup(char *s, int *dummy);
+#if defined(__386__)
+#  define QLA1280_BIOSPARAM  qla1280_biosparam
+#else
+#  define QLA1280_BIOSPARAM  NULL
+#endif
+
+/*
+ * Scsi_Host_template (see hosts.h) 
+ * Device driver Interfaces to mid-level SCSI driver.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+/* This interface is now obsolete !!! */ 
+#define QLA1280_LINUX_TEMPLATE {		                 \
+        next:           NULL,                                    \
+        usage_count:    NULL,                                    \
+	proc_dir:		NULL,          	                 \
+	proc_info:		NULL,	                         \
+	name:			"Qlogic ISP 1280",               \
+	detect:			qla1280_detect,	                 \
+	release:		qla1280_release,                 \
+	info:			qla1280_info,	                 \
+        command:        NULL,                                    \
+	queuecommand:	qla1280_queuecommand,	                 \
+	abort:			qla1280_abort,	                 \
+	reset:			qla1280_reset,	                 \
+        slave_attach:   NULL,                                    \
+	bios_param:		QLA1280_BIOSPARAM,               \
+	can_queue:		255, /* MAX_OUTSTANDING_COMMANDS */   \
+	this_id:		-1,  /* scsi id of host adapter */        \
+	sg_tablesize:	SG_ALL,	 \
+	cmd_per_lun:	3,	  /* max commands per lun */	       \
+	present:	    0,    /* number of 1280s present */	       \
+	unchecked_isa_dma: 0, /* no memeory DMA restrictions */    \
+	use_clustering:	ENABLE_CLUSTERING			               \
+}
+#else
+
+#define QLA1280_LINUX_TEMPLATE {		                 \
+	next: NULL,						\
+	module: NULL,						\
+	proc_dir: NULL,						\
+	proc_info: qla1280_proc_info,				\
+	name:			"Qlogic ISP 1280\1080",               \
+	detect: qla1280_detect,					\
+	release: qla1280_release,				\
+	info: qla1280_info,					\
+	ioctl: NULL,						\
+	command: NULL,						\
+	queuecommand: qla1280_queuecommand,			\
+	eh_strategy_handler: NULL,				\
+	eh_abort_handler: NULL,					\
+	eh_device_reset_handler: NULL,				\
+	eh_bus_reset_handler: NULL,				\
+	eh_host_reset_handler: NULL,				\
+	abort: qla1280_abort,					\
+	reset: qla1280_reset,					\
+	slave_attach: NULL,					\
+	bios_param: QLA1280_BIOSPARAM,				\
+	can_queue: 255,		/* max simultaneous cmds      */\
+	this_id: -1,		/* scsi id of host adapter    */\
+	sg_tablesize: SG_ALL,	/* max scatter-gather cmds    */\
+	cmd_per_lun: 3,		/* cmds per lun (linked cmds) */\
+	present: 0,		/* number of 7xxx's present   */\
+	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
+	use_clustering: ENABLE_CLUSTERING,			\
+	use_new_eh_code: 0,					\
+	emulated: 0					        \
+}
+#endif
+
+
+#endif /* _IO_HBA_QLA1280_H */
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
--- v2.3.42/linux/drivers/scsi/qlogicisp.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/scsi/qlogicisp.c	Tue Feb  8 18:58:25 2000
@@ -508,6 +508,11 @@
  */
 #define RES_QUEUE_LEN		((QLOGICISP_REQ_QUEUE_LEN + 1) / 8 - 1)
 #define QUEUE_ENTRY_LEN		64
+#define QSIZE(entries)  (((entries) + 1) * QUEUE_ENTRY_LEN)
+
+struct isp_queue_entry {
+	char __opaque[QUEUE_ENTRY_LEN];
+};
 
 struct isp1020_hostdata {
 	u_long	memaddr;
@@ -516,6 +521,9 @@
 	struct	dev_param dev_param[MAX_TARGETS];
 	struct	pci_dev *pci_dev;
 	
+	struct isp_queue_entry *res_cpu; /* CPU-side address of response queue. */
+	struct isp_queue_entry *req_cpu; /* CPU-size address of request queue. */
+
 	/* result and request queues (shared with isp1020): */
 	u_int	req_in_ptr;		/* index of next request slot */
 	u_int	res_out_ptr;		/* index of next result slot */
@@ -523,8 +531,15 @@
 	/* this is here so the queues are nicely aligned */
 	long	send_marker;		/* do we need to send a marker? */
 
-	char	res[RES_QUEUE_LEN+1][QUEUE_ENTRY_LEN];
-	char	req[QLOGICISP_REQ_QUEUE_LEN+1][QUEUE_ENTRY_LEN];
+	/* The cmd->handle has a fixed size, and is only 32-bits.  We
+	 * need to take care to handle 64-bit systems correctly thus what
+	 * we actually place in cmd->handle is an index to the following
+	 * table.  Kudos to Matt Jacob for the technique.  -DaveM
+	 */
+	Scsi_Cmnd *cmd_slots[QLOGICISP_REQ_QUEUE_LEN + 1];
+
+	dma_addr_t res_dma;	/* PCI side view of response queue */
+	dma_addr_t req_dma;	/* PCI side view of request queue */
 };
 
 /* queue length's _must_ be power of two: */
@@ -616,10 +631,8 @@
 
 		hostdata->pci_dev = pdev;
 
-		if (isp1020_init(host)) {
-			scsi_unregister(host);
-			continue;
-		}
+		if (isp1020_init(host))
+			goto fail_and_unregister;
 		
 		if (isp1020_reset_hardware(host)
 #if USE_NVRAM_DEFAULTS
@@ -630,8 +643,7 @@
 		    || isp1020_load_parameters(host)) {
 			iounmap((void *)hostdata->memaddr);
 			release_region(host->io_port, 0xff);
-			scsi_unregister(host);
-			continue;
+			goto fail_and_unregister;
 		}
 
 		host->this_id = hostdata->host_param.initiator_scsi_id;
@@ -643,8 +655,7 @@
 			       host->irq);
 			iounmap((void *)hostdata->memaddr);
 			release_region(host->io_port, 0xff);
-			scsi_unregister(host);
-			continue;
+			goto fail_and_unregister;
 		}
 
 		isp_outw(0x0, host, PCI_SEMAPHORE);
@@ -652,6 +663,20 @@
 		isp1020_enable_irqs(host);
 
 		hosts++;
+		continue;
+
+	fail_and_unregister:
+		if (hostdata->res_cpu)
+			pci_free_consistent(hostdata->pci_dev,
+					    QSIZE(RES_QUEUE_LEN),
+					    hostdata->res_cpu,
+					    hostdata->res_dma);
+		if (hostdata->req_cpu)
+			pci_free_consistent(hostdata->pci_dev,
+					    QSIZE(QLOGICISP_REQ_QUEUE_LEN),
+					    hostdata->req_cpu,
+					    hostdata->req_dma);
+		scsi_unregister(host);
 	}
 
 	LEAVE("isp1020_detect");
@@ -709,7 +734,7 @@
  */
 int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
 {
-	int i, sg_count, n, num_free;
+	int i, n, num_free;
 	u_int in_ptr, out_ptr;
 	struct dataseg * ds;
 	struct scatterlist *sg;
@@ -732,7 +757,7 @@
 	DEBUG(printk("qlogicisp : request queue depth %d\n",
 		     REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
 
-	cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
+	cmd = (struct Command_Entry *) &hostdata->req_cpu[in_ptr];
 	in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN;
 	if (in_ptr == out_ptr) {
 		printk("qlogicisp : request queue overflow\n");
@@ -760,7 +785,7 @@
 			printk("qlogicisp : request queue overflow\n");
 			return 1;
 		}
-		cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
+		cmd = (struct Command_Entry *) &hostdata->req_cpu[in_ptr];
 		in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN;
 	}
 
@@ -771,7 +796,6 @@
 	cmd->hdr.entry_type = ENTRY_COMMAND;
 	cmd->hdr.entry_cnt = 1;
 
-	cmd->handle = cpu_to_le32((u_int) virt_to_bus(Cmnd));
 	cmd->target_lun = Cmnd->lun;
 	cmd->target_id = Cmnd->target;
 	cmd->cdb_length = cpu_to_le16(Cmnd->cmd_len);
@@ -781,17 +805,22 @@
 	memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
 
 	if (Cmnd->use_sg) {
-		cmd->segment_cnt = cpu_to_le16(sg_count = Cmnd->use_sg);
+		int sg_count;
+
 		sg = (struct scatterlist *) Cmnd->request_buffer;
 		ds = cmd->dataseg;
 
+		sg_count = pci_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg);
+
+		cmd->segment_cnt = cpu_to_le16(sg_count);
+
 		/* fill in first four sg entries: */
 		n = sg_count;
 		if (n > 4)
 			n = 4;
 		for (i = 0; i < n; i++) {
-			ds[i].d_base  = cpu_to_le32((u_int) virt_to_bus(sg->address));
-			ds[i].d_count = cpu_to_le32(sg->length);
+			ds[i].d_base  = cpu_to_le32(sg_dma_address(sg));
+			ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
 			++sg;
 		}
 		sg_count -= 4;
@@ -799,7 +828,7 @@
 		while (sg_count > 0) {
 			++cmd->hdr.entry_cnt;
 			cont = (struct Continuation_Entry *)
-				&hostdata->req[in_ptr][0];
+				&hostdata->req_cpu[in_ptr];
 			in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN;
 			if (in_ptr == out_ptr) {
 				printk("isp1020: unexpected request queue "
@@ -817,20 +846,29 @@
 			if (n > 7)
 				n = 7;
 			for (i = 0; i < n; ++i) {
-				ds[i].d_base = cpu_to_le32((u_int)virt_to_bus(sg->address));
-				ds[i].d_count = cpu_to_le32(sg->length);
+				ds[i].d_base = cpu_to_le32(sg_dma_address(sg));
+				ds[i].d_count = cpu_to_le32(sg_dma_len(sg));
 				++sg;
 			}
 			sg_count -= n;
 		}
 	} else {
+		Cmnd->SCp.ptr = (char *)(unsigned long)
+			pci_map_single(hostdata->pci_dev,
+				       Cmnd->request_buffer,
+				       Cmnd->request_bufflen);
+
 		cmd->dataseg[0].d_base =
-			cpu_to_le32((u_int) virt_to_bus(Cmnd->request_buffer));
+			cpu_to_le32((u32)(long)Cmnd->SCp.ptr);
 		cmd->dataseg[0].d_count =
-			cpu_to_le32((u_int) Cmnd->request_bufflen);
+			cpu_to_le32((u32)Cmnd->request_bufflen);
 		cmd->segment_cnt = cpu_to_le16(1);
 	}
 
+	/* Committed, record Scsi_Cmd so we can find it later. */
+	cmd->handle = in_ptr;
+	hostdata->cmd_slots[in_ptr] = Cmnd;
+
 	isp_outw(in_ptr, host, MBOX4);
 	hostdata->req_in_ptr = in_ptr;
 
@@ -905,10 +943,14 @@
 			  QUEUE_DEPTH(in_ptr, out_ptr, RES_QUEUE_LEN)));
 
 	while (out_ptr != in_ptr) {
-		sts = (struct Status_Entry *) &hostdata->res[out_ptr][0];
+		u_int cmd_slot;
+
+		sts = (struct Status_Entry *) &hostdata->res_cpu[out_ptr];
 		out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
 
-		Cmnd = (Scsi_Cmnd *) bus_to_virt(le32_to_cpu(sts->handle));
+		cmd_slot = sts->handle;
+		Cmnd = hostdata->cmd_slots[cmd_slot];
+		hostdata->cmd_slots[cmd_slot] = NULL;
 
 		TRACE("done", out_ptr, Cmnd);
 
@@ -928,6 +970,15 @@
 		else
 			Cmnd->result = DID_ERROR << 16;
 
+		if (Cmnd->use_sg)
+			pci_unmap_sg(hostdata->pci_dev,
+				     (struct scatterlist *)Cmnd->buffer,
+				     Cmnd->use_sg);
+		else
+			pci_unmap_single(hostdata->pci_dev,
+					 (u32)((long)Cmnd->SCp.ptr),
+					 Cmnd->request_bufflen);
+
 		isp_outw(out_ptr, host, MBOX5);
 		(*Cmnd->scsi_done)(Cmnd);
 	}
@@ -1031,19 +1082,25 @@
 	struct Scsi_Host *host;
 	struct isp1020_hostdata *hostdata;
 	int return_status = SCSI_ABORT_SUCCESS;
-	u_int cmdaddr = virt_to_bus(Cmnd);
+	u_int cmd_cookie;
+	int i;
 
 	ENTER("isp1020_abort");
 
 	host = Cmnd->host;
 	hostdata = (struct isp1020_hostdata *) host->hostdata;
 
+	for (i = 0; i < QLOGICISP_REQ_QUEUE_LEN + 1; i++)
+		if (hostdata->cmd_slots[i] == Cmnd)
+			break;
+	cmd_cookie = i;
+
 	isp1020_disable_irqs(host);
 
 	param[0] = MBOX_ABORT;
 	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
-	param[2] = cmdaddr >> 16;
-	param[3] = cmdaddr & 0xffff;
+	param[2] = cmd_cookie >> 16;
+	param[3] = cmd_cookie & 0xffff;
 
 	isp1020_mbox_command(host, param);
 
@@ -1313,6 +1370,26 @@
 	sh->max_id = MAX_TARGETS;
 	sh->max_lun = MAX_LUNS;
 
+	hostdata->res_cpu = pci_alloc_consistent(hostdata->pci_dev,
+						 QSIZE(RES_QUEUE_LEN),
+						 &hostdata->res_dma);
+	if (hostdata->res_cpu == NULL) {
+		printk("qlogicisp : can't allocate response queue\n");
+		return 1;
+	}
+
+	hostdata->req_cpu = pci_alloc_consistent(hostdata->pci_dev,
+						 QSIZE(QLOGICISP_REQ_QUEUE_LEN),
+						 &hostdata->req_dma);
+	if (hostdata->req_cpu == NULL) {
+		pci_free_consistent(hostdata->pci_dev,
+				    QSIZE(RES_QUEUE_LEN),
+				    hostdata->res_cpu,
+				    hostdata->res_dma);
+		printk("qlogicisp : can't allocate request queue\n");
+		return 1;
+	}
+
 	LEAVE("isp1020_init");
 
 	return 0;
@@ -1667,7 +1744,7 @@
 		}
 	}
 
-	queue_addr = (u_int) virt_to_bus(&hostdata->res[0][0]);
+	queue_addr = hostdata->res_dma;
 
 	param[0] = MBOX_INIT_RES_QUEUE;
 	param[1] = RES_QUEUE_LEN + 1;
@@ -1684,7 +1761,7 @@
 		return 1;
 	}
 
-	queue_addr = (u_int) virt_to_bus(&hostdata->req[0][0]);
+	queue_addr = hostdata->req_dma;
 
 	param[0] = MBOX_INIT_REQ_QUEUE;
 	param[1] = QLOGICISP_REQ_QUEUE_LEN + 1;
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.42/linux/drivers/scsi/scsi.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/scsi.c	Wed Feb  9 18:40:23 2000
@@ -147,7 +147,7 @@
 
 
 /*
- * Function:    scsi_get_request_handler()
+ * Function:    scsi_initialize_queue()
  *
  * Purpose:     Selects queue handler function for a device.
  *
@@ -165,20 +165,17 @@
  *              For this case, we have a special handler function, which
  *              does some checks and ultimately calls scsi_request_fn.
  *
- *              As a future enhancement, it might be worthwhile to add support
- *              for stacked handlers - there might get to be too many permutations
- *              otherwise.  Then again, we might just have one handler that does
- *              all of the special cases (a little bit slower), and those devices
- *              that don't need the special case code would directly call 
- *              scsi_request_fn.
- *
- *              As it stands, I can think of a number of special cases that
- *              we might need to handle.  This would not only include the blocked
- *              case, but single_lun (for changers), and any special handling
- *              we might need for a spun-down disk to spin it back up again.
+ *              The single_lun feature is a similar special case.
+ *
+ *              We handle these things by stacking the handlers.  The
+ *              special case handlers simply check a few conditions,
+ *              and return if they are not supposed to do anything.
+ *              In the event that things are OK, then they call the next
+ *              handler in the list - ultimately they call scsi_request_fn
+ *              to do the dirty deed.
  */
-request_fn_proc * scsi_get_request_handler(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) {
-        return scsi_request_fn;
+void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) {
+	blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
 }
 
 #ifdef MODULE
@@ -530,7 +527,7 @@
 #endif
 	struct Scsi_Host *host;
 	int rtn = 0;
-	unsigned long flags;
+	unsigned long flags = 0;
 	unsigned long timeout;
 
 	ASSERT_LOCK(&io_request_lock, 0);
@@ -1075,45 +1072,46 @@
 
 int scsi_loadable_module_flag;	/* Set after we scan builtin drivers */
 
-void *scsi_init_malloc(unsigned int size, int gfp_mask)
-{
-	void *retval;
-
-	/*
-	 * For buffers used by the DMA pool, we assume page aligned 
-	 * structures.
-	 */
-	if ((size % PAGE_SIZE) == 0) {
-		int order, a_size;
-		for (order = 0, a_size = PAGE_SIZE;
-		     a_size < size; order++, a_size <<= 1);
-		retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order);
-	} else
-		retval = kmalloc(size, gfp_mask);
-
-	if (retval)
-		memset(retval, 0, size);
-	return retval;
-}
-
-
-void scsi_init_free(char *ptr, unsigned int size)
+/*
+ * Function:    scsi_release_commandblocks()
+ *
+ * Purpose:     Release command blocks associated with a device.
+ *
+ * Arguments:   SDpnt   - device
+ *
+ * Returns:     Nothing
+ *
+ * Lock status: No locking assumed or required.
+ *
+ * Notes:
+ */
+void scsi_release_commandblocks(Scsi_Device * SDpnt)
 {
-	/*
-	 * We need this special code here because the DMA pool assumes
-	 * page aligned data.  Besides, it is wasteful to allocate
-	 * page sized chunks with kmalloc.
-	 */
-	if ((size % PAGE_SIZE) == 0) {
-		int order, a_size;
+	Scsi_Cmnd *SCpnt;
+	unsigned long flags;
 
-		for (order = 0, a_size = PAGE_SIZE;
-		     a_size < size; order++, a_size <<= 1);
-		free_pages((unsigned long) ptr, order);
-	} else
-		kfree(ptr);
+	spin_lock_irqsave(&device_request_lock, flags);
+	for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) {
+		SDpnt->device_queue = SCpnt->next;
+		kfree((char *) SCpnt);
+	}
+	SDpnt->has_cmdblocks = 0;
+	spin_unlock_irqrestore(&device_request_lock, flags);
 }
 
+/*
+ * Function:    scsi_build_commandblocks()
+ *
+ * Purpose:     Allocate command blocks associated with a device.
+ *
+ * Arguments:   SDpnt   - device
+ *
+ * Returns:     Nothing
+ *
+ * Lock status: No locking assumed or required.
+ *
+ * Notes:
+ */
 void scsi_build_commandblocks(Scsi_Device * SDpnt)
 {
 	unsigned long flags;
@@ -1129,9 +1127,10 @@
 
 	for (j = 0; j < SDpnt->queue_depth; j++) {
 		SCpnt = (Scsi_Cmnd *)
-		    scsi_init_malloc(sizeof(Scsi_Cmnd),
+		    kmalloc(sizeof(Scsi_Cmnd),
 				     GFP_ATOMIC |
 				(host->unchecked_isa_dma ? GFP_DMA : 0));
+		memset(SCpnt, 0, sizeof(Scsi_Cmnd));
 		if (NULL == SCpnt)
 			break;	/* If not, the next line will oops ... */
 		memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
@@ -1323,7 +1322,6 @@
 static int proc_scsi_gen_write(struct file * file, const char * buf,
                               unsigned long length, void *data)
 {
-	Scsi_Cmnd *SCpnt;
 	struct Scsi_Device_Template *SDTpnt;
 	Scsi_Device *scd;
 	struct Scsi_Host *HBA_ptr;
@@ -1537,10 +1535,8 @@
 			 * Nobody is using this device any more.
 			 * Free all of the command structures.
 			 */
-			for (SCpnt = scd->device_queue; SCpnt; SCpnt = SCpnt->next) {
-				scd->device_queue = SCpnt->next;
-				scsi_init_free((char *) SCpnt, sizeof(*SCpnt));
-			}
+			scsi_release_commandblocks(scd);
+
 			/* Now we can remove the device structure */
 			if (scd->next != NULL)
 				scd->next->prev = scd->prev;
@@ -1552,7 +1548,7 @@
 				HBA_ptr->host_queue = scd->next;
 			}
 			blk_cleanup_queue(&scd->request_queue);
-			scsi_init_free((char *) scd, sizeof(Scsi_Device));
+			kfree((char *) scd);
 		} else {
 			goto out;
 		}
@@ -1865,17 +1861,12 @@
 		}
 		for (SDpnt = shpnt->host_queue; SDpnt;
 		     SDpnt = shpnt->host_queue) {
-			while (SDpnt->device_queue) {
-				SCpnt = SDpnt->device_queue->next;
-				scsi_init_free((char *) SDpnt->device_queue, sizeof(Scsi_Cmnd));
-				SDpnt->device_queue = SCpnt;
-			}
-			SDpnt->has_cmdblocks = 0;
+			scsi_release_commandblocks(SDpnt);
 
 			blk_cleanup_queue(&SDpnt->request_queue);
 			/* Next free up the Scsi_Device structures for this host */
 			shpnt->host_queue = SDpnt->next;
-			scsi_init_free((char *) SDpnt, sizeof(Scsi_Device));
+			kfree((char *) SDpnt);
 
 		}
 	}
@@ -2023,7 +2014,6 @@
 static int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
 {
 	Scsi_Device *SDpnt;
-	Scsi_Cmnd *SCpnt;
 	struct Scsi_Host *shpnt;
 	struct Scsi_Device_Template *spnt;
 	struct Scsi_Device_Template *prev_spnt;
@@ -2050,13 +2040,7 @@
 				 * Nobody is using this device any more.  Free all of the
 				 * command structures.
 				 */
-				for (SCpnt = SDpnt->device_queue; SCpnt;
-				     SCpnt = SCpnt->next) {
-					if (SCpnt == SDpnt->device_queue)
-						SDpnt->device_queue = SCpnt->next;
-					scsi_init_free((char *) SCpnt, sizeof(*SCpnt));
-				}
-				SDpnt->has_cmdblocks = 0;
+				scsi_release_commandblocks(SDpnt);
 			}
 		}
 	}
@@ -2309,7 +2293,7 @@
 Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt)
 {
         Scsi_Device * SDpnt;
-        Scsi_Cmnd   * SCpnt;
+
         /*
          * Attach a single Scsi_Device to the Scsi_Host - this should
          * be made to look like a "pseudo-device" that points to the
@@ -2330,18 +2314,9 @@
         SDpnt->type = -1;
         SDpnt->queue_depth = 1;
         
-        SCpnt = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);
-        memset(SCpnt, 0, sizeof(Scsi_Cmnd));
-        SCpnt->host = SHpnt;
-        SCpnt->device = SDpnt;
-        SCpnt->target = SDpnt->id;
-        SCpnt->state = SCSI_STATE_UNUSED;
-        SCpnt->owner = SCSI_OWNER_NOBODY;
-        SCpnt->request.rq_status = RQ_INACTIVE;
-
-        SDpnt->device_queue = SCpnt;
+	scsi_build_commandblocks(SDpnt);
 
-        blk_init_queue(&SDpnt->request_queue, scsi_get_request_handler(SDpnt, SDpnt->host));
+	scsi_initialize_queue(SDpnt, SHpnt);
         blk_queue_headactive(&SDpnt->request_queue, 0);
         SDpnt->request_queue.queuedata = (void *) SDpnt;
 
@@ -2380,7 +2355,7 @@
          * We only have a single SCpnt attached to this device.  Free
          * it now.
          */
-        kfree(SDpnt->device_queue);
+	scsi_release_commandblocks(SDpnt);
         kfree(SDpnt);
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.3.42/linux/drivers/scsi/scsi.h	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/scsi.h	Wed Feb  9 21:34:43 2000
@@ -415,8 +415,7 @@
 /*
  * Prototypes for functions in scsi_lib.c
  */
-extern void scsi_maybe_unblock_host(Scsi_Device * SDpnt);
-extern void scsi_blocked_request_fn(request_queue_t * q);
+extern int scsi_maybe_unblock_host(Scsi_Device * SDpnt);
 extern Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate,
 				   int sectors);
 extern struct Scsi_Device_Template *scsi_get_request_dev(struct request *);
@@ -426,13 +425,14 @@
 			       int block_sectors);
 extern void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt);
 extern void scsi_request_fn(request_queue_t * q);
-
+extern int scsi_starvation_completion(Scsi_Device * SDpnt);
 
 /*
  * Prototypes for functions in scsi.c
  */
 extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
 extern void scsi_bottom_half_handler(void);
+extern void scsi_release_commandblocks(Scsi_Device * SDpnt);
 extern void scsi_build_commandblocks(Scsi_Device * SDpnt);
 extern void scsi_done(Scsi_Cmnd * SCpnt);
 extern void scsi_finish_command(Scsi_Cmnd *);
@@ -447,6 +447,7 @@
 			  void *buffer, unsigned bufflen,
 			  int timeout, int retries);
 extern int scsi_dev_init(void);
+
 
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.3.42/linux/drivers/scsi/scsi_error.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/scsi/scsi_error.c	Wed Feb  9 18:40:23 2000
@@ -972,9 +972,13 @@
 		 * When the low level driver returns DID_SOFT_ERROR,
 		 * it is responsible for keeping an internal retry counter 
 		 * in order to avoid endless loops (DB)
+		 *
+		 * Actually this is a bug in this function here.  We should
+		 * be mindful of the maximum number of retries specified
+		 * and not get stuck in a loop.
 		 */
 	case DID_SOFT_ERROR:
-		return NEEDS_RETRY;
+		goto maybe_retry;
 
 	case DID_BUS_BUSY:
 	case DID_PARITY:
@@ -1830,6 +1834,8 @@
          */
         if( host->loaded_as_module ) {
 	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
+	} else {
+	siginitsetinv(&current->blocked, 0);
         }
 
 	lock_kernel();
@@ -1865,13 +1871,20 @@
 		 * trying to unload a module.
 		 */
 		SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler sleeping\n"));
-                if( host->loaded_as_module ) {
-		down_interruptible(&sem);
 
-		if (signal_pending(current))
-			break;
-                } else {
-                        down(&sem);
+		/*
+		 * Note - we always use down_interruptible with the semaphore
+		 * even if the module was loaded as part of the kernel.  The
+		 * reason is that down() will cause this thread to be counted
+		 * in the load average as a running process, and down
+		 * interruptible doesn't.  Given that we need to allow this
+		 * thread to die if the driver was loaded as a module, using
+		 * semaphores isn't unreasonable.
+		 */
+		down_interruptible(&sem);
+		if( host->loaded_as_module ) {
+			if (signal_pending(current))
+				break;
                 }
 
 		SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler waking up\n"));
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.3.42/linux/drivers/scsi/scsi_ioctl.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/scsi_ioctl.c	Wed Feb  9 18:40:23 2000
@@ -323,7 +323,7 @@
 	{
 		int i;
 		printk("scsi_ioctl : device %d.  command = ", dev->id);
-		for (i = 0; i < 12; ++i)
+		for (i = 0; i < cmdlen; ++i)
 			printk("%02x ", cmd[i]);
 		printk("\nbuffer =");
 		for (i = 0; i < 20; ++i)
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- v2.3.42/linux/drivers/scsi/scsi_lib.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/scsi_lib.c	Wed Feb  9 18:40:23 2000
@@ -50,12 +50,6 @@
  * This entire source file deals with the new queueing code.
  */
 
-/*
- * For hosts that request single-file access to the ISA bus, this is a pointer to
- * the currently active host.
- */
-volatile struct Scsi_Host *host_active = NULL;
-
 
 /*
  * Function:    scsi_insert_special_cmd()
@@ -191,7 +185,6 @@
 	return 1;
 }
 
-
 /*
  * Function:    scsi_queue_next_request()
  *
@@ -1009,4 +1002,21 @@
 		 */
 		spin_lock_irq(&io_request_lock);
 	}
+}
+
+/*
+ * FIXME(eric) - these are empty stubs for the moment.  I need to re-implement
+ * host blocking from scratch. The theory is that hosts that wish to block
+ * will register/deregister using these functions instead of the old way
+ * of setting the wish_block flag.
+ *
+ * The details of the implementation remain to be settled, however the
+ * stubs are here now so that the actual drivers will properly compile.
+ */
+void scsi_register_blocked_host(struct Scsi_Host * SHpnt)
+{
+}
+
+void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt)
+{
 }
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c
--- v2.3.42/linux/drivers/scsi/scsi_merge.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/scsi/scsi_merge.c	Mon Feb  7 19:45:28 2000
@@ -109,9 +109,7 @@
 #define SANITY_CHECK(req, _CLUSTER, _DMA)				\
     if( req->nr_segments != __count_segments(req, _CLUSTER, _DMA, NULL) )	\
     {									\
-	__label__ here;							\
-here:									\
-	printk("Incorrect segment count at 0x%p", &&here);		\
+	printk("Incorrect segment count at 0x%p", current_text_addr());	\
 	dump_stats(req, _CLUSTER, _DMA, __count_segments(req, _CLUSTER, _DMA, NULL)); \
     }
 #else
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c
--- v2.3.42/linux/drivers/scsi/scsi_scan.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/scsi_scan.c	Wed Feb  9 18:40:23 2000
@@ -42,7 +42,7 @@
 
 static void print_inquiry(unsigned char *data);
 static int scan_scsis_single(int channel, int dev, int lun, int *max_scsi_dev,
-		int *sparse_lun, Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt,
+		int *sparse_lun, Scsi_Device ** SDpnt,
 			     struct Scsi_Host *shpnt, char *scsi_result);
 
 struct dev_info {
@@ -119,6 +119,7 @@
 	{"IOMEGA", "Io20S         *F", "*", BLIST_KEY},
 	{"INSITE", "Floptical   F*8I", "*", BLIST_KEY},
 	{"INSITE", "I325VM", "*", BLIST_KEY},
+	{"LASOUND","CDX7405","3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
 	{"NRC", "MBR-7", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"NRC", "MBR-7.4", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
 	{"REGAL", "CDC-4X", "*", BLIST_MAX5LUN | BLIST_SINGLELUN},
@@ -259,7 +260,6 @@
 	int dev;
 	int lun;
 	int max_dev_lun;
-	Scsi_Cmnd *SCpnt;
 	unsigned char *scsi_result;
 	unsigned char scsi_result0[256];
 	Scsi_Device *SDpnt;
@@ -267,29 +267,26 @@
 	int sparse_lun;
 
 	scsi_result = NULL;
-	SCpnt = (Scsi_Cmnd *) kmalloc(sizeof(Scsi_Cmnd),
-					       GFP_ATOMIC | GFP_DMA);
-	if (SCpnt) {
-                memset(SCpnt, 0, sizeof(Scsi_Cmnd));
-		SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device),
-							 GFP_ATOMIC);
-		if (SDpnt) {
-                        memset(SDpnt, 0, sizeof(Scsi_Device));
-			/*
-			 * Register the queue for the device.  All I/O requests will come
-			 * in through here.  We also need to register a pointer to
-			 * ourselves, since the queue handler won't know what device
-			 * the queue actually represents.   We could look it up, but it
-			 * is pointless work.
-			 */
-			blk_init_queue(&SDpnt->request_queue, scsi_get_request_handler(SDpnt, shpnt));
-			blk_queue_headactive(&SDpnt->request_queue, 0);
-			SDpnt->request_queue.queuedata = (void *) SDpnt;
-			/* Make sure we have something that is valid for DMA purposes */
-			scsi_result = ((!shpnt->unchecked_isa_dma)
-				       ? &scsi_result0[0] : kmalloc(512, GFP_DMA));
-		}
+
+	SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device),
+					GFP_ATOMIC);
+	if (SDpnt) {
+		memset(SDpnt, 0, sizeof(Scsi_Device));
+		/*
+		 * Register the queue for the device.  All I/O requests will come
+		 * in through here.  We also need to register a pointer to
+		 * ourselves, since the queue handler won't know what device
+		 * the queue actually represents.   We could look it up, but it
+		 * is pointless work.
+		 */
+		scsi_initialize_queue(SDpnt, shpnt);
+		blk_queue_headactive(&SDpnt->request_queue, 0);
+		SDpnt->request_queue.queuedata = (void *) SDpnt;
+		/* Make sure we have something that is valid for DMA purposes */
+		scsi_result = ((!shpnt->unchecked_isa_dma)
+			       ? &scsi_result0[0] : kmalloc(512, GFP_DMA));
 	}
+
 	if (scsi_result == NULL) {
 		printk("Unable to obtain scsi_result buffer\n");
 		goto leave;
@@ -297,11 +294,12 @@
 	/*
 	 * We must chain ourself in the host_queue, so commands can time out 
 	 */
-	SCpnt->next = NULL;
-	SDpnt->device_queue = SCpnt;
+	SDpnt->queue_depth = 1;
 	SDpnt->host = shpnt;
 	SDpnt->online = TRUE;
 
+	scsi_build_commandblocks(SDpnt);
+
 	initialize_merge_fn(SDpnt);
 
         /*
@@ -329,9 +327,6 @@
 	 * We need to increment the counter for this one device so we can track when
 	 * things are quiet.
 	 */
-	atomic_inc(&shpnt->host_active);
-	atomic_inc(&SDpnt->device_active);
-
 	if (hardcoded == 1) {
 		Scsi_Device *oldSDpnt = SDpnt;
 		struct Scsi_Device_Template *sdtpnt;
@@ -345,7 +340,7 @@
 		if (lun >= shpnt->max_lun)
 			goto leave;
 		scan_scsis_single(channel, dev, lun, &max_dev_lun, &sparse_lun,
-				  &SDpnt, SCpnt, shpnt, scsi_result);
+				  &SDpnt, shpnt, scsi_result);
 		if (SDpnt != oldSDpnt) {
 
 			/* it could happen the blockdevice hasn't yet been inited */
@@ -397,7 +392,7 @@
 					sparse_lun = 0;
 					for (lun = 0; lun < max_dev_lun; ++lun) {
 						if (!scan_scsis_single(channel, order_dev, lun, &max_dev_lun,
-								       &sparse_lun, &SDpnt, SCpnt, shpnt,
+								       &sparse_lun, &SDpnt, shpnt,
 							     scsi_result)
 						    && !sparse_lun)
 							break;	/* break means don't probe further for luns!=0 */
@@ -407,13 +402,6 @@
 		}		/* for channel ends */
 	}			/* if/else hardcoded */
 
-	/*
-	 * We need to decrement the counter for this one device
-	 * so we know when everything is quiet.
-	 */
-	atomic_dec(&shpnt->host_active);
-	atomic_dec(&SDpnt->device_active);
-
       leave:
 
 	{			/* Unchain SCpnt from host_queue */
@@ -434,13 +422,12 @@
 		}
 	}
 
+	scsi_release_commandblocks(SDpnt);
+
 	/* Last device block does not exist.  Free memory. */
 	if (SDpnt != NULL)
 		kfree((char *) SDpnt);
 
-	if (SCpnt != NULL)
-		kfree((char *) SCpnt);
-
 	/* If we allocated a buffer so we could do DMA, free it now */
 	if (scsi_result != &scsi_result0[0] && scsi_result != NULL) {
 		kfree(scsi_result);
@@ -464,13 +451,14 @@
  * Returning 0 means Please don't ask further for lun!=0, 1 means OK go on.
  * Global variables used : scsi_devices(linked list)
  */
-int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun,
-	       int *sparse_lun, Scsi_Device ** SDpnt2, Scsi_Cmnd * SCpnt,
+static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun,
+	       int *sparse_lun, Scsi_Device ** SDpnt2, 
 		      struct Scsi_Host *shpnt, char *scsi_result)
 {
 	unsigned char scsi_cmd[MAX_COMMAND_SIZE];
 	struct Scsi_Device_Template *sdtpnt;
 	Scsi_Device *SDtail, *SDpnt = *SDpnt2;
+	Scsi_Cmnd * SCpnt;
 	int bflags, type = -1;
 	static int ghost_channel=-1, ghost_dev=-1;
 	int org_lun = lun;
@@ -505,6 +493,8 @@
 	scsi_cmd[1] = lun << 5;
 	scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0;
 
+	SCpnt = scsi_allocate_device(SDpnt, 0, 0);
+
 	SCpnt->host = SDpnt->host;
 	SCpnt->device = SDpnt;
 	SCpnt->target = SDpnt->id;
@@ -527,10 +517,14 @@
 		    ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
 			if (((SCpnt->sense_buffer[2] & 0xf) != NOT_READY) &&
 			    ((SCpnt->sense_buffer[2] & 0xf) != UNIT_ATTENTION) &&
-			    ((SCpnt->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0))
+			    ((SCpnt->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0)) {
+				scsi_release_command(SCpnt);
 				return 1;
-		} else
+			}
+		} else {
+			scsi_release_command(SCpnt);
 			return 0;
+		}
 	}
 	SCSI_LOG_SCAN_BUS(3, printk("scsi: performing INQUIRY\n"));
 	/*
@@ -551,14 +545,17 @@
 	SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY %s with code 0x%x\n",
 		SCpnt->result ? "failed" : "successful", SCpnt->result));
 
-	if (SCpnt->result)
+	if (SCpnt->result) {
+		scsi_release_command(SCpnt);
 		return 0;	/* assume no peripheral if any sort of error */
+	}
 
 	/*
 	 * Check the peripheral qualifier field - this tells us whether LUNS
 	 * are supported here or not.
 	 */
 	if ((scsi_result[0] >> 5) == 3) {
+		scsi_release_command(SCpnt);
 		return 0;	/* assume no peripheral if any sort of error */
 	}
 
@@ -703,11 +700,11 @@
 	        	(void *) scsi_result, 0x2a,
 	        	SCSI_TIMEOUT, 3);
 	}
-	/*
-	 * Detach the command from the device. It was just a temporary to be used while
-	 * scanning the bus - the real ones will be allocated later.
-	 */
-	SDpnt->device_queue = NULL;
+
+	scsi_release_command(SCpnt);
+	SCpnt = NULL;
+
+	scsi_release_commandblocks(SDpnt);
 
 	/*
 	 * This device was already hooked up to the host in question,
@@ -715,13 +712,19 @@
 	 * allocate a new one and attach it to the host so that we can further scan the bus.
 	 */
 	SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), GFP_ATOMIC);
-	*SDpnt2 = SDpnt;
 	if (!SDpnt) {
 		printk("scsi: scan_scsis_single: Cannot malloc\n");
 		return 0;
 	}
         memset(SDpnt, 0, sizeof(Scsi_Device));
 
+	*SDpnt2 = SDpnt;
+	SDpnt->queue_depth = 1;
+	SDpnt->host = shpnt;
+	SDpnt->online = TRUE;
+
+	scsi_build_commandblocks(SDpnt);
+
 	/*
 	 * Register the queue for the device.  All I/O requests will come
 	 * in through here.  We also need to register a pointer to
@@ -729,17 +732,15 @@
 	 * the queue actually represents.   We could look it up, but it
 	 * is pointless work.
 	 */
-	blk_init_queue(&SDpnt->request_queue, scsi_get_request_handler(SDpnt, shpnt));
+	scsi_initialize_queue(SDpnt, shpnt);
 	blk_queue_headactive(&SDpnt->request_queue, 0);
 	SDpnt->request_queue.queuedata = (void *) SDpnt;
 	SDpnt->host = shpnt;
 	initialize_merge_fn(SDpnt);
 
 	/*
-	 * And hook up our command block to the new device we will be testing
-	 * for.
+	 * Mark this device as online, or otherwise we won't be able to do much with it.
 	 */
-	SDpnt->device_queue = SCpnt;
 	SDpnt->online = TRUE;
 
         /*
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.3.42/linux/drivers/scsi/scsi_syms.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/scsi/scsi_syms.c	Wed Feb  9 18:40:23 2000
@@ -50,8 +50,6 @@
 EXPORT_SYMBOL(scsi_do_cmd);
 EXPORT_SYMBOL(scsi_wait_cmd);
 EXPORT_SYMBOL(scsi_command_size);
-EXPORT_SYMBOL(scsi_init_malloc);
-EXPORT_SYMBOL(scsi_init_free);
 EXPORT_SYMBOL(scsi_ioctl);
 EXPORT_SYMBOL(print_command);
 EXPORT_SYMBOL(print_sense);
@@ -79,6 +77,9 @@
 
 EXPORT_SYMBOL(scsi_io_completion);
 EXPORT_SYMBOL(scsi_end_request);
+
+EXPORT_SYMBOL(scsi_register_blocked_host);
+EXPORT_SYMBOL(scsi_deregister_blocked_host);
 
 /*
  * These are here only while I debug the rest of the scsi stuff.
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.3.42/linux/drivers/scsi/sd.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/scsi/sd.c	Wed Feb  9 18:40:23 2000
@@ -960,15 +960,15 @@
 		return 0;
 
 	rscsi_disks = (Scsi_Disk *)
-	    scsi_init_malloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
+	    kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
 	memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk));
 
 	/* for every (necessary) major: */
-	sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+	sd_sizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
 	memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int));
 
-	sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
-	sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+	sd_blocksizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+	sd_hardsizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
 
 	for (i = 0; i < sd_template.dev_max << 4; i++) {
 		sd_blocksizes[i] = 1024;
@@ -979,9 +979,10 @@
 		blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4);
 		hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4);
 	}
-	sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) *
-						sizeof(struct hd_struct),
-						   GFP_ATOMIC);
+	sd = (struct hd_struct *) kmalloc((sd_template.dev_max << 4) *
+					  sizeof(struct hd_struct),
+					  GFP_ATOMIC);
+	memset(sd, 0, (sd_template.dev_max << 4) * sizeof(struct hd_struct));
 
 	if (N_USED_SD_MAJORS > 1)
 		sd_gendisks = (struct gendisk *)
@@ -1215,13 +1216,11 @@
 
 	sd_registered--;
 	if (rscsi_disks != NULL) {
-		scsi_init_free((char *) rscsi_disks,
-			       sd_template.dev_max * sizeof(Scsi_Disk));
-		scsi_init_free((char *) sd_sizes, sd_template.dev_max * sizeof(int));
-		scsi_init_free((char *) sd_blocksizes, sd_template.dev_max * sizeof(int));
-		scsi_init_free((char *) sd_hardsizes, sd_template.dev_max * sizeof(int));
-		scsi_init_free((char *) sd,
-		  (sd_template.dev_max << 4) * sizeof(struct hd_struct));
+		kfree((char *) rscsi_disks);
+		kfree((char *) sd_sizes);
+		kfree((char *) sd_blocksizes);
+		kfree((char *) sd_hardsizes);
+		kfree((char *) sd);
 
 		/*
 		 * Now remove sd_gendisks from the linked list
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.3.42/linux/drivers/scsi/sg.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/scsi/sg.c	Thu Feb 10 12:37:22 2000
@@ -6,7 +6,7 @@
  *
  * Original driver (sg.c):
  *        Copyright (C) 1992 Lawrence Foard
- * 2.x extensions to driver:
+ * Version 2 and 3 extensions to driver:
  *        Copyright (C) 1998, 1999 Douglas Gilbert
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,35 +14,29 @@
  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.
  *
- *  Borrows code from st driver. Thanks to Alessandro Rubini's "dd" book.
  */
- static char * sg_version_str = "Version: 2.3.35 (990708)";
- static int sg_version_num = 20335; /* 2 digits for each component */
+ static char * sg_version_str = "Version: 3.1.10 (20000123)";
+ static int sg_version_num = 30110; /* 2 digits for each component */
 /*
  *  D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
  *      - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
  *        the kernel/module needs to be built with CONFIG_SCSI_LOGGING
- *        (otherwise the macros compile to empty statements). 
- *        Then before running the program to be debugged enter: 
- *          # echo "scsi log timeout 7" > /proc/scsi/scsi 
+ *        (otherwise the macros compile to empty statements).
+ *        Then before running the program to be debugged enter:
+ *          # echo "scsi log timeout 7" > /proc/scsi/scsi
  *        This will send copious output to the console and the log which
  *        is usually /var/log/messages. To turn off debugging enter:
- *          # echo "scsi log timeout 0" > /proc/scsi/scsi 
+ *          # echo "scsi log timeout 0" > /proc/scsi/scsi
  *        The 'timeout' token was chosen because it is relatively unused.
  *        The token 'hlcomplete' should be used but that triggers too
  *        much output from the sd device driver. To dump the current
  *        state of the SCSI mid level data structures enter:
- *          # echo "scsi dump 1" > /proc/scsi/scsi 
- *        To dump the state of sg's data structures get the 'sg_debug'
- *        program from the utilities and enter:
- *          # sg_debug /dev/sga 
- *        or any valid sg device name. The state of _all_ sg devices
- *        will be sent to the console and the log.
- *
- *      - The 'alt_address' field in the scatter_list structure and the
- *        related 'mem_src' indicate the source of the heap allocation.
+ *          # echo "scsi dump 1" > /proc/scsi/scsi
+ *        To dump the state of sg's data structures use:
+ *          # cat /proc/scsi/sg/debug
  *
  */
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/fs.h>
@@ -54,6 +48,7 @@
 #include <linux/mtio.h>
 #include <linux/ioctl.h>
 #include <linux/fcntl.h>
+#include <linux/init.h>
 #include <linux/poll.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -65,13 +60,29 @@
 #include <scsi/scsi_ioctl.h>
 #include <scsi/sg.h>
 
-static spinlock_t sg_request_lock = SPIN_LOCK_UNLOCKED;
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+static int sg_proc_init(void);
+static void sg_proc_cleanup(void);
+#endif
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif /* LINUX_VERSION_CODE */
+
+/* #define SG_ALLOW_DIO */
+#ifdef SG_ALLOW_DIO
+#include <linux/iobuf.h>
+#endif
 
-int sg_big_buff = SG_DEF_RESERVED_SIZE; /* sg_big_buff is ro through sysctl */
-/* N.B. This global is here to keep existing software happy. It now holds
-   the size of the reserve buffer of the most recent sucessful sg_open(). 
-   Only available when 'sg' compiled into kernel (rather than a module). 
-   This is deprecated (use SG_GET_RESERVED_SIZE ioctl() instead). */
+int sg_big_buff = SG_DEF_RESERVED_SIZE;
+/* N.B. This variable is readable and writeable via
+   /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer
+   of this size (or less if there is not enough memory) will be reserved
+   for use by this file descriptor. [Deprecated usage: this variable is also
+   readable via /proc/sys/kernel/sg-big-buff if the sg driver is built into
+   the kernel (i.e. it is not a module).] */
+static int def_reserved_size = -1;      /* picks up init parameter */
 
 #define SG_SECTOR_SZ 512
 #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
@@ -81,17 +92,10 @@
 
 static int sg_pool_secs_avail = SG_MAX_POOL_SECTORS;
 
-/* #define SG_DEBUG */  /* for counting varieties of allocations */
-
-#ifdef SG_DEBUG
-static int sg_num_kmal = 0;
-static int sg_num_pool = 0;
-static int sg_num_page = 0;
-#endif
-
 #define SG_HEAP_PAGE 1  /* heap from kernel via get_free_pages() */
 #define SG_HEAP_KMAL 2  /* heap from kernel via kmalloc() */
 #define SG_HEAP_POOL 3  /* heap from scsi dma pool (mid-level) */
+#define SG_USER_MEM 4   /* memory belongs to user space */
 
 
 static int sg_init(void);
@@ -100,28 +104,36 @@
 static int sg_detect(Scsi_Device *);
 static void sg_detach(Scsi_Device *);
 
+static Scsi_Cmnd * dummy_cmdp = 0;    /* only used for sizeof */
+
 
-struct Scsi_Device_Template sg_template = 
+static spinlock_t sg_request_lock = SPIN_LOCK_UNLOCKED;
+
+struct Scsi_Device_Template sg_template =
 {
-	tag:"sg", 
-	scsi_type:0xff,
-	major:SCSI_GENERIC_MAJOR, 
-	detect:sg_detect, 
-	init:sg_init,
-	finish:sg_finish, 
-	attach:sg_attach, 
-	detach:sg_detach
+      tag:"sg",
+      scsi_type:0xff,
+      major:SCSI_GENERIC_MAJOR,
+      detect:sg_detect,
+      init:sg_init,
+      finish:sg_finish,
+      attach:sg_attach,
+      detach:sg_detach
 };
 
+/* Need to add 'rwlock_t sg_rw_lock = RW_LOCK_UNLOCKED;' for list protection */
 
 typedef struct sg_scatter_hold  /* holding area for scsi scatter gather info */
 {
-    unsigned short use_sg;      /* Number of pieces of scatter-gather */
+    unsigned short k_use_sg;    /* Count of kernel scatter-gather pieces */
     unsigned short sglist_len;  /* size of malloc'd scatter-gather list */
     unsigned bufflen;           /* Size of (aggregate) data buffer */
     unsigned b_malloc_len;      /* actual len malloc'ed in buffer */
     void * buffer;              /* Data buffer or scatter list,12 bytes each*/
-    char mem_src;               /* heap whereabouts of 'buffer' */
+    struct kiobuf * kiobp;      /* for direct IO information */
+    char mapped;                /* indicates kiobp has locked pages */
+    char buffer_mem_src;        /* heap whereabouts of 'buffer' */
+    unsigned char cmd_opcode;   /* first byte of command */
 } Sg_scatter_hold;    /* 20 bytes long on i386 */
 
 struct sg_device;               /* forward declarations */
@@ -129,20 +141,23 @@
 
 typedef struct sg_request  /* SG_MAX_QUEUE requests outstanding per file */
 {
-    Scsi_Cmnd * my_cmdp;        /* NULL -> ready to read, else id */
+    Scsi_Cmnd * my_cmdp;        /* != 0  when request with lower levels */
     struct sg_request * nextrp; /* NULL -> tail request (slist) */
     struct sg_fd * parentfp;    /* NULL -> not in use */
     Sg_scatter_hold data;       /* hold buffer, perhaps scatter list */
-    struct sg_header header;    /* scsi command+info, see <scsi/sg.h> */
+    sg_io_hdr_t header;         /* scsi command+info, see <scsi/sg.h> */
+    unsigned char sense_b[sizeof(dummy_cmdp->sense_buffer)];
     char res_used;              /* 1 -> using reserve buffer, 0 -> not ... */
-} Sg_request; /* 72 bytes long on i386 */
+    char orphan;                /* 1 -> drop on sight, 0 -> normal */
+    char sg_io_owned;           /* 1 -> packet belongs to SG_IO */
+    char done;                  /* 1 -> bh handler done, 0 -> prior to bh */
+} Sg_request; /* 168 bytes long on i386 */
 
 typedef struct sg_fd /* holds the state of a file descriptor */
 {
     struct sg_fd * nextfp; /* NULL when last opened fd on this device */
     struct sg_device * parentdp;     /* owning device */
     wait_queue_head_t read_wait;     /* queue read until command done */
-    wait_queue_head_t write_wait;    /* write waits on pending read */
     int timeout;                     /* defaults to SG_DEFAULT_TIMEOUT */
     Sg_scatter_hold reserve;  /* buffer held for this file descriptor */
     unsigned save_scat_len;   /* original length of trunc. scat. element */
@@ -152,60 +167,73 @@
     char low_dma;       /* as in parent but possibly overridden to 1 */
     char force_packid;  /* 1 -> pack_id input to read(), 0 -> ignored */
     char closed;        /* 1 -> fd closed but request(s) outstanding */
-    char my_mem_src;    /* heap whereabouts of this Sg_fd object */
+    char fd_mem_src;    /* heap whereabouts of this Sg_fd object */
     char cmd_q;         /* 1 -> allow command queuing, 0 -> don't */
-    char underrun_flag; /* 1 -> flag underruns, 0 -> don't, 2 -> test */
     char next_cmd_len;  /* 0 -> automatic (def), >0 -> use on next write() */
+    char keep_orphan;   /* 0 -> drop orphan (def), 1 -> keep for read() */
 } Sg_fd; /* 1212 bytes long on i386 */
 
 typedef struct sg_device /* holds the state of each scsi generic device */
 {
     Scsi_Device * device;
-    wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */
+    wait_queue_head_t o_excl_wait;   /* queue open() when O_EXCL in use */
     int sg_tablesize;   /* adapter's max scatter-gather table size */
     Sg_fd * headfp;     /* first open fd belonging to this device */
     kdev_t i_rdev;      /* holds device major+minor number */
     char exclude;       /* opened for exclusive access */
     char sgdebug;       /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
-    unsigned char merge_fd; /* 0->sequencing per fd, else fd count */
 } Sg_device; /* 24 bytes long on i386 */
 
 
 static int sg_fasync(int fd, struct file * filp, int mode);
-static void sg_command_done(Scsi_Cmnd * SCpnt);
-static int sg_start_req(Sg_request * srp, int max_buff_size,
-                        const char * inp, int num_write_xfer);
-static void sg_finish_rem_req(Sg_request * srp, char * outp,
-                              int num_read_xfer);
-static int sg_build_scat(Sg_scatter_hold * schp, int buff_size, 
-                         const Sg_fd * sfp);
-static void sg_write_xfer(Sg_scatter_hold * schp, const char * inp, 
-                          int num_write_xfer);
+static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt);
+static int sg_start_req(Sg_request * srp);
+static void sg_finish_rem_req(Sg_request * srp);
+static int sg_build_indi(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
+static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp);
+static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count,
+			   Sg_request * srp);
+static ssize_t sg_new_write(Sg_fd * sfp, const char * buf, size_t count,
+			int blocking, int read_only, Sg_request ** o_srp);
+static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
+			   unsigned char * cmnd, int timeout, int blocking);
+static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
+		      int wr_xf, int * countp, unsigned char ** up);
+static int sg_write_xfer(Sg_request * srp);
+static int sg_read_xfer(Sg_request * srp);
+static void sg_read_oxfer(Sg_request * srp, char * outp, int num_read_xfer);
 static void sg_remove_scat(Sg_scatter_hold * schp);
-static void sg_read_xfer(Sg_scatter_hold * schp, char * outp,
-                         int num_read_xfer);
+static char * sg_get_sgat_msa(Sg_scatter_hold * schp);
 static void sg_build_reserve(Sg_fd * sfp, int req_size);
 static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
 static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
-static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp, 
+static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp,
                         int * mem_srcp);
 static void sg_free(char * buff, int size, int mem_src);
-static char * sg_low_malloc(int rqSz, int lowDma, int mem_src, 
+static char * sg_low_malloc(int rqSz, int lowDma, int mem_src,
                             int * retSzp);
 static void sg_low_free(char * buff, int size, int mem_src);
-static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev, int get_reserved);
+static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev);
 static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
 static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id);
 static Sg_request * sg_add_request(Sg_fd * sfp);
-static int sg_remove_request(Sg_fd * sfp, const Sg_request * srp);
+static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(const Sg_fd * sfp);
+static int sg_dio_in_use(const Sg_fd * sfp);
 static void sg_clr_scpnt(Scsi_Cmnd * SCpnt);
 static void sg_shorten_timeout(Scsi_Cmnd * scpnt);
-static void sg_debug(const Sg_device * sdp, const Sg_fd * sfp, int part_of);
-static void sg_debug_all(const Sg_fd * sfp);
+static int sg_ms_to_jif(unsigned int msecs);
+static unsigned sg_jif_to_ms(int jifs);
+static int sg_allow_access(unsigned char opcode, char dev_type);
+static int sg_last_dev(void);
+static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
+static void sg_unmap_and(Sg_scatter_hold * schp, int free_also);
 
 static Sg_device * sg_dev_arr = NULL;
 static const int size_sg_header = sizeof(struct sg_header);
+static const int size_sg_io_hdr = sizeof(sg_io_hdr_t);
+static const int size_sg_iovec = sizeof(sg_iovec_t);
+static const int size_sg_req_info = sizeof(sg_req_info_t);
 
 
 static int sg_open(struct inode * inode, struct file * filp)
@@ -240,8 +268,8 @@
         if (sdp->headfp && (filp->f_flags & O_NONBLOCK))
             return -EBUSY;
         res = 0;  /* following is a macro that beats race condition */
-        __wait_event_interruptible(sdp->o_excl_wait, 
-               ((sdp->headfp || sdp->exclude) ? 0 : (sdp->exclude = 1)), 
+	__wait_event_interruptible(sdp->o_excl_wait,
+	       ((sdp->headfp || sdp->exclude) ? 0 : (sdp->exclude = 1)),
                                    res);
         if (res)
             return res; /* -ERESTARTSYS because signal hit process */
@@ -257,15 +285,9 @@
     if (! sdp->headfp) { /* no existing opens on this device */
         sdp->sgdebug = 0;
         sdp->sg_tablesize = sdp->device->host->sg_tablesize;
-        sdp->merge_fd = 0;   /* A little tricky if SG_DEF_MERGE_FD set */
     }
-    if ((sfp = sg_add_sfp(sdp, dev, O_RDWR == (flags & O_ACCMODE)))) {
+    if ((sfp = sg_add_sfp(sdp, dev)))
         filp->private_data = sfp;
-#if SG_DEF_MERGE_FD
-        if (0 == sdp->merge_fd)
-            sdp->merge_fd = 1;
-#endif
-    }
     else {
         if (flags & O_EXCL) sdp->exclude = 0; /* undo if error */
         return -ENOMEM;
@@ -287,12 +309,10 @@
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
     SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
-    sg_fasync(-1, filp, 0);   /* remove filp from async notification list */    
+    sg_fasync(-1, filp, 0);   /* remove filp from async notification list */
     sg_remove_sfp(sdp, sfp);
-    if (! sdp->headfp) {
+    if (! sdp->headfp)
         filp->private_data = NULL;
-        sdp->merge_fd = 0;
-    }
 
     if (sdp->device->host->hostt->module)
         __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
@@ -311,70 +331,162 @@
     Sg_fd * sfp;
     Sg_request * srp;
     int req_pack_id = -1;
-    struct sg_header * shp = (struct sg_header *)buf;
+    struct sg_header old_hdr;
+    sg_io_hdr_t new_hdr;
+    sg_io_hdr_t * hp;
 
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
-    SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n", 
+    SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n",
                                MINOR(sdp->i_rdev), (int)count));
-    
+
     if(! scsi_block_when_processing_errors(sdp->device))
         return -ENXIO;
     if (ppos != &filp->f_pos)
         ; /* FIXME: Hmm.  Seek to the right place, or fail?  */
     if ((k = verify_area(VERIFY_WRITE, buf, count)))
         return k;
-    if (sfp->force_packid && (count >= size_sg_header))
-        req_pack_id = shp->pack_id;
+    if (sfp->force_packid && (count >= size_sg_header)) {
+	__copy_from_user(&old_hdr, buf, size_sg_header);
+	if (old_hdr.reply_len < 0) {
+	    if (count >= size_sg_io_hdr) {
+		__copy_from_user(&new_hdr, buf, size_sg_io_hdr);
+		req_pack_id = new_hdr.pack_id;
+	    }
+	}
+	else
+	    req_pack_id = old_hdr.pack_id;
+    }
     srp = sg_get_request(sfp, req_pack_id);
     if (! srp) { /* now wait on packet to arrive */
         if (filp->f_flags & O_NONBLOCK)
             return -EAGAIN;
-        res = 0;  /* following is a macro that beats race condition */
-        __wait_event_interruptible(sfp->read_wait, 
+	while (1) {
+	    int dio = sg_dio_in_use(sfp);
+	    res = 0;  /* following is a macro that beats race condition */
+	    __wait_event_interruptible(sfp->read_wait,
                                    (srp = sg_get_request(sfp, req_pack_id)),
                                    res);
-        if (res)
-            return res; /* -ERESTARTSYS because signal hit process */
+	    if (0 == res)
+		break;
+	    else if (! dio)     /* only let signal out if no dio */
+		return res; /* -ERESTARTSYS because signal hit process */
+	}
+    }
+    if (srp->header.interface_id != '\0')
+	return sg_new_read(sfp, buf, count, srp);
+
+    hp = &srp->header;
+    memset(&old_hdr, 0, size_sg_header);
+    old_hdr.reply_len = (int)hp->timeout;
+    old_hdr.pack_len = old_hdr.reply_len;   /* very old, strange behaviour */
+    old_hdr.pack_id = hp->pack_id;
+    old_hdr.twelve_byte =
+	    ((srp->data.cmd_opcode >= 0xc0) && (12 == hp->cmd_len)) ? 1 : 0;
+    old_hdr.target_status = hp->masked_status;
+    old_hdr.host_status = hp->host_status;
+    old_hdr.driver_status = hp->driver_status;
+    if ((CHECK_CONDITION & hp->masked_status) ||
+	(DRIVER_SENSE & hp->driver_status))
+	memcpy(old_hdr.sense_buffer, srp->sense_b,
+	       sizeof(old_hdr.sense_buffer));
+    switch (hp->host_status)
+    { /* This setup of 'result' is for backward compatibility and is best
+	 ignored by the user who should use target, host + driver status */
+	case DID_OK:
+	case DID_PASSTHROUGH:
+	case DID_SOFT_ERROR:
+	    old_hdr.result = 0;
+	    break;
+	case DID_NO_CONNECT:
+	case DID_BUS_BUSY:
+	case DID_TIME_OUT:
+	    old_hdr.result = EBUSY;
+	    break;
+	case DID_BAD_TARGET:
+	case DID_ABORT:
+	case DID_PARITY:
+	case DID_RESET:
+	case DID_BAD_INTR:
+	    old_hdr.result = EIO;
+	    break;
+	case DID_ERROR:
+	    old_hdr.result =
+	      (srp->sense_b[0] == 0 && hp->masked_status == GOOD) ? 0 : EIO;
+	    break;
+	default:
+	    old_hdr.result = EIO;
+	    break;
     }
-    if (2 != sfp->underrun_flag)
-        srp->header.pack_len = srp->header.reply_len;   /* Why ????? */
 
     /* Now copy the result back to the user buffer.  */
     if (count >= size_sg_header) {
-        __copy_to_user(buf, &srp->header, size_sg_header);
+	__copy_to_user(buf, &old_hdr, size_sg_header);
         buf += size_sg_header;
-        if (count > srp->header.reply_len)
-            count = srp->header.reply_len;
-        if (count > size_sg_header) /* release does copy_to_user */
-            sg_finish_rem_req(srp, buf, count - size_sg_header);
-        else
-            sg_finish_rem_req(srp, NULL, 0);
+	if (count > old_hdr.reply_len)
+	    count = old_hdr.reply_len;
+	if (count > size_sg_header)
+	    sg_read_oxfer(srp, buf, count - size_sg_header);
     }
-    else {
-        count = (srp->header.result == 0) ? 0 : -EIO;
-        sg_finish_rem_req(srp, NULL, 0);
-    }
-    if (! sfp->cmd_q)
-        wake_up_interruptible(&sfp->write_wait);
+    else
+	count = (old_hdr.result == 0) ? 0 : -EIO;
+    sg_finish_rem_req(srp);
     return count;
 }
 
-static ssize_t sg_write(struct file * filp, const char * buf, 
+static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count,
+			   Sg_request * srp)
+{
+    Sg_device           * sdp = sfp->parentdp;
+    sg_io_hdr_t         * hp = &srp->header;
+    int                   k, len;
+
+    if(! scsi_block_when_processing_errors(sdp->device) )
+	return -ENXIO;
+    if (count < size_sg_io_hdr)
+	return -EINVAL;
+
+    hp->sb_len_wr = 0;
+    if ((hp->mx_sb_len > 0) && hp->sbp) {
+	if ((CHECK_CONDITION & hp->masked_status) ||
+	    (DRIVER_SENSE & hp->driver_status)) {
+	    int sb_len = sizeof(dummy_cmdp->sense_buffer);
+	    sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len;
+	    len = 8 + (int)srp->sense_b[7]; /* Additional sense length field */
+	    len = (len > sb_len) ? sb_len : len;
+	    if ((k = verify_area(VERIFY_WRITE, hp->sbp, len)))
+		return k;
+	    __copy_to_user(hp->sbp, srp->sense_b, len);
+	    hp->sb_len_wr = len;
+	}
+    }
+    if (hp->masked_status || hp->host_status || hp->driver_status)
+	hp->info |= SG_INFO_CHECK;
+    copy_to_user(buf, hp, size_sg_io_hdr);
+
+    k = sg_read_xfer(srp);
+    if (k) return k; /* probably -EFAULT, bad addr in dxferp or iovec list */
+    sg_finish_rem_req(srp);
+    return count;
+}
+
+
+static ssize_t sg_write(struct file * filp, const char * buf,
                         size_t count, loff_t *ppos)
 {
     int                   mxsize, cmd_size, k;
-    unsigned char         cmnd[MAX_COMMAND_SIZE];
-    int                   input_size;
+    int                   input_size, blocking;
     unsigned char         opcode;
-    Scsi_Cmnd           * SCpnt;
     Sg_device           * sdp;
     Sg_fd               * sfp;
     Sg_request          * srp;
+    struct sg_header      old_hdr;
+    sg_io_hdr_t         * hp;
+    unsigned char         cmnd[sizeof(dummy_cmdp->cmnd)];
 
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
-    SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n", 
+    SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n",
                                MINOR(sdp->i_rdev), (int)count));
 
     if(! scsi_block_when_processing_errors(sdp->device) )
@@ -384,33 +496,26 @@
 
     if ((k = verify_area(VERIFY_READ, buf, count)))
         return k;  /* protects following copy_from_user()s + get_user()s */
+    if (count < size_sg_header)
+	return -EIO;
+    __copy_from_user(&old_hdr, buf, size_sg_header);
+    blocking = !(filp->f_flags & O_NONBLOCK);
+    if (old_hdr.reply_len < 0)
+	return sg_new_write(sfp, buf, count, blocking, 0, NULL);
     if (count < (size_sg_header + 6))
-        return -EIO;   /* The minimum scsi command length is 6 bytes. */ 
+	return -EIO;   /* The minimum scsi command length is 6 bytes. */
 
     if (! (srp = sg_add_request(sfp))) {
-        if (sfp->cmd_q) {
-            SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full\n"));
-            return -EDOM;
-        }
-        else { /* old semantics: wait for pending read() to finish */
-            if (filp->f_flags & O_NONBLOCK)
-                return -EAGAIN;
-            k = 0;
-            __wait_event_interruptible(sfp->write_wait, 
-                                   (srp = sg_add_request(sfp)),
-                                   k);
-            if (k)
-                return k; /* -ERESTARTSYS because signal hit process */
-        }
+	SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full\n"));
+	return -EDOM;
     }
-    __copy_from_user(&srp->header, buf, size_sg_header); 
     buf += size_sg_header;
-    srp->header.pack_len = count;
     __get_user(opcode, buf);
     if (sfp->next_cmd_len > 0) {
         if (sfp->next_cmd_len > MAX_COMMAND_SIZE) {
             SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n"));
             sfp->next_cmd_len = 0;
+	    sg_remove_request(sfp, srp);
             return -EIO;
         }
         cmd_size = sfp->next_cmd_len;
@@ -418,87 +523,204 @@
     }
     else {
         cmd_size = COMMAND_SIZE(opcode); /* based on SCSI command group */
-        if ((opcode >= 0xc0) && srp->header.twelve_byte) 
+	if ((opcode >= 0xc0) && old_hdr.twelve_byte)
             cmd_size = 12;
     }
-    SCSI_LOG_TIMEOUT(4, printk("sg_write:   scsi opcode=0x%02x, cmd_size=%d\n", 
+    SCSI_LOG_TIMEOUT(4, printk("sg_write:   scsi opcode=0x%02x, cmd_size=%d\n",
                                (int)opcode, cmd_size));
 /* Determine buffer size.  */
     input_size = count - cmd_size;
-    mxsize = (input_size > srp->header.reply_len) ? input_size :
-                                                    srp->header.reply_len;
+    mxsize = (input_size > old_hdr.reply_len) ? input_size :
+						old_hdr.reply_len;
     mxsize -= size_sg_header;
     input_size -= size_sg_header;
     if (input_size < 0) {
         sg_remove_request(sfp, srp);
         return -EIO; /* User did not pass enough bytes for this command. */
     }
-    if ((k = sg_start_req(srp, mxsize, buf + cmd_size, input_size))) {
-        SCSI_LOG_TIMEOUT(1, printk("sg_write: build err=%d\n", k));
-        sg_finish_rem_req(srp, NULL, 0);
+    hp = &srp->header;
+    hp->interface_id = '\0'; /* indicator of old interface tunnelled */
+    hp->cmd_len = (unsigned char)cmd_size;
+    hp->iovec_count = 0;
+    hp->mx_sb_len = 0;
+    if (input_size > 0)
+	hp->dxfer_direction = ((old_hdr.reply_len - size_sg_header) > 0) ?
+			      SG_DXFER_TO_FROM_DEV : SG_DXFER_TO_DEV;
+    else
+	hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV :
+					     SG_DXFER_NONE;
+    hp->dxfer_len = mxsize;
+    hp->dxferp = (unsigned char *)buf + cmd_size;
+    hp->sbp = NULL;
+    hp->timeout = old_hdr.reply_len;    /* structure abuse ... */
+    hp->flags = input_size;             /* structure abuse ... */
+    hp->pack_id = old_hdr.pack_id;
+    hp->usr_ptr = NULL;
+    __copy_from_user(cmnd, buf, cmd_size);
+    k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking);
+    return (k < 0) ? k : count;
+}
+
+static ssize_t sg_new_write(Sg_fd * sfp, const char * buf, size_t count,
+			    int blocking, int read_only, Sg_request ** o_srp)
+{
+    int                   k;
+    Sg_request          * srp;
+    sg_io_hdr_t         * hp;
+    unsigned char         cmnd[sizeof(dummy_cmdp->cmnd)];
+    int                   timeout;
+
+    if (count < size_sg_io_hdr)
+	return -EINVAL;
+    if ((k = verify_area(VERIFY_READ, buf, count)))
+	return k;  /* protects following copy_from_user()s + get_user()s */
+
+    sfp->cmd_q = 1;  /* when sg_io_hdr seen, set command queuing on */
+    if (! (srp = sg_add_request(sfp))) {
+	SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n"));
+	return -EDOM;
+    }
+    hp = &srp->header;
+    __copy_from_user(hp, buf, size_sg_io_hdr);
+    if (hp->interface_id != 'S') {
+	sg_remove_request(sfp, srp);
+	return -ENOSYS;
+    }
+    timeout = sg_ms_to_jif(srp->header.timeout);
+    if ((! hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof(cmnd))) {
+	sg_remove_request(sfp, srp);
+	return -EMSGSIZE;
+    }
+    if ((k = verify_area(VERIFY_READ, hp->cmdp, hp->cmd_len))) {
+	sg_remove_request(sfp, srp);
+	return k;  /* protects following copy_from_user()s + get_user()s */
+    }
+    __copy_from_user(cmnd, hp->cmdp, hp->cmd_len);
+    if (read_only &&
+	(! sg_allow_access(cmnd[0], sfp->parentdp->device->type))) {
+	sg_remove_request(sfp, srp);
+	return -EACCES;
+    }
+    k = sg_common_write(sfp, srp, cmnd, timeout, blocking);
+    if (k < 0) return k;
+    if (o_srp) *o_srp = srp;
+    return count;
+}
+
+static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
+			   unsigned char * cmnd, int timeout, int blocking)
+{
+    int                   k;
+    Scsi_Cmnd           * SCpnt;
+    Sg_device           * sdp = sfp->parentdp;
+    sg_io_hdr_t         * hp = &srp->header;
+
+    srp->data.cmd_opcode = cmnd[0];  /* hold opcode of command */
+    hp->status = 0;
+    hp->masked_status = 0;
+    hp->msg_status = 0;
+    hp->info = 0;
+    hp->host_status = 0;
+    hp->driver_status = 0;
+    hp->resid = 0;
+    SCSI_LOG_TIMEOUT(4,
+	printk("sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",
+	       (int)cmnd[0], (int)hp->cmd_len));
+
+    if ((k = sg_start_req(srp))) {
+	SCSI_LOG_TIMEOUT(1, printk("sg_write: start_req err=%d\n", k));
+	sg_finish_rem_req(srp);
         return k;    /* probably out of space --> ENOMEM */
     }
+    if ((k = sg_write_xfer(srp))) {
+	SCSI_LOG_TIMEOUT(1, printk("sg_write: write_xfer, bad address\n"));
+	sg_finish_rem_req(srp);
+	return k;
+    }
 /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: allocating device\n")); */
-    if (! (SCpnt = scsi_allocate_device(sdp->device, 
-                                        !(filp->f_flags & O_NONBLOCK), 
-					TRUE))) {
-        sg_finish_rem_req(srp, NULL, 0);
-        if( signal_pending(current) )
-        {
-                return -EINTR;
-        }
-        return -EAGAIN;   /* No available command blocks at the moment */
+    SCpnt = scsi_allocate_device(sdp->device, blocking, TRUE);
+    if (! SCpnt) {
+	sg_finish_rem_req(srp);
+	return (signal_pending(current)) ? -EINTR : -EAGAIN;
+	/* No available command blocks, or, interrupted while waiting */
     }
 /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: device allocated\n")); */
     srp->my_cmdp = SCpnt;
     SCpnt->request.rq_dev = sdp->i_rdev;
     SCpnt->request.rq_status = RQ_ACTIVE;
     SCpnt->sense_buffer[0] = 0;
-    SCpnt->cmd_len = cmd_size;
-    __copy_from_user(cmnd, buf, cmd_size);
+    SCpnt->cmd_len = hp->cmd_len;
 /* Set the LUN field in the command structure, overriding user input  */
-    cmnd[1]= (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
+    if (! (hp->flags & SG_FLAG_LUN_INHIBIT))
+	cmnd[1] = (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
 
 /*  SCSI_LOG_TIMEOUT(7, printk("sg_write: do cmd\n")); */
-    SCpnt->use_sg = srp->data.use_sg;
+    SCpnt->use_sg = srp->data.k_use_sg;
     SCpnt->sglist_len = srp->data.sglist_len;
     SCpnt->bufflen = srp->data.bufflen;
-    if (1 == sfp->underrun_flag)
-        SCpnt->underflow = srp->data.bufflen;
-    else
-        SCpnt->underflow = 0;
+    SCpnt->underflow = 0;
     SCpnt->buffer = srp->data.buffer;
-    srp->data.use_sg = 0;
+    srp->data.k_use_sg = 0;
     srp->data.sglist_len = 0;
     srp->data.bufflen = 0;
     srp->data.buffer = NULL;
+    hp->duration = jiffies;
 /* Now send everything of to mid-level. The next time we hear about this
-   packet is when sg_command_done() is called (ie a callback). */
+   packet is when sg_cmd_done_bh() is called (i.e. a callback). */
     scsi_do_cmd(SCpnt, (void *)cmnd,
-                (void *)SCpnt->buffer, mxsize,
-                sg_command_done, sfp->timeout, SG_DEFAULT_RETRIES);
-    /* 'mxsize' overwrites SCpnt->bufflen, hence need for b_malloc_len */
-/*  SCSI_LOG_TIMEOUT(6, printk("sg_write: sent scsi cmd to mid-level\n")); */
-    return count;
+		(void *)SCpnt->buffer, hp->dxfer_len,
+		sg_cmd_done_bh, timeout, SG_DEFAULT_RETRIES);
+    /* dxfer_len overwrites SCpnt->bufflen, hence need for b_malloc_len */
+    return 0;
 }
 
 static int sg_ioctl(struct inode * inode, struct file * filp,
                     unsigned int cmd_in, unsigned long arg)
 {
-    int result, val;
+    int result, val, read_only;
     Sg_device * sdp;
     Sg_fd * sfp;
     Sg_request * srp;
 
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
-    SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n", 
+    SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n",
                                MINOR(sdp->i_rdev), (int)cmd_in));
     if(! scsi_block_when_processing_errors(sdp->device) )
         return -ENXIO;
+    read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
 
     switch(cmd_in)
     {
+    case SG_IO:
+	{
+	    int blocking = 1;   /* ignore O_NONBLOCK flag */
+
+	    if(! scsi_block_when_processing_errors(sdp->device) )
+		return -ENXIO;
+	    result = verify_area(VERIFY_WRITE, (void *)arg, size_sg_io_hdr);
+	    if (result) return result;
+	    result = sg_new_write(sfp, (const char *)arg, size_sg_io_hdr,
+				  blocking, read_only, &srp);
+	    if (result < 0) return result;
+	    srp->sg_io_owned = 1;
+	    while (1) {
+		int dio = sg_dio_in_use(sfp);
+		result = 0;  /* following macro to beat race condition */
+		__wait_event_interruptible(sfp->read_wait,
+				   (sfp->closed || srp->done), result);
+		if (sfp->closed)
+		    return 0;       /* request packet dropped already */
+		if (0 == result)
+		    break;
+		else if (! dio) {       /* only let signal out if no dio */
+		    srp->orphan = 1;
+		    return result; /* -ERESTARTSYS because signal hit process */
+		}
+	    }
+	    result = sg_new_read(sfp, (char *)arg, size_sg_io_hdr, srp);
+	    return (result < 0) ? result : 0;
+	}
     case SG_SET_TIMEOUT:
         result =  get_user(val, (int *)arg);
         if (result) return result;
@@ -525,21 +747,21 @@
     case SG_GET_LOW_DMA:
         return put_user((int)sfp->low_dma, (int *)arg);
     case SG_GET_SCSI_ID:
-        result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(Sg_scsi_id));
+	result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(sg_scsi_id_t));
         if (result) return result;
         else {
-            Sg_scsi_id * sg_idp = (Sg_scsi_id *)arg;
+	    sg_scsi_id_t * sg_idp = (sg_scsi_id_t *)arg;
             __put_user((int)sdp->device->host->host_no, &sg_idp->host_no);
             __put_user((int)sdp->device->channel, &sg_idp->channel);
             __put_user((int)sdp->device->id, &sg_idp->scsi_id);
             __put_user((int)sdp->device->lun, &sg_idp->lun);
             __put_user((int)sdp->device->type, &sg_idp->scsi_type);
-            __put_user((short)sdp->device->host->cmd_per_lun, 
+	    __put_user((short)sdp->device->host->cmd_per_lun,
                        &sg_idp->h_cmd_per_lun);
-            __put_user((short)sdp->device->queue_depth, 
+	    __put_user((short)sdp->device->queue_depth,
                        &sg_idp->d_queue_depth);
-            __put_user(0, &sg_idp->unused1);
-            __put_user(0, &sg_idp->unused2);
+	    __put_user(0, &sg_idp->unused[0]);
+	    __put_user(0, &sg_idp->unused[1]);
             return 0;
         }
     case SG_SET_FORCE_PACK_ID:
@@ -552,7 +774,7 @@
         if (result) return result;
         srp = sfp->headrp;
         while (srp) {
-            if (! srp->my_cmdp) {
+	    if (srp->done && (! srp->sg_io_owned)) {
                 __put_user(srp->header.pack_id, (int *)arg);
                 return 0;
             }
@@ -564,7 +786,7 @@
         srp = sfp->headrp;
         val = 0;
         while (srp) {
-            if (! srp->my_cmdp)
+	    if (srp->done && (! srp->sg_io_owned))
                 ++val;
             srp = srp->nextrp;
         }
@@ -572,8 +794,6 @@
     case SG_GET_SG_TABLESIZE:
         return put_user(sdp->sg_tablesize, (int *)arg);
     case SG_SET_RESERVED_SIZE:
-        if (O_RDWR != (filp->f_flags & O_ACCMODE))
-            return -EACCES;
         result = get_user(val, (int *)arg);
         if (result) return result;
         if (val != sfp->reserve.bufflen) {
@@ -586,20 +806,6 @@
     case SG_GET_RESERVED_SIZE:
         val = (int)sfp->reserve.bufflen;
         return put_user(val, (int *)arg);
-    case SG_GET_MERGE_FD:
-        return put_user((int)sdp->merge_fd, (int *)arg);
-    case SG_SET_MERGE_FD:
-        if (O_RDWR != (filp->f_flags & O_ACCMODE))
-            return -EACCES; /* require write access since effect wider
-                               then just this fd */
-        result = get_user(val, (int *)arg);
-        if (result) return result;
-        val = val ? 1 : 0;
-        if ((val ^ (0 != sdp->merge_fd)) && 
-            sdp->headfp && sdp->headfp->nextfp)
-            return -EBUSY;   /* too much work if multiple fds already */
-        sdp->merge_fd = val;
-        return 0;
     case SG_SET_COMMAND_Q:
         result = get_user(val, (int *)arg);
         if (result) return result;
@@ -607,13 +813,13 @@
         return 0;
     case SG_GET_COMMAND_Q:
         return put_user((int)sfp->cmd_q, (int *)arg);
-    case SG_SET_UNDERRUN_FLAG:
+    case SG_SET_KEEP_ORPHAN:
         result = get_user(val, (int *)arg);
         if (result) return result;
-        sfp->underrun_flag = val;
+	sfp->keep_orphan = val;
         return 0;
-    case SG_GET_UNDERRUN_FLAG:
-        return put_user((int)sfp->underrun_flag, (int *)arg);
+    case SG_GET_KEEP_ORPHAN:
+	return put_user((int)sfp->keep_orphan, (int *)arg);
     case SG_NEXT_CMD_LEN:
         result = get_user(val, (int *)arg);
         if (result) return result;
@@ -621,6 +827,32 @@
         return 0;
     case SG_GET_VERSION_NUM:
         return put_user(sg_version_num, (int *)arg);
+    case SG_GET_REQUEST_TABLE:
+	result = verify_area(VERIFY_WRITE, (void *) arg,
+			     size_sg_req_info * SG_MAX_QUEUE);
+	if (result) return result;
+	else {
+	    sg_req_info_t rinfo[SG_MAX_QUEUE];
+	    Sg_request * srp = sfp->headrp;
+	    for (val = 0; val < SG_MAX_QUEUE;
+		 ++val, srp = srp ? srp->nextrp : srp) {
+		memset(&rinfo[val], 0, size_sg_req_info);
+		if (srp) {
+		    rinfo[val].req_state = srp->done ? 2 : 1;
+		    rinfo[val].problem = srp->header.masked_status &
+			srp->header.host_status & srp->header.driver_status;
+		    rinfo[val].duration = srp->done ?
+			    sg_jif_to_ms(srp->header.duration) :
+			    sg_jif_to_ms(jiffies - srp->header.duration);
+		    rinfo[val].orphan = srp->orphan;
+		    rinfo[val].sg_io_owned = srp->sg_io_owned;
+		    rinfo[val].pack_id = srp->header.pack_id;
+		    rinfo[val].usr_ptr = srp->header.usr_ptr;
+		}
+	    }
+	    __copy_to_user((void *)arg, rinfo, size_sg_req_info * SG_MAX_QUEUE);
+	    return 0;
+	}
     case SG_EMULATED_HOST:
         return put_user(sdp->device->host->hostt->emulated, (int *)arg);
     case SG_SCSI_RESET:
@@ -628,23 +860,22 @@
             return -EBUSY;
         result = get_user(val, (int *)arg);
         if (result) return result;
-        /* Don't do anything till scsi mod level visibility */
+	/* Don't do anything till scsi mid level visibility */
         return 0;
     case SCSI_IOCTL_SEND_COMMAND:
-        /* Allow SCSI_IOCTL_SEND_COMMAND without checking suser() since the
-           user already has read/write access to the generic device and so
-           can execute arbitrary SCSI commands.  */
-        if (O_RDWR != (filp->f_flags & O_ACCMODE))
-            return -EACCES; /* very dangerous things can be done here */
+	if (read_only) {
+	    unsigned char opcode = WRITE_6;
+	    Scsi_Ioctl_Command * siocp = (void *)arg;
+
+	    copy_from_user(&opcode, siocp->data, 1);
+	    if (! sg_allow_access(opcode, sdp->device->type))
+		return -EACCES;
+	}
         return scsi_ioctl_send_command(sdp->device, (void *)arg);
     case SG_SET_DEBUG:
         result = get_user(val, (int *)arg);
         if (result) return result;
         sdp->sgdebug = (char)val;
-        if (9 == sdp->sgdebug)
-            sg_debug(sdp, sfp, 0);
-        else if (sdp->sgdebug > 9)
-            sg_debug_all(sfp);
         return 0;
     case SCSI_IOCTL_GET_IDLUN:
     case SCSI_IOCTL_GET_BUS_NUMBER:
@@ -652,7 +883,7 @@
     case SG_GET_TRANSFORM:
         return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
     default:
-        if (O_RDWR != (filp->f_flags & O_ACCMODE))
+	if (read_only)
             return -EACCES; /* don't know so take safe approach */
         return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
     }
@@ -671,18 +902,18 @@
     poll_wait(filp, &sfp->read_wait, wait);
     srp = sfp->headrp;
     while (srp) {   /* if any read waiting, flag it */
-        if (! (res || srp->my_cmdp))
+	if ((0 == res) && srp->done && (! srp->sg_io_owned))
             res = POLLIN | POLLRDNORM;
         ++count;
         srp = srp->nextrp;
     }
-    if (0 == sfp->cmd_q) {
+    if (! sfp->cmd_q) {
         if (0 == count)
             res |= POLLOUT | POLLWRNORM;
     }
     else if (count < SG_MAX_QUEUE)
         res |= POLLOUT | POLLWRNORM;
-    SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n", 
+    SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n",
                         MINOR(sdp->i_rdev), (int)res));
     return res;
 }
@@ -695,36 +926,29 @@
 
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))
         return -ENXIO;
-    SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n", 
+    SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n",
                                MINOR(sdp->i_rdev), mode));
 
     retval = fasync_helper(fd, filp, mode, &sfp->async_qp);
     return (retval < 0) ? retval : 0;
 }
 
-/* This function is called by the interrupt handler when we
- * actually have a command that is complete. */
-static void sg_command_done(Scsi_Cmnd * SCpnt)
+/* This function is a "bottom half" handler that is called by the
+ * mid level when a command is completed (or has failed). */
+static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt)
 {
     int dev = MINOR(SCpnt->request.rq_dev);
     Sg_device * sdp;
     Sg_fd * sfp;
     Sg_request * srp = NULL;
-    int closed = 0;
-    static const int min_sb_len = 
-                SG_MAX_SENSE > sizeof(SCpnt->sense_buffer) ? 
-                        sizeof(SCpnt->sense_buffer) : SG_MAX_SENSE;
 
-    if ((NULL == sg_dev_arr) || (dev < 0) || (dev >= sg_template.dev_max)) {
-        SCSI_LOG_TIMEOUT(1, printk("sg__done: bad args dev=%d\n", dev));
+    if ((NULL == sg_dev_arr) || (dev < 0) || (dev >= sg_template.dev_max)
+	|| (NULL == (sdp = &sg_dev_arr[dev]))) {
+	SCSI_LOG_TIMEOUT(1, printk("sg...bh: bad args dev=%d\n", dev));
         scsi_release_command(SCpnt);
         SCpnt = NULL;
         return;
     }
-    sdp = &sg_dev_arr[dev];
-    if (NULL == sdp->device)
-        return; /* Get out of here quick ... */
-
     sfp = sdp->headfp;
     while (sfp) {
         srp = sfp->headrp;
@@ -738,215 +962,88 @@
         sfp = sfp->nextfp;
     }
     if (! srp) {
-        SCSI_LOG_TIMEOUT(1, printk("sg__done: req missing, dev=%d\n", dev));
+	SCSI_LOG_TIMEOUT(1, printk("sg...bh: req missing, dev=%d\n", dev));
         scsi_release_command(SCpnt);
         SCpnt = NULL;
         return;
     }
-/* First transfer ownership of data buffers to sg_device object. */
-    srp->data.use_sg = SCpnt->use_sg;
+    /* First transfer ownership of data buffers to sg_device object. */
+    srp->data.k_use_sg = SCpnt->use_sg;
     srp->data.sglist_len = SCpnt->sglist_len;
     srp->data.bufflen = SCpnt->bufflen;
     srp->data.buffer = SCpnt->buffer;
-    if (2 == sfp->underrun_flag)
-        srp->header.pack_len = SCpnt->underflow;
     sg_clr_scpnt(SCpnt);
     srp->my_cmdp = NULL;
+    srp->done = 1;
 
-    SCSI_LOG_TIMEOUT(4, printk("sg__done: dev=%d, scsi_stat=%d, res=0x%x\n", 
-                dev, (int)status_byte(SCpnt->result), (int)SCpnt->result));
-    memcpy(srp->header.sense_buffer, SCpnt->sense_buffer, min_sb_len);
-    switch (host_byte(SCpnt->result)) 
-    { /* This setup of 'result' is for backward compatibility and is best
-         ignored by the user who should use target, host + driver status */
-    case DID_OK:
-    case DID_PASSTHROUGH: 
-    case DID_SOFT_ERROR:
-      srp->header.result = 0;
-      break;
-    case DID_NO_CONNECT:
-    case DID_BUS_BUSY:
-    case DID_TIME_OUT:
-      srp->header.result = EBUSY;
-      break;
-    case DID_BAD_TARGET:
-    case DID_ABORT:
-    case DID_PARITY:
-    case DID_RESET:
-    case DID_BAD_INTR:
-      srp->header.result = EIO;
-      break;
-    case DID_ERROR:
-      if (SCpnt->sense_buffer[0] == 0 &&
-          status_byte(SCpnt->result) == GOOD)
-          srp->header.result = 0;
-      else 
-          srp->header.result = EIO;
-      break;
-    default:
-      SCSI_LOG_TIMEOUT(1, printk(
-                "sg: unexpected host_byte=%d, dev=%d in 'done'\n", 
-                host_byte(SCpnt->result), dev));
-      srp->header.result = EIO;
-      break;
-    }
-
-/* Following if statement is a patch supplied by Eric Youngdale */
-    if (driver_byte(SCpnt->result) != 0
-        && (SCpnt->sense_buffer[0] & 0x7f) == 0x70
-        && (SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION
-        && sdp->device->removable) {
-/* Detected disc change. Set the bit - this may be used if there are */
-/* filesystems using this device. */
-        sdp->device->changed = 1;
-    }
-    srp->header.target_status = status_byte(SCpnt->result);
-    if ((sdp->sgdebug > 0) && 
-        ((CHECK_CONDITION == srp->header.target_status) ||
-         (COMMAND_TERMINATED == srp->header.target_status)))
-        print_sense("sg_command_done", SCpnt);
-    srp->header.host_status = host_byte(SCpnt->result);
-    srp->header.driver_status = driver_byte(SCpnt->result);
+    SCSI_LOG_TIMEOUT(4, printk("sg...bh: dev=%d, pack_id=%d, res=0x%x\n",
+		     dev, srp->header.pack_id, (int)SCpnt->result));
+    srp->header.resid = SCpnt->resid;
+    /* sg_unmap_and(&srp->data, 0); */     /* unmap locked pages a.s.a.p. */
+    srp->header.duration = sg_jif_to_ms(jiffies - (int)srp->header.duration);
+    if (0 != SCpnt->result) {
+	memcpy(srp->sense_b, SCpnt->sense_buffer, sizeof(srp->sense_b));
+	srp->header.status = 0xff & SCpnt->result;
+	srp->header.masked_status  = status_byte(SCpnt->result);
+	srp->header.msg_status  = msg_byte(SCpnt->result);
+	srp->header.host_status = host_byte(SCpnt->result);
+	srp->header.driver_status = driver_byte(SCpnt->result);
+	if ((sdp->sgdebug > 0) &&
+	    ((CHECK_CONDITION == srp->header.masked_status) ||
+	     (COMMAND_TERMINATED == srp->header.masked_status)))
+	    print_sense("sg_cmd_done_bh", SCpnt);
+
+	/* Following if statement is a patch supplied by Eric Youngdale */
+	if (driver_byte(SCpnt->result) != 0
+	    && (SCpnt->sense_buffer[0] & 0x7f) == 0x70
+	    && (SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION
+	    && sdp->device->removable) {
+	    /* Detected disc change. Set the bit - this may be used if */
+	    /* there are filesystems using this device. */
+	    sdp->device->changed = 1;
+	}
+    }
+    /* Rely on write phase to clean out srp status values, so no "else" */
 
     scsi_release_command(SCpnt);
     SCpnt = NULL;
     if (sfp->closed) { /* whoops this fd already released, cleanup */
-        closed = 1;
         SCSI_LOG_TIMEOUT(1,
-               printk("sg__done: already closed, freeing ...\n"));
-/* should check if module is unloaded <<<<<<< */
-        sg_finish_rem_req(srp, NULL, 0);
-        if (NULL == sfp->headrp) { 
+	       printk("sg...bh: already closed, freeing ...\n"));
+	/* should check if module is unloaded <<<<<<< */
+	sg_finish_rem_req(srp);
+	srp = NULL;
+	if (NULL == sfp->headrp) {
             SCSI_LOG_TIMEOUT(1,
-                printk("sg__done: already closed, final cleanup\n"));
+		printk("sg...bh: already closed, final cleanup\n"));
             sg_remove_sfp(sdp, sfp);
+	    sfp = NULL;
         }
     }
-/* Now wake up any sg_read() that is waiting for this packet. */
-    wake_up_interruptible(&sfp->read_wait);
-    if ((sfp->async_qp) && (! closed))
-        kill_fasync(sfp->async_qp, SIGPOLL, POLL_IN);
-}
-
-static void sg_debug_all(const Sg_fd * sfp)
-{
-    const Sg_device * sdp = sg_dev_arr;
-    int k;
-   
-    if (NULL == sg_dev_arr) {
-        printk("sg_debug_all: sg_dev_arr NULL, death is imminent\n"); 
-        return;
-    }
-    if (! sfp)
-        printk("sg_debug_all: sfp (file descriptor pointer) NULL\n"); 
-    
-    printk("sg_debug_all: dev_max=%d, %s\n", 
-           sg_template.dev_max, sg_version_str);
-    printk(" scsi_dma_free_sectors=%u, sg_pool_secs_aval=%d\n",
-           scsi_dma_free_sectors, sg_pool_secs_avail);
-    printk(" sg_big_buff=%d\n", sg_big_buff);
-#ifdef SG_DEBUG
-    printk(" malloc counts, kmallocs=%d, dma_pool=%d, pages=%d\n",
-           sg_num_kmal, sg_num_pool, sg_num_page);
-#endif
-    for (k = 0; k < sg_template.dev_max; ++k, ++sdp) {
-        if (sdp->headfp) {
-            if (! sfp)
-                sfp = sdp->headfp;      /* just to keep things going */
-            else if (sdp == sfp->parentdp)
-        printk("  ***** Invoking device follows *****\n");
-            sg_debug(sdp, sfp, 1);
-        }
-    }
-}
-
-static void sg_debug(const Sg_device * sdp, const Sg_fd * sfp, int part_of)
-{
-    Sg_fd * fp;
-    Sg_request * srp;
-    int dev;
-    int k;
-   
-    if (! sfp)
-        printk("sg_debug: sfp (file descriptor pointer) NULL\n"); 
-    if (! sdp) {
-        printk("sg_debug: sdp pointer (to device) NULL\n"); 
-        return;
-    }
-    else if (! sdp->device) {
-        printk("sg_debug: device detached ??\n"); 
-        return;
-    }
-    dev = MINOR(sdp->i_rdev);
-
-    if (part_of)
-        printk(" >>> device=%d(sg%c), ", dev, 'a' + dev);
-    else
-        printk("sg_debug: device=%d(sg%c), ", dev, 'a' + dev);
-    printk("scsi%d chan=%d id=%d lun=%d  em=%d\n", sdp->device->host->host_no,
-           sdp->device->channel, sdp->device->id, sdp->device->lun,
-           sdp->device->host->hostt->emulated);
-    printk(" sg_tablesize=%d, excl=%d, sgdebug=%d, merge_fd=%d\n",
-           sdp->sg_tablesize, sdp->exclude, sdp->sgdebug, sdp->merge_fd);
-    if (! part_of) {
-        printk(" scsi_dma_free_sectors=%u, sg_pool_secs_aval=%d\n",
-               scsi_dma_free_sectors, sg_pool_secs_avail);
-#ifdef SG_DEBUG
-        printk(" mallocs: kmallocs=%d, dma_pool=%d, pages=%d\n",
-               sg_num_kmal, sg_num_pool, sg_num_page);
-#endif
-    }
-
-    fp = sdp->headfp;
-    for (k = 1; fp; fp = fp->nextfp, ++k) {
-        if (sfp == fp)
-            printk("  *** Following data belongs to invoking FD ***\n");
-        else if (! fp->parentdp)
-            printk(">> Following FD has NULL parent pointer ???\n");
-        printk("   FD(%d): timeout=%d, bufflen=%d, use_sg=%d\n",
-               k, fp->timeout, fp->reserve.bufflen, (int)fp->reserve.use_sg);
-        printk("   low_dma=%d, cmd_q=%d, s_sc_len=%d, f_packid=%d\n",
-               (int)fp->low_dma, (int)fp->cmd_q, (int)fp->save_scat_len,
-               (int)fp->force_packid);
-        printk("   urun_flag=%d, next_cmd_len=%d, closed=%d\n",
-               (int)fp->underrun_flag, (int)fp->next_cmd_len, 
-               (int)fp->closed);
-        srp = fp->headrp;
-        if (NULL == srp)
-            printk("     No requests active\n");
-        while (srp) {
-            if (srp->res_used)
-                printk("reserved buff >> ");
-            else
-                printk("     ");
-            if (srp->my_cmdp)
-                printk("written: pack_id=%d, bufflen=%d, use_sg=%d\n",
-                       srp->header.pack_id, srp->my_cmdp->bufflen, 
-                       srp->my_cmdp->use_sg);
-            else
-                printk("to_read: pack_id=%d, bufflen=%d, use_sg=%d\n",
-                   srp->header.pack_id, srp->data.bufflen, srp->data.use_sg);
-            if (! srp->parentfp)
-                printk(">> request has NULL parent pointer ???\n");
-            srp = srp->nextrp;
-        }
+    else if (srp && srp->orphan) {
+	if (sfp->keep_orphan)
+	    srp->sg_io_owned = 0;
+	else {
+	    sg_finish_rem_req(srp);
+	    srp = NULL;
+        }
+    }
+    if (sfp && srp) {
+	/* Now wake up any sg_read() that is waiting for this packet. */
+	wake_up_interruptible(&sfp->read_wait);
+	if (sfp->async_qp)
+	    kill_fasync(sfp->async_qp, SIGPOLL, POLL_IN);
     }
 }
 
 static struct file_operations sg_fops = {
-    NULL,            /* lseek */
-    sg_read,         /* read */
-    sg_write,        /* write */
-    NULL,            /* readdir */
-    sg_poll,         /* poll */
-    sg_ioctl,        /* ioctl */
-    NULL,            /* mmap */
-    sg_open,         /* open */
-    NULL,            /* flush */
-    sg_release,      /* release, was formerly sg_close */
-    NULL,            /* fsync */
-    sg_fasync,       /* fasync */
-    NULL,            /* lock */
+	 read:		sg_read,
+	 write:		sg_write,
+	 poll:		sg_poll,
+	 ioctl:		sg_ioctl,
+	 open:		sg_open,
+	 release:	sg_release,
+	 fasync:	sg_fasync,
 };
 
 
@@ -962,7 +1059,7 @@
         printk("Detected scsi generic sg%c at scsi%d,"
                 " channel %d, id %d, lun %d\n",
                'a'+sg_template.dev_noticed,
-               scsidp->host->host_no, scsidp->channel, 
+	       scsidp->host->host_no, scsidp->channel,
                scsidp->id, scsidp->lun);
     }
     sg_template.dev_noticed++;
@@ -973,6 +1070,7 @@
 static int sg_init()
 {
     static int sg_registered = 0;
+    int size;
 
     if (sg_template.dev_noticed == 0) return 0;
 
@@ -990,19 +1088,42 @@
     if(sg_dev_arr) return 0;
 
     SCSI_LOG_TIMEOUT(3, printk("sg_init\n"));
-    sg_dev_arr = (Sg_device *)
-	kmalloc((sg_template.dev_noticed + SG_EXTRA_DEVS)
-		* sizeof(Sg_device), GFP_ATOMIC);
-    memset(sg_dev_arr, 0, (sg_template.dev_noticed + SG_EXTRA_DEVS)
-		* sizeof(Sg_device));
+    size = sizeof(Sg_device) *
+	   (sg_template.dev_noticed + SG_EXTRA_DEVS);
+    sg_dev_arr = (Sg_device *)kmalloc(size, GFP_ATOMIC);
+    memset(sg_dev_arr, 0, size);
     if (NULL == sg_dev_arr) {
         printk("sg_init: no space for sg_dev_arr\n");
         return 1;
     }
+#ifdef CONFIG_PROC_FS
+    sg_proc_init();
+#endif  /* CONFIG_PROC_FS */
     sg_template.dev_max = sg_template.dev_noticed + SG_EXTRA_DEVS;
     return 0;
 }
 
+#ifndef MODULE
+static int __init sg_def_reserved_size_setup(char *str)
+{
+    int tmp;
+
+    if (get_option(&str, &tmp) == 1) {
+	def_reserved_size = tmp;
+	if (tmp >= 0)
+	    sg_big_buff = tmp;
+	return 1;
+    } else {
+	printk("sg_def_reserved_size : usage sg_def_reserved_size=n "
+	       "(n could be 65536, 131072 or 262144)\n");
+	return 0;
+    }
+}
+
+__setup("sg_def_reserved_size=", sg_def_reserved_size_setup);
+#endif
+
+
 static int sg_attach(Scsi_Device * scsidp)
 {
     Sg_device * sdp = sg_dev_arr;
@@ -1011,6 +1132,8 @@
     if ((sg_template.nr_dev >= sg_template.dev_max) || (! sdp))
     {
         scsidp->attached--;
+	printk("sg_attach: rejected since exceeds dev_max=%d\n",
+	       sg_template.dev_max);
         return 1;
     }
 
@@ -1024,7 +1147,6 @@
     init_waitqueue_head(&sdp->o_excl_wait);
     sdp->headfp= NULL;
     sdp->exclude = 0;
-    sdp->merge_fd = 0;  /* Cope with SG_DEF_MERGE_FD on open */
     sdp->sgdebug = 0;
     sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
     sdp->i_rdev = MKDEV(SCSI_GENERIC_MAJOR, k);
@@ -1052,13 +1174,13 @@
         if(sdp->device != scsidp)
             continue;   /* dirty but lowers nesting */
         if (sdp->headfp) {
-/* Need to stop sg_command_done() playing with this list during this loop */
+/* Need to stop sg_cmd_done_bh() playing with this list during this loop */
             spin_lock_irqsave(&sg_request_lock, flags);
             sfp = sdp->headfp;
             while (sfp) {
                 srp = sfp->headrp;
                 while (srp) {
-                    if (srp->my_cmdp)
+		    if (! srp->done)
                         sg_shorten_timeout(srp->my_cmdp);
                     srp = srp->nextrp;
                 }
@@ -1070,7 +1192,7 @@
         }
         else {
             SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k));
-            sdp->device = NULL; 
+	    sdp->device = NULL;
         }
         scsidp->attached--;
         sg_template.nr_dev--;
@@ -1084,7 +1206,12 @@
 
 #ifdef MODULE
 
+MODULE_PARM(def_reserved_size, "i");
+MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
+
 int init_module(void) {
+    if (def_reserved_size >= 0)
+	sg_big_buff = def_reserved_size;
     sg_template.module = &__this_module;
     return scsi_register_module(MODULE_SCSI_DEV, &sg_template);
 }
@@ -1094,10 +1221,13 @@
     scsi_unregister_module(MODULE_SCSI_DEV, &sg_template);
     unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
 
+#ifdef CONFIG_PROC_FS
+    sg_proc_cleanup();
+#endif  /* CONFIG_PROC_FS */
     if(sg_dev_arr != NULL) {
 /* Really worrying situation of writes still pending and get here */
 /* Strategy: shorten timeout on release + wait on detach ... */
-	kfree((char *) sg_dev_arr);
+	kfree((char *)sg_dev_arr);
         sg_dev_arr = NULL;
     }
     sg_template.dev_max = 0;
@@ -1124,56 +1254,178 @@
         scsi_add_timer(scpnt, scpnt->timeout_per_command,
                        scsi_old_times_out);
 #else
-    spin_unlock_irq(&sg_request_lock);
+    unsigned long flags = 0;
+    spin_lock_irqsave(&sg_request_lock, flags);
     scsi_sleep(HZ); /* just sleep 1 second and hope ... */
-    spin_lock_irq(&sg_request_lock);
+    spin_unlock_irqrestore(&sg_request_lock, flags);
 #endif
 }
 
-static int sg_start_req(Sg_request * srp, int max_buff_size,
-                        const char * inp, int num_write_xfer)
+static int sg_start_req(Sg_request * srp)
 {
     int res;
     Sg_fd * sfp = srp->parentfp;
+    sg_io_hdr_t * hp = &srp->header;
+    int dxfer_len = (int)hp->dxfer_len;
     Sg_scatter_hold * req_schp = &srp->data;
     Sg_scatter_hold * rsv_schp = &sfp->reserve;
 
-    SCSI_LOG_TIMEOUT(4, printk("sg_start_req: max_buff_size=%d\n", 
-                               max_buff_size)); 
-    if ((! sg_res_in_use(sfp)) && (max_buff_size <= rsv_schp->bufflen)) {
-        sg_link_reserve(sfp, srp, max_buff_size);
-        sg_write_xfer(req_schp, inp, num_write_xfer);
+    SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len));
+    if ((hp->flags & SG_FLAG_DIRECT_IO) && (dxfer_len > 0) &&
+	(hp->dxfer_direction != SG_DXFER_NONE) && (0 == hp->iovec_count) &&
+	(! sfp->parentdp->device->host->unchecked_isa_dma)) {
+	res = sg_build_dir(srp, sfp, dxfer_len);
+	if (res <= 0)   /* -ve -> error, 0 -> done, 1 -> try indirect */
+	    return res;
+    }
+    if ((! sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) {
+	sg_link_reserve(sfp, srp, dxfer_len);
     }
     else {
-        res = sg_build_scat(req_schp, max_buff_size, sfp);
+	res = sg_build_indi(req_schp, sfp, dxfer_len);
         if (res) {
             sg_remove_scat(req_schp);
             return res;
         }
-        sg_write_xfer(req_schp, inp, num_write_xfer);
     }
     return 0;
 }
 
-static void sg_finish_rem_req(Sg_request * srp, char * outp, 
-                              int num_read_xfer)
+static void sg_finish_rem_req(Sg_request * srp)
 {
     Sg_fd * sfp = srp->parentfp;
     Sg_scatter_hold * req_schp = &srp->data;
 
     SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n",
-                               (int)srp->res_used)); 
-    if (num_read_xfer > 0)
-        sg_read_xfer(req_schp, outp, num_read_xfer);
+			       (int)srp->res_used));
+    sg_unmap_and(&srp->data, 1);
     if (srp->res_used)
         sg_unlink_reserve(sfp, srp);
-    else 
+    else
         sg_remove_scat(req_schp);
     sg_remove_request(sfp, srp);
 }
 
-static int sg_build_scat(Sg_scatter_hold * schp, int buff_size, 
-                         const Sg_fd * sfp)
+static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp)
+{
+    int mem_src, ret_sz;
+    int sg_bufflen = PAGE_SIZE;
+    int elem_sz = sizeof(struct scatterlist) + sizeof(char);
+    int mx_sc_elems = (sg_bufflen / elem_sz) - 1;
+
+    mem_src = SG_HEAP_KMAL;
+    schp->buffer = (struct scatterlist *)sg_malloc(sfp, sg_bufflen,
+						   &ret_sz, &mem_src);
+    schp->buffer_mem_src = (char)mem_src;
+    if (! schp->buffer)
+	return -ENOMEM;
+    else if (ret_sz != sg_bufflen) {
+	sg_bufflen = ret_sz;
+	mx_sc_elems = (sg_bufflen / elem_sz) - 1;
+    }
+    schp->sglist_len = sg_bufflen;
+    memset(schp->buffer, 0, sg_bufflen);
+    return mx_sc_elems; /* number of scat_gath elements allocated */
+}
+
+static void sg_unmap_and(Sg_scatter_hold * schp, int free_also)
+{
+#ifdef SG_ALLOW_DIO
+    if (schp && schp->kiobp) {
+	if (schp->mapped) {
+	    unmap_kiobuf(schp->kiobp);
+	    schp->mapped = 0;
+	}
+	if (free_also) {
+	    free_kiovec(1, &schp->kiobp);
+	    schp->kiobp = NULL;
+	}
+    }
+#endif
+}
+
+static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
+{
+#ifdef SG_ALLOW_DIO
+    int res, k, split, offset, num, mx_sc_elems, rem_sz;
+    struct kiobuf * kp;
+    char * mem_src_arr;
+    struct scatterlist * sclp;
+    unsigned long addr, prev_addr;
+    sg_io_hdr_t * hp = &srp->header;
+    Sg_scatter_hold * schp = &srp->data;
+    int sg_tablesize = sfp->parentdp->sg_tablesize;
+
+    res = alloc_kiovec(1, &schp->kiobp);
+    if (0 != res) {
+	SCSI_LOG_TIMEOUT(5, printk("sg_build_dir: alloc_kiovec res=%d\n", res));
+	return 1;
+    }
+    res = map_user_kiobuf((SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0,
+			  schp->kiobp, (unsigned long)hp->dxferp, dxfer_len);
+    if (0 != res) {
+	SCSI_LOG_TIMEOUT(5,
+		printk("sg_build_dir: map_user_kiobuf res=%d\n", res));
+	sg_unmap_and(schp, 1);
+	return 1;
+    }
+    schp->mapped = 1;
+    kp = schp->kiobp;
+    prev_addr = page_address(kp->maplist[0]);
+    for (k = 1, split = 0; k < kp->nr_pages; ++k, prev_addr = addr) {
+	addr = page_address(kp->maplist[k]);
+	if ((prev_addr + PAGE_SIZE) != addr) {
+	    split = k;
+	    break;
+	}
+    }
+    if (! split) {
+	schp->k_use_sg = 0;
+	schp->buffer = (void *)(page_address(kp->maplist[0]) + kp->offset);
+	schp->bufflen = dxfer_len;
+	schp->buffer_mem_src = SG_USER_MEM;
+	schp->b_malloc_len = dxfer_len;
+	hp->info |= SG_INFO_DIRECT_IO;
+	return 0;
+    }
+    mx_sc_elems = sg_build_sgat(schp, sfp);
+    if (mx_sc_elems <= 1) {
+	sg_unmap_and(schp, 1);
+	sg_remove_scat(schp);
+	return 1;
+    }
+    mem_src_arr = schp->buffer + (mx_sc_elems * sizeof(struct scatterlist));
+    for (k = 0, sclp = schp->buffer, rem_sz = dxfer_len;
+	 (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems);
+	 ++k, ++sclp) {
+	offset = (0 == k) ? kp->offset : 0;
+	num = (rem_sz > (PAGE_SIZE - offset)) ? (PAGE_SIZE - offset) :
+						rem_sz;
+	sclp->address = (void *)(page_address(kp->maplist[k]) + offset);
+	sclp->length = num;
+	mem_src_arr[k] = SG_USER_MEM;
+	rem_sz -= num;
+	SCSI_LOG_TIMEOUT(5,
+	    printk("sg_build_dir: k=%d, a=0x%p, len=%d, ms=%d\n",
+	    k, sclp->address, num, mem_src_arr[k]));
+    }
+    schp->k_use_sg = k;
+    SCSI_LOG_TIMEOUT(5,
+	printk("sg_build_dir: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
+    schp->bufflen = dxfer_len;
+    if (rem_sz > 0) {   /* must have failed */
+	sg_unmap_and(schp, 1);
+	sg_remove_scat(schp);
+	return 1;   /* out of scatter gather elements, try indirect */
+    }
+    hp->info |= SG_INFO_DIRECT_IO;
+    return 0;
+#else
+    return 1;
+#endif /* SG_ALLOW_DIO */
+}
+
+static int sg_build_indi(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
 {
     int ret_sz, mem_src;
     int blk_size = buff_size;
@@ -1185,7 +1437,7 @@
         ++blk_size;             /* don't know why */
 /* round request up to next highest SG_SECTOR_SZ byte boundary */
     blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
-    SCSI_LOG_TIMEOUT(4, printk("sg_build_scat: buff_size=%d, blk_size=%d\n",
+    SCSI_LOG_TIMEOUT(4, printk("sg_build_indi: buff_size=%d, blk_size=%d\n",
                                buff_size, blk_size));
     if (blk_size <= SG_SCATTER_SZ) {
         mem_src = SG_HEAP_PAGE;
@@ -1193,10 +1445,10 @@
         if (! p)
             return -ENOMEM;
         if (blk_size == ret_sz) { /* got it on the first attempt */
-            schp->use_sg = 0;
+	    schp->k_use_sg = 0;
             schp->buffer = p;
             schp->bufflen = blk_size;
-            schp->mem_src = mem_src;
+	    schp->buffer_mem_src = (char)mem_src;
             schp->b_malloc_len = blk_size;
             return 0;
         }
@@ -1210,29 +1462,23 @@
 /* Want some local declarations, so start new block ... */
     {   /* lets try and build a scatter gather list */
         struct scatterlist * sclp;
-        int k, rem_sz, num, nxt;
-        int sc_bufflen = PAGE_SIZE;
-        int mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
+	int k, rem_sz, num;
+	int mx_sc_elems;
         int sg_tablesize = sfp->parentdp->sg_tablesize;
         int first = 1;
+	char * mem_src_arr;
 
-        k = SG_HEAP_KMAL;  /* want to protect mem_src, use k as scratch */
-        schp->buffer = (struct scatterlist *)sg_malloc(sfp, 
-                                sc_bufflen, &num, &k);
-        schp->mem_src = (char)k;
         /* N.B. ret_sz and mem_src carried into this block ... */
-        if (! schp->buffer)
-            return -ENOMEM;
-        else if (num != sc_bufflen) {
-            sc_bufflen = num;
-            mx_sc_elems = (sc_bufflen / sizeof(struct scatterlist)) - 1;
-        }
-        schp->sglist_len = sc_bufflen;
-        memset(schp->buffer, 0, sc_bufflen);
-        for (k = 0, sclp = schp->buffer, rem_sz = blk_size, nxt =0; 
-             (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems); 
+	mx_sc_elems = sg_build_sgat(schp, sfp);
+	if (mx_sc_elems < 0)
+	    return mx_sc_elems; /* most likely -ENOMEM */
+	mem_src_arr = schp->buffer +
+		      (mx_sc_elems * sizeof(struct scatterlist));
+
+	for (k = 0, sclp = schp->buffer, rem_sz = blk_size;
+	     (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems);
              ++k, rem_sz -= ret_sz, ++sclp) {
-            if (first) 
+	    if (first)
                 first = 0;
             else {
                 num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
@@ -1243,15 +1489,15 @@
             }
             sclp->address = p;
             sclp->length = ret_sz;
-            sclp->alt_address = (char *)(long)mem_src;
-            
-            SCSI_LOG_TIMEOUT(5, 
-                printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n", 
+	    mem_src_arr[k] = mem_src;
+
+	    SCSI_LOG_TIMEOUT(5,
+		printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n",
                 k, sclp->address, ret_sz, mem_src));
         } /* end of for loop */
-        schp->use_sg = k;
-        SCSI_LOG_TIMEOUT(5, 
-            printk("sg_build_scat: use_sg=%d, rem_sz=%d\n", k, rem_sz));
+	schp->k_use_sg = k;
+	SCSI_LOG_TIMEOUT(5,
+	    printk("sg_build_indi: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
         schp->bufflen = blk_size;
         if (rem_sz > 0)   /* must have failed */
             return -ENOMEM;
@@ -1259,74 +1505,254 @@
     return 0;
 }
 
-static void sg_write_xfer(Sg_scatter_hold * schp, const char * inp, 
-                          int num_write_xfer)
+static int sg_write_xfer(Sg_request * srp)
 {
-    SCSI_LOG_TIMEOUT(4, printk("sg_write_xfer: num_write_xfer=%d, use_sg=%d\n", 
-                               num_write_xfer, schp->use_sg)); 
-    if ((! inp) || (num_write_xfer <= 0))
-        return;
-    if (schp->use_sg > 0) {
-        int k, num;
-        struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+    sg_io_hdr_t * hp = &srp->header;
+    Sg_scatter_hold * schp = &srp->data;
+    int num_xfer = 0;
+    int j, k, onum, usglen, ksglen, res, ok;
+    int iovec_count = (int)hp->iovec_count;
+    unsigned char * p;
+    unsigned char * up;
+    int new_interface = ('\0' == hp->interface_id) ? 0 : 1;
+
+    if ((SG_DXFER_TO_DEV == hp->dxfer_direction) ||
+	(SG_DXFER_TO_FROM_DEV == hp->dxfer_direction)) {
+	num_xfer = (int)(new_interface ?  hp->dxfer_len : hp->flags);
+	if (schp->bufflen < num_xfer)
+	    num_xfer = schp->bufflen;
+    }
+    if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags)))
+	return 0;
+
+    SCSI_LOG_TIMEOUT(4,
+	 printk("sg_write_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n",
+		num_xfer, iovec_count, schp->k_use_sg));
+    if (iovec_count) {
+	onum = iovec_count;
+	if ((k = verify_area(VERIFY_READ, hp->dxferp,
+			     size_sg_iovec * onum)))
+	    return k;
+    }
+    else
+	onum = 1;
 
-        for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) { 
-            num = (int)sclp->length;
-            if (num > num_write_xfer) {
-                __copy_from_user(sclp->address, inp, num_write_xfer);
-                break;
+    if (0 == schp->k_use_sg) {  /* kernel has single buffer */
+	if (SG_USER_MEM != schp->buffer_mem_src) { /* else nothing to do */
+
+	    for (j = 0, p = schp->buffer; j < onum; ++j) {
+		res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
+		if (res) return res;
+		usglen = (num_xfer > usglen) ? usglen : num_xfer;
+		__copy_from_user(p, up, usglen);
+		p += usglen;
+		num_xfer -= usglen;
+		if (num_xfer <= 0)
+		    return 0;
             }
-            else {
-                __copy_from_user(sclp->address, inp, num);
-                num_write_xfer -= num;
-                if (num_write_xfer <= 0)
+	}
+    }
+    else {      /* kernel using scatter gather list */
+	struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+	char * mem_src_arr = sg_get_sgat_msa(schp);
+	ksglen = (int)sclp->length;
+	p = sclp->address;
+
+	for (j = 0, k = 0; j < onum; ++j) {
+	    res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
+	    if (res) return res;
+
+	    for (; (k < schp->k_use_sg) && p;
+		 ++k, ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
+		ok = (SG_USER_MEM != mem_src_arr[k]);
+		if (usglen <= 0)
+		    break;
+		if (ksglen > usglen) {
+		    if (usglen >= num_xfer) {
+			if (ok) __copy_from_user(p, up, num_xfer);
+			return 0;
+		    }
+		    if (ok) __copy_from_user(p, up, usglen);
+		    p += usglen;
+		    ksglen -= usglen;
                     break;
-                inp += num;
+		}
+		else {
+		    if (ksglen >= num_xfer) {
+			if (ok) __copy_from_user(p, up, num_xfer);
+			return 0;
+		    }
+		    if (ok) __copy_from_user(p, up, ksglen);
+		    up += ksglen;
+		    usglen -= ksglen;
+		}
             }
         }
     }
-    else
-        __copy_from_user(schp->buffer, inp, num_write_xfer);
+    return 0;
+}
+
+static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
+		      int wr_xf, int * countp, unsigned char ** up)
+{
+    int num_xfer = (int)hp->dxfer_len;
+    unsigned char * p;
+    int count, k;
+    sg_iovec_t u_iovec;
+
+    if (0 == sg_num) {
+	p = (unsigned char *)hp->dxferp;
+	if (wr_xf && ('\0' == hp->interface_id))
+	    count = (int)hp->flags; /* holds "old" input_size */
+	else
+	    count = num_xfer;
+    }
+    else {
+	__copy_from_user(&u_iovec,
+			 (unsigned char *)hp->dxferp + (ind * size_sg_iovec),
+			 size_sg_iovec);
+	p = (unsigned char *)u_iovec.iov_base;
+	count = (int)u_iovec.iov_len;
+    }
+    if ((k = verify_area(wr_xf ? VERIFY_READ : VERIFY_WRITE, p, count)))
+	return k;
+    if (up) *up = p;
+    if (countp) *countp = count;
+    return 0;
+}
+
+static char * sg_get_sgat_msa(Sg_scatter_hold * schp)
+{
+    int elem_sz = sizeof(struct scatterlist) + sizeof(char);
+    int mx_sc_elems = (schp->sglist_len / elem_sz) - 1;
+    return schp->buffer + (sizeof(struct scatterlist) * mx_sc_elems);
 }
 
 static void sg_remove_scat(Sg_scatter_hold * schp)
 {
-    SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: use_sg=%d\n", schp->use_sg)); 
-    if(schp->use_sg > 0) {
+    SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n",
+			       schp->k_use_sg));
+    if (schp->buffer && schp->sglist_len) {
         int k, mem_src;
         struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+	char * mem_src_arr = sg_get_sgat_msa(schp);
 
-        for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) {
-            mem_src = (int)(long)sclp->alt_address;
-            SCSI_LOG_TIMEOUT(5, 
-                printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n", 
+	for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
+	    mem_src = mem_src_arr[k];
+	    SCSI_LOG_TIMEOUT(5,
+		printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n",
                        k, sclp->address, sclp->length, mem_src));
             sg_free(sclp->address, sclp->length, mem_src);
             sclp->address = NULL;
             sclp->length = 0;
         }
-        sg_free(schp->buffer, schp->sglist_len, schp->mem_src);
+	sg_free(schp->buffer, schp->sglist_len, schp->buffer_mem_src);
     }
     else if (schp->buffer)
-        sg_free(schp->buffer, schp->b_malloc_len, schp->mem_src);
-    schp->buffer = NULL;
-    schp->bufflen = 0;
-    schp->use_sg = 0;
-    schp->sglist_len = 0;
+	sg_free(schp->buffer, schp->b_malloc_len, schp->buffer_mem_src);
+    memset(schp, 0, sizeof(*schp));
+}
+
+static int sg_read_xfer(Sg_request * srp)
+{
+    sg_io_hdr_t * hp = &srp->header;
+    Sg_scatter_hold * schp = &srp->data;
+    int num_xfer = 0;
+    int j, k, onum, usglen, ksglen, res, ok;
+    int iovec_count = (int)hp->iovec_count;
+    unsigned char * p;
+    unsigned char * up;
+    int new_interface = ('\0' == hp->interface_id) ? 0 : 1;
+
+    if ((SG_DXFER_FROM_DEV == hp->dxfer_direction) ||
+	(SG_DXFER_TO_FROM_DEV == hp->dxfer_direction)) {
+	num_xfer =  hp->dxfer_len;
+	if (schp->bufflen < num_xfer)
+	    num_xfer = schp->bufflen;
+    }
+    if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags)))
+	return 0;
+
+    SCSI_LOG_TIMEOUT(4,
+	 printk("sg_read_xfer: num_xfer=%d, iovec_count=%d, k_use_sg=%d\n",
+		num_xfer, iovec_count, schp->k_use_sg));
+    if (iovec_count) {
+	onum = iovec_count;
+	if ((k = verify_area(VERIFY_READ, hp->dxferp,
+			     size_sg_iovec * onum)))
+	    return k;
+    }
+    else
+	onum = 1;
+
+    if (0 == schp->k_use_sg) {  /* kernel has single buffer */
+	if (SG_USER_MEM != schp->buffer_mem_src) { /* else nothing to do */
+
+	    for (j = 0, p = schp->buffer; j < onum; ++j) {
+		res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
+		if (res) return res;
+		usglen = (num_xfer > usglen) ? usglen : num_xfer;
+		__copy_to_user(up, p, usglen);
+		p += usglen;
+		num_xfer -= usglen;
+		if (num_xfer <= 0)
+		    return 0;
+	    }
+	}
+    }
+    else {      /* kernel using scatter gather list */
+	struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
+	char * mem_src_arr = sg_get_sgat_msa(schp);
+	ksglen = (int)sclp->length;
+	p = sclp->address;
+
+	for (j = 0, k = 0; j < onum; ++j) {
+	    res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
+	    if (res) return res;
+
+	    for (; (k < schp->k_use_sg) && p;
+		 ++k, ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
+		ok = (SG_USER_MEM != mem_src_arr[k]);
+		if (usglen <= 0)
+		    break;
+		if (ksglen > usglen) {
+		    if (usglen >= num_xfer) {
+			if (ok) __copy_to_user(up, p, num_xfer);
+			return 0;
+		    }
+		    if (ok) __copy_to_user(up, p, usglen);
+		    p += usglen;
+		    ksglen -= usglen;
+		    break;
+		}
+		else {
+		    if (ksglen >= num_xfer) {
+			if (ok) __copy_to_user(up, p, num_xfer);
+			return 0;
+		    }
+		    if (ok) __copy_to_user(up, p, ksglen);
+		    up += ksglen;
+		    usglen -= ksglen;
+		}
+	    }
+	}
+    }
+    return 0;
 }
 
-static void sg_read_xfer(Sg_scatter_hold * schp, char * outp,
-                         int num_read_xfer)
+static void sg_read_oxfer(Sg_request * srp, char * outp, int num_read_xfer)
 {
-    SCSI_LOG_TIMEOUT(4, printk("sg_read_xfer: num_read_xfer=%d\n", 
-                               num_read_xfer)); 
+    Sg_scatter_hold * schp = &srp->data;
+
+    SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n",
+			       num_read_xfer));
     if ((! outp) || (num_read_xfer <= 0))
         return;
-    if(schp->use_sg > 0) {
+    if(schp->k_use_sg > 0) {
         int k, num;
         struct scatterlist * sclp = (struct scatterlist *)schp->buffer;
 
-        for (k = 0; (k < schp->use_sg) && sclp->address; ++k, ++sclp) {
+	for (k = 0; (k < schp->k_use_sg) && sclp->address; ++k, ++sclp) {
             num = (int)sclp->length;
             if (num > num_read_xfer) {
                 __copy_to_user(outp, sclp->address, num_read_xfer);
@@ -1349,11 +1775,11 @@
 {
     Sg_scatter_hold * schp = &sfp->reserve;
 
-    SCSI_LOG_TIMEOUT(4, printk("sg_build_reserve: req_size=%d\n", req_size)); 
+    SCSI_LOG_TIMEOUT(4, printk("sg_build_reserve: req_size=%d\n", req_size));
     do {
         if (req_size < PAGE_SIZE)
             req_size = PAGE_SIZE;
-        if (0 == sg_build_scat(schp, req_size, sfp))
+	if (0 == sg_build_indi(schp, sfp, req_size))
             return;
         else
             sg_remove_scat(schp);
@@ -1366,13 +1792,13 @@
     Sg_scatter_hold * req_schp = &srp->data;
     Sg_scatter_hold * rsv_schp = &sfp->reserve;
 
-    SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); 
-    if (rsv_schp->use_sg > 0) {
+    SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
+    if (rsv_schp->k_use_sg > 0) {
         int k, num;
         int rem = size;
         struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer;
 
-        for (k = 0; k < rsv_schp->use_sg; ++k, ++sclp) {
+	for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
             num = (int)sclp->length;
             if (rem <= num) {
                 sfp->save_scat_len = num;
@@ -1382,23 +1808,23 @@
             else
                 rem -= num;
         }
-        if (k < rsv_schp->use_sg) {
-            req_schp->use_sg = k + 1;   /* adjust scatter list length */
+	if (k < rsv_schp->k_use_sg) {
+	    req_schp->k_use_sg = k + 1;   /* adjust scatter list length */
             req_schp->bufflen = size;
             req_schp->sglist_len = rsv_schp->sglist_len;
             req_schp->buffer = rsv_schp->buffer;
-            req_schp->mem_src = rsv_schp->mem_src;
+	    req_schp->buffer_mem_src = rsv_schp->buffer_mem_src;
             req_schp->b_malloc_len = rsv_schp->b_malloc_len;
         }
         else
-            SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n")); 
+	    SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
     }
     else {
-        req_schp->use_sg = 0;
+	req_schp->k_use_sg = 0;
         req_schp->bufflen = size;
         req_schp->buffer = rsv_schp->buffer;
-        req_schp->mem_src = rsv_schp->mem_src;
-        req_schp->use_sg = rsv_schp->use_sg;
+	req_schp->buffer_mem_src = rsv_schp->buffer_mem_src;
+	req_schp->k_use_sg = rsv_schp->k_use_sg;
         req_schp->b_malloc_len = rsv_schp->b_malloc_len;
     }
     srp->res_used = 1;
@@ -1409,19 +1835,19 @@
     Sg_scatter_hold * req_schp = &srp->data;
     Sg_scatter_hold * rsv_schp = &sfp->reserve;
 
-    SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->use_sg=%d\n",
-                               (int)req_schp->use_sg)); 
-    if (rsv_schp->use_sg > 0) {
+    SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n",
+			       (int)req_schp->k_use_sg));
+    if (rsv_schp->k_use_sg > 0) {
         struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer;
 
-        if (sfp->save_scat_len > 0) 
-            (sclp + (req_schp->use_sg - 1))->length = 
+	if (sfp->save_scat_len > 0)
+	    (sclp + (req_schp->k_use_sg - 1))->length =
                                         (unsigned)sfp->save_scat_len;
         else
             SCSI_LOG_TIMEOUT(1, printk(
-                        "sg_unlink_reserve: BAD save_scat_len\n")); 
+			"sg_unlink_reserve: BAD save_scat_len\n"));
     }
-    req_schp->use_sg = 0;
+    req_schp->k_use_sg = 0;
     req_schp->bufflen = 0;
     req_schp->buffer = NULL;
     req_schp->sglist_len = 0;
@@ -1434,8 +1860,8 @@
     Sg_request * resp = NULL;
 
     resp = sfp->headrp;
-    while (resp) {
-        if ((! resp->my_cmdp) && 
+    while (resp) { /* look for requests that are ready + not SG_IO owned */
+	if (resp->done && (! resp->sg_io_owned) &&
             ((-1 == pack_id) || (resp->header.pack_id == pack_id)))
             return resp;
         resp = resp->nextrp;
@@ -1477,15 +1903,21 @@
         resp->parentfp = sfp;
         resp->nextrp = NULL;
         resp->res_used = 0;
+	resp->orphan = 0;
+	resp->sg_io_owned = 0;
+	resp->done = 0;
         memset(&resp->data, 0, sizeof(Sg_scatter_hold));
-        memset(&resp->header, 0, sizeof(struct sg_header));
+	memset(&resp->header, 0, size_sg_io_hdr);
+	resp->header.duration = jiffies;
         resp->my_cmdp = NULL;
+	resp->data.kiobp = NULL;
+	resp->data.mapped = 0;
     }
     return resp;
 }
 
 /* Return of 1 for found; 0 for not found */
-static int sg_remove_request(Sg_fd * sfp, const Sg_request * srp)
+static int sg_remove_request(Sg_fd * sfp, Sg_request * srp)
 {
     Sg_request * prev_rp;
     Sg_request * rp;
@@ -1509,30 +1941,23 @@
     return 0;
 }
 
-static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev, int get_reserved)
+static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev)
 {
     Sg_fd * sfp;
 
-    if (sdp->merge_fd) {
-        ++sdp->merge_fd;
-        return sdp->headfp;
-    }
     sfp = (Sg_fd *)sg_low_malloc(sizeof(Sg_fd), 0, SG_HEAP_KMAL, 0);
-    if (sfp) {
-        memset(sfp, 0, sizeof(Sg_fd));
-        sfp->my_mem_src = SG_HEAP_KMAL;
-        init_waitqueue_head(&sfp->read_wait);
-        init_waitqueue_head(&sfp->write_wait);
-    }
-    else
+    if (! sfp)
         return NULL;
-        
+    memset(sfp, 0, sizeof(Sg_fd));
+    sfp->fd_mem_src = SG_HEAP_KMAL;
+    init_waitqueue_head(&sfp->read_wait);
+
     sfp->timeout = SG_DEFAULT_TIMEOUT;
     sfp->force_packid = SG_DEF_FORCE_PACK_ID;
     sfp->low_dma = (SG_DEF_FORCE_LOW_DMA == 0) ?
                    sdp->device->host->unchecked_isa_dma : 1;
     sfp->cmd_q = SG_DEF_COMMAND_Q;
-    sfp->underrun_flag = SG_DEF_UNDERRUN_FLAG;
+    sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
     sfp->parentdp = sdp;
     if (! sdp->headfp)
         sdp->headfp = sfp;
@@ -1543,13 +1968,10 @@
         pfp->nextfp = sfp;
     }
     SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p, m_s=%d\n",
-                               sfp, (int)sfp->my_mem_src));
-    if (get_reserved) {
-        sg_build_reserve(sfp, SG_DEF_RESERVED_SIZE);
-        sg_big_buff = sfp->reserve.bufflen; /* sysctl shows most recent size */
-        SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, use_sg=%d\n",
-                               sfp->reserve.bufflen, sfp->reserve.use_sg));
-    }
+			       sfp, (int)sfp->fd_mem_src));
+    sg_build_reserve(sfp, sg_big_buff);
+    SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp:   bufflen=%d, k_use_sg=%d\n",
+			   sfp->reserve.bufflen, sfp->reserve.k_use_sg));
     return sfp;
 }
 
@@ -1560,17 +1982,13 @@
     int dirty = 0;
     int res = 0;
 
-    if (sdp->merge_fd) {
-        if (--sdp->merge_fd)
-            return 0;   /* if merge_fd then dec merge_fd counter */
-    }
     srp = sfp->headrp;
     if (srp) {
-/* Need to stop sg_command_done() playing with this list during this loop */
+/* Need to stop sg_cmd_done_bh() playing with this list during this loop */
         while (srp) {
             tsrp = srp->nextrp;
-            if (! srp->my_cmdp)
-                sg_finish_rem_req(srp, NULL, 0);
+	    if (srp->done)
+		sg_finish_rem_req(srp);
             else
                 ++dirty;
             srp = tsrp;
@@ -1592,13 +2010,13 @@
             }
         }
         if (sfp->reserve.bufflen > 0) {
-SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp:    bufflen=%d, use_sg=%d\n",
-                 (int)sfp->reserve.bufflen, (int)sfp->reserve.use_sg));
+SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp:    bufflen=%d, k_use_sg=%d\n",
+		 (int)sfp->reserve.bufflen, (int)sfp->reserve.k_use_sg));
             sg_remove_scat(&sfp->reserve);
         }
         sfp->parentdp = NULL;
-    SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp:    sfp=0x%p\n", sfp));
-        sg_low_free((char *)sfp, sizeof(Sg_fd), sfp->my_mem_src);
+	SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp:    sfp=0x%p\n", sfp));
+	sg_low_free((char *)sfp, sizeof(Sg_fd), sfp->fd_mem_src);
         res = 1;
     }
     else {
@@ -1621,6 +2039,18 @@
     return 0;
 }
 
+static int sg_dio_in_use(const Sg_fd * sfp)
+{
+    const Sg_request * srp = sfp->headrp;
+
+    while (srp) {
+	if ((! srp->done) && srp->data.kiobp)
+	    return 1;
+	srp = srp->nextrp;
+    }
+    return 0;
+}
+
 /* If retSzp==NULL want exact size or fail */
 /* sg_low_malloc() should always be called from a process context allowing
    GFP_KERNEL to be used instead of GFP_ATOMIC */
@@ -1636,9 +2066,6 @@
         /* Seen kmalloc(..,GFP_KERNEL) hang for 40 secs! */
         resp = kmalloc(rqSz, page_mask);
         if (resp && retSzp) *retSzp = rqSz;
-#ifdef SG_DEBUG
-        if (resp) ++sg_num_kmal;
-#endif
         return resp;
     }
     if (SG_HEAP_POOL == mem_src) {
@@ -1657,9 +2084,6 @@
                 if (resp) {
                     if (retSzp) *retSzp = rqSz;
                     sg_pool_secs_avail -= num_sect;
-#ifdef SG_DEBUG
-                    ++sg_num_pool;
-#endif
                     return resp;
                 }
             }
@@ -1684,16 +2108,13 @@
             resSz = a_size;
         }
         if (retSzp) *retSzp = resSz;
-#ifdef SG_DEBUG
-        if (resp) ++sg_num_page;
-#endif
     }
     else
         printk("sg_low_malloc: bad mem_src=%d, rqSz=%df\n", mem_src, rqSz);
     return resp;
 }
 
-static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp, 
+static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp,
                         int * mem_srcp)
 {
     char * resp = NULL;
@@ -1705,7 +2126,7 @@
         int low_dma = sfp->low_dma;
         int l_ms = -1;  /* invalid value */
 
-        switch (*mem_srcp) 
+	switch (*mem_srcp)
         {
         case SG_HEAP_PAGE:
             l_ms = (size < PAGE_SIZE) ? SG_HEAP_POOL : SG_HEAP_PAGE;
@@ -1738,45 +2159,54 @@
         }
         if (resp) *mem_srcp = l_ms;
     }
-    SCSI_LOG_TIMEOUT(6, printk("sg_malloc: size=%d, ms=%d, ret=0x%p\n", 
+    SCSI_LOG_TIMEOUT(6, printk("sg_malloc: size=%d, ms=%d, ret=0x%p\n",
                                size, *mem_srcp, resp));
     return resp;
 }
 
 static void sg_low_free(char * buff, int size, int mem_src)
 {
-    if (! buff)
-        return;
-    if (SG_HEAP_POOL == mem_src) {
-        int num_sect = size / SG_SECTOR_SZ;
-        scsi_free(buff, size);
-        sg_pool_secs_avail += num_sect;
-    }
-    else if (SG_HEAP_KMAL == mem_src)
-        kfree(buff);    /* size not used */
-    else if (SG_HEAP_PAGE == mem_src) {
-        int order, a_size;
-
-        for (order = 0, a_size = PAGE_SIZE;
-             a_size < size; order++, a_size <<= 1)
-            ;
-        free_pages((unsigned long)buff, order);
-    }
-    else
-        printk("sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%df\n", 
+    if (! buff) return;
+    switch (mem_src) {
+    case SG_HEAP_POOL:
+	{
+	    int num_sect = size / SG_SECTOR_SZ;
+
+	    scsi_free(buff, size);
+	    sg_pool_secs_avail += num_sect;
+	}
+	break;
+    case SG_HEAP_KMAL:
+	kfree(buff);    /* size not used */
+	break;
+    case SG_HEAP_PAGE:
+	{
+	    int order, a_size;
+	    for (order = 0, a_size = PAGE_SIZE;
+		 a_size < size; order++, a_size <<= 1)
+		;
+	    free_pages((unsigned long)buff, order);
+	}
+	break;
+    case SG_USER_MEM:
+	break; /* nothing to do */
+    default:
+	printk("sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%df\n",
                mem_src, buff, size);
+	break;
+    }
 }
 
 static void sg_free(char * buff, int size, int mem_src)
 {
-    SCSI_LOG_TIMEOUT(6, 
+    SCSI_LOG_TIMEOUT(6,
         printk("sg_free: buff=0x%p, size=%d\n", buff, size));
     if ((! buff) || (size <= 0))
         ;
     else
         sg_low_free(buff, size, mem_src);
 }
-        
+
 static void sg_clr_scpnt(Scsi_Cmnd * SCpnt)
 {
     SCpnt->use_sg = 0;
@@ -1787,3 +2217,391 @@
     SCpnt->request.rq_dev = MKDEV(0, 0);  /* "sg" _disowns_ command blk */
 }
 
+static int sg_ms_to_jif(unsigned int msecs)
+{
+    if ((UINT_MAX / 2U) < msecs)
+	return INT_MAX;      /* special case, set largest possible */
+    else
+	return ((int)msecs < (INT_MAX / 1000)) ? (((int)msecs * HZ) / 1000)
+					       : (((int)msecs / 1000) * HZ);
+}
+
+static unsigned sg_jif_to_ms(int jifs)
+{
+    if (jifs <= 0)
+	return 0U;
+    else {
+	unsigned int j = (unsigned int)jifs;
+	return (j < (UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) * 1000);
+    }
+}
+
+static unsigned char allow_ops[] = {TEST_UNIT_READY, INQUIRY,
+READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12};
+
+static int sg_allow_access(unsigned char opcode, char dev_type)
+{
+    int k;
+
+    if (TYPE_SCANNER == dev_type) /* TYPE_ROM maybe burner */
+	return 1;
+    for (k = 0; k < sizeof(allow_ops); ++k) {
+	if (opcode == allow_ops[k])
+	    return 1;
+    }
+    return 0;
+}
+
+
+static int sg_last_dev()
+{
+    int k;
+    for (k = sg_template.dev_max - 1; k >= 0; --k) {
+	if (sg_dev_arr[k].device)
+	    return k + 1;
+    }
+    return 0;   /* origin 1 */
+}
+
+#ifdef CONFIG_PROC_FS
+
+static struct proc_dir_entry * sg_proc_sgp = NULL;
+
+static const char * sg_proc_sg_dirname = "sg";
+static const char * sg_proc_leaf_names[] = {"def_reserved_size", "debug",
+			    "devices", "device_hdr", "device_strs",
+			    "hosts", "host_hdr", "host_strs", "version"};
+
+static int sg_proc_dressz_read(char * buffer, char ** start, off_t offset,
+			       int size, int * eof, void * data);
+static int sg_proc_dressz_info(char * buffer, int * len, off_t * begin,
+			       off_t offset, int size);
+static int sg_proc_dressz_write(struct file * filp, const char * buffer,
+				unsigned long count, void * data);
+static int sg_proc_debug_read(char * buffer, char ** start, off_t offset,
+			      int size, int * eof, void * data);
+static int sg_proc_debug_info(char * buffer, int * len, off_t * begin,
+			      off_t offset, int size);
+static int sg_proc_dev_read(char * buffer, char ** start, off_t offset,
+			    int size, int * eof, void * data);
+static int sg_proc_dev_info(char * buffer, int * len, off_t * begin,
+			    off_t offset, int size);
+static int sg_proc_devhdr_read(char * buffer, char ** start, off_t offset,
+			       int size, int * eof, void * data);
+static int sg_proc_devhdr_info(char * buffer, int * len, off_t * begin,
+			       off_t offset, int size);
+static int sg_proc_devstrs_read(char * buffer, char ** start, off_t offset,
+				int size, int * eof, void * data);
+static int sg_proc_devstrs_info(char * buffer, int * len, off_t * begin,
+				off_t offset, int size);
+static int sg_proc_host_read(char * buffer, char ** start, off_t offset,
+			     int size, int * eof, void * data);
+static int sg_proc_host_info(char * buffer, int * len, off_t * begin,
+			     off_t offset, int size);
+static int sg_proc_hosthdr_read(char * buffer, char ** start, off_t offset,
+				int size, int * eof, void * data);
+static int sg_proc_hosthdr_info(char * buffer, int * len, off_t * begin,
+				off_t offset, int size);
+static int sg_proc_hoststrs_read(char * buffer, char ** start, off_t offset,
+				 int size, int * eof, void * data);
+static int sg_proc_hoststrs_info(char * buffer, int * len, off_t * begin,
+				 off_t offset, int size);
+static int sg_proc_version_read(char * buffer, char ** start, off_t offset,
+				int size, int * eof, void * data);
+static int sg_proc_version_info(char * buffer, int * len, off_t * begin,
+				off_t offset, int size);
+static read_proc_t * sg_proc_leaf_reads[] = {
+	     sg_proc_dressz_read, sg_proc_debug_read,
+	     sg_proc_dev_read, sg_proc_devhdr_read, sg_proc_devstrs_read,
+	     sg_proc_host_read, sg_proc_hosthdr_read, sg_proc_hoststrs_read,
+	     sg_proc_version_read};
+static write_proc_t * sg_proc_leaf_writes[] = {
+	     sg_proc_dressz_write, 0, 0, 0, 0, 0, 0, 0, 0};
+
+#define PRINT_PROC(fmt,args...)                                 \
+    do {                                                        \
+	*len += sprintf(buffer + *len, fmt, ##args);            \
+	if (*begin + *len > offset + size)                      \
+	    return 0;                                           \
+	if (*begin + *len < offset) {                           \
+	    *begin += *len;                                     \
+	    *len = 0;                                           \
+	}                                                       \
+    } while(0)
+
+#define SG_PROC_READ_FN(infofp)                                 \
+    do {                                                        \
+	int len = 0;                                            \
+	off_t begin = 0;                                        \
+	*eof = infofp(buffer, &len, &begin, offset, size);      \
+	if (offset >= (begin + len))                            \
+	    return 0;                                           \
+	*start = buffer + ((begin > offset) ?                   \
+			(begin - offset) : (offset - begin));   \
+	return (size < (begin + len - offset)) ?                \
+				size : begin + len - offset;    \
+    } while(0)
+
+
+static int sg_proc_init()
+{
+    int k, mask;
+    int leaves = sizeof(sg_proc_leaf_names) / sizeof(sg_proc_leaf_names[0]);
+    struct proc_dir_entry * pdep;
+
+    if (! proc_scsi)
+	return 1;
+    sg_proc_sgp = create_proc_entry(sg_proc_sg_dirname,
+				    S_IFDIR | S_IRUGO | S_IXUGO, proc_scsi);
+    if (! sg_proc_sgp)
+	return 1;
+    for (k = 0; k < leaves; ++k) {
+	mask = sg_proc_leaf_writes[k] ? S_IRUGO | S_IWUSR : S_IRUGO;
+	pdep = create_proc_entry(sg_proc_leaf_names[k], mask, sg_proc_sgp);
+	if (pdep) {
+	    pdep->read_proc = sg_proc_leaf_reads[k];
+	    if (sg_proc_leaf_writes[k])
+		pdep->write_proc = sg_proc_leaf_writes[k];
+	}
+    }
+    return 0;
+}
+
+static void sg_proc_cleanup()
+{
+    int k;
+    int leaves = sizeof(sg_proc_leaf_names) / sizeof(sg_proc_leaf_names[0]);
+
+    if ((! proc_scsi) || (! sg_proc_sgp))
+	return;
+    for (k = 0; k < leaves; ++k)
+	remove_proc_entry(sg_proc_leaf_names[k], sg_proc_sgp);
+    remove_proc_entry(sg_proc_sg_dirname, proc_scsi);
+}
+
+static int sg_proc_dressz_read(char * buffer, char ** start, off_t offset,
+			       int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_dressz_info); }
+
+static int sg_proc_dressz_info(char * buffer, int * len, off_t * begin,
+			       off_t offset, int size)
+{
+    PRINT_PROC("%d\n", sg_big_buff);
+    return 1;
+}
+
+static int sg_proc_dressz_write(struct file * filp, const char * buffer,
+				unsigned long count, void * data)
+{
+    int num;
+    unsigned long k = ULONG_MAX;
+    char buff[11];
+
+    if (! capable(CAP_SYS_ADMIN))
+	return -EACCES;
+    num = (count < 10) ? count : 10;
+    copy_from_user(buff, buffer, num);
+    buff[count] = '\0';
+    k = simple_strtoul(buff, 0, 10);
+    if (k <= 1048576) {
+	sg_big_buff = k;
+	return count;
+    }
+    return -ERANGE;
+}
+
+static int sg_proc_debug_read(char * buffer, char ** start, off_t offset,
+			      int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_debug_info); }
+
+static int sg_proc_debug_info(char * buffer, int * len, off_t * begin,
+			      off_t offset, int size)
+{
+    const Sg_device * sdp = sg_dev_arr;
+    const sg_io_hdr_t * hp;
+    int j, max_dev;
+
+    if (NULL == sg_dev_arr) {
+	PRINT_PROC("sg_dev_arr NULL, death is imminent\n");
+	return 1;
+    }
+    max_dev = sg_last_dev();
+    PRINT_PROC("dev_max=%d max_active_device=%d (origin 1)\n",
+	       sg_template.dev_max, max_dev);
+    PRINT_PROC(" scsi_dma_free_sectors=%u sg_pool_secs_aval=%d "
+	       "def_reserved_size=%d\n",
+	       scsi_dma_free_sectors, sg_pool_secs_avail, sg_big_buff);
+    max_dev = sg_last_dev();
+    for (j = 0; j < max_dev; ++j, ++sdp) {
+	if (sdp) {
+	    Sg_fd * fp;
+	    Sg_request * srp;
+	    struct scsi_device * scsidp;
+	    int dev, k, blen, usg, crep;
+
+	    if (! (scsidp = sdp->device)) {
+		PRINT_PROC("device %d detached ??\n", j);
+		continue;
+	    }
+	    dev = MINOR(sdp->i_rdev);
+	    crep = 'a' + dev;
+
+	    PRINT_PROC(" >>> device=%d(sg%c) ", dev, crep > 126 ? '?' : crep);
+	    PRINT_PROC("scsi%d chan=%d id=%d lun=%d   em=%d sg_tablesize=%d"
+		       " excl=%d\n", scsidp->host->host_no, scsidp->channel,
+		       scsidp->id, scsidp->lun, scsidp->host->hostt->emulated,
+		       sdp->sg_tablesize, sdp->exclude);
+	    fp = sdp->headfp;
+	    for (k = 1; fp; fp = fp->nextfp, ++k) {
+		PRINT_PROC("   FD(%d): timeout=%d bufflen=%d "
+			   "(res)sgat=%d low_dma=%d\n",
+			   k, fp->timeout, fp->reserve.bufflen,
+			   (int)fp->reserve.k_use_sg, (int)fp->low_dma);
+		PRINT_PROC("   cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n",
+			   (int)fp->cmd_q, (int)fp->force_packid,
+			   (int)fp->keep_orphan, (int)fp->closed);
+		srp = fp->headrp;
+		if (NULL == srp)
+		    PRINT_PROC("     No requests active\n");
+		while (srp) {
+		    hp = &srp->header;
+/* stop indenting so far ... */
+	PRINT_PROC(srp->res_used ? "     reserved_buff>> " :
+	    ((SG_INFO_DIRECT_IO_MASK & hp->info) ? "     dio>> " : "     "));
+	blen = srp->my_cmdp ? srp->my_cmdp->bufflen : srp->data.bufflen;
+	usg = srp->my_cmdp ? srp->my_cmdp->use_sg : srp->data.k_use_sg;
+	PRINT_PROC(srp->done ? "rcv: id=%d" : (srp->my_cmdp ? "act: id=%d" :
+		    "prior: id=%d"), srp->header.pack_id);
+	if (! srp->res_used) PRINT_PROC(" blen=%d", blen);
+	if (srp->done)
+	    PRINT_PROC(" dur=%d", sg_jif_to_ms(hp->duration));
+	else
+	    PRINT_PROC(" t_o/elap=%d/%d", ((hp->interface_id == '\0') ?
+			sg_jif_to_ms(fp->timeout) : hp->timeout),
+		  sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0));
+	PRINT_PROC(" sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode);
+	srp = srp->nextrp;
+/* reset indenting */
+		}
+	    }
+	}
+    }
+    return 1;
+}
+
+static int sg_proc_dev_read(char * buffer, char ** start, off_t offset,
+			    int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_dev_info); }
+
+static int sg_proc_dev_info(char * buffer, int * len, off_t * begin,
+			    off_t offset, int size)
+{
+    const Sg_device * sdp = sg_dev_arr;
+    int j, max_dev;
+    struct scsi_device * scsidp;
+
+    max_dev = sg_last_dev();
+    for (j = 0; j < max_dev; ++j, ++sdp) {
+	if (sdp) {
+	    if (! (scsidp = sdp->device)) {
+		PRINT_PROC("-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+		continue;
+	    }
+	    PRINT_PROC("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
+	       scsidp->host->host_no, scsidp->channel, scsidp->id,
+	       scsidp->lun, (int)scsidp->type, (int)scsidp->disconnect,
+	       (int)scsidp->queue_depth, (int)scsidp->tagged_queue);
+	}
+    }
+    return 1;
+}
+
+static int sg_proc_devhdr_read(char * buffer, char ** start, off_t offset,
+			       int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_devhdr_info); }
+
+static int sg_proc_devhdr_info(char * buffer, int * len, off_t * begin,
+			       off_t offset, int size)
+{
+    PRINT_PROC("host\tchan\tid\tlun\ttype\tdiscon\tqdepth\ttq\n");
+    return 1;
+}
+
+static int sg_proc_devstrs_read(char * buffer, char ** start, off_t offset,
+				int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_devstrs_info); }
+
+static int sg_proc_devstrs_info(char * buffer, int * len, off_t * begin,
+				off_t offset, int size)
+{
+    const Sg_device * sdp = sg_dev_arr;
+    int j, max_dev;
+    struct scsi_device * scsidp;
+
+    max_dev = sg_last_dev();
+    for (j = 0; j < max_dev; ++j, ++sdp) {
+	if (sdp) {
+	    if ((scsidp = sdp->device))
+		PRINT_PROC("%8.8s\t%16.16s\t%4.4s\n",
+			   scsidp->vendor, scsidp->model, scsidp->rev);
+	    else
+		PRINT_PROC("<no active device>\n");
+	}
+    }
+    return 1;
+}
+
+static int sg_proc_host_read(char * buffer, char ** start, off_t offset,
+			     int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_host_info); }
+
+static int sg_proc_host_info(char * buffer, int * len, off_t * begin,
+			     off_t offset, int size)
+{
+    struct Scsi_Host * shp;
+
+    for (shp = scsi_hostlist; shp; shp = shp->next)
+	PRINT_PROC("%u\t%hu\t%hd\t%hu\t%d\t%d\n",
+		   shp->unique_id, shp->host_busy, shp->cmd_per_lun,
+		   shp->sg_tablesize, (int)shp->unchecked_isa_dma,
+		   (int)shp->hostt->emulated);
+    return 1;
+}
+
+static int sg_proc_hosthdr_read(char * buffer, char ** start, off_t offset,
+				int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_hosthdr_info); }
+
+static int sg_proc_hosthdr_info(char * buffer, int * len, off_t * begin,
+				off_t offset, int size)
+{
+    PRINT_PROC("uid\tbusy\tcpl\tscatg\tisa\temul\n");
+    return 1;
+}
+
+static int sg_proc_hoststrs_read(char * buffer, char ** start, off_t offset,
+				 int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_hoststrs_info); }
+
+static int sg_proc_hoststrs_info(char * buffer, int * len, off_t * begin,
+				 off_t offset, int size)
+{
+    struct Scsi_Host * shp;
+
+    for (shp = scsi_hostlist; shp; shp = shp->next)
+	PRINT_PROC("%s\n", shp->hostt->info ? shp->hostt->info(shp) :
+		    (shp->hostt->name ? shp->hostt->name : "<no name>"));
+    return 1;
+}
+
+static int sg_proc_version_read(char * buffer, char ** start, off_t offset,
+				int size, int * eof, void * data)
+{ SG_PROC_READ_FN(sg_proc_version_info); }
+
+static int sg_proc_version_info(char * buffer, int * len, off_t * begin,
+				off_t offset, int size)
+{
+    PRINT_PROC("%d\t%s\n", sg_version_num, sg_version_str);
+    return 1;
+}
+#endif  /* CONFIG_PROC_FS */
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.3.42/linux/drivers/scsi/sr.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/sr.c	Wed Feb  9 18:40:24 2000
@@ -703,17 +703,17 @@
 		return 0;
 	sr_template.dev_max =
 	    sr_template.dev_noticed + SR_EXTRA_DEVS;
-	scsi_CDs = (Scsi_CD *) scsi_init_malloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC);
+	scsi_CDs = (Scsi_CD *) kmalloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC);
 	memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD));
 
-	sr_sizes = (int *) scsi_init_malloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
+	sr_sizes = (int *) kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
 	memset(sr_sizes, 0, sr_template.dev_max * sizeof(int));
 
-	sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max *
-						 sizeof(int), GFP_ATOMIC);
+	sr_blocksizes = (int *) kmalloc(sr_template.dev_max *
+					sizeof(int), GFP_ATOMIC);
 
-	sr_hardsizes = (int *) scsi_init_malloc(sr_template.dev_max *
-						 sizeof(int), GFP_ATOMIC);
+	sr_hardsizes = (int *) kmalloc(sr_template.dev_max *
+				       sizeof(int), GFP_ATOMIC);
 	/*
 	 * These are good guesses for the time being.
 	 */
@@ -831,16 +831,14 @@
 	unregister_blkdev(MAJOR_NR, "sr");
 	sr_registered--;
 	if (scsi_CDs != NULL) {
-		scsi_init_free((char *) scsi_CDs,
-			       (sr_template.dev_noticed + SR_EXTRA_DEVS)
-			       * sizeof(Scsi_CD));
+		kfree((char *) scsi_CDs);
 
-		scsi_init_free((char *) sr_sizes, sr_template.dev_max * sizeof(int));
+		kfree((char *) sr_sizes);
 		sr_sizes = NULL;
 
-		scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int));
+		kfree((char *) sr_blocksizes);
 		sr_blocksizes = NULL;
-		scsi_init_free((char *) sr_hardsizes, sr_template.dev_max * sizeof(int));
+		kfree((char *) sr_hardsizes);
 		sr_hardsizes = NULL;
 	}
 	blksize_size[MAJOR_NR] = NULL;
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.3.42/linux/drivers/scsi/st.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/scsi/st.c	Wed Feb  9 11:42:35 2000
@@ -3217,17 +3217,12 @@
 
 static struct file_operations st_fops =
 {
-	NULL,			/* lseek - default */
-	st_read,		/* read - general block-dev read */
-	st_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	st_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	scsi_tape_open,		/* open */
-	scsi_tape_flush,	/* flush */
-	scsi_tape_close,	/* release */
-	NULL			/* fsync */
+	read:		st_read,
+	write:		st_write,
+	ioctl:		st_ioctl,
+	open:		scsi_tape_open,
+	flush:		scsi_tape_flush,
+	release:	scsi_tape_close,
 };
 
 static int st_attach(Scsi_Device * SDp)
diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v2.3.42/linux/drivers/scsi/u14-34f.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/scsi/u14-34f.c	Wed Feb  9 18:40:24 2000
@@ -826,7 +826,7 @@
       }
    else {
       unsigned long flags;
-//FIXME//      sh[j]->wish_block = TRUE;
+      scsi_register_blocked_host(sh[j]);
       sh[j]->unchecked_isa_dma = TRUE;
       
       flags=claim_dma_lock();
@@ -1947,6 +1947,10 @@
 
    if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
                             driver_name);
+
+   if( sh[j]->block != NULL ) {
+	   scsi_deregister_blocked_host(sh[j]);
+   }
 
    for (i = 0; i < sh[j]->can_queue; i++)
       if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
diff -u --recursive --new-file v2.3.42/linux/drivers/sgi/char/ds1286.c linux/drivers/sgi/char/ds1286.c
--- v2.3.42/linux/drivers/sgi/char/ds1286.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/sgi/char/ds1286.c	Wed Feb  9 11:42:35 2000
@@ -373,16 +373,12 @@
  */
 
 static struct file_operations ds1286_fops = {
-	ds1286_llseek,
-	ds1286_read,
-	NULL,		/* No write */
-	NULL,		/* No readdir */
-	ds1286_poll,
-	ds1286_ioctl,
-	NULL,		/* No mmap */
-	ds1286_open,
-	NULL,
-	ds1286_release
+	llseek:		ds1286_llseek,
+	read:		ds1286_read,
+	poll:		ds1286_poll,
+	ioctl:		ds1286_ioctl,
+	open:		ds1286_open,
+	release:	ds1286_release,
 };
 
 static struct miscdevice ds1286_dev=
diff -u --recursive --new-file v2.3.42/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c
--- v2.3.42/linux/drivers/sgi/char/graphics.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sgi/char/graphics.c	Wed Feb  9 11:42:35 2000
@@ -287,18 +287,10 @@
 #endif
 
 struct file_operations sgi_graphics_fops = {
-	NULL,			/* llseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	sgi_graphics_ioctl,	/* ioctl */
-	sgi_graphics_mmap,	/* mmap */
-	sgi_graphics_open,	/* open */
-	NULL,			/* flush */
-	sgi_graphics_close,	/* release */
-	NULL,			/* fsync */
-	NULL			/* lock */
+	ioctl:		sgi_graphics_ioctl,
+	mmap:		sgi_graphics_mmap,
+	open:		sgi_graphics_open,
+	release:	sgi_graphics_close,
 };
 
 /* /dev/graphics */
diff -u --recursive --new-file v2.3.42/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c
--- v2.3.42/linux/drivers/sgi/char/shmiq.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sgi/char/shmiq.c	Wed Feb  9 11:42:35 2000
@@ -429,21 +429,14 @@
 }
 
 
-static struct
-file_operations shmiq_fops =
+static struct file_operations shmiq_fops =
 {
-        NULL,                   /* seek */
-        NULL,                   /* read */
-        NULL,                   /* write */
-        NULL,                   /* readdir */
-        shmiq_qcntl_poll,       /* poll */
-        shmiq_qcntl_ioctl,      /* ioctl */
-        shmiq_qcntl_mmap,       /* mmap */
-        shmiq_qcntl_open,       /* open */
-	NULL,			/* flush */
-        shmiq_qcntl_close,      /* close */
-        NULL,                   /* fsync */
-        shmiq_qcntl_fasync,     /* fasync */
+	poll:		shmiq_qcntl_poll,
+	ioctl:		shmiq_qcntl_ioctl,
+	mmap:		shmiq_qcntl_mmap,
+	open:		shmiq_qcntl_open,
+	release:	shmiq_qcntl_close,
+	fasync:		shmiq_qcntl_fasync,
 };
 
 void
diff -u --recursive --new-file v2.3.42/linux/drivers/sgi/char/streamable.c linux/drivers/sgi/char/streamable.c
--- v2.3.42/linux/drivers/sgi/char/streamable.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sgi/char/streamable.c	Wed Feb  9 11:42:35 2000
@@ -72,18 +72,9 @@
 }
 
 struct file_operations sgi_gfx_fops = {
-	NULL,			/* llseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	sgi_gfx_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	sgi_gfx_open,		/* open */
-	NULL,			/* flush */
-	sgi_gfx_close,		/* release */
-	NULL,			/* fsync */
-	NULL			/* lock */
+	ioctl:		sgi_gfx_ioctl,
+	open:		sgi_gfx_open,
+	release:	sgi_gfx_close,
 };
  
 static struct miscdevice dev_gfx = {
@@ -191,18 +182,8 @@
 }
 
 struct file_operations sgi_keyb_fops = {
-	NULL,			/* llseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	sgi_keyb_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	sgi_keyb_open,		/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL			/* lock */
+	ioctl:		sgi_keyb_ioctl,
+	open:		sgi_keyb_open,
 };
 
 static struct miscdevice dev_input_keyboard = {
@@ -330,18 +311,9 @@
 }
 
 struct file_operations sgi_mouse_fops = {
-	NULL,			/* llseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	sgi_mouse_ioctl,	/* ioctl */
-	NULL,			/* mmap */
-	sgi_mouse_open,		/* open */
-	NULL,			/* flush */
-	sgi_mouse_close,	/* release */
-	NULL,			/* fsync */
-	NULL			/* lock */
+	ioctl:		sgi_mouse_ioctl,
+	open:		sgi_mouse_open,
+	release:	sgi_mouse_close,
 };
 
 /* /dev/input/mouse */
diff -u --recursive --new-file v2.3.42/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c
--- v2.3.42/linux/drivers/sgi/char/usema.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sgi/char/usema.c	Wed Feb  9 11:42:35 2000
@@ -170,18 +170,10 @@
 }
 
 struct file_operations sgi_usemaclone_fops = {
-	NULL,			/* llseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	sgi_usemaclone_poll,	/* poll */
-	sgi_usemaclone_ioctl,	/* ioctl */
-	NULL,			/* mmap */
-	sgi_usemaclone_open,	/* open */
-	NULL,			/* flush */
-	sgi_usemaclone_release,	/* release */
-	NULL,			/* fsync */
-	NULL			/* lock */
+	poll:		sgi_usemaclone_poll,
+	ioctl:		sgi_usemaclone_ioctl,
+	open:		sgi_usemaclone_open,
+	release:	sgi_usemaclone_release,
 };
 
 static struct miscdevice dev_usemaclone = {
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.3.42/linux/drivers/sound/Makefile	Tue Feb  1 01:35:44 2000
+++ linux/drivers/sound/Makefile	Wed Feb  9 18:54:11 2000
@@ -53,7 +53,7 @@
 obj-$(CONFIG_SOUND_CS4232)	+= uart401.o
 obj-$(CONFIG_SOUND_GUS)		+= gus.o ad1848.o
 obj-$(CONFIG_SOUND_MAD16)	+= mad16.o ad1848.o sb.o uart401.o
-obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx.o sb.o uart401.o ac97.o
+obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o sb.o uart401.o ac97.o
 obj-$(CONFIG_SOUND_MAUI)	+= maui.o mpu401.o
 obj-$(CONFIG_SOUND_MPU401)	+= mpu401.o
 obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o
@@ -81,7 +81,7 @@
 obj-$(CONFIG_SOUND_SONICVIBES)	+= sonicvibes.o
 obj-$(CONFIG_SOUND_CMPCI)	+= cmpci.o
 obj-$(CONFIG_SOUND_ES1370)	+= es1370.o
-obj-$(CONFIG_SOUND_ES1371)	+= es1371.o
+obj-$(CONFIG_SOUND_ES1371)	+= es1371.o ac97_codec.o
 obj-$(CONFIG_SOUND_ESSSOLO1)	+= esssolo1.o
 obj-$(CONFIG_SOUND_MAESTRO)	+= maestro.o
 obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/ac97_codec.h linux/drivers/sound/ac97_codec.h
--- v2.3.42/linux/drivers/sound/ac97_codec.h	Tue Feb  1 01:35:44 2000
+++ linux/drivers/sound/ac97_codec.h	Thu Feb 10 12:22:03 2000
@@ -154,4 +154,5 @@
 };
 
 extern int ac97_probe_codec(struct ac97_codec *);
-#endif
+
+#endif /* _AC97_CODEC_H_ */
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.3.42/linux/drivers/sound/cmpci.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sound/cmpci.c	Wed Feb  9 11:42:35 2000
@@ -1180,19 +1180,10 @@
 }
 
 static /*const*/ struct file_operations cm_mixer_fops = {
-	&cm_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&cm_ioctl_mixdev,
-	NULL,  /* mmap */
-	&cm_open_mixdev,
-	NULL,	/* flush */
-	&cm_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		cm_llseek,
+	ioctl:		cm_ioctl_mixdev,
+	open:		cm_open_mixdev,
+	release:	cm_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -1801,19 +1792,14 @@
 }
 
 static /*const*/ struct file_operations cm_audio_fops = {
-	&cm_llseek,
-	&cm_read,
-	&cm_write,
-	NULL,  /* readdir */
-	&cm_poll,
-	&cm_ioctl,
-	&cm_mmap,
-	&cm_open,
-	NULL,	/* flush */
-	&cm_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		cm_llseek,
+	read:		cm_read,
+	write:		cm_write,
+	poll:		cm_poll,
+	ioctl:		cm_ioctl,
+	mmap:		cm_mmap,
+	open:		cm_open,
+	release:	cm_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2080,19 +2066,12 @@
 }
 
 static /*const*/ struct file_operations cm_midi_fops = {
-	&cm_llseek,
-	&cm_midi_read,
-	&cm_midi_write,
-	NULL,  /* readdir */
-	&cm_midi_poll,
-	NULL,  /* ioctl */
-	NULL,  /* mmap */
-	&cm_midi_open,
-	NULL,	/* flush */
-	&cm_midi_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		cm_llseek,
+	read:		cm_midi_read,
+	write:		cm_midi_write,
+	poll:		cm_midi_poll,
+	open:		cm_midi_open,
+	release:	cm_midi_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2252,19 +2231,10 @@
 }
 
 static /*const*/ struct file_operations cm_dmfm_fops = {
-	&cm_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&cm_dmfm_ioctl,
-	NULL,  /* mmap */
-	&cm_dmfm_open,
-	NULL,	/* flush */
-	&cm_dmfm_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		cm_llseek,
+	ioctl:		cm_dmfm_ioctl,
+	open:		cm_dmfm_open,
+	release:	cm_dmfm_release,
 };
 
 /* --------------------------------------------------------------------- */
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c
--- v2.3.42/linux/drivers/sound/dev_table.c	Tue May 11 23:40:50 1999
+++ linux/drivers/sound/dev_table.c	Thu Feb 10 12:32:03 2000
@@ -13,6 +13,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/init.h>
 
 
 #define _DEV_TABLE_C_
@@ -313,9 +314,12 @@
 	return 0;
 }
 
-void sound_setup(char *str, int *ints)
+static int __init sound_setup(char *str)
 {
 	int i, n = num_sound_cards;
+	int ints[32];
+
+	str = get_options(str, ARRAY_SIZE(ints), ints);
 
 	/*
 	 *	First disable all drivers
@@ -325,7 +329,7 @@
 		snd_installed_cards[i].enabled = 0;
 
 	if (ints[0] == 0 || ints[1] == 0)
-		return;
+		return 1;
 	/*
 	 *	Then enable them one by time
 	 */
@@ -343,7 +347,7 @@
 			/*
 			 * Add any future extensions here
 			 */
-			return;
+			return 1;
 		}
 		ioaddr = (val & 0x000fff00) >> 8;
 		irq = (val & 0x000000f0) >> 4;
@@ -376,7 +380,11 @@
 			snd_installed_cards[ptr].config.card_subtype = 0;
 		}
 	}
+	
+	return 1;
 }
+
+__setup("sound=", sound_setup);
 
 
 struct address_info * sound_getconf(int card_type)
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.3.42/linux/drivers/sound/dev_table.h	Fri Oct 22 13:21:50 1999
+++ linux/drivers/sound/dev_table.h	Thu Feb 10 12:32:03 2000
@@ -717,7 +717,10 @@
 void sound_unload_drivers(void);
 void sound_unload_driver(int type);
 int sndtable_identify_card(char *name);
+
+#if FIXED_FOR_2_4_0
 void sound_setup (char *str, int *ints);
+#endif
 
 extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
 int sndtable_probe (int unit, struct address_info *hw_config);
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.3.42/linux/drivers/sound/dmasound.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sound/dmasound.c	Thu Feb 10 12:31:07 2000
@@ -4605,16 +4605,10 @@
 
 static struct file_operations mixer_fops =
 {
-	sound_lseek,
-	NULL,			/* mixer_read */
-	NULL,			/* mixer_write */
-	NULL,			/* mixer_readdir */
-	NULL,			/* mixer_poll */
-	mixer_ioctl,
-	NULL,			/* mixer_mmap */
-	mixer_open,
-	NULL,			/* flush */
-	mixer_release,
+	llseek:		sound_lseek,
+	ioctl:		mixer_ioctl,
+	open:		mixer_open,
+	release:	mixer_release,
 };
 
 
@@ -5231,20 +5225,14 @@
 
 static struct file_operations sq_fops =
 {
-	sound_lseek,
+	llseek:		sound_lseek,
+	write:		sq_write,
+	ioctl:		sq_ioctl,
+	open:		sq_open,
+	release:	sq_release,
 #ifdef CONFIG_PPC
-	sq_read,			/* sq_read */
-#else
-	NULL,			/* sq_read */
+	read:		sq_read,			/* sq_read */
 #endif
-	sq_write,
-	NULL,			/* sq_readdir */
-	NULL,			/* sq_poll */
-	sq_ioctl,
-	NULL,			/* sq_mmap */
-	sq_open,
-	NULL,			/* flush */
-	sq_release,
 };
 
 
@@ -5449,16 +5437,10 @@
 
 static struct file_operations state_fops =
 {
-	sound_lseek,
-	state_read,
-	NULL,			/* state_write */
-	NULL,			/* state_readdir */
-	NULL,			/* state_poll */
-	NULL,			/* state_ioctl */
-	NULL,			/* state_mmap */
-	state_open,
-	NULL,			/* flush */
-	state_release,
+	llseek:		sound_lseek,
+	read:		state_read,
+	open:		state_open,
+	release:	state_release,
 };
 
 
@@ -5700,10 +5682,12 @@
 }
 
 
-#define MAXARGS		8	/* Should be sufficient for now */
-
-void __init dmasound_setup(char *str, int *ints)
+static int __init dmasound_setup(char *str)
 {
+	int ints[6];
+
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+
 	/* check the bootstrap parameter for "dmasound=" */
 
 	switch (ints[0]) {
@@ -5727,8 +5711,13 @@
 		break;
 	default:
 		printk("dmasound_setup: illegal number of arguments\n");
+		return 0;
 	}
+	
+	return 1;
 }
+
+__setup("dmasound=", dmasound_setup);
 
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.42/linux/drivers/sound/es1370.c	Fri Jan 21 18:19:17 2000
+++ linux/drivers/sound/es1370.c	Wed Feb  9 11:42:35 2000
@@ -116,6 +116,7 @@
  *    28.10.1999   0.31  More waitqueue races fixed
  *    08.01.2000   0.32  Prevent some ioctl's from returning bad count values on underrun/overrun;
  *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    07.02.2000   0.33  Use pci_alloc_consistent and pci_register_driver
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -307,8 +308,11 @@
 	/* magic */
 	unsigned int magic;
 
-	/* we keep sb cards in a linked list */
-	struct es1370_state *next;
+	/* list of es1370 devices */
+	struct list_head devs;
+
+	/* the corresponding pci_dev structure */
+	struct pci_dev *dev;
 
 	/* soundcore stuff */
 	int dev_audio;
@@ -340,6 +344,7 @@
 
 	struct dmabuf {
 		void *rawbuf;
+		dma_addr_t dmaaddr;
 		unsigned buforder;
 		unsigned numfrag;
 		unsigned fragshift;
@@ -374,7 +379,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct es1370_state *devs = NULL;
+static LIST_HEAD(devs);
 
 /*
  * The following buffer is used to point the phantom write channel to,
@@ -532,7 +537,7 @@
 #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-extern inline void dealloc_dmabuf(struct dmabuf *db)
+extern inline void dealloc_dmabuf(struct es1370_state *s, struct dmabuf *db)
 {
 	unsigned long map, mapend;
 
@@ -541,7 +546,7 @@
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
 		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
 			clear_bit(PG_reserved, &mem_map[map].flags);	
-		free_pages((unsigned long)db->rawbuf, db->buforder);
+		pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr);
 	}
 	db->rawbuf = NULL;
 	db->mapped = db->ready = 0;
@@ -558,7 +563,7 @@
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
 		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
+			if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr)))
 				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
@@ -593,7 +598,7 @@
 	db->dmasize = db->numfrag << db->fragshift;
 	memset(db->rawbuf, (fmt & ES1370_FMT_S16) ? 0 : 0x80, db->dmasize);
 	outl((reg >> 8) & 15, s->io+ES1370_REG_MEMPAGE);
-	outl(virt_to_bus(db->rawbuf), s->io+(reg & 0xff));
+	outl(db->dmaaddr, s->io+(reg & 0xff));
 	outl((db->dmasize >> 2)-1, s->io+((reg + 4) & 0xff));
 	db->ready = 1;
 	return 0;
@@ -1013,12 +1018,16 @@
 static int es1370_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
-	struct es1370_state *s = devs;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && s->dev_mixer != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (s->dev_mixer == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	MOD_INC_USE_COUNT;
@@ -1040,19 +1049,10 @@
 }
 
 static /*const*/ struct file_operations es1370_mixer_fops = {
-	&es1370_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&es1370_ioctl_mixdev,
-	NULL,  /* mmap */
-	&es1370_open_mixdev,
-	NULL,	/* flush */
-	&es1370_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	ioctl:		es1370_ioctl_mixdev,
+	open:		es1370_open_mixdev,
+	release:	es1370_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -1655,13 +1655,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1370_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && ((s->dev_audio ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (!((s->dev_audio ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -1720,11 +1724,11 @@
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac2(s);
 		synchronize_irq();
-		dealloc_dmabuf(&s->dma_dac2);
+		dealloc_dmabuf(s, &s->dma_dac2);
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(s);
-		dealloc_dmabuf(&s->dma_adc);
+		dealloc_dmabuf(s, &s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
 	wake_up(&s->open_wait);
@@ -1734,19 +1738,14 @@
 }
 
 static /*const*/ struct file_operations es1370_audio_fops = {
-	&es1370_llseek,
-	&es1370_read,
-	&es1370_write,
-	NULL,  /* readdir */
-	&es1370_poll,
-	&es1370_ioctl,
-	&es1370_mmap,
-	&es1370_open,
-	NULL,	/* flush */
-	&es1370_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	read:		es1370_read,
+	write:		es1370_write,
+	poll:		es1370_poll,
+	ioctl:		es1370_ioctl,
+	mmap:		es1370_mmap,
+	open:		es1370_open,
+	release:	es1370_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2065,13 +2064,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1370_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && ((s->dev_dac ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (!((s->dev_dac ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
        	/* we allow opening with O_RDWR, most programs do it although they will only write */
 #if 0
@@ -2123,7 +2126,7 @@
 	drain_dac1(s, file->f_flags & O_NONBLOCK);
 	down(&s->open_sem);
 	stop_dac1(s);
-	dealloc_dmabuf(&s->dma_dac1);
+	dealloc_dmabuf(s, &s->dma_dac1);
 	s->open_mode &= ~FMODE_DAC;
 	wake_up(&s->open_wait);
 	up(&s->open_sem);
@@ -2132,19 +2135,13 @@
 }
 
 static /*const*/ struct file_operations es1370_dac_fops = {
-	&es1370_llseek,
-	NULL,  /* read */
-	&es1370_write_dac,
-	NULL,  /* readdir */
-	&es1370_poll_dac,
-	&es1370_ioctl_dac,
-	&es1370_mmap_dac,
-	&es1370_open_dac,
-	NULL,	/* flush */
-	&es1370_release_dac,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	write:		es1370_write_dac,
+	poll:		es1370_poll_dac,
+	ioctl:		es1370_ioctl_dac,
+	mmap:		es1370_mmap_dac,
+	open:		es1370_open_dac,
+	release:	es1370_release_dac,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2307,13 +2304,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1370_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && s->dev_midi != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (s->dev_midi == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2404,30 +2405,25 @@
 }
 
 static /*const*/ struct file_operations es1370_midi_fops = {
-	&es1370_llseek,
-	&es1370_midi_read,
-	&es1370_midi_write,
-	NULL,  /* readdir */
-	&es1370_midi_poll,
-	NULL,  /* ioctl */
-	NULL,  /* mmap */
-	&es1370_midi_open,
-	NULL,	/* flush */
-	&es1370_midi_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	read:		es1370_midi_read,
+	write:		es1370_midi_write,
+	poll:		es1370_midi_poll,
+	open:		es1370_midi_open,
+	release:	es1370_midi_release,
 };
 
 /* --------------------------------------------------------------------- */
 
-/* maximum number of devices */
+/* maximum number of devices; only used for command line params */
 #define NR_DEVICE 5
 
 static int joystick[NR_DEVICE] = { 0, };
 static int lineout[NR_DEVICE] = { 0, };
 static int micbias[NR_DEVICE] = { 0, };
 
+static unsigned int devindex = 0;
+
 MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
 MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
 MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
@@ -2460,142 +2456,168 @@
 				 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
 
-
-static int __init init_es1370(void)
+static int es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1370_state *s;
-	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
-	int i, val, index = 0;
+	int i, val;
+
+	if (!RSRCISIOREGION(pcidev, 0))
+		return -1;
+	if (pcidev->irq == 0) 
+		return -1;
+	if (!(s = kmalloc(sizeof(struct es1370_state), GFP_KERNEL))) {
+		printk(KERN_WARNING "es1370: out of memory\n");
+		return -1;
+	}
+	memset(s, 0, sizeof(struct es1370_state));
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac1.wait);
+	init_waitqueue_head(&s->dma_dac2.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_waitqueue_head(&s->midi.iwait);
+	init_waitqueue_head(&s->midi.owait);
+	init_MUTEX(&s->open_sem);
+	spin_lock_init(&s->lock);
+	s->magic = ES1370_MAGIC;
+	s->dev = pcidev;
+	s->io = RSRCADDRESS(pcidev, 0);
+	s->irq = pcidev->irq;
+	if (!request_region(s->io, ES1370_EXTENT, "es1370")) {
+		printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
+		goto err_region;
+	}
+	if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
+		printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
+		goto err_irq;
+	}
+	pci_enable_device(pcidev);
+	/* initialize codec registers */
+	/* note: setting CTRL_SERR_DIS is reported to break
+	 * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
+	s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
+	if (joystick[devindex]) {
+		if (check_region(0x200, JOY_EXTENT))
+			printk(KERN_ERR "es1370: io port 0x200 in use\n");
+		else
+			s->ctrl |= CTRL_JYSTK_EN;
+	}
+	if (lineout[devindex])
+		s->ctrl |= CTRL_XCTL0;
+	if (micbias[devindex])
+		s->ctrl |= CTRL_XCTL1;
+	s->sctrl = 0;
+	printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
+	       KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
+	       s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
+	       (s->ctrl & CTRL_XCTL0) ? "out" : "in",
+		       (s->ctrl & CTRL_XCTL1) ? "1" : "0");
+	/* register devices */
+	if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0)
+		goto err_dev1;
+	if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0)
+		goto err_dev2;
+	if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0)
+		goto err_dev3;
+	if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0)
+		goto err_dev4;
+	/* initialize the chips */
+	outl(s->ctrl, s->io+ES1370_REG_CONTROL);
+	outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL);
+	/* point phantom write channel to "bugbuf" */
+	outl((ES1370_REG_PHANTOM_FRAMEADR >> 8) & 15, s->io+ES1370_REG_MEMPAGE);
+	outl(virt_to_bus(bugbuf), s->io+(ES1370_REG_PHANTOM_FRAMEADR & 0xff));
+	outl(0, s->io+(ES1370_REG_PHANTOM_FRAMECNT & 0xff));
+	pci_set_master(pcidev);  /* enable bus mastering */
+	wrcodec(s, 0x16, 3); /* no RST, PD */
+	wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!!  */
+	wrcodec(s, 0x18, 0); /* recording source is mixer */
+	wrcodec(s, 0x19, s->mix.micpreamp = 1); /* turn on MIC preamp */
+	s->mix.imix = 1;
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD;
+	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+		val = initvol[i].vol;
+		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+	}
+	set_fs(fs);
+	/* store it in the driver field */
+	pcidev->driver_data = s;
+	pcidev->dma_mask = 0xffffffff;
+	/* put it into driver list */
+	list_add_tail(&s->devs, &devs);
+	/* increment devindex */
+	if (devindex < NR_DEVICE-1)
+		devindex++;
+	return 0;
+
+ err_dev4:
+	unregister_sound_dsp(s->dev_dac);
+ err_dev3:
+	unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+	printk(KERN_ERR "es1370: cannot register misc device\n");
+	free_irq(s->irq, s);
+ err_irq:
+	release_region(s->io, ES1370_EXTENT);
+ err_region:
+	kfree_s(s, sizeof(struct es1370_state));
+	return -1;
+}
+
+static void es1370_remove(struct pci_dev *dev)
+{
+       struct es1370_state *s = (struct es1370_state *)dev->driver_data;
+
+       if (!s)
+               return;
+       list_del(&s->devs);
+       outl(CTRL_SERR_DIS | (1 << CTRL_SH_WTSRSEL), s->io+ES1370_REG_CONTROL); /* switch everything off */
+       outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
+       synchronize_irq();
+       free_irq(s->irq, s);
+       release_region(s->io, ES1370_EXTENT);
+       unregister_sound_dsp(s->dev_audio);
+       unregister_sound_mixer(s->dev_mixer);
+       unregister_sound_dsp(s->dev_dac);
+       unregister_sound_midi(s->dev_midi);
+       kfree_s(s, sizeof(struct es1370_state));
+       dev->driver_data = NULL;
+}
+
+static const struct pci_device_id id_table[] = {
+	{ PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver es1370_driver = {
+	name: "es1370",
+	id_table: id_table,
+	probe: es1370_probe,
+	remove: es1370_remove
+};
 
+static int __init init_es1370(void)
+{
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.32 time " __TIME__ " " __DATE__ "\n");
-	while (index < NR_DEVICE && 
-	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
-		if (!RSRCISIOREGION(pcidev, 0))
-			continue;
-		if (pcidev->irq == 0) 
-			continue;
-		if (!(s = kmalloc(sizeof(struct es1370_state), GFP_KERNEL))) {
-			printk(KERN_WARNING "es1370: out of memory\n");
-			continue;
-		}
-		memset(s, 0, sizeof(struct es1370_state));
-		init_waitqueue_head(&s->dma_adc.wait);
-		init_waitqueue_head(&s->dma_dac1.wait);
-		init_waitqueue_head(&s->dma_dac2.wait);
-		init_waitqueue_head(&s->open_wait);
-		init_waitqueue_head(&s->midi.iwait);
-		init_waitqueue_head(&s->midi.owait);
-		init_MUTEX(&s->open_sem);
-		spin_lock_init(&s->lock);
-		s->magic = ES1370_MAGIC;
-		s->io = RSRCADDRESS(pcidev, 0);
-		s->irq = pcidev->irq;
-		if (check_region(s->io, ES1370_EXTENT)) {
-			printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
-			goto err_region;
-		}
-		request_region(s->io, ES1370_EXTENT, "es1370");
-		if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
-			printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
-			goto err_irq;
-		}
-		/* initialize codec registers */
-		/* note: setting CTRL_SERR_DIS is reported to break
-		 * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
-	        s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
-	        if (joystick[index]) {
-			if (check_region(0x200, JOY_EXTENT))
-				printk(KERN_ERR "es1370: io port 0x200 in use\n");
-			else
-				s->ctrl |= CTRL_JYSTK_EN;
-		}
-		if (lineout[index])
-			s->ctrl |= CTRL_XCTL0;
-		if (micbias[index])
-			s->ctrl |= CTRL_XCTL1;
-		s->sctrl = 0;
-		printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
-		       KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
-		       s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
-		       (s->ctrl & CTRL_XCTL0) ? "out" : "in",
-		       (s->ctrl & CTRL_XCTL1) ? "1" : "0");
-		/* register devices */
-		if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0)
-			goto err_dev1;
-		if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0)
-			goto err_dev2;
-		if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0)
-			goto err_dev3;
-		if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0)
-			goto err_dev4;
-		/* initialize the chips */
-		outl(s->ctrl, s->io+ES1370_REG_CONTROL);
-		outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL);
-		/* point phantom write channel to "bugbuf" */
-		outl((ES1370_REG_PHANTOM_FRAMEADR >> 8) & 15, s->io+ES1370_REG_MEMPAGE);
-		outl(virt_to_bus(bugbuf), s->io+(ES1370_REG_PHANTOM_FRAMEADR & 0xff));
-		outl(0, s->io+(ES1370_REG_PHANTOM_FRAMECNT & 0xff));
-		pci_set_master(pcidev);  /* enable bus mastering */
-		wrcodec(s, 0x16, 3); /* no RST, PD */
-		wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!!  */
-		wrcodec(s, 0x18, 0); /* recording source is mixer */
-		wrcodec(s, 0x19, s->mix.micpreamp = 1); /* turn on MIC preamp */
-		s->mix.imix = 1;
-		fs = get_fs();
-		set_fs(KERNEL_DS);
-		val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD;
-		mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-		for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-			val = initvol[i].vol;
-			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
-		}
-		set_fs(fs);
-		/* queue it for later freeing */
-		s->next = devs;
-		devs = s;
-		index++;
-		continue;
-
-	err_dev4:
-		unregister_sound_dsp(s->dev_dac);
-	err_dev3:
-		unregister_sound_mixer(s->dev_mixer);
-	err_dev2:
-		unregister_sound_dsp(s->dev_audio);
-	err_dev1:
-		printk(KERN_ERR "es1370: cannot register misc device\n");
-		free_irq(s->irq, s);
-	err_irq:
-		release_region(s->io, ES1370_EXTENT);
-	err_region:
-		kfree_s(s, sizeof(struct es1370_state));
-	}
-	if (!devs)
+	printk(KERN_INFO "es1370: version v0.33 time " __TIME__ " " __DATE__ "\n");
+	if (!pci_register_driver(&es1370_driver))
 		return -ENODEV;
-	return 0;
+        return 0;
+
 }
 
 static void __exit cleanup_es1370(void)
 {
-	struct es1370_state *s;
-
-	while ((s = devs)) {
-		devs = devs->next;
-		outl(CTRL_SERR_DIS | (1 << CTRL_SH_WTSRSEL), s->io+ES1370_REG_CONTROL); /* switch everything off */
-		outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
-		synchronize_irq();
-		free_irq(s->irq, s);
-		release_region(s->io, ES1370_EXTENT);
-		unregister_sound_dsp(s->dev_audio);
-		unregister_sound_mixer(s->dev_mixer);
-		unregister_sound_dsp(s->dev_dac);
-		unregister_sound_midi(s->dev_midi);
-		kfree_s(s, sizeof(struct es1370_state));
-	}
 	printk(KERN_INFO "es1370: unloading\n");
+	pci_unregister_driver(&es1370_driver);
 }
 
 module_init(init_es1370);
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.3.42/linux/drivers/sound/es1371.c	Fri Jan 21 18:19:17 2000
+++ linux/drivers/sound/es1371.c	Wed Feb  9 11:42:35 2000
@@ -98,6 +98,8 @@
  *                       Eric Lemar, elemar@cs.washington.edu
  *    08.01.2000   0.23  Prevent some ioctl's from returning bad count values on underrun/overrun;
  *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    07.02.2000   0.24  Use pci_alloc_consistent and pci_register_driver
+ *    07.02.2000   0.25  Use ac97_codec
  */
 
 /*****************************************************************************/
@@ -121,7 +123,7 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
-#include "ac97.h"
+#include "ac97_codec.h"
 
 /* --------------------------------------------------------------------- */
 
@@ -376,49 +378,18 @@
 
 /* --------------------------------------------------------------------- */
 
-static const char *stereo_enhancement[] __initdata = 
-{
-	"no 3D stereo enhancement",
-	"Analog Devices Phat Stereo",
-	"Creative Stereo Enhancement",
-	"National Semiconductor 3D Stereo Enhancement",
-	"YAMAHA Ymersion",
-	"BBE 3D Stereo Enhancement",
-	"Crystal Semiconductor 3D Stereo Enhancement",
-	"Qsound QXpander",
-	"Spatializer 3D Stereo Enhancement",
-	"SRS 3D Stereo Enhancement",
-	"Platform Technologies 3D Stereo Enhancement", 
-	"AKM 3D Audio",
-	"Aureal Stereo Enhancement",
-	"AZTECH  3D Enhancement",
-	"Binaura 3D Audio Enhancement",
-	"ESS Technology Stereo Enhancement",
-	"Harman International VMAx",
-	"NVidea 3D Stereo Enhancement",
-	"Philips Incredible Sound",
-	"Texas Instruments 3D Stereo Enhancement",
-	"VLSI Technology 3D Stereo Enhancement",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"SigmaTel SS3D"
-};
-
-/* --------------------------------------------------------------------- */
-
 struct es1371_state {
 	/* magic */
 	unsigned int magic;
 
-	/* we keep sb cards in a linked list */
-	struct es1371_state *next;
+	/* list of es1371 devices */
+	struct list_head devs;
+
+	/* the corresponding pci_dev structure */
+	struct pci_dev *dev;
 
 	/* soundcore stuff */
 	int dev_audio;
-	int dev_mixer;
 	int dev_dac;
 	int dev_midi;
 	
@@ -435,14 +406,8 @@
         /* debug /proc entry */
 	struct proc_dir_entry *ps;
 #endif /* ES1371_DEBUG */
-        /* mixer registers; there is no HW readback */
-	struct {
-		unsigned short codec_id;
-		unsigned int modcnt;
-#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
-		unsigned short vol[13];
-#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
-	} mix;
+
+	struct ac97_codec codec;
 
 	/* wave stuff */
 	unsigned ctrl;
@@ -456,6 +421,7 @@
 
 	struct dmabuf {
 		void *rawbuf;
+		dma_addr_t dmaaddr;
 		unsigned buforder;
 		unsigned numfrag;
 		unsigned fragshift;
@@ -490,7 +456,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct es1371_state *devs = NULL;
+static LIST_HEAD(devs);
 
 /* --------------------------------------------------------------------- */
 
@@ -707,8 +673,9 @@
 
 /* --------------------------------------------------------------------- */
 
-static void wrcodec(struct es1371_state *s, unsigned addr, unsigned data)
+static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
 {
+	struct es1371_state *s = (struct es1371_state *)codec->private_data;
 	unsigned long flags;
 	unsigned t, x;
         
@@ -721,7 +688,7 @@
         x = wait_src_ready(s);
 
         /* enable SRC state data in SRC mux */
-	outl(( x & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)) | 0x00010000,
+	outl((x & (SRC_DIS | SRC_DDAC1 | SRC_DDAC2 | SRC_DADC)) | 0x00010000,
 	     s->io+ES1371_REG_SRCONV);
 
         /* wait for not busy (state 0) first to avoid
@@ -748,8 +715,9 @@
 	spin_unlock_irqrestore(&s->lock, flags);
 }
 
-static unsigned rdcodec(struct es1371_state *s, unsigned addr)
+static u16 rdcodec(struct ac97_codec *codec, u8 addr)
 {
+	struct es1371_state *s = (struct es1371_state *)codec->private_data;
 	unsigned long flags;
 	unsigned t, x;
 
@@ -907,7 +875,7 @@
 #define DMABUF_MINORDER 1
 
 
-extern inline void dealloc_dmabuf(struct dmabuf *db)
+extern inline void dealloc_dmabuf(struct es1371_state *s, struct dmabuf *db)
 {
 	unsigned long map, mapend;
 
@@ -915,8 +883,8 @@
 		/* undo marking the pages as reserved */
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
 		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
-			clear_bit(PG_reserved, &mem_map[map].flags);	
-		free_pages((unsigned long)db->rawbuf, db->buforder);
+			clear_bit(PG_reserved, &mem_map[map].flags);
+		pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr);
 	}
 	db->rawbuf = NULL;
 	db->mapped = db->ready = 0;
@@ -933,7 +901,7 @@
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
 		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
+			if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr)))
 				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
@@ -968,7 +936,7 @@
 	db->dmasize = db->numfrag << db->fragshift;
 	memset(db->rawbuf, (fmt & ES1371_FMT_S16) ? 0 : 0x80, db->dmasize);
 	outl((reg >> 8) & 15, s->io+ES1371_REG_MEMPAGE);
-	outl(virt_to_bus(db->rawbuf), s->io+(reg & 0xff));
+	outl(db->dmaaddr, s->io+(reg & 0xff));
 	outl((db->dmasize >> 2)-1, s->io+((reg + 4) & 0xff));
 	db->ready = 1;
 	return 0;
@@ -1157,6 +1125,13 @@
 
 /* --------------------------------------------------------------------- */
 
+static loff_t es1371_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+/* --------------------------------------------------------------------- */
+
 /*
  * AC97 Mixer Register to Connections mapping of the Concert 97 board
  *
@@ -1172,435 +1147,19 @@
  * AC97_PCMOUT_VOL          Wave Output (stereo)
  */
 
-#define AC97_PESSIMISTIC
-
-/*
- * this define causes the driver to assume that all optional
- * AC97 bits are missing. This is what Ensoniq does too in their
- * Windows driver. Maybe we should one day autoprobe for these
- * bits. But anyway I have to see an AC97 codec that implements
- * one of those optional (volume) bits.
- */
-
-static const unsigned int recsrc[8] = 
-{
-	SOUND_MASK_MIC,
-	SOUND_MASK_CD,
-	SOUND_MASK_VIDEO,
-	SOUND_MASK_LINE1,
-	SOUND_MASK_LINE,
-	SOUND_MASK_VOLUME,
-	SOUND_MASK_PHONEOUT,
-	SOUND_MASK_PHONEIN
-};
-
-static const unsigned char volreg[SOUND_MIXER_NRDEVICES] = 
-{
-	/* 5 bit stereo */
-	[SOUND_MIXER_LINE] = AC97_LINEIN_VOL,
-	[SOUND_MIXER_CD] = AC97_CD_VOL,
-	[SOUND_MIXER_VIDEO] = AC97_VIDEO_VOL,
-	[SOUND_MIXER_LINE1] = AC97_AUX_VOL,
-	[SOUND_MIXER_PCM] = AC97_PCMOUT_VOL,
-	/* 6 bit stereo */
-	[SOUND_MIXER_VOLUME] = AC97_MASTER_VOL_STEREO,
-	[SOUND_MIXER_PHONEOUT] = AC97_HEADPHONE_VOL,
-	/* 6 bit mono */
-	[SOUND_MIXER_OGAIN] = AC97_MASTER_VOL_MONO,
-	[SOUND_MIXER_PHONEIN] = AC97_PHONE_VOL,
-	/* 4 bit mono but shifted by 1 */
-	[SOUND_MIXER_SPEAKER] = AC97_MASTER_TONE,
-	/* 6 bit mono + preamp */
-	[SOUND_MIXER_MIC] = AC97_MIC_VOL,
-	/* 4 bit stereo */
-	[SOUND_MIXER_RECLEV] = AC97_RECORD_GAIN,
-	/* 4 bit mono */
-	[SOUND_MIXER_IGAIN] = AC97_RECORD_GAIN_MIC
-};
-
-#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
-
-#define swab(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
-
-static int mixer_rdch(struct es1371_state *s, unsigned int ch, int *arg)
-{
-	int j;
-
-	switch (ch) {
-	case SOUND_MIXER_MIC:
-		j = rdcodec(s, AC97_MIC_VOL);
-		if (j & AC97_MUTE)
-			return put_user(0, (int *)arg);
-#ifdef AC97_PESSIMISTIC
-		return put_user(0x4949 - 0x202 * (j & 0x1f) + ((j & 0x40) ? 0x1b1b : 0), (int *)arg);
-#else /* AC97_PESSIMISTIC */
-		return put_user(0x5757 - 0x101 * ((j & 0x3f) * 5 / 4) + ((j & 0x40) ? 0x0d0d : 0), (int *)arg);
-#endif /* AC97_PESSIMISTIC */
-
-	case SOUND_MIXER_OGAIN:
-	case SOUND_MIXER_PHONEIN:
-		j = rdcodec(s, volreg[ch]);
-		if (j & AC97_MUTE)
-			return put_user(0, (int *)arg);
-#ifdef AC97_PESSIMISTIC
-		return put_user(0x6464 - 0x303 * (j & 0x1f), (int *)arg);
-#else /* AC97_PESSIMISTIC */
-		return put_user((0x6464 - 0x303 * (j & 0x3f) / 2) & 0x7f7f, (int *)arg);
-#endif /* AC97_PESSIMISTIC */
-
-	case SOUND_MIXER_PHONEOUT:
-		if (!(s->mix.codec_id & CODEC_ID_HEADPHONEOUT))
-			return -EINVAL;
-		/* fall through */
-	case SOUND_MIXER_VOLUME:
-		j = rdcodec(s, volreg[ch]);
-		if (j & AC97_MUTE)
-			return put_user(0, (int *)arg);
-#ifdef AC97_PESSIMISTIC
-		return put_user(0x6464 - (swab(j) & 0x1f1f) * 3, (int *)arg);
-#else /* AC97_PESSIMISTIC */
-		return put_user((0x6464 - (swab(j) & 0x3f3f) * 3 / 2) & 0x7f7f, (int *)arg);
-#endif /* AC97_PESSIMISTIC */
-		
-	case SOUND_MIXER_SPEAKER:
-		j = rdcodec(s, AC97_PCBEEP_VOL);
-		if (j & AC97_MUTE)
-			return put_user(0, (int *)arg);
-		return put_user(0x6464 - ((j >> 1) & 0xf) * 0x606, (int *)arg);
-		
-	case SOUND_MIXER_LINE:
-	case SOUND_MIXER_CD:
-	case SOUND_MIXER_VIDEO:
-	case SOUND_MIXER_LINE1:
-	case SOUND_MIXER_PCM:
-		j = rdcodec(s, volreg[ch]);
-		if (j & AC97_MUTE)
-			return put_user(0, (int *)arg);
-		return put_user(0x6464 - (swab(j) & 0x1f1f) * 3, (int *)arg);
-
-	case SOUND_MIXER_BASS:
-	case SOUND_MIXER_TREBLE:
-		if (!(s->mix.codec_id & CODEC_ID_BASSTREBLE))
-			return -EINVAL;
-		j = rdcodec(s, AC97_MASTER_TONE);
-		if (ch == SOUND_MIXER_BASS)
-			j >>= 8;
-		return put_user((((j & 15) * 100) / 15) * 0x101, (int *)arg);
-	
-		/* SOUND_MIXER_RECLEV and SOUND_MIXER_IGAIN specify gain */
-	case SOUND_MIXER_RECLEV:
-		j = rdcodec(s, AC97_RECORD_GAIN);
-		if (j & AC97_MUTE)
-			return put_user(0, (int *)arg);
-		return put_user((swab(j)  & 0xf0f) * 6 + 0xa0a, (int *)arg);
-		
-	case SOUND_MIXER_IGAIN:
-		if (!(s->mix.codec_id & CODEC_ID_DEDICATEDMIC))
-			return -EINVAL;
-		j = rdcodec(s, AC97_RECORD_GAIN_MIC);
-		if (j & AC97_MUTE)
-			return put_user(0, (int *)arg);
-		return put_user((j & 0xf) * 0x606 + 0xa0a, (int *)arg);
-	
-	default:
-		return -EINVAL;
-	}
-}
-
-#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
-
-static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = 
-{
-	/* 5 bit stereo */
-	[SOUND_MIXER_LINE] = 1,
-	[SOUND_MIXER_CD] = 2,
-	[SOUND_MIXER_VIDEO] = 3,
-	[SOUND_MIXER_LINE1] = 4,
-	[SOUND_MIXER_PCM] = 5,
-	/* 6 bit stereo */
-	[SOUND_MIXER_VOLUME] = 6,
-	[SOUND_MIXER_PHONEOUT] = 7,
-	/* 6 bit mono */
-	[SOUND_MIXER_OGAIN] = 8,
-	[SOUND_MIXER_PHONEIN] = 9,
-	/* 4 bit mono but shifted by 1 */
-	[SOUND_MIXER_SPEAKER] = 10,
-	/* 6 bit mono + preamp */
-	[SOUND_MIXER_MIC] = 11,
-	/* 4 bit stereo */
-	[SOUND_MIXER_RECLEV] = 12,
-	/* 4 bit mono */
-	[SOUND_MIXER_IGAIN] = 13
-};
-
-#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
-
-static int mixer_wrch(struct es1371_state *s, unsigned int ch, int val)
-{
-	int i;
-	unsigned l1, r1;
-
-	l1 = val & 0xff;
-	r1 = (val >> 8) & 0xff;
-	if (l1 > 100)
-		l1 = 100;
-	if (r1 > 100)
-		r1 = 100;
-	switch (ch) {
-	case SOUND_MIXER_LINE:
-	case SOUND_MIXER_CD:
-	case SOUND_MIXER_VIDEO:
-	case SOUND_MIXER_LINE1:
-	case SOUND_MIXER_PCM:
-		if (l1 < 7 && r1 < 7) {
-			wrcodec(s, volreg[ch], AC97_MUTE);
-			return 0;
-		}
-		if (l1 < 7)
-			l1 = 7;
-		if (r1 < 7)
-			r1 = 7;
-		wrcodec(s, volreg[ch], (((100 - l1) / 3) << 8) | ((100 - r1) / 3));
-		return 0;
-
-	case SOUND_MIXER_PHONEOUT:
-		if (!(s->mix.codec_id & CODEC_ID_HEADPHONEOUT))
-			return -EINVAL;
-		/* fall through */
-	case SOUND_MIXER_VOLUME:
-#ifdef AC97_PESSIMISTIC
-		if (l1 < 7 && r1 < 7) {
-			wrcodec(s, volreg[ch], AC97_MUTE);
-			return 0;
-		}
-		if (l1 < 7)
-			l1 = 7;
-		if (r1 < 7)
-			r1 = 7;
-		wrcodec(s, volreg[ch], (((100 - l1) / 3) << 8) | ((100 - r1) / 3));
-		return 0;
-#else /* AC97_PESSIMISTIC */
-		if (l1 < 4 && r1 < 4) {
-			wrcodec(s, volreg[ch], AC97_MUTE);
-			return 0;
-		}
-		if (l1 < 4)
-			l1 = 4;
-		if (r1 < 4)
-			r1 = 4;
-		wrcodec(s, volreg[ch], ((2 * (100 - l1) / 3) << 8) | (2 * (100 - r1) / 3));
-		return 0;
-#endif /* AC97_PESSIMISTIC */
-
-	case SOUND_MIXER_OGAIN:
-	case SOUND_MIXER_PHONEIN:
-#ifdef AC97_PESSIMISTIC
-		wrcodec(s, volreg[ch], (l1 < 7) ? AC97_MUTE : (100 - l1) / 3);
-		return 0;
-#else /* AC97_PESSIMISTIC */
-		wrcodec(s, volreg[ch], (l1 < 4) ? AC97_MUTE : (2 * (100 - l1) / 3));
-		return 0;
-#endif /* AC97_PESSIMISTIC */
-			
-	case SOUND_MIXER_SPEAKER:
-		wrcodec(s, AC97_PCBEEP_VOL, (l1 < 10) ? AC97_MUTE : ((100 - l1) / 6) << 1);
-		return 0;
-
-	case SOUND_MIXER_MIC:
-#ifdef AC97_PESSIMISTIC
-		if (l1 < 11) {
-			wrcodec(s, AC97_MIC_VOL, AC97_MUTE);
-			return 0;
-		}
-		i = 0;
-		if (l1 >= 27) {
-			l1 -= 27;
-			i = 0x40;
-		}
-		if (l1 < 11) 
-			l1 = 11;
-		wrcodec(s, AC97_MIC_VOL, ((73 - l1) / 2) | i);
-		return 0;
-#else /* AC97_PESSIMISTIC */
-		if (l1 < 9) {
-			wrcodec(s, AC97_MIC_VOL, AC97_MUTE);
-			return 0;
-		}
-		i = 0;
-		if (l1 >= 13) {
-			l1 -= 13;
-			i = 0x40;
-		}
-		if (l1 < 9) 
-			l1 = 9;
-		wrcodec(s, AC97_MIC_VOL, (((87 - l1) * 4) / 5) | i);
-		return 0;
-#endif /* AC97_PESSIMISTIC */
-		
-	case SOUND_MIXER_BASS:
-		val = ((l1 * 15) / 100) & 0xf;
-		wrcodec(s, AC97_MASTER_TONE, (rdcodec(s, AC97_MASTER_TONE) & 0x00ff) | (val << 8));
-		return 0;
-
-	case SOUND_MIXER_TREBLE:
-		val = ((l1 * 15) / 100) & 0xf;
-		wrcodec(s, AC97_MASTER_TONE, (rdcodec(s, AC97_MASTER_TONE) & 0xff00) | val);
-		return 0;
-		
-		/* SOUND_MIXER_RECLEV and SOUND_MIXER_IGAIN specify gain */
-	case SOUND_MIXER_RECLEV:
-		if (l1 < 10 || r1 < 10) {
-			wrcodec(s, AC97_RECORD_GAIN, AC97_MUTE);
-			return 0;
-		}
-		if (l1 < 10)
-			l1 = 10;
-		if (r1 < 10)
-			r1 = 10;
-		wrcodec(s, AC97_RECORD_GAIN, (((l1 - 10) / 6) << 8) | ((r1 - 10) / 6));
-		return 0;
-
-	case SOUND_MIXER_IGAIN:
-		if (!(s->mix.codec_id & CODEC_ID_DEDICATEDMIC))
-			return -EINVAL;
-		wrcodec(s, AC97_RECORD_GAIN_MIC, (l1 < 10) ? AC97_MUTE : ((l1 - 10) / 6) & 0xf);
-		return 0;
-		
-	default:
-		return -EINVAL;
-	}
-}
-
-static int mixer_ioctl(struct es1371_state *s, unsigned int cmd, unsigned long arg)
-{
-	int i, val;
-
-	VALIDATE_STATE(s);
-	if (cmd == SOUND_MIXER_PRIVATE1) {
-		if (!(s->mix.codec_id & (CODEC_ID_SEMASK << CODEC_ID_SESHIFT)))
-			return -EINVAL;
-		get_user_ret(val, (int *)arg, -EFAULT);
-		if (val & 1)
-			wrcodec(s, AC97_3D_CONTROL, ((val << 3) & 0xf00) | ((val >> 1) & 0xf));
-		val = rdcodec(s, AC97_3D_CONTROL);
-		return put_user(((val & 0xf) << 1) | ((val & 0xf00) >> 3), (int *)arg);
-	}
-        if (cmd == SOUND_MIXER_INFO) {
-		mixer_info info;
-		strncpy(info.id, "ES1371", sizeof(info.id));
-		strncpy(info.name, "Ensoniq ES1371", sizeof(info.name));
-		info.modify_counter = s->mix.modcnt;
-		if (copy_to_user((void *)arg, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == SOUND_OLD_MIXER_INFO) {
-		_old_mixer_info info;
-		strncpy(info.id, "ES1371", sizeof(info.id));
-		strncpy(info.name, "Ensoniq ES1371", sizeof(info.name));
-		if (copy_to_user((void *)arg, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, (int *)arg);
-	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
-                return -EINVAL;
-        if (_IOC_DIR(cmd) == _IOC_READ) {
-                switch (_IOC_NR(cmd)) {
-                case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-			return put_user(recsrc[rdcodec(s, AC97_RECORD_SELECT) & 7], (int *)arg);
-			
-                case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
-			return put_user(SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_VIDEO |
-					SOUND_MASK_LINE1 | SOUND_MASK_PCM | SOUND_MASK_VOLUME |
-					SOUND_MASK_OGAIN | SOUND_MASK_PHONEIN | SOUND_MASK_SPEAKER |
-					SOUND_MASK_MIC | SOUND_MASK_RECLEV |
-					((s->mix.codec_id & CODEC_ID_BASSTREBLE) ? (SOUND_MASK_BASS | SOUND_MASK_TREBLE) : 0) |
-					((s->mix.codec_id & CODEC_ID_HEADPHONEOUT) ? SOUND_MASK_PHONEOUT : 0) |
-					((s->mix.codec_id & CODEC_ID_DEDICATEDMIC) ? SOUND_MASK_IGAIN : 0), (int *)arg);
-
-		case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
-			return put_user(SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VIDEO | SOUND_MASK_LINE1 |
-					SOUND_MASK_LINE | SOUND_MASK_VOLUME | SOUND_MASK_PHONEOUT |
-					SOUND_MASK_PHONEIN, (int *)arg);
-
-                case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
-			return put_user(SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_VIDEO |
-					SOUND_MASK_LINE1 | SOUND_MASK_PCM | SOUND_MASK_VOLUME |
-					SOUND_MASK_PHONEOUT | SOUND_MASK_RECLEV, (int *)arg);
-
-                case SOUND_MIXER_CAPS:
-			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
-
-		default:
-			i = _IOC_NR(cmd);
-                        if (i >= SOUND_MIXER_NRDEVICES)
-                                return -EINVAL;
-#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
-			return mixer_rdch(s, i, (int *)arg);
-#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
-			if (!volidx[i])
-				return -EINVAL;
-			return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
-#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
-		}
-	}
-        if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
-		return -EINVAL;
-	s->mix.modcnt++;
-	switch (_IOC_NR(cmd)) {
-	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-                get_user_ret(val, (int *)arg, -EFAULT);
-                i = hweight32(val);
-                if (i == 0)
-                        return 0; /*val = mixer_recmask(s);*/
-                else if (i > 1) 
-                        val &= ~recsrc[rdcodec(s, AC97_RECORD_SELECT) & 7];
-                for (i = 0; i < 8; i++) {
-			if (val & recsrc[i]) {
-				wrcodec(s, AC97_RECORD_SELECT, 0x101 * i);
-				return 0;
-			}
-		}
-                return 0;
-
-	default:
-		i = _IOC_NR(cmd);
-		if (i >= SOUND_MIXER_NRDEVICES)
-			return -EINVAL;
-		get_user_ret(val, (int *)arg, -EFAULT);
-		if (mixer_wrch(s, i, val))
-			return -EINVAL;
-#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
-		return mixer_rdch(s, i, (int *)arg);
-#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
-		if (!volidx[i])
-			return -EINVAL;
-		s->mix.vol[volidx[i]-1] = val;
-		return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
-#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
-	}
-}
-
-/* --------------------------------------------------------------------- */
-
-static loff_t es1371_llseek(struct file *file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-
-/* --------------------------------------------------------------------- */
-
 static int es1371_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
-	struct es1371_state *s = devs;
+	struct list_head *list;
+	struct es1371_state *s;
 
-	while (s && s->dev_mixer != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1371_state, devs);
+		if (s->codec.dev_mixer == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	MOD_INC_USE_COUNT;
@@ -1618,23 +1177,15 @@
 
 static int es1371_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	return mixer_ioctl((struct es1371_state *)file->private_data, cmd, arg);
+	struct ac97_codec *codec = &((struct es1371_state *)file->private_data)->codec;
+	return codec->mixer_ioctl(codec, cmd, arg);
 }
 
 static /*const*/ struct file_operations es1371_mixer_fops = {
-	&es1371_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&es1371_ioctl_mixdev,
-	NULL,  /* mmap */
-	&es1371_open_mixdev,
-	NULL,	/* flush */
-	&es1371_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1371_llseek,
+	ioctl:		es1371_ioctl_mixdev,
+	open:		es1371_open_mixdev,
+	release:	es1371_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2223,20 +1774,24 @@
                 return -EINVAL;
 		
 	}
-	return mixer_ioctl(s, cmd, arg);
+	return s->codec.mixer_ioctl(&s->codec, cmd, arg);
 }
 
 static int es1371_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1371_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1371_state *s;
 
-	while (s && ((s->dev_audio ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1371_state, devs);
+		if (!((s->dev_audio ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2297,11 +1852,11 @@
 	down(&s->open_sem);
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac2(s);
-		dealloc_dmabuf(&s->dma_dac2);
+		dealloc_dmabuf(s, &s->dma_dac2);
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(s);
-		dealloc_dmabuf(&s->dma_adc);
+		dealloc_dmabuf(s, &s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
 	up(&s->open_sem);
@@ -2311,19 +1866,14 @@
 }
 
 static /*const*/ struct file_operations es1371_audio_fops = {
-	&es1371_llseek,
-	&es1371_read,
-	&es1371_write,
-	NULL,  /* readdir */
-	&es1371_poll,
-	&es1371_ioctl,
-	&es1371_mmap,
-	&es1371_open,
-	NULL,	/* flush */
-	&es1371_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1371_llseek,
+	read:		es1371_read,
+	write:		es1371_write,
+	poll:		es1371_poll,
+	ioctl:		es1371_ioctl,
+	mmap:		es1371_mmap,
+	open:		es1371_open,
+	release:	es1371_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2626,20 +2176,24 @@
                 return -EINVAL;
 		
 	}
-	return mixer_ioctl(s, cmd, arg);
+	return s->codec.mixer_ioctl(&s->codec, cmd, arg);
 }
 
 static int es1371_open_dac(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1371_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1371_state *s;
 
-	while (s && ((s->dev_dac ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1371_state, devs);
+		if (!((s->dev_dac ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
        	/* we allow opening with O_RDWR, most programs do it although they will only write */
 #if 0
@@ -2690,7 +2244,7 @@
 	drain_dac1(s, file->f_flags & O_NONBLOCK);
 	down(&s->open_sem);
 	stop_dac1(s);
-	dealloc_dmabuf(&s->dma_dac1);
+	dealloc_dmabuf(s, &s->dma_dac1);
 	s->open_mode &= ~FMODE_DAC;
 	up(&s->open_sem);
 	wake_up(&s->open_wait);
@@ -2699,19 +2253,13 @@
 }
 
 static /*const*/ struct file_operations es1371_dac_fops = {
-	&es1371_llseek,
-	NULL,  /* read */
-	&es1371_write_dac,
-	NULL,  /* readdir */
-	&es1371_poll_dac,
-	&es1371_ioctl_dac,
-	&es1371_mmap_dac,
-	&es1371_open_dac,
-	NULL,	/* flush */
-	&es1371_release_dac,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1371_llseek,
+	write:		es1371_write_dac,
+	poll:		es1371_poll_dac,
+	ioctl:		es1371_ioctl_dac,
+	mmap:		es1371_mmap_dac,
+	open:		es1371_open_dac,
+	release:	es1371_release_dac,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2874,13 +2422,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1371_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1371_state *s;
 
-	while (s && s->dev_midi != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1371_state, devs);
+		if (s->dev_midi == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2970,45 +2522,38 @@
 }
 
 static /*const*/ struct file_operations es1371_midi_fops = {
-	&es1371_llseek,
-	&es1371_midi_read,
-	&es1371_midi_write,
-	NULL,  /* readdir */
-	&es1371_midi_poll,
-	NULL,  /* ioctl */
-	NULL,  /* mmap */
-	&es1371_midi_open,
-	NULL,	/* flush */
-	&es1371_midi_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1371_llseek,
+	read:		es1371_midi_read,
+	write:		es1371_midi_write,
+	poll:		es1371_midi_poll,
+	open:		es1371_midi_open,
+	release:	es1371_midi_release,
 };
 
 /* --------------------------------------------------------------------- */
 
 /*
  * for debugging purposes, we'll create a proc device that dumps the
- *  CODEC chipstate
+ * CODEC chipstate
  */
 
 #ifdef ES1371_DEBUG
 static int proc_es1371_dump (char *buf, char **start, off_t fpos, int length, int *eof, void *data)
 {
-        int len = 0;
-        
-        struct es1371_state *s = devs;
-        int cnt;
+	struct es1371_state *s;
+        int cnt, len = 0;
 
+	if (list_empty(&devs))
+		return 0;
+	s = list_entry(devs.next, struct es1371_state, devs);
         /* print out header */
         len += sprintf(buf + len, "\t\tCreative ES137x Debug Dump-o-matic\n");
 
         /* print out CODEC state */
         len += sprintf (buf + len, "AC97 CODEC state\n");
-        
-        for (cnt=0; cnt <= 0x7e; cnt = cnt +2)
-                len+= sprintf (buf + len, "reg:0x%02x  val:0x%04x\n", cnt, rdcodec(s , cnt));
-                
+	for (cnt=0; cnt <= 0x7e; cnt = cnt +2)
+                len+= sprintf (buf + len, "reg:0x%02x  val:0x%04x\n", cnt, rdcodec(&s->codec, cnt));
+
         if (fpos >=len){
                 *start = buf;
                 *eof =1;
@@ -3025,12 +2570,14 @@
 
 /* --------------------------------------------------------------------- */
 
-/* maximum number of devices */
+/* maximum number of devices; only used for command line params */
 #define NR_DEVICE 5
 
 static int joystick[NR_DEVICE] = { 0, };
 static int spdif[NR_DEVICE] = { 0, };
 
+static unsigned int devindex = 0;
+
 MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
 MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
 MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i");
@@ -3064,12 +2611,11 @@
 				 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
 
-static int __init probe_chip(struct pci_dev *pcidev, int index)
+static int es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1371_state *s;
 	mm_segment_t fs;
-	int i, val, val2;
-	unsigned char id[4];
+	int i, val;
 	unsigned long tmo;
 	signed long tmo2;
 	unsigned int cssr;
@@ -3092,28 +2638,33 @@
 	init_MUTEX(&s->open_sem);
 	spin_lock_init(&s->lock);
 	s->magic = ES1371_MAGIC;
+	s->dev = pcidev;
 	s->io = RSRCADDRESS(pcidev, 0);
 	s->irq = pcidev->irq;
 	s->vendor = pcidev->vendor;
 	s->device = pcidev->device;
 	pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+	s->codec.private_data = s;
+	s->codec.id = 0;
+	s->codec.codec_read = rdcodec;
+	s->codec.codec_write = wrcodec;
 	printk(KERN_INFO "es1371: found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
 	       s->vendor, s->device, s->rev);
-	if (check_region(s->io, ES1371_EXTENT)) {
+	if (!request_region(s->io, ES1371_EXTENT, "es1371")) {
 		printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
 		goto err_region;
 	}
-	request_region(s->io, ES1371_EXTENT, "es1371");
 	if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
 		printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
 		goto err_irq;
 	}
+	pci_enable_device(pcidev);
 	printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
-	       KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
+	       KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[devindex]);
 	/* register devices */
 	if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
 		goto err_dev1;
-	if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+	if ((s->codec.dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
 		goto err_dev2;
 	if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
 		goto err_dev3;
@@ -3126,17 +2677,17 @@
 	
 	/* initialize codec registers */
 	s->ctrl = 0;
-	if ((joystick[index] & ~0x18) == 0x200) {
-		if (check_region(joystick[index], JOY_EXTENT))
-			printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
+	if ((joystick[devindex] & ~0x18) == 0x200) {
+		if (check_region(joystick[devindex], JOY_EXTENT))
+			printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[devindex]);
 		else {
-			s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+			s->ctrl |= CTRL_JYSTK_EN | (((joystick[devindex] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
 		}
 	}
 	s->sctrl = 0;
 	cssr = 0;
 	/* check to see if s/pdif mode is being requested */
-	if (spdif[index]) {
+	if (spdif[devindex]) {
 		if (s->rev >= 4) {
 			printk(KERN_INFO "es1371: enabling S/PDIF output\n");
 			cssr |= STAT_EN_SPDIF;
@@ -3173,68 +2724,34 @@
 	/* init the sample rate converter */
 	src_init(s);
 	/* codec init */
-	wrcodec(s, AC97_RESET, 0); /* reset codec */
-	s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
-	val = rdcodec(s, AC97_VENDOR_ID1);
-	val2 = rdcodec(s, AC97_VENDOR_ID2);
-	id[0] = val >> 8;
-	id[1] = val;
-	id[2] = val2 >> 8;
-	id[3] = 0;
-	if (id[0] <= ' ' || id[0] > 0x7f)
-		id[0] = ' ';
-	if (id[1] <= ' ' || id[1] > 0x7f)
-		id[1] = ' ';
-	if (id[2] <= ' ' || id[2] > 0x7f)
-		id[2] = ' ';
-	printk(KERN_INFO "es1371: codec vendor %s (0x%04x%02x) revision %d (0x%02x)\n", 
-	       id, val & 0xffff, (val2 >> 8) & 0xff, val2 & 0xff, val2 & 0xff);
-	printk(KERN_INFO "es1371: codec features");
-	if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
-		printk(" dedicated MIC PCM in");
-	if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
-		printk(" Modem Line Codec");
-	if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
-		printk(" Bass & Treble");
-	if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
-		printk(" Simulated Stereo");
-	if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
-		printk(" Headphone out");
-	if (s->mix.codec_id & CODEC_ID_LOUDNESS)
-		printk(" Loudness");
-	if (s->mix.codec_id & CODEC_ID_18BITDAC)
-		printk(" 18bit DAC");
-	if (s->mix.codec_id & CODEC_ID_20BITDAC)
-		printk(" 20bit DAC");
-	if (s->mix.codec_id & CODEC_ID_18BITADC)
-		printk(" 18bit ADC");
-	if (s->mix.codec_id & CODEC_ID_20BITADC)
-		printk(" 20bit ADC");
-	printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
-	val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
-	printk(KERN_INFO "es1371: stereo enhancement: %s\n", 
-	       (val <= 26 && stereo_enhancement[val]) ? stereo_enhancement[val] : "unknown");
-
+	if (!ac97_probe_codec(&s->codec))
+		goto err_dev4;
+	/* set default values */
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	val = SOUND_MASK_LINE;
-	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+	s->codec.mixer_ioctl(&s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
 	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
 		val = initvol[i].vol;
-		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+		s->codec.mixer_ioctl(&s->codec, initvol[i].mixch, (unsigned long)&val);
 	}
 	set_fs(fs);
 	/* turn on S/PDIF output driver if requested */
 	outl(cssr, s->io+ES1371_REG_STATUS);
-	/* queue it for later freeing */
-	s->next = devs;
-	devs = s;
+	/* store it in the driver field */
+	pcidev->driver_data = s;
+	pcidev->dma_mask = 0xffffffff;
+	/* put it into driver list */
+	list_add_tail(&s->devs, &devs);
+	/* increment devindex */
+	if (devindex < NR_DEVICE-1)
+		devindex++;
        	return 0;
 
  err_dev4:
 	unregister_sound_dsp(s->dev_dac);
  err_dev3:
-	unregister_sound_mixer(s->dev_mixer);
+	unregister_sound_mixer(s->codec.dev_mixer);
  err_dev2:
 	unregister_sound_dsp(s->dev_audio);
  err_dev1:
@@ -3247,55 +2764,60 @@
 	return -1;
 }
 
+static void es1371_remove(struct pci_dev *dev)
+{
+	struct es1371_state *s = (struct es1371_state *)dev->driver_data;
+
+	if (!s)
+		return;
+	list_del(&s->devs);
+#ifdef ES1371_DEBUG
+	if (s->ps)
+		remove_proc_entry("es1371", NULL);
+#endif /* ES1371_DEBUG */
+	outl(0, s->io+ES1371_REG_CONTROL); /* switch everything off */
+	outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
+	synchronize_irq();
+	free_irq(s->irq, s);
+	release_region(s->io, ES1371_EXTENT);
+	unregister_sound_dsp(s->dev_audio);
+	unregister_sound_mixer(s->codec.dev_mixer);
+	unregister_sound_dsp(s->dev_dac);
+	unregister_sound_midi(s->dev_midi);
+	kfree_s(s, sizeof(struct es1371_state));
+	dev->driver_data = NULL;
+}
+
+static const struct pci_device_id id_table[] = {
+	{ PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_CT5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ PCI_VENDOR_ID_ECTIVA, PCI_DEVICE_ID_ECTIVA_EV1938, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver es1371_driver = {
+	name: "es1371",
+	id_table: id_table,
+	probe: es1371_probe,
+	remove: es1371_remove
+};
 
 static int __init init_es1371(void)
 {
-	struct pci_dev *pcidev = NULL;
-	int index = 0;
-
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.23 time " __TIME__ " " __DATE__ "\n");
-	while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))) {
-		if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
-			if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
-			    pcidev->device != PCI_DEVICE_ID_ENSONIQ_CT5880)
-				continue;
-		} else if (pcidev->vendor == PCI_VENDOR_ID_ECTIVA) {
-			if (pcidev->device != PCI_DEVICE_ID_ECTIVA_EV1938)
-				continue;
-		} else
-			continue;
-		if (!probe_chip(pcidev, index))
-			index++;
-	}
-	if (!devs)
+	printk(KERN_INFO "es1371: version v0.25 time " __TIME__ " " __DATE__ "\n");
+	if (!pci_register_driver(&es1371_driver))
 		return -ENODEV;
 	return 0;
 }
 
 static void __exit cleanup_es1371(void)
 {
-	struct es1371_state *s;
-
-	while ((s = devs)) {
-		devs = devs->next;
-#ifdef ES1371_DEBUG
-		if (s->ps)
-			remove_proc_entry("es1371", NULL);
-#endif /* ES1371_DEBUG */
-		outl(0, s->io+ES1371_REG_CONTROL); /* switch everything off */
-		outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
-		synchronize_irq();
-		free_irq(s->irq, s);
-		release_region(s->io, ES1371_EXTENT);
-		unregister_sound_dsp(s->dev_audio);
-		unregister_sound_mixer(s->dev_mixer);
-		unregister_sound_dsp(s->dev_dac);
-		unregister_sound_midi(s->dev_midi);
-		kfree_s(s, sizeof(struct es1371_state));
-	}
 	printk(KERN_INFO "es1371: unloading\n");
+	pci_unregister_driver(&es1371_driver);
 }
 
 module_init(init_es1371);
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.3.42/linux/drivers/sound/esssolo1.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sound/esssolo1.c	Wed Feb  9 11:42:35 2000
@@ -66,12 +66,12 @@
  *    12.01.2000   0.12  Prevent some ioctl's from returning bad count values on underrun/overrun;
  *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
  *                       Integrated (aka redid 8-)) APM support patch by Zach Brown
+ *    07.02.2000   0.13  Use pci_alloc_consistent and pci_register_driver
  *
  */
 
 /*****************************************************************************/
       
-#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -83,7 +83,7 @@
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
-#include <linux/apm_bios.h>
+#include <linux/pm.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
@@ -137,11 +137,11 @@
 	/* magic */
 	unsigned int magic;
 
-	/* we keep the cards in a linked list */
-	struct solo1_state *next;
+	/* list of esssolo1 devices */
+	struct list_head devs;
 	
-	/* pcidev is needed to turn off the DDMA controller at driver shutdown */
-	struct pci_dev *pcidev;
+	/* the corresponding pci_dev structure */
+	struct pci_dev *dev;
 
 	/* soundcore stuff */
 	int dev_audio;
@@ -175,6 +175,7 @@
 
 	struct dmabuf {
 		void *rawbuf;
+		dma_addr_t dmaaddr;
 		unsigned buforder;
 		unsigned numfrag;
 		unsigned fragshift;
@@ -210,7 +211,7 @@
 
 /* --------------------------------------------------------------------- */
 
-struct solo1_state *devs = NULL;
+static LIST_HEAD(devs);
 
 /* --------------------------------------------------------------------- */
 
@@ -396,7 +397,7 @@
 #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-extern inline void dealloc_dmabuf(struct dmabuf *db)
+extern inline void dealloc_dmabuf(struct solo1_state *s, struct dmabuf *db)
 {
 	unsigned long map, mapend;
 
@@ -405,13 +406,13 @@
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
 		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
 			clear_bit(PG_reserved, &mem_map[map].flags);	
-		free_pages((unsigned long)db->rawbuf, db->buforder);
+		pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr);
 	}
 	db->rawbuf = NULL;
 	db->mapped = db->ready = 0;
 }
 
-static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db, int gfp_mask)
+static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db, unsigned long dmamask)
 {
 	int order;
 	unsigned bytespersec;
@@ -421,19 +422,12 @@
 	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
+		s->dev->dma_mask = dmamask;
                 for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-                        if ((db->rawbuf = (void *)__get_free_pages(gfp_mask, order)))
+			if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr)))
 				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
-		/* work around a problem of the alpha port */
-		if ((gfp_mask & GFP_DMA) && (virt_to_bus(db->rawbuf) & (~0xffffffUL))) {
-			printk(KERN_ERR "solo1: requested DMA buffer below 16M but got 0x%lx, Alpha bug?\n", 
-			       (unsigned long)virt_to_bus(db->rawbuf));
-			kfree(db->rawbuf);
-			db->rawbuf = NULL;
-			return -ENOMEM;
-		}
 		db->buforder = order;
 		/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
@@ -475,9 +469,9 @@
 	int c;
 
 	stop_adc(s);
-	if ((c = prog_dmabuf(s, &s->dma_adc, GFP_KERNEL | GFP_DMA)))
+	if ((c = prog_dmabuf(s, &s->dma_adc, 0xffffff)))
 		return c;
-	va = virt_to_bus(s->dma_adc.rawbuf);
+	va = s->dma_adc.dmaaddr;
 	if ((va & ~((1<<24)-1)))
 		panic("solo1: buffer above 16M boundary");
 	outb(0, s->ddmabase+0xd);  /* clear */
@@ -500,10 +494,10 @@
 	int c;
 
 	stop_dac(s);
-	if ((c = prog_dmabuf(s, &s->dma_dac, GFP_KERNEL)))
+	if ((c = prog_dmabuf(s, &s->dma_dac, 0xffffffff)))
 		return c;
 	memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0 : 0x80, s->dma_dac.dmasize); /* almost correct for U16 */
-	va = virt_to_bus(s->dma_dac.rawbuf);
+	va = s->dma_dac.dmaaddr;
 	if ((va ^ (va + s->dma_dac.dmasize - 1)) & ~((1<<20)-1))
 		panic("solo1: buffer crosses 1M boundary");
 	outl(va, s->iobase);
@@ -900,12 +894,16 @@
 static int solo1_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
-	struct solo1_state *s = devs;
+	struct list_head *list;
+	struct solo1_state *s;
 
-	while (s && s->dev_mixer != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct solo1_state, devs);
+		if (s->dev_mixer == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	MOD_INC_USE_COUNT;
@@ -915,7 +913,7 @@
 static int solo1_release_mixdev(struct inode *inode, struct file *file)
 {
 	struct solo1_state *s = (struct solo1_state *)file->private_data;
-	
+
 	VALIDATE_STATE(s);
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -927,19 +925,10 @@
 }
 
 static /*const*/ struct file_operations solo1_mixer_fops = {
-	&solo1_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&solo1_ioctl_mixdev,
-	NULL,  /* mmap */
-	&solo1_open_mixdev,
-	NULL,  /* flush */
-	&solo1_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		solo1_llseek,
+	ioctl:		solo1_ioctl_mixdev,
+	open:		solo1_open_mixdev,
+	release:	solo1_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -1522,13 +1511,13 @@
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac(s);
 		outb(0, s->iobase+6);  /* disable DMA */
-		dealloc_dmabuf(&s->dma_dac);
+		dealloc_dmabuf(s, &s->dma_dac);
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(s);
 		outb(1, s->ddmabase+0xf); /* mask DMA channel */
 		outb(0, s->ddmabase+0xd); /* DMA master clear */
-		dealloc_dmabuf(&s->dma_adc);
+		dealloc_dmabuf(s, &s->dma_adc);
 	}
 	s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
 	wake_up(&s->open_wait);
@@ -1541,12 +1530,16 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct solo1_state *s = devs;
-
-	while (s && ((s->dev_audio ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	struct list_head *list;
+	struct solo1_state *s;
+	
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct solo1_state, devs);
+		if (!((s->dev_audio ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -1581,19 +1574,14 @@
 }
 
 static /*const*/ struct file_operations solo1_audio_fops = {
-	&solo1_llseek,
-	&solo1_read,
-	&solo1_write,
-	NULL,  /* readdir */
-	&solo1_poll,
-	&solo1_ioctl,
-	&solo1_mmap,
-	&solo1_open,
-	NULL,  /* flush */
-	&solo1_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		solo1_llseek,
+	read:		solo1_read,
+	write:		solo1_write,
+	poll:		solo1_poll,
+	ioctl:		solo1_ioctl,
+	mmap:		solo1_mmap,
+	open:		solo1_open,
+	release:	solo1_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -1821,13 +1809,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct solo1_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct solo1_state *s;
 
-	while (s && s->dev_midi != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct solo1_state, devs);
+		if (s->dev_midi == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -1923,19 +1915,12 @@
 }
 
 static /*const*/ struct file_operations solo1_midi_fops = {
-	&solo1_llseek,
-	&solo1_midi_read,
-	&solo1_midi_write,
-	NULL,  /* readdir */
-	&solo1_midi_poll,
-	NULL,  /* ioctl */
-	NULL,  /* mmap */
-	&solo1_midi_open,
-	NULL,  /* flush */
-	&solo1_midi_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		solo1_llseek,
+	read:		solo1_midi_read,
+	write:		solo1_midi_write,
+	poll:		solo1_midi_poll,
+	open:		solo1_midi_open,
+	release:	solo1_midi_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2041,12 +2026,16 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct solo1_state *s = devs;
+	struct list_head *list;
+	struct solo1_state *s;
 
-	while (s && s->dev_dmfm != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct solo1_state, devs);
+		if (s->dev_dmfm == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2107,28 +2096,14 @@
 }
 
 static /*const*/ struct file_operations solo1_dmfm_fops = {
-	&solo1_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&solo1_dmfm_ioctl,
-	NULL,  /* mmap */
-	&solo1_dmfm_open,
-	NULL,  /* flush */
-	&solo1_dmfm_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		solo1_llseek,
+	ioctl:		solo1_dmfm_ioctl,
+	open:		solo1_dmfm_open,
+	release:	solo1_dmfm_release,
 };
 
 /* --------------------------------------------------------------------- */
 
-/* maximum number of devices */
-#define NR_DEVICE 5
-
-/* --------------------------------------------------------------------- */
-
 static struct initvol {
 	int mixch;
 	int vol;
@@ -2147,7 +2122,7 @@
 
 static int setup_solo1(struct solo1_state *s)
 {
-	struct pci_dev *pcidev = s->pcidev;
+	struct pci_dev *pcidev = s->dev;
 	mm_segment_t fs;
 	int i, val;
 
@@ -2187,141 +2162,185 @@
 	return 0;
 }
 
-#ifdef CONFIG_APM
-
-static int solo1_apm_callback(apm_event_t event)
+static int solo1_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-	struct solo1_state *s;
-
-	switch(event) {
-	case APM_NORMAL_RESUME:
-	case APM_CRITICAL_RESUME:
-	case APM_STANDBY_RESUME:
-		for(s = devs ; s ; s = s->next)
+	struct solo1_state *s = (struct solo1_state*) dev->data;
+	if (s) {
+		switch(rqst) {
+		case PM_RESUME:
 			setup_solo1(s);
-		break;
+			break;
 
-		default: 
-			for(s = devs ; s ; s = s->next) {
-				outb(0, s->iobase+6);
-				/* DMA master clear */
-				outb(0, s->ddmabase+0xd); 
-				/* reset sequencer and FIFO */
-				outb(3, s->sbbase+6); 
-				/* turn off DDMA controller address space */
-				pci_write_config_word(s->pcidev, 0x60, 0); 
-			}
+		case PM_SUSPEND:
+			outb(0, s->iobase+6);
+			/* DMA master clear */
+			outb(0, s->ddmabase+0xd); 
+			/* reset sequencer and FIFO */
+			outb(3, s->sbbase+6); 
+			/* turn off DDMA controller address space */
+			pci_write_config_word(s->dev, 0x60, 0); 
+			break;
+		}
 	}
 	return 0;
 }
 
-#endif
-
 
 #define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
 				 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
 
-
-static int __init init_solo1(void)
+static int solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct solo1_state *s;
-	struct pci_dev *pcidev = NULL;
-	int index = 0;
+	struct pm_dev *pmdev;
 
-	if (!pci_present())   /* No PCI bus in this machine! */
-		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.12 time " __TIME__ " " __DATE__ "\n");
-	while (index < NR_DEVICE && 
-	       (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
-		if (!RSRCISIOREGION(pcidev, 0) ||
-		    !RSRCISIOREGION(pcidev, 1) ||
-		    !RSRCISIOREGION(pcidev, 2) ||
-		    !RSRCISIOREGION(pcidev, 3))
-			continue;
-		if (pcidev->irq == 0)
-			continue;
-		if (!(s = kmalloc(sizeof(struct solo1_state), GFP_KERNEL))) {
-			printk(KERN_WARNING "solo1: out of memory\n");
-			continue;
-		}
-		memset(s, 0, sizeof(struct solo1_state));
-		init_waitqueue_head(&s->dma_adc.wait);
-		init_waitqueue_head(&s->dma_dac.wait);
-		init_waitqueue_head(&s->open_wait);
-		init_waitqueue_head(&s->midi.iwait);
-		init_waitqueue_head(&s->midi.owait);
-		init_MUTEX(&s->open_sem);
-		spin_lock_init(&s->lock);
-		s->magic = SOLO1_MAGIC;
-		s->pcidev = pcidev;
-		s->iobase = RSRCADDRESS(pcidev, 0);
-		s->sbbase = RSRCADDRESS(pcidev, 1);
-		s->vcbase = RSRCADDRESS(pcidev, 2);
-		s->ddmabase = s->vcbase + DDMABASE_OFFSET;
-		s->mpubase = RSRCADDRESS(pcidev, 3);
-		s->gpbase = RSRCADDRESS(pcidev, 4);
-		s->irq = pcidev->irq;
-		if (check_region(s->iobase, IOBASE_EXTENT) ||
-		    check_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT) ||
-		    check_region(s->ddmabase, DDMABASE_EXTENT) ||
-		    check_region(s->mpubase, MPUBASE_EXTENT)) {
-			printk(KERN_ERR "solo1: io ports in use\n");
-			goto err_region;
-		}
-		request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1");
-		request_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT, "ESS Solo1");
-		request_region(s->ddmabase, DDMABASE_EXTENT, "ESS Solo1");
-		request_region(s->mpubase, MPUBASE_EXTENT, "ESS Solo1");
-		if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) {
-			printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
-			goto err_irq;
-		}
-		printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase);
-
-		printk(KERN_INFO "solo1: joystick port at %#lx\n", s->gpbase+1);
-
-		/* register devices */
-		if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0)
-			goto err_dev1;
-		if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0)
-			goto err_dev2;
-		if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0)
-			goto err_dev3;
-		if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0)
-			goto err_dev4;
-		if (setup_solo1(s))
-			goto err;
-		/* queue it for later freeing */
-		s->next = devs;
-		devs = s;
-		index++;
-		continue;
-
-	err:
-		unregister_sound_dsp(s->dev_dmfm);
-	err_dev4:
-		unregister_sound_dsp(s->dev_midi);
-	err_dev3:
-		unregister_sound_mixer(s->dev_mixer);
-	err_dev2:
-		unregister_sound_dsp(s->dev_audio);
-	err_dev1:
-		printk(KERN_ERR "solo1: initialisation error\n");
-		free_irq(s->irq, s);
-	err_irq:
-		release_region(s->iobase, IOBASE_EXTENT);
-		release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
-		release_region(s->ddmabase, DDMABASE_EXTENT);
-		release_region(s->mpubase, MPUBASE_EXTENT);
-	err_region:
-		kfree_s(s, sizeof(struct solo1_state));
+	if (!RSRCISIOREGION(pcidev, 0) ||
+	    !RSRCISIOREGION(pcidev, 1) ||
+	    !RSRCISIOREGION(pcidev, 2) ||
+	    !RSRCISIOREGION(pcidev, 3))
+		return -1;
+	if (pcidev->irq == 0)
+		return -1;
+	if (!(s = kmalloc(sizeof(struct solo1_state), GFP_KERNEL))) {
+		printk(KERN_WARNING "solo1: out of memory\n");
+		return -1;
 	}
-	if (!devs)
+	memset(s, 0, sizeof(struct solo1_state));
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_waitqueue_head(&s->midi.iwait);
+	init_waitqueue_head(&s->midi.owait);
+	init_MUTEX(&s->open_sem);
+	spin_lock_init(&s->lock);
+	s->magic = SOLO1_MAGIC;
+	s->dev = pcidev;
+	s->iobase = RSRCADDRESS(pcidev, 0);
+	s->sbbase = RSRCADDRESS(pcidev, 1);
+	s->vcbase = RSRCADDRESS(pcidev, 2);
+	s->ddmabase = s->vcbase + DDMABASE_OFFSET;
+	s->mpubase = RSRCADDRESS(pcidev, 3);
+	s->gpbase = RSRCADDRESS(pcidev, 4);
+	s->irq = pcidev->irq;
+	if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) {
+		printk(KERN_ERR "solo1: io ports in use\n");
+		goto err_region1;
+	}
+	if (!request_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT, "ESS Solo1")) {
+		printk(KERN_ERR "solo1: io ports in use\n");
+		goto err_region2;
+	}
+	if (!request_region(s->ddmabase, DDMABASE_EXTENT, "ESS Solo1")) {
+		printk(KERN_ERR "solo1: io ports in use\n");
+		goto err_region3;
+	}
+	if (!request_region(s->mpubase, MPUBASE_EXTENT, "ESS Solo1")) {
+		printk(KERN_ERR "solo1: io ports in use\n");
+		goto err_region4;
+	}
+	if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) {
+		printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
+		goto err_irq;
+	}
+	pci_enable_device(pcidev);
+	printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase);
+	printk(KERN_INFO "solo1: joystick port at %#lx\n", s->gpbase+1);
+	/* register devices */
+	if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0)
+		goto err_dev1;
+	if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0)
+		goto err_dev2;
+	if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0)
+		goto err_dev3;
+	if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0)
+		goto err_dev4;
+	if (setup_solo1(s))
+		goto err;
+	/* store it in the driver field */
+	pcidev->driver_data = s;
+	pcidev->dma_mask = 0xffffff;  /* pessimistic; play can handle 32bit addrs */
+	/* put it into driver list */
+	list_add_tail(&s->devs, &devs);
+
+	pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), solo1_pm_callback);
+	if (pmdev)
+		pmdev->data = s;
+
+	return 0;
+
+ err:
+	unregister_sound_dsp(s->dev_dmfm);
+ err_dev4:
+	unregister_sound_dsp(s->dev_midi);
+ err_dev3:
+	unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+	printk(KERN_ERR "solo1: initialisation error\n");
+	free_irq(s->irq, s);
+ err_irq:
+	release_region(s->iobase, IOBASE_EXTENT);
+ err_region4:
+	release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
+ err_region3:
+	release_region(s->ddmabase, DDMABASE_EXTENT);
+ err_region2:
+	release_region(s->mpubase, MPUBASE_EXTENT);
+ err_region1:
+	kfree_s(s, sizeof(struct solo1_state));
+	return -1;
+}
+
+static void solo1_remove(struct pci_dev *dev)
+{
+	struct solo1_state *s = (struct solo1_state *)dev->driver_data;
+	
+	if (!s)
+		return;
+	list_del(&s->devs);
+	/* stop DMA controller */
+	outb(0, s->iobase+6);
+	outb(0, s->ddmabase+0xd); /* DMA master clear */
+	outb(3, s->sbbase+6); /* reset sequencer and FIFO */
+	synchronize_irq();
+	pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */
+	free_irq(s->irq, s);
+	release_region(s->iobase, IOBASE_EXTENT);
+	release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
+	release_region(s->ddmabase, DDMABASE_EXTENT);
+	release_region(s->mpubase, MPUBASE_EXTENT);
+	unregister_sound_dsp(s->dev_audio);
+	unregister_sound_mixer(s->dev_mixer);
+	unregister_sound_midi(s->dev_midi);
+	unregister_sound_special(s->dev_dmfm);
+	kfree_s(s, sizeof(struct solo1_state));
+	dev->driver_data = NULL;
+}
+
+static const struct pci_device_id id_table[] = {
+	{ PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver solo1_driver = {
+	name: "ESS Solo1",
+	id_table: id_table,
+	probe: solo1_probe,
+	remove: solo1_remove
+};
+
+
+static int __init init_solo1(void)
+{
+	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-#ifdef CONFIG_APM
-	apm_register_callback(solo1_apm_callback);
-#endif
+	printk(KERN_INFO "solo1: version v0.13 time " __TIME__ " " __DATE__ "\n");
+	if (!pci_register_driver(&solo1_driver))
+                return -ENODEV;
 	return 0;
 }
 
@@ -2332,31 +2351,9 @@
 
 static void __exit cleanup_solo1(void)
 {
-	struct solo1_state *s;
-
-	while ((s = devs)) {
-		devs = devs->next;
-		/* stop DMA controller */
-		outb(0, s->iobase+6);
-		outb(0, s->ddmabase+0xd); /* DMA master clear */
-		outb(3, s->sbbase+6); /* reset sequencer and FIFO */
-		synchronize_irq();
-		pci_write_config_word(s->pcidev, 0x60, 0); /* turn off DDMA controller address space */
-		free_irq(s->irq, s);
-		release_region(s->iobase, IOBASE_EXTENT);
-		release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
-		release_region(s->ddmabase, DDMABASE_EXTENT);
-		release_region(s->mpubase, MPUBASE_EXTENT);
-		unregister_sound_dsp(s->dev_audio);
-		unregister_sound_mixer(s->dev_mixer);
-		unregister_sound_midi(s->dev_midi);
-		unregister_sound_special(s->dev_dmfm);
-		kfree_s(s, sizeof(struct solo1_state));
-	}
-#ifdef CONFIG_APM
-	apm_unregister_callback(solo1_apm_callback);
-#endif
 	printk(KERN_INFO "solo1: unloading\n");
+	pci_unregister_driver(&solo1_driver);
+	pm_unregister_all(solo1_pm_callback);
 }
 
 /* --------------------------------------------------------------------- */
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c
--- v2.3.42/linux/drivers/sound/maestro.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/maestro.c	Wed Feb  9 11:42:35 2000
@@ -177,7 +177,6 @@
 
 /*****************************************************************************/
 
-#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 
@@ -217,16 +216,12 @@
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-static int maestro_apm_callback(apm_event_t ae);
+#include <linux/pm.h>
+static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d);
 static int in_suspend=0;
 wait_queue_head_t suspend_queue;
 static void check_suspend(void);
 #define CHECK_SUSPEND check_suspend();
-#else
-#define CHECK_SUSPEND
-#endif
 
 #include "maestro.h"
 
@@ -390,11 +385,9 @@
 	
 	struct ess_state channels[MAX_DSPS];
 	u16 maestro_map[NR_IDRS];	/* Register map */
-#ifdef CONFIG_APM
 	/* we have to store this junk so that we can come back from a
 		suspend */
 	u16 apu_map[NR_APUS][NR_APU_REGS];	/* contents of apu regs */
-#endif
 
 	/* this locks around the physical registers on the card */
 	spinlock_t lock;
@@ -1020,10 +1013,8 @@
 			printk("BAD CHANNEL %d.\n",channel);
 		else
 			channel = s->apu[channel];
-#ifdef	CONFIG_APM
 		/* store based on real hardware apu/reg */
 		s->card->apu_map[channel][reg]=data;
-#endif
 	}
 	reg|=(channel<<4);
 	
@@ -2032,19 +2023,10 @@
 }
 
 static /*const*/ struct file_operations ess_mixer_fops = {
-	&ess_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&ess_ioctl_mixdev,
-	NULL,  /* mmap */
-	&ess_open_mixdev,
-	NULL,	/* flush */
-	&ess_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		ess_llseek,
+	ioctl:		ess_ioctl_mixdev,
+	open:		ess_open_mixdev,
+	release:	ess_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2171,9 +2153,7 @@
 				goto rec_return_free;
 			}
 			if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
-#ifdef CONFIG_APM
 				if(! in_suspend)
-#endif
 				printk(KERN_DEBUG "maestro: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
 				       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, 
 				       s->dma_adc.hwptr, s->dma_adc.swptr);
@@ -2273,9 +2253,7 @@
 				goto return_free;
 			}
 			if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
-#ifdef CONFIG_APM
 				if(! in_suspend)
-#endif
 				printk(KERN_DEBUG "maestro: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
 				       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, 
 				       s->dma_dac.hwptr, s->dma_dac.swptr);
@@ -2906,19 +2884,14 @@
 }
 
 static struct file_operations ess_audio_fops = {
-	&ess_llseek,
-	&ess_read,
-	&ess_write,
-	NULL,  /* readdir */
-	&ess_poll,
-	&ess_ioctl,
-	&ess_mmap,
-	&ess_open,
-	NULL,	/* flush */
-	&ess_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		ess_llseek,
+	read:		ess_read,
+	write:		ess_write,
+	poll:		ess_poll,
+	ioctl:		ess_ioctl,
+	mmap:		ess_mmap,
+	open:		ess_open,
+	release:	ess_release,
 };
 
 static int
@@ -3176,6 +3149,7 @@
 	int i;
 	struct ess_card *card;
 	struct ess_state *ess;
+        struct pm_dev *pmdev;
 	int num = 0;
 
 	/* don't pick up weird modem maestros */
@@ -3209,11 +3183,11 @@
 	memset(card, 0, sizeof(*card));
 	memcpy(&card->pcidev,pcidev,sizeof(card->pcidev));
 
-#ifdef CONFIG_APM
-	if (apm_register_callback(maestro_apm_callback)) {
-		printk(KERN_WARNING "maestro: apm suspend might not work.\n");
-	}
-#endif
+	pmdev = pm_register(PM_PCI_DEV,
+                            PM_PCI_ID(pcidev),
+                            maestro_pm_callback);
+        if (pmdev)
+                pmdev->data = card;
 
 	card->iobase = iobase;
 	card->card_type = card_type;
@@ -3331,9 +3305,7 @@
 		printk(KERN_WARNING "maestro: clipping dsps_order to %d\n",dsps_order);
 	}
 
-#ifdef CONFIG_APM
 	init_waitqueue_head(&suspend_queue);
-#endif
 
 	/*
 	 *	Find the ESS Maestro 2.
@@ -3382,9 +3354,8 @@
 {
 	struct ess_card *s;
 
-#ifdef CONFIG_APM
-	apm_unregister_callback(maestro_apm_callback);
-#endif
+	pm_unregister_all(maestro_pm_callback);
+
 	while ((s = devs)) {
 		int i;
 		devs = devs->next;
@@ -3406,7 +3377,6 @@
 }
 
 #endif /* MODULE */
-#ifdef CONFIG_APM
 
 void
 check_suspend(void)
@@ -3424,38 +3394,35 @@
 }
 
 static int 
-maestro_suspend(void)
+maestro_suspend(struct ess_card *card)
 {
-	struct ess_card *card;
 	unsigned long flags;
+        int i,j;
 
 	save_flags(flags);
 	cli();
 
-	for (card = devs; card ; card = card->next) {
-		int i,j;
-
-		M_printk("maestro: apm in dev %p\n",card);
+        M_printk("maestro: pm in dev %p\n",card);
 
-		for(i=0;i<NR_DSPS;i++) {
-			struct ess_state *s = &card->channels[i];
+        for(i=0;i<NR_DSPS;i++) {
+                struct ess_state *s = &card->channels[i];
 
-			if(s->dev_audio == -1)
-				continue;
+                if(s->dev_audio == -1)
+                        continue;
+                
+                M_printk("maestro: stopping apus for device %d\n",i);
+                stop_dac(s);
+                stop_adc(s);
+                for(j=0;j<6;j++) 
+                        card->apu_map[s->apu[j]][5]=apu_get_register(s,j,5);
+                
+        }
 
-			M_printk("maestro: stopping apus for device %d\n",i);
-			stop_dac(s);
-			stop_adc(s);
-			for(j=0;j<6;j++) 
-				card->apu_map[s->apu[j]][5]=apu_get_register(s,j,5);
+        /* get rid of interrupts? */
+        if( card->dsps_open > 0)
+                stop_bob(&card->channels[0]);
 
-		}
-
-		/* get rid of interrupts? */
-		if( card->dsps_open > 0)
-			stop_bob(&card->channels[0]);
-	}
-	in_suspend=1;
+        in_suspend=1;
 
 	restore_flags(flags);
 
@@ -3464,10 +3431,10 @@
 	return 0;
 }
 static int 
-maestro_resume(void)
+maestro_resume(struct ess_card *card)
 {
-	struct ess_card *card;
 	unsigned long flags;
+        int i;
 
 	save_flags(flags);
 	cli();
@@ -3475,52 +3442,45 @@
 	M_printk("maestro: resuming\n");
 
 	/* first lets just bring everything back. .*/
-	for (card = devs; card ; card = card->next) {
-		int i;
 
-		M_printk("maestro: apm in dev %p\n",card);
-
-		maestro_config(card);
-		/* need to restore the base pointers.. */ 
-		if(card->dmapages) 
-			set_base_registers(&card->channels[0],card->dmapages);
-
-		mixer_push_state(card);
+        M_printk("maestro: pm in dev %p\n",card);
 
-		for(i=0;i<NR_DSPS;i++) {
-			struct ess_state *s = &card->channels[i];
-			int chan,reg;
-
-			if(s->dev_audio == -1)
-				continue;
-
-			for(chan = 0 ; chan < 6 ; chan++) {
-				wave_set_register(s,s->apu[chan]<<3,s->apu_base[chan]);
-				for(reg = 1 ; reg < NR_APU_REGS ; reg++)  
-					apu_set_register(s,chan,reg,s->card->apu_map[s->apu[chan]][reg]);
-			}
-			for(chan = 0 ; chan < 6 ; chan++)  
-				apu_set_register(s,chan,0,s->card->apu_map[s->apu[chan]][0] & 0xFF0F);
-		}
-	}
+        maestro_config(card);
+        /* need to restore the base pointers.. */ 
+        if(card->dmapages) 
+                set_base_registers(&card->channels[0],card->dmapages);
+        
+        mixer_push_state(card);
+        
+        for(i=0;i<NR_DSPS;i++) {
+                struct ess_state *s = &card->channels[i];
+                int chan,reg;
+                
+                if(s->dev_audio == -1)
+                        continue;
+                
+                for(chan = 0 ; chan < 6 ; chan++) {
+                        wave_set_register(s,s->apu[chan]<<3,s->apu_base[chan]);
+                        for(reg = 1 ; reg < NR_APU_REGS ; reg++)  
+                                apu_set_register(s,chan,reg,s->card->apu_map[s->apu[chan]][reg]);
+                }
+                for(chan = 0 ; chan < 6 ; chan++)  
+                        apu_set_register(s,chan,0,s->card->apu_map[s->apu[chan]][0] & 0xFF0F);
+        }
 
 	/* now we flip on the music */
-	for (card = devs; card ; card = card->next) {
-		int i;
-
-		M_printk("maestro: apm in dev %p\n",card);
-
-		for(i=0;i<NR_DSPS;i++) {
-			struct ess_state *s = &card->channels[i];
+        M_printk("maestro: pm in dev %p\n",card);
 
-			/* these use the apu_mode, and can handle
-				spurious calls */
-			start_dac(s);	
-			start_adc(s);	
-		}
-		if( card->dsps_open > 0)
-			start_bob(&card->channels[0]);
-	}
+        for(i=0;i<NR_DSPS;i++) {
+                struct ess_state *s = &card->channels[i];
+                
+                /* these use the apu_mode, and can handle
+                   spurious calls */
+                start_dac(s);	
+                start_adc(s);	
+        }
+        if( card->dsps_open > 0)
+                start_bob(&card->channels[0]);
 
 	restore_flags(flags);
 
@@ -3530,22 +3490,20 @@
 }
 
 int 
-maestro_apm_callback(apm_event_t ae) {
-
-	M_printk("maestro: apm event received: 0x%x\n",ae);
-
-	switch(ae) {
-	case APM_SYS_SUSPEND: 
-	case APM_CRITICAL_SUSPEND: 
-	case APM_USER_SUSPEND: 
-		maestro_suspend();break;
-	case APM_NORMAL_RESUME: 
-	case APM_CRITICAL_RESUME: 
-	case APM_STANDBY_RESUME: 
-		maestro_resume();break;
-	default: break;
-	}
+maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) {
+        struct ess_card *card = (struct ess_card*) dev->data;
+        if (card) {
+                M_printk("maestro: pm event received: 0x%x\n", rqst);
+
+                switch (rqst) {
+                case PM_SUSPEND: 
+                        maestro_suspend(card);
+                        break;
+                case PM_RESUME: 
+                        maestro_resume(card);
+                        break;
+                }
+        }
 
 	return 0;
 }
-#endif
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.3.42/linux/drivers/sound/msnd_pinnacle.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sound/msnd_pinnacle.c	Wed Feb  9 11:42:35 2000
@@ -1122,20 +1122,11 @@
 }
 
 static struct file_operations dev_fileops = {
-	NULL,		/* llseek */
-	dev_read,	/* read */
-	dev_write,	/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	dev_ioctl,	/* ioctl */
-	NULL,		/* mmap */
-	dev_open,	/* open */
-#ifndef LINUX20
-	NULL,		/* flush */
-#endif
-	dev_release,	/* release */
-	NULL,		/* fsync */
-	NULL,		/* fasync */
+	read:		dev_read,
+	write:		dev_write,
+	ioctl:		dev_ioctl,
+	open:		dev_open,
+	release:	dev_release,
 };
 
 static int reset_dsp(void)
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/nm256_audio.c linux/drivers/sound/nm256_audio.c
--- v2.3.42/linux/drivers/sound/nm256_audio.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/nm256_audio.c	Tue Feb  8 18:49:27 2000
@@ -13,13 +13,10 @@
  * off of it; go on, I dare you.  
  */
 
-#include <linux/config.h>
 #define __NO_VERSION__
 #include <linux/pci.h>
 #include <linux/module.h>
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
+#include <linux/pm.h>
 #include "sound_config.h"
 #include "soundmodule.h"
 #include "nm256.h"
@@ -41,6 +38,7 @@
 static int nm256_releaseInterrupt (struct nm256_info *card);
 static void nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy);
 static void nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy);
+static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data);
 
 /* These belong in linux/pci.h. */
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
@@ -1037,6 +1035,7 @@
 nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
 {
     struct nm256_info *card;
+    struct pm_dev *pmdev;
     int x;
 
     card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL);
@@ -1211,50 +1210,42 @@
 
     nm256_install_mixer (card);
 
+    pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), handle_pm_event);
+    if (pmdev)
+        pmdev->data = card;
+
     return 1;
 }
 
 
-#ifdef CONFIG_APM
 /*
- * APM event handler, so the card is properly reinitialized after a power
+ * PM event handler, so the card is properly reinitialized after a power
  * event.
  */
 static int
-handle_apm_event (apm_event_t event)
+handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-    static int down = 0;
-
-    switch (event)
-	{
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-	    down++;
+    struct nm256_info *crd = (struct nm256_info*) dev->data;
+    if (crd) {
+        switch (rqst) {
+	case PM_SUSPEND:
 	    break;
-	case APM_NORMAL_RESUME:
-	case APM_CRITICAL_RESUME:
-	    if (down)
-		{
-		    struct nm256_info *crd;
-
-		    down = 0;
-		    for (crd = nmcard_list;  crd != NULL; crd = crd->next_card)
-			{
-			    int playing = crd->playing;
-			    nm256_full_reset (crd);
-			    /*
-			     * A little ugly, but that's ok; pretend the
-			     * block we were playing is done. 
-			     */
-			    if (playing)
-				DMAbuf_outputintr (crd->dev_for_play, 1);
-			}
-		}
+	case PM_RESUME:
+            {
+                int playing = crd->playing;
+                nm256_full_reset (crd);
+                /*
+                 * A little ugly, but that's ok; pretend the
+                 * block we were playing is done. 
+                 */
+                if (playing)
+                    DMAbuf_outputintr (crd->dev_for_play, 1);
+            }
 	    break;
 	}
+    }
     return 0;
 }
-#endif
 
 /*
  * 	This loop walks the PCI configuration database and finds where
@@ -1285,10 +1276,6 @@
     if (count == 0)
 	return -ENODEV;
 
-#ifdef CONFIG_APM
-    apm_register_callback (&handle_apm_event);
-#endif
-
     printk (KERN_INFO "Done installing NM256 audio driver.\n");
     return 0;
 }
@@ -1699,9 +1686,7 @@
 	}
 	nmcard_list = NULL;
     }
-#ifdef CONFIG_APM
-    apm_unregister_callback (&handle_apm_event);
-#endif
+    pm_unregister_all (&handle_pm_event);
 }
 #endif
 
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.3.42/linux/drivers/sound/sb_card.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/sb_card.c	Wed Feb  9 18:48:03 2000
@@ -9,20 +9,25 @@
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
+ *
+ *
+ * 26th November 1999 - patched to compile without ISA PnP support in the
+ * kernel. -Daniel Stone (tamriel@ductape.net) 
+ *
+ * 06-01-2000 Refined and bugfixed ISA PnP support, added
+ *  CMI 8330 support - Alessandro Zummo <azummo@ita.flashnet.it>
+ *
+ *
+ * 04-02-2000 Added Soundblaster AWE 64 PnP support, isapnpjump
+ *  Alessandro Zummo <azummo@ita.flashnet.it>
+ *
  */
 
-/* 26th Novemner 1999 - patched to compile without ISA PnP support in the
-   kernel. -Daniel Stone (tamriel@ductape.net) */
-
 #include <linux/config.h>
-#ifdef CONFIG_MCA
 #include <linux/mca.h>
-#endif
 #include <linux/module.h>
 #include <linux/init.h>
-#ifdef CONFIG_ISAPNP		/* Patched so it will compile withOUT ISA PnP */
 #include <linux/isapnp.h>
-#endif
 
 #include "sound_config.h"
 #include "soundmodule.h"
@@ -36,10 +41,8 @@
 
 void attach_sb_card(struct address_info *hw_config)
 {
-#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
 	if(!sb_dsp_init(hw_config))
 		hw_config->slots[0] = -1;
-#endif
 }
 
 int probe_sb(struct address_info *hw_config)
@@ -91,7 +94,7 @@
 					hw_config->driver_use_2 = midiaddr[(pos2 >> 3) & 0x3];
 				*/
 	
-				printk("SB: Reply MCA SB at slot=%d \
+				printk(KERN_INFO "sb: Reply MCA SB at slot=%d \
 iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
 						slot+1,
 				        	hw_config->io_base, hw_config->irq,
@@ -99,12 +102,14 @@
 			}
 			else
 			{
-				printk ("Reply SB Base I/O address disabled\n");
+				printk (KERN_INFO "sb: Reply SB Base I/O address disabled\n");
 			}
 		}
 	}
 #endif
 
+	/* This is useless since is done by sb_dsp_detect - azummo*/
+	
 	if (check_region(hw_config->io_base, 16))
 	{
 		printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base);
@@ -127,92 +132,403 @@
 static struct address_info config;
 static struct address_info config_mpu;
 
+struct pci_dev 	*sb_dev 	= NULL, 
+				*wss_dev 	= NULL, 
+				*jp_dev 	= NULL, 
+				*mpu_dev 	= NULL, 
+				*wt_dev 	= NULL;
 /*
  *    Note DMA2 of -1 has the right meaning in the SB16 driver as well
- *      as here. It will cause either an error if it is needed or a fallback
- *      to the 8bit channel.
+ *    as here. It will cause either an error if it is needed or a fallback
+ *    to the 8bit channel.
  */
 
-int mpu_io = 0;
-int io = -1;
-int irq = -1;
-int dma = -1;
-int dma16 = -1;		/* Set this for modules that need it */
-int type = 0;		/* Can set this to a specific card type */
-int mad16 = 0;		/* Set mad16=1 to load this as support for mad16 */
-int trix = 0;		/* Set trix=1 to load this as support for trix */
-int pas2 = 0;		/* Set pas2=1 to load this as support for pas2 */
-int support = 0;	/* Set support to load this as a support module */
-int sm_games = 0;	/* Mixer - see sb_mixer.c */
-int acer = 0;		/* Do acer notebook init */
-
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(dma, "i");
-MODULE_PARM(dma16, "i");
-MODULE_PARM(mpu_io, "i");
-MODULE_PARM(type, "i");
-MODULE_PARM(mad16, "i");
-MODULE_PARM(support, "i");
-MODULE_PARM(trix, "i");
-MODULE_PARM(pas2, "i");
-MODULE_PARM(sm_games, "i");
-MODULE_PARM(esstype, "i");
+int mpu_io 	= 0;
+int io 		= -1;
+int irq 	= -1;
+int dma 	= -1;
+int dma16 	= -1;		/* Set this for modules that need it */
+int type 	= 0;		/* Can set this to a specific card type */
+int mad16 	= 0;		/* Set mad16=1 to load this as support for mad16 */
+int trix 	= 0;		/* Set trix=1 to load this as support for trix */
+int pas2 	= 0;		/* Set pas2=1 to load this as support for pas2 */
+int support 	= 0;		/* Set support to load this as a support module */
+int sm_games	= 0;		/* Mixer - see sb_mixer.c */
+int acer 	= 0;		/* Do acer notebook init */
+
+#ifdef CONFIG_ISAPNP
+int isapnp 		= 1;
+int isapnpjump 		= 0;
+#else
+int isapnp 		= 0;
+#endif
+
+MODULE_DESCRIPTION("Soundblaster driver");
+
+MODULE_PARM(io, 	"i");
+MODULE_PARM(irq, 	"i");
+MODULE_PARM(dma, 	"i");
+MODULE_PARM(dma16, 	"i");
+MODULE_PARM(mpu_io, 	"i");
+MODULE_PARM(type, 	"i");
+MODULE_PARM(mad16, 	"i");
+MODULE_PARM(support, 	"i");
+MODULE_PARM(trix, 	"i");
+MODULE_PARM(pas2, 	"i");
+MODULE_PARM(sm_games, 	"i");
+MODULE_PARM(esstype, 	"i");
+MODULE_PARM(acer, 	"i");
+
+#ifdef CONFIG_ISAPNP
+MODULE_PARM(isapnp, 	"i");
+MODULE_PARM(isapnpjump, "i");
+MODULE_PARM_DESC(isapnp,	"When set to 0, Plug & Play support will be disabled");
+MODULE_PARM_DESC(isapnpjump, 	"Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
+#endif
+
+MODULE_PARM_DESC(io, 		"Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
+MODULE_PARM_DESC(irq,		"IRQ (5,7,9,10)");
+MODULE_PARM_DESC(dma,		"8-bit DMA channel (0,1,3)");
+MODULE_PARM_DESC(dma16,		"16-bit DMA channel (5,6,7)");
+MODULE_PARM_DESC(mpu_io,	"Mpu base address");
+MODULE_PARM_DESC(type,		"You can set this to specific card type");
+MODULE_PARM_DESC(mad16,		"Enable MAD16 support");
+MODULE_PARM_DESC(trix,		"Enable Audiotrix support");
+MODULE_PARM_DESC(pas2,		"Enable Pas2 support");
+MODULE_PARM_DESC(support,	"Set this to load as generic support module");
+MODULE_PARM_DESC(sm_games,	"Enable support for Logitech soundman games");
+MODULE_PARM_DESC(esstype,	"ESS chip type");
+MODULE_PARM_DESC(acer,		"Set this to detect cards in some ACER notebooks");
 
 void *smw_free = NULL;
 
 #ifdef CONFIG_ISAPNP
-static struct { unsigned short vendor, function; char *name; }
+
+/* That's useful. */
+
+static int check_base(char *devname, char *resname, struct resource *res)
+{
+	if (check_region(res->start, res->end - res->start))
+	{
+		printk(KERN_ERR "sb: %s %s error, i/o at %#lx already in use\n", devname, resname, res->start);
+		return 0;
+	}
+
+	printk(KERN_INFO "sb: %s %s base located at %#lx\n", devname, resname, res->start);
+	return 1;
+}
+
+
+/* Card's specific initialization functions
+ */
+
+static struct pci_dev *sb_init_generic(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+	if((sb_dev = isapnp_find_dev(card,
+				card->vendor,
+				card->device,
+				NULL)))
+	{
+		sb_dev->prepare(sb_dev);
+		sb_dev->activate(sb_dev);
+
+		if (!sb_dev->resource[0].start)
+			return(NULL);
+
+		hw_config->io_base 	= sb_dev->resource[0].start;
+		hw_config->irq 		= sb_dev->irq_resource[0].start;
+		hw_config->dma 		= sb_dev->dma_resource[0].start;
+		hw_config->dma2 	= sb_dev->dma_resource[1].start;
+		mpu_config->io_base     = sb_dev->resource[1].start;
+	}
+	return(sb_dev);
+}
+
+static struct pci_dev *sb_init_ess(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+	if((sb_dev = isapnp_find_dev(card,
+				card->vendor,
+				card->device,
+				NULL)))
+	{
+		sb_dev->prepare(sb_dev);
+		sb_dev->activate(sb_dev);
+
+		if (!sb_dev->resource[0].start)
+			return(NULL);
+
+		hw_config->io_base 	= sb_dev->resource[0].start;
+		hw_config->irq 		= sb_dev->irq_resource[0].start;
+		hw_config->dma 		= sb_dev->dma_resource[0].start;
+		hw_config->dma2 	= sb_dev->dma_resource[1].start;
+		mpu_config->io_base     = sb_dev->resource[2].start;
+	}
+	return(sb_dev);
+}
+
+static struct pci_dev *sb_init_cmi(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+	/* What a stupid chip... where did they get all those @@@ ?*/
+
+	printk(KERN_INFO "sb: CMI8330 detected\n");
+
+	/* Soundblaster compatible logical device. */
+
+	if((sb_dev = isapnp_find_dev(card,
+				ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+	{
+#ifdef CMI8330_DMA0BAD
+		int dmahack = 0;
+#endif
+		sb_dev->prepare(sb_dev);
+		
+		/*  This device doesn't work with DMA 0, so we must allocate
+			it to prevent PnP routines to assign it to the card.
+
+			I know i could have inlined the following lines, but it's cleaner
+			this way.
+		*/
+	
+#ifdef CMI8330_DMA0BAD
+		if(sb_dev->dma_resource[0].start == 0)
+		{
+			if(!request_dma(0, "cmi8330 dma hack"))
+			{
+				/* DMA was free, we now have it */
+				dmahack = 1;
+			}
+		}
+#endif
+
+		if(sb_dev->activate(sb_dev) >= 0)
+		{
+			hw_config->io_base 	= sb_dev->resource[0].start;
+			hw_config->irq 		= sb_dev->irq_resource[0].start;
+			hw_config->dma 		= sb_dev->dma_resource[0].start;
+			hw_config->dma2 	= sb_dev->dma_resource[1].start;
+
+			check_base("CMI8330", "sb", &sb_dev->resource[0]);
+		}
+		else
+			printk(KERN_ERR "sb: CMI8330 sb config failed (out of resources?)\n");
+
+#ifdef CMI8330_DMA0BAD
+		if(dmahack)
+			free_dma(0);
+#endif
+	}
+	else
+		printk(KERN_ERR "sb: CMI8330 panic! sb base not found\n");
+
+	if((mpu_dev = isapnp_find_dev(card,
+				ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+	{
+		mpu_dev->prepare(mpu_dev);
+
+		/* This disables the interrupt on this resource. Do we need it ? */
+
+		mpu_dev->irq_resource[0].flags = 0;
+
+		if(mpu_dev->activate(mpu_dev) >= 0)
+		{
+			if( check_base("CMI8330", "mpu", &mpu_dev->resource[0]) ) 
+				mpu_config->io_base = mpu_dev->resource[0].start;
+		}
+		else
+			printk(KERN_ERR "sb: CMI8330 mpu config failed (out of resources?)\n");
+	}
+	else
+		printk(KERN_ERR "sb: CMI8330 panic! mpu not found\n");
+
+
+	/* Gameport. */
+
+	if((jp_dev = isapnp_find_dev(card,
+				ISAPNP_VENDOR('@','P','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+	{
+		jp_dev->prepare(jp_dev);
+		
+		if(jp_dev->activate(jp_dev) >= 0)
+		{
+			check_base("CMI8330", "gameport", &jp_dev->resource[0]);
+		}
+		else
+			printk(KERN_ERR "sb: CMI8330 gameport config failed (out of resources?)\n");
+	}
+	else
+		printk(KERN_ERR "sb: CMI8330 panic! gameport not found\n");
+
+
+	/* OPL3 support */
+
+#if defined(CONFIG_SOUND_YM3812) || defined(CONFIG_SOUND_YM3812_MODULE)
+	if((wss_dev = isapnp_find_dev(card,
+				ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), NULL)))
+	{
+		wss_dev->prepare(wss_dev);
+
+		/* Let's disable IRQ and DMA for WSS device */
+
+		wss_dev->irq_resource[0].flags = 0;
+		wss_dev->dma_resource[0].flags = 0;
+
+		if(wss_dev->activate(wss_dev) >= 0)
+		{
+			check_base("CMI8330", "opl3", &wss_dev->resource[1]);
+		}
+		else
+			printk(KERN_ERR "sb: CMI8330 opl3 config failed (out of resources?)\n");
+	}
+	else
+		printk(KERN_ERR "sb: CMI8330 panic! opl3 not found\n");
+#endif
+
+	printk(KERN_INFO "sb: CMI8330 mail reports to Alessandro Zummo <azummo@ita.flashnet.it>\n");
+
+	return(sb_dev);
+}
+
+static struct pci_dev *sb_init_awe64(struct pci_bus *card, struct address_info *hw_config, struct address_info *mpu_config)
+{
+	printk(KERN_INFO "sb: SoundBlaster AWE 64 detected\n");
+
+	/* CTL0042:Audio. */
+
+	if((sb_dev = isapnp_find_dev(card,
+				ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), NULL)))
+	{
+		sb_dev->prepare(sb_dev);
+		
+		if(sb_dev->activate(sb_dev) >= 0)
+		{
+			hw_config->io_base 	= sb_dev->resource[0].start;
+			hw_config->irq 		= sb_dev->irq_resource[0].start;
+			hw_config->dma 		= sb_dev->dma_resource[0].start;
+			hw_config->dma2 	= sb_dev->dma_resource[1].start;
+
+			mpu_config->io_base	= sb_dev->resource[1].start;
+
+			check_base("AWE64", "sb", 	&sb_dev->resource[0]);
+			check_base("AWE64", "mpu", 	&sb_dev->resource[1]);
+			check_base("AWE64", "opl3",	&sb_dev->resource[2]);
+		}
+		else
+			printk(KERN_ERR "sb: AWE64 sb config failed (out of resources?)\n");
+	}
+	else
+		printk(KERN_ERR "sb: AWE64 panic! sb base not found\n");
+
+
+	/* CTL7002:Game */
+
+	if((jp_dev = isapnp_find_dev(card,
+				ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x7002), NULL)))
+	{
+		jp_dev->prepare(jp_dev);
+		
+		if(jp_dev->activate(jp_dev) >= 0)
+		{
+			check_base("AWE64", "gameport", &jp_dev->resource[0]);
+		}
+		else
+			printk(KERN_ERR "sb: AWE64 gameport config failed (out of resources?)\n");
+	}
+	else
+		printk(KERN_ERR "sb: AWE64 panic! gameport not found\n");
+
+
+	/* CTL0022:WaveTable */
+
+	if((wt_dev = isapnp_find_dev(card,
+				ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0022), NULL)))
+	{
+		wt_dev->prepare(wt_dev);
+		
+		if(wt_dev->activate(wt_dev) >= 0)
+		{
+			check_base("AWE64", "wavetable", &wt_dev->resource[0]);
+			check_base("AWE64", "wavetable", &wt_dev->resource[1]);
+			check_base("AWE64", "wavetable", &wt_dev->resource[2]);
+		}
+		else
+			printk(KERN_ERR "sb: AWE64 wavetable config failed (out of resources?)\n");
+	}
+	else
+		printk(KERN_ERR "sb: AWE64 panic! wavetable not found\n");
+
+	printk(KERN_INFO "sb: AWE64 mail reports to Alessandro Zummo <azummo@ita.flashnet.it>\n");
+
+	return(sb_dev);
+}
+
+
+static struct { unsigned short vendor, function; struct pci_dev * (*initfunc)(struct pci_bus *, struct address_info *, struct address_info *); char *name; }
 isapnp_sb_list[] __initdata = {
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), "Sound Blaster 16" },
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), "Sound Blaster 16" },
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), "Sound Blaster 16" },
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), "Sound Blaster 16" },
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), "Sound Blaster 16" },
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), "Sound Blaster 16" },
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), "Sound Blaster 16" },
-	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), "ESS 1868" },
-	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), "ESS 1868" },
-	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), "ESS 1869" },
-	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), "ESS 1878" },
-	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), "ESS 1879" },
-	{0,}
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), &sb_init_generic,	"Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), &sb_init_generic,	"Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), &sb_init_generic,	"Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), &sb_init_generic,	"Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), &sb_init_generic,	"Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), &sb_init_generic,	"Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), &sb_init_generic,	"Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x009D), &sb_init_awe64,	"Sound Blaster AWE 64" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), &sb_init_ess,		"ESS 1868" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), &sb_init_ess,		"ESS 1868" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), &sb_init_ess,		"ESS 1869" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), &sb_init_ess,		"ESS 1878" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), &sb_init_ess,		"ESS 1879" },
+	{ISAPNP_VENDOR('C','M','I'), ISAPNP_FUNCTION(0x0001), &sb_init_cmi, 	"CMI 8330 SoundPRO" },
+    {0}
 };
 
+/* Actually this routine will detect and configure only the first card with successful
+   initalization. isapnpjump could be used to jump to a specific entry.
+   Please always add entries at the end of the array.
+   Should this be fixed? - azummo
+*/
 
 static int __init sb_probe_isapnp(struct address_info *hw_config, struct address_info *mpu_config) {
+
 	int i;
+
+	/* Count entries in isapnp_sb_list */
+	for (i = 0; isapnp_sb_list[i].vendor != 0; i++);
+
+	/* Check and adjust isapnpjump */
+	if( isapnpjump < 0 || isapnpjump > ( i - 1 ) )
+	{
+		printk(KERN_ERR "sb: Valid range for isapnpjump is 0-%d. Adjusted to 0.\n", i-1);
+		isapnpjump = 0;
+	}
 	
-	for (i = 0; isapnp_sb_list[i].vendor != 0; i++) {
-		struct pci_dev *idev = NULL;
+	for (i = isapnpjump; isapnp_sb_list[i].vendor != 0; i++) {
+		struct pci_bus *card = NULL;
 			
-		while ((idev = isapnp_find_dev(NULL,
+		while ((card = isapnp_find_card(
 					       isapnp_sb_list[i].vendor,
 					       isapnp_sb_list[i].function,
-					       idev))) {
-			idev->prepare(idev);
-			idev->activate(idev);
-			if (!idev->resource[0].start || check_region(idev->resource[0].start,16))
-			  continue;
-			hw_config->io_base = idev->resource[0].start;
-			hw_config->irq = idev->irq_resource[0].start;
-			hw_config->dma = idev->dma_resource[0].start;
-			hw_config->dma2 = idev->dma_resource[1].start;
-#ifdef CONFIG_MIDI
-			if (isapnp_sb_list[i].vendor == ISAPNP_VENDOR('E','S','S'))
-			  mpu_config->io_base = idev->resource[2].start;
-			else
-			  mpu_config->io_base = idev->resource[1].start;
-#endif
-			break;
+					       card))) {
+
+       			/* You missed the init func? That's bad. */
+
+			if(isapnp_sb_list[i].initfunc)
+			{
+				struct pci_dev *idev = NULL;
+
+				/* Initialize this baby. */
+
+				if((idev = isapnp_sb_list[i].initfunc(card, hw_config, mpu_config)))
+				{
+					/* We got it. */
+
+					printk(KERN_INFO "sb: ISAPnP reports %s at i/o %#x, irq %d, dma %d, %d\n",
+					       isapnp_sb_list[i].name,
+					       hw_config->io_base, hw_config->irq, hw_config->dma,
+					       hw_config->dma2);
+					return 0;
+				}
+			}
 		}
-		if (!idev)
-		  continue;
-		printk(KERN_INFO "ISAPnP reports %s at i/o %#x, irq %d, dma %d, %d\n",
-		       isapnp_sb_list[i].name,
-		       hw_config->io_base, hw_config->irq, hw_config->dma,
-		       hw_config->dma2);
-		return 0;
 	}
 	return -ENODEV;
 }
@@ -224,38 +540,52 @@
 
 	if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
 	{
+		/* Please remember that even with CONFIG_ISAPNP defined one should still be
+			able to disable PNP support for this single driver!
+		*/
+
 #ifdef CONFIG_ISAPNP			
-		if (sb_probe_isapnp(&config, &config_mpu)<0)
+		if (isapnp)
+		{
+			if(sb_probe_isapnp(&config, &config_mpu) < 0 )
+			{
+				printk(KERN_ERR "sb_card: No ISAPnP cards found\n");
+				return -EINVAL;
+			}
+		}
+		else
 		{
-#endif			
+#endif		
 			if (io == -1 || dma == -1 || irq == -1)
 			{
 				printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n");
 				return -EINVAL;
 			}
-			config.io_base = io;
-			config.irq = irq;
-			config.dma = dma;
-			config.dma2 = dma16;
-			config.card_subtype = type;
-#ifdef CONFIG_MIDI
-			config_mpu.io_base = mpu_io;
-#endif
+
+			config.io_base 	= io;
+			config.irq 		= irq;
+			config.dma 		= dma;
+			config.dma2 	= dma16;
 #ifdef CONFIG_ISAPNP
 		}
 #endif
+
+		/* If this is not before the #ifdef line, there's a reason... */
+		config.card_subtype = type;
+
 		if (!probe_sb(&config))
 			return -ENODEV;
 		attach_sb_card(&config);
 	
 		if(config.slots[0]==-1)
 			return -ENODEV;
-#ifdef CONFIG_MIDI
+
+		if (isapnp == 0) 
+			config_mpu.io_base = mpu_io;
 		if (probe_sbmpu(&config_mpu))
 			sbmpu = 1;
 		if (sbmpu)
 			attach_sbmpu(&config_mpu);
-#endif
 	}
 	SOUND_LOCK;
 	return 0;
@@ -270,6 +600,12 @@
 	if (sbmpu)
 		unload_sbmpu(&config_mpu);
 	SOUND_LOCK_END;
+
+	if(sb_dev)	sb_dev->deactivate(sb_dev);
+	if(jp_dev)	jp_dev->deactivate(jp_dev);
+	if(wt_dev)	wt_dev->deactivate(wt_dev);
+	if(mpu_dev)	mpu_dev->deactivate(mpu_dev);
+	if(wss_dev)	wss_dev->deactivate(wss_dev);
 }
 
 #else
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.3.42/linux/drivers/sound/sonicvibes.c	Fri Jan 21 18:19:17 2000
+++ linux/drivers/sound/sonicvibes.c	Wed Feb  9 11:42:35 2000
@@ -87,6 +87,7 @@
  *    08.01.2000   0.25  Prevent some ioctl's from returning bad count values on underrun/overrun;
  *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
  *                       use Martin Mares' pci_assign_resource
+ *    07.02.2000   0.26  Use pci_alloc_consistent and pci_register_driver
  *
  */
 
@@ -287,8 +288,11 @@
 	/* magic */
 	unsigned int magic;
 
-	/* we keep sv cards in a linked list */
-	struct sv_state *next;
+	/* list of sonicvibes devices */
+	struct list_head devs;
+
+	/* the corresponding pci_dev structure */
+	struct pci_dev *dev;
 
 	/* soundcore stuff */
 	int dev_audio;
@@ -319,6 +323,7 @@
 
 	struct dmabuf {
 		void *rawbuf;
+		dma_addr_t dmaaddr;
 		unsigned buforder;
 		unsigned numfrag;
 		unsigned fragshift;
@@ -354,7 +359,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct sv_state *devs = NULL;
+static LIST_HEAD(devs);
 static unsigned long wavetable_mem = 0;
 
 /* --------------------------------------------------------------------- */
@@ -684,7 +689,7 @@
 #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-static void dealloc_dmabuf(struct dmabuf *db)
+static void dealloc_dmabuf(struct sv_state *s, struct dmabuf *db)
 {
 	unsigned long map, mapend;
 
@@ -693,7 +698,7 @@
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
 		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
 			clear_bit(PG_reserved, &mem_map[map].flags);	
-		free_pages((unsigned long)db->rawbuf, db->buforder);
+		pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr);
 	}
 	db->rawbuf = NULL;
 	db->mapped = db->ready = 0;
@@ -729,7 +734,7 @@
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
 		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))
+			if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr)))
 				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
@@ -770,12 +775,12 @@
 	memset(db->rawbuf, (fmt & SV_CFMT_16BIT) ? 0 : 0x80, db->dmasize);
 	spin_lock_irqsave(&s->lock, flags);
 	if (rec) {
-		set_dmac(s, virt_to_bus(db->rawbuf), db->numfrag << db->fragshift);
+		set_dmac(s, db->dmaaddr, db->numfrag << db->fragshift);
 		/* program enhanced mode registers */
 		wrindir(s, SV_CIDMACBASECOUNT1, (db->fragsamples-1) >> 8);
 		wrindir(s, SV_CIDMACBASECOUNT0, db->fragsamples-1);
 	} else {
-		set_dmaa(s, virt_to_bus(db->rawbuf), db->numfrag << db->fragshift);
+		set_dmaa(s, db->dmaaddr, db->numfrag << db->fragshift);
 		/* program enhanced mode registers */
 		wrindir(s, SV_CIDMAABASECOUNT1, (db->fragsamples-1) >> 8);
 		wrindir(s, SV_CIDMAABASECOUNT0, db->fragsamples-1);
@@ -1223,12 +1228,16 @@
 static int sv_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
-	struct sv_state *s = devs;
+	struct list_head *list;
+	struct sv_state *s;
 
-	while (s && s->dev_mixer != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct sv_state, devs);
+		if (s->dev_mixer == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	MOD_INC_USE_COUNT;
@@ -1250,19 +1259,10 @@
 }
 
 static /*const*/ struct file_operations sv_mixer_fops = {
-	&sv_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&sv_ioctl_mixdev,
-	NULL,  /* mmap */
-	&sv_open_mixdev,
-	NULL,	/* flush */
-	&sv_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		sv_llseek,
+	ioctl:		sv_ioctl_mixdev,
+	open:		sv_open_mixdev,
+	release:	sv_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -1852,13 +1852,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct sv_state *s = devs;
 	unsigned char fmtm = ~0, fmts = 0;
+	struct list_head *list;
+	struct sv_state *s;
 
-	while (s && ((s->dev_audio ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct sv_state, devs);
+		if (!((s->dev_audio ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -1909,11 +1913,11 @@
 	down(&s->open_sem);
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac(s);
-		dealloc_dmabuf(&s->dma_dac);
+		dealloc_dmabuf(s, &s->dma_dac);
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(s);
-		dealloc_dmabuf(&s->dma_adc);
+		dealloc_dmabuf(s, &s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
 	wake_up(&s->open_wait);
@@ -1923,19 +1927,14 @@
 }
 
 static /*const*/ struct file_operations sv_audio_fops = {
-	&sv_llseek,
-	&sv_read,
-	&sv_write,
-	NULL,  /* readdir */
-	&sv_poll,
-	&sv_ioctl,
-	&sv_mmap,
-	&sv_open,
-	NULL,	/* flush */
-	&sv_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		sv_llseek,
+	read:		sv_read,
+	write:		sv_write,
+	poll:		sv_poll,
+	ioctl:		sv_ioctl,
+	mmap:		sv_mmap,
+	open:		sv_open,
+	release:	sv_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2098,13 +2097,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct sv_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct sv_state *s;
 
-	while (s && s->dev_midi != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct sv_state, devs);
+		if (s->dev_midi == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2203,19 +2206,12 @@
 }
 
 static /*const*/ struct file_operations sv_midi_fops = {
-	&sv_llseek,
-	&sv_midi_read,
-	&sv_midi_write,
-	NULL,  /* readdir */
-	&sv_midi_poll,
-	NULL,  /* ioctl */
-	NULL,  /* mmap */
-	&sv_midi_open,
-	NULL,	/* flush */
-	&sv_midi_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		sv_llseek,
+	read:		sv_midi_read,
+	write:		sv_midi_write,
+	poll:		sv_midi_poll,
+	open:		sv_midi_open,
+	release:	sv_midi_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2321,12 +2317,16 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct sv_state *s = devs;
+	struct list_head *list;
+	struct sv_state *s;
 
-	while (s && s->dev_dmfm != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct sv_state, devs);
+		if (s->dev_dmfm == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2380,24 +2380,15 @@
 }
 
 static /*const*/ struct file_operations sv_dmfm_fops = {
-	&sv_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&sv_dmfm_ioctl,
-	NULL,  /* mmap */
-	&sv_dmfm_open,
-	NULL,	/* flush */
-	&sv_dmfm_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		sv_llseek,
+	ioctl:		sv_dmfm_ioctl,
+	open:		sv_dmfm_open,
+	release:	sv_dmfm_release,
 };
 
 /* --------------------------------------------------------------------- */
 
-/* maximum number of devices */
+/* maximum number of devices; only used for command line params */
 #define NR_DEVICE 5
 
 static int reverb[NR_DEVICE] = { 0, };
@@ -2406,6 +2397,8 @@
 static int wavetable[NR_DEVICE] = { 0, };
 #endif
 
+static unsigned int devindex = 0;
+
 MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
 MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
 #if 0
@@ -2437,216 +2430,235 @@
 				 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
 
-static int __init init_sonicvibes(void)
+static int sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	static const char __initlocaldata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller";
        	struct sv_state *s;
-	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
-	int i, val, index = 0;
+	int i, val;
 	char *ddmaname;
 	unsigned ddmanamelen;
 
+	if (!RSRCISIOREGION(pcidev, RESOURCE_SB) ||
+	    !RSRCISIOREGION(pcidev, RESOURCE_ENH) ||
+	    !RSRCISIOREGION(pcidev, RESOURCE_SYNTH) ||
+	    !RSRCISIOREGION(pcidev, RESOURCE_MIDI) ||
+	    !RSRCISIOREGION(pcidev, RESOURCE_GAME))
+		return -1;
+	if (pcidev->irq == 0)
+		return -1;
+	/* try to allocate a DDMA resource if not already available */
+	if (!RSRCISIOREGION(pcidev, RESOURCE_DDMA)) {
+		pcidev->resource[RESOURCE_DDMA].start = 0;
+		pcidev->resource[RESOURCE_DDMA].end = 2*SV_EXTENT_DMA-1;
+		pcidev->resource[RESOURCE_DDMA].flags = PCI_BASE_ADDRESS_SPACE_IO | IORESOURCE_IO;
+		ddmanamelen = strlen(sv_ddma_name)+1;
+		if (!(ddmaname = kmalloc(ddmanamelen, GFP_KERNEL)))
+			return -1;
+		memcpy(ddmaname, sv_ddma_name, ddmanamelen);
+		pcidev->resource[RESOURCE_DDMA].name = ddmaname;
+		if (pci_assign_resource(pcidev, RESOURCE_DDMA)) {
+			pcidev->resource[RESOURCE_DDMA].name = NULL;
+			kfree(ddmaname);
+			printk(KERN_ERR "sv: cannot allocate DDMA controller io ports\n");
+			return -1;
+		}
+	}
+	if (!(s = kmalloc(sizeof(struct sv_state), GFP_KERNEL))) {
+		printk(KERN_WARNING "sv: out of memory\n");
+		return -1;
+	}
+	memset(s, 0, sizeof(struct sv_state));
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_waitqueue_head(&s->midi.iwait);
+	init_waitqueue_head(&s->midi.owait);
+	init_MUTEX(&s->open_sem);
+	spin_lock_init(&s->lock);
+	s->magic = SV_MAGIC;
+	s->dev = pcidev;
+	s->iosb = RSRCADDRESS(pcidev, RESOURCE_SB);
+	s->ioenh = RSRCADDRESS(pcidev, RESOURCE_ENH);
+	s->iosynth = RSRCADDRESS(pcidev, RESOURCE_SYNTH);
+	s->iomidi = RSRCADDRESS(pcidev, RESOURCE_MIDI);
+	s->iogame = RSRCADDRESS(pcidev, RESOURCE_GAME);
+	s->iodmaa = RSRCADDRESS(pcidev, RESOURCE_DDMA);
+	s->iodmac = RSRCADDRESS(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA;
+	pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9);  /* enable and use extended mode */
+	pci_write_config_dword(pcidev, 0x48, s->iodmac | 9);  /* enable */
+	printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#lx %#x %#x\n",
+	       s->iosb, s->ioenh, s->iosynth, s->iomidi, s->iogame, s->iodmaa, s->iodmac);
+	s->irq = pcidev->irq;
+	
+	/* hack */
+	pci_write_config_dword(pcidev, 0x60, wavetable_mem >> 12);  /* wavetable base address */
+	
+	if (!request_region(s->ioenh, SV_EXTENT_ENH, "S3 SonicVibes PCM")) {
+		printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
+		goto err_region5;
+	}
+	if (!request_region(s->iodmaa, SV_EXTENT_DMA, "S3 SonicVibes DMAA")) {
+		printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iodmaa, s->iodmaa+SV_EXTENT_DMA-1);
+		goto err_region4;
+	}
+	if (!request_region(s->iodmac, SV_EXTENT_DMA, "S3 SonicVibes DMAC")) {
+		printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iodmac, s->iodmac+SV_EXTENT_DMA-1);
+		goto err_region3;
+	}
+	if (!request_region(s->iomidi, SV_EXTENT_MIDI, "S3 SonicVibes Midi")) {
+		printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iomidi, s->iomidi+SV_EXTENT_MIDI-1);
+		goto err_region2;
+	}
+	if (!request_region(s->iosynth, SV_EXTENT_SYNTH, "S3 SonicVibes Synth")) {
+		printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
+		goto err_region1;
+	}
+	pci_enable_device(pcidev);
+	/* initialize codec registers */
+	outb(0x80, s->ioenh + SV_CODEC_CONTROL); /* assert reset */
+	udelay(50);
+	outb(0x00, s->ioenh + SV_CODEC_CONTROL); /* deassert reset */
+	udelay(50);
+	outb(SV_CCTRL_INTADRIVE | SV_CCTRL_ENHANCED /*| SV_CCTRL_WAVETABLE */
+	     | (reverb[devindex] ? SV_CCTRL_REVERB : 0), s->ioenh + SV_CODEC_CONTROL);
+	inb(s->ioenh + SV_CODEC_STATUS); /* clear ints */
+	wrindir(s, SV_CIDRIVECONTROL, 0);  /* drive current 16mA */
+	wrindir(s, SV_CIENABLE, s->enable = 0);  /* disable DMAA and DMAC */
+	outb(~(SV_CINTMASK_DMAA | SV_CINTMASK_DMAC), s->ioenh + SV_CODEC_INTMASK);
+	/* outb(0xff, s->iodmaa + SV_DMA_RESET); */
+	/* outb(0xff, s->iodmac + SV_DMA_RESET); */
+	inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */
+	wrindir(s, SV_CIADCCLKSOURCE, 0); /* use pll as ADC clock source */
+	wrindir(s, SV_CIANALOGPWRDOWN, 0); /* power up the analog parts of the device */
+	wrindir(s, SV_CIDIGITALPWRDOWN, 0); /* power up the digital parts of the device */
+	setpll(s, SV_CIADCPLLM, 8000);
+	wrindir(s, SV_CISRSSPACE, 0x80); /* SRS off */
+	wrindir(s, SV_CIPCMSR0, (8000 * 65536 / FULLRATE) & 0xff);
+	wrindir(s, SV_CIPCMSR1, ((8000 * 65536 / FULLRATE) >> 8) & 0xff);
+	wrindir(s, SV_CIADCOUTPUT, 0);
+	/* request irq */
+	if (request_irq(s->irq, sv_interrupt, SA_SHIRQ, "S3 SonicVibes", s)) {
+		printk(KERN_ERR "sv: irq %u in use\n", s->irq);
+		goto err_irq;
+	}
+	printk(KERN_INFO "sv: found adapter at io %#lx irq %u dmaa %#06x dmac %#06x revision %u\n",
+	       s->ioenh, s->irq, s->iodmaa, s->iodmac, rdindir(s, SV_CIREVISION));
+	/* register devices */
+	if ((s->dev_audio = register_sound_dsp(&sv_audio_fops, -1)) < 0)
+		goto err_dev1;
+	if ((s->dev_mixer = register_sound_mixer(&sv_mixer_fops, -1)) < 0)
+		goto err_dev2;
+	if ((s->dev_midi = register_sound_midi(&sv_midi_fops, -1)) < 0)
+		goto err_dev3;
+	if ((s->dev_dmfm = register_sound_special(&sv_dmfm_fops, 15 /* ?? */)) < 0)
+		goto err_dev4;
+	pci_set_master(pcidev);  /* enable bus mastering */
+	/* initialize the chips */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	val = SOUND_MASK_LINE|SOUND_MASK_SYNTH;
+	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+		val = initvol[i].vol;
+		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+	}
+	set_fs(fs);
+       /* store it in the driver field */
+	pcidev->driver_data = s;
+	pcidev->dma_mask = 0x00ffffff;
+	/* put it into driver list */
+	list_add_tail(&s->devs, &devs);
+	/* increment devindex */
+	if (devindex < NR_DEVICE-1)
+		devindex++;
+	return 0;
+
+ err_dev4:
+	unregister_sound_midi(s->dev_midi);
+ err_dev3:
+	unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+	printk(KERN_ERR "sv: cannot register misc device\n");
+	free_irq(s->irq, s);
+ err_irq:
+	release_region(s->iosynth, SV_EXTENT_SYNTH);
+ err_region1:
+	release_region(s->iomidi, SV_EXTENT_MIDI);
+ err_region2:
+	release_region(s->iodmac, SV_EXTENT_DMA);
+ err_region3:
+	release_region(s->iodmaa, SV_EXTENT_DMA);
+ err_region4:
+	release_region(s->ioenh, SV_EXTENT_ENH);
+ err_region5:
+	kfree_s(s, sizeof(struct sv_state));
+	return -1;
+}
+
+static void sv_remove(struct pci_dev *dev)
+{
+       struct sv_state *s = (struct sv_state *)dev->driver_data;
+
+       if (!s)
+               return;
+       list_del(&s->devs);
+       outb(~0, s->ioenh + SV_CODEC_INTMASK);  /* disable ints */
+       synchronize_irq();
+       inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */
+       wrindir(s, SV_CIENABLE, 0);     /* disable DMAA and DMAC */
+       /*outb(0, s->iodmaa + SV_DMA_RESET);*/
+       /*outb(0, s->iodmac + SV_DMA_RESET);*/
+       free_irq(s->irq, s);
+       release_region(s->iodmac, SV_EXTENT_DMA);
+       release_region(s->iodmaa, SV_EXTENT_DMA);
+       release_region(s->ioenh, SV_EXTENT_ENH);
+       release_region(s->iomidi, SV_EXTENT_MIDI);
+       release_region(s->iosynth, SV_EXTENT_SYNTH);
+       unregister_sound_dsp(s->dev_audio);
+       unregister_sound_mixer(s->dev_mixer);
+       unregister_sound_midi(s->dev_midi);
+       unregister_sound_special(s->dev_dmfm);
+       kfree_s(s, sizeof(struct sv_state));
+       dev->driver_data = NULL;
+}
+
+static const struct pci_device_id id_table[] = {
+       { PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SONICVIBES, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+       { 0, 0, 0, 0, 0, 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver sv_driver = {
+       name: "sonicvibes",
+       id_table: id_table,
+       probe: sv_probe,
+       remove: sv_remove
+};
+ 
+static int __init init_sonicvibes(void)
+{
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.25 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.26 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
 #endif
-	while (index < NR_DEVICE && 
-	       (pcidev = pci_find_device(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SONICVIBES, pcidev))) {
-		if (!RSRCISIOREGION(pcidev, RESOURCE_SB) ||
-		    !RSRCISIOREGION(pcidev, RESOURCE_ENH) ||
-		    !RSRCISIOREGION(pcidev, RESOURCE_SYNTH) ||
-		    !RSRCISIOREGION(pcidev, RESOURCE_MIDI) ||
-		    !RSRCISIOREGION(pcidev, RESOURCE_GAME))
-			continue;
-		if (pcidev->irq == 0)
-			continue;
-		/* try to allocate a DDMA resource if not already available */
-		if (!RSRCISIOREGION(pcidev, RESOURCE_DDMA)) {
-			pcidev->resource[RESOURCE_DDMA].start = 0;
-			pcidev->resource[RESOURCE_DDMA].end = 2*SV_EXTENT_DMA-1;
-			pcidev->resource[RESOURCE_DDMA].flags = PCI_BASE_ADDRESS_SPACE_IO | IORESOURCE_IO;
-			ddmanamelen = strlen(sv_ddma_name)+1;
-			if (!(ddmaname = kmalloc(ddmanamelen, GFP_KERNEL)))
-				continue;
-			memcpy(ddmaname, sv_ddma_name, ddmanamelen);
-			pcidev->resource[RESOURCE_DDMA].name = ddmaname;
-			if (pci_assign_resource(pcidev, RESOURCE_DDMA)) {
-				pcidev->resource[RESOURCE_DDMA].name = NULL;
-				kfree(ddmaname);
-				printk(KERN_ERR "sv: cannot allocate DDMA controller io ports\n");
-				continue;
-			}
-		}
-		if (!(s = kmalloc(sizeof(struct sv_state), GFP_KERNEL))) {
-			printk(KERN_WARNING "sv: out of memory\n");
-			continue;
-		}
-		memset(s, 0, sizeof(struct sv_state));
-		init_waitqueue_head(&s->dma_adc.wait);
-		init_waitqueue_head(&s->dma_dac.wait);
-		init_waitqueue_head(&s->open_wait);
-		init_waitqueue_head(&s->midi.iwait);
-		init_waitqueue_head(&s->midi.owait);
-		init_MUTEX(&s->open_sem);
-		spin_lock_init(&s->lock);
-		s->magic = SV_MAGIC;
-		s->iosb = RSRCADDRESS(pcidev, RESOURCE_SB);
-		s->ioenh = RSRCADDRESS(pcidev, RESOURCE_ENH);
-		s->iosynth = RSRCADDRESS(pcidev, RESOURCE_SYNTH);
-		s->iomidi = RSRCADDRESS(pcidev, RESOURCE_MIDI);
-		s->iogame = RSRCADDRESS(pcidev, RESOURCE_GAME);
-		s->iodmaa = RSRCADDRESS(pcidev, RESOURCE_DDMA);
-		s->iodmac = RSRCADDRESS(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA;
-		pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9);  /* enable and use extended mode */
-		pci_write_config_dword(pcidev, 0x48, s->iodmac | 9);  /* enable */
-		printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#lx %#x %#x\n",
-		       s->iosb, s->ioenh, s->iosynth, s->iomidi, s->iogame, s->iodmaa, s->iodmac);
-		s->irq = pcidev->irq;
-
-		/* hack */
-		pci_write_config_dword(pcidev, 0x60, wavetable_mem >> 12);  /* wavetable base address */
-
-		if (check_region(s->ioenh, SV_EXTENT_ENH)) {
-			printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
-			goto err_region5;
-		}
-		request_region(s->ioenh, SV_EXTENT_ENH, "S3 SonicVibes PCM");
-		if (check_region(s->iodmaa, SV_EXTENT_DMA)) {
-			printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iodmaa, s->iodmaa+SV_EXTENT_DMA-1);
-			goto err_region4;
-		}
-		request_region(s->iodmaa, SV_EXTENT_DMA, "S3 SonicVibes DMAA");
-		if (check_region(s->iodmac, SV_EXTENT_DMA)) {
-			printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iodmac, s->iodmac+SV_EXTENT_DMA-1);
-			goto err_region3;
-		}
-		request_region(s->iodmac, SV_EXTENT_DMA, "S3 SonicVibes DMAC");
-		if (check_region(s->iomidi, SV_EXTENT_MIDI)) {
-			printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iomidi, s->iomidi+SV_EXTENT_MIDI-1);
-			goto err_region2;
-		}
-		request_region(s->iomidi, SV_EXTENT_MIDI, "S3 SonicVibes Midi");
-		if (check_region(s->iosynth, SV_EXTENT_SYNTH)) {
-			printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
-			goto err_region1;
-		}
-		request_region(s->iosynth, SV_EXTENT_SYNTH, "S3 SonicVibes Synth");
-		/* initialize codec registers */
-		outb(0x80, s->ioenh + SV_CODEC_CONTROL); /* assert reset */
-		udelay(50);
-		outb(0x00, s->ioenh + SV_CODEC_CONTROL); /* deassert reset */
-		udelay(50);
-		outb(SV_CCTRL_INTADRIVE | SV_CCTRL_ENHANCED /*| SV_CCTRL_WAVETABLE */
-		     | (reverb[index] ? SV_CCTRL_REVERB : 0), s->ioenh + SV_CODEC_CONTROL);
-		inb(s->ioenh + SV_CODEC_STATUS); /* clear ints */
-		wrindir(s, SV_CIDRIVECONTROL, 0);  /* drive current 16mA */
-		wrindir(s, SV_CIENABLE, s->enable = 0);  /* disable DMAA and DMAC */
-		outb(~(SV_CINTMASK_DMAA | SV_CINTMASK_DMAC), s->ioenh + SV_CODEC_INTMASK);
-		/* outb(0xff, s->iodmaa + SV_DMA_RESET); */
-		/* outb(0xff, s->iodmac + SV_DMA_RESET); */
-		inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */
-		wrindir(s, SV_CIADCCLKSOURCE, 0); /* use pll as ADC clock source */
-		wrindir(s, SV_CIANALOGPWRDOWN, 0); /* power up the analog parts of the device */
-		wrindir(s, SV_CIDIGITALPWRDOWN, 0); /* power up the digital parts of the device */
-		setpll(s, SV_CIADCPLLM, 8000);
-		wrindir(s, SV_CISRSSPACE, 0x80); /* SRS off */
-		wrindir(s, SV_CIPCMSR0, (8000 * 65536 / FULLRATE) & 0xff);
-		wrindir(s, SV_CIPCMSR1, ((8000 * 65536 / FULLRATE) >> 8) & 0xff);
-		wrindir(s, SV_CIADCOUTPUT, 0);
-		/* request irq */
-		if (request_irq(s->irq, sv_interrupt, SA_SHIRQ, "S3 SonicVibes", s)) {
-			printk(KERN_ERR "sv: irq %u in use\n", s->irq);
-			goto err_irq;
-		}
-		printk(KERN_INFO "sv: found adapter at io %#lx irq %u dmaa %#06x dmac %#06x revision %u\n",
-		       s->ioenh, s->irq, s->iodmaa, s->iodmac, rdindir(s, SV_CIREVISION));
-		/* register devices */
-		if ((s->dev_audio = register_sound_dsp(&sv_audio_fops, -1)) < 0)
-			goto err_dev1;
-		if ((s->dev_mixer = register_sound_mixer(&sv_mixer_fops, -1)) < 0)
-			goto err_dev2;
-		if ((s->dev_midi = register_sound_midi(&sv_midi_fops, -1)) < 0)
-			goto err_dev3;
-		if ((s->dev_dmfm = register_sound_special(&sv_dmfm_fops, 15 /* ?? */)) < 0)
-			goto err_dev4;
-		pci_set_master(pcidev);  /* enable bus mastering */
-		/* initialize the chips */
-		fs = get_fs();
-		set_fs(KERNEL_DS);
-		val = SOUND_MASK_LINE|SOUND_MASK_SYNTH;
-		mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-		for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-			val = initvol[i].vol;
-			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
-		}
-		set_fs(fs);
-		/* queue it for later freeing */
-		s->next = devs;
-		devs = s;
-		index++;
-		continue;
-
-	err_dev4:
-		unregister_sound_midi(s->dev_midi);
-	err_dev3:
-		unregister_sound_mixer(s->dev_mixer);
-	err_dev2:
-		unregister_sound_dsp(s->dev_audio);
-	err_dev1:
-		printk(KERN_ERR "sv: cannot register misc device\n");
-		free_irq(s->irq, s);
-	err_irq:
-		release_region(s->iosynth, SV_EXTENT_SYNTH);
-	err_region1:
-		release_region(s->iomidi, SV_EXTENT_MIDI);
-	err_region2:
-		release_region(s->iodmac, SV_EXTENT_DMA);
-	err_region3:
-		release_region(s->iodmaa, SV_EXTENT_DMA);
-	err_region4:
-		release_region(s->ioenh, SV_EXTENT_ENH);
-	err_region5:
-		kfree_s(s, sizeof(struct sv_state));
-	}
-	if (!devs) {
-		if (wavetable_mem)
-			free_pages(wavetable_mem, 20-PAGE_SHIFT);
-		return -ENODEV;
-	}
-	return 0;
+	if (!pci_register_driver(&sv_driver))
+                return -ENODEV;
+        return 0;
 }
 
 static void __exit cleanup_sonicvibes(void)
 {
-	struct sv_state *s;
-
-	while ((s = devs)) {
-		devs = devs->next;
-		outb(~0, s->ioenh + SV_CODEC_INTMASK);  /* disable ints */
-		synchronize_irq();
-		inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */
-		wrindir(s, SV_CIENABLE, 0);     /* disable DMAA and DMAC */
-		/*outb(0, s->iodmaa + SV_DMA_RESET);*/
-		/*outb(0, s->iodmac + SV_DMA_RESET);*/
-		free_irq(s->irq, s);
-		release_region(s->iodmac, SV_EXTENT_DMA);
-		release_region(s->iodmaa, SV_EXTENT_DMA);
-		release_region(s->ioenh, SV_EXTENT_ENH);
-		release_region(s->iomidi, SV_EXTENT_MIDI);
-		release_region(s->iosynth, SV_EXTENT_SYNTH);
-		unregister_sound_dsp(s->dev_audio);
-		unregister_sound_mixer(s->dev_mixer);
-		unregister_sound_midi(s->dev_midi);
-		unregister_sound_special(s->dev_dmfm);
-		kfree_s(s, sizeof(struct sv_state));
-	}
-	if (wavetable_mem)
-		free_pages(wavetable_mem, 20-PAGE_SHIFT);
 	printk(KERN_INFO "sv: unloading\n");
+	pci_unregister_driver(&sv_driver);
+ 	if (wavetable_mem)
+		free_pages(wavetable_mem, 20-PAGE_SHIFT);
 }
 
 module_init(init_sonicvibes);
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.3.42/linux/drivers/sound/soundcard.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/sound/soundcard.c	Thu Feb 10 12:32:03 2000
@@ -778,16 +778,14 @@
 
 struct file_operations oss_sound_fops =
 {
-	sound_lseek,
-	sound_read,
-	sound_write,
-	NULL,			/* sound_readdir */
-	sound_poll,
-	sound_ioctl,
-	sound_mmap,
-	sound_open,
-	NULL,			/* flush */
-	sound_release
+	llseek:		sound_lseek,
+	read:		sound_read,
+	write:		sound_write,
+	poll:		sound_poll,
+	ioctl:		sound_ioctl,
+	mmap:		sound_mmap,
+	open:		sound_open,
+	release:	sound_release,
 };
 
 /*
@@ -877,8 +875,10 @@
 int init_module(void)
 {
 	int             err;
+#if FIXED_FOR_2_4_0
 	int             ints[21];
 	int             i;
+#endif
 
 	trace_init=traceinit;
 	
@@ -890,6 +890,7 @@
 		printk(KERN_ERR "sound: rebuild with PCI_QUIRKS enabled to configure this.\n");
 #endif
 		
+#if FIXED_FOR_2_4_0
 	/*
 	 * "sound=" command line handling by Harald Milz.
 	 */
@@ -900,6 +901,7 @@
 
 	if (i)
 		sound_setup("sound=", ints);
+#endif
 
 	err = create_special_devices();
 	if (err)
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/trident.c linux/drivers/sound/trident.c
--- v2.3.42/linux/drivers/sound/trident.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/sound/trident.c	Wed Feb  9 18:48:03 2000
@@ -29,6 +29,8 @@
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.11.1 Jan 28 2000 Ollie Lho
+ *	small bug in setting sample rate for 4d-nx (reported by Aaron)
  *  v0.11 Jan 27 2000 Ollie Lho
  *	DMA bug, scheduler latency, second try
  *  v0.10 Jan 24 2000 Ollie Lho
@@ -61,7 +63,6 @@
  *	"Channel Binding" ioctl extension
  */
       
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/string.h>
@@ -81,16 +82,12 @@
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
-
 #include "trident.h"
 #include "ac97_codec.h"
 
 #undef DEBUG
 
-#define DRIVER_VERSION "0.11"
+#define DRIVER_VERSION "0.11.1"
 
 /* magic numbers to protect our data structures */
 #define TRIDENT_CARD_MAGIC	0x5072696E /* "Prin" */
@@ -527,7 +524,7 @@
 		break;
 	case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
 		data[0] = (channel->delta << 24);
-		data[2] = ((channel->delta << 24) & 0xff000000) | (channel->eso & 0x00ffffff);
+		data[2] = ((channel->delta << 16) & 0xff000000) | (channel->eso & 0x00ffffff);
 		data[3] = channel->fm_vol & 0xffff;
 		break;
 	default:
@@ -1837,19 +1834,14 @@
 }
 
 static /*const*/ struct file_operations trident_audio_fops = {
-	&trident_llseek,
-	&trident_read,
-	&trident_write,
-	NULL,	/* readdir */
-	&trident_poll,
-	&trident_ioctl,
-	&trident_mmap,
-	&trident_open,
-	NULL,	/* flush */
-	&trident_release,
-	NULL,	/* fsync */
-	NULL,	/* fasync */
-	NULL,	/* lock */
+	llseek:		trident_llseek,
+	read:		trident_read,
+	write:		trident_write,
+	poll:		trident_poll,
+	ioctl:		trident_ioctl,
+	mmap:		trident_mmap,
+	open:		trident_open,
+	release:	trident_release,
 };
 
 /* trident specific AC97 functions */
@@ -1999,19 +1991,10 @@
 }
 
 static /*const*/ struct file_operations trident_mixer_fops = {
-	&trident_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&trident_ioctl_mixdev,
-	NULL,  /* mmap */
-	&trident_open_mixdev,
-	NULL,	/* flush */
-	&trident_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		trident_llseek,
+	ioctl:		trident_ioctl_mixdev,
+	open:		trident_open_mixdev,
+	release:	trident_release_mixdev,
 };
 
 /* AC97 codec initialisation. */
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/via82cxxx.c linux/drivers/sound/via82cxxx.c
--- v2.3.42/linux/drivers/sound/via82cxxx.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/via82cxxx.c	Wed Dec 31 16:00:00 1969
@@ -1,721 +0,0 @@
-/*
- * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
- *
- * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
- * See the "COPYING" file distributed with this software for more info.
- *
- * Documentation for this driver available as
- * linux/Documentation/sound/via82cxxx.txt.
- *
- * Since the mixer is called from the OSS glue the kernel lock is always held
- * on our AC97 mixing
- */
- 
-
-#define VIA_VERSION	"1.1.2"
-
-
-
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-
-#include <asm/io.h>
-
-#include "sound_config.h"
-#include "soundmodule.h"
-#include "sb.h"
-#include "ac97.h"
-
-#ifndef SOUND_LOCK
-#define SOUND_LOCK do {} while (0)
-#define SOUND_LOCK_END do {} while (0)
-#endif
-
-#define VIA_DEBUG 0	/* define to 1 to enable debugging output and checks */
-#if VIA_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#define VIA_NDEBUG 0	/* define to 1 to disable lightweight runtime checks */
-#if VIA_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
-        if(!(expr)) {					\
-        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
-        #expr,__FILE__,__FUNCTION__,__LINE__);		\
-        }
-#endif
-
-#define arraysize(x)            (sizeof(x)/sizeof(*(x)))
-
-#define MAX_CARDS	2
-
-#define	LINE_SIZE	10
-
-#define VIA_CARD_NAME	"VIA 82Cxxx Audio driver " VIA_VERSION
-#define VIA_MODULE_NAME "via82cxxx"
-#define PFX		VIA_MODULE_NAME ": "
-
-#define VIA_COUNTER_LIMIT	100000
-
-/* 82C686 function 5 (audio codec) PCI configuration registers */
-#define VIA_FUNC_ENABLE		0x42
-#define VIA_PNP_CONTROL		0x43
-#define VIA_AC97_CTRL		0x80
-
-/* PCI configuration register bits and masks */
-#define VIA_CR40_AC97_READY	0x01
-#define VIA_CR40_AC97_LOW_POWER	0x02
-#define VIA_CR40_SECONDARY_READY 0x04
-
-#define VIA_CR41_ACLINK_ENABLE	0x80
-
-#define VIA_CR42_SB_ENABLE	0x01
-#define VIA_CR42_MIDI_ENABLE	0x02
-#define VIA_CR42_FM_ENABLE	0x04
-#define VIA_CR42_GAME_ENABLE	0x08
-
-#define VIA_CR44_SECOND_CODEC_SUPPORT	(1 << 6)
-#define VIA_CR44_AC_LINK_ACCESS		(1 << 7)
-
-#define VIA_CR80_FIRST_CODEC		0
-#define VIA_CR80_SECOND_CODEC		(1 << 30)
-#define VIA_CR80_FIRST_CODEC_VALID	(1 << 25)
-#define VIA_CR80_SECOND_CODEC_VALID	(1 << 27)
-#define VIA_CR80_BUSY			(1 << 24)
-#define VIA_CR80_READ_MODE		(1 << 23)
-#define VIA_CR80_WRITE_MODE		0
-#define VIA_CR80_REG_IDX(idx)		(((idx) & 0x7E) << 16)
-
-struct via_info {
-	struct address_info sb_data;
-	struct address_info opl3_data;
-	struct pci_dev *pdev;
-	struct ac97_hwint ac97;
-	int mixer_oss_dev;
-	int have_ac97;
-};
-static struct via_info		cards [MAX_CARDS];
-static unsigned			num_cards = 0;
-
-
-static const struct {
-	int revision;
-	const char *rev_name;
-} via_chip_revs[] __initdata = {
-	{ 0x10, "A" },
-	{ 0x11, "B" },
-	{ 0x12, "C" },
-	{ 0x13, "D" },
-	{ 0x14, "E" },
-	{ 0x20, "H" },
-};
-
-static inline void via_ac97_write32 (struct pci_dev *pdev, int port, u32 data)
-{
-	struct resource *rsrc = &pdev->resource[0];
-	outw ((u16)data,rsrc->start+port);	
-	outw ((u16)(data>>16),rsrc->start+port+2);	
-}
-
-static inline u32 via_ac97_read32 (struct pci_dev *pdev, int port)
-{
-	struct resource *rsrc = &pdev->resource[0];
-	return
-		((u32)inw (rsrc->start+port)) |
-		(((u32)inw (rsrc->start+port+2)) << 16);
-}
-
-/****************************************************************
- *
- * Intel Audio Codec '97 interface
- *
- *
- */
- 
-static inline void via_ac97_wait_idle (struct pci_dev *pdev)
-{
-	u32 tmp;
-	int counter = VIA_COUNTER_LIMIT;
-	
-	DPRINTK ("ENTER\n");
-
-	assert (pdev != NULL);
-	
-	do {
-		tmp = via_ac97_read32 (pdev,VIA_AC97_CTRL);
-	} while ((tmp & VIA_CR80_BUSY) && (counter-- > 0));
-
-	DPRINTK ("EXIT%s\n", counter > 0 ? "" : ", counter limit reached");
-}
-
-
-static int via_ac97_read_reg (struct ac97_hwint *dev, u8 reg)
-{
-	u32 data;
-	struct via_info *card;
-	struct pci_dev *pdev;
-	
-	DPRINTK ("ENTER\n");
-
-	assert (dev != NULL);
-	assert (dev->driver_private != NULL);
-
-	card = (struct via_info *) dev->driver_private;
-	pdev = card->pdev;
-	assert (pdev != NULL);
-
-	via_ac97_wait_idle (pdev);
-	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
-		VIA_CR80_READ_MODE | VIA_CR80_REG_IDX(reg);
-	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
-	via_ac97_wait_idle (pdev);
-	data = via_ac97_read32 (pdev,VIA_AC97_CTRL);
-
-#if 0
-	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
-		DPRINTK ("EXIT, first codec not valid, returning -1\n");
-		return -1;
-	}
-#endif
-
-	DPRINTK ("EXIT, returning %d\n", data & 0xFFFF);
-	return data & 0xFFFF;
-}
-
-
-static int via_ac97_write_reg (struct ac97_hwint *dev, u8 reg, u16 value)
-{
-	u32 data;
-	struct via_info *card;
-	struct pci_dev *pdev;
-	
-	DPRINTK ("ENTER\n");
-
-	assert (dev != NULL);
-	assert (dev->driver_private != NULL);
-
-	card = (struct via_info *) dev->driver_private;
-	pdev = card->pdev;
-	assert (pdev != NULL);
-
-	via_ac97_wait_idle (pdev);
-	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
-		VIA_CR80_WRITE_MODE | VIA_CR80_REG_IDX(reg) | value;
-	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
-
-#if 0
-	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
-		DPRINTK ("EXIT, first codec invalid, returning -1\n");
-		return -1;
-	}
-#endif
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static int via_ac97_reset (struct ac97_hwint *dev)
-{
-	struct via_info *card;
-	struct pci_dev *pdev;
-	
-	DPRINTK ("ENTER\n");
-
-	assert (dev != NULL);
-	assert (dev->driver_private != NULL);
-
-	card = (struct via_info *) dev->driver_private;
-	pdev = card->pdev;
-	assert (pdev != NULL);
-	
-	pci_write_config_word (pdev, PCI_COMMAND, PCI_COMMAND_IO);
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static struct via_info *via_ac97_find_card_for_mixer (int dev)
-{
-	int x;
-
-	DPRINTK ("ENTER\n");
-
-	for (x = 0; x < num_cards; x++)
-		if (cards[x].mixer_oss_dev == dev) {
-			DPRINTK ("EXIT, returning %p\n", cards + x);
-			return cards + x;
-		}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return NULL;
-}
-
-
-static int
-via_ac97_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
-{
-	int rc;
-	struct via_info *card = via_ac97_find_card_for_mixer (dev);
-
-	DPRINTK ("ENTER\n");
-
-	if (card != NULL) {
-		rc = ac97_mixer_ioctl (&card->ac97, cmd, arg);
-		DPRINTK ("EXIT, returning %d\n", rc);
-		return rc;
-	}
-	
-	DPRINTK ("EXIT, returning -ENODEV\n");
-	return -ENODEV;
-
-}
-
-static struct mixer_operations via_ac97_mixer_operations =
-{
-	"VIA82Cxxx",
-	"via82cxxxAC97Mixer",
-	via_ac97_default_mixer_ioctl
-};
-
-static int __init via_attach_ac97 (struct via_info *card)
-{
-	int mixer;
-	struct ac97_hwint *mdev;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	mdev = &card->ac97;
-
-	memset (mdev, 0, sizeof (*mdev));
-	mdev->reset_device = via_ac97_reset;
-	mdev->read_reg = via_ac97_read_reg;
-	mdev->write_reg = via_ac97_write_reg;
-	mdev->driver_private = (void *) card;
-
-	if (ac97_init (mdev)) {
-		printk (KERN_ERR PFX "Unable to init AC97\n");
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
-	mixer = sound_alloc_mixerdev ();
-	if (mixer < 0 || num_mixers >= MAX_MIXER_DEV) {
-		printk (KERN_ERR PFX "Unable to alloc mixerdev\n");
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
-	mixer_devs[mixer] = &via_ac97_mixer_operations;
-	card->mixer_oss_dev = mixer;
-
-	/* Some reasonable default values.  */
-	ac97_set_mixer (mdev, SOUND_MIXER_VOLUME, (85 << 8) | 85);
-	ac97_set_mixer (mdev, SOUND_MIXER_SPEAKER, 100);
-	ac97_set_mixer (mdev, SOUND_MIXER_PCM, (65 << 8) | 65);
-	ac97_set_mixer (mdev, SOUND_MIXER_CD, (65 << 8) | 65);
-
-	printk (KERN_INFO PFX "Initialized AC97 mixer\n");
-	
-	card->have_ac97 = mixer;
-	
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static void via_unload_ac97 (struct via_info *card)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	if (card->have_ac97 >= 0)
-		sound_unload_mixerdev (card->have_ac97);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-/****************************************************************
- *
- * /proc/driver/via82cxxx/info
- *
- *
- */
-
-static int via_info_read_proc (char *page, char **start, off_t off,
-			       int count, int *eof, void *data)
-{
-#define YN(val,bit) (((val) & (bit)) ? "yes" : "no")
-
-	int len = 0, i;
-	u8 r40, r41, r42, r44;
-	
-	DPRINTK ("ENTER\n");
-
-	len += sprintf (page+len, VIA_CARD_NAME "\n\n");
-	
-	for (i = 0; i < num_cards; i++) {
-		pci_read_config_byte (cards[i].pdev, 0x40, &r40);
-		pci_read_config_byte (cards[i].pdev, 0x42, &r41);
-		pci_read_config_byte (cards[i].pdev, 0x42, &r42);
-		pci_read_config_byte (cards[i].pdev, 0x44, &r44);
-	
-		len += sprintf (page+len,
-			"40  AC97 Codec Ready: %s\n"
-			"    AC97 Codec Low-power: %s\n"
-			"    Secondary Codec Ready: %s\n"
-
-			"41  AC-Link Interface Enable: %s\n"
-
-			"42  Game port enabled: %s\n"
-			"    SoundBlaster enabled: %s\n"
-			"    FM enabled: %s\n"
-			"    MIDI enabled: %s\n"
-			
-			"44  AC-Link Interface Access: %s\n"
-			"    Secondary Codec Support: %s\n"
-			
-			"\n",
-			
-			YN (r40, VIA_CR40_AC97_READY),
-			YN (r40, VIA_CR40_AC97_LOW_POWER),
-			YN (r40, VIA_CR40_SECONDARY_READY),
-
-			YN (r41, VIA_CR41_ACLINK_ENABLE),
-
-			YN (r42, VIA_CR42_GAME_ENABLE),
-			YN (r42, VIA_CR42_SB_ENABLE),
-			YN (r42, VIA_CR42_FM_ENABLE),
-			YN (r42, VIA_CR42_MIDI_ENABLE),
-
-			YN (r44, VIA_CR44_AC_LINK_ACCESS),
-			YN (r44, VIA_CR44_SECOND_CODEC_SUPPORT)
-			
-			);
-	}
-	
-	DPRINTK("EXIT, returning %d\n", len);
-	return len;
-
-#undef YN
-}
-
-
-/****************************************************************
- *
- * /proc/driver/via82cxxx
- *
- *
- */
-
-static int __init via_init_proc (void)
-{
-	DPRINTK ("ENTER\n");
-
-	proc_mkdir ("driver/via_audio", 0);
-	create_proc_read_entry ("driver/via_audio/info", 0, 0, via_info_read_proc, NULL);
-	
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-
-static void __exit via_cleanup_proc (void)
-{
-	DPRINTK ("ENTER\n");
-	remove_proc_entry ("driver/via_audio/info", NULL);
-	remove_proc_entry ("driver/via_audio", NULL);
-	DPRINTK("EXIT\n");
-}
-
-
-#else
-
-static inline int via_init_proc (void) { return 0; }
-static inline void via_cleanup_proc (void) {}
-
-#endif /* CONFIG_PROC_FS */
-
-
-/****************************************************************
- *
- * Legacy SoundBlaster Pro, FM support via OSS
- *
- *
- */
-
-static void __init via_attach_sb(struct address_info *hw_config)
-{
-	DPRINTK ("ENTER\n");
-
-	if(!sb_dsp_init(hw_config))
-		hw_config->slots[0] = -1;
-
-	DPRINTK("EXIT\n");
-}
-
-
-static int __init via_probe_sb(struct address_info *hw_config)
-{
-	DPRINTK ("ENTER\n");
-
-	if (check_region(hw_config->io_base, 16))
-	{
-		printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
-		       hw_config->io_base);
-		return 0;
-	}
-	DPRINTK("EXIT after sb_dsp_detect\n");
-	return sb_dsp_detect(hw_config, 0, 0);
-}
-
-
-static void __exit via_unload_sb(struct address_info *hw_config)
-{
-	DPRINTK ("ENTER\n");
-
-	if(hw_config->slots[0] != -1)
-		sb_dsp_unload(hw_config, 1);
-
-	DPRINTK("EXIT\n");
-}
-
-
-static const struct {
-	int sb_irq,
-	    sb_dma,
-	    midi_base,
-	    sb_io_base;
-} via_pnp_data[] __initdata = {
-	{ 5, 0, 0x300, 0x220 },
-	{ 7, 1, 0x310, 0x240 },
-	{ 9, 2, 0x320, 0x260 },
-	{ 10,3, 0x330, 0x280 },
-};
-
-
-/****************************************************************
- *
- * Chip setup and kernel registration
- *
- *
- */
-
-static int __init via82cxxx_install (struct pci_dev *pcidev)
-{
-	int sb_io_base;
-	int sb_irq;
-	int sb_dma;
-	int midi_base, rc;
-	u8 tmp8;
-	struct via_info *card = &cards[num_cards];
-	
-	DPRINTK ("ENTER\n");
-
-	card->pdev = pcidev;
-	card->have_ac97 = -1;
-	
-	/* turn off legacy features, if not already */
-	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
-	tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
-		  VIA_CR42_FM_ENABLE);
-	pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
-
-	/* 
-	 * try to init AC97 mixer device
-	 */
-	rc = via_attach_ac97 (card);
-	if (rc) {
-		printk (KERN_WARNING PFX
-			"AC97 init failed, SB legacy mode only\n");
-	}
-	
-	/* turn on legacy features */
-	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
-	tmp8 |= VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
-		VIA_CR42_FM_ENABLE;
-	pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
-
-	/* read legacy PNP info byte */
-	pci_read_config_byte (pcidev, VIA_PNP_CONTROL, &tmp8);
-	pci_write_config_byte (pcidev, VIA_PNP_CONTROL, tmp8);
-	
-	sb_irq = via_pnp_data[((tmp8 >> 6) & 0x03)].sb_irq;
-	sb_dma = via_pnp_data[((tmp8 >> 4) & 0x03)].sb_dma;
-	midi_base = via_pnp_data[((tmp8 >> 2) & 0x03)].midi_base;
-	sb_io_base = via_pnp_data[(tmp8 & 0x03)].sb_io_base;
-
-	udelay(100);
-	
-	printk(KERN_INFO PFX "legacy "
-	       "MIDI: 0x%X, SB: 0x%X / %d IRQ / %d DMA\n",
-		midi_base, sb_io_base, sb_irq, sb_dma);
-		
-	card->sb_data.name = VIA_CARD_NAME;
-	card->sb_data.card_subtype = MDL_SBPRO;
-	card->sb_data.io_base = sb_io_base;
-	card->sb_data.irq = sb_irq;
-	card->sb_data.dma = sb_dma;
-	
-	/* register legacy SoundBlaster Pro */
-	if (!via_probe_sb (&card->sb_data)) {
-		printk (KERN_ERR PFX
-			"SB probe @ 0x%X failed, aborting\n",
-			sb_io_base);
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
-	via_attach_sb (&card->sb_data);
-
-	card->opl3_data.name = card->sb_data.name;
-	card->opl3_data.io_base = midi_base;
-	card->opl3_data.irq = -1;
-	
-	/* register legacy MIDI */
-	if (!probe_uart401 (&card->opl3_data)) {
-		printk (KERN_WARNING PFX
-			"MIDI probe @ 0x%X failed, continuing\n",
-			midi_base);
-		card->opl3_data.io_base = 0;
-	} else {
-		attach_uart401 (&card->opl3_data);
-	}
-
-	num_cards++;	
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/*
- * 	This loop walks the PCI configuration database and finds where
- *	the sound cards are.
- *
- *	Note - only a single PCI scan occurs, eliminating possibility
- *	of multiple audio chips
- *
- */
- 
-static int __init probe_via82cxxx (void)
-{
-	struct pci_dev *pcidev = NULL;
-
-	DPRINTK ("ENTER\n");
-
-	pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
-				  PCI_DEVICE_ID_VIA_82C686_5, NULL);
-
-	if (!pcidev || via82cxxx_install (pcidev) != 0) {
-		printk (KERN_ERR PFX "audio init failed\n");
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/*
- *	This function is called when the user or kernel loads the 
- *	module into memory.
- */
-
-
-static int __init init_via82cxxx_module(void)
-{
-	u8 tmp;
-	int i;
-	const char *rev = "unknown!";
-	
-	memset (cards, 0, sizeof (cards));
-	
-	DPRINTK ("ENTER\n");
-
-	if (!pci_present ()) {
-		printk (KERN_DEBUG PFX "PCI not present, exiting\n");
-		DPRINTK ("EXIT, returning -ENODEV\n");
-		return -ENODEV;
-	}
-
-	if (probe_via82cxxx() != 0) {
-		printk(KERN_ERR PFX "probe failed, aborting\n");
-		/* XXX unload cards registered so far, if any */
-		DPRINTK ("EXIT, returning -ENODEV\n");
-		return -ENODEV;
-	}
-
-	pci_read_config_byte (cards[0].pdev, PCI_REVISION_ID, &tmp);
-	for (i = 0; i < arraysize(via_chip_revs); i++)
-		if (via_chip_revs[i].revision == tmp) {
-			rev = via_chip_revs[i].rev_name;
-			break;
-		}
-	printk (KERN_INFO PFX VIA_CARD_NAME " loaded\n");
-	printk (KERN_INFO PFX "Chip rev %s.  Features: SBPro compat%s%s\n",
-		rev,
-		cards[0].opl3_data.io_base == 0 ? "" : ", MPU-401 MIDI",
-		cards[0].have_ac97 == -1 ? "" : ", AC97 mixer");
-	
-	if (via_init_proc () != 0) {
-		printk (KERN_WARNING PFX
-			"Unable to init experimental /proc, ignoring\n");
-	}
-
-	/*
-	 *	Binds us to the sound subsystem	
-	 */
-	SOUND_LOCK;
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-/*
- *	This is called when it is removed. It will only be removed 
- *	when its use count is 0. For sound the SOUND_LOCK/SOUND_UNLOCK
- *	macros hide the entire work for this.
- */
- 
-static void __exit cleanup_via82cxxx_module(void)
-{
-	DPRINTK("ENTER\n");
-	
-	if (cards[0].opl3_data.io_base)
-		unload_uart401 (&cards[0].opl3_data);
-
-	via_unload_sb (&cards[0].sb_data);
-	
-	via_unload_ac97 (&cards[0]);
-
-	via_cleanup_proc ();
-	
-	/*
-	 *	Final clean up with the sound layer
-	 */
-	SOUND_LOCK_END;
-
-	DPRINTK("EXIT\n");
-}
-
-module_init(init_via82cxxx_module);
-module_exit(cleanup_via82cxxx_module);
-
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- v2.3.42/linux/drivers/sound/via82cxxx_audio.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/via82cxxx_audio.c	Wed Feb  9 18:54:11 2000
@@ -0,0 +1,721 @@
+/*
+ * Support for VIA 82Cxxx Audio Codecs
+ * Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ *
+ * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
+ * See the "COPYING" file distributed with this software for more info.
+ *
+ * Documentation for this driver available as
+ * linux/Documentation/sound/via82cxxx.txt.
+ *
+ * Since the mixer is called from the OSS glue the kernel lock is always held
+ * on our AC97 mixing
+ */
+ 
+
+#define VIA_VERSION	"1.1.2.1"
+
+
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+
+#include <asm/io.h>
+
+#include "sound_config.h"
+#include "soundmodule.h"
+#include "sb.h"
+#include "ac97.h"
+
+#ifndef SOUND_LOCK
+#define SOUND_LOCK do {} while (0)
+#define SOUND_LOCK_END do {} while (0)
+#endif
+
+#define VIA_DEBUG 0	/* define to 1 to enable debugging output and checks */
+#if VIA_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define VIA_NDEBUG 0	/* define to 1 to disable lightweight runtime checks */
+#if VIA_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+        if(!(expr)) {					\
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
+        #expr,__FILE__,__FUNCTION__,__LINE__);		\
+        }
+#endif
+
+#define arraysize(x)            (sizeof(x)/sizeof(*(x)))
+
+#define MAX_CARDS	2
+
+#define	LINE_SIZE	10
+
+#define VIA_CARD_NAME	"VIA 82Cxxx Audio driver " VIA_VERSION
+#define VIA_MODULE_NAME "via_audio"
+#define PFX		VIA_MODULE_NAME ": "
+
+#define VIA_COUNTER_LIMIT	100000
+
+/* 82C686 function 5 (audio codec) PCI configuration registers */
+#define VIA_FUNC_ENABLE		0x42
+#define VIA_PNP_CONTROL		0x43
+#define VIA_AC97_CTRL		0x80
+
+/* PCI configuration register bits and masks */
+#define VIA_CR40_AC97_READY	0x01
+#define VIA_CR40_AC97_LOW_POWER	0x02
+#define VIA_CR40_SECONDARY_READY 0x04
+
+#define VIA_CR41_ACLINK_ENABLE	0x80
+
+#define VIA_CR42_SB_ENABLE	0x01
+#define VIA_CR42_MIDI_ENABLE	0x02
+#define VIA_CR42_FM_ENABLE	0x04
+#define VIA_CR42_GAME_ENABLE	0x08
+
+#define VIA_CR44_SECOND_CODEC_SUPPORT	(1 << 6)
+#define VIA_CR44_AC_LINK_ACCESS		(1 << 7)
+
+#define VIA_CR80_FIRST_CODEC		0
+#define VIA_CR80_SECOND_CODEC		(1 << 30)
+#define VIA_CR80_FIRST_CODEC_VALID	(1 << 25)
+#define VIA_CR80_SECOND_CODEC_VALID	(1 << 27)
+#define VIA_CR80_BUSY			(1 << 24)
+#define VIA_CR80_READ_MODE		(1 << 23)
+#define VIA_CR80_WRITE_MODE		0
+#define VIA_CR80_REG_IDX(idx)		(((idx) & 0x7E) << 16)
+
+struct via_info {
+	struct address_info sb_data;
+	struct address_info opl3_data;
+	struct pci_dev *pdev;
+	struct ac97_hwint ac97;
+	int mixer_oss_dev;
+	int have_ac97;
+};
+static struct via_info		cards [MAX_CARDS];
+static unsigned			num_cards = 0;
+
+
+static const struct {
+	int revision;
+	const char *rev_name;
+} via_chip_revs[] __initdata = {
+	{ 0x10, "A" },
+	{ 0x11, "B" },
+	{ 0x12, "C" },
+	{ 0x13, "D" },
+	{ 0x14, "E" },
+	{ 0x20, "H" },
+};
+
+static inline void via_ac97_write32 (struct pci_dev *pdev, int port, u32 data)
+{
+	struct resource *rsrc = &pdev->resource[0];
+	outw ((u16)data,rsrc->start+port);	
+	outw ((u16)(data>>16),rsrc->start+port+2);	
+}
+
+static inline u32 via_ac97_read32 (struct pci_dev *pdev, int port)
+{
+	struct resource *rsrc = &pdev->resource[0];
+	return
+		((u32)inw (rsrc->start+port)) |
+		(((u32)inw (rsrc->start+port+2)) << 16);
+}
+
+/****************************************************************
+ *
+ * Intel Audio Codec '97 interface
+ *
+ *
+ */
+ 
+static inline void via_ac97_wait_idle (struct pci_dev *pdev)
+{
+	u32 tmp;
+	int counter = VIA_COUNTER_LIMIT;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (pdev != NULL);
+	
+	do {
+		tmp = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+	} while ((tmp & VIA_CR80_BUSY) && (counter-- > 0));
+
+	DPRINTK ("EXIT%s\n", counter > 0 ? "" : ", counter limit reached");
+}
+
+
+static int via_ac97_read_reg (struct ac97_hwint *dev, u8 reg)
+{
+	u32 data;
+	struct via_info *card;
+	struct pci_dev *pdev;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (dev != NULL);
+	assert (dev->driver_private != NULL);
+
+	card = (struct via_info *) dev->driver_private;
+	pdev = card->pdev;
+	assert (pdev != NULL);
+
+	via_ac97_wait_idle (pdev);
+	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+		VIA_CR80_READ_MODE | VIA_CR80_REG_IDX(reg);
+	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+	via_ac97_wait_idle (pdev);
+	data = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+
+#if 0
+	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+		DPRINTK ("EXIT, first codec not valid, returning -1\n");
+		return -1;
+	}
+#endif
+
+	DPRINTK ("EXIT, returning %d\n", data & 0xFFFF);
+	return data & 0xFFFF;
+}
+
+
+static int via_ac97_write_reg (struct ac97_hwint *dev, u8 reg, u16 value)
+{
+	u32 data;
+	struct via_info *card;
+	struct pci_dev *pdev;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (dev != NULL);
+	assert (dev->driver_private != NULL);
+
+	card = (struct via_info *) dev->driver_private;
+	pdev = card->pdev;
+	assert (pdev != NULL);
+
+	via_ac97_wait_idle (pdev);
+	data =	VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+		VIA_CR80_WRITE_MODE | VIA_CR80_REG_IDX(reg) | value;
+	via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+
+#if 0
+	if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+		DPRINTK ("EXIT, first codec invalid, returning -1\n");
+		return -1;
+	}
+#endif
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static int via_ac97_reset (struct ac97_hwint *dev)
+{
+	struct via_info *card;
+	struct pci_dev *pdev;
+	
+	DPRINTK ("ENTER\n");
+
+	assert (dev != NULL);
+	assert (dev->driver_private != NULL);
+
+	card = (struct via_info *) dev->driver_private;
+	pdev = card->pdev;
+	assert (pdev != NULL);
+	
+	pci_write_config_word (pdev, PCI_COMMAND, PCI_COMMAND_IO);
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static struct via_info *via_ac97_find_card_for_mixer (int dev)
+{
+	int x;
+
+	DPRINTK ("ENTER\n");
+
+	for (x = 0; x < num_cards; x++)
+		if (cards[x].mixer_oss_dev == dev) {
+			DPRINTK ("EXIT, returning %p\n", cards + x);
+			return cards + x;
+		}
+
+	DPRINTK ("EXIT, returning 0\n");
+	return NULL;
+}
+
+
+static int
+via_ac97_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+	int rc;
+	struct via_info *card = via_ac97_find_card_for_mixer (dev);
+
+	DPRINTK ("ENTER\n");
+
+	if (card != NULL) {
+		rc = ac97_mixer_ioctl (&card->ac97, cmd, arg);
+		DPRINTK ("EXIT, returning %d\n", rc);
+		return rc;
+	}
+	
+	DPRINTK ("EXIT, returning -ENODEV\n");
+	return -ENODEV;
+
+}
+
+static struct mixer_operations via_ac97_mixer_operations =
+{
+	"VIA82Cxxx",
+	"via82cxxxAC97Mixer",
+	via_ac97_default_mixer_ioctl
+};
+
+static int __init via_attach_ac97 (struct via_info *card)
+{
+	int mixer;
+	struct ac97_hwint *mdev;
+
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+
+	mdev = &card->ac97;
+
+	memset (mdev, 0, sizeof (*mdev));
+	mdev->reset_device = via_ac97_reset;
+	mdev->read_reg = via_ac97_read_reg;
+	mdev->write_reg = via_ac97_write_reg;
+	mdev->driver_private = (void *) card;
+
+	if (ac97_init (mdev)) {
+		printk (KERN_ERR PFX "Unable to init AC97\n");
+		DPRINTK ("EXIT, returning -1\n");
+		return -1;
+	}
+	mixer = sound_alloc_mixerdev ();
+	if (mixer < 0 || num_mixers >= MAX_MIXER_DEV) {
+		printk (KERN_ERR PFX "Unable to alloc mixerdev\n");
+		DPRINTK ("EXIT, returning -1\n");
+		return -1;
+	}
+	mixer_devs[mixer] = &via_ac97_mixer_operations;
+	card->mixer_oss_dev = mixer;
+
+	/* Some reasonable default values.  */
+	ac97_set_mixer (mdev, SOUND_MIXER_VOLUME, (85 << 8) | 85);
+	ac97_set_mixer (mdev, SOUND_MIXER_SPEAKER, 100);
+	ac97_set_mixer (mdev, SOUND_MIXER_PCM, (65 << 8) | 65);
+	ac97_set_mixer (mdev, SOUND_MIXER_CD, (65 << 8) | 65);
+
+	printk (KERN_INFO PFX "Initialized AC97 mixer\n");
+	
+	card->have_ac97 = mixer;
+	
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+static void via_unload_ac97 (struct via_info *card)
+{
+	DPRINTK ("ENTER\n");
+
+	assert (card != NULL);
+
+	if (card->have_ac97 >= 0)
+		sound_unload_mixerdev (card->have_ac97);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+#ifdef CONFIG_PROC_FS
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx/info
+ *
+ *
+ */
+
+static int via_info_read_proc (char *page, char **start, off_t off,
+			       int count, int *eof, void *data)
+{
+#define YN(val,bit) (((val) & (bit)) ? "yes" : "no")
+
+	int len = 0, i;
+	u8 r40, r41, r42, r44;
+	
+	DPRINTK ("ENTER\n");
+
+	len += sprintf (page+len, VIA_CARD_NAME "\n\n");
+	
+	for (i = 0; i < num_cards; i++) {
+		pci_read_config_byte (cards[i].pdev, 0x40, &r40);
+		pci_read_config_byte (cards[i].pdev, 0x42, &r41);
+		pci_read_config_byte (cards[i].pdev, 0x42, &r42);
+		pci_read_config_byte (cards[i].pdev, 0x44, &r44);
+	
+		len += sprintf (page+len,
+			"40  AC97 Codec Ready: %s\n"
+			"    AC97 Codec Low-power: %s\n"
+			"    Secondary Codec Ready: %s\n"
+
+			"41  AC-Link Interface Enable: %s\n"
+
+			"42  Game port enabled: %s\n"
+			"    SoundBlaster enabled: %s\n"
+			"    FM enabled: %s\n"
+			"    MIDI enabled: %s\n"
+			
+			"44  AC-Link Interface Access: %s\n"
+			"    Secondary Codec Support: %s\n"
+			
+			"\n",
+			
+			YN (r40, VIA_CR40_AC97_READY),
+			YN (r40, VIA_CR40_AC97_LOW_POWER),
+			YN (r40, VIA_CR40_SECONDARY_READY),
+
+			YN (r41, VIA_CR41_ACLINK_ENABLE),
+
+			YN (r42, VIA_CR42_GAME_ENABLE),
+			YN (r42, VIA_CR42_SB_ENABLE),
+			YN (r42, VIA_CR42_FM_ENABLE),
+			YN (r42, VIA_CR42_MIDI_ENABLE),
+
+			YN (r44, VIA_CR44_AC_LINK_ACCESS),
+			YN (r44, VIA_CR44_SECOND_CODEC_SUPPORT)
+			
+			);
+	}
+	
+	DPRINTK("EXIT, returning %d\n", len);
+	return len;
+
+#undef YN
+}
+
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx
+ *
+ *
+ */
+
+static int __init via_init_proc (void)
+{
+	DPRINTK ("ENTER\n");
+
+	proc_mkdir ("driver/via_audio", 0);
+	create_proc_read_entry ("driver/via_audio/info", 0, 0, via_info_read_proc, NULL);
+	
+	DPRINTK("EXIT\n");
+	return 0;
+}
+
+
+
+static void __exit via_cleanup_proc (void)
+{
+	DPRINTK ("ENTER\n");
+	remove_proc_entry ("driver/via_audio/info", NULL);
+	remove_proc_entry ("driver/via_audio", NULL);
+	DPRINTK("EXIT\n");
+}
+
+
+#else
+
+static inline int via_init_proc (void) { return 0; }
+static inline void via_cleanup_proc (void) {}
+
+#endif /* CONFIG_PROC_FS */
+
+
+/****************************************************************
+ *
+ * Legacy SoundBlaster Pro, FM support via OSS
+ *
+ *
+ */
+
+static void __init via_attach_sb(struct address_info *hw_config)
+{
+	DPRINTK ("ENTER\n");
+
+	if(!sb_dsp_init(hw_config))
+		hw_config->slots[0] = -1;
+
+	DPRINTK("EXIT\n");
+}
+
+
+static int __init via_probe_sb(struct address_info *hw_config)
+{
+	DPRINTK ("ENTER\n");
+
+	if (check_region(hw_config->io_base, 16))
+	{
+		printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
+		       hw_config->io_base);
+		return 0;
+	}
+	DPRINTK("EXIT after sb_dsp_detect\n");
+	return sb_dsp_detect(hw_config, 0, 0);
+}
+
+
+static void __exit via_unload_sb(struct address_info *hw_config)
+{
+	DPRINTK ("ENTER\n");
+
+	if(hw_config->slots[0] != -1)
+		sb_dsp_unload(hw_config, 1);
+
+	DPRINTK("EXIT\n");
+}
+
+
+static const struct {
+	int sb_irq,
+	    sb_dma,
+	    midi_base,
+	    sb_io_base;
+} via_pnp_data[] __initdata = {
+	{ 5, 0, 0x300, 0x220 },
+	{ 7, 1, 0x310, 0x240 },
+	{ 9, 2, 0x320, 0x260 },
+	{ 10,3, 0x330, 0x280 },
+};
+
+
+/****************************************************************
+ *
+ * Chip setup and kernel registration
+ *
+ *
+ */
+
+static int __init via82cxxx_install (struct pci_dev *pcidev)
+{
+	int sb_io_base;
+	int sb_irq;
+	int sb_dma;
+	int midi_base, rc;
+	u8 tmp8;
+	struct via_info *card = &cards[num_cards];
+	
+	DPRINTK ("ENTER\n");
+
+	card->pdev = pcidev;
+	card->have_ac97 = -1;
+	
+	/* turn off legacy features, if not already */
+	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
+	tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
+		  VIA_CR42_FM_ENABLE);
+	pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
+
+	/* 
+	 * try to init AC97 mixer device
+	 */
+	rc = via_attach_ac97 (card);
+	if (rc) {
+		printk (KERN_WARNING PFX
+			"AC97 init failed, SB legacy mode only\n");
+	}
+	
+	/* turn on legacy features */
+	pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
+	tmp8 |= VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
+		VIA_CR42_FM_ENABLE;
+	pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
+
+	/* read legacy PNP info byte */
+	pci_read_config_byte (pcidev, VIA_PNP_CONTROL, &tmp8);
+	pci_write_config_byte (pcidev, VIA_PNP_CONTROL, tmp8);
+	
+	sb_irq = via_pnp_data[((tmp8 >> 6) & 0x03)].sb_irq;
+	sb_dma = via_pnp_data[((tmp8 >> 4) & 0x03)].sb_dma;
+	midi_base = via_pnp_data[((tmp8 >> 2) & 0x03)].midi_base;
+	sb_io_base = via_pnp_data[(tmp8 & 0x03)].sb_io_base;
+
+	udelay(100);
+	
+	printk(KERN_INFO PFX "legacy "
+	       "MIDI: 0x%X, SB: 0x%X / %d IRQ / %d DMA\n",
+		midi_base, sb_io_base, sb_irq, sb_dma);
+		
+	card->sb_data.name = VIA_CARD_NAME;
+	card->sb_data.card_subtype = MDL_SBPRO;
+	card->sb_data.io_base = sb_io_base;
+	card->sb_data.irq = sb_irq;
+	card->sb_data.dma = sb_dma;
+	
+	/* register legacy SoundBlaster Pro */
+	if (!via_probe_sb (&card->sb_data)) {
+		printk (KERN_ERR PFX
+			"SB probe @ 0x%X failed, aborting\n",
+			sb_io_base);
+		DPRINTK ("EXIT, returning -1\n");
+		return -1;
+	}
+	via_attach_sb (&card->sb_data);
+
+	card->opl3_data.name = card->sb_data.name;
+	card->opl3_data.io_base = midi_base;
+	card->opl3_data.irq = -1;
+	
+	/* register legacy MIDI */
+	if (!probe_uart401 (&card->opl3_data)) {
+		printk (KERN_WARNING PFX
+			"MIDI probe @ 0x%X failed, continuing\n",
+			midi_base);
+		card->opl3_data.io_base = 0;
+	} else {
+		attach_uart401 (&card->opl3_data);
+	}
+
+	num_cards++;	
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+/*
+ * 	This loop walks the PCI configuration database and finds where
+ *	the sound cards are.
+ *
+ *	Note - only a single PCI scan occurs, eliminating possibility
+ *	of multiple audio chips
+ *
+ */
+ 
+static int __init probe_via82cxxx (void)
+{
+	struct pci_dev *pcidev = NULL;
+
+	DPRINTK ("ENTER\n");
+
+	pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
+				  PCI_DEVICE_ID_VIA_82C686_5, NULL);
+
+	if (!pcidev || via82cxxx_install (pcidev) != 0) {
+		printk (KERN_ERR PFX "audio init failed\n");
+		DPRINTK ("EXIT, returning -1\n");
+		return -1;
+	}
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+/*
+ *	This function is called when the user or kernel loads the 
+ *	module into memory.
+ */
+
+
+static int __init init_via82cxxx_module(void)
+{
+	u8 tmp;
+	int i;
+	const char *rev = "unknown!";
+	
+	memset (cards, 0, sizeof (cards));
+	
+	DPRINTK ("ENTER\n");
+
+	if (!pci_present ()) {
+		printk (KERN_DEBUG PFX "PCI not present, exiting\n");
+		DPRINTK ("EXIT, returning -ENODEV\n");
+		return -ENODEV;
+	}
+
+	if (probe_via82cxxx() != 0) {
+		printk(KERN_ERR PFX "probe failed, aborting\n");
+		/* XXX unload cards registered so far, if any */
+		DPRINTK ("EXIT, returning -ENODEV\n");
+		return -ENODEV;
+	}
+
+	pci_read_config_byte (cards[0].pdev, PCI_REVISION_ID, &tmp);
+	for (i = 0; i < arraysize(via_chip_revs); i++)
+		if (via_chip_revs[i].revision == tmp) {
+			rev = via_chip_revs[i].rev_name;
+			break;
+		}
+	printk (KERN_INFO PFX VIA_CARD_NAME " loaded\n");
+	printk (KERN_INFO PFX "Chip rev %s.  Features: SBPro compat%s%s\n",
+		rev,
+		cards[0].opl3_data.io_base == 0 ? "" : ", MPU-401 MIDI",
+		cards[0].have_ac97 == -1 ? "" : ", AC97 mixer");
+	
+	if (via_init_proc () != 0) {
+		printk (KERN_WARNING PFX
+			"Unable to init experimental /proc, ignoring\n");
+	}
+
+	/*
+	 *	Binds us to the sound subsystem	
+	 */
+	SOUND_LOCK;
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+/*
+ *	This is called when it is removed. It will only be removed 
+ *	when its use count is 0. For sound the SOUND_LOCK/SOUND_UNLOCK
+ *	macros hide the entire work for this.
+ */
+ 
+static void __exit cleanup_via82cxxx_module(void)
+{
+	DPRINTK("ENTER\n");
+	
+	if (cards[0].opl3_data.io_base)
+		unload_uart401 (&cards[0].opl3_data);
+
+	via_unload_sb (&cards[0].sb_data);
+	
+	via_unload_ac97 (&cards[0]);
+
+	via_cleanup_proc ();
+	
+	/*
+	 *	Final clean up with the sound layer
+	 */
+	SOUND_LOCK_END;
+
+	DPRINTK("EXIT\n");
+}
+
+module_init(init_via82cxxx_module);
+module_exit(cleanup_via82cxxx_module);
+
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/vwsnd.c linux/drivers/sound/vwsnd.c
--- v2.3.42/linux/drivers/sound/vwsnd.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/vwsnd.c	Wed Feb  9 11:42:35 2000
@@ -3029,19 +3029,14 @@
 }
 
 static struct file_operations vwsnd_audio_fops = {
-	&vwsnd_audio_llseek,
-	&vwsnd_audio_read,
-	&vwsnd_audio_write,
-	NULL,				/* readdir */
-	&vwsnd_audio_poll,
-	&vwsnd_audio_ioctl,
-	&vwsnd_audio_mmap,
-	&vwsnd_audio_open,
-	NULL,				/* flush */
-	&vwsnd_audio_release,
-	NULL,				/* fsync */
-	NULL,				/* fasync */
-	NULL,				/* lock */
+	llseek:		vwsnd_audio_llseek,
+	read:		vwsnd_audio_read,
+	write:		vwsnd_audio_write,
+	poll:		vwsnd_audio_poll,
+	ioctl:		vwsnd_audio_ioctl,
+	mmap:		vwsnd_audio_mmap,
+	open:		vwsnd_audio_open,
+	release:	vwsnd_audio_release,
 };
 
 /*****************************************************************************/
@@ -3238,19 +3233,10 @@
 }
 
 static struct file_operations vwsnd_mixer_fops = {
-	&vwsnd_mixer_llseek,
-	NULL,				/* read */
-	NULL,				/* write */
-	NULL,				/* readdir */
-	NULL,				/* poll */
-	&vwsnd_mixer_ioctl,
-	NULL,				/* mmap */
-	&vwsnd_mixer_open,
-	NULL,				/* flush */
-	&vwsnd_mixer_release,
-	NULL,				/* fsync */
-	NULL,				/* fasync */
-	NULL,				/* lock */
+	llseek:		vwsnd_mixer_llseek,
+	ioctl:		vwsnd_mixer_ioctl,
+	open:		vwsnd_mixer_open,
+	release:	vwsnd_mixer_release,
 };
 
 /*****************************************************************************/
diff -u --recursive --new-file v2.3.42/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.3.42/linux/drivers/sound/wavfront.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/wavfront.c	Wed Feb  9 11:42:35 2000
@@ -2002,19 +2002,10 @@
 }
 
 static /*const*/ struct file_operations wavefront_fops = {
-	&wavefront_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&wavefront_ioctl,
-	NULL,  /* mmap */
-	&wavefront_open,
-	NULL,  /* flush */
-	&wavefront_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		wavefront_llseek,
+	ioctl:		wavefront_ioctl,
+	open:		wavefront_open,
+	release:	wavefront_release,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c
--- v2.3.42/linux/drivers/telephony/ixj.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/telephony/ixj.c	Wed Feb  9 11:42:35 2000
@@ -3922,20 +3922,12 @@
 
 struct file_operations ixj_fops =
 {
-	NULL,			/* ixj_lseek */
-	ixj_enhanced_read,
-	ixj_enhanced_write,
-	NULL,			/* ixj_readdir */
-	ixj_poll,
-	ixj_ioctl,
-	NULL,			/* ixj_mmap */
-//  ixj_open,
-	NULL,			/* ixj_open */
-	NULL,			/* ixj_flush */
-	ixj_release,
-	NULL,			/* ixj_fsync */
-	ixj_fasync,		/* ixj_fasync */
-	NULL			/* lock */
+	read:		ixj_enhanced_read,
+	write:		ixj_enhanced_write,
+	poll:		ixj_poll,
+	ioctl:		ixj_ioctl,
+	release:	ixj_release,
+	fasync:		ixj_fasync,
 };
 
 static int ixj_linetest(int board)
diff -u --recursive --new-file v2.3.42/linux/drivers/telephony/phonedev.c linux/drivers/telephony/phonedev.c
--- v2.3.42/linux/drivers/telephony/phonedev.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/telephony/phonedev.c	Wed Feb  9 11:42:35 2000
@@ -112,16 +112,7 @@
 
 static struct file_operations phone_fops =
 {
-	NULL,
-	NULL,
-	NULL,
-	NULL,			/* readdir */
-	NULL,
-	NULL,
-	NULL,
-	phone_open,
-	NULL,			/* flush */
-	NULL
+	open:		phone_open,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.42/linux/drivers/usb/Config.in	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/Config.in	Tue Feb  8 17:11:13 2000
@@ -10,6 +10,9 @@
 comment 'USB Controllers'
    dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
    dep_tristate '  UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
+   if [ "$CONFIG_USB_UHCI_ALT" != "n" ]; then
+      bool '    UHCI unlink optimizations (EXPERIMENTAL)' CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
+   fi
    dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
 
 comment 'Miscellaneous USB options'
@@ -26,6 +29,7 @@
       bool '    USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR
       bool '    USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT
       bool '    USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI
+      bool '    USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA
       bool '    USB Belkin Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN
       bool '    USB Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PERACOM
    fi
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.42/linux/drivers/usb/Makefile	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/Makefile	Tue Feb  8 17:07:22 2000
@@ -90,8 +90,8 @@
 
 # Translate to Rules.make lists.
 
-O_OBJS		:= $(filter-out $(export-objs), $(obj-y))
-OX_OBJS		:= $(filter     $(export-objs), $(obj-y))
+O_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-y)))
+OX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-y)))
 M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
 MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
 MI_OBJS		:= $(sort $(filter-out $(export-objs), $(int-m)))
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.42/linux/drivers/usb/acm.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/acm.c	Wed Feb  9 11:51:13 2000
@@ -223,21 +223,25 @@
 
 	if (!ACM_READY(acm)) return;
 
+	if (urb->status)
+		dbg("nonzero read bulk status received: %d", urb->status);
+
 	if (!urb->status & !acm->throttle)  {
 		for (i = 0; i < urb->actual_length && !acm->throttle; i++)
 			tty_insert_flip_char(tty, data[i], 0);
 		tty_flip_buffer_push(tty);
-	} else
-		dbg("nonzero read bulk status received: %d", urb->status);
+	}
 
-	if (!acm->throttle) {
-		urb->actual_length = 0;
-		if (usb_submit_urb(urb))
-			dbg("failed resubmitting read urb");
-	} else {
+	if (acm->throttle) {
 		memmove(data, data + i, urb->actual_length - i);
 		urb->actual_length -= i;
+		return;
 	}
+
+	urb->actual_length = 0;
+
+	if (usb_submit_urb(urb))
+		dbg("failed resubmitting read urb");
 }
 
 static void acm_write_bulk(struct urb *urb)
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.42/linux/drivers/usb/audio.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/audio.c	Wed Feb  9 11:42:35 2000
@@ -258,7 +258,6 @@
 struct usb_audiodev {
 	struct list_head list;
 	struct usb_audio_state *state;
-	int remove_pending;
 	
 	/* soundcore stuff */
 	int dev_audio;
@@ -838,8 +837,6 @@
 #if 0
 	printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
 #endif
-	if (as->remove_pending)
-		return;
 	if (urb == &u->durb[0].urb)
 		mask = FLG_URB0RUNNING;
 	else if (urb == &u->durb[1].urb)
@@ -904,9 +901,6 @@
 #if 0
 	printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
 #endif
-	if (as->remove_pending)
-		return;
-
 	if (urb == &u->surb[0].urb)
 		mask = FLG_SYNC0RUNNING;
 	else if (urb == &u->surb[1].urb)
@@ -1266,8 +1260,6 @@
 #if 0
 	printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
 #endif
-	if (as->remove_pending)
-		return;
 	if (urb == &u->surb[0].urb)
 		mask = FLG_SYNC0RUNNING;
 	else if (urb == &u->surb[1].urb)
@@ -1462,6 +1454,7 @@
 		d->srate = fmt->sratelo;
 	if (d->srate > fmt->sratehi)
 		d->srate = fmt->sratehi;
+printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
 	if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {
 		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
 		       dev->devnum, u->interface, fmt->altsetting);
@@ -1527,13 +1520,13 @@
 	u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf);
 	u->syncpipe = u->syncinterval = 0;
 	if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x04) {
-
+#if 0
 		printk(KERN_DEBUG "bNumEndpoints 0x%02x endpoint[1].bmAttributes 0x%02x\n"
 		       KERN_DEBUG "endpoint[1].bSynchAddress 0x%02x endpoint[1].bEndpointAddress 0x%02x\n"
 		       KERN_DEBUG "endpoint[0].bSynchAddress 0x%02x\n", alts->bNumEndpoints,
 		       alts->endpoint[1].bmAttributes, alts->endpoint[1].bSynchAddress,
 		       alts->endpoint[1].bEndpointAddress, alts->endpoint[0].bSynchAddress);
-
+#endif
 		if (alts->bNumEndpoints < 2 ||
 		    alts->endpoint[1].bmAttributes != 0x01 ||
 		    alts->endpoint[1].bSynchAddress != 0 ||
@@ -1545,14 +1538,11 @@
 		u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
 		u->syncinterval = alts->endpoint[1].bRefresh;
 	}
-
-	printk(KERN_DEBUG "datapipe 0x%x syncpipe 0x%x\n", u->datapipe, u->syncpipe);
-
-
 	if (d->srate < fmt->sratelo)
 		d->srate = fmt->sratelo;
 	if (d->srate > fmt->sratehi)
 		d->srate = fmt->sratehi;
+printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
 	if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
 		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
 		       dev->devnum, u->interface, fmt->altsetting);
@@ -1904,19 +1894,10 @@
 }
 
 static /*const*/ struct file_operations usb_mixer_fops = {
-	&usb_audio_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&usb_audio_ioctl_mixdev,
-	NULL,  /* mmap */
-	&usb_audio_open_mixdev,
-	NULL,   /* flush */
-	&usb_audio_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		usb_audio_llseek,
+	ioctl:		usb_audio_ioctl_mixdev,
+	open:		usb_audio_open_mixdev,
+	release:	usb_audio_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2473,7 +2454,6 @@
 	file->private_data = as;
 	as->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 	s->count++;
-	as->remove_pending=0;
 	MOD_INC_USE_COUNT;
 	up(&open_sem);
 	return 0;
@@ -2515,19 +2495,14 @@
 }
 
 static /*const*/ struct file_operations usb_audio_fops = {
-	&usb_audio_llseek,
-	&usb_audio_read,
-	&usb_audio_write,
-	NULL,  /* readdir */
-	&usb_audio_poll,
-	&usb_audio_ioctl,
-	&usb_audio_mmap,
-	&usb_audio_open,
-	NULL,   /* flush */
-	&usb_audio_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		usb_audio_llseek,
+	read:		usb_audio_read,
+	write:		usb_audio_write,
+	poll:		usb_audio_poll,
+	ioctl:		usb_audio_ioctl,
+	mmap:		usb_audio_mmap,
+	open:		usb_audio_open,
+	release:	usb_audio_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -3143,14 +3118,20 @@
 	}
 	if (state->nrchannels > 2)
 		printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
-	if (ftr[0] < 7+ftr[5]*(1+state->nrchannels)) {
-		printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", ftr[3]);
-		return;
+	if (state->nrchannels == 1 && ftr[0] == 7+ftr[5]) {
+		printk(KERN_WARNING "usbaudio: workaround for broken Philips Camera Microphone descriptor enabled\n");
+		mchftr = ftr[6];
+		chftr = 0;
+	} else {
+		if (ftr[0] < 7+ftr[5]*(1+state->nrchannels)) {
+			printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", ftr[3]);
+			return;
+		}
+		mchftr = ftr[6];
+		chftr = ftr[6+ftr[5]];
+		if (state->nrchannels > 1)
+			chftr &= ftr[6+2*ftr[5]];
 	}
-	mchftr = ftr[6];
-	chftr = ftr[6+ftr[5]];
-	if (state->nrchannels > 1)
-		chftr &= ftr[6+2*ftr[5]];
 	/* volume control */
 	if (chftr & 2) {
 		ch = getmixchannel(state, getvolchannel(state));
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c
--- v2.3.42/linux/drivers/usb/cpia.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/cpia.c	Mon Feb  7 19:13:37 2000
@@ -2,10 +2,8 @@
  * USB CPiA Video Camera driver
  *
  * Supports CPiA based Video Cameras. Many manufacturers use this chipset.
- * There's a good chance, if you have a USB video camera, it's a CPiA based
- * one.
  *
- * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@valinux.com
  * (C) Copyright 1999 Randy Dunlap
  */
 
@@ -496,7 +494,6 @@
 	copylen = 0;
 
 wakeup:
-
 	cpia->curframe = -1;
 
 	/* This will cause the process to request another frame. */
@@ -555,9 +552,8 @@
 	struct cpia_sbuf *sbuf;
 	int i;
 
-#if 0
-printk("cpia_isoc_irq: %p status %d, errcount = %d, length = %d\n", urb, urb->status, urb->error_count, urb->actual_length);
-#endif
+	if (!cpia->dev)
+		return;
 
 	if (!cpia->streaming) {
 		if (debug >= 1)
@@ -566,7 +562,6 @@
 	}
 	
 	sbuf = &cpia->sbuf[cpia->cursbuf];
-	// usb_kill_isoc(sbuf->isodesc);
 
 	/* Copy the data received into our scratch buffer */
 	len = cpia_compress_isochronous(cpia, urb);
@@ -584,18 +579,15 @@
 		sbuf->urb->iso_frame_desc[i].status = 0;
 		sbuf->urb->iso_frame_desc[i].actual_length = 0;
 	}
+
 	/* Move to the next sbuf */
 	cpia->cursbuf = (cpia->cursbuf + 1) % CPIA_NUMSBUF;
 
-	/* Reschedule this block of Isochronous desc */
-	// usb_run_isoc(sbuf->isodesc, cpia->sbuf[cpia->cursbuf].isodesc);
-
 	return;
 }
 
 static int cpia_init_isoc(struct usb_cpia *cpia)
 {
-	struct usb_device *dev = cpia->dev;
 	urb_t *urb;
 	int fx, err;
 
@@ -611,7 +603,6 @@
 	}
 
 	/* We double buffer the Iso lists */
-//	err = usb_init_isoc(dev, usb_rcvisocpipe(dev, 1), FRAMES_PER_DESC, cpia, &cpia->sbuf[0].isodesc);
 	urb = usb_alloc_urb(FRAMES_PER_DESC);
 	
 	if (!urb) {
@@ -620,9 +611,9 @@
 		return -ENOMEM;
 	}
 	cpia->sbuf[0].urb = urb;
-	urb->dev = dev;
+	urb->dev = cpia->dev;
 	urb->context = cpia;
-	urb->pipe = usb_rcvisocpipe(dev, 1);
+	urb->pipe = usb_rcvisocpipe(cpia->dev, 1);
 	urb->transfer_flags = USB_ISO_ASAP;
 	urb->transfer_buffer = cpia->sbuf[0].data;
  	urb->complete = cpia_isoc_irq;
@@ -639,9 +630,9 @@
 		return -ENOMEM;
 	}
 	cpia->sbuf[1].urb = urb;
-	urb->dev = dev;
+	urb->dev = cpia->dev;
 	urb->context = cpia;
-	urb->pipe = usb_rcvisocpipe(dev, 1);
+	urb->pipe = usb_rcvisocpipe(cpia->dev, 1);
 	urb->transfer_flags = USB_ISO_ASAP;
 	urb->transfer_buffer = cpia->sbuf[1].data;
  	urb->complete = cpia_isoc_irq;
@@ -657,11 +648,11 @@
 	
 	err = usb_submit_urb(cpia->sbuf[0].urb);
 	if (err)
-		printk(KERN_ERR "cpia_init_isoc: usb_run_isoc(0) ret %d\n",
+		printk(KERN_ERR "cpia_init_isoc: usb_submit_urb(0) ret %d\n",
 			err);
 	err = usb_submit_urb(cpia->sbuf[1].urb);
 	if (err)
-		printk(KERN_ERR "cpia_init_isoc: usb_run_isoc(1) ret %d\n",
+		printk(KERN_ERR "cpia_init_isoc: usb_submit_urb(1) ret %d\n",
 			err);
 
 	cpia->streaming = 1;
@@ -671,7 +662,7 @@
 
 static void cpia_stop_isoc(struct usb_cpia *cpia)
 {
-	if (!cpia->streaming)
+	if (!cpia->streaming || !cpia->dev)
 		return;
 
 	/* Turn off continuous grab */
@@ -686,15 +677,21 @@
 		return /* -EINVAL */;
 	}
 
-	/* Unschedule all of the iso td's */
-	usb_unlink_urb(cpia->sbuf[1].urb);
-	usb_unlink_urb(cpia->sbuf[0].urb);
-
 	cpia->streaming = 0;
 
-	/* Delete them all */
-	usb_free_urb(cpia->sbuf[1].urb);
-	usb_free_urb(cpia->sbuf[0].urb);
+	/* Unschedule all of the iso td's */
+	if (cpia->sbuf[1].urb) {
+		cpia->sbuf[1].urb->next = NULL;
+		usb_unlink_urb(cpia->sbuf[1].urb);
+		usb_free_urb(cpia->sbuf[1].urb);
+		cpia->sbuf[1].urb = NULL;
+	}
+	if (cpia->sbuf[0].urb) {
+		cpia->sbuf[0].urb->next = NULL;
+		usb_unlink_urb(cpia->sbuf[0].urb);
+		usb_free_urb(cpia->sbuf[0].urb);
+		cpia->sbuf[0].urb = NULL;
+	}
 }
 
 static int cpia_new_frame(struct usb_cpia *cpia, int framenum)
@@ -702,6 +699,9 @@
 	struct cpia_frame *frame;
 	int width, height;
 
+	if (!cpia->dev)
+		return -1;
+
 	/* If we're not grabbing a frame right now and the other frame is */
 	/*  ready to be grabbed into, then use it instead */
 	if (cpia->curframe == -1) {
@@ -833,6 +833,11 @@
 	kfree(cpia->sbuf[0].data);
 
 	up(&cpia->lock);
+
+	if (!cpia->dev) {
+		video_unregister_device(&cpia->vdev);
+		kfree(cpia);
+	}
 }
 
 static int cpia_init_done(struct video_device *dev)
@@ -849,6 +854,9 @@
 {
 	struct usb_cpia *cpia = (struct usb_cpia *)dev;
 
+	if (!cpia->dev)
+		return -EIO;
+
 	switch (cmd) {
 		case VIDIOCGCAP:
 		{
@@ -1025,10 +1033,10 @@
 			case FRAME_GRABBING:
 			case FRAME_ERROR:
 redo:
+				if (!cpia->dev)
+					return -EIO;
+
 				do {
-#if 0
-					init_waitqueue_head(&cpia->frame[frame].wq);
-#endif
 					interruptible_sleep_on(&cpia->frame[frame].wq);
 					if (signal_pending(current))
 						return -EINTR;
@@ -1095,6 +1103,9 @@
 	if (!dev || !buf)
 		return -EFAULT;
 
+	if (!cpia->dev)
+		return -EIO;
+
 	/* See if a frame is completed, then use it. */
 	if (cpia->frame[0].grabstate >= FRAME_DONE)	/* _DONE or _ERROR */
 		frmx = 0;
@@ -1120,6 +1131,9 @@
 	frame = &cpia->frame[frmx];
 
 restart:
+	if (!cpia->dev)
+		return -EIO;
+
 	while (frame->grabstate == FRAME_GRABBING) {
 		interruptible_sleep_on(&frame->wq);
 		if (signal_pending(current))
@@ -1168,6 +1182,9 @@
 	unsigned long start = (unsigned long)adr;
 	unsigned long page, pos;
 
+	if (!cpia->dev)
+		return -EIO;
+
 	if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
 		return -EINVAL;
 
@@ -1326,23 +1343,56 @@
 	cpia->iface = interface->bInterfaceNumber;
 
 	if (!usb_cpia_configure(cpia)) {
-	    cpia->user=0; 
-	    init_MUTEX(&cpia->lock);	/* to 1 == available */
-	    return cpia;
-	} else return NULL;
+		cpia->user=0; 
+		init_MUTEX(&cpia->lock);	/* to 1 == available */
+
+		return cpia;
+	} else
+		return NULL;
 }
 
 static void cpia_disconnect(struct usb_device *dev, void *ptr)
 {
 	struct usb_cpia *cpia = (struct usb_cpia *) ptr;
 
-	video_unregister_device(&cpia->vdev);
+	/* We don't want people trying to open up the device */
+	if (!cpia->user)
+		video_unregister_device(&cpia->vdev);
 
 	usb_driver_release_interface(&cpia_driver,
 		&cpia->dev->actconfig->interface[0]);
 
+	cpia->dev = NULL;
+	cpia->frame[0].grabstate = FRAME_ERROR;
+	cpia->frame[1].grabstate = FRAME_ERROR;
+	cpia->curframe = -1;
+
+	/* This will cause the process to request another frame. */
+	if (waitqueue_active(&cpia->frame[0].wq))
+		wake_up_interruptible(&cpia->frame[0].wq);
+
+	if (waitqueue_active(&cpia->frame[1].wq))
+		wake_up_interruptible(&cpia->frame[1].wq);
+
+	cpia->streaming = 0;
+
+	/* Unschedule all of the iso td's */
+	if (cpia->sbuf[1].urb) {
+		cpia->sbuf[1].urb->next = NULL;
+		usb_unlink_urb(cpia->sbuf[1].urb);
+		usb_free_urb(cpia->sbuf[1].urb);
+		cpia->sbuf[1].urb = NULL;
+	}
+	if (cpia->sbuf[0].urb) {
+		cpia->sbuf[0].urb->next = NULL;
+		usb_unlink_urb(cpia->sbuf[0].urb);
+		usb_free_urb(cpia->sbuf[0].urb);
+		cpia->sbuf[0].urb = NULL;
+	}
+
 	/* Free the memory */
-	kfree(cpia);
+	if (!cpia->user)
+		kfree(cpia);
 }
 
 static struct usb_driver cpia_driver = {
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- v2.3.42/linux/drivers/usb/dabusb.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/dabusb.c	Wed Feb  9 15:20:13 2000
@@ -21,7 +21,7 @@
  *
  *
  *
- *  $Id: dabusb.c,v 1.30 1999/12/17 17:50:58 fliegl Exp $
+ *  $Id: dabusb.c,v 1.45 2000/01/31 10:23:44 fliegl Exp $
  *
  */
 
@@ -38,26 +38,22 @@
 #include <asm/atomic.h>
 #include <linux/delay.h>
 
-#undef DEBUG
-#undef DEBUG_ALL
-
 #include "usb.h"
 
 #include "dabusb.h"
 #include "dabfirmware.h"
+
 /* --------------------------------------------------------------------- */
 
 #define NRDABUSB 4
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#define __init 
-#define __exit
-#endif
-
 /*-------------------------------------------------------------------*/
+
 static dabusb_t dabusb[NRDABUSB];
 static int buffers = 256;
+
 /*-------------------------------------------------------------------*/
+
 static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src)
 {
 	unsigned long flags;
@@ -79,7 +75,7 @@
 	return ret;
 }
 /*-------------------------------------------------------------------*/
-#ifdef DEBUG
+#ifdef DEBUG 
 static void dump_urb (purb_t purb)
 {
 	dbg("urb                   :%p", purb);
@@ -108,10 +104,12 @@
 	pbuff_t b;
 
 	dbg("dabusb_cancel_queue");
+
 	spin_lock_irqsave (&s->lock, flags);
 
 	for (p = q->next; p != q; p = p->next) {
 		b = list_entry (p, buff_t, buff_list);
+
 #ifdef DEBUG
 		dump_urb(b->purb);
 #endif
@@ -130,26 +128,34 @@
 	dbg("dabusb_free_queue");
 	for (p = q->next; p != q;) {
 		b = list_entry (p, buff_t, buff_list);
-#ifdef DEBUG
+
+#ifdef DEBUG 
 		dump_urb(b->purb);
 #endif
 		if (b->purb->transfer_buffer)
 			kfree (b->purb->transfer_buffer);
-		if (b->purb)
-			kfree (b->purb);
+		usb_free_urb(b->purb);
 		tmp = p->next;
 		list_del (p);
 		kfree (b);
 		p = tmp;
 	}
+
 	return 0;
 }
 /*-------------------------------------------------------------------*/
 static int dabusb_free_buffers (pdabusb_t s)
 {
+	unsigned long flags;
 	dbg("dabusb_free_buffers");
+
+	spin_lock_irqsave(&s->lock, flags);
+
 	dabusb_free_queue (&s->free_buff_list);
 	dabusb_free_queue (&s->rec_buff_list);
+
+	spin_unlock_irqrestore(&s->lock, flags);
+
 	s->got_mem = 0;
 	return 0;
 }
@@ -163,14 +169,14 @@
 	int dst = 0;
 	void *buf = purb->transfer_buffer;
 
-#ifdef DEBUG_ALL
 	dbg("dabusb_iso_complete");
-#endif
-	if (purb->status != USB_ST_URB_KILLED) {
+
+	// process if URB was not killed
+	if (purb->status != -ENOENT) {
 		unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
 		int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
 		for (i = 0; i < purb->number_of_packets; i++)
-			if (purb->iso_frame_desc[i].status == USB_ST_NOERROR) {
+			if (!purb->iso_frame_desc[i].status) {
 				len = purb->iso_frame_desc[i].actual_length;
 				if (len <= pipesize) {
 					memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len);
@@ -179,6 +185,8 @@
 				else
 					err("dabusb_iso_complete: invalid len %d", len);
 			}
+			else
+				warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status);
 		if (dst != purb->actual_length)
 			err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
 	}
@@ -199,10 +207,9 @@
 	int packets = _ISOPIPESIZE / pipesize;
 	int transfer_buffer_length = packets * pipesize;
 	int i;
-	int len = sizeof (urb_t) + packets * sizeof (iso_packet_descriptor_t);
 
-	dbg("dabusb_alloc_buffers len:%d pipesize:%d packets:%d transfer_buffer_len:%d",
-		len, pipesize, packets, transfer_buffer_length);
+	dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
+		 pipesize, packets, transfer_buffer_length);
 
 	while (buffers < (s->total_buffer_size << 10)) {
 		b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL);
@@ -212,13 +219,13 @@
 		}
 		memset (b, sizeof (buff_t), 0);
 		b->s = s;
-		b->purb = (purb_t) kmalloc (len, GFP_KERNEL);
+		b->purb = usb_alloc_urb(packets);
 		if (!b->purb) {
-			err("kmalloc(sizeof(urb_t)+packets*sizeof(iso_packet_descriptor_t))==NULL");
+			err("usb_alloc_urb == NULL");
 			kfree (b);
 			goto err;
 		}
-		memset (b->purb, 0, len);
+
 		b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL);
 		if (!b->purb->transfer_buffer) {
 			kfree (b->purb);
@@ -247,124 +254,55 @@
 
 	return 0;
 
-err:
+	err:
 	dabusb_free_buffers (s);
 	return -ENOMEM;
 }
 /*-------------------------------------------------------------------*/
-static int dabusb_reset_pipe (struct usb_device *usbdev, unsigned int ep)
-{
-	dbg("dabusb_reset_pipe");
-	if ((ep & ~0x80) >= 16)
-		return -EINVAL;
-
-	usb_settoggle (usbdev, ep & 0xf, !(ep & 0x80), 0);
-
-	return 0;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_submit_urb (pdabusb_t s, purb_t purb)
-{
-	int ret;
-	bulk_completion_context_t context;
-
-	init_waitqueue_head (&context.wait);
-	purb->context = &context;
-
-#ifdef DEBUG_ALL
-	dump_urb(purb);
-#endif
-
-	ret = usb_submit_urb (purb);
-	if (ret < 0) {
-		dbg("dabusb_bulk: usb_submit_urb returned %d", ret);
-		return -EINVAL;
-	}
-	interruptible_sleep_on_timeout (&context.wait, HZ);
-	if (purb->status == USB_ST_URB_PENDING) {
-		err("dabusb_usb_submit_urb: %p timed out", purb);
-		usb_unlink_urb (purb);
-		dabusb_reset_pipe(purb->dev, purb->pipe);
-		return -ETIMEDOUT;
-	}
-	return purb->status;
-}
-/* --------------------------------------------------------------------- */
-static void dabusb_bulk_complete (purb_t purb)
-{
-	pbulk_completion_context_t context = purb->context;
-
-#ifdef DEBUG_ALL
-	dbg("dabusb_bulk_complete");
-	dump_urb(purb);
-#endif
-	wake_up (&context->wait);
-}
-
-/* --------------------------------------------------------------------- */
 static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
 {
 	int ret;
-	urb_t urb;
 	unsigned int pipe;
+	int actual_length;
 
-#ifdef DEBUG_ALL
 	dbg("dabusb_bulk");
-#endif
 
 	if (!pb->pipe)
 		pipe = usb_rcvbulkpipe (s->usbdev, 2);
 	else
 		pipe = usb_sndbulkpipe (s->usbdev, 2);
 
-	memset (&urb, 0, sizeof (urb_t));
-	FILL_BULK_URB ((&urb), s->usbdev, pipe, pb->data, pb->size, dabusb_bulk_complete, NULL);
+	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 1000);
+	if(ret<0) {
+		err("dabusb: usb_bulk_msg failed(%d)",ret);
+	}
+	
+	if( ret == -EPIPE ) {
+		warn("CLEAR_FEATURE request to remove STALL condition.");
+		if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
+			err("request failed");
+		}
 
-	ret = dabusb_submit_urb (s, &urb);
-	pb->size = urb.actual_length;
+	pb->size = actual_length;
 	return ret;
 }
 /* --------------------------------------------------------------------- */
 static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len)
 {
 	int ret;
-	urb_t urb;
-	unsigned int pipe;
-	unsigned char *setup = kmalloc (8, GFP_KERNEL);
-	unsigned char *transfer_buffer;
+	unsigned char *transfer_buffer =  kmalloc (len, GFP_KERNEL);
 
-	if (!setup) {
-		err("dabusb_writemem: kmalloc(8) failed.");
-		return -ENOMEM;
-	}
-	transfer_buffer = kmalloc (len, GFP_KERNEL);
 	if (!transfer_buffer) {
 		err("dabusb_writemem: kmalloc(%d) failed.", len);
-		kfree (setup);
 		return -ENOMEM;
 	}
-	setup[0] = 0x40;
-	setup[1] = 0xa0;
-	setup[2] = pos & 0xff;
-	setup[3] = pos >> 8;
-	setup[4] = 0;
-	setup[5] = 0;
-	setup[6] = len & 0xff;
-	setup[7] = len >> 8;
 
 	memcpy (transfer_buffer, data, len);
 
-	pipe = usb_sndctrlpipe (s->usbdev, 0);
+	ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
 
-	memset (&urb, 0, sizeof (urb_t));
-	FILL_CONTROL_URB ((&urb), s->usbdev, pipe, setup, transfer_buffer, len, dabusb_bulk_complete, NULL);
-
-	ret = dabusb_submit_urb (s, &urb);
-	kfree (setup);
 	kfree (transfer_buffer);
-	if (ret < 0)
-		return ret;
-	return urb.status;
+	return ret;
 }
 /* --------------------------------------------------------------------- */
 static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
@@ -379,21 +317,23 @@
 	PINTEL_HEX_RECORD ptr = firmware;
 
 	dbg("Enter dabusb_loadmem (internal)");
-
+	
 	ret = dabusb_8051_reset (s, 1);
 	while (ptr->Type == 0) {
-#ifdef DEBUG_ALL
-		err("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
-#endif
+
+		dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
+
 		ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
 		if (ret < 0) {
-			err("dabusb_writemem failed (%04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
+			err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length);
 			break;
 		}
 		ptr++;
 	}
 	ret = dabusb_8051_reset (s, 0);
+
 	dbg("dabusb_loadmem: exit");
+
 	return ret;
 }
 /* --------------------------------------------------------------------- */
@@ -406,6 +346,7 @@
 	b->data[3] = 0;
 
 	dbg("dabusb_fpga_clear");
+
 	return dabusb_bulk (s, b);
 }
 /* --------------------------------------------------------------------- */
@@ -418,6 +359,7 @@
 	b->data[3] = 0;
 
 	dbg("dabusb_fpga_init");
+
 	return dabusb_bulk (s, b);
 }
 /* --------------------------------------------------------------------- */
@@ -429,6 +371,7 @@
 	unsigned char *buf = bitstream;
 
 	dbg("Enter dabusb_fpga_download (internal)");
+
 	if (!b) {
 		err("kmalloc(sizeof(bulk_transfer_t))==NULL");
 		return -ENOMEM;
@@ -438,7 +381,9 @@
 	ret = dabusb_fpga_clear (s, b);
 	mdelay (10);
 	blen = buf[73] + (buf[72] << 8);
+
 	dbg("Bitstream len: %i", blen);
+
 	b->data[0] = 0x2b;
 	b->data[1] = 0;
 	b->data[2] = 0;
@@ -460,6 +405,7 @@
 	kfree (b);
 
 	dbg("exit dabusb_fpga_download");
+
 	return ret;
 }
 
@@ -484,12 +430,12 @@
 static int dabusb_startrek (pdabusb_t s)
 {
 	if (!s->got_mem && s->state != _started) {
+
 		dbg("dabusb_startrek");
 
 		if (dabusb_alloc_buffers (s) < 0)
 			return -ENOMEM;
 		dabusb_stop (s);
-		dabusb_reset_pipe (s->usbdev, _DABUSB_ISOPIPE);
 		s->state = _started;
 		s->readptr = 0;
 	}
@@ -497,11 +443,11 @@
 	if (!list_empty (&s->free_buff_list)) {
 		pbuff_t end;
 		int ret;
+		
+	while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
 
-		while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
-#ifdef DEBUG_ALL
 			dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
-#endif
+
 			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
 
 			ret = usb_submit_urb (end->purb);
@@ -509,29 +455,28 @@
 				err("usb_submit_urb returned:%d", ret);
 				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
 					err("startrek: dabusb_add_buf_tail failed");
+				break;
 			}
 			else
 				atomic_inc (&s->pending_io);
 		}
-#ifdef DEBUG_ALL
 		dbg("pending_io: %d",s->pending_io.counter);
-#endif
 	}
+
 	return 0;
 }
 
 static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos)
 {
 	pdabusb_t s = (pdabusb_t) file->private_data;
+	unsigned long flags;
 	unsigned ret = 0;
 	int rem;
 	int cnt;
 	pbuff_t b;
 	purb_t purb = NULL;
 
-#ifdef DEBUG_ALL
 	dbg("dabusb_read");
-#endif
 
 	if (*ppos)
 		return -ESPIPE;
@@ -545,14 +490,23 @@
 
 	while (count > 0) {
 		dabusb_startrek (s);
+
+		spin_lock_irqsave (&s->lock, flags);
+
 		if (list_empty (&s->rec_buff_list)) {
+
+			spin_unlock_irqrestore(&s->lock, flags);
+
 			err("error: rec_buf_list is empty");
 			goto err;
 		}
+		
 		b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
 		purb = b->purb;
 
-		if (purb->status == USB_ST_URB_PENDING) {
+		spin_unlock_irqrestore(&s->lock, flags);
+
+		if (purb->status == -EINPROGRESS) {
 			if (file->f_flags & O_NONBLOCK)		// return nonblocking
 			 {
 				if (!ret)
@@ -567,10 +521,15 @@
 					ret = -ERESTARTSYS;
 				goto err;
 			}
+
+			spin_lock_irqsave (&s->lock, flags);
+
 			if (list_empty (&s->rec_buff_list)) {
+				spin_unlock_irqrestore(&s->lock, flags);
 				err("error: still no buffer available.");
 				goto err;
 			}
+			spin_unlock_irqrestore(&s->lock, flags);
 			s->readptr = 0;
 		}
 		if (s->remove_pending) {
@@ -585,9 +544,7 @@
 		else
 			cnt = count;
 
-#ifdef DEBUG_ALL
 		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
-#endif
 
 		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
 			err("read: copy_to_user failed");
@@ -608,7 +565,7 @@
 			s->readptr = 0;
 		}
 	}
-err:			//up(&s->mutex);
+      err:			//up(&s->mutex);
 	return ret;
 }
 
@@ -641,14 +598,14 @@
 		}
 		down (&s->mutex);
 	}
-	s->opened = 1;
-	up (&s->mutex);
-
 	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
-		err("dabusb: set_interface failed");
+		err("set_interface failed");
 		MOD_DEC_USE_COUNT;
 		return -EINVAL;
 	}
+	s->opened = 1;
+	up (&s->mutex);
+
 	file->f_pos = 0;
 	file->private_data = s;
 
@@ -668,7 +625,7 @@
 
 	if (!s->remove_pending) {
 		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
-			err("dabusb: set_interface failed");
+			err("set_interface failed");
 	}
 	else
 		wake_up (&s->remove_ok);
@@ -684,9 +641,8 @@
 	pbulk_transfer_t pbulk;
 	int ret = 0;
 	int version = DABUSB_VERSION;
-	DECLARE_WAITQUEUE (wait, current);
 
-//        dbg("dabusb_ioctl");
+	dbg("dabusb_ioctl");
 
 	if (s->remove_pending)
 		return -EIO;
@@ -737,19 +693,11 @@
 
 static struct file_operations dabusb_fops =
 {
-	dabusb_llseek,
-	dabusb_read,
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	dabusb_ioctl,
-	NULL,			/* mmap */
-	dabusb_open,
-	NULL,			/* flush */
-	dabusb_release,
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	NULL			/* lock */
+	llseek:		dabusb_llseek,
+	read:		dabusb_read,
+	ioctl:		dabusb_ioctl,
+	open:		dabusb_open,
+	release:	dabusb_release,
 };
 
 static int dabusb_find_struct (void)
@@ -799,8 +747,10 @@
 		err("set_configuration failed");
 		goto reject;
 	}
-	if (usbdev->descriptor.idProduct == 0x2131)
+	if (usbdev->descriptor.idProduct == 0x2131) {
 		dabusb_loadmem (s, NULL);
+		goto reject;
+	}
 	else {
 		dabusb_fpga_download (s, NULL);
 
@@ -814,7 +764,7 @@
 	MOD_INC_USE_COUNT;
 	return s;
 
-reject:
+      reject:
 	up (&s->mutex);
 	s->usbdev = NULL;
 	return NULL;
@@ -869,12 +819,14 @@
 	usb_register (&dabusb_driver);
 
 	dbg("dabusb_init: driver registered");
+
 	return 0;
 }
 
 void __exit dabusb_cleanup (void)
 {
 	dbg("dabusb_cleanup");
+
 	usb_deregister (&dabusb_driver);
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/dabusb.h linux/drivers/usb/dabusb.h
--- v2.3.42/linux/drivers/usb/dabusb.h	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/dabusb.h	Mon Feb  7 19:12:12 2000
@@ -33,7 +33,6 @@
 	int opened;
 	struct list_head free_buff_list;
 	struct list_head rec_buff_list;
-	int in_use;
 } dabusb_t,*pdabusb_t;
 
 typedef struct 
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/devices.c linux/drivers/usb/devices.c
--- v2.3.42/linux/drivers/usb/devices.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/devices.c	Wed Feb  9 11:51:13 2000
@@ -366,7 +366,7 @@
 /*****************************************************************/
 
 static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev,
-			     int bus, int level, int index, int count)
+			     struct usb_bus *bus, int level, int index, int count)
 {
 	int chix;
 	int cnt = 0;
@@ -380,7 +380,7 @@
 	 * So the root hub's parent is 0 and any device that is
 	 * plugged into the root hub has a parent of 0.
 	 */
-	start += sprintf(start, format_topo, bus, level, parent_devnum, index, count,
+	start += sprintf(start, format_topo, bus->busnum, level, parent_devnum, index, count,
 			 usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
 	/*
 	 * level = topology-tier level;
@@ -388,9 +388,13 @@
 	 * index = parent's connector number;
 	 * count = device count at this level
 	 */
-	/* do not dump descriptors for root hub */
-	if (usbdev->devnum >= 0)
-		start = usb_dump_desc(start, end, usbdev);
+	/* If this is the root hub, display the bandwidth information */
+	if (level == 0)
+		start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, 
+				FRAME_TIME_MAX_USECS_ALLOC,
+				(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
+			         bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
+	start = usb_dump_desc(start, end, usbdev);
 	if (start > end)
 		return start + sprintf(start, "(truncated)\n");
 	/* Now look at all of this device's children. */
@@ -422,12 +426,9 @@
 	pos = *ppos;
 	/* enumerate busses */
 	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
-		/* print bandwidth allocation */
+		/* print devices for this bus */
 		bus = list_entry(buslist, struct usb_bus, bus_list);
-		len = sprintf(page, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC,
-			      (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
-			      bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
-		end = usb_device_dump(page + len, page + (2*PAGE_SIZE - 256), bus->root_hub, bus->busnum, 0, 0, 0);
+		end = usb_device_dump(page, page + (2*PAGE_SIZE - 256), bus->root_hub, bus, 0, 0, 0);
 		len = end - page;
 		if (len > pos) {
 			len -= pos;
@@ -512,15 +513,9 @@
 }
 
 struct file_operations usbdevfs_devices_fops = {
-	usb_device_lseek,   /* lseek   */
-	usb_device_read,    /* read    */
-	NULL,               /* write   */
-	NULL,               /* readdir */
-	usb_device_poll,    /* poll    */
-	NULL,               /* ioctl   */
-	NULL,               /* mmap    */
-	usb_device_open,    /* open    */
-	NULL,               /* flush   */
-	usb_device_release, /* release */
-	NULL                /* fsync   */
+	llseek:		usb_device_lseek,
+	read:		usb_device_read,
+	poll:		usb_device_poll,
+	open:		usb_device_open,
+	release:	usb_device_release,
 };
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/devio.c linux/drivers/usb/devio.c
--- v2.3.42/linux/drivers/usb/devio.c	Fri Jan 21 18:19:17 2000
+++ linux/drivers/usb/devio.c	Wed Feb  9 11:42:35 2000
@@ -19,7 +19,7 @@
  *      along with this program; if not, write to the Free Software
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *  $Id: devio.c,v 1.6 2000/01/11 23:26:33 tom Exp $
+ *  $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $
  *
  *  This file implements the usbdevfs/x/y files, where
  *  x is the bus number and y the device number.
@@ -132,8 +132,8 @@
         urb->transfer_buffer = data;
         urb->transfer_buffer_length = size;
 	ret = do_sync(urb, timeout);
-	if (ret >= 0)
-		ret = urb->status;
+	//if (ret >= 0)
+	//	ret = urb->status;
 	if (ret >= 0)
 		ret = urb->actual_length;
 	kfree(urb->setup_packet);
@@ -154,8 +154,8 @@
         urb->transfer_buffer = data;
         urb->transfer_buffer_length = len;
 	ret = do_sync(urb, timeout);
-	if (ret >= 0)
-		ret = urb->status;
+	//if (ret >= 0)
+	//	ret = urb->status;
 	if (ret >= 0 && actual_length != NULL)
 		*actual_length = urb->actual_length;
 	usb_free_urb(urb);
@@ -321,7 +321,7 @@
         struct dev_state *ps = as->ps;
 	struct siginfo sinfo;
 
-#if 0
+#if 1
 	printk(KERN_DEBUG "usbdevfs: async_completed: status %d errcount %d actlen %d pipe 0x%x\n", 
 	       urb->status, urb->error_count, urb->actual_length, urb->pipe);
 #endif
@@ -345,7 +345,7 @@
         unsigned long flags;
 
         spin_lock_irqsave(&ps->lock, flags);
-        if (!list_empty(&ps->async_pending)) {
+        while (!list_empty(&ps->async_pending)) {
                 as = list_entry(ps->async_pending.next, struct async, asynclist);
                 list_del(&as->asynclist);
                 INIT_LIST_HEAD(&as->asynclist);
@@ -1003,17 +1003,12 @@
 }
 
 static struct file_operations usbdevfs_device_file_operations = {
-	usbdev_lseek,    /* lseek   */
-	usbdev_read,     /* read    */
-	NULL,            /* write   */
-	NULL,            /* readdir */
-	usbdev_poll,     /* poll    */
-	usbdev_ioctl,    /* ioctl   */
-	NULL,            /* mmap    */
-	usbdev_open,     /* open    */
-	NULL,            /* flush   */
-	usbdev_release,  /* release */
-	NULL             /* fsync   */
+	llseek:		usbdev_lseek,
+	read:		usbdev_read,
+	poll:		usbdev_poll,
+	ioctl:		usbdev_ioctl,
+	open:		usbdev_open,
+	release:	usbdev_release,
 };
 
 struct inode_operations usbdevfs_device_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/drivers.c linux/drivers/usb/drivers.c
--- v2.3.42/linux/drivers/usb/drivers.c	Fri Jan 21 18:19:17 2000
+++ linux/drivers/usb/drivers.c	Wed Feb  9 11:42:35 2000
@@ -112,15 +112,6 @@
 }
 
 struct file_operations usbdevfs_drivers_fops = {
-	usb_driver_lseek, /* lseek   */
-	usb_driver_read,  /* read    */
-	NULL,             /* write   */
-	NULL,             /* readdir */
-	NULL,             /* poll    */
-	NULL,             /* ioctl   */
-	NULL,             /* mmap    */
-	NULL,             /* open    */
-	NULL,             /* flush   */
-	NULL,             /* release */
-	NULL              /* fsync   */
+	llseek:		usb_driver_lseek,
+	read:		usb_driver_read,
 };
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/hid.c linux/drivers/usb/hid.c
--- v2.3.42/linux/drivers/usb/hid.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/hid.c	Mon Feb  7 19:14:45 2000
@@ -53,6 +53,8 @@
 #define hid_dump_device(c)	do { } while (0)
 #endif
 
+#define unk	KEY_UNKNOWN
+
 static unsigned char hid_keyboard[256] = {
 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
@@ -61,13 +63,13 @@
 	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
 	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
 	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
-	120,121,122,123,192,138,192,192,128,129,131,137,133,135,136,113,
-	115,114,192,192,192,192,192,124,192,192,192,192,192,192,192,192,
-	192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-	192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-	192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-	192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-	192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
+	120,121,122,123,unk,138,unk,unk,128,129,131,137,133,135,136,113,
+	115,114,unk,unk,unk,unk,unk,124,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	134,130,132,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
 	 29, 42, 56,125, 97, 54,100,126
 };
 
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.42/linux/drivers/usb/hub.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/hub.c	Mon Feb  7 19:12:16 2000
@@ -446,8 +446,18 @@
 			}
 
 			if (portchange & USB_PORT_STAT_C_ENABLE) {
-				dbg("port %d enable change", i + 1);
+				dbg("port %d enable change, status %x", i + 1, portstatus);
 				usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
+
+				// EM interference sometimes causes bad shielded USB devices to 
+				// be shutdown by the hub, this hack enables them again.
+				// Works at least with mouse driver. 
+				if (!(portstatus & USB_PORT_STAT_ENABLE) && 
+				    (portstatus & USB_PORT_STAT_CONNECTION)) {
+					err("already running port %i disabled by hub (EMI?), re-enabling...",
+						i + 1);
+					usb_hub_port_connect_change(dev, i);
+				}
 			}
 
 			if (portstatus & USB_PORT_STAT_SUSPEND) {
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c
--- v2.3.42/linux/drivers/usb/ibmcam.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/ibmcam.c	Mon Feb  7 19:15:56 2000
@@ -26,6 +26,21 @@
 #include "usb.h"
 #include "ibmcam.h"
 
+/*
+ * IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED: This symbol controls
+ * the locking of the driver. If non-zero, the driver counts the
+ * probe() call as usage and increments module usage counter; this
+ * effectively prevents removal of the module (with rmmod) until the
+ * device is unplugged (then disconnect() callback reduces the module
+ * usage counter back, and module can be removed).
+ *
+ * This behavior may be useful if you prefer to lock the driver in
+ * memory until device is unplugged. However you can't reload the
+ * driver if you want to alter some parameters - you'd need to unplug
+ * the camera first. Therefore, I recommend setting 0.
+ */
+#define IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED	0
+
 #define	ENABLE_HEXDUMP	0	/* Enable if you need it */
 static int debug = 0;
 
@@ -100,6 +115,7 @@
 static int init_contrast = 192;
 static int init_color = 128;
 static int init_hue = 128;
+static int hue_correction = 128;
 
 MODULE_PARM(debug, "i");
 MODULE_PARM(flags, "i");
@@ -111,6 +127,7 @@
 MODULE_PARM(init_contrast, "i");
 MODULE_PARM(init_color, "i");
 MODULE_PARM(init_hue, "i");
+MODULE_PARM(hue_correction, "i");
 
 MODULE_AUTHOR ("module author");
 MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
@@ -123,6 +140,10 @@
 static const unsigned short light_27 = 0x0027;
 static const unsigned short sharp_13 = 0x0013;
 
+#define MAX_IBMCAM	4
+
+struct usb_ibmcam cams[MAX_IBMCAM];
+
 /*******************************/
 /* Memory management functions */
 /*******************************/
@@ -130,6 +151,7 @@
 #define MDEBUG(x)	do { } while(0)		/* Debug memory management */
 
 static struct usb_driver ibmcam_driver;
+static void usb_ibmcam_release(struct usb_ibmcam *ibmcam);
 
 /* Given PGD from the address space's page table, return the kernel
  * virtual mapping of the physical memory mapped at ADR.
@@ -555,12 +577,14 @@
 	struct ibmcam_frame *frame;
 	unsigned char *data, *f, *chromaLine;
 	unsigned int len;
-	const int v4l_linesize = imgwidth * V4L_BYTES_PER_PIXEL; /* V4L line offset */
-	int y, u, v, i, frame_done=0, mono_plane, hue_corr, color_corr;
-
-	hue_corr = (ibmcam->vpic.hue - 0x8000) >> 10;      /* -32..+31 */
-	color_corr = (ibmcam->vpic.colour - 0x8000) >> 10; /* -32..+31 */
+	const int v4l_linesize = imgwidth * V4L_BYTES_PER_PIXEL;	/* V4L line offset */
+	const int hue_corr  = (ibmcam->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
+	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
+	const int ccm = 128; /* Color correction median - see below */
+	int y, u, v, i, frame_done=0, mono_plane, color_corr;
 
+	color_corr = (ibmcam->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
 	data = ibmcam->scratch;
 	frame = &ibmcam->frame[ibmcam->curframe];
 
@@ -694,11 +718,18 @@
 		else {
 			if (frame->order_uv) {
 				u = chromaLine[(i >> 1) << 2] + hue_corr;
-				v = chromaLine[((i >> 1) << 2) + 2] + color_corr;
+				v = chromaLine[((i >> 1) << 2) + 2] + hue2_corr;
 			} else {
-				v = chromaLine[(i >> 1) << 2] + color_corr;
+				v = chromaLine[(i >> 1) << 2] + hue2_corr;
 				u = chromaLine[((i >> 1) << 2) + 2] + hue_corr;
 			}
+
+			/* Apply color correction */
+			if (color_corr != 0) {
+				/* Magnify up to 2 times, reduce down to zero saturation */
+				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
+				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
+			}
 			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
 		}
 
@@ -915,7 +946,7 @@
 	int i;
 
 	/* We don't want to do anything if we are about to be removed! */
-	if (ibmcam->remove_pending)
+	if (!IBMCAM_IS_OPERATIONAL(ibmcam))
 		return;
 
 #if 0
@@ -976,38 +1007,46 @@
 	return;
 }
 
+/*
+ * usb_ibmcam_veio()
+ *
+ * History:
+ * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
+ */
 static int usb_ibmcam_veio(
-	struct usb_device *dev,
+	struct usb_ibmcam *ibmcam,
 	unsigned char req,
 	unsigned short value,
 	unsigned short index)
 {
 	static const char proc[] = "usb_ibmcam_veio";
-	unsigned char cp[8] = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef };
-	const unsigned short len = sizeof(cp);
+	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
 	int i;
 
+	if (!IBMCAM_IS_OPERATIONAL(ibmcam))
+		return 0;
+
 	if (req == 1) {
 		i = usb_control_msg(
-			dev,
-			usb_rcvctrlpipe(dev, 0),
+			ibmcam->dev,
+			usb_rcvctrlpipe(ibmcam->dev, 0),
 			req,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 			value,
 			index,
 			cp,
-			len,
+			sizeof(cp),
 			HZ);
 #if 0
 		printk(KERN_DEBUG "USB => %02x%02x%02x%02x%02x%02x%02x%02x "
-		       "(req=$%02x val=$%04x ind=$%04x len=%d.)\n",
+		       "(req=$%02x val=$%04x ind=$%04x)\n",
 		       cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
-		       req, value, index, len);
+		       req, value, index);
 #endif
 	} else {
 		i = usb_control_msg(
-			dev,
-			usb_sndctrlpipe(dev, 0),
+			ibmcam->dev,
+			usb_sndctrlpipe(ibmcam->dev, 0),
 			req,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
 			value,
@@ -1016,8 +1055,11 @@
 			0,
 			HZ);
 	}
-	if (i < 0)
-		printk(KERN_ERR "%s: ERROR=%d.\n", proc, i);
+	if (i < 0) {
+		printk(KERN_ERR "%s: ERROR=%d. Camera stopped - "
+		       "reconnect or reload driver.\n", proc, i);
+		ibmcam->last_error = i;
+	}
 	return i;
 }
 
@@ -1053,86 +1095,86 @@
  * History:
  * 1/2/00   Created.
  */
-static void usb_ibmcam_send_FF_04_02(struct usb_device *dev)
+static void usb_ibmcam_send_FF_04_02(struct usb_ibmcam *ibmcam)
 {
-	usb_ibmcam_veio(dev, 0, 0x00FF, 0x0127);
-	usb_ibmcam_veio(dev, 0, 0x0004, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0002, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x00FF, 0x0127);
+	usb_ibmcam_veio(ibmcam, 0, 0x0004, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0002, 0x0124);
 }
 
-static void usb_ibmcam_send_00_04_06(struct usb_device *dev)
+static void usb_ibmcam_send_00_04_06(struct usb_ibmcam *ibmcam)
 {
-	usb_ibmcam_veio(dev, 0, 0x0000, 0x0127);
-	usb_ibmcam_veio(dev, 0, 0x0004, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0006, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0000, 0x0127);
+	usb_ibmcam_veio(ibmcam, 0, 0x0004, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0006, 0x0124);
 }
 
-static void usb_ibmcam_send_x_00(struct usb_device *dev, unsigned short x)
+static void usb_ibmcam_send_x_00(struct usb_ibmcam *ibmcam, unsigned short x)
 {
-	usb_ibmcam_veio(dev, 0, x,      0x0127);
-	usb_ibmcam_veio(dev, 0, 0x0000, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, x,      0x0127);
+	usb_ibmcam_veio(ibmcam, 0, 0x0000, 0x0124);
 }
 
-static void usb_ibmcam_send_x_00_05(struct usb_device *dev, unsigned short x)
+static void usb_ibmcam_send_x_00_05(struct usb_ibmcam *ibmcam, unsigned short x)
 {
-	usb_ibmcam_send_x_00(dev, x);
-	usb_ibmcam_veio(dev, 0, 0x0005, 0x0124);
+	usb_ibmcam_send_x_00(ibmcam, x);
+	usb_ibmcam_veio(ibmcam, 0, 0x0005, 0x0124);
 }
 
-static void usb_ibmcam_send_x_00_05_02(struct usb_device *dev, unsigned short x)
+static void usb_ibmcam_send_x_00_05_02(struct usb_ibmcam *ibmcam, unsigned short x)
 {
-	usb_ibmcam_veio(dev, 0, x,      0x0127);
-	usb_ibmcam_veio(dev, 0, 0x0000, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0005, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0002, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, x,      0x0127);
+	usb_ibmcam_veio(ibmcam, 0, 0x0000, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0005, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0002, 0x0124);
 }
 
-static void usb_ibmcam_send_x_01_00_05(struct usb_device *dev, unsigned short x)
+static void usb_ibmcam_send_x_01_00_05(struct usb_ibmcam *ibmcam, unsigned short x)
 {
-	usb_ibmcam_veio(dev, 0, x,      0x0127);
-	usb_ibmcam_veio(dev, 0, 0x0001, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0000, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0005, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, x,      0x0127);
+	usb_ibmcam_veio(ibmcam, 0, 0x0001, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0000, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0005, 0x0124);
 }
 
-static void usb_ibmcam_send_x_00_05_02_01(struct usb_device *dev, unsigned short x)
+static void usb_ibmcam_send_x_00_05_02_01(struct usb_ibmcam *ibmcam, unsigned short x)
 {
-	usb_ibmcam_veio(dev, 0, x,      0x0127);
-	usb_ibmcam_veio(dev, 0, 0x0000, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0005, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0002, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0001, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, x,      0x0127);
+	usb_ibmcam_veio(ibmcam, 0, 0x0000, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0005, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0002, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0001, 0x0124);
 }
 
-static void usb_ibmcam_send_x_00_05_02_08_01(struct usb_device *dev, unsigned short x)
+static void usb_ibmcam_send_x_00_05_02_08_01(struct usb_ibmcam *ibmcam, unsigned short x)
 {
-	usb_ibmcam_veio(dev, 0, x,      0x0127);
-	usb_ibmcam_veio(dev, 0, 0x0000, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0005, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0002, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0008, 0x0124);
-	usb_ibmcam_veio(dev, 0, 0x0001, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, x,      0x0127);
+	usb_ibmcam_veio(ibmcam, 0, 0x0000, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0005, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0002, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0008, 0x0124);
+	usb_ibmcam_veio(ibmcam, 0, 0x0001, 0x0124);
 }
 
-static void usb_ibmcam_Packet_Format1(struct usb_device *dev, unsigned char fkey, unsigned char val)
+static void usb_ibmcam_Packet_Format1(struct usb_ibmcam *ibmcam, unsigned char fkey, unsigned char val)
 {
-	usb_ibmcam_send_x_01_00_05	(dev, unknown_88);
-	usb_ibmcam_send_x_00_05		(dev, fkey);
-	usb_ibmcam_send_x_00_05_02_08_01(dev, val);
-	usb_ibmcam_send_x_00_05		(dev, unknown_88);
-	usb_ibmcam_send_x_00_05_02_01	(dev, fkey);
-	usb_ibmcam_send_x_00_05		(dev, unknown_89);
-	usb_ibmcam_send_x_00		(dev, fkey);
-	usb_ibmcam_send_00_04_06	(dev);
-	usb_ibmcam_veio			(dev, 1, 0x0000, 0x0126);
-	usb_ibmcam_send_FF_04_02	(dev);
+	usb_ibmcam_send_x_01_00_05	(ibmcam, unknown_88);
+	usb_ibmcam_send_x_00_05		(ibmcam, fkey);
+	usb_ibmcam_send_x_00_05_02_08_01(ibmcam, val);
+	usb_ibmcam_send_x_00_05		(ibmcam, unknown_88);
+	usb_ibmcam_send_x_00_05_02_01	(ibmcam, fkey);
+	usb_ibmcam_send_x_00_05		(ibmcam, unknown_89);
+	usb_ibmcam_send_x_00		(ibmcam, fkey);
+	usb_ibmcam_send_00_04_06	(ibmcam);
+	usb_ibmcam_veio			(ibmcam, 1, 0x0000, 0x0126);
+	usb_ibmcam_send_FF_04_02	(ibmcam);
 }
 
-static void usb_ibmcam_PacketFormat2(struct usb_device *dev, unsigned char fkey, unsigned char val)
+static void usb_ibmcam_PacketFormat2(struct usb_ibmcam *ibmcam, unsigned char fkey, unsigned char val)
 {
-	usb_ibmcam_send_x_01_00_05	(dev, unknown_88);
-	usb_ibmcam_send_x_00_05		(dev, fkey);
-	usb_ibmcam_send_x_00_05_02	(dev, val);
+	usb_ibmcam_send_x_01_00_05	(ibmcam, unknown_88);
+	usb_ibmcam_send_x_00_05		(ibmcam, fkey);
+	usb_ibmcam_send_x_00_05_02	(ibmcam, val);
 }
 
 /*
@@ -1149,7 +1191,6 @@
  */
 static void usb_ibmcam_adjust_contrast(struct usb_ibmcam *ibmcam)
 {
-	struct usb_device *dev = ibmcam->dev;
 	unsigned char new_contrast = ibmcam->vpic.contrast >> 12;
 	const int ntries = 5;
 
@@ -1160,10 +1201,9 @@
 		int i;
 		ibmcam->vpic_old.contrast = new_contrast;
 		for (i=0; i < ntries; i++) {
-			usb_ibmcam_Packet_Format1(dev, contrast_14, new_contrast);
-			usb_ibmcam_send_FF_04_02(dev);
+			usb_ibmcam_Packet_Format1(ibmcam, contrast_14, new_contrast);
+			usb_ibmcam_send_FF_04_02(ibmcam);
 		}
-		/*usb_ibmcam_veio(dev, 0, 0x00FF, 0x0127);*/
 	}
 }
 
@@ -1179,7 +1219,6 @@
 static void usb_ibmcam_change_lighting_conditions(struct usb_ibmcam *ibmcam)
 {
 	static const char proc[] = "usb_ibmcam_change_lighting_conditions";
-	struct usb_device *dev = ibmcam->dev;
 	const int ntries = 5;
 	int i;
 
@@ -1188,13 +1227,12 @@
 		printk(KERN_INFO "%s: Set lighting to %hu.\n", proc, lighting);
 
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, light_27, (unsigned short) lighting);
+		usb_ibmcam_Packet_Format1(ibmcam, light_27, (unsigned short) lighting);
 }
 
 static void usb_ibmcam_set_sharpness(struct usb_ibmcam *ibmcam)
 {
 	static const char proc[] = "usb_ibmcam_set_sharpness";
-	struct usb_device *dev = ibmcam->dev;
 	static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
 	unsigned short i, sv;
 
@@ -1204,16 +1242,15 @@
 
 	sv = sa[sharpness - SHARPNESS_MIN];
 	for (i=0; i < 2; i++) {
-		usb_ibmcam_send_x_01_00_05	(dev, unknown_88);
-		usb_ibmcam_send_x_00_05		(dev, sharp_13);
-		usb_ibmcam_send_x_00_05_02	(dev, sv);
+		usb_ibmcam_send_x_01_00_05	(ibmcam, unknown_88);
+		usb_ibmcam_send_x_00_05		(ibmcam, sharp_13);
+		usb_ibmcam_send_x_00_05_02	(ibmcam, sv);
 	}
 }
 
 static void usb_ibmcam_set_brightness(struct usb_ibmcam *ibmcam)
 {
 	static const char proc[] = "usb_ibmcam_set_brightness";
-	struct usb_device *dev = ibmcam->dev;
 	static const unsigned short n = 1;
 	unsigned short i, j, bv[3];
 
@@ -1228,7 +1265,7 @@
 
 	for (j=0; j < 3; j++)
 		for (i=0; i < n; i++)
-			usb_ibmcam_Packet_Format1(dev, bright_3x[j], bv[j]);
+			usb_ibmcam_Packet_Format1(ibmcam, bright_3x[j], bv[j]);
 }
 
 static void usb_ibmcam_adjust_picture(struct usb_ibmcam *ibmcam)
@@ -1239,197 +1276,196 @@
 
 static int usb_ibmcam_setup(struct usb_ibmcam *ibmcam)
 {
-	struct usb_device *dev = ibmcam->dev;
 	const int ntries = 5;
 	int i;
 
-	usb_ibmcam_veio(dev, 1, 0, 0x128);
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0100);
-	usb_ibmcam_veio(dev, 0, 0x01, 0x0100);	/* LED On  */
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0100);
-	usb_ibmcam_veio(dev, 0, 0x81, 0x0100);  /* LED Off */
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0100);
-	usb_ibmcam_veio(dev, 0, 0x01, 0x0100);	/* LED On  */
-	usb_ibmcam_veio(dev, 0, 0x01, 0x0108);
-
-	usb_ibmcam_veio(dev, 0, 0x03, 0x0112);
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0115);
-	usb_ibmcam_veio(dev, 0, 0x06, 0x0115);
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0116);
-	usb_ibmcam_veio(dev, 0, 0x44, 0x0116);
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0116);
-	usb_ibmcam_veio(dev, 0, 0x40, 0x0116);
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0115);
-	usb_ibmcam_veio(dev, 0, 0x0e, 0x0115);
-	usb_ibmcam_veio(dev, 0, 0x19, 0x012c);
-
-	usb_ibmcam_Packet_Format1(dev, 0x00, 0x1e);
-	usb_ibmcam_Packet_Format1(dev, 0x39, 0x0d);
-	usb_ibmcam_Packet_Format1(dev, 0x39, 0x09);
-	usb_ibmcam_Packet_Format1(dev, 0x3b, 0x00);
-	usb_ibmcam_Packet_Format1(dev, 0x28, 0x22);
-	usb_ibmcam_Packet_Format1(dev, light_27, 0);
-	usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1f);
-	usb_ibmcam_Packet_Format1(dev, 0x39, 0x08);
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0128);
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0100);
+	usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0100);	/* LED On  */
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0100);
+	usb_ibmcam_veio(ibmcam, 0, 0x81, 0x0100);  /* LED Off */
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0100);
+	usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0100);	/* LED On  */
+	usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0108);
+
+	usb_ibmcam_veio(ibmcam, 0, 0x03, 0x0112);
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0115);
+	usb_ibmcam_veio(ibmcam, 0, 0x06, 0x0115);
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0116);
+	usb_ibmcam_veio(ibmcam, 0, 0x44, 0x0116);
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0116);
+	usb_ibmcam_veio(ibmcam, 0, 0x40, 0x0116);
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0115);
+	usb_ibmcam_veio(ibmcam, 0, 0x0e, 0x0115);
+	usb_ibmcam_veio(ibmcam, 0, 0x19, 0x012c);
+
+	usb_ibmcam_Packet_Format1(ibmcam, 0x00, 0x1e);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x39, 0x0d);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x39, 0x09);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x3b, 0x00);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x28, 0x22);
+	usb_ibmcam_Packet_Format1(ibmcam, light_27, 0);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x2b, 0x1f);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x39, 0x08);
 
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x2c, 0x00);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x2c, 0x00);
 
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x30, 0x14);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x30, 0x14);
 
-	usb_ibmcam_PacketFormat2(dev, 0x39, 0x02);
-	usb_ibmcam_PacketFormat2(dev, 0x01, 0xe1);
-	usb_ibmcam_PacketFormat2(dev, 0x02, 0xcd);
-	usb_ibmcam_PacketFormat2(dev, 0x03, 0xcd);
-	usb_ibmcam_PacketFormat2(dev, 0x04, 0xfa);
-	usb_ibmcam_PacketFormat2(dev, 0x3f, 0xff);
-	usb_ibmcam_PacketFormat2(dev, 0x39, 0x00);
-
-	usb_ibmcam_PacketFormat2(dev, 0x39, 0x02);
-	usb_ibmcam_PacketFormat2(dev, 0x0a, 0x37);
-	usb_ibmcam_PacketFormat2(dev, 0x0b, 0xb8);
-	usb_ibmcam_PacketFormat2(dev, 0x0c, 0xf3);
-	usb_ibmcam_PacketFormat2(dev, 0x0d, 0xe3);
-	usb_ibmcam_PacketFormat2(dev, 0x0e, 0x0d);
-	usb_ibmcam_PacketFormat2(dev, 0x0f, 0xf2);
-	usb_ibmcam_PacketFormat2(dev, 0x10, 0xd5);
-	usb_ibmcam_PacketFormat2(dev, 0x11, 0xba);
-	usb_ibmcam_PacketFormat2(dev, 0x12, 0x53);
-	usb_ibmcam_PacketFormat2(dev, 0x3f, 0xff);
-	usb_ibmcam_PacketFormat2(dev, 0x39, 0x00);
-
-	usb_ibmcam_PacketFormat2(dev, 0x39, 0x02);
-	usb_ibmcam_PacketFormat2(dev, 0x16, 0x00);
-	usb_ibmcam_PacketFormat2(dev, 0x17, 0x28);
-	usb_ibmcam_PacketFormat2(dev, 0x18, 0x7d);
-	usb_ibmcam_PacketFormat2(dev, 0x19, 0xbe);
-	usb_ibmcam_PacketFormat2(dev, 0x3f, 0xff);
-	usb_ibmcam_PacketFormat2(dev, 0x39, 0x00);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x39, 0x02);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x01, 0xe1);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x02, 0xcd);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x03, 0xcd);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x04, 0xfa);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x3f, 0xff);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x39, 0x00);
+
+	usb_ibmcam_PacketFormat2(ibmcam, 0x39, 0x02);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x0a, 0x37);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x0b, 0xb8);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x0c, 0xf3);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x0d, 0xe3);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x0e, 0x0d);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x0f, 0xf2);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x10, 0xd5);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x11, 0xba);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x12, 0x53);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x3f, 0xff);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x39, 0x00);
+
+	usb_ibmcam_PacketFormat2(ibmcam, 0x39, 0x02);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x16, 0x00);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x17, 0x28);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x18, 0x7d);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x19, 0xbe);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x3f, 0xff);
+	usb_ibmcam_PacketFormat2(ibmcam, 0x39, 0x00);
 
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x00, 0x18);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x00, 0x18);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x13, 0x18);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x13, 0x18);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x14, 0x06);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x14, 0x06);
 
 	/* This is default brightness */
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x31, 0x37);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x31, 0x37);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x32, 0x46);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x32, 0x46);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x33, 0x55);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x33, 0x55);
 
-	usb_ibmcam_Packet_Format1(dev, 0x2e, 0x04);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x2e, 0x04);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x2d, 0x04);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x2d, 0x04);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x29, 0x80);
-	usb_ibmcam_Packet_Format1(dev, 0x2c, 0x01);
-	usb_ibmcam_Packet_Format1(dev, 0x30, 0x17);
-	usb_ibmcam_Packet_Format1(dev, 0x39, 0x08);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x29, 0x80);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x2c, 0x01);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x30, 0x17);
+	usb_ibmcam_Packet_Format1(ibmcam, 0x39, 0x08);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x34, 0x00);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x34, 0x00);
 
-	usb_ibmcam_veio(dev, 0, 0x00, 0x0101);
-	usb_ibmcam_veio(dev, 0, 0x00, 0x010a);
+	usb_ibmcam_veio(ibmcam, 0, 0x00, 0x0101);
+	usb_ibmcam_veio(ibmcam, 0, 0x00, 0x010a);
 
 	switch (videosize) {
 	case VIDEOSIZE_128x96:
-		usb_ibmcam_veio(dev, 0, 0x80, 0x0103);
-		usb_ibmcam_veio(dev, 0, 0x60, 0x0105);
-		usb_ibmcam_veio(dev, 0, 0x0c, 0x010b);
-		usb_ibmcam_veio(dev, 0, 0x04, 0x011b);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x0b, 0x011d);
-		usb_ibmcam_veio(dev, 0, 0x00, 0x011e);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x00, 0x0129);
+		usb_ibmcam_veio(ibmcam, 0, 0x80, 0x0103);
+		usb_ibmcam_veio(ibmcam, 0, 0x60, 0x0105);
+		usb_ibmcam_veio(ibmcam, 0, 0x0c, 0x010b);
+		usb_ibmcam_veio(ibmcam, 0, 0x04, 0x011b);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x0b, 0x011d);
+		usb_ibmcam_veio(ibmcam, 0, 0x00, 0x011e);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x00, 0x0129);
 		break;
 	case VIDEOSIZE_176x144:
-		usb_ibmcam_veio(dev, 0, 0xb0, 0x0103);
-		usb_ibmcam_veio(dev, 0, 0x8f, 0x0105);
-		usb_ibmcam_veio(dev, 0, 0x06, 0x010b);
-		usb_ibmcam_veio(dev, 0, 0x04, 0x011b);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x0d, 0x011d);
-		usb_ibmcam_veio(dev, 0, 0x00, 0x011e);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x03, 0x0129);
+		usb_ibmcam_veio(ibmcam, 0, 0xb0, 0x0103);
+		usb_ibmcam_veio(ibmcam, 0, 0x8f, 0x0105);
+		usb_ibmcam_veio(ibmcam, 0, 0x06, 0x010b);
+		usb_ibmcam_veio(ibmcam, 0, 0x04, 0x011b);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x0d, 0x011d);
+		usb_ibmcam_veio(ibmcam, 0, 0x00, 0x011e);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x03, 0x0129);
 		break;
 	case VIDEOSIZE_352x288:
-		usb_ibmcam_veio(dev, 0, 0xb0, 0x0103);
-		usb_ibmcam_veio(dev, 0, 0x90, 0x0105);
-		usb_ibmcam_veio(dev, 0, 0x02, 0x010b);
-		usb_ibmcam_veio(dev, 0, 0x04, 0x011b);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x05, 0x011d);
-		usb_ibmcam_veio(dev, 0, 0x00, 0x011e);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x00, 0x0129);
+		usb_ibmcam_veio(ibmcam, 0, 0xb0, 0x0103);
+		usb_ibmcam_veio(ibmcam, 0, 0x90, 0x0105);
+		usb_ibmcam_veio(ibmcam, 0, 0x02, 0x010b);
+		usb_ibmcam_veio(ibmcam, 0, 0x04, 0x011b);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x05, 0x011d);
+		usb_ibmcam_veio(ibmcam, 0, 0x00, 0x011e);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x00, 0x0129);
 		break;
 	}
 
-	usb_ibmcam_veio(dev, 0, 0xff, 0x012b);
+	usb_ibmcam_veio(ibmcam, 0, 0xff, 0x012b);
 
 	/* This is another brightness - don't know why */
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x31, 0xc3);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x31, 0xc3);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x32, 0xd2);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x32, 0xd2);
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, 0x33, 0xe1);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x33, 0xe1);
 
 	/* Default contrast */
 	for (i=0; i < ntries; i++)
-		usb_ibmcam_Packet_Format1(dev, contrast_14, 0x0a);
+		usb_ibmcam_Packet_Format1(ibmcam, contrast_14, 0x0a);
 
 	/* Default sharpness */
 	for (i=0; i < 2; i++)
-		usb_ibmcam_PacketFormat2(dev, sharp_13, 0x1a);	/* Level 4 FIXME */
+		usb_ibmcam_PacketFormat2(ibmcam, sharp_13, 0x1a);	/* Level 4 FIXME */
 
 	/* Default lighting conditions */
-	usb_ibmcam_Packet_Format1(dev, light_27, lighting); /* 0=Bright 2=Low */
+	usb_ibmcam_Packet_Format1(ibmcam, light_27, lighting); /* 0=Bright 2=Low */
 
 	/* Assorted init */
 
 	switch (videosize) {
 	case VIDEOSIZE_128x96:
-		usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1e);
-		usb_ibmcam_veio(dev, 0, 0xc9, 0x0119);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x80, 0x0109);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x36, 0x0102);
-		usb_ibmcam_veio(dev, 0, 0x1a, 0x0104);
-		usb_ibmcam_veio(dev, 0, 0x04, 0x011a);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x2b, 0x011c);
-		usb_ibmcam_veio(dev, 0, 0x23, 0x012a);	/* Same everywhere */
+		usb_ibmcam_Packet_Format1(ibmcam, 0x2b, 0x1e);
+		usb_ibmcam_veio(ibmcam, 0, 0xc9, 0x0119);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x80, 0x0109);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x36, 0x0102);
+		usb_ibmcam_veio(ibmcam, 0, 0x1a, 0x0104);
+		usb_ibmcam_veio(ibmcam, 0, 0x04, 0x011a);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x2b, 0x011c);
+		usb_ibmcam_veio(ibmcam, 0, 0x23, 0x012a);	/* Same everywhere */
 #if 0
-		usb_ibmcam_veio(dev, 0, 0x00, 0x0106);
-		usb_ibmcam_veio(dev, 0, 0x38, 0x0107);
+		usb_ibmcam_veio(ibmcam, 0, 0x00, 0x0106);
+		usb_ibmcam_veio(ibmcam, 0, 0x38, 0x0107);
 #else
-		usb_ibmcam_veio(dev, 0, 0x02, 0x0106);
-		usb_ibmcam_veio(dev, 0, 0x2a, 0x0107);
+		usb_ibmcam_veio(ibmcam, 0, 0x02, 0x0106);
+		usb_ibmcam_veio(ibmcam, 0, 0x2a, 0x0107);
 #endif
 		break;
 	case VIDEOSIZE_176x144:
-		usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1e);
-		usb_ibmcam_veio(dev, 0, 0xc9, 0x0119);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x80, 0x0109);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x04, 0x0102);
-		usb_ibmcam_veio(dev, 0, 0x02, 0x0104);
-		usb_ibmcam_veio(dev, 0, 0x04, 0x011a);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x2b, 0x011c);
-		usb_ibmcam_veio(dev, 0, 0x23, 0x012a);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x01, 0x0106);
-		usb_ibmcam_veio(dev, 0, 0xca, 0x0107);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x2b, 0x1e);
+		usb_ibmcam_veio(ibmcam, 0, 0xc9, 0x0119);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x80, 0x0109);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x04, 0x0102);
+		usb_ibmcam_veio(ibmcam, 0, 0x02, 0x0104);
+		usb_ibmcam_veio(ibmcam, 0, 0x04, 0x011a);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x2b, 0x011c);
+		usb_ibmcam_veio(ibmcam, 0, 0x23, 0x012a);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0106);
+		usb_ibmcam_veio(ibmcam, 0, 0xca, 0x0107);
 		break;
 	case VIDEOSIZE_352x288:
-		usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1f);
-		usb_ibmcam_veio(dev, 0, 0xc9, 0x0119);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x80, 0x0109);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x08, 0x0102);
-		usb_ibmcam_veio(dev, 0, 0x01, 0x0104);
-		usb_ibmcam_veio(dev, 0, 0x04, 0x011a);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x2f, 0x011c);
-		usb_ibmcam_veio(dev, 0, 0x23, 0x012a);	/* Same everywhere */
-		usb_ibmcam_veio(dev, 0, 0x03, 0x0106);
-		usb_ibmcam_veio(dev, 0, 0xf6, 0x0107);
+		usb_ibmcam_Packet_Format1(ibmcam, 0x2b, 0x1f);
+		usb_ibmcam_veio(ibmcam, 0, 0xc9, 0x0119);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x80, 0x0109);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x08, 0x0102);
+		usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0104);
+		usb_ibmcam_veio(ibmcam, 0, 0x04, 0x011a);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x2f, 0x011c);
+		usb_ibmcam_veio(ibmcam, 0, 0x23, 0x012a);	/* Same everywhere */
+		usb_ibmcam_veio(ibmcam, 0, 0x03, 0x0106);
+		usb_ibmcam_veio(ibmcam, 0, 0xf6, 0x0107);
 		break;
 	}
 	return 0; /* TODO: return actual completion status! */
@@ -1441,16 +1477,16 @@
  * This code adds finishing touches to the video data interface.
  * Here we configure the frame rate and turn on the LED.
  */
-static void usb_ibmcam_setup_after_video_if(struct usb_device *dev)
+static void usb_ibmcam_setup_after_video_if(struct usb_ibmcam *ibmcam)
 {
 	unsigned short internal_frame_rate;
 
 	RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
 	internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */
-	usb_ibmcam_veio(dev, 0, 0x01, 0x0100);	/* LED On  */
-	usb_ibmcam_veio(dev, 0, internal_frame_rate, 0x0111);
-	usb_ibmcam_veio(dev, 0, 0x01, 0x0114);
-	usb_ibmcam_veio(dev, 0, 0xc0, 0x010c);
+	usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0100);	/* LED On  */
+	usb_ibmcam_veio(ibmcam, 0, internal_frame_rate, 0x0111);
+	usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0114);
+	usb_ibmcam_veio(ibmcam, 0, 0xc0, 0x010c);
 }
 
 /*
@@ -1459,16 +1495,16 @@
  * This code tells camera to stop streaming. The interface remains
  * configured and bandwidth - claimed.
  */
-static void usb_ibmcam_setup_video_stop(struct usb_device *dev)
+static void usb_ibmcam_setup_video_stop(struct usb_ibmcam *ibmcam)
 {
-	usb_ibmcam_veio(dev, 0, 0x00, 0x010c);
-	usb_ibmcam_veio(dev, 0, 0x00, 0x010c);
-	usb_ibmcam_veio(dev, 0, 0x01, 0x0114);
-	usb_ibmcam_veio(dev, 0, 0xc0, 0x010c);
-	usb_ibmcam_veio(dev, 0, 0x00, 0x010c);
-	usb_ibmcam_send_FF_04_02(dev);
-	usb_ibmcam_veio(dev, 1, 0x00, 0x0100);
-	usb_ibmcam_veio(dev, 0, 0x81, 0x0100);	/* LED Off */
+	usb_ibmcam_veio(ibmcam, 0, 0x00, 0x010c);
+	usb_ibmcam_veio(ibmcam, 0, 0x00, 0x010c);
+	usb_ibmcam_veio(ibmcam, 0, 0x01, 0x0114);
+	usb_ibmcam_veio(ibmcam, 0, 0xc0, 0x010c);
+	usb_ibmcam_veio(ibmcam, 0, 0x00, 0x010c);
+	usb_ibmcam_send_FF_04_02(ibmcam);
+	usb_ibmcam_veio(ibmcam, 1, 0x00, 0x0100);
+	usb_ibmcam_veio(ibmcam, 0, 0x81, 0x0100);	/* LED Off */
 }
 
 /*
@@ -1484,19 +1520,28 @@
 static void usb_ibmcam_reinit_iso(struct usb_ibmcam *ibmcam, int do_stop)
 {
 	if (do_stop)
-		usb_ibmcam_setup_video_stop(ibmcam->dev);
+		usb_ibmcam_setup_video_stop(ibmcam);
 
-	usb_ibmcam_veio(ibmcam->dev, 0, 0x0001, 0x0114);
-	usb_ibmcam_veio(ibmcam->dev, 0, 0x00c0, 0x010c);
+	usb_ibmcam_veio(ibmcam, 0, 0x0001, 0x0114);
+	usb_ibmcam_veio(ibmcam, 0, 0x00c0, 0x010c);
 	usb_clear_halt(ibmcam->dev, ibmcam->video_endp);
-	usb_ibmcam_setup_after_video_if(ibmcam->dev);
+	usb_ibmcam_setup_after_video_if(ibmcam);
 }
 
+/*
+ * ibmcam_init_isoc()
+ *
+ * History:
+ * 1/27/00  Used ibmcam->iface, ibmcam->ifaceAltActive instead of hardcoded values.
+ *          Simplified by using for loop, allowed any number of URBs.
+ */
 static int ibmcam_init_isoc(struct usb_ibmcam *ibmcam)
 {
 	struct usb_device *dev = ibmcam->dev;
-	urb_t *urb;
-	int fx, err;
+	int i, err;
+
+	if (!IBMCAM_IS_OPERATIONAL(ibmcam))
+		return -EFAULT;
 
 	ibmcam->compress = 0;
 	ibmcam->curframe = -1;
@@ -1504,8 +1549,10 @@
 	ibmcam->scratchlen = 0;
 
 	/* Alternate interface 1 is is the biggest frame size */
-	if (usb_set_interface(ibmcam->dev, 2, 1) < 0) {
+	i = usb_set_interface(dev, ibmcam->iface, ibmcam->ifaceAltActive);
+	if (i < 0) {
 		printk(KERN_ERR "usb_set_interface error\n");
+		ibmcam->last_error = i;
 		return -EBUSY;
 	}
 	usb_ibmcam_change_lighting_conditions(ibmcam);
@@ -1513,57 +1560,46 @@
 	usb_ibmcam_reinit_iso(ibmcam, 0);
 
 	/* We double buffer the Iso lists */
-	urb = usb_alloc_urb(FRAMES_PER_DESC);
-	
-	if (!urb) {
-		printk(KERN_ERR "ibmcam_init_isoc: usb_init_isoc ret %d\n",
-			0);
-		return -ENOMEM;
-	}
-	ibmcam->sbuf[0].urb = urb;
-	urb->dev = dev;
-	urb->context = ibmcam;
-	urb->pipe = usb_rcvisocpipe(dev, ibmcam->video_endp);
-	urb->transfer_flags = USB_ISO_ASAP;
-	urb->transfer_buffer = ibmcam->sbuf[0].data;
- 	urb->complete = ibmcam_isoc_irq;
- 	urb->number_of_packets = FRAMES_PER_DESC;
- 	urb->transfer_buffer_length = ibmcam->iso_packet_len * FRAMES_PER_DESC;
- 	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
- 		urb->iso_frame_desc[fx].offset = ibmcam->iso_packet_len * fx;
-		urb->iso_frame_desc[fx].length = ibmcam->iso_packet_len;
-	}
-	urb = usb_alloc_urb(FRAMES_PER_DESC);
-	if (!urb) {
-		printk(KERN_ERR "ibmcam_init_isoc: usb_init_isoc ret %d\n",
-			0);
-		return -ENOMEM;
-	}
-	ibmcam->sbuf[1].urb = urb;
-	urb->dev = dev;
-	urb->context = ibmcam;
-	urb->pipe = usb_rcvisocpipe(dev, ibmcam->video_endp);
-	urb->transfer_flags = USB_ISO_ASAP;
-	urb->transfer_buffer = ibmcam->sbuf[1].data;
- 	urb->complete = ibmcam_isoc_irq;
- 	urb->number_of_packets = FRAMES_PER_DESC;
- 	urb->transfer_buffer_length = ibmcam->iso_packet_len * FRAMES_PER_DESC;
- 	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
- 		urb->iso_frame_desc[fx].offset = ibmcam->iso_packet_len * fx;
-		urb->iso_frame_desc[fx].length = ibmcam->iso_packet_len;
+
+	for (i=0; i < IBMCAM_NUMSBUF; i++) {
+		int j, k;
+		urb_t *urb;
+
+		urb = usb_alloc_urb(FRAMES_PER_DESC);
+		if (urb == NULL) {
+			printk(KERN_ERR "ibmcam_init_isoc: usb_init_isoc() failed.\n");
+			return -ENOMEM;
+		}
+		ibmcam->sbuf[i].urb = urb;
+		urb->dev = dev;
+		urb->context = ibmcam;
+		urb->pipe = usb_rcvisocpipe(dev, ibmcam->video_endp);
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->transfer_buffer = ibmcam->sbuf[i].data;
+		urb->complete = ibmcam_isoc_irq;
+		urb->number_of_packets = FRAMES_PER_DESC;
+		urb->transfer_buffer_length = ibmcam->iso_packet_len * FRAMES_PER_DESC;
+		for (j=k=0; j < FRAMES_PER_DESC; j++, k += ibmcam->iso_packet_len) {
+			urb->iso_frame_desc[j].offset = k;
+			urb->iso_frame_desc[j].length = ibmcam->iso_packet_len;
+		}
 	}
 
-	ibmcam->sbuf[1].urb->next = ibmcam->sbuf[0].urb;
-	ibmcam->sbuf[0].urb->next = ibmcam->sbuf[1].urb;
-	
-	err = usb_submit_urb(ibmcam->sbuf[0].urb);
-	if (err)
-		printk(KERN_ERR "ibmcam_init_isoc: usb_run_isoc(0) ret %d\n",
-			err);
-	err = usb_submit_urb(ibmcam->sbuf[1].urb);
-	if (err)
-		printk(KERN_ERR "ibmcam_init_isoc: usb_run_isoc(1) ret %d\n",
-			err);
+	/* Link URBs into a ring so that they invoke each other infinitely */
+	for (i=0; i < IBMCAM_NUMSBUF; i++) {
+		if ((i+1) < IBMCAM_NUMSBUF)
+			ibmcam->sbuf[i].urb->next = ibmcam->sbuf[i+1].urb;
+		else
+			ibmcam->sbuf[i].urb->next = ibmcam->sbuf[0].urb;
+	}
+
+	/* Submit all URBs */
+	for (i=0; i < IBMCAM_NUMSBUF; i++) {
+		err = usb_submit_urb(ibmcam->sbuf[i].urb);
+		if (err)
+			printk(KERN_ERR "ibmcam_init_isoc: usb_run_isoc(%d) ret %d\n",
+			       i, err);
+	}
 
 	ibmcam->streaming = 1;
 	// printk(KERN_DEBUG "streaming=1 ibmcam->video_endp=$%02x\n", ibmcam->video_endp);
@@ -1578,28 +1614,39 @@
  *
  * History:
  * 1/22/00  Corrected order of actions to work after surprise removal.
+ * 1/27/00  Used ibmcam->iface, ibmcam->ifaceAltInactive instead of hardcoded values.
  */
 static void ibmcam_stop_isoc(struct usb_ibmcam *ibmcam)
 {
-	if (!ibmcam->streaming)
+	static const char proc[] = "ibmcam_stop_isoc";
+	int i, j;
+
+	if (!ibmcam->streaming || (ibmcam->dev == NULL))
 		return;
 
 	/* Unschedule all of the iso td's */
-	usb_unlink_urb(ibmcam->sbuf[1].urb);
-	usb_unlink_urb(ibmcam->sbuf[0].urb);
-
+	for (i=0; i < IBMCAM_NUMSBUF; i++) {
+		j = usb_unlink_urb(ibmcam->sbuf[i].urb);
+		if (j < 0)
+			printk(KERN_ERR "%s: usb_unlink_urb() error %d.\n", proc, j);
+	}
 	/* printk(KERN_DEBUG "streaming=0\n"); */
 	ibmcam->streaming = 0;
 
 	/* Delete them all */
-	usb_free_urb(ibmcam->sbuf[1].urb);
-	usb_free_urb(ibmcam->sbuf[0].urb);
+	for (i=0; i < IBMCAM_NUMSBUF; i++)
+		usb_free_urb(ibmcam->sbuf[i].urb);
 
-	usb_ibmcam_setup_video_stop(ibmcam->dev);
+	if (!ibmcam->remove_pending) {
+		usb_ibmcam_setup_video_stop(ibmcam);
 
-	/* Set packet size to 0 */
-	if (usb_set_interface(ibmcam->dev, 2, 0) < 0)
-		printk(KERN_ERR "usb_set_interface error\n");
+		/* Set packet size to 0 */
+		j = usb_set_interface(ibmcam->dev, ibmcam->iface, ibmcam->ifaceAltInactive);
+		if (j < 0) {
+			printk(KERN_ERR "%s: usb_set_interface() error %d.\n", proc, j);
+			ibmcam->last_error = j;
+		}
+	}
 }
 
 static int ibmcam_new_frame(struct usb_ibmcam *ibmcam, int framenum)
@@ -1669,11 +1716,11 @@
  * 1/22/00  Rewrote, moved scratch buffer allocation here. Now the
  *          camera is also initialized here (once per connect), at
  *          expense of V4L client (it waits on open() call).
+ * 1/27/00  Used IBMCAM_NUMSBUF as number of URB buffers.
  */
 static int ibmcam_open(struct video_device *dev, int flags)
 {
 	struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev;
-	const int nbuffers = 2;
 	const int sb_size = FRAMES_PER_DESC * ibmcam->iso_packet_len;
 	int i, err = 0;
 
@@ -1683,11 +1730,11 @@
 		err = -EBUSY;
 	else {
 		/* Clean pointers so we know if we allocated something */
-		for (i=0; i < nbuffers; i++)
+		for (i=0; i < IBMCAM_NUMSBUF; i++)
 			ibmcam->sbuf[i].data = NULL;
 
 		/* Allocate memory for the frame buffers */
-		ibmcam->fbuf_size = nbuffers * MAX_FRAME_SIZE;
+		ibmcam->fbuf_size = IBMCAM_NUMFRAMES * MAX_FRAME_SIZE;
 		ibmcam->fbuf = rvmalloc(ibmcam->fbuf_size);
 		ibmcam->scratch = kmalloc(scratchbufsize, GFP_KERNEL);
 		ibmcam->scratchlen = 0;
@@ -1695,15 +1742,9 @@
 			err = -ENOMEM;
 		else {
 			/* Allocate all buffers */
-			for (i=0; i < nbuffers; i++) {
+			for (i=0; i < IBMCAM_NUMFRAMES; i++) {
 				ibmcam->frame[i].grabstate = FRAME_UNUSED;
 				ibmcam->frame[i].data = ibmcam->fbuf + i*MAX_FRAME_SIZE;
-
-				ibmcam->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
-				if (ibmcam->sbuf[i].data == NULL) {
-					err = -ENOMEM;
-					break;
-				}
 				/*
 				 * Set default sizes in case IOCTL (VIDIOCMCAPTURE)
 				 * is not used (using read() instead).
@@ -1712,6 +1753,13 @@
 				ibmcam->frame[i].height = imgheight;
 				ibmcam->frame[i].bytes_read = 0;
 			}
+			for (i=0; i < IBMCAM_NUMSBUF; i++) {
+				ibmcam->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
+				if (ibmcam->sbuf[i].data == NULL) {
+					err = -ENOMEM;
+					break;
+				}
+			}
 		}
 		if (err) {
 			/* Have to free all that memory */
@@ -1723,7 +1771,7 @@
 				kfree(ibmcam->scratch);
 				ibmcam->scratch = NULL;
 			}
-			for (i=0; i < nbuffers; i++) {
+			for (i=0; i < IBMCAM_NUMSBUF; i++) {
 				if (ibmcam->sbuf[i].data != NULL) {
 					kfree (ibmcam->sbuf[i].data);
 					ibmcam->sbuf[i].data = NULL;
@@ -1762,10 +1810,12 @@
  *
  * History:
  * 1/22/00  Moved scratch buffer deallocation here.
+ * 1/27/00  Used IBMCAM_NUMSBUF as number of URB buffers.
  */
 static void ibmcam_close(struct video_device *dev)
 {
 	struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev;
+	int i;
 
 	down(&ibmcam->lock);	
 
@@ -1773,12 +1823,16 @@
 
 	rvfree(ibmcam->fbuf, ibmcam->fbuf_size);
 	kfree(ibmcam->scratch);
-	kfree(ibmcam->sbuf[1].data);
-	kfree(ibmcam->sbuf[0].data);
+	for (i=0; i < IBMCAM_NUMSBUF; i++)
+		kfree(ibmcam->sbuf[i].data);
 
 	ibmcam->user--;
 	MOD_DEC_USE_COUNT;
 
+	if (ibmcam->remove_pending) {
+		printk(KERN_INFO "ibmcam_close: Final disconnect.\n");
+		usb_ibmcam_release(ibmcam);
+	}
 	up(&ibmcam->lock);
 }
 
@@ -1804,7 +1858,7 @@
 {
 	struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev;
 
-	if (ibmcam->remove_pending)
+	if (!IBMCAM_IS_OPERATIONAL(ibmcam))
 		return -EFAULT;
 
 	switch (cmd) {
@@ -1959,6 +2013,8 @@
 			{
 				int ntries;
 		redo:
+				if (!IBMCAM_IS_OPERATIONAL(ibmcam))
+					return -EIO;
 				ntries = 0; 
 				do {
 					interruptible_sleep_on(&ibmcam->frame[frame].wq);
@@ -2042,10 +2098,7 @@
 	if (debug >= 1)
 		printk(KERN_DEBUG "ibmcam_read: %ld bytes, noblock=%d\n", count, noblock);
 
-	if (ibmcam->remove_pending)
-		return -EFAULT;
-
-	if (!dev || !buf)
+	if (!IBMCAM_IS_OPERATIONAL(ibmcam) || (buf == NULL))
 		return -EFAULT;
 
 	/* See if a frame is completed, then use it. */
@@ -2073,6 +2126,8 @@
 	frame = &ibmcam->frame[frmx];
 
 restart:
+	if (!IBMCAM_IS_OPERATIONAL(ibmcam))
+		return -EIO;
 	while (frame->grabstate == FRAME_GRABBING) {
 		interruptible_sleep_on((void *)&frame->wq);
 		if (signal_pending(current))
@@ -2120,7 +2175,7 @@
 	unsigned long start = (unsigned long)adr;
 	unsigned long page, pos;
 
-	if (ibmcam->remove_pending)
+	if (!IBMCAM_IS_OPERATIONAL(ibmcam))
 		return -EFAULT;
 
 	if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
@@ -2169,6 +2224,7 @@
 	RESTRICT_TO_RANGE(init_contrast, 0, 255);
 	RESTRICT_TO_RANGE(init_color, 0, 255);
 	RESTRICT_TO_RANGE(init_hue, 0, 255);
+	RESTRICT_TO_RANGE(hue_correction, 0, 255);
 
 	memset(&ibmcam->vpic, 0, sizeof(ibmcam->vpic));
 	memset(&ibmcam->vpic_old, 0x55, sizeof(ibmcam->vpic_old));
@@ -2200,6 +2256,27 @@
 }
 
 /*
+ * usb_ibmcam_release()
+ *
+ * This code searches the array of preallocated (static) structures
+ * and returns index of the first one that isn't in use. Returns -1
+ * if there are no free structures.
+ *
+ * History:
+ * 1/27/00  Created.
+ */
+static int ibmcam_find_struct(void)
+{
+	int u;
+
+	for (u = 0; u < MAX_IBMCAM; u++) {
+		if (!cams[u].ibmcam_used) /* This one is free */
+			return u;
+	}
+	return -1;
+}
+
+/*
  * usb_ibmcam_probe()
  *
  * This procedure queries device descriptor and accepts the interface
@@ -2207,11 +2284,13 @@
  *
  * History:
  * 1/22/00  Moved camera init code to ibmcam_open()
+ * 1/27/00  Changed to use static structures, added locking.
  */
 static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_ibmcam *ibmcam = NULL;
 	struct usb_interface_descriptor *interface;
+	int devnum;
 
 	if (debug >= 1)
 		printk(KERN_DEBUG "ibmcam_probe(%p,%u.)\n", dev, ifnum);
@@ -2225,6 +2304,8 @@
 	    (dev->descriptor.idProduct != 0x8080))
 		return NULL;
 
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+
 	/* Camera confirmed. We claim only interface 2 (video data) */
 	if (ifnum != 2)
 		return NULL;
@@ -2232,26 +2313,32 @@
 	/* We found an IBM camera */
 	printk(KERN_INFO "IBM USB camera found (interface %u.)\n", ifnum);
 
-	if (debug >= 1)
-		printk(KERN_DEBUG "ibmcam_probe: new ibmcam alloc\n");
-	ibmcam = kmalloc(sizeof(*ibmcam), GFP_KERNEL);
-	if (ibmcam == NULL) {
-		printk(KERN_ERR "couldn't kmalloc ibmcam struct\n");
+	devnum = ibmcam_find_struct();
+	if (devnum == -1) {
+		printk(KERN_INFO "IBM USB camera driver: Too many devices!\n");
 		return NULL;
 	}
-	memset(ibmcam, 0, sizeof(struct usb_ibmcam));
+	ibmcam = &cams[devnum];
+
+	down(&ibmcam->lock);
+	ibmcam->ibmcam_used = 1;	/* In use now */
+	ibmcam->remove_pending = 0;
+	ibmcam->last_error = 0;
 	ibmcam->dev = dev;
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
-	ibmcam->iface = interface->bInterfaceNumber;
+	ibmcam->iface = ifnum;
+	ibmcam->ifaceAltInactive = 0;
+	ibmcam->ifaceAltActive = 1;
 	ibmcam->video_endp = 0x82;
-	init_waitqueue_head (&ibmcam->remove_ok);
 	ibmcam->iso_packet_len = 1014;
+	ibmcam->compress = 0;
+	ibmcam->user=0; 
 
-	memcpy(&ibmcam->vdev, &ibmcam_template, sizeof(ibmcam_template));
 	usb_ibmcam_configure_video(ibmcam);
+	up (&ibmcam->lock);
 
-	init_waitqueue_head(&ibmcam->frame[0].wq);
-	init_waitqueue_head(&ibmcam->frame[1].wq);
+#if IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED
+	MOD_INC_USE_COUNT;
+#endif
 
 	if (video_register_device(&ibmcam->vdev, VFL_TYPE_GRABBER) == -1) {
 		printk(KERN_ERR "video_register_device failed\n");
@@ -2260,14 +2347,27 @@
 	if (debug > 1)
 		printk(KERN_DEBUG "video_register_device() successful\n");
 
-	ibmcam->compress = 0;
-	ibmcam->user=0; 
-	init_MUTEX(&ibmcam->lock);	/* to 1 == available */
-
 	return ibmcam;
 }
 
 /*
+ * usb_ibmcam_release()
+ *
+ * This code does final release of struct usb_ibmcam. This happens
+ * after the device is disconnected -and- all clients closed their files.
+ *
+ * History:
+ * 1/27/00  Created.
+ */
+static void usb_ibmcam_release(struct usb_ibmcam *ibmcam)
+{
+	video_unregister_device(&ibmcam->vdev);
+	if (debug > 0)
+		printk(KERN_DEBUG "usb_ibmcam_release: Video unregistered.\n");
+	ibmcam->ibmcam_used = 0;
+}
+
+/*
  * usb_ibmcam_disconnect()
  *
  * This procedure stops all driver activity, deallocates interface-private
@@ -2278,40 +2378,32 @@
  *
  * History:
  * 1/22/00  Added polling of MOD_IN_USE to delay removal until all users gone.
+ * 1/27/00  Reworked to allow pending disconnects; see ibmcam_close()
  */
 static void usb_ibmcam_disconnect(struct usb_device *dev, void *ptr)
 {
 	static const char proc[] = "usb_ibmcam_disconnect";
 	struct usb_ibmcam *ibmcam = (struct usb_ibmcam *) ptr;
-	wait_queue_head_t wq;	/* Wait here until removal is safe */
 
 	if (debug > 0)
 		printk(KERN_DEBUG "%s(%p,%p.)\n", proc, dev, ptr);
 
-	init_waitqueue_head(&wq);
+	down(&ibmcam->lock);
 	ibmcam->remove_pending = 1; /* Now all ISO data will be ignored */
 
 	/* At this time we ask to cancel outstanding URBs */
 	ibmcam_stop_isoc(ibmcam);
 
-	if (MOD_IN_USE) {
-		printk(KERN_INFO "%s: In use, disconnect pending.\n", proc);
-		while (MOD_IN_USE)
-			interruptible_sleep_on_timeout (&wq, HZ);
-		printk(KERN_INFO "%s: Released, wait.\n", proc);
-//		interruptible_sleep_on_timeout (&wq, HZ*10);
-	}
-	video_unregister_device(&ibmcam->vdev);
-	printk(KERN_INFO "%s: Video dereg'd, wait.\n", proc);
-//	interruptible_sleep_on_timeout (&wq, HZ*10);
-
-	/* Free the memory */
-	if (debug > 0)
-		printk(KERN_DEBUG "%s: freeing ibmcam=%p\n", proc, ibmcam);
-	kfree(ibmcam);
+	ibmcam->dev = NULL;    	    /* USB device is no more */
 
-	printk(KERN_INFO "%s: Memory freed, wait.\n", proc);
-//	interruptible_sleep_on_timeout (&wq, HZ*10);
+#if IBMCAM_LOCKS_DRIVER_WHILE_DEVICE_IS_PLUGGED
+	MOD_DEC_USE_COUNT;
+#endif
+	if (ibmcam->user)
+		printk(KERN_INFO "%s: In use, disconnect pending.\n", proc);
+	else
+		usb_ibmcam_release(ibmcam);
+	up(&ibmcam->lock);
 
 	printk(KERN_INFO "IBM USB camera disconnected.\n");
 }
@@ -2323,8 +2415,30 @@
 	{ NULL, NULL }
 };
 
+/*
+ * usb_ibmcam_init()
+ *
+ * This code is run to initialize the driver.
+ *
+ * History:
+ * 1/27/00  Reworked to use statically allocated usb_ibmcam structures.
+ */
 int usb_ibmcam_init(void)
 {
+	unsigned i, u;
+
+	/* Initialize struct */
+	for (u = 0; u < MAX_IBMCAM; u++) {
+		struct usb_ibmcam *ibmcam = &cams[u];
+		memset (ibmcam, 0, sizeof(struct usb_ibmcam));
+
+		init_waitqueue_head (&ibmcam->remove_ok);
+		for (i=0; i < IBMCAM_NUMFRAMES; i++)
+			init_waitqueue_head(&ibmcam->frame[i].wq);
+		init_MUTEX(&ibmcam->lock);	/* to 1 == available */
+		ibmcam->dev = NULL;
+		memcpy(&ibmcam->vdev, &ibmcam_template, sizeof(ibmcam_template));
+	}
 	return usb_register(&ibmcam_driver);
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/ibmcam.h linux/drivers/usb/ibmcam.h
--- v2.3.42/linux/drivers/usb/ibmcam.h	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/ibmcam.h	Mon Feb  7 19:15:56 2000
@@ -119,6 +119,17 @@
 	interruptible_sleep_on_timeout (&wq, HZ*3); \
 }
 
+/*
+ * This macro checks if ibmcam is still operational. The 'ibmcam'
+ * pointer must be valid, ibmcam->dev must be valid, we are not
+ * removing the device and the device has not erred on us.
+ */
+#define IBMCAM_IS_OPERATIONAL(ibm_cam) (\
+	(ibm_cam != NULL) && \
+	((ibm_cam)->dev != NULL) && \
+	((ibm_cam)->last_error == 0) && \
+	(!(ibm_cam)->remove_pending))
+
 enum {
 	STATE_SCANNING,		/* Scanning for header */
 	STATE_LINES,		/* Parsing lines */
@@ -167,14 +178,17 @@
 	/* Device structure */
 	struct usb_device *dev;
 
-	unsigned char iface;
+	unsigned char iface;                            /* Video interface number */
+	unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */
 
 	struct semaphore lock;
 	int user;		/* user count for exclusive use */
 
+	int ibmcam_used;        /* Is this structure in use? */
 	int initialized;	/* Had we already sent init sequence? */
 	int streaming;		/* Are we streaming Isochronous? */
 	int grabbing;		/* Are we grabbing? */
+	int last_error;		/* What calamity struck us? */
 
 	int compress;		/* Should the next frame be compressed? */
 
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/inode.c linux/drivers/usb/inode.c
--- v2.3.42/linux/drivers/usb/inode.c	Fri Jan 21 18:19:17 2000
+++ linux/drivers/usb/inode.c	Wed Feb  9 11:42:35 2000
@@ -400,21 +400,21 @@
 }
 
 static struct file_operations usbdevfs_root_file_operations = {
-	readdir: usbdevfs_root_readdir
+	readdir: usbdevfs_root_readdir,
 };
 
 static struct inode_operations usbdevfs_root_inode_operations = {
 	default_file_ops: &usbdevfs_root_file_operations,
-	lookup: usbdevfs_root_lookup
+	lookup: usbdevfs_root_lookup,
 };
 
 static struct file_operations usbdevfs_bus_file_operations = {
-	readdir: usbdevfs_bus_readdir
+	readdir: usbdevfs_bus_readdir,
 };
 
 static struct inode_operations usbdevfs_bus_inode_operations = {
 	default_file_ops: &usbdevfs_bus_file_operations,
-	lookup: usbdevfs_bus_lookup
+	lookup: usbdevfs_bus_lookup,
 };
 
 static void usbdevfs_read_inode(struct inode *inode)
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/keybdev.c linux/drivers/usb/keybdev.c
--- v2.3.42/linux/drivers/usb/keybdev.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/keybdev.c	Thu Feb 10 12:28:01 2000
@@ -112,7 +112,7 @@
 #error "Cannot generate rawmode keyboard for your architecture yet."
 #endif
 
-	mark_bh(KEYBOARD_BH);
+	tasklet_schedule(&keyboard_tasklet);
 }
 
 static int keybdev_connect(struct input_handler *handler, struct input_dev *dev)
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- v2.3.42/linux/drivers/usb/ov511.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/ov511.c	Wed Feb  9 11:51:13 2000
@@ -1,6 +1,7 @@
 /*
  * OmniVision OV511 Camera-to-USB Bridge Driver
- * Copyright 1999/2000 Mark W. McClelland
+ * Copyright (c) 1999/2000 Mark W. McClelland
+ * Many improvements by Bret Wallach
  *
  * Based on the Linux CPiA driver.
  * 
@@ -11,7 +12,7 @@
  *    DEBUG - Debugging code.
  *    FIXME - Something that is broken or needs improvement.
  *
- * Version: 1.06
+ * Version: 1.07
  *
  * Please see the file: linux/Documentation/usb/ov511.txt 
  * and the website at:  http://people.delphi.com/mmcclelland/linux/ 
@@ -58,7 +59,7 @@
 #include <linux/wrapper.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-
+#include <linux/time.h>
 #include <asm/io.h>
 
 #include "usb.h"
@@ -70,9 +71,9 @@
 
 /* Video Size 640 x 480 x 3 bytes for RGB */
 #define MAX_FRAME_SIZE (640 * 480 * 3)
+#define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))
 
-// FIXME - Force CIF to make some apps happy for the moment. Should find a 
-//         better way to do this.
+// FIXME - Should find a better way to do this.
 #define DEFAULT_WIDTH 640
 #define DEFAULT_HEIGHT 480
 
@@ -206,7 +207,7 @@
 		0, (__u16)reg, &value, 1, HZ);	
 			
 #if 0
-	PDEBUG("reg write: 0x%02X:0x%02X", reg, value);
+	PDEBUG("reg write: 0x%02X:0x%02X, 0x%x", reg, value, rc);
 #endif
 			
 	return rc;
@@ -261,10 +262,10 @@
 
 		if((rc&2) == 0) /* Ack? */
 			break;
-
+#if 0
 		/* I2C abort */	
 		ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
-
+#endif
 		if (--retries < 0) return -1;
 	}
 
@@ -331,6 +332,58 @@
 	return (value);
 }
 
+
+// This version doesn't always work
+#if 0
+ /* returns: negative is error, pos or zero is data */
+ int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
+ {
+	int rc, value;
+
+	/* Select camera register */
+	rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
+	if (rc < 0) return rc;
+ 
+
+	/* Initiate 2-byte write cycle */
+	rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);
+	if (rc < 0) return rc;
+ 
+
+	/* Initiate 2-byte read cycle */
+	rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
+	if (rc < 0) return rc;
+ 
+ 	value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
+ #if 0
+ 	PDEBUG("i2c read: 0x%02X:0x%02X", reg, value);
+ #endif
+ 		
+ 	return (value);
+ }
+#endif
+
+static int ov511_write_regvals(struct usb_device *dev,
+			       struct ov511_regvals * pRegvals)
+{
+	int ret;
+	while(pRegvals->bus != OV511_DONE_BUS) {
+		if (pRegvals->bus == OV511_REG_BUS) {
+			if ((ret = ov511_reg_write(dev, pRegvals->reg,
+			                           pRegvals->val)) < 0)
+				return ret;
+		} else if (pRegvals->bus == OV511_I2C_BUS) {
+			if ((ret = ov511_i2c_write(dev, pRegvals->reg, 
+			                           pRegvals->val)) < 0)
+				return ret;
+		} else {
+		  err("Bad regval array");
+		}
+		pRegvals++;
+	}
+	return 0;
+}
+
 #if 0
 static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn)
 {
@@ -384,18 +437,6 @@
 }
 #endif
 
-int ov511_i2c_reset(struct usb_device *dev)
-{
-	int rc;
-
-	PDEBUG("Reset 7610");
-	rc = ov511_i2c_write(dev, 0x12, 0x80);
-	if (rc < 0)
-		err("i2c reset: command failed");
-
-	return rc;
-}
-
 int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
 	int rc;
@@ -480,6 +521,21 @@
 static inline int ov7610_set_picture(struct usb_ov511 *ov511,
                                      struct video_picture *p)
 {
+	int ret;
+
+	/* Stop the camera */
+	if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x3d) < 0) {
+		err("reset: command failed");
+		return -EIO;
+	}
+
+	if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_COM_B)) < 0)
+		return -EIO;
+#if 0
+	if(ov511_i2c_write(ov511->dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
+		return -EIO;
+#endif
+
 	if(ov511_i2c_write(ov511->dev, OV7610_REG_SAT, p->colour >> 8) < 0)
 		return -EIO;
 
@@ -489,6 +545,12 @@
 	if(ov511_i2c_write(ov511->dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
 		return -EIO;
 
+	/* Restart the camera */
+	if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x0) < 0) {
+		err("reset: command failed");
+		return -EIO;
+	}
+
 	return 0;
 }
 
@@ -497,6 +559,12 @@
 {
 	int ret;
 
+	/* Stop the camera */
+	if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x3d) < 0) {
+		err("reset: command failed");
+		return -EIO;
+	}
+
 	if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_SAT)) < 0) return -EIO;
 	p->colour = ret << 8;
 
@@ -511,43 +579,71 @@
 	p->depth = 24;
 	p->palette = VIDEO_PALETTE_RGB24;
 
+	/* Restart the camera */
+	if (ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_RESET, 0x0) < 0) {
+		err("reset: command failed");
+		return -EIO;
+	}
+
 	return 0;
 }
 
 static int ov511_mode_init_regs(struct usb_ov511 *ov511,
-				int width, int height, int mode)
+				int width, int height, int mode, int sub_flag)
 {
 	int rc = 0;
 	struct usb_device *dev = ov511->dev;
 
 #if 0
-	PDEBUG("ov511_mode_init_regs(ov511, %d, %d, %d)", width, height, mode);
+	PDEBUG("ov511_mode_init_regs(ov511, %d, %d, %d, %d)",
+	       width, height, mode, sub_flag);
 #endif
-	ov511_set_packet_size(ov511, 0);
 
-	/* Set mode consistent registers */
-	ov511_i2c_write(dev, 0x0f, 0x03);
-	ov511_i2c_write(dev, 0x10, 0xff);
-	ov511_i2c_write(dev, 0x13, 0x01);
-	ov511_i2c_write(dev, 0x16, 0x06);
-	ov511_i2c_write(dev, 0x20, 0x1c);
-	ov511_i2c_write(dev, 0x24, 0x2e); /* 10 */
-	ov511_i2c_write(dev, 0x25, 0x7c); /* 8a */
-	ov511_i2c_write(dev, 0x26, 0x00); /* was 0x70 */
-	ov511_i2c_write(dev, 0x28, 0x24); /* 24 */
-	ov511_i2c_write(dev, 0x2b, 0xac);
-	ov511_i2c_write(dev, 0x2c, 0xfe);
-	ov511_i2c_write(dev, 0x2d, 0x93);
-	ov511_i2c_write(dev, 0x34, 0x8b);
+//	ov511_set_packet_size(ov511, 0);
+	if (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d) < 0) {
+		err("reset: command failed");
+		return -EIO;
+	}
+
+	if (mode == VIDEO_PALETTE_GREY) {
+		ov511_reg_write(dev, 0x16, 0);
+		ov511_i2c_write(dev, 0xe, 0x44);
+		ov511_i2c_write(dev, 0x13, 0x21);
+	} else {
+		ov511_reg_write(dev, 0x16, 1);
+		ov511_i2c_write(dev, 0xe, 0x4);
+		ov511_i2c_write(dev, 0x13, 0x1);
+	}
 
 	if (width == 640 && height == 480) {
-		ov511_reg_write(dev, 0x12, 0x4f);
-		ov511_reg_write(dev, 0x13, 0x3d);
+		if (sub_flag) {
+			ov511_i2c_write(ov511->dev, 0x17, 0x38+(ov511->subx>>2));
+			ov511_i2c_write(ov511->dev, 0x18,
+					0x3a+((ov511->subx+ov511->subw)>>2));
+			ov511_i2c_write(ov511->dev, 0x19, 0x5+(ov511->suby>>1));
+			ov511_i2c_write(ov511->dev, 0x1a,
+					0x5+((ov511->suby+ov511->subh)>>1));
+			ov511_reg_write(ov511->dev, 0x12, (ov511->subw>>3)-1);
+			ov511_reg_write(ov511->dev, 0x13, (ov511->subh>>3)-1);
+			ov511_i2c_write(dev, 0x11, 0x01);
+		} else {
+			ov511_i2c_write(ov511->dev, 0x17, 0x38);
+			ov511_i2c_write(ov511->dev, 0x18, 0x3a + (640>>2));
+			ov511_i2c_write(ov511->dev, 0x19, 0x5);
+			ov511_i2c_write(ov511->dev, 0x1c, + (480>>1));
+			ov511_reg_write(dev, 0x12, 0x4f);
+			ov511_reg_write(dev, 0x13, 0x3d);
+			if (mode == VIDEO_PALETTE_GREY) {
+			  ov511_i2c_write(dev, 0x11, 4); /* check */
+			} else {
+			  ov511_i2c_write(dev, 0x11, 6); /* check */
+			}
+		}
+
 		ov511_reg_write(dev, 0x14, 0x00);
 		ov511_reg_write(dev, 0x15, 0x00);
 		ov511_reg_write(dev, 0x18, 0x03);
 
-		ov511_i2c_write(dev, 0x11, 0x01);
 		ov511_i2c_write(dev, 0x12, 0x24);
 		ov511_i2c_write(dev, 0x14, 0x04);
 		ov511_i2c_write(dev, 0x35, 0x9e);
@@ -558,7 +654,12 @@
 		ov511_reg_write(dev, 0x15, 0x00);
 		ov511_reg_write(dev, 0x18, 0x03);
 
-		ov511_i2c_write(dev, 0x11, 0x00);
+		if (mode == VIDEO_PALETTE_GREY) {
+		  ov511_i2c_write(dev, 0x11, 1); /* check */
+		} else {
+		  ov511_i2c_write(dev, 0x11, 1); /* check */
+		}
+
 		ov511_i2c_write(dev, 0x12, 0x04);
 		ov511_i2c_write(dev, 0x14, 0x24);
 		ov511_i2c_write(dev, 0x35, 0x1e);
@@ -566,7 +667,13 @@
 		err("Unknown mode (%d, %d): %d", width, height, mode);
 		rc = -EINVAL;
 	}
-	ov511_set_packet_size(ov511, 993);
+
+//	ov511_set_packet_size(ov511, 993);
+
+	if (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00) < 0) {
+		PDEBUG("reset: command failed");
+		return -EIO;
+	}
 
 	return rc;
 }
@@ -633,25 +740,20 @@
 #define HDIV 8
 #define WDIV (256/HDIV)
 
-static void ov511_parse_data(unsigned char * pIn0,
-			     unsigned char * pOut0,
-			     int iWidth,
-			     int iSegment)
-			    
+
+static void ov511_parse_data_rgb24(unsigned char * pIn0,
+				   unsigned char * pOut0,
+				   int iOutY,
+				   int iOutUV,
+				   int iHalf,
+				   int iWidth)
+ 			    			    
 {
 #ifndef OV511_DUMPPIX
     int k, l, m;
     unsigned char * pIn;
     unsigned char * pOut, * pOut1;
 
-    int iHalf = (iSegment / (iWidth / 32)) & 1;
-    int iY     = iSegment / (iWidth / WDIV);
-    int jY     = iSegment - iY * (iWidth / WDIV);
-    int iOutY  = (iY*HDIV*iWidth + jY*WDIV) * 3;
-    int iUV    = iSegment / (iWidth / WDIV * 2);
-    int jUV    = iSegment - iUV * (iWidth / WDIV * 2);
-    int iOutUV = (iUV*HDIV*2*iWidth + jUV*WDIV/2) * 3;
-
     /* Just copy the Y's if in the first stripe */
     if (!iHalf) {
 	pIn = pIn0 + 128;
@@ -723,13 +825,49 @@
 #else
 	/* Just dump pix data straight out for debug */
 	int i;
-	pOut0 += iSegment * 384;
+	pOut0 += iSegmentY * 384;
 	for(i=0; i<384; i++) {
 	  *pOut0++ = *pIn0++;
 	}
 #endif
 }
 
+/***************************************************************
+
+For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
+The segments represent 4 squares of 8x8 pixels as
+follows:
+
+  0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+  8  9 ... 15    72  73 ...  79        200 201 ... 207
+       ...              ...                    ...
+ 56 57 ... 63   120 121     127        248 249 ... 255
+
+****************************************************************/ 
+static void ov511_parse_data_grey(unsigned char * pIn0,
+				  unsigned char * pOut0,
+				  int iOutY,
+				  int iWidth)
+			    
+{
+    int k, l, m;
+    unsigned char * pIn;
+    unsigned char * pOut, * pOut1;
+
+    pIn = pIn0;
+    pOut = pOut0 + iOutY;
+    for(k=0; k<4; k++) {
+      pOut1 = pOut;
+      for(l=0; l<8; l++) {
+	for(m=0; m<8; m++) {
+	  *pOut1++ = *pIn++;
+	}
+	pOut1 += iWidth - 8;
+      }
+      pOut += 8;
+    }
+}
+
 static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
 {
 	unsigned char *cdata;
@@ -741,12 +879,13 @@
 		int n = urb->iso_frame_desc[i].actual_length;
 		int st = urb->iso_frame_desc[i].status;
 		urb->iso_frame_desc[i].actual_length = 0;
-		urb->iso_frame_desc[i].status = 0;		
+		urb->iso_frame_desc[i].status = 0;
 		cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 
 		aPackNum[i] = n ? cdata[992] : -1;
 
 		if (!n || ov511->curframe == -1) continue;
+
 		if (st)
 			PDEBUG("data error: [%d] len=%d, status=%d", i, n, st);
 
@@ -757,33 +896,35 @@
 		     cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
 		    (cdata[8] & 8) && (cdata[8] & 0x80)) {
 
+		    struct timeval *ts;
+		    ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE);
+		    do_gettimeofday(ts);
 #if 0
-		    PDEBUG("Found Frame End!, packnum = %d", (int)(cdata[992]));
-		    PDEBUG("Current frame = %d", ov511->curframe);
+		    PDEBUG("Frame End, curframe = %d, packnum=%d, hw=%d, vw=%d",
+			   ov511->curframe, (int)(cdata[992]),
+			   (int)(cdata[9]), (int)(cdata[10]));
 #endif
 
 		    if (frame->scanstate == STATE_LINES) {
 		        int iFrameNext;
+				frame->grabstate = FRAME_DONE;
 		        if (waitqueue_active(&frame->wq)) {
+			  		frame->grabstate = FRAME_DONE;
+			 	 	wake_up_interruptible(&frame->wq);
+				}
+				/* If next frame is ready or grabbing, point to it */
+				iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
+				if (ov511->frame[iFrameNext].grabstate== FRAME_READY ||
+				    ov511->frame[iFrameNext].grabstate== FRAME_GRABBING) {
+				  ov511->curframe = iFrameNext;
+				  ov511->frame[iFrameNext].scanstate = STATE_SCANNING;
+				} else {
 #if 0
-			  PDEBUG("About to wake up waiting processes");
-#endif
-			  frame->grabstate = FRAME_DONE;
-			  wake_up_interruptible(&frame->wq);
-			}
-			/* If next frame is ready or grabbing, point to it */
-			iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
-			if (ov511->frame[iFrameNext].grabstate== FRAME_READY ||
-			    ov511->frame[iFrameNext].grabstate== FRAME_GRABBING) {
-			  ov511->curframe = iFrameNext;
-			  frame->scanstate = STATE_SCANNING;
-			} else {
-#if 0
-			  PDEBUG("Frame not ready? state = %d",
-				 ov511->frame[iFrameNext].grabstate);
+				  PDEBUG("Frame not ready? state = %d",
+					 ov511->frame[iFrameNext].grabstate);
 #endif
-			  ov511->curframe = -1;
-			}
+				  ov511->curframe = -1;
+				}
 		    }
 		}
 
@@ -792,8 +933,8 @@
 			  cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
 			 (cdata[8] & 8)) {
 #if 0
-			PDEBUG("ov511: Found Frame Start!, packnum = %d", (int)(cdata[992]));
-			PDEBUG("ov511: Frame Header Byte = 0x%x", (int)(cdata[8]));
+			PDEBUG("ov511: Found Frame Start!, framenum = %d",
+			       ov511->curframe);
 #endif
 		    frame->scanstate = STATE_LINES;
 			frame->segment = 0;
@@ -808,26 +949,67 @@
 			if (frame->segment) {
 			  pData = ov511->scratch;
 			  iPix = - ov511->scratchlen;
-			  memmove(pData + ov511->scratchlen, cdata, iPix+384);
-		  } else {
+			  memmove(pData + ov511->scratchlen, cdata,
+				  iPix+frame->segsize);
+			} else {
 			  pData = &cdata[iPix = 9];
-		  }
+		 	}
 
 			/* Parse the segments */
-			while(iPix <= 992 - 384 &&
+			while(iPix <= 992 - frame->segsize &&
 			      frame->segment < frame->width * frame->height / 256) {
-			  ov511_parse_data(pData, frame->data,
-					   frame->width,
-					   frame->segment);
+			  int iSegY;
+			  int iSegUV;
+			  int iY, jY, iUV, jUV;
+			  int iOutY, iOutUV;
+			  unsigned char * pOut;
+
+			  iSegY = iSegUV = frame->segment;
+			  pOut = frame->data;
+			  
 			  frame->segment++;
-			  iPix += 384;
+			  iPix += frame->segsize;
+
+			  if (frame->sub_flag) {
+			    int iSeg1;
+			    iSeg1 = iSegY / (ov511->subw / 32);
+			    iSeg1 *= frame->width / 32;
+			    iSegY = iSeg1 + (iSegY % (ov511->subw / 32));
+			    if (iSegY >= frame->width * ov511->subh / 256)
+			      break;
+
+			    iSeg1 = iSegUV / (ov511->subw / 16);
+			    iSeg1 *= frame->width / 16;
+			    iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16));
+
+			    pOut += (ov511->subx +
+				     ov511->suby * frame->width) * frame->depth;
+			  }
+
+			  iY     = iSegY / (frame->width / WDIV);
+			  jY     = iSegY - iY * (frame->width / WDIV);
+			  iOutY  = (iY*HDIV*frame->width + jY*WDIV) * frame->depth;
+			  iUV    = iSegUV / (frame->width / WDIV * 2);
+			  jUV    = iSegUV - iUV * (frame->width / WDIV * 2);
+			  iOutUV = (iUV*HDIV*2*frame->width + jUV*WDIV/2) * frame->depth;
+
+			  if (frame->format == VIDEO_PALETTE_GREY) {
+			    ov511_parse_data_grey(pData, pOut, iOutY, frame->width);
+			  } else if (frame->format == VIDEO_PALETTE_RGB24) {
+			    ov511_parse_data_rgb24(pData, pOut, iOutY, iOutUV, iY & 1,
+						   frame->width);
+			  }
 			  pData = &cdata[iPix];
-		}
+			}
 
 			/* Save extra data for next time */
 			if (frame->segment < frame->width * frame->height / 256) {
-			  memmove(ov511->scratch, pData, 992 - iPix);
 			  ov511->scratchlen = 992 - iPix;
+			  if (ov511->scratchlen < frame->segsize) {
+			    memmove(ov511->scratch, pData, ov511->scratchlen);
+			  } else {
+			    ov511->scratchlen = 0;
+			  }
 			}
 		}
 	}
@@ -845,7 +1027,9 @@
 	int len;
 	struct usb_ov511 *ov511 = urb->context;
 	struct ov511_sbuf *sbuf;
-	int i;
+
+	if (!ov511->dev)
+		return;
 
 	if (!ov511->streaming) {
 		PDEBUG("hmmm... not streaming, but got interrupt\n");
@@ -855,14 +1039,10 @@
 	sbuf = &ov511->sbuf[ov511->cursbuf];
 
 	/* Copy the data received into our scratch buffer */
-	if (ov511->curframe >= 0) {
+	if (ov511->curframe >= 0)
 	  len = ov511_move_data(ov511, urb);
-	}
-
-	for (i = 0; i < FRAMES_PER_DESC; i++) {
-		sbuf->urb->iso_frame_desc[i].status = 0;
-		sbuf->urb->iso_frame_desc[i].actual_length = 0;
-	}
+	else if (waitqueue_active(&ov511->wq))
+	  wake_up_interruptible(&ov511->wq);
 	
 	/* Move to the next sbuf */
 	ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
@@ -872,7 +1052,6 @@
 
 static int ov511_init_isoc(struct usb_ov511 *ov511)
 {
-	struct usb_device *dev = ov511->dev;
 	urb_t *urb;
 	int fx, err;
 	
@@ -891,9 +1070,9 @@
 		return -ENOMEM;
 	}
 	ov511->sbuf[0].urb = urb;
-	urb->dev = dev;
+	urb->dev = ov511->dev;
 	urb->context = ov511;
-	urb->pipe = usb_rcvisocpipe(dev, OV511_ENDPOINT_ADDRESS);
+	urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
 	urb->transfer_flags = USB_ISO_ASAP;
 	urb->transfer_buffer = ov511->sbuf[0].data;
  	urb->complete = ov511_isoc_irq;
@@ -910,9 +1089,9 @@
 		return -ENOMEM;
 	}
 	ov511->sbuf[1].urb = urb;
-	urb->dev = dev;
+	urb->dev = ov511->dev;
 	urb->context = ov511;
-	urb->pipe = usb_rcvisocpipe(dev, OV511_ENDPOINT_ADDRESS);
+	urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
 	urb->transfer_flags = USB_ISO_ASAP;
 	urb->transfer_buffer = ov511->sbuf[1].data;
  	urb->complete = ov511_isoc_irq;
@@ -928,10 +1107,10 @@
 
 	err = usb_submit_urb(ov511->sbuf[0].urb);
 	if (err)
-		err("ov511_init_isoc: usb_run_isoc(0) ret %d", err);
+		err("ov511_init_isoc: usb_submit_urb(0) ret %d", err);
 	err = usb_submit_urb(ov511->sbuf[1].urb);
 	if (err)
-		err("ov511_init_isoc: usb_run_isoc(1) ret %d", err);
+		err("ov511_init_isoc: usb_submit_urb(1) ret %d", err);
 
 	ov511->streaming = 1;
 
@@ -941,27 +1120,37 @@
 
 static void ov511_stop_isoc(struct usb_ov511 *ov511)
 {
-	if (!ov511->streaming)
+	if (!ov511->streaming || !ov511->dev)
 		return;
 
 	ov511_set_packet_size(ov511, 0);
-	
-	/* Unschedule all of the iso td's */
-	usb_unlink_urb(ov511->sbuf[1].urb);
-	usb_unlink_urb(ov511->sbuf[0].urb);
 
 	ov511->streaming = 0;
 
-	/* Delete them all */
-	usb_free_urb(ov511->sbuf[1].urb);
-	usb_free_urb(ov511->sbuf[0].urb);
+	/* Unschedule all of the iso td's */
+	if (ov511->sbuf[1].urb) {
+		ov511->sbuf[1].urb->next = NULL;
+		usb_unlink_urb(ov511->sbuf[1].urb);
+		usb_free_urb(ov511->sbuf[1].urb);
+		ov511->sbuf[1].urb = NULL;
+	}
+	if (ov511->sbuf[0].urb) {
+		ov511->sbuf[0].urb->next = NULL;
+		usb_unlink_urb(ov511->sbuf[0].urb);
+		usb_free_urb(ov511->sbuf[0].urb);
+		ov511->sbuf[0].urb = NULL;
+	}
 }
 
 static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
 {
+#if 1
 	struct ov511_frame *frame;
 	int width, height;
 
+	if (!ov511->dev)
+		return -1;
+
 	/* If we're not grabbing a frame right now and the other frame is */
 	/*  ready to be grabbed into, then use it instead */
 	if (ov511->curframe == -1) {
@@ -988,15 +1177,15 @@
 	if (height > DEFAULT_HEIGHT)
 		height = DEFAULT_HEIGHT;
 	height = (height / 4) * 4;	/* Multiple of 4 */
-	
+
 //	/* We want a fresh frame every 30 we get */
 //	ov511->compress = (ov511->compress + 1) % 30;
 
+#endif
 	return 0;
 }
 
 
-
 /* Video 4 Linux API */
 static int ov511_open(struct video_device *dev, int flags)
 {
@@ -1004,23 +1193,24 @@
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
 
 	PDEBUG("ov511_open");
-	
+
 	down(&ov511->lock);
 	if (ov511->user)
 		goto out_unlock;
-		
+
 	ov511->frame[0].grabstate = FRAME_UNUSED;
 	ov511->frame[1].grabstate = FRAME_UNUSED;
 
 	err = -ENOMEM;
-	
-	/* Allocate memory for the frame buffers */				
-	ov511->fbuf = rvmalloc(2 * MAX_FRAME_SIZE);
+
+	/* Allocate memory for the frame buffers */
+	ov511->fbuf = rvmalloc(2 * MAX_DATA_SIZE);
 	if (!ov511->fbuf)
 		goto open_err_ret;
 
 	ov511->frame[0].data = ov511->fbuf;
-	ov511->frame[1].data = ov511->fbuf + MAX_FRAME_SIZE;
+	ov511->frame[1].data = ov511->fbuf + MAX_DATA_SIZE;
+	ov511->sub_flag = 0;
 
 	PDEBUG("frame [0] @ %p", ov511->frame[0].data);
 	PDEBUG("frame [1] @ %p", ov511->frame[1].data);
@@ -1051,7 +1241,7 @@
 open_err_on1:
 	kfree (ov511->sbuf[0].data);
 open_err_on0:
-	rvfree(ov511->fbuf, 2 * MAX_FRAME_SIZE);
+	rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE);
 open_err_ret:
 	return err;
 out_unlock:
@@ -1073,12 +1263,17 @@
 
 	ov511_stop_isoc(ov511);
 
-	rvfree(ov511->fbuf, 2 * MAX_FRAME_SIZE);
+	rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE);
 
 	kfree(ov511->sbuf[1].data);
 	kfree(ov511->sbuf[0].data);
 
 	up(&ov511->lock);
+
+	if (!ov511->dev) {
+		video_unregister_device(&ov511->vdev);
+		kfree(ov511);
+	}
 }
 
 static int ov511_init_done(struct video_device *dev)
@@ -1091,13 +1286,16 @@
 	return -EINVAL;
 }
 
-// FIXME - Needs much work!!!
 static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
 #if 0	
 	PDEBUG("IOCtl: 0x%X", cmd);
 #endif	
+
+	if (!ov511->dev)
+		return -EIO;	
+
 	switch (cmd) {
 		case VIDIOCGCAP:
 		{
@@ -1109,8 +1307,8 @@
 			b.audios = 0;
 			b.maxwidth = DEFAULT_WIDTH;
 			b.maxheight = DEFAULT_HEIGHT;
-			b.minwidth = 8;
-			b.minheight = 4;
+			b.minwidth = 32;
+			b.minheight = 16;
 
 			if (copy_to_user(arg, &b, sizeof(b)))
 				return -EFAULT;
@@ -1173,6 +1371,42 @@
 
 			return 0;
 		}
+		case VIDIOCGCAPTURE:
+		{
+			int vf;
+			if (copy_from_user(&vf, arg, sizeof(vf)))
+				return -EFAULT;
+			ov511->sub_flag = vf;
+			return 0;
+		}
+		case VIDIOCSCAPTURE:
+		{
+			struct video_capture vc;
+
+			if (copy_from_user(&vc, arg, sizeof(vc)))
+				return -EFAULT;
+			if (vc.flags)
+				return -EINVAL;
+			if (vc.decimation)
+				return -EINVAL;
+			vc.x /= 4;
+			vc.x *= 4;
+			vc.y /= 2;
+			vc.y *= 2;
+			vc.width /= 32;
+			vc.width *= 32;
+			if (vc.width == 0) vc.width = 32;
+			vc.height /= 16;
+			vc.height *= 16;
+			if (vc.height == 0) vc.height = 16;
+
+			ov511->subx = vc.x;
+			ov511->suby = vc.y;
+			ov511->subw = vc.width;
+			ov511->subh = vc.height;
+
+			return 0;
+		}
 		case VIDIOCSWIN:
 		{
 			struct video_window vw;
@@ -1213,10 +1447,10 @@
 			struct video_mbuf vm;
 
 			memset(&vm, 0, sizeof(vm));
-			vm.size = MAX_FRAME_SIZE * 2;
+			vm.size = 2 * MAX_DATA_SIZE;
 			vm.frames = 2;
 			vm.offsets[0] = 0;
-			vm.offsets[1] = MAX_FRAME_SIZE;
+			vm.offsets[1] = MAX_FRAME_SIZE + sizeof (struct timeval);
 
 			if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
 				return -EFAULT;
@@ -1236,7 +1470,8 @@
 				vm.frame, vm.width, vm.height, vm.format);
 #endif
 
-			if (vm.format != VIDEO_PALETTE_RGB24)
+			if (vm.format != VIDEO_PALETTE_RGB24 &&
+			    vm.format != VIDEO_PALETTE_GREY)
 				return -EINVAL;
 
 			if ((vm.frame != 0) && (vm.frame != 1))
@@ -1247,18 +1482,27 @@
 
 			/* Don't compress if the size changed */
 			if ((ov511->frame[vm.frame].width != vm.width) ||
-			    (ov511->frame[vm.frame].height != vm.height)) {
-				ov511->compress = 0;
+			    (ov511->frame[vm.frame].height != vm.height) ||
+			    (ov511->frame[vm.frame].format != vm.format) ||
+			    (ov511->frame[vm.frame].sub_flag !=
+			     ov511->sub_flag)) {
+				/* If we're collecting previous frame wait
+				   before changing modes */
+				interruptible_sleep_on(&ov511->wq);
+				if (signal_pending(current)) return -EINTR;
 				ov511_mode_init_regs(ov511,
-						     vm.width, vm.height, 0);
-#if 0
-				PDEBUG("ov511: Setting frame %d to (%d, %d) : %d",
-				       vm.frame, vm.width, vm.height, 0);
-#endif
+						     vm.width, vm.height,
+						     vm.format, ov511->sub_flag);
 			}
 
 			ov511->frame[vm.frame].width = vm.width;
 			ov511->frame[vm.frame].height = vm.height;
+			ov511->frame[vm.frame].format = vm.format;
+			ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
+			ov511->frame[vm.frame].segsize =
+			  vm.format == VIDEO_PALETTE_RGB24 ? 384 : 256;
+			ov511->frame[vm.frame].depth =
+			  vm.format == VIDEO_PALETTE_RGB24 ? 3 : 1;
 
 			/* Mark it as ready */
 			ov511->frame[vm.frame].grabstate = FRAME_READY;
@@ -1273,7 +1517,8 @@
 				return -EFAULT;
 
 #if 0
-			PDEBUG("syncing to frame %d", frame);
+			PDEBUG("syncing to frame %d, grabstate = %d", frame,
+			       ov511->frame[frame].grabstate);
 #endif
 			switch (ov511->frame[frame].grabstate) {
 				case FRAME_UNUSED:
@@ -1282,6 +1527,9 @@
 				case FRAME_GRABBING:
 				case FRAME_ERROR:
 redo:
+				if (!ov511->dev)
+					return -EIO;
+
 				do {
 #if 0
 					init_waitqueue_head(&ov511->frame[frame].wq);
@@ -1351,6 +1599,9 @@
 	if (!dev || !buf)
 		return -EFAULT;
 
+	if (!ov511->dev)
+		return -EIO;
+
 	/* See if a frame is completed, then use it. */
 	if (ov511->frame[0].grabstate >= FRAME_DONE)	/* _DONE or _ERROR */
 		frmx = 0;
@@ -1376,6 +1627,9 @@
 	frame = &ov511->frame[frmx];
 
 restart:
+	if (!ov511->dev)
+		return -EIO;
+
 	while (frame->grabstate == FRAME_GRABBING) {
 		interruptible_sleep_on(&ov511->frame[frmx].wq);
 		if (signal_pending(current))
@@ -1422,9 +1676,12 @@
 	unsigned long start = (unsigned long)adr;
 	unsigned long page, pos;
 
+	if (!ov511->dev)
+		return -EIO;
+
 	PDEBUG("mmap: %ld (%lX) bytes", size, size);
 
-	if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+	if (size > (((2 * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
 		return -EINVAL;
 
 	pos = (unsigned long)ov511->fbuf;
@@ -1444,11 +1701,10 @@
 	return 0;
 }
 
-// FIXME - needs V4L ID to be assigned
 static struct video_device ov511_template = {
 	"OV511 USB Camera",
 	VID_TYPE_CAPTURE,
-	VID_HARDWARE_CPIA,  /* FIXME */
+	VID_HARDWARE_OV511,
 	ov511_open,
 	ov511_close,
 	ov511_read,
@@ -1471,25 +1727,17 @@
 	if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
 	                        OV7610_I2C_READ_ID) < 0)
 		return -1;
-	
-	/* Reset the camera chip */
-	if (ov511_i2c_reset(dev) < 0)
-		return -1;
 
-#if 0
-	if(usb_ov511_reg_write(dev, OV511_REG_I2C_CLOCK_PRESCALER,
-	                            OV511_I2C_CLOCK_PRESCALER))
-		return -1;
-#endif
-	
 	if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
 		return -1;
 	
+	if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
+	schedule_timeout (1 + 150 * HZ / 1000);
+
 	/* Dummy read to sync I2C */
 	if(ov511_i2c_read(dev, 0x00) < 0)
 		return -1;
-	
-
+ 
 	if((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) != 0x7F) ||
 	   (ov511_i2c_read(dev, OV7610_REG_ID_LOW) != 0xA2)) {
 		err("Failed to read OV7610 ID. You might not have an OV7610,");
@@ -1504,6 +1752,74 @@
 static int ov511_configure(struct usb_ov511 *ov511)
 {
 	struct usb_device *dev = ov511->dev;
+	int rc;
+
+	static struct ov511_regvals aRegvalsInit[] =
+	{{OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x7f},
+	 {OV511_REG_BUS,  OV511_REG_SYSTEM_INIT, 0x01},
+	 {OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x7f},
+	 {OV511_REG_BUS,  OV511_REG_SYSTEM_INIT, 0x01},
+	 {OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x3f},
+	 {OV511_REG_BUS,  OV511_REG_SYSTEM_INIT, 0x01},
+	 {OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x3d},
+	 {OV511_DONE_BUS, 0x0, 0x00},
+	};
+	static struct ov511_regvals aRegvalsNorm[] =
+	{{OV511_REG_BUS, 0x20, 1},
+#if 1
+	 {OV511_REG_BUS, 0x52, 0x02},
+	 {OV511_REG_BUS, 0x52, 0x00},
+	 {OV511_REG_BUS, 0x31, 0x1f}, /* 0f */
+	 {OV511_REG_BUS, 0x70, 0x3f},
+	 {OV511_REG_BUS, 0x71, 0x3f},
+	 {OV511_REG_BUS, 0x72, 0x01},
+	 {OV511_REG_BUS, 0x73, 0x01},
+	 {OV511_REG_BUS, 0x74, 0x01},
+	 {OV511_REG_BUS, 0x75, 0x01},
+	 {OV511_REG_BUS, 0x76, 0x01},
+	 {OV511_REG_BUS, 0x77, 0x01},
+	 {OV511_REG_BUS, 0x78, 0x06},
+	 {OV511_REG_BUS, 0x79, 0x03},
+
+
+	 {OV511_I2C_BUS, 0x10, 0xff},
+	 {OV511_I2C_BUS, 0x16, 0x06},
+	 {OV511_I2C_BUS, 0x28, 0x24}, /* 24 */
+	 {OV511_I2C_BUS, 0x2b, 0xac},
+	 {OV511_I2C_BUS, 0x5, 0x00},
+	 {OV511_I2C_BUS, 0x6, 0x00},
+#if 0
+#endif
+	 {OV511_I2C_BUS, 0x12, 0x00},
+	 {OV511_I2C_BUS, 0x13, 0x00},
+	 {OV511_I2C_BUS, 0x38, 0x81},
+	 {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */
+	 {OV511_I2C_BUS, 0x05, 0x00},
+	 {OV511_I2C_BUS, 0x0f, 0x05},
+	 {OV511_I2C_BUS, 0x15, 0x01},
+	 {OV511_I2C_BUS, 0x20, 0x1c},
+	 {OV511_I2C_BUS, 0x23, 0x2a},
+	 {OV511_I2C_BUS, 0x24, 0x10},
+	 {OV511_I2C_BUS, 0x25, 0x8a},
+	 {OV511_I2C_BUS, 0x26, 0x90},
+	 {OV511_I2C_BUS, 0x27, 0xc2},
+	 {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */
+	 {OV511_I2C_BUS, 0x2a, 0x04},
+	 {OV511_I2C_BUS, 0x2c, 0xfe},
+	 {OV511_I2C_BUS, 0x2d, 0x93}, /* d7 */
+	 {OV511_I2C_BUS, 0x30, 0x71},
+	 {OV511_I2C_BUS, 0x31, 0x60},
+	 {OV511_I2C_BUS, 0x32, 0x26},
+	 {OV511_I2C_BUS, 0x33, 0x20},
+	 {OV511_I2C_BUS, 0x34, 0x48},
+	 {OV511_I2C_BUS, 0x12, 0x24},
+	 {OV511_I2C_BUS, 0x13, 0x01},
+	 {OV511_I2C_BUS, 0x11, 0x01},
+	 {OV511_I2C_BUS, 0x0c, 0x24},
+	 {OV511_I2C_BUS, 0x0d, 0x24},
+#endif
+	 {OV511_DONE_BUS, 0x0, 0x00},
+	};
 
 	/* Set altsetting 0 */
 	if (usb_set_interface(dev, ov511->iface, 0) < 0) {
@@ -1515,25 +1831,15 @@
 
 	init_waitqueue_head(&ov511->frame[0].wq);
 	init_waitqueue_head(&ov511->frame[1].wq);
+	init_waitqueue_head(&ov511->wq);
 
 	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) {
 		err("video_register_device failed");
 		return -EBUSY;
 	}
 
-	/* Reset in case driver was unloaded and reloaded without unplug */
-	if (ov511_reset(dev, OV511_RESET_ALL) < 0)
-		goto error;
-
-	/* Initialize system */
-	if (ov511_reg_write(dev, OV511_REG_SYSTEM_INIT, 0x01) < 0) {
-		err("enable system: command failed");
-		goto error;
-	}
-
-	/* This seems to be necessary */
-	if (ov511_reset(dev, OV511_RESET_ALL) < 0)
-		goto error;
+	if ((rc = ov511_write_regvals(dev, aRegvalsInit)))
+		return rc;
 
 	if(ov7610_configure(dev) < 0) {
 		err("failed to configure OV7610");
@@ -1558,7 +1864,10 @@
 	ov511->frame[1].bytes_read = 0;
 
 	/* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */
-	ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0);
+	if ((rc = ov511_write_regvals(dev, aRegvalsNorm))) return rc;
+	if ((rc = ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+				       VIDEO_PALETTE_RGB24, 0)) < 0) return rc;
+
 
 	return 0;
 	
@@ -1624,6 +1933,9 @@
 	case 3:
 		printk("ov511: Camera is a D-Link DSB-C300\n");
 		break;
+	case 5:
+		printk("ov511: Camera is a Puretek PT-6007\n");
+		break;
 	case 21:
 		printk("ov511: Camera is a Creative Labs WebCam 3\n");
 		break;
@@ -1661,13 +1973,49 @@
 
 	struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
 
-	video_unregister_device(&ov511->vdev);
+//	video_unregister_device(&ov511->vdev);
+
+	/* We don't want people trying to open up the device */
+	if (!ov511->user)
+		video_unregister_device(&ov511->vdev);
 
 	usb_driver_release_interface(&ov511_driver,
 		&ov511->dev->actconfig->interface[ov511->iface]);
 
+	ov511->dev = NULL;
+	ov511->frame[0].grabstate = FRAME_ERROR;
+	ov511->frame[1].grabstate = FRAME_ERROR;
+	ov511->curframe = -1;
+
+	/* This will cause the process to request another frame */
+	if (waitqueue_active(&ov511->frame[0].wq))
+		wake_up_interruptible(&ov511->frame[0].wq);
+	if (waitqueue_active(&ov511->frame[1].wq))
+		wake_up_interruptible(&ov511->frame[1].wq);
+	if (waitqueue_active(&ov511->wq))
+		wake_up_interruptible(&ov511->wq);
+
+	ov511->streaming = 0;
+
+	/* Unschedule all of the iso td's */
+	if (ov511->sbuf[1].urb) {
+		ov511->sbuf[1].urb->next = NULL;
+		usb_unlink_urb(ov511->sbuf[1].urb);
+		usb_free_urb(ov511->sbuf[1].urb);
+		ov511->sbuf[1].urb = NULL;
+	}
+	if (ov511->sbuf[0].urb) {
+		ov511->sbuf[0].urb->next = NULL;
+		usb_unlink_urb(ov511->sbuf[0].urb);
+		usb_free_urb(ov511->sbuf[0].urb);
+		ov511->sbuf[0].urb = NULL;
+	}	
+
 	/* Free the memory */
-	kfree(ov511); ov511 = NULL;
+	if (!ov511->user) {
+		kfree(ov511);
+		ov511 = NULL;
+	}
 }
 
 static struct usb_driver ov511_driver = {
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/ov511.h linux/drivers/usb/ov511.h
--- v2.3.42/linux/drivers/usb/ov511.h	Fri Jan 21 18:19:17 2000
+++ linux/drivers/usb/ov511.h	Wed Feb  9 11:51:13 2000
@@ -166,7 +166,9 @@
 
 /* Prototypes */
 int usb_ov511_reg_read(struct usb_device *dev, unsigned char reg);
-int usb_ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char value);
+int usb_ov511_reg_write(struct usb_device *dev,
+                        unsigned char reg,
+                        unsigned char value);
 
 
 enum {
@@ -175,10 +177,6 @@
 	STATE_LINES,		/* Parsing lines */
 };
 
-struct ov511_frame_header {
-	// FIXME - nothing here yet
-};
-
 struct usb_device;
 
 struct ov511_sbuf {
@@ -194,17 +192,30 @@
 	FRAME_ERROR,		/* Something bad happened while processing */
 };
 
+struct ov511_regvals {
+	enum {
+	  OV511_DONE_BUS,
+	  OV511_REG_BUS,
+	  OV511_I2C_BUS,
+	} bus;
+	unsigned char reg;
+	unsigned char val;
+};
+
 struct ov511_frame {
 	char *data;		/* Frame buffer */
 
-	struct ov511_frame_header header;	/* Header from stream */
-
+	int depth;		/* Bytes per pixel */
 	int width;		/* Width application is expecting */
 	int height;		/* Height */
 
 	int hdrwidth;		/* Width the frame actually is */
 	int hdrheight;		/* Height */
 
+	int sub_flag;		/* Sub-capture mode for this frame? */
+	int format;		/* Format for this frame */
+	int segsize;		/* How big is each segment from the camera? */
+
 	volatile int grabstate;	/* State of grabbing */
 	int scanstate;		/* State of scanning */
 
@@ -241,6 +252,12 @@
 
 	char *fbuf;			/* Videodev buffer area */
 
+	int sub_flag;		/* Pix Array subcapture on flag */
+	int subx;		/* Pix Array subcapture x offset */
+	int suby;		/* Pix Array subcapture y offset */
+	int subw;		/* Pix Array subcapture width */
+	int subh;		/* Pix Array subcapture height */
+
 	int curframe;		/* Current receiving sbuf */
 	struct ov511_frame frame[OV511_NUMFRAMES];	
 
@@ -250,6 +267,8 @@
 	/* Scratch space from the Isochronous pipe */
 	unsigned char scratch[SCRATCH_BUF_SIZE];
 	int scratchlen;
+
+	wait_queue_head_t wq;	/* Processes waiting */
 };
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.42/linux/drivers/usb/printer.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/printer.c	Wed Feb  9 15:20:13 2000
@@ -206,7 +206,6 @@
 
 static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	struct usblp *usblp = file->private_data;
 	int retval, timeout, writecount = 0;
 
@@ -267,7 +266,6 @@
 static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct usblp *usblp = file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
 
 	if (!usblp->bidir)
 		return -EINVAL;
@@ -423,7 +421,7 @@
 	write:		usblp_write,
 	open:		usblp_open,
 	release:	usblp_release,
-	poll:		usblp_poll
+	poll:		usblp_poll,
 };
 
 static struct usb_driver usblp_driver = {
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c
--- v2.3.42/linux/drivers/usb/scanner.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/scanner.c	Wed Feb  9 11:42:35 2000
@@ -1,7 +1,7 @@
 /* -*- linux-c -*- */
 
 /* 
- * Driver for USB Scanners (linux-2.3.41)
+ * Driver for USB Scanners (linux-2.3.42)
  *
  * Copyright (C) 1999, 2000 David E. Nelson
  *
@@ -85,7 +85,7 @@
  *    - Added the HP 5200C USB Vendor/Product ID's.
  *
  *
- *  0.3.4
+ *  0.3.4  1/23/2000
  *
  *    - Added Greg K-H's <greg@kroah.com> patch for better handling of 
  *      Product/Vendor detection.
@@ -106,14 +106,34 @@
  *    - Added some Mustek ID's. Thanks to Gernot Hoyler 
  *      <Dr.Hoyler@t-online.de>.
  *    - Modified the usb_string() reporting.  See kfree() comment above.
- *    - Added Umax Astra 2000U. Thanks to Doug Alcorn.
+ *    - Added Umax Astra 2000U. Thanks to Doug Alcorn <doug@lathi.net>.
  *    - Updated the printk()'s to use the info/warn/dbg macros.
- *    - Updated usb_bulk_msg() argument types to correct gcc warnings.
+ *    - Updated usb_bulk_msg() argument types to fix gcc warnings.
+ *
+ *
+ *  0.4  2/4/2000
+ *
+ *    - Removed usb_string() from probe_scanner since the core now does a
+ *      good job of reporting what was connnected.  
+ *    - Finally, simultaneous multiple device attachment!
+ *    - Fixed some potential memory freeing issues should memory allocation
+ *      fail in probe_scanner();
+ *    - Some fixes to disconnect_scanner().
+ *    - Added interrupt endpoint support.
+ *    - Added Agfa SnapScan Touch. Thanks to Jan Van den Bergh
+ *      <jan.vandenbergh@cs.kuleuven.ac.be>.
+ *    - Added Umax 1220U ID's. Thanks to Maciek Klimkowski
+ *      <mac@nexus.carleton.ca>.
+ *    - Fixed bug in write_scanner(). The buffer was not being properly
+ *      updated for writes larger than OBUF_SIZE. Thanks to Henrik 
+ *      Johansson <henrikjo@post.utfors.se> for identifying it.
+ *    - Added Microtek X6 ID's. Thanks to Oliver Neukum
+ *      <Oliver.Neukum@lrz.uni-muenchen.de>.
  *
  *
  *  TODO
  *
- *    - Simultaneous multiple device attachment
+ *    - Select/poll methods
  *
  *
  *  Thanks to:
@@ -131,31 +151,68 @@
  *            300 dpi scan of the entire bed
  *      24 Bit Color ~ 70 secs - 3.6 Mbit/sec
  *       8 Bit Gray  ~ 17 secs - 4.2 Mbit/sec
- * */
+ */
 
 #include "scanner.h"
 
+
+static void
+irq_scanner(struct urb *urb)
+{
+
+/*
+ * For the meantime, this is just a placeholder until I figure out what
+ * all I want to do with it.
+ */
+
+	struct scn_usb_data *scn = urb->context;
+	unsigned char *data = &scn->button;
+
+	if (urb->status) {
+		return;
+	}
+
+	dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
+	return;
+}
+
+
 static int
 open_scanner(struct inode * inode, struct file * file)
 {
-	struct hpscan_usb_data *hps = &hpscan;
+	struct scn_usb_data *scn;
 	struct usb_device *dev;
 
-	dev = hps->hpscan_dev;
+	kdev_t scn_minor;
+
+	scn_minor = USB_SCN_MINOR(inode);
+
+	dbg("open_scanner: scn_minor:%d", scn_minor);
+
+	if (!p_scn_table[scn_minor]) {
+		err("open_scanner(%d): invalid scn_minor", scn_minor);
+		return -ENOIOCTLCMD;
+	}
+
+	scn = p_scn_table[scn_minor];
+
+	dev = scn->scn_dev;
 
 	if (!dev) {
 		return -ENODEV;
 	}
 
-	if (!hps->present) {
+	if (!scn->present) {
 		return -ENODEV;
 	}
 
-	if (hps->isopen) {
+	if (scn->isopen) {
 		return -EBUSY;
 	}
 
-	hps->isopen = 1;
+	scn->isopen = 1;
+
+	file->private_data = scn; /* Used by the read and write metheds */
 
 	MOD_INC_USE_COUNT;
 
@@ -165,9 +222,24 @@
 static int
 close_scanner(struct inode * inode, struct file * file)
 {
-	struct hpscan_usb_data *hps = &hpscan;
+	struct scn_usb_data *scn;
 
-	hps->isopen = 0;
+	kdev_t scn_minor;
+
+	scn_minor = USB_SCN_MINOR (inode);
+
+	dbg("close_scanner: scn_minor:%d", scn_minor);
+
+	if (!p_scn_table[scn_minor]) {
+		err("close_scanner(%d): invalid scn_minor", scn_minor);
+		return -ENOIOCTLCMD;
+	}
+
+	scn = p_scn_table[scn_minor];
+
+	scn->isopen = 0;
+
+	file->private_data = NULL;
 
 	MOD_DEC_USE_COUNT;
 
@@ -178,7 +250,7 @@
 write_scanner(struct file * file, const char * buffer,
               size_t count, loff_t *ppos)
 {
-	struct hpscan_usb_data *hps = &hpscan;
+	struct scn_usb_data *scn;
 	struct usb_device *dev;
 	
 	ssize_t bytes_written = 0;
@@ -188,9 +260,13 @@
 	int partial;
 	int result = 0;
 	
-	char *obuf = hps->obuf;
+	char *obuf;
+
+	scn = file->private_data;
+
+	obuf = scn->obuf;
 
-	dev = hps->hpscan_dev;
+	dev = scn->scn_dev;
 
 	while (count > 0) {
 
@@ -201,20 +277,20 @@
 
 		copy_size = (count > OBUF_SIZE) ? OBUF_SIZE : count;
 		
-		if (copy_from_user(hps->obuf, buffer, copy_size)) {
+		if (copy_from_user(scn->obuf, buffer, copy_size)) {
 			ret = -EFAULT;
 			break;
 		}
 
-		result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, hps->bulk_out_ep), obuf, copy_size, &partial, 60*HZ);
-		dbg("write stats: result:%d copy_size:%d partial:%d", result, copy_size, partial);
+		result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), obuf, copy_size, &partial, 60*HZ);
+		dbg("write stats(%d): result:%d copy_size:%d partial:%d", scn->scn_minor, result, copy_size, partial);
 
 		if (result == USB_ST_TIMEOUT) {	/* NAK -- shouldn't happen */
 			warn("write_scanner: NAK recieved.");
 			ret = -ETIME;
 			break;
 		} else if (result < 0) { /* We should not get any I/O errors */
-			warn("write_scanner: funky result: %d. Please notify the maintainer.", result);
+			warn("write_scanner(%d): funky result: %d. Please notify the maintainer.", scn->scn_minor, result);
 			ret = -EIO;
 			break;
 		} 
@@ -223,7 +299,7 @@
 		if (partial) {
 			unsigned char cnt, cnt_max;
 			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump: ");
+			printk(KERN_DEBUG "dump(%d): ", scn->scn_minor);
 			for (cnt=0; cnt < cnt_max; cnt++) {
 				printk("%X ", obuf[cnt]);
 			}
@@ -236,7 +312,7 @@
 		}
 
 		if (partial) { /* Data written */
-			obuf += partial;
+			buffer += partial;
 			count -= partial;
 			bytes_written += partial;
 		} else { /* No data written */
@@ -245,7 +321,7 @@
 			break;
 		}
 	}
-	mdelay(5);
+	mdelay(5);		/* This seems to help with SANE queries */
 	return ret ? ret : bytes_written;
 }
 
@@ -253,7 +329,7 @@
 read_scanner(struct file * file, char * buffer,
              size_t count, loff_t *ppos)
 {
-	struct hpscan_usb_data *hps = &hpscan;
+	struct scn_usb_data *scn;
 	struct usb_device *dev;
 
 	ssize_t read_count, ret = 0;
@@ -262,9 +338,13 @@
 	int this_read;
 	int result;
 
-	char *ibuf = hps->ibuf;
+	char *ibuf;
 
-	dev = hps->hpscan_dev;
+	scn = file->private_data;
+
+	ibuf = scn->ibuf;
+
+	dev = scn->scn_dev;
 
 	read_count = 0;
 
@@ -276,15 +356,15 @@
 
 		this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count;
 		
-		result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, hps->bulk_in_ep), ibuf, this_read, &partial, 60*HZ);
-		dbg("read stats: result:%d this_read:%d partial:%d", result, this_read, partial);
+		result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, 60*HZ);
+		dbg("read stats(%d): result:%d this_read:%d partial:%d", scn->scn_minor, result, this_read, partial);
 
 		if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
-			warn("read_scanner: NAK received");
+			warn("read_scanner(%d): NAK received", scn->scn_minor);
 			ret = -ETIME;
 			break;
 		} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
-			warn("read_scanner: funky result: %d. Please notify the maintainer.", (int)result);
+			warn("read_scanner(%d): funky result:%d. Please notify the maintainer.", scn->scn_minor, (int)result);
 			ret = -EIO;
 			break;
 		}
@@ -293,7 +373,7 @@
 		if (partial) {
 			unsigned char cnt, cnt_max;
 			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump: ");
+			printk(KERN_DEBUG "dump(%d): ", scn->scn_minor);
 			for (cnt=0; cnt < cnt_max; cnt++) {
 				printk("%X ", ibuf[cnt]);
 			}
@@ -325,21 +405,24 @@
 static void *
 probe_scanner(struct usb_device *dev, unsigned int ifnum)
 {
-	struct hpscan_usb_data *hps = &hpscan;
+	struct scn_usb_data *scn;
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	
 	int ep_cnt;
 
+	kdev_t scn_minor;
+
 	char valid_device = 0;
 	char have_bulk_in, have_bulk_out, have_intr;
 
-	hps->present = 0;
-
 	if (vendor != -1 && product != -1) {
 		info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product);
 	}
 
+	dbg("probe_scanner: USB dev address:%p", dev);
+	dbg("probe_scanner: ifnum:%u", ifnum);
+
 /*
  * 1. Check Vendor/Product
  * 2. Determine/Assign Bulk Endpoints
@@ -375,16 +458,20 @@
 			}
 		}
 		
-		if (dev->descriptor.idVendor == 0x06bd &&  /* AGFA */
-		    dev->descriptor.idProduct == 0x0001) { /* SnapScan 1212U */
-			valid_device = 1;
-			break;
+		if (dev->descriptor.idVendor == 0x06bd) {	   /* Agfa */
+		    	if (dev->descriptor.idProduct == 0x0001 || /* SnapScan 1212U */
+		    	    dev->descriptor.idProduct == 0x0100) { /* SnapScan Touch */
+				valid_device = 1;
+				break;
+			}
 		}
 		
-		if (dev->descriptor.idVendor == 0x1606 &&  /* Umax */
-		    dev->descriptor.idProduct == 0x0030) { /* Astra 2000U */
-			valid_device = 1;
-			break;
+		if (dev->descriptor.idVendor == 0x1606) {          /* Umax */
+			if (dev->descriptor.idProduct == 0x0010 || /* Astra 1220U */
+			    dev->descriptor.idProduct == 0x0030) { /* Astra 2000U */
+				valid_device = 1;
+				break;
+			}
 		}
 		
 		if (dev->descriptor.idVendor == 0x04b8)	{          /* Seiko/Epson Corp. */
@@ -402,15 +489,24 @@
 			}
 		}
 
+		if (dev->descriptor.idVendor == 0x05da) {          /* Microtek */
+			if (dev->descriptor.idProduct == 0x0099) { /* X6 */
+				valid_device = 1;
+				break;
+			}
+		}
+
 		if (dev->descriptor.idVendor == vendor &&   /* User specified */
 		    dev->descriptor.idProduct == product) { /* User specified */
 			valid_device = 1;
 			break;
 		}
+
+
 	} while (0);
 
-	if (!valid_device)
-		return NULL;
+	if (!valid_device)	
+		return NULL;	/* We didn't find anything pleasing */
 
 
 /*
@@ -419,17 +515,17 @@
  */
 
 	if (dev->descriptor.bNumConfigurations != 1) {
-		info("probe_scanner: Only one configuration is supported.");
+		info("probe_scanner: Only one device configuration is supported.");
 		return NULL;
 	}
 
 	if (dev->config[0].bNumInterfaces != 1) {
-		info("probe_scanner: Only one interface is supported.");
+		info("probe_scanner: Only one device interface is supported.");
 		return NULL;
 	}
 
-	interface = dev->config[0].interface[0].altsetting;
-	endpoint = interface[0].endpoint;
+	interface = dev->config[0].interface[ifnum].altsetting;
+	endpoint = interface[ifnum].endpoint;
 
 /* 
  * Start checking for two bulk endpoints OR two bulk endpoints *and* one
@@ -437,8 +533,7 @@
  * setup the handler. FIXME: This is a future enhancement...
  */
 
-
-	dbg("probe_scanner: Number of Endpoints: %d", (int) interface->bNumEndpoints);
+	dbg("probe_scanner: Number of Endpoints:%d", (int) interface->bNumEndpoints);
 
 	if ((interface->bNumEndpoints != 2) && (interface->bNumEndpoints != 3)) {
 		info("probe_scanner: Only two or three endpoints supported.");
@@ -450,32 +545,35 @@
 	while (ep_cnt < interface->bNumEndpoints) {
 
 		if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) {
-			have_bulk_in = 1;
-			hps->bulk_in_ep = ep_cnt + 1;
 			ep_cnt++;
-			dbg("probe_scanner: bulk_in_ep: %d", (int)hps->bulk_in_ep);
+			have_bulk_in = ep_cnt;
+			dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in);
 			continue;
 		}
 		
 		if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
-			have_bulk_out = 1;
-			hps->bulk_out_ep = ep_cnt + 1;
 			ep_cnt++;
-			dbg("probe_scanner: bulk_out_ep: %d", (int)hps->bulk_out_ep);
+			have_bulk_out = ep_cnt;
+			dbg("probe_scanner: bulk_out_ep:%d", have_bulk_out);
 			continue;
 		}
 
 		if (!have_intr && IS_EP_INTR(endpoint[ep_cnt])) {
-			have_intr = 1;
-			hps->intr_ep = ep_cnt + 1;
 			ep_cnt++;
-			dbg("probe_scanner: intr_ep: %d", (int)hps->intr_ep);
+			have_intr = ep_cnt;
+			dbg("probe_scanner: intr_ep:%d", have_intr);
 			continue;
 		}
 		info("probe_scanner: Undetected endpoint. Notify the maintainer.");
 		return NULL;	/* Shouldn't ever get here unless we have something weird */
 	}
 
+
+/*
+ * Perform a quick check to make sure that everything worked as it
+ * should have.
+ */
+
 	switch(interface->bNumEndpoints) {
 	case 2:
 		if (!have_bulk_in || !have_bulk_out) {
@@ -494,53 +592,124 @@
 		return NULL;
 	}
 
-	hps->present = 1;
-	hps->hpscan_dev = dev;
 
-	if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+/* 
+ * Determine a minor number and initialize the structure associated
+ * with it.  The problem with this is that we are counting on the fact
+ * that the user will sequentially add device nodes for the scanner
+ * devices.  */
+
+	for (scn_minor = 0; scn_minor < SCN_MAX_MNR; scn_minor++) {
+		if (!p_scn_table[scn_minor])
+			break;
+	}
+
+/* Check to make sure that the last slot isn't already taken */
+	if (p_scn_table[scn_minor]) {
+		err("probe_scanner: No more minor devices remaining.");
+		return NULL;
+	}
+
+	dbg("probe_scanner: Allocated minor:%d", scn_minor);
+
+	if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
+		err("probe_scanner: Out of memory.");
+		return NULL;
+	}
+	memset (scn, 0, sizeof(struct scn_usb_data));
+	dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, scn);
+
+
+/* Ok, if we detected an interrupt EP, setup a handler for it */
+	if (have_intr) {
+		dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", scn_minor, have_intr);
+		FILL_INT_URB(&scn->scn_irq, dev, 
+			     usb_rcvintpipe(dev, have_intr),
+			     &scn->button, 1, irq_scanner, scn,
+			     // endpoint[(int)have_intr].bInterval);
+			     250);
+
+	        if (usb_submit_urb(&scn->scn_irq)) {
+			err("probe_scanner(%d): Unable to allocate INT URB.", scn_minor);
+                	kfree(scn);
+                	return NULL;
+        	}
+	}
+
+
+/* Ok, now initialize all the relevant values */
+	if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+		err("probe_scanner(%d): Not enough memory for the output buffer.", scn_minor);
+		kfree(scn);
 		return NULL;
 	}
+	dbg("probe_scanner(%d): obuf address:%p", scn_minor, scn->obuf);
 
-	if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+	if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+		err("probe_scanner(%d): Not enough memory for the input buffer.", scn_minor);
+		kfree(scn->obuf);
+		kfree(scn);
 		return NULL;
 	}
+	dbg("probe_scanner(%d): ibuf address:%p", scn_minor, scn->ibuf);
 
-	return hps;
+	scn->bulk_in_ep = have_bulk_in;
+	scn->bulk_out_ep = have_bulk_out;
+	scn->intr_ep = have_intr;
+	scn->present = 1;
+	scn->scn_dev = dev;
+	scn->scn_minor = scn_minor;
+	scn->isopen = 0;
+
+	return p_scn_table[scn_minor] = scn;
 }
 
 static void
 disconnect_scanner(struct usb_device *dev, void *ptr)
 {
-	struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr;
-
-	if (hps->isopen) {
-		/* better let it finish - the release will do whats needed */
-		hps->hpscan_dev = NULL;
-		return;
-	}
-	kfree(hps->ibuf);
-	kfree(hps->obuf);
-
-	hps->present = 0;
+	struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
+	
+	if(scn->intr_ep) {
+		dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor);
+		usb_unlink_urb(&scn->scn_irq);
+	}
+        usb_driver_release_interface(&scanner_driver,
+                &scn->scn_dev->actconfig->interface[scn->ifnum]);
+
+	kfree(scn->ibuf);
+	kfree(scn->obuf);
+
+	dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
+	p_scn_table[scn->scn_minor] = NULL;
+	kfree (scn);
 }
 
 static int
 ioctl_scanner(struct inode *inode, struct file *file,
 	      unsigned int cmd, unsigned long arg)
 {
-	struct hpscan_usb_data *hps = &hpscan;
 	struct usb_device *dev;
-
+	
 	int result;
+
+	kdev_t scn_minor;
 	
-	dev = hps->hpscan_dev;
+	scn_minor = USB_SCN_MINOR(inode);
+
+	if (!p_scn_table[scn_minor]) {
+		err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
+		return -ENOIOCTLCMD;
+	}
 
+	dev = p_scn_table[scn_minor]->scn_dev;
+	
 	switch (cmd)
 	{
-	case PV8630_RECEIVE :
+	case PV8630_IOCTL_INREQUEST :
 	{
 		struct {
-			unsigned char data;
+			__u8  data;
+			__u8  request;
 			__u16 value;
 			__u16 index;
 		} args;
@@ -548,23 +717,25 @@
 		if (copy_from_user(&args, (void *)arg, sizeof(args)))
 			return -EFAULT;
 		
-		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x0,
-					 USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
-					 args.value, args.index, &args.data, 1, HZ);
+		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+					 args.request, USB_TYPE_VENDOR|
+					 USB_RECIP_DEVICE|USB_DIR_IN,
+					 args.value, args.index, &args.data,
+					 1, HZ*5);
 
-		dbg("ioctl_scanner recv: args.data:%x args.value:%x args.index:%x",
-				 args.data, args.value, args.index);
+		dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request);
 
 		if (copy_to_user((void *)arg, &args, sizeof(args)))
 			return -EFAULT;
-		
-		dbg("ioctl_scanner recv: result:%d", result);
 
+		dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);
+		
 		return result;
 	}
-	case PV8630_SEND :
+	case PV8630_IOCTL_OUTREQUEST :
 	{
 		struct {
+			__u8  request;
 			__u16 value;
 			__u16 index;
 		} args;
@@ -572,15 +743,16 @@
 		if (copy_from_user(&args, (void *)arg, sizeof(args)))
 			return -EFAULT;
 		
-		dbg("ioctl_scanner send: args.value:%x args.index:%x", args.value, args.index);
+		dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request);
 
-		result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x1 /* Vendor Specific bRequest */,
-					 USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_OUT /* 0x40 */,
-					 args.value, args.index, NULL, 0, HZ);
+		result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+					 args.request, USB_TYPE_VENDOR|
+					 USB_RECIP_DEVICE|USB_DIR_OUT,
+					 args.value, args.index, NULL,
+					 0, HZ*5);
 
-		dbg("ioctl_scanner send: result:%d", result);
+		dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);
 		
-
 		return result;
 	}
 	default:
@@ -591,18 +763,11 @@
 
 static struct
 file_operations usb_scanner_fops = {
-	NULL,		/* seek */
-	read_scanner,
-	write_scanner,
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	ioctl_scanner, 	/* ioctl */
-	NULL,		/* mmap */
-	open_scanner,
-	NULL,		/* flush */
-	close_scanner,
-	NULL,         
-	NULL,         /* fasync */
+	read:		read_scanner,
+	write:		write_scanner,
+	ioctl:		ioctl_scanner,
+	open:		open_scanner,
+	release:	close_scanner,
 };
 
 static struct
@@ -612,7 +777,7 @@
        disconnect_scanner,
        { NULL, NULL },
        &usb_scanner_fops,
-       48
+       SCN_BASE_MNR
 };
 
 int
@@ -625,16 +790,6 @@
 	return 0;
 }
 
-
-void
-usb_scanner_cleanup(void)
-{
-	struct hpscan_usb_data *hps = &hpscan;
-
-	hps->present = 0;
-	usb_deregister(&scanner_driver);
-}
-
 #ifdef MODULE
 
 int
@@ -646,7 +801,7 @@
 void
 cleanup_module(void)
 {
-	usb_scanner_cleanup();
+	usb_deregister(&scanner_driver);
 }
 #endif
 
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h
--- v2.3.42/linux/drivers/usb/scanner.h	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/scanner.h	Mon Feb  7 19:13:45 2000
@@ -18,6 +18,8 @@
 #define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
 #define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
 
+#define USB_SCN_MINOR(X) MINOR((X)->i_rdev) - SCN_BASE_MNR
+
 #ifdef DEBUG
 #define SCN_DEBUG(X) X
 #else
@@ -30,19 +32,25 @@
 
 /* FIXME: These are NOT registered ioctls()'s */
 
-#define PV8630_RECEIVE 69
-#define PV8630_SEND    70
+#define PV8630_IOCTL_INREQUEST 69
+#define PV8630_IOCTL_OUTREQUEST 70
+
+#define SCN_MAX_MNR 16		/* We're allocated 16 minors */
+#define SCN_BASE_MNR 48		/* USB Scanners start at minor 48 */
 
-struct hpscan_usb_data {
-	struct usb_device *hpscan_dev;
-        int isopen;		/* Not zero if the device is open */
-	int present;		/* Device is present on the bus */
+struct scn_usb_data {
+	struct usb_device *scn_dev;
+	struct urb scn_irq;
+	unsigned int ifnum;	/* Interface number of the USB device */
+	kdev_t scn_minor;	/* Scanner minor - used in disconnect() */
+	unsigned char button;	/* Front panel buffer */
+        char isopen;		/* Not zero if the device is open */
+	char present;		/* Not zero if device is present */
 	char *obuf, *ibuf;	/* transfer buffers */
 	char bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */
-	char *button;		/* Front panel button buffer */
 };
 
-static struct hpscan_usb_data hpscan;
+static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
 
 MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
 MODULE_DESCRIPTION("USB Scanner Driver");
@@ -53,3 +61,6 @@
 
 MODULE_PARM(product, "i");
 MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+/* Forward declarations */
+static struct usb_driver scanner_driver;
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.42/linux/drivers/usb/uhci.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/uhci.c	Tue Feb  8 17:11:13 2000
@@ -46,10 +46,8 @@
 #include "uhci.h"
 #include "uhci-debug.h"
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-static int handle_apm_event(apm_event_t event);
-#endif
+#include <linux/pm.h>
+static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data);
 
 static int debug = 1;
 MODULE_PARM(debug, "i");
@@ -61,53 +59,41 @@
 
 static int rh_submit_urb(urb_t *urb);
 static int rh_unlink_urb(urb_t *urb);
-static int uhci_get_current_frame_number(struct usb_device *usb_dev);
+static int uhci_get_current_frame_number(struct usb_device *dev);
+static void uhci_stop_hc_schedule(struct uhci *uhci);
+static void uhci_start_hc_schedule(struct uhci *uhci);
+static int uhci_unlink_urb(urb_t *urb);
 
 #define min(a,b) (((a)<(b))?(a):(b))
 
 /*
  * Only the USB core should call uhci_alloc_dev and uhci_free_dev
  */
-static int uhci_alloc_dev(struct usb_device *usb_dev)
+static int uhci_alloc_dev(struct usb_device *dev)
 {
-	struct uhci_device *dev;
-
-	/* Allocate the UHCI device private data */
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -1;
-
-	/* Initialize "dev" */
-	memset(dev, 0, sizeof(*dev));
-
-	usb_dev->hcpriv = dev;
-	dev->usb = usb_dev;
-	atomic_set(&dev->refcnt, 1);
-
-	if (usb_dev->parent)
-		dev->uhci = usb_to_uhci(usb_dev->parent)->uhci;
-
 	return 0;
 }
 
-static int uhci_free_dev(struct usb_device *usb_dev)
+static int uhci_free_dev(struct usb_device *dev)
 {
-	struct uhci_device *dev = usb_to_uhci(usb_dev);
-
-	if (atomic_dec_and_test(&dev->refcnt))
-		kfree(dev);
+	urb_t *u;
+	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
+	struct list_head *tmp, *head = &uhci->urb_list;
+	unsigned long flags;
 
-	return 0;
-}
+	/* Walk through the entire URB list and forcefully remove any */
+	/*  URBs that are still active for that device */
+	nested_lock(&uhci->urblist_lock, flags);
+	tmp = head->next;
+	while (tmp != head) {
+		u = list_entry(tmp, urb_t, urb_list);
 
-static void uhci_inc_dev_use(struct uhci_device *dev)
-{
-	atomic_inc(&dev->refcnt);
-}
+		if (u->dev == dev)
+			uhci_unlink_urb(u);
+	}
+	nested_unlock(&uhci->urblist_lock, flags);
 
-static void uhci_dec_dev_use(struct uhci_device *dev)
-{
-	uhci_free_dev(dev->usb);
+	return 0;
 }
 
 /*
@@ -138,21 +124,21 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->urblist_lock, flags);
+	nested_lock(&uhci->urblist_lock, flags);
 	list_add(&urb->urb_list, &uhci->urb_list);
-	spin_unlock_irqrestore(&uhci->urblist_lock, flags);
+	nested_unlock(&uhci->urblist_lock, flags);
 }
 
 static void uhci_remove_urb_list(struct uhci *uhci, struct urb *urb)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->urblist_lock, flags);
+	nested_lock(&uhci->urblist_lock, flags);
 	if (urb->urb_list.next != &urb->urb_list) {
 		list_del(&urb->urb_list);
 		INIT_LIST_HEAD(&urb->urb_list);
 	}
-	spin_unlock_irqrestore(&uhci->urblist_lock, flags);
+	nested_unlock(&uhci->urblist_lock, flags);
 }
 
 /*
@@ -255,7 +241,7 @@
 	prevtd->link = UHCI_PTR_TERM;
 }
 
-static struct uhci_td *uhci_td_alloc(struct uhci_device *dev)
+static struct uhci_td *uhci_alloc_td(struct usb_device *dev)
 {
 	struct uhci_td *td;
 
@@ -273,33 +259,20 @@
 	INIT_LIST_HEAD(&td->irq_list);
 	INIT_LIST_HEAD(&td->list);
 
-	uhci_inc_dev_use(dev);
+	usb_inc_dev_use(dev);
 
 	return td;
 }
 
-static void uhci_td_free(struct uhci_td *td)
+static void uhci_free_td(struct uhci_td *td)
 {
 	kmem_cache_free(uhci_td_cachep, td);
 
 	if (td->dev)
-		uhci_dec_dev_use(td->dev);
+		usb_dec_dev_use(td->dev);
 }
 
-static void uhci_schedule_delete_td(struct uhci *uhci, struct uhci_td *td)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->freelist_lock, flags);
-	list_add(&td->list, &uhci->td_free_list);
-	if (td->dev) {
-		uhci_dec_dev_use(td->dev);
-		td->dev = NULL;
-	}
-	spin_unlock_irqrestore(&uhci->freelist_lock, flags);
-}
-
-static struct uhci_qh *uhci_qh_alloc(struct uhci_device *dev)
+static struct uhci_qh *uhci_alloc_qh(struct usb_device *dev)
 {
 	struct uhci_qh *qh;
 
@@ -315,30 +288,17 @@
 
 	INIT_LIST_HEAD(&qh->list);
 
-	uhci_inc_dev_use(dev);
+	usb_inc_dev_use(dev);
 
 	return qh;
 }
 
-static void uhci_qh_free(struct uhci_qh *qh)
+static void uhci_free_qh(struct uhci_qh *qh)
 {
 	kmem_cache_free(uhci_qh_cachep, qh);
 
 	if (qh->dev)
-		uhci_dec_dev_use(qh->dev);
-}
-
-static void uhci_schedule_delete_qh(struct uhci *uhci, struct uhci_qh *qh)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->freelist_lock, flags);
-	list_add(&qh->list, &uhci->qh_free_list);
-	if (qh->dev) {
-		uhci_dec_dev_use(qh->dev);
-		qh->dev = NULL;
-	}
-	spin_unlock_irqrestore(&uhci->freelist_lock, flags);
+		usb_dec_dev_use(qh->dev);
 }
 
 static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct uhci_qh *qh)
@@ -398,6 +358,30 @@
 		urbp->begin = td;
 }
 
+void uhci_inc_fsbr(struct uhci *uhci)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->framelist_lock, flags);
+
+	if (!uhci->fsbr++)
+		uhci->skel_term_qh.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH;
+
+	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
+void uhci_dec_fsbr(struct uhci *uhci)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->framelist_lock, flags);
+
+	if (!--uhci->fsbr)
+		uhci->skel_term_qh.link = UHCI_PTR_TERM;
+
+	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
 /*
  * Map status to standard result codes
  *
@@ -438,8 +422,7 @@
 	struct uhci_td *td;
 	struct uhci_qh *qh;
 	unsigned long destination, status;
-	struct uhci_device *dev = usb_to_uhci(urb->dev);
-	struct uhci *uhci = dev->uhci;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
 	unsigned char *data = urb->transfer_buffer;
@@ -462,7 +445,7 @@
 	/*
 	 * Build the TD for the control request
 	 */
-	td = uhci_td_alloc(dev);
+	td = uhci_alloc_td(urb->dev);
 	if (!td)
 		return -ENOMEM;
 
@@ -482,7 +465,7 @@
 	/*
 	 * Build the DATA TD's
 	 */
-	td = uhci_td_alloc(dev);
+	td = uhci_alloc_td(urb->dev);
 	if (!td) {
 		/* FIXME: Free the TD's */
 		return -ENOMEM;
@@ -504,7 +487,7 @@
 		data += pktsze;
 		len -= pktsze;
 
-		td = uhci_td_alloc(dev);
+		td = uhci_alloc_td(urb->dev);
 		if (!td)
 			/* FIXME: Free all of the previously allocated td's */
 			return -ENOMEM;
@@ -532,14 +515,19 @@
 
 	uhci_add_irq_list(uhci, td);
 
-	qh = uhci_qh_alloc(dev);
+	qh = uhci_alloc_qh(urb->dev);
 	if (!qh) {
 		/* FIXME: Free all of the TD's */
 		return -ENOMEM;
 	}
 	uhci_insert_tds_in_qh(qh, urbp->begin);
 
-	uhci_insert_qh(uhci, &uhci->skel_control_qh, qh);
+	if (!(urb->pipe & TD_CTRL_LS)) {
+		uhci_insert_qh(uhci, &uhci->skel_hs_control_qh, qh);
+		uhci_inc_fsbr(uhci);
+	} else
+		uhci_insert_qh(uhci, &uhci->skel_ls_control_qh, qh);
+
 	urbp->qh = qh;
 
 	uhci_add_urb_list(uhci, urb);
@@ -549,18 +537,27 @@
 	return -EINPROGRESS;
 }
 
+/* This is also the uhci_unlink_bulk function */
 static int uhci_unlink_control(urb_t *urb)
 {
 	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
-	struct uhci_device *dev = usb_to_uhci(urb->dev);
-	struct uhci *uhci = dev->uhci;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	int notfinished;
 
 	if (!urbp)
 		return -EINVAL;
 
+	notfinished = (urb->status == -EINPROGRESS);
+
+	if (notfinished)
+		uhci_stop_hc_schedule(uhci);
+
+	if (!(urb->pipe & TD_CTRL_LS))
+		uhci_dec_fsbr(uhci);
+
 	uhci_remove_qh(uhci, urbp->qh);
-	uhci_schedule_delete_qh(uhci, urbp->qh);
+	uhci_free_qh(urbp->qh);
 
 	/* Go through the rest of the TD's, deleting them, then scheduling */
 	/*  their deletion */
@@ -571,11 +568,14 @@
 		if (td->status & TD_CTRL_IOC)
 			uhci_remove_irq_list(uhci, td);
 
-		uhci_schedule_delete_td(uhci, td);
+		uhci_free_td(td);
 
 		td = next;
 	}
 
+	if (notfinished)
+		uhci_start_hc_schedule(uhci);
+
 	kfree(urbp);
 	urb->hcpriv = NULL;
 
@@ -589,7 +589,6 @@
 	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
 	unsigned int status;
-	int ret;
 
 	td = urbp->begin;
 	if (!td)		/* Nothing to do */
@@ -617,8 +616,9 @@
 
 		/* If SPD is set then we received a short packet */
 		/*  There will be no status phase at the end */
+		/* FIXME: Re-setup the queue to run the STATUS phase? */
 		if (td->status & TD_CTRL_SPD && (uhci_actual_length(td->status) < uhci_expected_length(td->info)))
-			goto td_success;
+			return 0;
 
 		if (status)
 			goto td_error;
@@ -635,7 +635,7 @@
 	if (td->status & TD_CTRL_IOC &&
 	    status & TD_CTRL_ACTIVE &&
 	    status & TD_CTRL_NAK)
-		goto td_success;
+		return 0;
 
 	if (status & TD_CTRL_ACTIVE)
 		return -EINPROGRESS;
@@ -643,9 +643,6 @@
 	if (status)
 		goto td_error;
 
-td_success:
-	uhci_unlink_control(urb);
-
 	return 0;
 
 td_error:
@@ -662,16 +659,9 @@
 		/* endpoint has stalled - mark it halted */
 		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
 	    			uhci_packetout(td->info));
-		uhci_unlink_control(urb);
-
-		return -EPIPE;
 	}
 
-	ret = uhci_map_status(status, uhci_packetout(td->info));
-
-	uhci_unlink_control(urb);
-
-	return ret;
+	return uhci_map_status(status, uhci_packetout(td->info));
 }
 
 /*
@@ -681,8 +671,7 @@
 {
 	struct uhci_td *td;
 	unsigned long destination, status;
-	struct uhci_device *dev = usb_to_uhci(urb->dev);
-	struct uhci *uhci = dev->uhci;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	struct urb_priv *urbp;
 
 	if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
@@ -702,7 +691,7 @@
 
 	urb->hcpriv = urbp;
 
-	td = uhci_td_alloc(dev);
+	td = uhci_alloc_td(urb->dev);
 	if (!td)
 		return -ENOMEM;
 
@@ -728,17 +717,25 @@
 {
 	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
-	struct uhci_device *dev = usb_to_uhci(urb->dev);
-	struct uhci *uhci = dev->uhci;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	int notfinished;
 
 	if (!urbp)
 		return -EINVAL;
 
+	notfinished = (urb->status == -EINPROGRESS);
+
+	if (notfinished)
+		uhci_stop_hc_schedule(uhci);
+
 	td = urbp->begin;
 	uhci_remove_td(uhci, td);
 	if (td->status & TD_CTRL_IOC)
 		uhci_remove_irq_list(uhci, td);
-	uhci_schedule_delete_td(uhci, td);
+	uhci_free_td(td);
+
+	if (notfinished)
+		uhci_start_hc_schedule(uhci);
 
 	kfree(urbp);
 	urb->hcpriv = NULL;
@@ -765,12 +762,10 @@
 	if (status & TD_CTRL_ACTIVE)
 		return -EINPROGRESS;
 
-	if (status)
-		return uhci_map_status(status, uhci_packetout(td->info));
-
-	urb->actual_length += uhci_actual_length(td->status);
+	if (!status)
+		urb->actual_length = uhci_actual_length(td->status);
 
-	return 0;
+	return uhci_map_status(status, uhci_packetout(td->info));
 }
 
 static void uhci_reset_interrupt(urb_t *urb)
@@ -778,17 +773,14 @@
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	struct uhci_td *td;
 
-	if (urb->interval) {
-		td = urbp->begin;
+	td = urbp->begin;
 
-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
-		td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
-		td->info &= ~(1 << TD_TOKEN_TOGGLE);
-		td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+	td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
+	td->info &= ~(1 << TD_TOKEN_TOGGLE);
+	td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
 
-		urb->status = -EINPROGRESS;
-	} else
-		uhci_unlink_interrupt(urb);
+	urb->status = -EINPROGRESS;
 }
 
 /*
@@ -799,8 +791,7 @@
 	struct uhci_td *td;
 	struct uhci_qh *qh;
 	unsigned long destination, status;
-	struct uhci_device *dev = usb_to_uhci(urb->dev);
-	struct uhci *uhci = dev->uhci;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
 	unsigned char *data = urb->transfer_buffer;
@@ -834,7 +825,7 @@
 		if (pktsze > maxsze)
 			pktsze = maxsze;
 
-		td = uhci_td_alloc(dev);
+		td = uhci_alloc_td(urb->dev);
 		if (!td) {
 			/* FIXME: Free the TD's */
 			return -ENOMEM;
@@ -858,20 +849,22 @@
 			usb_pipeout(urb->pipe));
 	}
 
-	qh = uhci_qh_alloc(dev);
+	qh = uhci_alloc_qh(urb->dev);
 	if (!qh) {
 		/* FIXME: Free all of the TD's */
 		return -ENOMEM;
 	}
 	uhci_insert_tds_in_qh(qh, urbp->begin);
 
-	uhci_insert_qh(dev->uhci, &dev->uhci->skel_bulk_qh, qh);
+	uhci_insert_qh(uhci, &uhci->skel_bulk_qh, qh);
 	urbp->qh = qh;
 
 	uhci_add_urb_list(uhci, urb);
 
 	usb_inc_dev_use(urb->dev);
 
+	uhci_inc_fsbr(uhci);
+
 	return -EINPROGRESS;
 }
 
@@ -900,16 +893,13 @@
 				uhci_packetout(td->info),
 				uhci_toggle(td->info) ^ 1);
 
-			goto td_success;
+			return 0;
 		}
 
 		if (status)
 			goto td_error;
 	}
 
-td_success:
-	uhci_unlink_bulk(urb);
-
 	return 0;
 
 td_error:
@@ -926,7 +916,6 @@
 		/* endpoint has stalled - mark it halted */
 		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
 	    			uhci_packetout(td->info));
-		return -EPIPE;
 	}
 
 	return uhci_map_status(status, uhci_packetout(td->info));
@@ -942,7 +931,7 @@
 	struct list_head *tmp, *head = &uhci->urb_list;
 	unsigned long flags;
 
-	spin_lock_irqsave(&uhci->urblist_lock, flags);
+	nested_lock(&uhci->urblist_lock, flags);
 	tmp = head->next;
 	while (tmp != head) {
 		u = list_entry(tmp, urb_t, urb_list);
@@ -956,7 +945,7 @@
 		}
 		tmp = tmp->next;
 	}
-	spin_unlock_irqrestore(&uhci->urblist_lock, flags);
+	nested_unlock(&uhci->urblist_lock, flags);
 
 	if (last_urb) {
 		*end = (last_urb->start_frame + last_urb->number_of_packets) & 1023;
@@ -995,8 +984,7 @@
 static int uhci_submit_isochronous(urb_t *urb)
 {
 	struct uhci_td *td;
-	struct uhci_device *dev = usb_to_uhci(urb->dev);
-	struct uhci *uhci = dev->uhci;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	struct urb_priv *urbp;
 	int i, ret, framenum;
 	int status, destination;
@@ -1021,7 +1009,7 @@
 		if (!urb->iso_frame_desc[i].length)
 			continue;
 
-		td = uhci_td_alloc(dev);
+		td = uhci_alloc_td(urb->dev);
 		if (!td) {
 			/* FIXME: Free the TD's */
 			return -ENOMEM;
@@ -1050,12 +1038,17 @@
 {
 	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
-	struct uhci_device *dev = usb_to_uhci(urb->dev);
-	struct uhci *uhci = dev->uhci;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	int notfinished;
 
 	if (!urbp)
 		return -EINVAL;
 
+	notfinished = (urb->status == -EINPROGRESS);
+
+	if (notfinished)
+		uhci_stop_hc_schedule(uhci);
+
 	/* Go through the rest of the TD's, deleting them, then scheduling */
 	/*  their deletion */
 	td = urbp->begin;
@@ -1066,11 +1059,14 @@
 
 		if (td->status & TD_CTRL_IOC)
 			uhci_remove_irq_list(uhci, td);
-		uhci_schedule_delete_td(uhci, td);
+		uhci_free_td(td);
 
 		td = next;
 	}
 
+	if (notfinished)
+		uhci_start_hc_schedule(uhci);
+
 	kfree(urbp);
 	urb->hcpriv = NULL;
 
@@ -1090,14 +1086,12 @@
 	if (!td)		/* Nothing to do */
 		return -EINVAL;
 
-	status =  uhci_status_bits(td->status);
+	status = uhci_status_bits(td->status);
 	if (status & TD_CTRL_ACTIVE)
 		return -EINPROGRESS;
 
-	/* Assume no errors, we'll overwrite this if not */
-	urb->status = 0;
-
 	urb->actual_length = 0;
+
 	for (i = 0, td = urbp->begin; td; i++, td = td->next) {
 		int actlength;
 
@@ -1113,9 +1107,7 @@
 		}
 	}
 
-	uhci_unlink_isochronous(urb);
-
-	return status;
+	return ret;
 }
 
 static int uhci_submit_urb(urb_t *urb)
@@ -1150,11 +1142,8 @@
 	}
 
 	urb->status = ret;
-	if (ret == -EINPROGRESS) {
-		usb_inc_dev_use(urb->dev);
-
+	if (ret == -EINPROGRESS)
 		return 0;
-	}
 
 	return ret;
 }
@@ -1173,13 +1162,8 @@
 		ret = uhci_result_control(urb);
 		break;
 	case PIPE_INTERRUPT:
-		/* Interrupts are an exception */
-		urb->status = uhci_result_interrupt(urb);
-		if (urb->status != -EINPROGRESS) {
-			urb->complete(urb);
-			uhci_reset_interrupt(urb);
-		}
-		return;
+		ret = uhci_result_interrupt(urb);
+		break;
 	case PIPE_BULK:
 		ret = uhci_result_bulk(urb);
 		break;
@@ -1192,6 +1176,26 @@
 	if (urb->status == -EINPROGRESS)
 		return;
 
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		uhci_unlink_control(urb);
+		break;
+	case PIPE_INTERRUPT:
+		/* Interrupts are an exception */
+		urb->complete(urb);
+		if (urb->interval)
+			uhci_reset_interrupt(urb);
+		else
+			uhci_unlink_interrupt(urb);
+		return;
+	case PIPE_BULK:
+		uhci_unlink_bulk(urb);
+		break;
+	case PIPE_ISOCHRONOUS:
+		uhci_unlink_isochronous(urb);
+		break;
+	}
+
 	if (urb->next) {
 		turb = urb->next;
 		do {
@@ -1225,8 +1229,6 @@
 		if (urb->complete && !(urb->transfer_flags & USB_URB_EARLY_COMPLETE))
 			urb->complete(urb);
 	}
-
-	usb_dec_dev_use(urb->dev);
 }
 
 static int uhci_unlink_urb(urb_t *urb)
@@ -1237,6 +1239,9 @@
 	if (!urb)
 		return -EINVAL;
 
+	if (!urb->dev || !urb->dev->bus)
+		return -ENODEV;
+
 	uhci = (struct uhci *)urb->dev->bus->hcpriv;
 
 	if (usb_pipedevice(urb->pipe) == uhci->rh.devnum)
@@ -1261,6 +1266,7 @@
 		if (urb->complete)
 			urb->complete(urb);
 
+#ifndef CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
 		if (in_interrupt()) {		/* wait at least 1 frame */
 			int errorcount = 10;
 
@@ -1269,12 +1275,11 @@
 			udelay(1000);
 		} else
 			schedule_timeout(1+1*HZ/1000); 
+#endif
 
-		usb_dec_dev_use(urb->dev);
+		urb->status = -ENOENT;
 	}
 
-	urb->status = -ENOENT;
-
 	return ret;
 }
 
@@ -1283,11 +1288,11 @@
  *
  * returns the current frame number for a USB bus/controller.
  */
-static int uhci_get_current_frame_number(struct usb_device *usb_dev)
+static int uhci_get_current_frame_number(struct usb_device *dev)
 {
-	struct uhci_device *dev = (struct uhci_device *)usb_dev->hcpriv;
+	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
 
-	return inw(dev->uhci->io_addr + USBFRNUM);
+	return inw(uhci->io_addr + USBFRNUM);
 }
 
 struct usb_operations uhci_device_operations = {
@@ -1393,10 +1398,6 @@
 	urb->status = USB_ST_NOERROR;
 
 	if ((data > 0) && (uhci->rh.send != 0)) {
-#ifdef DEBUG /* JE */
-static int foo=5;
-if (foo--)
-#endif
 		dbg("root-hub INT complete: port1: %x port2: %x data: %x",
 			inw(io_addr + USBPORTSC1), inw(io_addr + USBPORTSC2), data);
 		urb->complete(urb);
@@ -1464,8 +1465,7 @@
 
 static int rh_submit_urb(urb_t *urb)
 {
-	struct usb_device *usb_dev = urb->dev;
-	struct uhci *uhci = (struct uhci *)usb_dev->bus->hcpriv;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	unsigned int pipe = urb->pipe;
 	devrequest *cmd = (devrequest *)urb->setup_packet;
 	void *data = urb->transfer_buffer;
@@ -1645,67 +1645,6 @@
 }
 /*-------------------------------------------------------------------*/
 
-/*
- * This is just incredibly fragile. The timings must be just
- * right, and they aren't really documented very well.
- *
- * Note the short delay between disabling reset and enabling
- * the port..
- */
-static void uhci_reset_port(unsigned int port)
-{
-	unsigned short status;
-
-	status = inw(port);
-	outw(status | USBPORTSC_PR, port);		/* reset port */
-	wait_ms(10);
-	outw(status & ~USBPORTSC_PR, port);
-	udelay(50);
-
-	status = inw(port);
-	outw(status | USBPORTSC_PE, port);		/* enable port */
-	wait_ms(10);
-
-	status = inw(port);
-	if (!(status & USBPORTSC_PE)) {
-		outw(status | USBPORTSC_PE, port);	/* one more try at enabling port */
-		wait_ms(50);
-	}
-
-}
-
-void uhci_free_pending(struct uhci *uhci)
-{
-	struct list_head *tmp, *head;
-
-	/* Free all of the pending QH's and TD's */
-	head = &uhci->td_free_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-                list_del(&td->list);
-                INIT_LIST_HEAD(&td->list);
-
-		uhci_td_free(td);
-	}
-
-	head = &uhci->qh_free_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, list);
-
-		tmp = tmp->next;
-
-                list_del(&qh->list);
-                INIT_LIST_HEAD(&qh->list);
-
-		uhci_qh_free(qh);
-	}
-}
-
 static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
 {
 	struct uhci *uhci = __uhci;
@@ -1737,11 +1676,6 @@
 		}
 	}
 
-	/* Free all of the pending QH's and TD's */
-	spin_lock(&uhci->freelist_lock);
-	uhci_free_pending(uhci);
-	spin_unlock(&uhci->freelist_lock);
-
 	/* Walk the list of pending TD's to see which ones completed.. */
 	nested_lock(&uhci->irqlist_lock, flags);
 	head = &uhci->interrupt_list;
@@ -1759,6 +1693,40 @@
 	nested_unlock(&uhci->irqlist_lock, flags);
 }
 
+static void uhci_stop_hc_schedule(struct uhci *uhci)
+{
+#ifdef CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
+	unsigned int cmdreg, timeout = 1000;
+
+	cmdreg = inw(uhci->io_addr + USBCMD);
+	outw(cmdreg & ~USBCMD_RS, uhci->io_addr + USBCMD);
+
+	while (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) {
+		if (!--timeout) {
+			printk(KERN_ERR "uhci: stop_hc_schedule failed, HC still running\n");
+			break;
+		}
+	}
+#endif
+}
+
+static void uhci_start_hc_schedule(struct uhci *uhci)
+{
+#ifdef CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
+	unsigned int cmdreg, timeout = 1000;
+
+	cmdreg = inw(uhci->io_addr + USBCMD);
+	outw(cmdreg | USBCMD_RS, uhci->io_addr + USBCMD);
+
+	while (inw(uhci->io_addr + USBSTS) & USBSTS_HCH) {
+		if (!--timeout) {
+			printk(KERN_ERR "uhci: start_hc_schedule failed, HC still halted\n");
+			break;
+		}
+	}
+#endif
+}
+
 static void reset_hc(struct uhci *uhci)
 {
 	unsigned int io_addr = uhci->io_addr;
@@ -1833,14 +1801,13 @@
 
 	INIT_LIST_HEAD(&uhci->interrupt_list);
 	INIT_LIST_HEAD(&uhci->urb_list);
-	INIT_LIST_HEAD(&uhci->td_free_list);
-	INIT_LIST_HEAD(&uhci->qh_free_list);
 
-	spin_lock_init(&uhci->urblist_lock);
 	spin_lock_init(&uhci->framelist_lock);
-	spin_lock_init(&uhci->freelist_lock);
+	nested_init(&uhci->urblist_lock);
 	nested_init(&uhci->irqlist_lock);
 
+	uhci->fsbr = 0;
+
 	/* We need exactly one page (per UHCI specs), how convenient */
 	/* We assume that one page is atleast 4k (1024 frames * 4 bytes) */
 	uhci->fl = (void *)__get_free_page(GFP_KERNEL);
@@ -1892,14 +1859,20 @@
 
 
 	uhci_fill_td(&uhci->skel_int1_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
-	uhci->skel_int1_td.link = virt_to_bus(&uhci->skel_control_qh) | UHCI_PTR_QH;
+	uhci->skel_int1_td.link = virt_to_bus(&uhci->skel_ls_control_qh) | UHCI_PTR_QH;
 
-	uhci->skel_control_qh.link = virt_to_bus(&uhci->skel_bulk_qh) | UHCI_PTR_QH;
-	uhci->skel_control_qh.element = UHCI_PTR_TERM;
+	uhci->skel_ls_control_qh.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH;
+	uhci->skel_ls_control_qh.element = UHCI_PTR_TERM;
 
-	uhci->skel_bulk_qh.link = UHCI_PTR_TERM;
+	uhci->skel_hs_control_qh.link = virt_to_bus(&uhci->skel_bulk_qh) | UHCI_PTR_QH;
+	uhci->skel_hs_control_qh.element = UHCI_PTR_TERM;
+
+	uhci->skel_bulk_qh.link = virt_to_bus(&uhci->skel_term_qh) | UHCI_PTR_QH;
 	uhci->skel_bulk_qh.element = UHCI_PTR_TERM;
 
+	uhci->skel_term_qh.link = UHCI_PTR_TERM;
+	uhci->skel_term_qh.element = UHCI_PTR_TERM;
+
 	/*
 	 * Fill the frame list: make all entries point to
 	 * the proper interrupt queue.
@@ -1970,19 +1943,17 @@
 
 int uhci_start_root_hub(struct uhci *uhci)
 {
-	struct usb_device *usb_dev;
+	struct usb_device *dev;
 
-	usb_dev = usb_alloc_dev(NULL, uhci->bus);
-	if (!usb_dev)
+	dev = usb_alloc_dev(NULL, uhci->bus);
+	if (!dev)
 		return -1;
 
-	usb_to_uhci(usb_dev)->uhci = uhci;
+	uhci->bus->root_hub = dev;
+	usb_connect(dev);
 
-	uhci->bus->root_hub = usb_dev;
-	usb_connect(usb_dev);
-
-	if (usb_new_device(usb_dev) != 0) {
-		usb_free_dev(usb_dev);
+	if (usb_new_device(dev) != 0) {
+		usb_free_dev(dev);
 
 		return -1;
 	}
@@ -1994,7 +1965,7 @@
  * If we've successfully found a UHCI, now is the time to increment the
  * module usage count, and return success..
  */
-static int setup_uhci(int irq, unsigned int io_addr, unsigned int io_size)
+static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
 {
 	int retval;
 	struct uhci *uhci;
@@ -2017,8 +1988,16 @@
 	if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci) == 0) {
 		uhci->irq = irq;
 
-		if (!uhci_start_root_hub(uhci))
+		if (!uhci_start_root_hub(uhci)) {
+			struct pm_dev *pmdev;
+
+			pmdev = pm_register(PM_PCI_DEV,
+					    PM_PCI_ID(dev),
+					    handle_pm_event);
+			if (pmdev)
+				pmdev->data = uhci;
 			return 0;
+		}
 	}
 
 	/* Couldn't allocate IRQ if we got here */
@@ -2060,38 +2039,22 @@
 			continue;
 		}
 
-		return setup_uhci(dev->irq, io_addr, io_size);
+		return setup_uhci(dev, dev->irq, io_addr, io_size);
 	}
 
 	return -1;
 }
 
-#ifdef CONFIG_APM
-static int handle_apm_event(apm_event_t event)
+static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-	static int down = 0;
-
-	switch (event) {
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-		if (down) {
-			dbg("received extra suspend event");
-			break;
-		}
-		down = 1;
+	switch (rqst) {
+	case PM_SUSPEND:
 		break;
-	case APM_NORMAL_RESUME:
-	case APM_CRITICAL_RESUME:
-		if (!down) {
-			dbg("received bogus resume event");
-			break;
-		}
-		down = 0;
+	case PM_RESUME:
 		break;
 	}
 	return 0;
 }
-#endif
 
 int uhci_init(void)
 {
@@ -2139,10 +2102,6 @@
 	if (retval && uhci_list.next == &uhci_list)
 		goto init_failed;
 
-#ifdef CONFIG_APM
-	apm_register_callback(&handle_apm_event);
-#endif
-
 	return 0;
 
 init_failed:
@@ -2160,8 +2119,6 @@
 void uhci_cleanup(void)
 {
 	struct list_head *next, *tmp, *head = &uhci_list;
-	int i;
-	unsigned long flags;
 
 	tmp = head->next;
 	while (tmp != head) {
@@ -2180,11 +2137,6 @@
 		reset_hc(uhci);
 		release_region(uhci->io_addr, uhci->io_size);
 
-		/* Free any outstanding TD's and QH's */
-		spin_lock_irqsave(&uhci->freelist_lock, flags);
-		uhci_free_pending(uhci);
-		spin_unlock_irqrestore(&uhci->freelist_lock, flags);
-
 		release_uhci(uhci);
 
 		tmp = next;
@@ -2205,9 +2157,7 @@
 
 void cleanup_module(void)
 {
-#ifdef CONFIG_APM
-	apm_unregister_callback(&handle_apm_event);
-#endif
+	pm_unregister_all(handle_pm_event);
 	uhci_cleanup();
 }
 #endif //MODULE
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h
--- v2.3.42/linux/drivers/usb/uhci.h	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/uhci.h	Tue Feb  8 17:11:13 2000
@@ -108,7 +108,7 @@
 	/* Software fields */
 	struct uhci_qh *prevqh, *nextqh;	/* Previous and next TD in queue */
 
-	struct uhci_device *dev;		/* The owning device */
+	struct usb_device *dev;			/* The owning device */
 
 	struct list_head list;
 } __attribute__((aligned(16)));
@@ -182,7 +182,7 @@
 	unsigned int *frameptr;		/* Frame list pointer */
 	struct uhci_td *prevtd, *nexttd; /* Previous and next TD in queue */
 
-	struct uhci_device *dev;
+	struct usb_device *dev;
 	struct urb *urb;		/* URB this TD belongs to */
 	struct uhci_td *next;		/* List of chained TD's for an URB */
 
@@ -191,26 +191,6 @@
 } __attribute__((aligned(16)));
 
 /*
- * Note the alignment requirements of the entries
- *
- * Each UHCI device has pre-allocated QH and TD entries.
- * You can use more than the pre-allocated ones, but I
- * don't see you usually needing to.
- */
-struct uhci;
-
-struct uhci_device {
-	struct usb_device	*usb;
-
-	atomic_t		refcnt;
-
-	struct uhci		*uhci;		/* HC this device is connected to */
-};
-
-#define uhci_to_usb(uhci)	((uhci)->usb)
-#define usb_to_uhci(usb)	((struct uhci_device *)(usb)->hcpriv)
-
-/*
  * There are various standard queues. We set up several different
  * queues for each of the three basic queue types: interrupt,
  * control, and bulk.
@@ -264,9 +244,11 @@
 #define skel_int128_td		skeltd[7]
 #define skel_int256_td		skeltd[8]
 
-#define UHCI_NUM_SKELQH		2
-#define skel_control_qh		skelqh[0]
-#define skel_bulk_qh		skelqh[1]
+#define UHCI_NUM_SKELQH		4
+#define skel_ls_control_qh	skelqh[0]
+#define skel_hs_control_qh	skelqh[1]
+#define skel_bulk_qh		skelqh[2]
+#define skel_term_qh		skelqh[3]
 
 /*
  * Search tree for determining where <interval> fits in the
@@ -340,14 +322,12 @@
 	struct s_nested_lock irqlist_lock;
 	struct list_head interrupt_list;	/* List of interrupt-active TD's for this uhci */
 
-	spinlock_t urblist_lock;
+	struct s_nested_lock urblist_lock;
 	struct list_head urb_list;
 
 	spinlock_t framelist_lock;
 
-	spinlock_t freelist_lock;
-	struct list_head td_free_list;
-	struct list_head qh_free_list;
+	int fsbr;			/* Full speed bandwidth reclamation */
 
 	struct virt_root_hub rh;	/* private data of the virtual root hub */
 };
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- v2.3.42/linux/drivers/usb/usb-ohci.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/usb-ohci.c	Wed Feb  9 19:43:57 2000
@@ -52,10 +52,8 @@
 #include "usb.h"
 #include "usb-ohci.h"
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-static int handle_apm_event (apm_event_t event);
-#endif
+#include <linux/pm.h>
+static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data);
 
 #ifdef CONFIG_PMAC_PBOOK
 #include <linux/adb.h>
@@ -1632,7 +1630,7 @@
 /* Increment the module usage count, start the control thread and
  * return success. */
  
-static int hc_found_ohci (int irq, void * mem_base)
+static int hc_found_ohci (struct pci_dev *dev, int irq, void * mem_base)
 {
 	ohci_t * ohci;
 	dbg("USB HC found: irq= %d membase= %lx", irq, (unsigned long) mem_base);
@@ -1651,8 +1649,17 @@
 	usb_register_bus (ohci->bus);
 	
 	if (request_irq (irq, hc_interrupt, SA_SHIRQ, "ohci-usb", ohci) == 0) {
+		struct pm_dev *pmdev;
+
 		ohci->irq = irq;     
 		hc_start (ohci);
+
+		pmdev = pm_register (PM_PCI_DEV,
+				     PM_PCI_ID(dev),
+				     handle_pm_event);
+		if (pmdev)
+			pmdev->data = ohci;
+
 		return 0;
  	}	
  	err("request interrupt %d failed", irq);
@@ -1664,6 +1671,7 @@
  
 static int hc_start_ohci (struct pci_dev * dev)
 {
+	u32 cmd;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
 	unsigned long mem_base = dev->resource[0].start;
 #else
@@ -1672,6 +1680,11 @@
 	mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
 #endif
 	
+	/* Some Mac firmware will switch memory response off */
+	pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+	cmd = (cmd | PCI_COMMAND_MEMORY);
+	pci_write_config_dword(dev, PCI_COMMAND, cmd);
+
 	pci_set_master (dev);
 	mem_base = (unsigned long) ioremap_nocache (mem_base, 4096);
 
@@ -1679,7 +1692,7 @@
 		err("Error mapping OHCI memory");
 		return -EFAULT;
 	}
-	return hc_found_ohci (dev->irq, (void *) mem_base);
+	return hc_found_ohci (dev, dev->irq, (void *) mem_base);
 } 
 
 /*-------------------------------------------------------------------------*/
@@ -1721,50 +1734,26 @@
 
 /*-------------------------------------------------------------------------*/
  
-#ifdef CONFIG_APM
-static int handle_apm_event (apm_event_t event) 
+static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-	static int down = 0;
-	ohci_t * ohci;
-	struct list_head * ohci_l;
-	
-	switch (event) {
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-		if (down) {
-			dbg("received extra suspend event");
-			break;
-		}
-		for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) {
-			ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list);
+	ohci_t * ohci = (ohci_t*) dev->data;
+	if (ohci) {
+		switch (rqst) {
+		case PM_SUSPEND:
 			dbg("USB-Bus suspend: %p", ohci);
 			writel (ohci->hc_control = 0xFF, &ohci->regs->control);
-		}
-		wait_ms (10);
-		down = 1;
-		break;
-	case APM_NORMAL_RESUME:
-	case APM_CRITICAL_RESUME:
-		if (!down) {
-			dbg("received bogus resume event");
+			wait_ms (10);
 			break;
-		}
-		for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) {
-			ohci = list_entry(ohci_l, ohci_t, ohci_hcd_list);
+		case PM_RESUME:
 			dbg("USB-Bus resume: %p", ohci);
 			writel (ohci->hc_control = 0x7F, &ohci->regs->control);
-		}		
-		wait_ms (20);
-		for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) {
-			ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list);
+			wait_ms (20);
 			writel (ohci->hc_control = 0xBF, &ohci->regs->control);
+			break;
 		}
-		down = 0;
-		break;
 	}
 	return 0;
 }
-#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -1779,10 +1768,6 @@
 		if (hc_start_ohci(dev) >= 0) ret = 0;
 	}
     
-#ifdef CONFIG_APM
-	apm_register_callback (&handle_apm_event);
-#endif
-
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_register_sleep_notifier (&ohci_sleep_notifier);
 #endif  
@@ -1803,9 +1788,7 @@
 {	
 	ohci_t * ohci;
 	
-#ifdef CONFIG_APM
-	apm_unregister_callback (&handle_apm_event);
-#endif
+	pm_unregister_all (handle_pm_event);
 
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_unregister_sleep_notifier (&ohci_sleep_notifier);
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.42/linux/drivers/usb/usb-serial.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/usb-serial.c	Mon Feb  7 19:14:42 2000
@@ -14,6 +14,17 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (02/05/2000) gkh
+ *	Added initial framework for the Keyspan PDA serial converter so that
+ *	Brian Warner has a place to put his code.
+ *	Made the ezusb specific functions generic enough that different
+ *	devices can use them (whiteheat and keyspan_pda both need them).
+ *	Split out a whole bunch of structure and other stuff to a seperate
+ *	usb-serial.h file.
+ *	Made the Visor connection messages a little more understandable, now
+ *	that Miles Lott (milos@insync.net) has gotten the Generic channel to
+ *	work. Also made them always show up in the log file.
+ * 
  * (01/25/2000) gkh
  *	Added initial framework for FTDI serial converter so that Bill Ryder
  *	has a place to put his code.
@@ -138,385 +149,12 @@
 #include "whiteheat.h"		/* firmware for the ConnectTech WhiteHEAT device */
 #endif
 
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
-MODULE_DESCRIPTION("USB Serial Driver");
-
-#ifdef CONFIG_USB_SERIAL_GENERIC
-static __u16	vendor	= 0x05f9;
-static __u16	product	= 0xffff;
-MODULE_PARM(vendor, "i");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "i");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
-#endif
+#include "usb-serial.h"
 
 
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
 static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
 
-
-/* USB Serial devices vendor ids and device ids that this driver supports */
-#define BELKIN_VENDOR_ID		0x056c
-#define BELKIN_SERIAL_CONVERTER_ID	0x8007
-#define PERACOM_VENDOR_ID		0x0565
-#define PERACOM_SERIAL_CONVERTER_ID	0x0001
-#define CONNECT_TECH_VENDOR_ID		0x0710
-#define CONNECT_TECH_FAKE_WHITE_HEAT_ID	0x0001
-#define CONNECT_TECH_WHITE_HEAT_ID	0x8001
-#define HANDSPRING_VENDOR_ID		0x082d
-#define HANDSPRING_VISOR_ID		0x0100
-#define FTDI_VENDOR_ID			0x0403
-#define FTDI_SERIAL_CONVERTER_ID	0x8372
-
-#define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
-#define SERIAL_TTY_MINORS	16	/* Actually we are allowed 255, but this is good for now */
-
-
-#define MAX_NUM_PORTS	8	/* The maximum number of ports one device can grab at once */
-
-struct usb_serial {
-	struct usb_device *		dev;
-	struct usb_serial_device_type *	type;
-	void *				irq_handle;
-	unsigned int			irqpipe;
-	struct tty_struct *		tty;			/* the coresponding tty for this device */
-	unsigned char			minor;
-	unsigned char			num_ports;		/* the number of ports this device has */
-	char				active[MAX_NUM_PORTS];	/* someone has this device open */
-
-	char			num_interrupt_in;		/* number of interrupt in endpoints we have */
-	__u8			interrupt_in_interval[MAX_NUM_PORTS];
-	unsigned char *		interrupt_in_buffer[MAX_NUM_PORTS];
-	struct urb		control_urb[MAX_NUM_PORTS];
-
-	char			num_bulk_in;			/* number of bulk in endpoints we have */
-	unsigned char *		bulk_in_buffer[MAX_NUM_PORTS];
-	struct urb		read_urb[MAX_NUM_PORTS];
-
-	char			num_bulk_out;			/* number of bulk out endpoints we have */
-	unsigned char *		bulk_out_buffer[MAX_NUM_PORTS];
-	int			bulk_out_size[MAX_NUM_PORTS];
-	struct urb		write_urb[MAX_NUM_PORTS];
-};
-
-
-#define MUST_HAVE_NOT	0x01
-#define MUST_HAVE	0x02
-#define DONT_CARE	0x03
-
-#define	HAS		0x02
-#define HAS_NOT		0x01
-
-#define NUM_DONT_CARE	(-1)
-
-/* local function prototypes */
-static int serial_open (struct tty_struct *tty, struct file * filp);
-static void serial_close (struct tty_struct *tty, struct file * filp);
-static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static int serial_write_room (struct tty_struct *tty);
-static int serial_chars_in_buffer (struct tty_struct *tty);
-static void serial_throttle (struct tty_struct * tty);
-static void serial_unthrottle (struct tty_struct * tty);
-
-
-/* This structure defines the individual serial converter. */
-struct usb_serial_device_type {
-	char	*name;
-	__u16	*idVendor;
-	__u16	*idProduct;
-	char	needs_interrupt_in;
-	char	needs_bulk_in;
-	char	needs_bulk_out;
-	char	num_interrupt_in;
-	char	num_bulk_in;
-	char	num_bulk_out;
-	char	num_ports;		/* number of serial ports this device has */
-
-	/* function call to make before accepting driver */
-	int (*startup) (struct usb_serial *serial);	/* return 0 to continue initialization, anything else to abort */
-	
-	/* serial function calls */
-	int  (*open)(struct tty_struct * tty, struct file * filp);
-	void (*close)(struct tty_struct * tty, struct file * filp);
-	int  (*write)(struct tty_struct * tty, int from_user,const unsigned char *buf, int count);
-	int  (*write_room)(struct tty_struct *tty);
-	int  (*chars_in_buffer)(struct tty_struct *tty);
-	void (*throttle)(struct tty_struct * tty);
-	void (*unthrottle)(struct tty_struct * tty);
-};
-
-
-/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
-/* need to always compile these in, as some of the other devices use these functions as their own. */
-static int  generic_serial_open		(struct tty_struct *tty, struct file *filp);
-static void generic_serial_close	(struct tty_struct *tty, struct file *filp);
-static int  generic_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static int  generic_write_room		(struct tty_struct *tty);
-static int  generic_chars_in_buffer	(struct tty_struct *tty);
-
-#ifdef CONFIG_USB_SERIAL_GENERIC
-/* All of the device info needed for the Generic Serial Converter */
-static struct usb_serial_device_type generic_device = {
-	name:			"Generic",
-	idVendor:		&vendor,		/* use the user specified vendor id */
-	idProduct:		&product,		/* use the user specified product id */
-	needs_interrupt_in:	DONT_CARE,		/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,		/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,		/* don't have to have a bulk out endpoint */
-	num_interrupt_in:	NUM_DONT_CARE,
-	num_bulk_in:		NUM_DONT_CARE,
-	num_bulk_out:		NUM_DONT_CARE,
-	num_ports:		1,
-	open:			generic_serial_open,
-	close:			generic_serial_close,
-	write:			generic_serial_write,
-	write_room:		generic_write_room,
-	chars_in_buffer:	generic_chars_in_buffer,
-};
-#endif
-
-#if defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM)
-/* function prototypes for the eTek type converters (this includes Belkin and Peracom) */
-static int  etek_serial_open		(struct tty_struct *tty, struct file *filp);
-static void etek_serial_close		(struct tty_struct *tty, struct file *filp);
-#endif
-
-#ifdef CONFIG_USB_SERIAL_BELKIN
-/* All of the device info needed for the Belkin Serial Converter */
-static __u16	belkin_vendor_id	= BELKIN_VENDOR_ID;
-static __u16	belkin_product_id	= BELKIN_SERIAL_CONVERTER_ID;
-static struct usb_serial_device_type belkin_device = {
-	name:			"Belkin",
-	idVendor:		&belkin_vendor_id,	/* the Belkin vendor id */
-	idProduct:		&belkin_product_id,	/* the Belkin serial converter product id */
-	needs_interrupt_in:	MUST_HAVE,		/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_interrupt_in:	1,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			etek_serial_open,
-	close:			etek_serial_close,
-	write:			generic_serial_write,
-	write_room:		generic_write_room,
-	chars_in_buffer:	generic_chars_in_buffer,
-};
-#endif
-
-
-#ifdef CONFIG_USB_SERIAL_PERACOM
-/* All of the device info needed for the Peracom Serial Converter */
-static __u16	peracom_vendor_id	= PERACOM_VENDOR_ID;
-static __u16	peracom_product_id	= PERACOM_SERIAL_CONVERTER_ID;
-static struct usb_serial_device_type peracom_device = {
-	name:			"Peracom",
-	idVendor:		&peracom_vendor_id,	/* the Peracom vendor id */
-	idProduct:		&peracom_product_id,	/* the Peracom serial converter product id */
-	needs_interrupt_in:	MUST_HAVE,		/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_ports:		1,
-	num_interrupt_in:	1,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	open:			etek_serial_open,
-	close:			etek_serial_close,
-	write:			generic_serial_write,
-	write_room:		generic_write_room,
-	chars_in_buffer:	generic_chars_in_buffer,
-};
-#endif
-
-
-#ifdef CONFIG_USB_SERIAL_WHITEHEAT
-/* function prototypes for the Connect Tech WhiteHEAT serial converter */
-static int  whiteheat_serial_open	(struct tty_struct *tty, struct file *filp);
-static void whiteheat_serial_close	(struct tty_struct *tty, struct file *filp);
-static void whiteheat_throttle		(struct tty_struct *tty);
-static void whiteheat_unthrottle	(struct tty_struct *tty);
-static int  whiteheat_startup		(struct usb_serial *serial);
-
-/* All of the device info needed for the Connect Tech WhiteHEAT */
-static __u16	connecttech_vendor_id			= CONNECT_TECH_VENDOR_ID;
-static __u16	connecttech_whiteheat_fake_product_id	= CONNECT_TECH_FAKE_WHITE_HEAT_ID;
-static __u16	connecttech_whiteheat_product_id	= CONNECT_TECH_WHITE_HEAT_ID;
-static struct usb_serial_device_type whiteheat_fake_device = {
-	name:			"Connect Tech - WhiteHEAT - (prerenumeration)",
-	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
-	idProduct:		&connecttech_whiteheat_fake_product_id,	/* the White Heat initial product id */
-	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
-	num_interrupt_in:	NUM_DONT_CARE,
-	num_bulk_in:		NUM_DONT_CARE,
-	num_bulk_out:		NUM_DONT_CARE,
-	startup:		whiteheat_startup	
-};
-static struct usb_serial_device_type whiteheat_device = {
-	name:			"Connect Tech - WhiteHEAT",
-	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
-	idProduct:		&connecttech_whiteheat_product_id,	/* the White Heat real product id */
-	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
-	num_interrupt_in:	NUM_DONT_CARE,
-	num_bulk_in:		NUM_DONT_CARE,
-	num_bulk_out:		NUM_DONT_CARE,
-	num_ports:		4,
-	open:			whiteheat_serial_open,
-	close:			whiteheat_serial_close,
-	write:			generic_serial_write,
-	write_room:		generic_write_room,
-	chars_in_buffer:	generic_chars_in_buffer,
-	throttle:		whiteheat_throttle,
-	unthrottle:		whiteheat_unthrottle
-};
-#endif
-
-
-#ifdef CONFIG_USB_SERIAL_VISOR
-
-/****************************************************************************
- * Handspring Visor Vendor specific request codes (bRequest values)
- * A big thank you to Handspring for providing the following information.
- * If anyone wants the original file where these values and structures came
- * from, send email to <greg@kroah.com>.
- ****************************************************************************/
-
-/****************************************************************************
- * VISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
- * are available to be transfered to the host for the specified endpoint.
- * Currently this is not used, and always returns 0x0001
- ****************************************************************************/
-#define VISOR_REQUEST_BYTES_AVAILABLE		0x01
-
-/****************************************************************************
- * VISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
- * is now closing the pipe. An empty packet is sent in response.
- ****************************************************************************/
-#define VISOR_CLOSE_NOTIFICATION		0x02
-
-/****************************************************************************
- * VISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
- * get the endpoints used by the connection.
- ****************************************************************************/
-#define VISOR_GET_CONNECTION_INFORMATION	0x03
-
-
-/****************************************************************************
- * VISOR_GET_CONNECTION_INFORMATION returns data in the following format
- ****************************************************************************/
-struct visor_connection_info {
-	__u16	num_ports;
-	struct {
-		__u8	port_function_id;
-		__u8	port;
-	} connections[2];
-};
-
-
-/* struct visor_connection_info.connection[x].port defines: */
-#define VISOR_ENDPOINT_1		0x01
-#define VISOR_ENDPOINT_2		0x02
-
-/* struct visor_connection_info.connection[x].port_function_id defines: */
-#define VISOR_FUNCTION_GENERIC		0x00
-#define VISOR_FUNCTION_DEBUGGER		0x01
-#define VISOR_FUNCTION_HOTSYNC		0x02
-#define VISOR_FUNCTION_CONSOLE		0x03
-#define VISOR_FUNCTION_REMOTE_FILE_SYS	0x04
-
-
-/* function prototypes for a handspring visor */
-static int  visor_serial_open		(struct tty_struct *tty, struct file *filp);
-static void visor_serial_close		(struct tty_struct *tty, struct file *filp);
-static void visor_throttle		(struct tty_struct *tty);
-static void visor_unthrottle		(struct tty_struct *tty);
-static int  visor_startup		(struct usb_serial *serial);
-
-/* All of the device info needed for the Handspring Visor */
-static __u16	handspring_vendor_id	= HANDSPRING_VENDOR_ID;
-static __u16	handspring_product_id	= HANDSPRING_VISOR_ID;
-static struct usb_serial_device_type handspring_device = {
-	name:			"Handspring Visor",
-	idVendor:		&handspring_vendor_id,	/* the Handspring vendor ID */
-	idProduct:		&handspring_product_id,	/* the Handspring Visor product id */
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_interrupt_in:	0,
-	num_bulk_in:		2,
-	num_bulk_out:		2,
-	num_ports:		2,
-	open:			visor_serial_open,
-	close:			visor_serial_close,
-	write:			generic_serial_write,
-	write_room:		generic_write_room,
-	chars_in_buffer:	generic_chars_in_buffer,
-	throttle:		visor_throttle,
-	unthrottle:		visor_unthrottle,
-	startup:		visor_startup
-};
-#endif
-
-
-#ifdef CONFIG_USB_SERIAL_FTDI
-/* function prototypes for a FTDI serial converter */
-static int  ftdi_serial_open	(struct tty_struct *tty, struct file *filp);
-static void ftdi_serial_close	(struct tty_struct *tty, struct file *filp);
-
-/* All of the device info needed for the Handspring Visor */
-static __u16	ftdi_vendor_id	= FTDI_VENDOR_ID;
-static __u16	ftdi_product_id	= FTDI_SERIAL_CONVERTER_ID;
-static struct usb_serial_device_type ftdi_device = {
-	name:			"FTDI",
-	idVendor:		&ftdi_vendor_id,	/* the FTDI vendor ID */
-	idProduct:		&ftdi_product_id,	/* the FTDI product id */
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_interrupt_in:	0,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			ftdi_serial_open,
-	close:			ftdi_serial_close,
-	write:			generic_serial_write,
-	write_room:		generic_write_room,
-	chars_in_buffer:	generic_chars_in_buffer
-};
-#endif
-
-/* To add support for another serial converter, create a usb_serial_device_type
-   structure for that device, and add it to this list, making sure that the last
-   entry is NULL. */
-static struct usb_serial_device_type *usb_serial_devices[] = {
-#ifdef CONFIG_USB_SERIAL_GENERIC
-	&generic_device,
-#endif
-#ifdef CONFIG_USB_SERIAL_WHITEHEAT
-	&whiteheat_fake_device,
-	&whiteheat_device,
-#endif
-#ifdef CONFIG_USB_SERIAL_BELKIN
-	&belkin_device,
-#endif
-#ifdef CONFIG_USB_SERIAL_PERACOM
-	&peracom_device,
-#endif
-#ifdef CONFIG_USB_SERIAL_VISOR
-	&handspring_device,
-#endif
-#ifdef CONFIG_USB_SERIAL_FTDI
-	&ftdi_device,
-#endif
-	NULL
-};
-
-
 static struct usb_driver usb_serial_driver = {
 	"serial",
 	usb_serial_probe,
@@ -532,8 +170,6 @@
 
 
 
-#define SERIAL_PTR_EMPTY ((void *)(-1))
-
 static struct usb_serial *get_serial_by_minor (int minor)
 {
 	int i;
@@ -592,6 +228,42 @@
 }
 
 
+#ifdef USES_EZUSB_FUNCTIONS
+/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
+#define CPUCS_REG    0x7F92
+
+static int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
+{
+	int result;
+	unsigned char *transfer_buffer =  kmalloc (length, GFP_KERNEL);
+
+//	dbg("ezusb_writememory %x, %d", address, length);
+
+	if (!transfer_buffer) {
+		err("ezusb_writememory: kmalloc(%d) failed.", length);
+		return -ENOMEM;
+	}
+	memcpy (transfer_buffer, data, length);
+	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 300);
+	kfree (transfer_buffer);
+	return result;
+}
+
+
+static int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+{
+	int	response;
+	dbg("ezusb_set_reset: %d", reset_bit);
+	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+	if (response < 0) {
+		err("ezusb_set_reset %d failed", reset_bit);
+	}
+	return (response);
+}
+
+#endif	/* USES_EZUSB_FUNCTIONS */
+
+
 static void serial_read_bulk (struct urb *urb)
 {
 	struct usb_serial *serial = (struct usb_serial *)urb->context;
@@ -606,9 +278,16 @@
 		return;
 	}
 
-	if (urb->actual_length)
-		dbg("%d %s", urb->actual_length, data);
-
+#ifdef DEBUG
+	if (urb->actual_length) {
+		printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length);
+		for (i = 0; i < urb->actual_length; ++i) {
+			printk ("0x%.2x ", data[i]);
+		}
+		printk ("\n");
+	}
+#endif
+	
 	if (urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
 			 tty_insert_flip_char(tty, data[i], 0);
@@ -988,38 +667,6 @@
 }
 
 
-static int whiteheat_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
-{
-	int result;
-	unsigned char *transfer_buffer =  kmalloc (length, GFP_KERNEL);
-
-//	dbg("whiteheat_writememory %x, %d", address, length);
-
-	if (!transfer_buffer) {
-		err("whiteheat_writememory: kmalloc(%d) failed.", length);
-		return -ENOMEM;
-	}
-	memcpy (transfer_buffer, data, length);
-	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 300);
-	kfree (transfer_buffer);
-	return result;
-}
-
-/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
-#define CPUCS_REG    0x7F92
-
-static int whiteheat_set_reset (struct usb_serial *serial, unsigned char reset_bit)
-{
-	int	response;
-	dbg("whiteheat_set_reset: %d", reset_bit);
-	response = whiteheat_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
-	if (response < 0) {
-		err("whiteheat_set_reset %d failed", reset_bit);
-	}
-	return (response);
-}
-
-
 /* steps to download the firmware to the WhiteHEAT device:
  - hold the reset (by writing to the reset bit of the CPUCS register)
  - download the VEND_AX.HEX file to the chip using VENDOR_REQUEST-ANCHOR_LOAD
@@ -1040,52 +687,52 @@
 	
 	dbg("whiteheat_startup");
 	
-	response = whiteheat_set_reset (serial, 1);
+	response = ezusb_set_reset (serial, 1);
 
 	record = &whiteheat_loader[0];
 	while (record->address != 0xffff) {
-		response = whiteheat_writememory (serial, record->address, 
+		response = ezusb_writememory (serial, record->address, 
 				(unsigned char *)record->data, record->data_size, 0xa0);
 		if (response < 0) {
-			err("whiteheat_writememory failed for loader (%d %04X %p %d)", 
+			err("ezusb_writememory failed for loader (%d %04X %p %d)", 
 				response, record->address, record->data, record->data_size);
 			break;
 		}
 		++record;
 	}
 
-	response = whiteheat_set_reset (serial, 0);
+	response = ezusb_set_reset (serial, 0);
 
 	record = &whiteheat_firmware[0];
 	while (record->address < 0x1b40) {
 		++record;
 	}
 	while (record->address != 0xffff) {
-		response = whiteheat_writememory (serial, record->address, 
+		response = ezusb_writememory (serial, record->address, 
 				(unsigned char *)record->data, record->data_size, 0xa0);
 		if (response < 0) {
-			err("whiteheat_writememory failed for first firmware step (%d %04X %p %d)", 
+			err("ezusb_writememory failed for first firmware step (%d %04X %p %d)", 
 				response, record->address, record->data, record->data_size);
 			break;
 		}
 		++record;
 	}
 	
-	response = whiteheat_set_reset (serial, 1);
+	response = ezusb_set_reset (serial, 1);
 
 	record = &whiteheat_firmware[0];
 	while (record->address < 0x1b40) {
-		response = whiteheat_writememory (serial, record->address, 
+		response = ezusb_writememory (serial, record->address, 
 				(unsigned char *)record->data, record->data_size, 0xa0);
 		if (response < 0) {
-			err("whiteheat_writememory failed for second firmware step (%d %04X %p %d)", 
+			err("ezusb_writememory failed for second firmware step (%d %04X %p %d)", 
 				response, record->address, record->data, record->data_size);
 			break;
 		}
 		++record;
 	}
 
-	response = whiteheat_set_reset (serial, 0);
+	response = ezusb_set_reset (serial, 0);
 
 	/* we want this device to fail to have a driver assigned to it. */
 	return (1);
@@ -1190,10 +837,9 @@
 	if (response < 0) {
 		err("visor_startup: error getting connection information");
 	} else {
-#ifdef DEBUG
 		struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
 		char *string;
-		dbg("%s: Number of ports: %d", serial->type->name, connection_info->num_ports);
+		info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports);
 		for (i = 0; i < connection_info->num_ports; ++i) {
 			switch (connection_info->connections[i].port_function_id) {
 				case VISOR_FUNCTION_GENERIC:
@@ -1212,9 +858,8 @@
 					string = "unknown";
 					break;	
 			}
-			dbg("%s: port %d, is for %s", serial->type->name, connection_info->connections[i].port, string);
+			info("%s: port %d, is for %s use and is bound to ttyUSB%d", serial->type->name, connection_info->connections[i].port, string, serial->minor + i);
 		}
-#endif
 	}
 
 	/* ask for the number of bytes available, but ignore the response as it is broken */
@@ -1280,6 +925,64 @@
 
 
 #endif
+
+
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
+/*****************************************************************************
+ * Keyspan PDA specific driver functions
+ *****************************************************************************/
+static int keyspan_pda_serial_open (struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("keyspan_pda_serial_open port %d", port);
+
+	if (serial->active[port]) {
+		dbg ("device already open");
+		return -EINVAL;
+	}
+	serial->active[port] = 1;
+ 
+	/*Start reading from the device*/
+	if (usb_submit_urb(&serial->read_urb[port]))
+		dbg("usb_submit_urb(read bulk) failed");
+
+	/* Need to do device specific setup here (control lines, baud rate, etc.) */
+	/* FIXME */
+
+	return (0);
+}
+
+
+static void keyspan_pda_serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("keyspan_pda_serial_close port %d", port);
+	
+	/* Need to change the control lines here */
+	/* FIXME */
+	
+	/* shutdown our bulk reads and writes */
+	usb_unlink_urb (&serial->write_urb[port]);
+	usb_unlink_urb (&serial->read_urb[port]);
+	serial->active[port] = 0;
+}
+
+
+static int  keyspan_pda_startup (struct usb_serial *serial)
+{
+	dbg("keyspan_pda_startup");
+
+	/* download the firmware here ... */
+	/* FIXME */
+
+	/* we want this device to fail to have a driver assigned to it. */
+	return (1);
+}
+#endif	/* CONFIG_USB_SERIAL_KEYSPAN_PDA */
 
 
 /*****************************************************************************
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usb-serial.h linux/drivers/usb/usb-serial.h
--- v2.3.42/linux/drivers/usb/usb-serial.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/usb-serial.h	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,459 @@
+/*
+ * USB Serial Converter driver
+ *
+ *	(C) Copyright (C) 1999, 2000
+ *	    Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *	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.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ */
+
+
+#ifndef __LINUX_USB_SERIAL_H
+#define __LINUX_USB_SERIAL_H
+
+#include <linux/config.h>
+
+/* Module information */
+MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
+MODULE_DESCRIPTION("USB Serial Driver");
+
+#ifdef CONFIG_USB_SERIAL_GENERIC
+static __u16	vendor	= 0x05f9;
+static __u16	product	= 0xffff;
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+#endif
+
+
+/* USB Serial devices vendor ids and device ids that this driver supports */
+#define BELKIN_VENDOR_ID		0x056c
+#define BELKIN_SERIAL_CONVERTER_ID	0x8007
+#define PERACOM_VENDOR_ID		0x0565
+#define PERACOM_SERIAL_CONVERTER_ID	0x0001
+#define CONNECT_TECH_VENDOR_ID		0x0710
+#define CONNECT_TECH_FAKE_WHITE_HEAT_ID	0x0001
+#define CONNECT_TECH_WHITE_HEAT_ID	0x8001
+#define HANDSPRING_VENDOR_ID		0x082d
+#define HANDSPRING_VISOR_ID		0x0100
+#define FTDI_VENDOR_ID			0x0403
+#define FTDI_SERIAL_CONVERTER_ID	0x8372
+#define KEYSPAN_VENDOR_ID		0x06cd
+#define KEYSPAN_PDA_FAKE_ID		0x0103
+#define KEYSPAN_PDA_ID			0x0103
+
+#define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
+#define SERIAL_TTY_MINORS	16	/* Actually we are allowed 255, but this is good for now */
+
+
+#define MAX_NUM_PORTS	8	/* The maximum number of ports one device can grab at once */
+
+struct usb_serial {
+	struct usb_device *		dev;
+	struct usb_serial_device_type *	type;
+	void *				irq_handle;
+	unsigned int			irqpipe;
+	struct tty_struct *		tty;			/* the coresponding tty for this device */
+	unsigned char			minor;
+	unsigned char			num_ports;		/* the number of ports this device has */
+	char				active[MAX_NUM_PORTS];	/* someone has this device open */
+
+	char			num_interrupt_in;		/* number of interrupt in endpoints we have */
+	__u8			interrupt_in_interval[MAX_NUM_PORTS];
+	unsigned char *		interrupt_in_buffer[MAX_NUM_PORTS];
+	struct urb		control_urb[MAX_NUM_PORTS];
+
+	char			num_bulk_in;			/* number of bulk in endpoints we have */
+	unsigned char *		bulk_in_buffer[MAX_NUM_PORTS];
+	struct urb		read_urb[MAX_NUM_PORTS];
+
+	char			num_bulk_out;			/* number of bulk out endpoints we have */
+	unsigned char *		bulk_out_buffer[MAX_NUM_PORTS];
+	int			bulk_out_size[MAX_NUM_PORTS];
+	struct urb		write_urb[MAX_NUM_PORTS];
+};
+
+
+#define MUST_HAVE_NOT	0x01
+#define MUST_HAVE	0x02
+#define DONT_CARE	0x03
+
+#define	HAS		0x02
+#define HAS_NOT		0x01
+
+#define NUM_DONT_CARE	(-1)
+
+/* local function prototypes */
+static int serial_open (struct tty_struct *tty, struct file * filp);
+static void serial_close (struct tty_struct *tty, struct file * filp);
+static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
+static int serial_write_room (struct tty_struct *tty);
+static int serial_chars_in_buffer (struct tty_struct *tty);
+static void serial_throttle (struct tty_struct * tty);
+static void serial_unthrottle (struct tty_struct * tty);
+
+
+/* This structure defines the individual serial converter. */
+struct usb_serial_device_type {
+	char	*name;
+	__u16	*idVendor;
+	__u16	*idProduct;
+	char	needs_interrupt_in;
+	char	needs_bulk_in;
+	char	needs_bulk_out;
+	char	num_interrupt_in;
+	char	num_bulk_in;
+	char	num_bulk_out;
+	char	num_ports;		/* number of serial ports this device has */
+
+	/* function call to make before accepting driver */
+	int (*startup) (struct usb_serial *serial);	/* return 0 to continue initialization, anything else to abort */
+	
+	/* serial function calls */
+	int  (*open)(struct tty_struct * tty, struct file * filp);
+	void (*close)(struct tty_struct * tty, struct file * filp);
+	int  (*write)(struct tty_struct * tty, int from_user,const unsigned char *buf, int count);
+	int  (*write_room)(struct tty_struct *tty);
+	int  (*chars_in_buffer)(struct tty_struct *tty);
+	void (*throttle)(struct tty_struct * tty);
+	void (*unthrottle)(struct tty_struct * tty);
+};
+
+
+/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
+/* need to always compile these in, as some of the other devices use these functions as their own. */
+static int  generic_serial_open		(struct tty_struct *tty, struct file *filp);
+static void generic_serial_close	(struct tty_struct *tty, struct file *filp);
+static int  generic_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static int  generic_write_room		(struct tty_struct *tty);
+static int  generic_chars_in_buffer	(struct tty_struct *tty);
+
+#ifdef CONFIG_USB_SERIAL_GENERIC
+/* All of the device info needed for the Generic Serial Converter */
+static struct usb_serial_device_type generic_device = {
+	name:			"Generic",
+	idVendor:		&vendor,		/* use the user specified vendor id */
+	idProduct:		&product,		/* use the user specified product id */
+	needs_interrupt_in:	DONT_CARE,		/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,		/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,		/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	num_ports:		1,
+	open:			generic_serial_open,
+	close:			generic_serial_close,
+	write:			generic_serial_write,
+	write_room:		generic_write_room,
+	chars_in_buffer:	generic_chars_in_buffer,
+};
+#endif
+
+#if defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM)
+/* function prototypes for the eTek type converters (this includes Belkin and Peracom) */
+static int  etek_serial_open		(struct tty_struct *tty, struct file *filp);
+static void etek_serial_close		(struct tty_struct *tty, struct file *filp);
+#endif
+
+#ifdef CONFIG_USB_SERIAL_BELKIN
+/* All of the device info needed for the Belkin Serial Converter */
+static __u16	belkin_vendor_id	= BELKIN_VENDOR_ID;
+static __u16	belkin_product_id	= BELKIN_SERIAL_CONVERTER_ID;
+static struct usb_serial_device_type belkin_device = {
+	name:			"Belkin",
+	idVendor:		&belkin_vendor_id,	/* the Belkin vendor id */
+	idProduct:		&belkin_product_id,	/* the Belkin serial converter product id */
+	needs_interrupt_in:	MUST_HAVE,		/* this device must have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
+	num_interrupt_in:	1,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			etek_serial_open,
+	close:			etek_serial_close,
+	write:			generic_serial_write,
+	write_room:		generic_write_room,
+	chars_in_buffer:	generic_chars_in_buffer,
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_PERACOM
+/* All of the device info needed for the Peracom Serial Converter */
+static __u16	peracom_vendor_id	= PERACOM_VENDOR_ID;
+static __u16	peracom_product_id	= PERACOM_SERIAL_CONVERTER_ID;
+static struct usb_serial_device_type peracom_device = {
+	name:			"Peracom",
+	idVendor:		&peracom_vendor_id,	/* the Peracom vendor id */
+	idProduct:		&peracom_product_id,	/* the Peracom serial converter product id */
+	needs_interrupt_in:	MUST_HAVE,		/* this device must have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
+	num_ports:		1,
+	num_interrupt_in:	1,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	open:			etek_serial_open,
+	close:			etek_serial_close,
+	write:			generic_serial_write,
+	write_room:		generic_write_room,
+	chars_in_buffer:	generic_chars_in_buffer,
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
+/* function prototypes for the Connect Tech WhiteHEAT serial converter */
+static int  whiteheat_serial_open	(struct tty_struct *tty, struct file *filp);
+static void whiteheat_serial_close	(struct tty_struct *tty, struct file *filp);
+static void whiteheat_throttle		(struct tty_struct *tty);
+static void whiteheat_unthrottle	(struct tty_struct *tty);
+static int  whiteheat_startup		(struct usb_serial *serial);
+
+/* All of the device info needed for the Connect Tech WhiteHEAT */
+static __u16	connecttech_vendor_id			= CONNECT_TECH_VENDOR_ID;
+static __u16	connecttech_whiteheat_fake_product_id	= CONNECT_TECH_FAKE_WHITE_HEAT_ID;
+static __u16	connecttech_whiteheat_product_id	= CONNECT_TECH_WHITE_HEAT_ID;
+static struct usb_serial_device_type whiteheat_fake_device = {
+	name:			"Connect Tech - WhiteHEAT - (prerenumeration)",
+	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
+	idProduct:		&connecttech_whiteheat_fake_product_id,	/* the White Heat initial product id */
+	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	startup:		whiteheat_startup	
+};
+static struct usb_serial_device_type whiteheat_device = {
+	name:			"Connect Tech - WhiteHEAT",
+	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
+	idProduct:		&connecttech_whiteheat_product_id,	/* the White Heat real product id */
+	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	num_ports:		4,
+	open:			whiteheat_serial_open,
+	close:			whiteheat_serial_close,
+	write:			generic_serial_write,
+	write_room:		generic_write_room,
+	chars_in_buffer:	generic_chars_in_buffer,
+	throttle:		whiteheat_throttle,
+	unthrottle:		whiteheat_unthrottle
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_VISOR
+
+/****************************************************************************
+ * Handspring Visor Vendor specific request codes (bRequest values)
+ * A big thank you to Handspring for providing the following information.
+ * If anyone wants the original file where these values and structures came
+ * from, send email to <greg@kroah.com>.
+ ****************************************************************************/
+
+/****************************************************************************
+ * VISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
+ * are available to be transfered to the host for the specified endpoint.
+ * Currently this is not used, and always returns 0x0001
+ ****************************************************************************/
+#define VISOR_REQUEST_BYTES_AVAILABLE		0x01
+
+/****************************************************************************
+ * VISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
+ * is now closing the pipe. An empty packet is sent in response.
+ ****************************************************************************/
+#define VISOR_CLOSE_NOTIFICATION		0x02
+
+/****************************************************************************
+ * VISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
+ * get the endpoints used by the connection.
+ ****************************************************************************/
+#define VISOR_GET_CONNECTION_INFORMATION	0x03
+
+
+/****************************************************************************
+ * VISOR_GET_CONNECTION_INFORMATION returns data in the following format
+ ****************************************************************************/
+struct visor_connection_info {
+	__u16	num_ports;
+	struct {
+		__u8	port_function_id;
+		__u8	port;
+	} connections[2];
+};
+
+
+/* struct visor_connection_info.connection[x].port defines: */
+#define VISOR_ENDPOINT_1		0x01
+#define VISOR_ENDPOINT_2		0x02
+
+/* struct visor_connection_info.connection[x].port_function_id defines: */
+#define VISOR_FUNCTION_GENERIC		0x00
+#define VISOR_FUNCTION_DEBUGGER		0x01
+#define VISOR_FUNCTION_HOTSYNC		0x02
+#define VISOR_FUNCTION_CONSOLE		0x03
+#define VISOR_FUNCTION_REMOTE_FILE_SYS	0x04
+
+
+/* function prototypes for a handspring visor */
+static int  visor_serial_open		(struct tty_struct *tty, struct file *filp);
+static void visor_serial_close		(struct tty_struct *tty, struct file *filp);
+static void visor_throttle		(struct tty_struct *tty);
+static void visor_unthrottle		(struct tty_struct *tty);
+static int  visor_startup		(struct usb_serial *serial);
+
+/* All of the device info needed for the Handspring Visor */
+static __u16	handspring_vendor_id	= HANDSPRING_VENDOR_ID;
+static __u16	handspring_product_id	= HANDSPRING_VISOR_ID;
+static struct usb_serial_device_type handspring_device = {
+	name:			"Handspring Visor",
+	idVendor:		&handspring_vendor_id,	/* the Handspring vendor ID */
+	idProduct:		&handspring_product_id,	/* the Handspring Visor product id */
+	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
+	num_interrupt_in:	0,
+	num_bulk_in:		2,
+	num_bulk_out:		2,
+	num_ports:		2,
+	open:			visor_serial_open,
+	close:			visor_serial_close,
+	write:			generic_serial_write,
+	write_room:		generic_write_room,
+	chars_in_buffer:	generic_chars_in_buffer,
+	throttle:		visor_throttle,
+	unthrottle:		visor_unthrottle,
+	startup:		visor_startup
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_FTDI
+/* function prototypes for a FTDI serial converter */
+static int  ftdi_serial_open	(struct tty_struct *tty, struct file *filp);
+static void ftdi_serial_close	(struct tty_struct *tty, struct file *filp);
+
+/* All of the device info needed for the Handspring Visor */
+static __u16	ftdi_vendor_id	= FTDI_VENDOR_ID;
+static __u16	ftdi_product_id	= FTDI_SERIAL_CONVERTER_ID;
+static struct usb_serial_device_type ftdi_device = {
+	name:			"FTDI",
+	idVendor:		&ftdi_vendor_id,	/* the FTDI vendor ID */
+	idProduct:		&ftdi_product_id,	/* the FTDI product id */
+	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
+	num_interrupt_in:	0,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			ftdi_serial_open,
+	close:			ftdi_serial_close,
+	write:			generic_serial_write,
+	write_room:		generic_write_room,
+	chars_in_buffer:	generic_chars_in_buffer
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
+/* function prototypes for a FTDI serial converter */
+static int  keyspan_pda_serial_open	(struct tty_struct *tty, struct file *filp);
+static void keyspan_pda_serial_close	(struct tty_struct *tty, struct file *filp);
+static int  keyspan_pda_startup		(struct usb_serial *serial);
+
+/* All of the device info needed for the Handspring Visor */
+static __u16	keyspan_vendor_id		= KEYSPAN_VENDOR_ID;
+static __u16	keyspan_pda_fake_product_id	= KEYSPAN_PDA_FAKE_ID;
+static __u16	keyspan_pda_product_id		= KEYSPAN_PDA_ID;
+static struct usb_serial_device_type keyspan_pda_fake_device = {
+	name:			"Keyspan PDA - (prerenumeration)",
+	idVendor:		&keyspan_vendor_id,		/* the Keyspan PDA vendor ID */
+	idProduct:		&keyspan_pda_fake_product_id,	/* the Keyspan PDA initial product id */
+	needs_interrupt_in:	DONT_CARE,			/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,			/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,			/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	startup:		keyspan_pda_startup	
+};
+static struct usb_serial_device_type keyspan_pda_device = {
+	name:			"Keyspan PDA",
+	idVendor:		&keyspan_vendor_id,		/* the Keyspan PDA vendor ID */
+	idProduct:		&keyspan_pda_product_id,	/* the Keyspan PDA product id */
+	needs_interrupt_in:	MUST_HAVE_NOT,			/* this device must not have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,			/* this device must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,			/* this device must have a bulk out endpoint */
+	num_interrupt_in:	0,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			keyspan_pda_serial_open,
+	close:			keyspan_pda_serial_close,
+	write:			generic_serial_write,
+	write_room:		generic_write_room,
+	chars_in_buffer:	generic_chars_in_buffer
+};
+#endif
+
+/* To add support for another serial converter, create a usb_serial_device_type
+   structure for that device, and add it to this list, making sure that the last
+   entry is NULL. */
+static struct usb_serial_device_type *usb_serial_devices[] = {
+#ifdef CONFIG_USB_SERIAL_GENERIC
+	&generic_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
+	&whiteheat_fake_device,
+	&whiteheat_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_BELKIN
+	&belkin_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_PERACOM
+	&peracom_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_VISOR
+	&handspring_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_FTDI
+	&ftdi_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
+	&keyspan_pda_fake_device,
+	&keyspan_pda_device,
+#endif
+	NULL
+};
+
+
+/* determine if we should include the EzUSB loader functions */
+#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_WHITEHEAT)
+	#define	USES_EZUSB_FUNCTIONS
+#else
+	#undef 	USES_EZUSB_FUNCTIONS
+#endif
+
+
+/* used to mark that a pointer is empty (and not NULL) */
+#define SERIAL_PTR_EMPTY ((void *)(-1))
+
+
+#endif	/* ifdef __LINUX_USB_SERIAL_H */
+
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- v2.3.42/linux/drivers/usb/usb-uhci.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/usb-uhci.c	Tue Feb  8 18:49:45 2000
@@ -12,10 +12,9 @@
  * (C) Copyright 1999 Johannes Erdfelt
  * (C) Copyright 1999 Randy Dunlap
  *
- * $Id: usb-uhci.c,v 1.169 2000/01/20 19:50:11 acher Exp $
+ * $Id: usb-uhci.c,v 1.185 2000/02/05 21:29:19 acher Exp $
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -34,73 +33,93 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 
+/* This enables more detailed sanity checks in submit_iso */
+//#define ISO_SANITY_CHECK
+
 /* This enables debug printks */
-//#define DEBUG
+#define DEBUG
+
 /* This enables all symbols to be exported, to ease debugging oopses */
-#define DEBUG_SYMBOLS
+//#define DEBUG_SYMBOLS
+
 /* This enables an extra UHCI slab for memory debugging */
-//#define DEBUG_SLAB
+#define DEBUG_SLAB
 
 #include "usb.h"
 #include "usb-uhci.h"
 #include "usb-uhci-debug.h"
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-static int handle_apm_event (apm_event_t event);
-#endif
+#undef DEBUG
+#undef dbg
+#define dbg(format, arg...) do {} while (0)
+
+#include <linux/pm.h>
+static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data);
 
 #ifdef DEBUG_SYMBOLS
-#define _static
-#ifndef EXPORT_SYMTAB
-#define EXPORT_SYMTAB
-#endif
+	#define _static
+	#ifndef EXPORT_SYMTAB
+	#define EXPORT_SYMTAB
+	#endif
 #else
-#define _static static
+	#define _static static
 #endif
 
 #ifdef DEBUG_SLAB
-static kmem_cache_t *uhci_desc_kmem;
-static kmem_cache_t *urb_priv_kmem;
+	static kmem_cache_t *uhci_desc_kmem;
+	static kmem_cache_t *urb_priv_kmem;
 #endif
 
-_static int rh_submit_urb (purb_t purb);
-_static int rh_unlink_urb (purb_t purb);
-static puhci_t devs = NULL;
+#define USE_CTRL_DEPTH_FIRST 1  // 0: Breadth first, 1: Depth first (standard)
+
+//#define USE_RECLAMATION_LOOP
+
+_static int rh_submit_urb (urb_t *urb);
+_static int rh_unlink_urb (urb_t *urb);
+_static int delete_qh (uhci_t *s, uhci_desc_t *qh);
+
+static uhci_t *devs = NULL;
 
 /* used by userspace UHCI data structure dumper */
-puhci_t *uhci_devices = &devs;
+uhci_t **uhci_devices = &devs;
+
+/*-------------------------------------------------------------------*/
+// Cleans up collected QHs
+void clean_descs(uhci_t *s, int force)
+{
+	struct list_head *q;
+	uhci_desc_t *qh;
+	int now=UHCI_GET_CURRENT_FRAME(s);
+
+	q=s->free_desc.prev;
 
+	while (q != &s->free_desc) {
+		qh = list_entry (q, uhci_desc_t, horizontal);
+		if ((qh->last_used!=now) || force)
+			delete_qh(s,qh);
+		q=qh->horizontal.prev;
+	}
+}
 /*-------------------------------------------------------------------*/
-_static void queue_urb (puhci_t s, struct list_head *p, int do_lock)
+_static void queue_urb (uhci_t *s, struct list_head *p)
 {
 	unsigned long flags=0;
 
-	if (do_lock) 
-		spin_lock_irqsave (&s->urb_list_lock, flags);
-		
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+
 	list_add_tail (p, &s->urb_list);
 	
-	if (do_lock) 
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
+	spin_unlock_irqrestore (&s->urb_list_lock, flags);
 }
 
 /*-------------------------------------------------------------------*/
-_static void dequeue_urb (puhci_t s, struct list_head *p, int do_lock)
+_static void dequeue_urb (uhci_t *s, struct list_head *p)
 {
-	unsigned long flags=0;
-	
-	if (do_lock) 
-		spin_lock_irqsave (&s->urb_list_lock, flags);
-
 	list_del (p);
 
-	if (do_lock) 
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
 }
-
 /*-------------------------------------------------------------------*/
-_static int alloc_td (puhci_desc_t * new, int flags)
+_static int alloc_td (uhci_desc_t ** new, int flags)
 {
 #ifdef DEBUG_SLAB
 	*new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
@@ -109,10 +128,8 @@
 #endif
 	if (!*new)
 		return -ENOMEM;
-	
-	memset (*new, 0, sizeof (uhci_desc_t));
+	 memset (*new, 0, sizeof (uhci_desc_t));
 	(*new)->hw.td.link = UHCI_PTR_TERM | (flags & UHCI_PTR_BITS);	// last by default
-
 	(*new)->type = TD_TYPE;
 	mb();
 	INIT_LIST_HEAD (&(*new)->vertical);
@@ -122,7 +139,7 @@
 }
 /*-------------------------------------------------------------------*/
 /* insert td at last position in td-list of qh (vertical) */
-_static int insert_td (puhci_t s, puhci_desc_t qh, puhci_desc_t new, int flags)
+_static int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags)
 {
 	uhci_desc_t *prev;
 	unsigned long xxx;
@@ -131,14 +148,14 @@
 
 	list_add_tail (&new->vertical, &qh->vertical);
 
-	if (qh->hw.qh.element & UHCI_PTR_TERM) {
+	prev = list_entry (new->vertical.prev, uhci_desc_t, vertical);
+
+	if (qh == prev ) {
 		// virgin qh without any tds
-		qh->hw.qh.element = virt_to_bus (new);	/* QH's cannot have the DEPTH bit set */
+		qh->hw.qh.element = virt_to_bus (new);
 	}
 	else {
-		// already tds inserted 
-		prev = list_entry (new->vertical.prev, uhci_desc_t, vertical);
-		// implicitely remove TERM bit of prev
+		// already tds inserted, implicitely remove TERM bit of prev
 		prev->hw.td.link = virt_to_bus (new) | (flags & UHCI_PTR_DEPTH);
 	}
 	mb();
@@ -148,61 +165,62 @@
 }
 /*-------------------------------------------------------------------*/
 /* insert new_td after td (horizontal) */
-_static int insert_td_horizontal (puhci_t s, puhci_desc_t td, puhci_desc_t new, int flags)
+_static int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new)
 {
 	uhci_desc_t *next;
-	unsigned long xxx;
+	unsigned long flags;
 	
-	spin_lock_irqsave (&s->td_lock, xxx);
+	spin_lock_irqsave (&s->td_lock, flags);
 
 	next = list_entry (td->horizontal.next, uhci_desc_t, horizontal);
-	new->hw.td.link = td->hw.td.link;
-	mb();
 	list_add (&new->horizontal, &td->horizontal);
+	new->hw.td.link = td->hw.td.link;
 	td->hw.td.link = virt_to_bus (new);
 	mb();
-	spin_unlock_irqrestore (&s->td_lock, xxx);	
+	spin_unlock_irqrestore (&s->td_lock, flags);	
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int unlink_td (puhci_t s, puhci_desc_t element)
+_static int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink)
 {
 	uhci_desc_t *next, *prev;
 	int dir = 0;
-	unsigned long xxx;
+	unsigned long flags;
 	
-	spin_lock_irqsave (&s->td_lock, xxx);
+	spin_lock_irqsave (&s->td_lock, flags);
 	
 	next = list_entry (element->vertical.next, uhci_desc_t, vertical);
 	
 	if (next == element) {
 		dir = 1;
-		next = list_entry (element->horizontal.next, uhci_desc_t, horizontal);
 		prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal);
 	}
-	else {
+	else 
 		prev = list_entry (element->vertical.prev, uhci_desc_t, vertical);
-	}
-	
-	if (prev->type == TD_TYPE)
-		prev->hw.td.link = element->hw.td.link;
-	else
-		prev->hw.qh.element = element->hw.td.link;
 	
+	if (phys_unlink) {
+		// really remove HW linking
+		if (prev->type == TD_TYPE)
+			prev->hw.td.link = element->hw.td.link;
+		else
+			prev->hw.qh.element = element->hw.td.link;	
+	}
+
+	element->hw.td.link=UHCI_PTR_TERM;
 	mb ();
-	
+
 	if (dir == 0)
 		list_del (&element->vertical);
 	else
 		list_del (&element->horizontal);
 	
-	spin_unlock_irqrestore (&s->td_lock, xxx);	
+	spin_unlock_irqrestore (&s->td_lock, flags);	
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int delete_desc (puhci_desc_t element)
+_static int delete_desc (uhci_desc_t *element)
 {
 #ifdef DEBUG_SLAB
 	kmem_cache_free(uhci_desc_kmem, element);
@@ -213,7 +231,7 @@
 }
 /*-------------------------------------------------------------------*/
 // Allocates qh element
-_static int alloc_qh (puhci_desc_t * new)
+_static int alloc_qh (uhci_desc_t ** new)
 {
 #ifdef DEBUG_SLAB
 	*new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
@@ -222,11 +240,11 @@
 #endif	
 	if (!*new)
 		return -ENOMEM;
-	
 	memset (*new, 0, sizeof (uhci_desc_t));
 	(*new)->hw.qh.head = UHCI_PTR_TERM;
 	(*new)->hw.qh.element = UHCI_PTR_TERM;
 	(*new)->type = QH_TYPE;
+	
 	mb();
 	INIT_LIST_HEAD (&(*new)->horizontal);
 	INIT_LIST_HEAD (&(*new)->vertical);
@@ -238,19 +256,18 @@
 /*-------------------------------------------------------------------*/
 // inserts new qh before/after the qh at pos
 // flags: 0: insert before pos, 1: insert after pos (for low speed transfers)
-_static int insert_qh (puhci_t s, puhci_desc_t pos, puhci_desc_t new, int flags)
+_static int insert_qh (uhci_t *s, uhci_desc_t *pos, uhci_desc_t *new, int order)
 {
-	puhci_desc_t old;
-	unsigned long xxx;
+	uhci_desc_t *old;
+	unsigned long flags;
 
-	spin_lock_irqsave (&s->qh_lock, xxx);
+	spin_lock_irqsave (&s->qh_lock, flags);
 
-	if (!flags) {
+	if (!order) {
 		// (OLD) (POS) -> (OLD) (NEW) (POS)
 		old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal);
 		list_add_tail (&new->horizontal, &pos->horizontal);
 		new->hw.qh.head = MAKE_QH_ADDR (pos) ;
-		mb();
 		if (!(old->hw.qh.head & UHCI_PTR_TERM))
 			old->hw.qh.head = MAKE_QH_ADDR (new) ;
 	}
@@ -259,57 +276,57 @@
 		old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal);
 		list_add (&new->horizontal, &pos->horizontal);
 		new->hw.qh.head = MAKE_QH_ADDR (old);
-		mb();
 		pos->hw.qh.head = MAKE_QH_ADDR (new) ;
 	}
 
 	mb ();
 	
-	spin_unlock_irqrestore (&s->qh_lock, xxx);
+	spin_unlock_irqrestore (&s->qh_lock, flags);
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int unlink_qh (puhci_t s, puhci_desc_t element)
+_static int unlink_qh (uhci_t *s, uhci_desc_t *element)
 {
-	puhci_desc_t next, prev;
-	unsigned long xxx;
+	uhci_desc_t  *prev;
+	unsigned long flags;
 
-	spin_lock_irqsave (&s->qh_lock, xxx);
+	spin_lock_irqsave (&s->qh_lock, flags);
 	
-	next = list_entry (element->horizontal.next, uhci_desc_t, horizontal);
 	prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal);
 	prev->hw.qh.head = element->hw.qh.head;
+
+	list_del(&element->horizontal);
+
 	mb ();
-	list_del (&element->horizontal);
-	
-	spin_unlock_irqrestore (&s->qh_lock, xxx);
+	spin_unlock_irqrestore (&s->qh_lock, flags);
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int delete_qh (puhci_t s, puhci_desc_t qh)
+_static int delete_qh (uhci_t *s, uhci_desc_t *qh)
 {
-	puhci_desc_t td;
+	uhci_desc_t *td;
 	struct list_head *p;
-
-	list_del (&qh->horizontal);
 	
+	list_del (&qh->horizontal);
+
 	while ((p = qh->vertical.next) != &qh->vertical) {
 		td = list_entry (p, uhci_desc_t, vertical);
-		unlink_td (s, td);
+		dbg("unlink td @ %p",td);
+		unlink_td (s, td, 0); // no physical unlink
 		delete_desc (td);
 	}
-	
+
 	delete_desc (qh);
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static void clean_td_chain (puhci_desc_t td)
+_static void clean_td_chain (uhci_desc_t *td)
 {
 	struct list_head *p;
-	puhci_desc_t td1;
+	uhci_desc_t *td1;
 
 	if (!td)
 		return;
@@ -323,13 +340,15 @@
 }
 /*-------------------------------------------------------------------*/
 // Removes ALL qhs in chain (paranoia!)
-_static void cleanup_skel (puhci_t s)
+_static void cleanup_skel (uhci_t *s)
 {
 	unsigned int n;
-	puhci_desc_t td;
+	uhci_desc_t *td;
 
 	dbg("cleanup_skel");
-	
+
+	clean_descs(s,1);
+
 	for (n = 0; n < 8; n++) {
 		td = s->int_chain[n];
 		clean_td_chain (td);
@@ -349,13 +368,15 @@
 	if (s->control_chain) {
 		// completed init_skel?
 		struct list_head *p;
-		puhci_desc_t qh, qh1;
+		uhci_desc_t *qh, *qh1;
 
 		qh = s->control_chain;
 		while ((p = qh->horizontal.next) != &qh->horizontal) {
 			qh1 = list_entry (p, uhci_desc_t, horizontal);
+			dbg("delete_qh @ %p",qh1);
 			delete_qh (s, qh1);
 		}
+			dbg("delete_qh last @ %p",qh);
 		delete_qh (s, qh);
 	}
 	else {
@@ -371,10 +392,10 @@
 /*-------------------------------------------------------------------*/
 // allocates framelist and qh-skeletons
 // only HW-links provide continous linking, SW-links stay in their domain (ISO/INT)
-_static int init_skel (puhci_t s)
+_static int init_skel (uhci_t *s)
 {
 	int n, ret;
-	puhci_desc_t qh, td;
+	uhci_desc_t *qh, *td;
 	
 	dbg("init_skel");
 	
@@ -386,7 +407,7 @@
 	memset (s->framelist, 0, 4096);
 
 	dbg("allocating iso desc pointer list");
-	s->iso_td = (puhci_desc_t *) kmalloc (1024 * sizeof (puhci_desc_t), GFP_KERNEL);
+	s->iso_td = (uhci_desc_t **) kmalloc (1024 * sizeof (uhci_desc_t*), GFP_KERNEL);
 	
 	if (!s->iso_td)
 		goto init_skel_cleanup;
@@ -429,13 +450,19 @@
 	
 	insert_qh (s, s->bulk_chain, qh, 0);
 	s->control_chain = qh;
+
+#ifdef USE_RECLAMATION_LOOP
+	s->chain_end->hw.qh.head=virt_to_bus(s->control_chain)|UHCI_PTR_QH;
+	info("Using loop for bandwidth reclamation.");
+#endif
+
 	for (n = 0; n < 8; n++)
 		s->int_chain[n] = 0;
 
 	dbg("allocating skeleton INT-TDs");
 	
 	for (n = 0; n < 8; n++) {
-		puhci_desc_t td;
+		uhci_desc_t *td;
 
 		alloc_td (&td, 0);
 		if (!td)
@@ -456,12 +483,12 @@
 		int m, o;
 		dbg("framelist[%i]=%x",n,s->framelist[n]);
 		if ((n&127)==127) 
-			((puhci_desc_t) s->iso_td[n])->hw.td.link = virt_to_bus(s->int_chain[0]);
+			((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus(s->int_chain[0]);
 		else {
 			for (o = 1, m = 2; m <= 128; o++, m += m) {
 				// n&(m-1) = n%m
 				if ((n & (m - 1)) == ((m - 1) / 2)) {
-					((puhci_desc_t) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]);
+					((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]);
 				}
 			}
 		}
@@ -478,7 +505,7 @@
 }
 
 /*-------------------------------------------------------------------*/
-_static void fill_td (puhci_desc_t td, int status, int info, __u32 buffer)
+_static void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer)
 {
 	td->hw.td.status = status;
 	td->hw.td.info = info;
@@ -489,15 +516,16 @@
 //                         LOW LEVEL STUFF
 //          assembles QHs und TDs for control, bulk and iso
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_control_urb (purb_t purb)
+_static int uhci_submit_control_urb (urb_t *urb)
 {
-	puhci_desc_t qh, td;
-	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
-	purb_priv_t purb_priv = purb->hcpriv;
+	uhci_desc_t *qh, *td;
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv;
 	unsigned long destination, status;
-	int maxsze = usb_maxpacket (purb->dev, purb->pipe, usb_pipeout (purb->pipe));
+	int maxsze = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
 	unsigned long len, bytesrequested;
 	char *data;
+	int depth_first=USE_CTRL_DEPTH_FIRST;  // UHCI descriptor chasing method
 
 	dbg("uhci_submit_control start");
 	alloc_qh (&qh);		// alloc qh for this request
@@ -505,7 +533,7 @@
 	if (!qh)
 		return -ENOMEM;
 
-	alloc_td (&td, UHCI_PTR_DEPTH);		// get td for setup stage
+	alloc_td (&td, UHCI_PTR_DEPTH * depth_first);		// get td for setup stage
 
 	if (!td) {
 		delete_qh (s, qh);
@@ -513,40 +541,42 @@
 	}
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (purb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
 
 	/* 3 errors */
-	status = (purb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE |
-		(purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE |
+		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
 
 	/*  Build the TD for the control request, try forever, 8 bytes of data */
-	fill_td (td, status, destination | (7 << 21), virt_to_bus (purb->setup_packet));
-
-	/* If direction is "send", change the frame from SETUP (0x2D)
-	   to OUT (0xE1). Else change it from SETUP to IN (0x69). */
-
-	destination ^= (USB_PID_SETUP ^ USB_PID_IN);	/* SETUP -> IN */
-	
-	if (usb_pipeout (purb->pipe))
-		destination ^= (USB_PID_IN ^ USB_PID_OUT);	/* IN -> OUT */
+	fill_td (td, status, destination | (7 << 21), virt_to_bus (urb->setup_packet));
 
 	insert_td (s, qh, td, 0);	// queue 'setup stage'-td in qh
 #if 0
-	dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", purb->pipe,
-		purb->setup_packet[0], purb->setup_packet[1], purb->setup_packet[2], purb->setup_packet[3],
-		purb->setup_packet[4], purb->setup_packet[5], purb->setup_packet[6], purb->setup_packet[7]);
+	dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", urb->pipe,
+		urb->setup_packet[0], urb->setup_packet[1], urb->setup_packet[2], urb->setup_packet[3],
+		urb->setup_packet[4], urb->setup_packet[5], urb->setup_packet[6], urb->setup_packet[7]);
 	//uhci_show_td(td);
 #endif
 
 	/*  Build the DATA TD's */
-	len = purb->transfer_buffer_length;
+	len = urb->transfer_buffer_length;
 	bytesrequested = len;
-	data = purb->transfer_buffer;
+	data = urb->transfer_buffer;
+
+	/* If direction is "send", change the frame from SETUP (0x2D)
+	   to OUT (0xE1). Else change it from SETUP to IN (0x69). */
+
+	destination &= ~UHCI_PID;
 	
+	if (usb_pipeout (urb->pipe))
+		destination |= USB_PID_OUT;
+	else
+		destination |= USB_PID_IN;	
+
 	while (len > 0) {
 		int pktsze = len;
 
-		alloc_td (&td, UHCI_PTR_DEPTH);
+		alloc_td (&td, UHCI_PTR_DEPTH * depth_first);
 		if (!td) {
 			delete_qh (s, qh);
 			return -ENOMEM;
@@ -560,7 +590,7 @@
 		fill_td (td, status, destination | ((pktsze - 1) << 21),
 			 virt_to_bus (data));	// Status, pktsze bytes of data
 
-		insert_td (s, qh, td, UHCI_PTR_DEPTH);	// queue 'data stage'-td in qh
+		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue 'data stage'-td in qh
 
 		data += pktsze;
 		len -= pktsze;
@@ -568,9 +598,10 @@
 
 	/*  Build the final TD for control status */
 	/* It's only IN if the pipe is out AND we aren't expecting data */
-	destination &= ~0xFF;
-	
-	if (usb_pipeout (purb->pipe) | (bytesrequested == 0))
+
+	destination &= ~UHCI_PID;
+
+	if (usb_pipeout (urb->pipe) || (bytesrequested == 0))
 		destination |= USB_PID_IN;
 	else
 		destination |= USB_PID_OUT;
@@ -583,23 +614,24 @@
 		delete_qh (s, qh);
 		return -ENOMEM;
 	}
+	status &=~TD_CTRL_SPD;
 
 	/* no limit on errors on final packet , 0 bytes of data */
 	fill_td (td, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),
 		 0);
 
-	insert_td (s, qh, td, UHCI_PTR_DEPTH);	// queue status td
+	insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue status td
 
+	list_add (&qh->desc_list, &urb_priv->desc_list);
 
-	list_add (&qh->desc_list, &purb_priv->desc_list);
+	urb->status = -EINPROGRESS;
+	queue_urb (s, &urb->urb_list);	// queue before inserting in desc chain
 
-	purb->status = USB_ST_URB_PENDING;
-	queue_urb (s, &purb->urb_list,1);	// queue before inserting in desc chain
+	qh->hw.qh.element&=~UHCI_PTR_TERM;
 
 	//uhci_show_queue(qh);
-
 	/* Start it up... put low speed first */
-	if (purb->pipe & TD_CTRL_LS)
+	if (urb->pipe & TD_CTRL_LS)
 		insert_qh (s, s->control_chain, qh, 1);	// insert after control chain
 	else
 		insert_qh (s, s->bulk_chain, qh, 0);	// insert before bulk chain
@@ -609,22 +641,26 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_bulk_urb (purb_t purb)
+_static int uhci_submit_bulk_urb (urb_t *urb)
 {
-	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
-	purb_priv_t purb_priv = purb->hcpriv;
-	puhci_desc_t qh, td;
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	uhci_desc_t *qh, *td;
 	unsigned long destination, status;
 	char *data;
-	unsigned int pipe = purb->pipe;
-	int maxsze = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
+	unsigned int pipe = urb->pipe;
+	int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
 	int info, len;
 
 	/* shouldn't the clear_halt be done in the USB core or in the client driver? - Thomas */
-	if (usb_endpoint_halted (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) &&
-	    usb_clear_halt (purb->dev, usb_pipeendpoint (pipe) | (pipe & USB_DIR_IN)))
+	if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) &&
+	    usb_clear_halt (urb->dev, usb_pipeendpoint (pipe) | (pipe & USB_DIR_IN)))
 		return -EPIPE;
-
+	if (urb->transfer_buffer_length < 0) {
+		err("Negative transfer length in submit_bulk");
+		return -EINVAL;
+	}
+	
 	if (!maxsze)
 		return -EMSGSIZE;
 	/* FIXME: should tell the client that the endpoint is invalid, i.e. not in the descriptor */
@@ -639,14 +675,14 @@
 
 	/* 3 errors */
 	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE |
-		((purb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27);
+		((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27);
 
 	/* Build the TDs for the bulk request */
-	len = purb->transfer_buffer_length;
-	data = purb->transfer_buffer;
+	len = urb->transfer_buffer_length;
+	data = urb->transfer_buffer;
 	dbg("uhci_submit_bulk_urb: pipe %x, len %d", pipe, len);
 	
-	while (len > 0) {
+	do {					// TBD: Really allow zero-length packets?
 		int pktsze = len;
 
 		alloc_td (&td, UHCI_PTR_DEPTH);
@@ -660,8 +696,8 @@
 			pktsze = maxsze;
 
 		// pktsze bytes of data 
-		info = destination | ((pktsze - 1) << 21) |
-			(usb_gettoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
+		info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
+			(usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
 
 		fill_td (td, status, info, virt_to_bus (data));
 
@@ -675,13 +711,15 @@
 		insert_td (s, qh, td, UHCI_PTR_DEPTH);
 		
 		/* Alternate Data0/1 (start with Data0) */
-		usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
-	}
+		usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+	} while (len > 0);
 
-	list_add (&qh->desc_list, &purb_priv->desc_list);
+	list_add (&qh->desc_list, &urb_priv->desc_list);
 
-	purb->status = USB_ST_URB_PENDING;
-	queue_urb (s, &purb->urb_list,1);
+	urb->status = -EINPROGRESS;
+	queue_urb (s, &urb->urb_list);
+	
+	qh->hw.qh.element&=~UHCI_PTR_TERM;
 
 	insert_qh (s, s->chain_end, qh, 0);	// insert before end marker
 	//uhci_show_queue(s->bulk_chain);
@@ -693,51 +731,50 @@
 // unlinks an urb by dequeuing its qh, waits some frames and forgets it
 // Problem: unlinking in interrupt requires waiting for one frame (udelay)
 // to allow the whole structures to be safely removed
-_static int uhci_unlink_urb (purb_t purb)
+_static int uhci_unlink_urb (urb_t *urb)
 {
-	puhci_t s;
-	puhci_desc_t qh;
-	puhci_desc_t td;
-	purb_priv_t purb_priv;
+	uhci_t *s;
+	uhci_desc_t *qh;
+	uhci_desc_t *td;
+	urb_priv_t *urb_priv;
 	unsigned long flags=0;
+
 	struct list_head *p;
 
-	if (!purb)		// you never know...
-		return -1;
+	if (!urb || !urb->dev)		// you never know...
+		return -EINVAL;
 
-	s = (puhci_t) purb->dev->bus->hcpriv;	// get pointer to uhci struct
+	s = (uhci_t*) urb->dev->bus->hcpriv;	// get pointer to uhci struct
 
-	if (usb_pipedevice (purb->pipe) == s->rh.devnum)
-		return rh_unlink_urb (purb);
+	if (usb_pipedevice (urb->pipe) == s->rh.devnum)
+		return rh_unlink_urb (urb);
 
-	if(!in_interrupt()) {
-		spin_lock_irqsave (&s->unlink_urb_lock, flags);		// do not allow interrupts
-	}
-	
-	//dbg("unlink_urb called %p",purb);
-	if (purb->status == USB_ST_URB_PENDING) {
+	if (!urb->hcpriv)		// you never know...
+		return -EINVAL;
+
+	//dbg("unlink_urb called %p",urb);
+
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+
+	if (urb->status == -EINPROGRESS) {
 		// URB probably still in work
-		purb_priv = purb->hcpriv;
-		dequeue_urb (s, &purb->urb_list,1);
-		purb->status = USB_ST_URB_KILLED;	// mark urb as killed
+		dequeue_urb (s, &urb->urb_list);
+		s->unlink_urb_done=1;
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);		
 		
-		if(!in_interrupt()) {
-			spin_unlock_irqrestore (&s->unlink_urb_lock, flags);	// allow interrupts from here
-		}
+		urb->status = -ENOENT;	// mark urb as killed		
+		urb_priv = urb->hcpriv;
 
-		switch (usb_pipetype (purb->pipe)) {
+		switch (usb_pipetype (urb->pipe)) {
 		case PIPE_ISOCHRONOUS:
 		case PIPE_INTERRUPT:
-			for (p = purb_priv->desc_list.next; p != &purb_priv->desc_list; p = p->next) {
+			for (p = urb_priv->desc_list.next; p != &urb_priv->desc_list; p = p->next) {
 				td = list_entry (p, uhci_desc_t, desc_list);
-				unlink_td (s, td);
+				unlink_td (s, td, 1);
 			}
 			// wait at least 1 Frame
-			if (in_interrupt ())
-				udelay (1000);
-			else
-				wait_ms(1);
-			while ((p = purb_priv->desc_list.next) != &purb_priv->desc_list) {
+			uhci_wait_ms(1);
+			while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) {
 				td = list_entry (p, uhci_desc_t, desc_list);
 				list_del (p);
 				delete_desc (td);
@@ -746,57 +783,51 @@
 
 		case PIPE_BULK:
 		case PIPE_CONTROL:
-			qh = list_entry (purb_priv->desc_list.next, uhci_desc_t, desc_list);
+			qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
 
 			unlink_qh (s, qh);	// remove this qh from qh-list
+			qh->last_used=UHCI_GET_CURRENT_FRAME(s);
+			list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion
 			// wait at least 1 Frame
-
-			if (in_interrupt ())
-				udelay (1000);
-			else
-				wait_ms(1);
-			delete_qh (s, qh);		// remove it physically
-
+			uhci_wait_ms(1);
 		}
 		
 #ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, purb->hcpriv);
+		kmem_cache_free(urb_priv_kmem, urb->hcpriv);
 #else
-		kfree (purb->hcpriv);
+		kfree (urb->hcpriv);
 #endif
-		if (purb->complete) {
+		if (urb->complete) {
 			dbg("unlink_urb: calling completion");
-			purb->complete ((struct urb *) purb);
-			usb_dec_dev_use (purb->dev);
+			urb->complete ((struct urb *) urb);
 		}
+		usb_dec_dev_use (urb->dev);
 		return 0;
 	}
-	else {
-		if(!in_interrupt())
-			spin_unlock_irqrestore (&s->unlink_urb_lock, flags);	// allow interrupts from here
-	}
-
+	else
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);
 	return 0;
 }
 /*-------------------------------------------------------------------*/
 // In case of ASAP iso transfer, search the URB-list for already queued URBs
 // for this EP and calculate the earliest start frame for the new
 // URB (easy seamless URB continuation!)
-_static int find_iso_limits (purb_t purb, unsigned int *start, unsigned int *end)
+_static int find_iso_limits (urb_t *urb, unsigned int *start, unsigned int *end)
 {
-	purb_t u, last_urb = NULL;
-	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
-	struct list_head *p = s->urb_list.next;
+	urb_t *u, *last_urb = NULL;
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	struct list_head *p;
 	int ret=-1;
 	unsigned long flags;
 	
 	spin_lock_irqsave (&s->urb_list_lock, flags);
+	p=s->urb_list.next;
 
 	for (; p != &s->urb_list; p = p->next) {
 		u = list_entry (p, urb_t, urb_list);
 		// look for pending URBs with identical pipe handle
 		// works only because iso doesn't toggle the data bit!
-		if ((purb->pipe == u->pipe) && (purb->dev == u->dev) && (u->status == USB_ST_URB_PENDING)) {
+		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS)) {
 			if (!last_urb)
 				*start = u->start_frame;
 			last_urb = u;
@@ -816,40 +847,40 @@
 /*-------------------------------------------------------------------*/
 // adjust start_frame according to scheduling constraints (ASAP etc)
 
-_static int iso_find_start (purb_t purb)
+_static int iso_find_start (urb_t *urb)
 {
-	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
 	unsigned int now;
 	unsigned int start_limit = 0, stop_limit = 0, queued_size;
 	int limits;
 
 	now = UHCI_GET_CURRENT_FRAME (s) & 1023;
 
-	if ((unsigned) purb->number_of_packets > 900)
+	if ((unsigned) urb->number_of_packets > 900)
 		return -EFBIG;
 	
-	limits = find_iso_limits (purb, &start_limit, &stop_limit);
+	limits = find_iso_limits (urb, &start_limit, &stop_limit);
 	queued_size = (stop_limit - start_limit) & 1023;
 
-	if (purb->transfer_flags & USB_ISO_ASAP) {
+	if (urb->transfer_flags & USB_ISO_ASAP) {
 		// first iso
 		if (limits) {
 			// 10ms setup should be enough //FIXME!
-			purb->start_frame = (now + 10) & 1023;
+			urb->start_frame = (now + 10) & 1023;
 		}
 		else {
-			purb->start_frame = stop_limit;		//seamless linkage
+			urb->start_frame = stop_limit;		//seamless linkage
 
-			if (((now - purb->start_frame) & 1023) <= (unsigned) purb->number_of_packets) {
-				dbg("iso_find_start: warning, ASAP gap, should not happen");
+			if (((now - urb->start_frame) & 1023) <= (unsigned) urb->number_of_packets) {
+				info("iso_find_start: gap in seamless isochronous scheduling");
 				dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x",
-					now, purb->start_frame, purb->number_of_packets, purb->pipe);
+					now, urb->start_frame, urb->number_of_packets, urb->pipe);
 // The following code is only for debugging purposes...
 #if 0
 				{
-					puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
+					uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
 					struct list_head *p;
-					purb_t u;
+					urb_t *u;
 					int a = -1, b = -1;
 					unsigned long flags;
 
@@ -858,7 +889,7 @@
 
 					for (; p != &s->urb_list; p = p->next) {
 						u = list_entry (p, urb_t, urb_list);
-						if (purb->dev != u->dev)
+						if (urb->dev != u->dev)
 							continue;
 						dbg("urb: pipe 0x%08x status %d start_frame %u number_of_packets %u",
 							u->pipe, u->status, u->start_frame, u->number_of_packets);
@@ -871,14 +902,14 @@
 					spin_unlock_irqrestore(&s->urb_list_lock, flags);
 				}
 #endif
-				purb->start_frame = (now + 5) & 1023;	// 5ms setup should be enough //FIXME!
+				urb->start_frame = (now + 5) & 1023;	// 5ms setup should be enough //FIXME!
 				//return -EAGAIN; //FIXME
 			}
 		}
 	}
 	else {
-		purb->start_frame &= 1023;
-		if (((now - purb->start_frame) & 1023) < (unsigned) purb->number_of_packets) {
+		urb->start_frame &= 1023;
+		if (((now - urb->start_frame) & 1023) < (unsigned) urb->number_of_packets) {
 			dbg("iso_find_start: now between start_frame and end");
 			return -EAGAIN;
 		}
@@ -888,10 +919,10 @@
 	if (limits)
 		return 0;
 
-	if (((purb->start_frame - start_limit) & 1023) < queued_size ||
-	    ((purb->start_frame + purb->number_of_packets - 1 - start_limit) & 1023) < queued_size) {
+	if (((urb->start_frame - start_limit) & 1023) < queued_size ||
+	    ((urb->start_frame + urb->number_of_packets - 1 - start_limit) & 1023) < queued_size) {
 		dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u",
-			purb->start_frame, purb->number_of_packets, start_limit, stop_limit);
+			urb->start_frame, urb->number_of_packets, start_limit, stop_limit);
 		return -EAGAIN;
 	}
 
@@ -902,43 +933,44 @@
 // ASAP-flag set implicitely
 // if period==0, the the transfer is only done once (usb_scsi need this...)
 
-_static int uhci_submit_int_urb (purb_t purb)
+_static int uhci_submit_int_urb (urb_t *urb)
 {
-	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
-	purb_priv_t purb_priv = purb->hcpriv;
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv;
 	int nint, n, ret;
-	puhci_desc_t td;
+	uhci_desc_t *td;
 	int status, destination;
 	int now;
 	int info;
-	unsigned int pipe = purb->pipe;
+	unsigned int pipe = urb->pipe;
 
 	//dbg("SUBMIT INT");
 
-	if (purb->interval < 0 || purb->interval >= 256)
+	if (urb->interval < 0 || urb->interval >= 256)
 		return -EINVAL;
 
-	if (purb->interval == 0)
+	if (urb->interval == 0)
 		nint = 0;
 	else {
 		for (nint = 0, n = 1; nint <= 8; nint++, n += n)	// round interval down to 2^n
 		 {
-			if (purb->interval < n) {
-				purb->interval = n / 2;
+			if (urb->interval < n) {
+				urb->interval = n / 2;
 				break;
 			}
 		}
 		nint--;
 	}
-	dbg("Rounded interval to %i, chain  %i", purb->interval, nint);
+
+	dbg("Rounded interval to %i, chain  %i", urb->interval, nint);
 
 	now = UHCI_GET_CURRENT_FRAME (s) & 1023;
-	purb->start_frame = now;	// remember start frame, just in case...
+	urb->start_frame = now;	// remember start frame, just in case...
 
-	purb->number_of_packets = 1;
+	urb->number_of_packets = 1;
 
 	// INT allows only one packet
-	if (purb->transfer_buffer_length > usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)))
+	if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)))
 		return -EINVAL;
 
 	ret = alloc_td (&td, UHCI_PTR_DEPTH);
@@ -947,55 +979,53 @@
 		return -ENOMEM;
 
 	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
-		(purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
 
-	destination = (purb->pipe & PIPE_DEVEP_MASK) | usb_packetid (purb->pipe) |
-		(((purb->transfer_buffer_length - 1) & 0x7ff) << 21);
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe) |
+		(((urb->transfer_buffer_length - 1) & 0x7ff) << 21);
 
 
-	info = destination | (usb_gettoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
+	info = destination | (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
 
-	fill_td (td, status, info, virt_to_bus (purb->transfer_buffer));
-	list_add_tail (&td->desc_list, &purb_priv->desc_list);
+	fill_td (td, status, info, virt_to_bus (urb->transfer_buffer));
+	list_add_tail (&td->desc_list, &urb_priv->desc_list);
 
-	purb->status = USB_ST_URB_PENDING;
-	queue_urb (s, &purb->urb_list,1);
+	urb->status = -EINPROGRESS;
+	queue_urb (s, &urb->urb_list);
 
-	insert_td_horizontal (s, s->int_chain[nint], td, UHCI_PTR_DEPTH);	// store in INT-TDs
+	insert_td_horizontal (s, s->int_chain[nint], td);	// store in INT-TDs
 
-	usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+	usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
 
 #if 0
-	td = tdm[purb->number_of_packets];
+	td = tdm[urb->number_of_packets];
 	fill_td (td, TD_CTRL_IOC, 0, 0);
-	insert_td_horizontal (s, s->iso_td[(purb->start_frame + (purb->number_of_packets) * purb->interval + 1) & 1023], td, UHCI_PTR_DEPTH);
-	list_add_tail (&td->desc_list, &purb_priv->desc_list);
+	insert_td_horizontal (s, s->iso_td[(urb->start_frame + (urb->number_of_packets) * urb->interval + 1) & 1023], td);
+	list_add_tail (&td->desc_list, &urb_priv->desc_list);
 #endif
 
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_iso_urb (purb_t purb)
+_static int uhci_submit_iso_urb (urb_t *urb)
 {
-	puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
-	purb_priv_t purb_priv = purb->hcpriv;
-	int pipe=purb->pipe;
-	int maxsze = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	int pipe=urb->pipe;
+	int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
 	int n, ret, last=0;
-	puhci_desc_t td, *tdm;
+	uhci_desc_t *td, **tdm;
 	int status, destination;
 	unsigned long flags;
-	spinlock_t lock;
 
-	spin_lock_init (&lock);
-	spin_lock_irqsave (&lock, flags);	// Disable IRQs to schedule all ISO-TDs in time
-
-	ret = iso_find_start (purb);	// adjusts purb->start_frame for later use
+	__save_flags(flags);
+	__cli();		      // Disable IRQs to schedule all ISO-TDs in time
+	ret = iso_find_start (urb);	// adjusts urb->start_frame for later use
 
 	if (ret)
 		goto err;
 
-	tdm = (puhci_desc_t *) kmalloc (purb->number_of_packets * sizeof (puhci_desc_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL);
+	tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL);
 
 	if (!tdm) {
 		ret = -ENOMEM;
@@ -1003,19 +1033,23 @@
 	}
 
 	// First try to get all TDs
-	for (n = 0; n < purb->number_of_packets; n++) {
-		dbg("n:%d purb->iso_frame_desc[n].length:%d", n, purb->iso_frame_desc[n].length);
-		if (!purb->iso_frame_desc[n].length) {
+	for (n = 0; n < urb->number_of_packets; n++) {
+		dbg("n:%d urb->iso_frame_desc[n].length:%d", n, urb->iso_frame_desc[n].length);
+		if (!urb->iso_frame_desc[n].length) {
 			// allows ISO striping by setting length to zero in iso_descriptor
 			tdm[n] = 0;
 			continue;
 		}
-		if(purb->iso_frame_desc[n].length > maxsze) {
-			err("submit_iso: purb->iso_frame_desc[%d].length(%d)>%d",n , purb->iso_frame_desc[n].length, maxsze);
+		#ifdef ISO_SANITY_CHECK
+		if(urb->iso_frame_desc[n].length > maxsze) {
+			err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze);
 			tdm[n] = 0;
-			continue;
+			ret=-EINVAL;
+			goto inval;
 		}
+		#endif
 		ret = alloc_td (&td, UHCI_PTR_DEPTH);
+	inval:
 		if (ret) {
 			int i;	// Cleanup allocated TDs
 
@@ -1023,20 +1057,19 @@
 				if (tdm[i])
 					kfree (tdm[i]);
 			kfree (tdm);
-			ret = -ENOMEM;
 			goto err;
 		}
 		last=n;
 		tdm[n] = td;
 	}
 
-	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;	//| (purb->transfer_flags&USB_DISABLE_SPD?0:TD_CTRL_SPD);
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;	//| (urb->transfer_flags&USB_DISABLE_SPD?0:TD_CTRL_SPD);
 
-	destination = (purb->pipe & PIPE_DEVEP_MASK) | usb_packetid (purb->pipe);
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe);
 
 	
 	// Queue all allocated TDs
-	for (n = 0; n < purb->number_of_packets; n++) {
+	for (n = 0; n < urb->number_of_packets; n++) {
 		td = tdm[n];
 		if (!td)
 			continue;
@@ -1044,45 +1077,47 @@
 		if (n  == last)
 			status |= TD_CTRL_IOC;
 
-		fill_td (td, status, destination | (((purb->iso_frame_desc[n].length - 1) & 0x7ff) << 21),
-			 virt_to_bus (purb->transfer_buffer + purb->iso_frame_desc[n].offset));
-		list_add_tail (&td->desc_list, &purb_priv->desc_list);
+		fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21),
+			 virt_to_bus (urb->transfer_buffer + urb->iso_frame_desc[n].offset));
+		list_add_tail (&td->desc_list, &urb_priv->desc_list);
 	
 		if (n == last) {
-			purb->status = USB_ST_URB_PENDING;
-			queue_urb (s, &purb->urb_list,1);
+			urb->status = -EINPROGRESS;
+			queue_urb (s, &urb->urb_list);
 		}
-		insert_td_horizontal (s, s->iso_td[(purb->start_frame + n) & 1023], td, UHCI_PTR_DEPTH);	// store in iso-tds
+		insert_td_horizontal (s, s->iso_td[(urb->start_frame + n) & 1023], td);	// store in iso-tds
 		//uhci_show_td(td);
 
 	}
 
 	kfree (tdm);
-	dbg("ISO-INT# %i, start %i, now %i", purb->number_of_packets, purb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
+	dbg("ISO-INT# %i, start %i, now %i", urb->number_of_packets, urb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
 	ret = 0;
 
       err:
-	spin_unlock_irqrestore (&lock, flags);
+	__restore_flags(flags);
 	return ret;
 
 }
 /*-------------------------------------------------------------------*/
-_static int search_dev_ep (puhci_t s, purb_t purb)
+_static int search_dev_ep (uhci_t *s, urb_t *urb)
 {
 	unsigned long flags;
-	struct list_head *p = s->urb_list.next;
-	purb_t tmp;
-	unsigned int mask = usb_pipecontrol(purb->pipe) ? (~USB_DIR_IN) : (~0);
+	struct list_head *p;
+	urb_t *tmp;
+	unsigned int mask = usb_pipecontrol(urb->pipe) ? (~USB_DIR_IN) : (~0);
 
 	dbg("search_dev_ep:");
 	spin_lock_irqsave (&s->urb_list_lock, flags);
+	p=s->urb_list.next;
+
 	for (; p != &s->urb_list; p = p->next) {
 		tmp = list_entry (p, urb_t, urb_list);
 		dbg("urb: %p", tmp);
 		// we can accept this urb if it is not queued at this time 
 		// or if non-iso transfer requests should be scheduled for the same device and pipe
-		if ((!usb_pipeisoc(purb->pipe) && tmp->dev == purb->dev && !((tmp->pipe ^ purb->pipe) & mask)) ||
-		    (purb == tmp)) {
+		if ((!usb_pipeisoc(urb->pipe) && tmp->dev == urb->dev && !((tmp->pipe ^ urb->pipe) & mask)) ||
+		    (urb == tmp)) {
 			spin_unlock_irqrestore (&s->urb_list_lock, flags);
 			return 1;	// found another urb already queued for processing
 		}
@@ -1091,76 +1126,78 @@
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static int uhci_submit_urb (purb_t purb)
+_static int uhci_submit_urb (urb_t *urb)
 {
-	puhci_t s;
-	purb_priv_t purb_priv;
+	uhci_t *s;
+	urb_priv_t *urb_priv;
 	int ret = 0;
 
-	if (!purb->dev || !purb->dev->bus)
+	if (!urb->dev || !urb->dev->bus)
 		return -ENODEV;
 
-	s = (puhci_t) purb->dev->bus->hcpriv;
-	//dbg("submit_urb: %p type %d",purb,usb_pipetype(purb->pipe));
+	s = (uhci_t*) urb->dev->bus->hcpriv;
+	//dbg("submit_urb: %p type %d",urb,usb_pipetype(urb->pipe));
 
-	if (usb_pipedevice (purb->pipe) == s->rh.devnum)
-		return rh_submit_urb (purb);	/* virtual root hub */
+	if (usb_pipedevice (urb->pipe) == s->rh.devnum)
+		return rh_submit_urb (urb);	/* virtual root hub */
 
-	usb_inc_dev_use (purb->dev);
+	usb_inc_dev_use (urb->dev);
 
-	if (search_dev_ep (s, purb)) {
-		usb_dec_dev_use (purb->dev);
+	if (search_dev_ep (s, urb)) {
+		usb_dec_dev_use (urb->dev);
 		return -ENXIO;	// urb already queued
 
 	}
 
 #ifdef DEBUG_SLAB
-	purb_priv = kmem_cache_alloc(urb_priv_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
+	urb_priv = kmem_cache_alloc(urb_priv_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
 #else
-	purb_priv = kmalloc (sizeof (urb_priv_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL);
+	urb_priv = kmalloc (sizeof (urb_priv_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL);
 #endif
-	if (!purb_priv) {
-		usb_dec_dev_use (purb->dev);
+	if (!urb_priv) {
+		usb_dec_dev_use (urb->dev);
 		return -ENOMEM;
 	}
 
-	purb->hcpriv = purb_priv;
-	INIT_LIST_HEAD (&purb_priv->desc_list);
-	purb_priv->short_control_packet=0;
-	dbg("submit_urb: scheduling %p", purb);
+	urb->hcpriv = urb_priv;
+	INIT_LIST_HEAD (&urb_priv->desc_list);
+	urb_priv->short_control_packet=0;
+	dbg("submit_urb: scheduling %p", urb);
 
-	switch (usb_pipetype (purb->pipe)) {
+	switch (usb_pipetype (urb->pipe)) {
 	case PIPE_ISOCHRONOUS:
-		ret = uhci_submit_iso_urb (purb);
+		ret = uhci_submit_iso_urb (urb);
 		break;
 	case PIPE_INTERRUPT:
-		ret = uhci_submit_int_urb (purb);
+		ret = uhci_submit_int_urb (urb);
 		break;
 	case PIPE_CONTROL:
-		//dump_urb (purb);
-		ret = uhci_submit_control_urb (purb);
+		//dump_urb (urb);
+		ret = uhci_submit_control_urb (urb);
 		break;
 	case PIPE_BULK:
-		ret = uhci_submit_bulk_urb (purb);
+		ret = uhci_submit_bulk_urb (urb);
 		break;
 	default:
 		ret = -EINVAL;
 	}
 
 	dbg("submit_urb: scheduled with ret: %d", ret);
-
-	if (ret != USB_ST_NOERROR) {
-		usb_dec_dev_use (purb->dev);
+	
+	
+	if (ret != 0) {
+		usb_dec_dev_use (urb->dev);
 #ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, purb_priv);
+		kmem_cache_free(urb_priv_kmem, urb_priv);
 #else
-		kfree (purb_priv);
+		kfree (urb_priv);
 #endif
 		return ret;
 	}
 /*
-	purb->status = USB_ST_URB_PENDING;
-	queue_urb (s, &purb->urb_list,1);
+	urb->status = -EINPROGRESS;
+	queue_urb (s, &urb->urb_list);
+
 	dbg("submit_urb: exit");
 */
 	return 0;
@@ -1243,12 +1280,11 @@
 
 /*-------------------------------------------------------------------------*/
 /* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
-_static int rh_send_irq (purb_t purb)
+_static int rh_send_irq (urb_t *urb)
 {
-
 	int len = 1;
 	int i;
-	puhci_t uhci = purb->dev->bus->hcpriv;
+	uhci_t *uhci = urb->dev->bus->hcpriv;
 	unsigned int io_addr = uhci->io_addr;
 	__u16 data = 0;
 
@@ -1257,52 +1293,52 @@
 		len = (i + 1) / 8 + 1;
 	}
 
-	*(__u16 *) purb->transfer_buffer = cpu_to_le16 (data);
-	purb->actual_length = len;
-	purb->status = USB_ST_NOERROR;
-
+	*(__u16 *) urb->transfer_buffer = cpu_to_le16 (data);
+	urb->actual_length = len;
+	urb->status = 0;
+	
 	if ((data > 0) && (uhci->rh.send != 0)) {
 		dbg("Root-Hub INT complete: port1: %x port2: %x data: %x",
 		     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data);
-		purb->complete (purb);
+		urb->complete (urb);
 
 	}
-	return USB_ST_NOERROR;
+	return 0;
 }
 
 /*-------------------------------------------------------------------------*/
 /* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
-_static int rh_init_int_timer (purb_t purb);
+_static int rh_init_int_timer (urb_t *urb);
 
 _static void rh_int_timer_do (unsigned long ptr)
 {
 	int len;
 
-	purb_t purb = (purb_t) ptr;
-	puhci_t uhci = purb->dev->bus->hcpriv;
+	urb_t *urb = (urb_t*) ptr;
+	uhci_t *uhci = urb->dev->bus->hcpriv;
 
 	if (uhci->rh.send) {
-		len = rh_send_irq (purb);
+		len = rh_send_irq (urb);
 		if (len > 0) {
-			purb->actual_length = len;
-			if (purb->complete)
-				purb->complete (purb);
+			urb->actual_length = len;
+			if (urb->complete)
+				urb->complete (urb);
 		}
 	}
-	rh_init_int_timer (purb);
+	rh_init_int_timer (urb);
 }
 
 /*-------------------------------------------------------------------------*/
 /* Root Hub INTs are polled by this timer */
-_static int rh_init_int_timer (purb_t purb)
+_static int rh_init_int_timer (urb_t *urb)
 {
-	puhci_t uhci = purb->dev->bus->hcpriv;
+	uhci_t *uhci = urb->dev->bus->hcpriv;
 
-	uhci->rh.interval = purb->interval;
+	uhci->rh.interval = urb->interval;
 	init_timer (&uhci->rh.rh_int_timer);
 	uhci->rh.rh_int_timer.function = rh_int_timer_do;
-	uhci->rh.rh_int_timer.data = (unsigned long) purb;
-	uhci->rh.rh_int_timer.expires = jiffies + (HZ * (purb->interval < 30 ? 30 : purb->interval)) / 1000;
+	uhci->rh.rh_int_timer.data = (unsigned long) urb;
+	uhci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
 	add_timer (&uhci->rh.rh_int_timer);
 
 	return 0;
@@ -1328,17 +1364,17 @@
  *************************/
 
 
-_static int rh_submit_urb (purb_t purb)
+_static int rh_submit_urb (urb_t *urb)
 {
-	struct usb_device *usb_dev = purb->dev;
-	puhci_t uhci = usb_dev->bus->hcpriv;
-	unsigned int pipe = purb->pipe;
-	devrequest *cmd = (devrequest *) purb->setup_packet;
-	void *data = purb->transfer_buffer;
-	int leni = purb->transfer_buffer_length;
+	struct usb_device *usb_dev = urb->dev;
+	uhci_t *uhci = usb_dev->bus->hcpriv;
+	unsigned int pipe = urb->pipe;
+	devrequest *cmd = (devrequest *) urb->setup_packet;
+	void *data = urb->transfer_buffer;
+	int leni = urb->transfer_buffer_length;
 	int len = 0;
 	int status = 0;
-	int stat = USB_ST_NOERROR;
+	int stat = 0;
 	int i;
 	unsigned int io_addr = uhci->io_addr;
 	__u16 cstatus;
@@ -1349,13 +1385,13 @@
 	__u16 wLength;
 
 	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
-		dbg("Root-Hub submit IRQ: every %d ms", purb->interval);
-		uhci->rh.urb = purb;
+		dbg("Root-Hub submit IRQ: every %d ms", urb->interval);
+		uhci->rh.urb = urb;
 		uhci->rh.send = 1;
-		uhci->rh.interval = purb->interval;
-		rh_init_int_timer (purb);
+		uhci->rh.interval = urb->interval;
+		rh_init_int_timer (urb);
 
-		return USB_ST_NOERROR;
+		return 0;
 	}
 
 
@@ -1455,12 +1491,12 @@
 			OK (0);
 		case (RH_PORT_RESET):
 			SET_RH_PORTSTAT (USBPORTSC_PR);
-			wait_ms (10);
+			uhci_wait_ms (10);
 			uhci->rh.c_p_r[wIndex - 1] = 1;
 			CLR_RH_PORTSTAT (USBPORTSC_PR);
 			udelay (10);
 			SET_RH_PORTSTAT (USBPORTSC_PE);
-			wait_ms (10);
+			uhci_wait_ms (10);
 			SET_RH_PORTSTAT (0xa);
 			OK (0);
 		case (RH_PORT_POWER):
@@ -1510,17 +1546,17 @@
 	dbg("Root-Hub stat port1: %x port2: %x",
 	     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2));
 
-	purb->actual_length = len;
-	purb->status = stat;
-	if (purb->complete)
-		purb->complete (purb);
-	return USB_ST_NOERROR;
+	urb->actual_length = len;
+	urb->status = stat;
+	if (urb->complete)
+		urb->complete (urb);
+	return 0;
 }
 /*-------------------------------------------------------------------------*/
 
-_static int rh_unlink_urb (purb_t purb)
+_static int rh_unlink_urb (urb_t *urb)
 {
-	puhci_t uhci = purb->dev->bus->hcpriv;
+	uhci_t *uhci = urb->dev->bus->hcpriv;
 
 	dbg("Root-Hub unlink IRQ");
 	uhci->rh.send = 0;
@@ -1538,7 +1574,7 @@
 _static int uhci_map_status (int status, int dir_out)
 {
 	if (!status)
-		return USB_ST_NOERROR;
+		return 0;
 	if (status & TD_CTRL_BITSTUFF)	/* Bitstuff error */
 		return -EPROTO;
 	if (status & TD_CTRL_CRCTIMEO) {	/* CRC/Timeout */
@@ -1556,7 +1592,7 @@
 	if (status & TD_CTRL_STALLED)	/* Stalled */
 		return -EPIPE;
 	if (status & TD_CTRL_ACTIVE)	/* Active */
-		return USB_ST_NOERROR;
+		return 0;
 
 	return -EPROTO;
 }
@@ -1569,8 +1605,42 @@
 	return 0;
 }
 
+_static void uhci_unlink_urbs(uhci_t *s, struct usb_device *usb_dev, int remove_all)
+{
+	unsigned long flags;
+	struct list_head *p;
+	struct list_head *p2;
+	urb_t *urb;
+
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+	p = s->urb_list.prev;	
+	while (p != &s->urb_list) {
+		p2 = p;
+		p = p->prev;
+		urb = list_entry (p2, urb_t, urb_list);
+		dbg("urb: %p", urb);
+		if (remove_all || (usb_dev == urb->dev)) {
+			warn("forced removing of queued URB %p due to disconnect",urb);
+			uhci_unlink_urb(urb);
+			urb->dev = NULL; // avoid further processing of this URB
+		}
+	}
+	spin_unlock_irqrestore (&s->urb_list_lock, flags);
+}
+
 _static int uhci_free_dev (struct usb_device *usb_dev)
 {
+	uhci_t *s;
+	
+	dbg("uhci_free_dev");	
+
+	if(!usb_dev || !usb_dev->bus || !usb_dev->bus->hcpriv)
+		return -EINVAL;
+	
+	s=(uhci_t*) usb_dev->bus->hcpriv;
+	
+	uhci_unlink_urbs(s, usb_dev, 0);
+
 	return 0;
 }
 
@@ -1581,7 +1651,7 @@
  */
 _static int uhci_get_current_frame_number (struct usb_device *usb_dev)
 {
-	return UHCI_GET_CURRENT_FRAME ((puhci_t) usb_dev->bus->hcpriv);
+	return UHCI_GET_CURRENT_FRAME ((uhci_t*) usb_dev->bus->hcpriv);
 }
 
 struct usb_operations uhci_device_operations =
@@ -1603,22 +1673,23 @@
  * when the transfered length fits exactly in maxsze-packets. A bit
  * more intelligence is needed to detect this and finish without error.
  */
-_static int process_transfer (puhci_t s, purb_t purb)
+
+_static int process_transfer (uhci_t *s, urb_t *urb)
 {
-	int ret = USB_ST_NOERROR;
-	purb_priv_t purb_priv = purb->hcpriv;
-	struct list_head *qhl = purb_priv->desc_list.next;
-	puhci_desc_t qh = list_entry (qhl, uhci_desc_t, desc_list);
+	int ret = 0;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	struct list_head *qhl = urb_priv->desc_list.next;
+	uhci_desc_t *qh = list_entry (qhl, uhci_desc_t, desc_list);
 	struct list_head *p = qh->vertical.next;
-	puhci_desc_t desc= list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list);
-	puhci_desc_t last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical);
-	int data_toggle = usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe));	// save initial data_toggle
+	uhci_desc_t *desc= list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
+	uhci_desc_t *last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical);
+	int data_toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));	// save initial data_toggle
 
 
 	// extracted and remapped info from TD
 	int maxlength;
 	int actual_length;
-	int status = USB_ST_NOERROR;
+	int status = 0;
 
 	dbg("process_transfer: urb contains bulk/control request");
 
@@ -1628,11 +1699,11 @@
 	   status stage is completed
 	 */
 #if 1
-	if (purb_priv->short_control_packet && 
+	if (urb_priv->short_control_packet && 
 		((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE)))) 
 		goto transfer_finished;
 #endif
-	purb->actual_length=0;
+	urb->actual_length=0;
 
 	for (; p != &qh->vertical; p = p->next) {
 		desc = list_entry (p, uhci_desc_t, vertical);
@@ -1643,24 +1714,24 @@
 		// extract transfer parameters from TD
 		actual_length = (desc->hw.td.status + 1) & 0x7ff;
 		maxlength = (((desc->hw.td.info >> 21) & 0x7ff) + 1) & 0x7ff;
-		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe));
+		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
 
 		// see if EP is stalled
 		if (status == -EPIPE) {
 			// set up stalled condition
-			usb_endpoint_halt (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe));
+			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
 		}
 
 		// if any error occured stop processing of further TDs
-		if (status != USB_ST_NOERROR) {
+		if (status != 0) {
 			// only set ret if status returned an error
 			uhci_show_td (desc);
 			ret = status;
-			purb->error_count++;
+			urb->error_count++;
 			break;
 		}
 		else if ((desc->hw.td.info & 0xff) != USB_PID_SETUP)
-			purb->actual_length += actual_length;
+			urb->actual_length += actual_length;
 
 #if 0
 		//	if (i++==0)
@@ -1669,21 +1740,21 @@
 
 		// got less data than requested
 		if ( (actual_length < maxlength)) {
-			if (purb->transfer_flags & USB_DISABLE_SPD) {
-				ret = USB_ST_SHORT_PACKET;	// treat as real error
+			if (urb->transfer_flags & USB_DISABLE_SPD) {
+				ret = -EREMOTEIO;	// treat as real error
 				dbg("process_transfer: SPD!!");
 				break;	// exit after this TD because SP was detected
 			}
 
 			// short read during control-IN: re-start status stage
-			if ((usb_pipetype (purb->pipe) == PIPE_CONTROL)) {
+			if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) {
 				if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) {
 			
 					qh->hw.qh.element = virt_to_bus (last_desc);  // re-trigger status stage
 					dbg("short packet during control transfer, retrigger status stage @ %p",last_desc);
 					uhci_show_td (desc);
 					uhci_show_td (last_desc);
-					purb_priv->short_control_packet=1;
+					urb_priv->short_control_packet=1;
 					return 0;
 				}
 			}
@@ -1696,33 +1767,23 @@
 		//dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle);      
 
 	}
-	usb_settoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe), !data_toggle);
+	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle);
 	transfer_finished:
 
-	/* APC BackUPS Pro kludge */     
-	/* It tries to send all of the descriptor instead of */
-	/*  the amount we requested */   
-	if (desc->hw.td.status & TD_CTRL_IOC &&  
-		status & TD_CTRL_ACTIVE &&   
-		status & TD_CTRL_NAK )
-	{
-		dbg("APS WORKAROUND");
-		ret=0;
-		status=0;
-	}
-
 	unlink_qh (s, qh);
-	delete_qh (s, qh);
+	//delete_qh (s, qh);
+	qh->last_used=UHCI_GET_CURRENT_FRAME(s);
+	list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion
+
+	urb->status = status;
 
-	purb->status = status;
-	                                                  	
 	dbg("process_transfer: urb %p, wanted len %d, len %d status %x err %d",
-		purb,purb->transfer_buffer_length,purb->actual_length, purb->status, purb->error_count);
+		urb,urb->transfer_buffer_length,urb->actual_length, urb->status, urb->error_count);
 	//dbg("process_transfer: exit");
 #if 0
-	if (purb->actual_length){
+	if (urb->actual_length){
 		char *uu;
-		uu=purb->transfer_buffer;
+		uu=urb->transfer_buffer;
 		dbg("%x %x %x %x %x %x %x %x",
 			*uu,*(uu+1),*(uu+2),*(uu+3),*(uu+4),*(uu+5),*(uu+6),*(uu+7));
 	}
@@ -1730,19 +1791,19 @@
 	return ret;
 }
 
-_static int process_interrupt (puhci_t s, purb_t purb)
+_static int process_interrupt (uhci_t *s, urb_t *urb)
 {
-	int i, ret = USB_ST_URB_PENDING;
-	purb_priv_t purb_priv = purb->hcpriv;
-	struct list_head *p = purb_priv->desc_list.next;
-	puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list);
+	int i, ret = -EINPROGRESS;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	struct list_head *p = urb_priv->desc_list.next;
+	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
 
 	int actual_length;
-	int status = USB_ST_NOERROR;
+	int status = 0;
 
 	//dbg("urb contains interrupt request");
 
-	for (i = 0; p != &purb_priv->desc_list; p = p->next, i++)	// Maybe we allow more than one TD later ;-)
+	for (i = 0; p != &urb_priv->desc_list; p = p->next, i++)	// Maybe we allow more than one TD later ;-)
 	{
 		desc = list_entry (p, uhci_desc_t, desc_list);
 
@@ -1759,47 +1820,54 @@
 		// extract transfer parameters from TD
 
 		actual_length = (desc->hw.td.status + 1) & 0x7ff;
-		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe));
+		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
 
 		// see if EP is stalled
 		if (status == -EPIPE) {
 			// set up stalled condition
-			usb_endpoint_halt (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe));
+			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
 		}
 
 		// if any error occured: ignore this td, and continue
-		if (status != USB_ST_NOERROR) {
+		if (status != 0) {
 			uhci_show_td (desc);
-			purb->error_count++;
+			urb->error_count++;
 			goto recycle;
 		}
 		else
-			purb->actual_length = actual_length;
+			urb->actual_length = actual_length;
 
 		// FIXME: SPD?
 
 	recycle:
-		if (purb->complete) {
+		if (urb->complete) {
 			//dbg("process_interrupt: calling completion, status %i",status);
-			purb->status = status;
-			purb->complete ((struct urb *) purb);
-			purb->status = USB_ST_URB_PENDING;
+			urb->status = status;
+			
+			spin_unlock(&s->urb_list_lock);
+			
+			urb->complete ((struct urb *) urb);
+			
+			spin_lock(&s->urb_list_lock);
+			
+			urb->status = -EINPROGRESS;
 		}
 
 		// Recycle INT-TD if interval!=0, else mark TD as one-shot
-		if (purb->interval) {
+		if (urb->interval) {
+
 			desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE);
 			if (status==0) {
-				desc->hw.td.info |= (usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe),
-				      usb_pipeout (purb->pipe)) << TD_TOKEN_TOGGLE);
-				usb_dotoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe));
+				desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+				      usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+				usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
 			} else {
-				desc->hw.td.info |= (!usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe),
-				      usb_pipeout (purb->pipe)) << TD_TOKEN_TOGGLE);
+				desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+				      usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
 			}
-			desc->hw.td.status= (purb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
-				(purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
-			wmb();
+			desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+				(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+			mb();
 		}
 		else {
 			desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
@@ -1810,23 +1878,23 @@
 }
 
 
-_static int process_iso (puhci_t s, purb_t purb)
+_static int process_iso (uhci_t *s, urb_t *urb)
 {
 	int i;
-	int ret = USB_ST_NOERROR;
-	purb_priv_t purb_priv = purb->hcpriv;
-	struct list_head *p = purb_priv->desc_list.next;
-	puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list);
+	int ret = 0;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	struct list_head *p = urb_priv->desc_list.next;
+	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
 
 	dbg("urb contains iso request");
 	if (desc->hw.td.status & TD_CTRL_ACTIVE)
-		return USB_ST_PARTIAL_ERROR;	// last TD not finished
+		return -EXDEV;	// last TD not finished
 
-	purb->error_count = 0;
-	purb->actual_length = 0;
-	purb->status = USB_ST_NOERROR;
+	urb->error_count = 0;
+	urb->actual_length = 0;
+	urb->status = 0;
 
-	for (i = 0; p != &purb_priv->desc_list; p = p->next, i++) {
+	for (i = 0; p != &urb_priv->desc_list; p = p->next, i++) {
 		desc = list_entry (p, uhci_desc_t, desc_list);
 
 		//uhci_show_td(desc);
@@ -1834,40 +1902,40 @@
 			// means we have completed the last TD, but not the TDs before
 			desc->hw.td.status &= ~TD_CTRL_ACTIVE;
 			dbg("TD still active (%x)- grrr. paranoia!", desc->hw.td.status);
-			ret = USB_ST_PARTIAL_ERROR;
-			purb->iso_frame_desc[i].status = ret;
-			unlink_td (s, desc);
+			ret = -EXDEV;
+			urb->iso_frame_desc[i].status = ret;
+			unlink_td (s, desc, 1);
 			// FIXME: immediate deletion may be dangerous
 			goto err;
 		}
 
-		unlink_td (s, desc);
+		unlink_td (s, desc, 1);
 
-		if (purb->number_of_packets <= i) {
-			dbg("purb->number_of_packets (%d)<=(%d)", purb->number_of_packets, i);
-			ret = USB_ST_URB_INVALID_ERROR;
+		if (urb->number_of_packets <= i) {
+			dbg("urb->number_of_packets (%d)<=(%d)", urb->number_of_packets, i);
+			ret = -EINVAL;
 			goto err;
 		}
 
-		if (purb->iso_frame_desc[i].offset + purb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) {
+		if (urb->iso_frame_desc[i].offset + urb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) {
 			// Hm, something really weird is going on
-			dbg("Pointer Paranoia: %p!=%p", purb->iso_frame_desc[i].offset + purb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
-			ret = USB_ST_URB_INVALID_ERROR;
-			purb->iso_frame_desc[i].status = ret;
+			dbg("Pointer Paranoia: %p!=%p", urb->iso_frame_desc[i].offset + urb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
+			ret = -EINVAL;
+			urb->iso_frame_desc[i].status = ret;
 			goto err;
 		}
-		purb->iso_frame_desc[i].actual_length = (desc->hw.td.status + 1) & 0x7ff;
-		purb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe));
-		purb->actual_length += purb->iso_frame_desc[i].actual_length;
+		urb->iso_frame_desc[i].actual_length = (desc->hw.td.status + 1) & 0x7ff;
+		urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
+		urb->actual_length += urb->iso_frame_desc[i].actual_length;
 
 	      err:
 
-		if (purb->iso_frame_desc[i].status != USB_ST_NOERROR) {
-			purb->error_count++;
-			purb->status = purb->iso_frame_desc[i].status;
+		if (urb->iso_frame_desc[i].status != 0) {
+			urb->error_count++;
+			urb->status = urb->iso_frame_desc[i].status;
 		}
 		dbg("process_iso: len:%d status:%x",
-		     purb->iso_frame_desc[i].length, purb->iso_frame_desc[i].status);
+		     urb->iso_frame_desc[i].length, urb->iso_frame_desc[i].status);
 
 		delete_desc (desc);
 		list_del (p);
@@ -1877,83 +1945,87 @@
 }
 
 
-_static int process_urb (puhci_t s, struct list_head *p)
+_static int process_urb (uhci_t *s, struct list_head *p)
 {
-	int ret = USB_ST_NOERROR;
-	purb_t purb;
+	int ret = 0;
+	urb_t *urb;
 
-	spin_lock(&s->urb_list_lock);
-	purb=list_entry (p, urb_t, urb_list);
-	dbg("found queued urb: %p", purb);
 
-	switch (usb_pipetype (purb->pipe)) {
+	urb=list_entry (p, urb_t, urb_list);
+	dbg("found queued urb: %p", urb);
+
+	switch (usb_pipetype (urb->pipe)) {
 	case PIPE_CONTROL:
 	case PIPE_BULK:
-		ret = process_transfer (s, purb);
+		ret = process_transfer (s, urb);
 		break;
 	case PIPE_ISOCHRONOUS:
-		ret = process_iso (s, purb);
+		ret = process_iso (s, urb);
 		break;
 	case PIPE_INTERRUPT:
-		ret = process_interrupt (s, purb);
+		ret = process_interrupt (s, urb);
 		break;
 	}
 
-	spin_unlock(&s->urb_list_lock);
-
-	if (purb->status != USB_ST_URB_PENDING) {
+	if (urb->status != -EINPROGRESS) {
 		int proceed = 0;
-		dbg("dequeued urb: %p", purb);
-		dequeue_urb (s, p, 1);
+
+		dbg("dequeued urb: %p", urb);
+		dequeue_urb (s, p);
 
 #ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, purb->hcpriv);
+		kmem_cache_free(urb_priv_kmem, urb->hcpriv);
 #else
-		kfree (purb->hcpriv);
+		kfree (urb->hcpriv);
 #endif
 
-		if ((usb_pipetype (purb->pipe) != PIPE_INTERRUPT)) {
-			purb_t tmp = purb->next;	// pointer to first urb
+		if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {
+			urb_t *tmp = urb->next;	// pointer to first urb
 			int is_ring = 0;
 			
-			if (purb->next) {
+			if (urb->next) {
 				do {
-					if (tmp->status != USB_ST_URB_PENDING) {
+					if (tmp->status != -EINPROGRESS) {
 						proceed = 1;
 						break;
 					}
 					tmp = tmp->next;
 				}
-				while (tmp != NULL && tmp != purb->next);
-				if (tmp == purb->next)
+				while (tmp != NULL && tmp != urb->next);
+				if (tmp == urb->next)
 					is_ring = 1;
 			}
 
+			spin_unlock(&s->urb_list_lock);
+
 			// In case you need the current URB status for your completion handler
-			if (purb->complete && (!proceed || (purb->transfer_flags & USB_URB_EARLY_COMPLETE))) {
+			if (urb->complete && (!proceed || (urb->transfer_flags & USB_URB_EARLY_COMPLETE))) {
 				dbg("process_transfer: calling early completion");
-				purb->complete ((struct urb *) purb);
-				if (!proceed && is_ring && (purb->status != USB_ST_URB_KILLED))
-					uhci_submit_urb (purb);
+				urb->complete ((struct urb *) urb);
+				if (!proceed && is_ring && (urb->status != -ENOENT))
+					uhci_submit_urb (urb);
 			}
 
-			if (proceed && purb->next) {
+			if (proceed && urb->next) {
 				// if there are linked urbs - handle submitting of them right now.
-				tmp = purb->next;	// pointer to first urb
+				tmp = urb->next;	// pointer to first urb
 
 				do {
-					if ((tmp->status != USB_ST_URB_PENDING) && (tmp->status != USB_ST_URB_KILLED) && uhci_submit_urb (tmp) != USB_ST_NOERROR)
+					if ((tmp->status != -EINPROGRESS) && (tmp->status != -ENOENT) && uhci_submit_urb (tmp) != 0)
 						break;
 					tmp = tmp->next;
 				}
-				while (tmp != NULL && tmp != purb->next);	// submit until we reach NULL or our own pointer or submit fails
+				while (tmp != NULL && tmp != urb->next);	// submit until we reach NULL or our own pointer or submit fails
 
-				if (purb->complete && !(purb->transfer_flags & USB_URB_EARLY_COMPLETE)) {
+				if (urb->complete && !(urb->transfer_flags & USB_URB_EARLY_COMPLETE)) {
 					dbg("process_transfer: calling completion");
-					purb->complete ((struct urb *) purb);
+					urb->complete ((struct urb *) urb);
 				}
 			}
-			usb_dec_dev_use (purb->dev);
+
+			spin_lock(&s->urb_list_lock);
+
+			usb_dec_dev_use (urb->dev);
 		}
 	}
 
@@ -1962,7 +2034,7 @@
 
 _static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
 {
-	puhci_t s = __uhci;
+	uhci_t *s = __uhci;
 	unsigned int io_addr = s->io_addr;
 	unsigned short status;
 	struct list_head *p, *p2;
@@ -1980,8 +2052,9 @@
 	dbg("interrupt");
 
 	if (status != 1) {
-		warn("interrupt, status %x", status);
-		
+		warn("interrupt, status %x, frame# %i", status, 
+		     UHCI_GET_CURRENT_FRAME(s));
+		//uhci_show_queue(s->control_chain);
 		// remove host controller halted state
 		if ((status&0x20) && (s->running)) {
 			// more to be done - check TDs for invalid entries
@@ -2000,39 +2073,42 @@
 	 * - Thomas Sailer
 	 */
 
-	spin_lock(&s->unlink_urb_lock);
 	spin_lock (&s->urb_list_lock);
-	p = s->urb_list.prev;
-	spin_unlock (&s->urb_list_lock);
+restart:
+	s->unlink_urb_done=0;
+	p = s->urb_list.prev;	
 
 	while (p != &s->urb_list) {
 		p2 = p;
 		p = p->prev;
 		process_urb (s, p2);
+		if(s->unlink_urb_done)
+		{
+			s->unlink_urb_done=0;
+			goto restart;
+		}
 	}
-
-	spin_unlock(&s->unlink_urb_lock);	
+	spin_unlock (&s->urb_list_lock);
+	clean_descs(s,0);	
 
 	outw (status, io_addr + USBSTS);
-#ifdef __alpha
-	mb ();			// ?
-#endif
-	dbg("done\n\n");
+
+	dbg("done");
 }
 
-_static void reset_hc (puhci_t s)
+_static void reset_hc (uhci_t *s)
 {
 	unsigned int io_addr = s->io_addr;
 
 	s->apm_state = 0;
 	/* Global reset for 50ms */
 	outw (USBCMD_GRESET, io_addr + USBCMD);
-	wait_ms (50);
+	uhci_wait_ms (50);
 	outw (0, io_addr + USBCMD);
-	wait_ms (10);
+	uhci_wait_ms (10);
 }
 
-_static void start_hc (puhci_t s)
+_static void start_hc (uhci_t *s)
 {
 	unsigned int io_addr = s->io_addr;
 	int timeout = 1000;
@@ -2065,13 +2141,17 @@
 	s->running = 1;
 }
 
-_static void __exit uhci_cleanup_dev(puhci_t s)
+_static void __exit uhci_cleanup_dev(uhci_t *s)
 {
 	struct usb_device *root_hub = s->bus->root_hub;
+
 	if (root_hub)
 		usb_disconnect (&root_hub);
 
+	uhci_unlink_urbs(s, 0, 1);  // Forced unlink of remaining URBs
+
 	usb_deregister_bus (s->bus);
+
 	s->running = 0;
 	reset_hc (s);
 	release_region (s->io_addr, s->io_size);
@@ -2079,10 +2159,9 @@
 	usb_free_bus (s->bus);
 	cleanup_skel (s);
 	kfree (s);
-
 }
 
-_static int __init uhci_start_usb (puhci_t s)
+_static int __init uhci_start_usb (uhci_t *s)
 {				/* start it up */
 	/* connect the virtual root hub */
 	struct usb_device *usb_dev;
@@ -2102,21 +2181,22 @@
 	return 0;
 }
 
-_static int __init alloc_uhci (int irq, unsigned int io_addr, unsigned int io_size)
+_static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
 {
-	puhci_t s;
+	uhci_t *s;
 	struct usb_bus *bus;
+	struct pm_dev *pmdev;
 
 	s = kmalloc (sizeof (uhci_t), GFP_KERNEL);
 	if (!s)
 		return -1;
 
 	memset (s, 0, sizeof (uhci_t));
+	INIT_LIST_HEAD (&s->free_desc);
 	INIT_LIST_HEAD (&s->urb_list);
 	spin_lock_init (&s->urb_list_lock);
 	spin_lock_init (&s->qh_lock);
 	spin_lock_init (&s->td_lock);
-	spin_lock_init (&s->unlink_urb_lock);
 	s->irq = -1;
 	s->io_addr = io_addr;
 	s->io_size = io_size;
@@ -2146,7 +2226,7 @@
 		if (!(portstatus & 0x0080))
 			break;
 	}
-	dbg("Detected %d ports", s->maxports);
+	warn("Detected %d ports", s->maxports);
 
 	/* This is experimental so anything less than 2 or greater than 8 is */
 	/*  something weird and we'll ignore it */
@@ -2185,10 +2265,14 @@
 		uhci_cleanup_dev(s);
 		return -1;
 	}
-	
+
 	//chain new uhci device into global list
 	devs = s;
 
+	pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(dev), handle_pm_event);
+	if (pmdev)
+		pmdev->data = s;
+
 	return 0;
 }
 
@@ -2217,47 +2301,27 @@
 			break;
 		/* disable legacy emulation */
 		pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
-
-		return alloc_uhci(dev->irq, io_addr, io_size);
+		return alloc_uhci(dev, dev->irq, io_addr, io_size);
 	}
 	return -1;
 }
 
-#ifdef CONFIG_APM
-_static int handle_apm_event (apm_event_t event)
+_static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data)
 {
-	static int down = 0;
-	puhci_t s = devs;
-	dbg("handle_apm_event(%d)", event);
-	switch (event) {
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-		if (down) {
-			dbg("received extra suspend event");
-			break;
-		}
-		while (s) {
+	uhci_t *s = (uhci_t*) dev->data;
+	dbg("handle_apm_event(%d)", rqst);
+	if (s) {
+		switch (rqst) {
+		case PM_SUSPEND:
 			reset_hc (s);
-			s = s->next;
-		}
-		down = 1;
-		break;
-	case APM_NORMAL_RESUME:
-	case APM_CRITICAL_RESUME:
-		if (!down) {
-			dbg("received bogus resume event");
 			break;
-		}
-		down = 0;
-		while (s) {
+		case PM_RESUME:
 			start_hc (s);
-			s = s->next;
+			break;
 		}
-		break;
 	}
 	return 0;
 }
-#endif
 
 int __init uhci_init (void)
 {
@@ -2267,26 +2331,15 @@
 	int i=0;
 
 #ifdef DEBUG_SLAB
-	char *slabname=kmalloc(16, GFP_KERNEL);
-
-	if(!slabname)
-		return -ENOMEM;
 
-	strcpy(slabname, "uhci_desc");
-	uhci_desc_kmem = kmem_cache_create(slabname, sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	uhci_desc_kmem = kmem_cache_create("uhci_desc", sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	
 	if(!uhci_desc_kmem) {
 		err("kmem_cache_create for uhci_desc failed (out of memory)");
 		return -ENOMEM;
 	}
 
-	slabname=kmalloc(16, GFP_KERNEL);
-
-	if(!slabname)
-		return -ENOMEM;
-
-	strcpy(slabname, "urb_priv");	
-	urb_priv_kmem = kmem_cache_create(slabname, sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	
 	if(!urb_priv_kmem) {
 		err("kmem_cache_create for urb_priv_t failed (out of memory)");
@@ -2319,26 +2372,26 @@
 	
 		if (!retval)
 			i++;
-
 	}
 
-#ifdef CONFIG_APM
-	if(i)
-		apm_register_callback (&handle_apm_event);
-#endif
 	return retval;
 }
 
 void __exit uhci_cleanup (void)
 {
-	puhci_t s;
+	uhci_t *s;
 	while ((s = devs)) {
 		devs = devs->next;
 		uhci_cleanup_dev(s);
 	}
 #ifdef DEBUG_SLAB
-	kmem_cache_shrink(uhci_desc_kmem);
-	kmem_cache_shrink(urb_priv_kmem);
+	
+	
+	if(kmem_cache_destroy(uhci_desc_kmem))
+		err("uhci_desc_kmem remained");
+		
+	if(kmem_cache_destroy(urb_priv_kmem))
+		err("urb_priv_kmem remained");
 #endif
 }
 
@@ -2350,9 +2403,7 @@
 
 void cleanup_module (void)
 {
-#ifdef CONFIG_APM
-	apm_unregister_callback (&handle_apm_event);
-#endif
+	pm_unregister_all (handle_pm_event);
 	uhci_cleanup ();
 }
 
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h
--- v2.3.42/linux/drivers/usb/usb-uhci.h	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/usb-uhci.h	Mon Feb  7 19:15:59 2000
@@ -2,10 +2,21 @@
 #define __LINUX_UHCI_H
 
 /*
-   $Id: usb-uhci.h,v 1.31 2000/01/15 22:02:30 acher Exp $
+   $Id: usb-uhci.h,v 1.39 2000/02/05 20:25:27 acher Exp $
  */
 #define MODNAME "usb-uhci"
-#define VERSTR "version v1.169 time " __TIME__ " " __DATE__
+#define VERSTR "version v1.184 time " __TIME__ " " __DATE__
+
+static __inline__ void uhci_wait_ms(unsigned int ms)
+{
+	if(!in_interrupt())
+	{
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(1 + ms * HZ / 1000);
+	}
+	else
+		mdelay(ms);
+}
 
 /* Command register */
 #define USBCMD		0
@@ -56,6 +67,7 @@
 #define USBLEGSUP_DEFAULT 0x2000	/* only PIRQ enable set */
 
 #define UHCI_NULL_DATA_SIZE	0x7ff	/* for UHCI controller TD */
+#define UHCI_PID 		0xff	/* PID MASK */
 
 #define UHCI_PTR_BITS		0x000F
 #define UHCI_PTR_TERM		0x0001
@@ -137,6 +149,7 @@
 	struct list_head horizontal;
 	struct list_head vertical;
 	struct list_head desc_list;
+	int last_used;
 } uhci_desc_t, *puhci_desc_t;
 
 typedef struct {
@@ -170,16 +183,17 @@
 
 	spinlock_t urb_list_lock;	// lock to keep consistency 
 
+	int unlink_urb_done;
+	
 	struct usb_bus *bus;	// our bus
 
-	spinlock_t unlink_urb_lock;	// lock for unlink_urb
-
 	__u32 *framelist;
 	uhci_desc_t **iso_td;
 	uhci_desc_t *int_chain[8];
 	uhci_desc_t *control_chain;
 	uhci_desc_t *bulk_chain;
 	uhci_desc_t *chain_end;
+	struct list_head free_desc;
 	spinlock_t qh_lock;
 	spinlock_t td_lock;
 	struct virt_root_hub rh;	//private data of the virtual root hub
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.42/linux/drivers/usb/usb.c	Tue Feb  1 01:35:44 2000
+++ linux/drivers/usb/usb.c	Wed Feb  9 11:42:35 2000
@@ -1363,7 +1363,7 @@
 
 static void usb_set_maxpacket(struct usb_device *dev)
 {
-	int i, j;
+	int i, j, b;
 	struct usb_interface *ifp;
 
 	for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
@@ -1375,12 +1375,15 @@
 			int e;
 
 			for (e=0; e<as->bNumEndpoints; e++) {
-				if (usb_endpoint_out(ep[e].bEndpointAddress))
-					dev->epmaxpacketout[ep[e].bEndpointAddress & 0x0f] =
-						ep[e].wMaxPacketSize;
-				else
-					dev->epmaxpacketin [ep[e].bEndpointAddress & 0x0f] =
-						ep[e].wMaxPacketSize;
+				b = ep[e].bEndpointAddress & 0x0f;
+				if (usb_endpoint_out(ep[e].bEndpointAddress)) {
+					if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
+						dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+				}
+				else {
+					if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
+						dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+				}
 			}
 		}
 	}
@@ -1756,16 +1759,7 @@
 }
 
 static struct file_operations usb_fops = {
-	NULL,		/* seek */
-	NULL,		/* read */
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	usb_open,
-	NULL,		/* flush */
-	NULL		/* release */
+	open:		usb_open,
 };
 
 int usb_major_init(void)
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usb_storage.h linux/drivers/usb/usb_storage.h
--- v2.3.42/linux/drivers/usb/usb_storage.h	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/usb_storage.h	Mon Feb  7 19:12:22 2000
@@ -72,7 +72,7 @@
 	__u8	Filler[18];
 };
 
-#define US_BULK_CS_WRAP_LEN	31
+#define US_BULK_CS_WRAP_LEN	13
 #define US_BULK_CS_SIGN		0x53425355
 #define US_BULK_STAT_OK		0
 #define US_BULK_STAT_FAIL	1
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- v2.3.42/linux/drivers/usb/usbkbd.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/usbkbd.c	Mon Feb  7 19:14:45 2000
@@ -49,7 +49,7 @@
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	134,130,132,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 29, 42, 56,125, 97, 54,100,126
 };
diff -u --recursive --new-file v2.3.42/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.3.42/linux/drivers/video/acornfb.c	Tue Dec  7 09:32:46 1999
+++ linux/drivers/video/acornfb.c	Sun Feb  6 17:45:25 2000
@@ -575,14 +575,16 @@
 			break;
 	}
 
-	if (min_size > size) {
-		/*
-		 * failed, use ypan
-		 */
-		size = current_par.screen_size;
-		var->yres_virtual = size / (font_line_len / fontht);
-	} else
-		var->yres_virtual = nr_y * fontht;
+	if (var->accel_flags & FB_ACCELF_TEXT) {
+		if (min_size > size) {
+			/*
+			 * failed, use ypan
+			 */
+			size = current_par.screen_size;
+			var->yres_virtual = size / (font_line_len / fontht);
+		} else
+			var->yres_virtual = nr_y * fontht;
+	}
 
 	current_par.screen_end = current_par.screen_base_p + size;
 
@@ -1283,7 +1285,7 @@
 	vmode:		FB_VMODE_NONINTERLACED
 };
 
-static void __init 
+static void __init
 acornfb_init_fbinfo(void)
 {
 	static int first = 1;
@@ -1325,6 +1327,7 @@
 	init_var.height		   = -1;
 	init_var.width		   = -1;
 	init_var.vmode		   = FB_VMODE_NONINTERLACED;
+	init_var.accel_flags	   = FB_ACCELF_TEXT;
 
 	current_par.dram_size	   = 0;
 	current_par.montype	   = -1;
@@ -1363,15 +1366,17 @@
  *	size can optionally be followed by 'M' or 'K' for
  *	MB or KB respectively.
  */
-static void __init 
+static void __init
 acornfb_parse_font(char *opt)
 {
 	strcpy(fb_info.fontname, opt);
 }
 
-static void __init 
+static void __init
 acornfb_parse_mon(char *opt)
 {
+	current_par.montype = -2;
+
 	fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0);
 	if (*opt == '-')
 		fb_info.monspecs.hfmax = simple_strtoul(opt + 1, &opt, 0);
@@ -1403,7 +1408,7 @@
 	init_var.height = simple_strtoul(opt + 1, NULL, 0);
 }
 
-static void __init 
+static void __init
 acornfb_parse_montype(char *opt)
 {
 	current_par.montype = -2;
@@ -1445,7 +1450,7 @@
 	}
 }
 
-static void __init 
+static void __init
 acornfb_parse_dram(char *opt)
 {
 	unsigned int size;
@@ -1479,7 +1484,7 @@
 	{ NULL, NULL }
 };
 
-int __init 
+int __init
 acornfb_setup(char *options)
 {
 	struct options *optp;
@@ -1517,7 +1522,7 @@
  * Detect type of monitor connected
  *  For now, we just assume SVGA
  */
-static int __init 
+static int __init
 acornfb_detect_monitortype(void)
 {
 	return 4;
@@ -1554,7 +1559,7 @@
 	printk("acornfb: freed %dK memory\n", mb_freed);
 }
 
-int __init 
+int __init
 acornfb_init(void)
 {
 	unsigned long size;
@@ -1566,10 +1571,11 @@
 	if (current_par.montype == -1)
 		current_par.montype = acornfb_detect_monitortype();
 
-	if (current_par.montype < 0 || current_par.montype > NR_MONTYPES)
+	if (current_par.montype == -1 || current_par.montype > NR_MONTYPES)
 		current_par.montype = 4;
 
-	fb_info.monspecs = monspecs[current_par.montype];
+	if (current_par.montype > 0)
+		fb_info.monspecs = monspecs[current_par.montype];
 	fb_info.monspecs.dpms = current_par.dpms;
 
 	/*
@@ -1642,7 +1648,7 @@
 		for (page = current_par.screen_base + size; page < top; page += PAGE_SIZE)
 			free_page(page);
 		current_par.screen_base_p =
-			virt_to_phys(current_par.screen_base);
+			virt_to_phys((void *)current_par.screen_base);
 	}
 #endif
 #if defined(HAS_VIDC)
diff -u --recursive --new-file v2.3.42/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c
--- v2.3.42/linux/drivers/video/aty128fb.c	Thu Jan  6 12:57:48 2000
+++ linux/drivers/video/aty128fb.c	Tue Feb  8 12:01:59 2000
@@ -1,22 +1,30 @@
-/* $Id: aty128fb.c,v 1.1 1999/10/12 11:00:43 geert Exp $
+/* $Id: aty128fb.c,v 1.1.1.1.36.1 1999/12/11 09:03:05 Exp $
  *  linux/drivers/video/aty128fb.c -- Frame buffer device for ATI Rage128
  *
- *  Copyright (C) Summer 1999, Anthony Tong <atong@uiuc.edu>
+ *  Copyright (C) 1999-2000, Anthony Tong <atong@uiuc.edu>
  *
- * 				Brad Douglas <brad@neruo.com>
+ *                Brad Douglas <brad@neruo.com>
  *				- x86 support
  *				- MTRR
  *				- Probe ROM for PLL
+ *				- modedb
+ *
+ *                Ani Joshi / Jeff Garzik
+ *                      - Code cleanup
  *
  *  Based off of Geert's atyfb.c and vfb.c.
  *
  *  TODO:
  *		- panning
- *		- fix 15/16 bpp on big endian arch's
  *		- monitor sensing (DDC)
+ *              - virtual display
  *		- other platform support (only ppc/x86 supported)
- *		- PPLL_REF_DIV & XTALIN calculation
- *		- determine MCLK from previous hardware setting
+ *		- PPLL_REF_DIV & XTALIN calculation    -done for x86
+ *		- determine MCLK from previous setting -done for x86            
+ *              - calculate XCLK, rather than probe BIOS
+ *		- hardware cursor support
+ *              - acceleration
+ *		- ioctl()'s
  */
 
 /*
@@ -24,6 +32,7 @@
  * example code and hardware. Thanks Nitya.	-atong
  */
 
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -39,7 +48,9 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/selection.h>
+#include <linux/console.h>
 #include <linux/pci.h>
+#include <linux/ioport.h>
 #include <asm/io.h>
 
 #if defined(CONFIG_PPC)
@@ -49,6 +60,10 @@
 #include <video/macmodes.h>
 #endif
 
+#ifdef CONFIG_FB_COMPAT_XPMAC
+#include <asm/vc_ioctl.h>
+#endif
+
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb16.h>
@@ -57,21 +72,30 @@
 
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
-#endif
+#endif /* CONFIG_MTRR */
 
 #include "aty128.h"
 
+/* compatibility with older kernels */
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+(y)<<8)+(z))
+#endif
+
+
+/* Debug flag */
 #undef DEBUG
-#undef CONFIG_MTRR	/* not ready? */
 
 #ifdef DEBUG
-#define DBG(x)		printk(KERN_INFO "aty128fb: %s\n",(x));
+#define DBG(x)		printk(KERN_DEBUG "aty128fb: %s\n",(x));
 #else
 #define DBG(x)
 #endif
 
-static char *aty128fb_name = "ATY Rage128";
-
+/* default mode */
 static struct fb_var_screeninfo default_var = {
     /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
     640, 480, 640, 480, 0, 0, 8, 0,
@@ -80,6 +104,35 @@
     0, FB_VMODE_NONINTERLACED
 };
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)
+#ifndef MODULE
+/* default modedb mode */
+static struct fb_videomode defaultmode __initdata = {
+    /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
+    NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2,
+    0, FB_VMODE_NONINTERLACED
+};
+#endif
+#endif
+
+/* chip description information */
+struct aty128_chip_info {
+    const char *name;
+    unsigned short vendor;
+    unsigned short device;
+};
+
+/* supported Rage128 chipsets */
+static const struct aty128_chip_info aty128_pci_probe_list[] =
+{
+    {"PCI_DEVICE_ID_ATI_RAGE128_RE", PCI_VENDOR_ID_ATI, 0x5245},
+    {"PCI_DEVICE_ID_ATI_RAGE128_RF", PCI_VENDOR_ID_ATI, 0x5246},
+    {"PCI_DEVICE_ID_ATI_RAGE128_RK", PCI_VENDOR_ID_ATI, 0x524b},
+    {"PCI_DEVICE_ID_ATI_RAGE128_RL", PCI_VENDOR_ID_ATI, 0x524c},
+    {NULL, 0, 0}
+};
+
+/* packed BIOS settings */
 #pragma pack(1)
 typedef struct {
     u8 clock_chip_type;
@@ -107,6 +160,7 @@
 } PLL_BLOCK;
 #pragma pack()
 
+/* onboard memory information */
 struct aty128_meminfo {
     u8 ML;
     u8 MB;
@@ -120,23 +174,32 @@
     u8 Rloop;
 };
 
+/* various memory configurations */
 const struct aty128_meminfo sdr_128   = { 4, 4, 3, 3, 1, 3, 1, 16, 30, 16 };
 const struct aty128_meminfo sdr_64    = { 4, 8, 3, 3, 1, 3, 1, 17, 46, 17 };
 const struct aty128_meminfo sdr_sgram = { 4, 4, 1, 2, 1, 2, 1, 16, 24, 16 };
 const struct aty128_meminfo ddr_sgram = { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16 };
 
 static int currcon = 0;
+
+static char *aty128fb_name = "ATY Rage128";
 static char fontname[40] __initdata = { 0 };
+static char noaccel __initdata = 0;
+
+#ifndef MODULE
+static const char *mode_option __initdata = NULL;
+#endif
 
 #if defined(CONFIG_PPC)
-static int default_vmode __initdata = VMODE_NVRAM;
-static int default_cmode __initdata = CMODE_NVRAM;
+static int default_vmode __initdata = VMODE_CHOOSE;
+static int default_cmode __initdata = CMODE_8;
 #endif
 
-#if defined(CONFIG_MTRR)
+#ifdef CONFIG_MTRR
 static int mtrr = 1;
-#endif
+#endif /* CONFIG_MTRR */
 
+/* PLL constants */
 struct aty128_constants {
     u32 dotclock;
     u32 ppll_min;
@@ -154,6 +217,7 @@
     u32 v_total, v_sync_strt_wid;
     u32 pitch;
     u32 offset, offset_cntl;
+    u32 xoffset, yoffset;
     u32 vxres, vyres;
     u32 bpp;
 };
@@ -179,17 +243,19 @@
 
 struct fb_info_aty128 {
     struct fb_info fb_info;
+    struct fb_info_aty128 *next;
     struct aty128_constants constants;
-    unsigned long regbase_phys, regbase;
-    unsigned long frame_buffer_phys, frame_buffer;
-    const struct aty128_meminfo *mem;
-    u32 vram_size;
-    u32 BIOS_SEG;
-#ifdef CONFIG_MTRR
-    struct { int vram; int vram_valid; } mtrr;
-#endif
+    unsigned long regbase_phys;         /* mmio                */
+    unsigned long frame_buffer_phys;    /* framebuffer memory  */
+    unsigned long frame_buffer;         /* remaped framebuffer */
+    void *regbase;
+    const struct aty128_meminfo *mem;   /* onboard mem info    */
+    u32 vram_size;                      /* onboard video ram   */
+    void *BIOS_SEG;                     /* BIOS segment        */
+    unsigned short card_revision;	/* video card revision */
     struct aty128fb_par default_par, current_par;
     struct display disp;
+    struct display_switch dispsw;       /* for cursor and font */
     struct { u8 red, green, blue, pad; } palette[256];
     union {
 #ifdef FBCON_HAS_CFB16
@@ -203,8 +269,16 @@
 #endif
     } fbcon_cmap;
     int blitter_may_be_busy;
+#ifdef CONFIG_PCI
+    struct pci_dev *pdev;
+#endif
+#ifdef CONFIG_MTRR
+    struct { int vram; int vram_valid; } mtrr;
+#endif /* CONFIG_MTRR */
 };
 
+static struct fb_info_aty128 *board_list = NULL;
+
 #define round_div(n, d) ((n+(d/2))/d)
 
     /*
@@ -226,7 +300,7 @@
 static int aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 			struct fb_info *info);
 static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
+			   struct fb_info *fb);
 static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 		     u_long arg, int con, struct fb_info *info);
 
@@ -242,7 +316,6 @@
 static int aty128fbcon_switch(int con, struct fb_info *info);
 static void aty128fbcon_blank(int blank, struct fb_info *info);
 
-
     /*
      *  Internal routines
      */
@@ -257,20 +330,43 @@
 static int aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 				u_int transp, struct fb_info *info);
 static void do_install_cmap(int con, struct fb_info *info);
+#ifndef CONFIG_FB_OF
 static void aty128pci_probe(void);
+static int aty128_pci_register(struct pci_dev *pdev,
+                               const struct aty128_chip_info *aci);
+#endif
+static struct fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128
+				*board_list, struct fb_info_aty128 *new_node);
+#ifndef CONFIG_PPC
 static int aty128find_ROM(struct fb_info_aty128 *info);
-static void aty128_timings(struct fb_info_aty128 *info);
 static void aty128_get_pllinfo(struct fb_info_aty128 *info);
+#endif
+static void aty128_timings(struct fb_info_aty128 *info);
+static void aty128_init_engine(const struct aty128fb_par *par, 
+				struct fb_info_aty128 *info);
 static void aty128_reset_engine(const struct fb_info_aty128 *info);
 static void aty128_flush_pixel_cache(const struct fb_info_aty128 *info);
 static void wait_for_fifo(u16 entries, const struct fb_info_aty128 *info);
-static void wait_for_idle(const struct fb_info_aty128 *info);
+static void wait_for_idle(struct fb_info_aty128 *info);
 static u32 bpp_to_depth(u32 bpp);
 
 #ifdef FBCON_HAS_CFB8
 static struct display_switch fbcon_aty128_8;
+static void fbcon_aty8_putc(struct vc_data *conp, struct display *p,
+                            int c, int yy, int xx);
+static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
+                             const unsigned short *s, int count,
+                             int yy, int xx);
+#endif
+#ifdef FBCON_HAS_CFB16
+static struct display_switch fbcon_aty128_16;
+#endif
+#ifdef FBCON_HAS_CFB24
+static struct display_switch fbcon_aty128_24;
+#endif
+#ifdef FBCON_HAS_CFB32
+static struct display_switch fbcon_aty128_32;
 #endif
-
 
 static struct fb_ops aty128fb_ops = {
     aty128fb_open, aty128fb_release, aty128fb_get_fix,
@@ -285,64 +381,58 @@
      *  or using the other register aperture? TODO.
      */
 static inline u32
-_aty_ld_le32(volatile unsigned int regindex,
+_aty_ld_le32(volatile unsigned int regindex, 
                               const struct fb_info_aty128 *info)
 {
-    unsigned long temp;
+    unsigned long *temp;
     u32 val;
 
 #if defined(__powerpc__)
     eieio();
     temp = info->regbase;
     asm("lwbrx %0,%1,%2" : "=b"(val) : "b" (regindex), "b" (temp));
-#elif defined(__sparc_v9__)
-    temp = info->regbase + regindex;
-    asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
 #else
     temp = info->regbase+regindex;
-    val = le32_to_cpu(*((volatile u32 *)(temp)));
+    val = readl (temp);
 #endif
+
     return val;
 }
 
 static inline void
-_aty_st_le32(volatile unsigned int regindex, u32 val,
+_aty_st_le32(volatile unsigned int regindex, u32 val, 
                                const struct fb_info_aty128 *info)
 {
-    unsigned long temp;
+    unsigned long *temp;
 
 #if defined(__powerpc__)
-    eieio();
     temp = info->regbase;
-    asm("stwbrx %0,%1,%2" : : "b" (val), "b" (regindex), "b" (temp) :
+    asm("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
         "memory");
-#elif defined(__sparc_v9__)
-    temp = info->regbase + regindex;
-    asm("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory");
+#elif defined(__mc68000__)
+    *((volatile u32 *)(info->regbase+regindex)) = cpu_to_le32(val);
 #else
     temp = info->regbase+regindex;
-    *((volatile u32 *)(temp)) = cpu_to_le32(val);
+    writel (val, temp);
 #endif
 }
 
 static inline u8
-_aty_ld_8(volatile unsigned int regindex,
-                          const struct fb_info_aty128 *info)
+_aty_ld_8(unsigned int regindex, const struct fb_info_aty128 *info)
 {
 #if defined(__powerpc__)
     eieio();
 #endif
-    return *(volatile u8 *)(info->regbase+regindex);
+    return readb (info->regbase + regindex);
 }
 
 static inline void
-_aty_st_8(volatile unsigned int regindex, u8 val,
-                            const struct fb_info_aty128 *info)
+_aty_st_8(unsigned int regindex, u8 val, const struct fb_info_aty128 *info)
 {
 #if defined(__powerpc__)
     eieio();
 #endif
-    *(volatile u8 *)(info->regbase+regindex) = val;
+    writeb (val, info->regbase + regindex);
 }
 
 #define aty_ld_le32(regindex)		_aty_ld_le32(regindex, info)
@@ -357,18 +447,26 @@
 #define aty_ld_pll(pll_index)		_aty_ld_pll(pll_index, info)
 #define aty_st_pll(pll_index, val)	_aty_st_pll(pll_index, val, info)
 
+
 static u32
 _aty_ld_pll(unsigned int pll_index,
 			const struct fb_info_aty128 *info)
 {       
+#if defined(__powerpc__)
+    eieio();
+#endif
     aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x1F);
     return aty_ld_le32(CLOCK_CNTL_DATA);
 }
+
     
 static void
 _aty_st_pll(unsigned int pll_index, u32 val,
 			const struct fb_info_aty128 *info)
-{   
+{
+#if defined(__powerpc__)
+    eieio();
+#endif
     aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x1F) | PLL_WR_EN);
     aty_st_le32(CLOCK_CNTL_DATA, val);
 }
@@ -380,6 +478,7 @@
     return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
 }
 
+
 static void
 aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
 {
@@ -394,10 +493,11 @@
 
 #ifdef DEBUG
     if (reset)	/* reset engine?? */
-	printk(KERN_ERR "aty128fb: PLL write timeout!");
+	DBG("PLL write timeout!");
 #endif
 }
 
+
 /* tell PLL to update */
 static void
 aty_pll_writeupdate(const struct fb_info_aty128 *info)
@@ -431,10 +531,10 @@
 
 
     /*
-     * Accelerator functions
+     * Accelerator engine functions
      */
 static void
-wait_for_idle(const struct fb_info_aty128 *info)
+wait_for_idle(struct fb_info_aty128 *info)
 {
     unsigned long timeout = jiffies + HZ/20;
     int reset = 1;
@@ -449,6 +549,8 @@
 
     if (reset)
 	aty128_reset_engine(info);
+	
+    info->blitter_may_be_busy = 0;
 }
 
 
@@ -476,7 +578,7 @@
 
     aty_st_le32(PC_NGUI_CTLSTAT, aty_ld_le32(PC_NGUI_CTLSTAT) | 0x000000ff);
 
-    while (i && (aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY))
+    while (i && ((aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY) == PC_BUSY))
 	i--;
 }
 
@@ -507,31 +609,33 @@
     aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
 
 #ifdef DEBUG
-    printk("aty128fb: engine reset\n");
+    DBG("engine reset");
 #endif
 }
 
 
 static void
 aty128_init_engine(const struct aty128fb_par *par,
-		const struct fb_info_aty128 *info)
+		struct fb_info_aty128 *info)
 {
-    u32 temp;
+    u32 pitch_value;
+
+    /* 3D scaler not spoken here */
     aty_st_le32(SCALE_3D_CNTL, 0x00000000);
 
     aty128_reset_engine(info);
 
-    temp = par->crtc.pitch;	/* fix this up */
+    pitch_value = par->crtc.pitch;	/* fix this up */
     if (par->crtc.bpp == 24) {
-        temp = temp * 3;
+        pitch_value = pitch_value * 3;
     }
 
     /* setup engine offset registers */
-    wait_for_fifo(4, info);
+    wait_for_fifo(1, info);
     aty_st_le32(DEFAULT_OFFSET, 0x00000000);
 
     /* setup engine pitch registers */
-    aty_st_le32(DEFAULT_PITCH, temp);
+    aty_st_le32(DEFAULT_PITCH, pitch_value);
 
     /* set the default scissor register to max dimensions */
     wait_for_fifo(1, info);
@@ -540,21 +644,22 @@
     /* set the drawing controls registers */
     wait_for_fifo(1, info);
     aty_st_le32(DP_GUI_MASTER_CNTL,
-			GMC_SRC_PITCH_OFFSET_DEFAULT		|
-			GMC_DST_PITCH_OFFSET_DEFAULT		|
-			GMC_SRC_CLIP_DEFAULT			|
-			GMC_DST_CLIP_DEFAULT			|
-			GMC_BRUSH_SOLIDCOLOR			|
-			(bpp_to_depth(par->crtc.bpp) << 8)	|
-			GMC_SRC_DSTCOLOR			|
-			GMC_BYTE_ORDER_MSB_TO_LSB		|
-			GMC_DP_CONVERSION_TEMP_6500		|
-			ROP3_PATCOPY				|
-			GMC_DP_SRC_RECT				|
-			GMC_3D_FCN_EN_CLR			|
-			GMC_DST_CLR_CMP_FCN_CLEAR		|
-			GMC_AUX_CLIP_CLEAR			|
-			GMC_WRITE_MASK_SET);
+		GMC_SRC_PITCH_OFFSET_DEFAULT		|
+		GMC_DST_PITCH_OFFSET_DEFAULT		|
+		GMC_SRC_CLIP_DEFAULT			|
+		GMC_DST_CLIP_DEFAULT			|
+		GMC_BRUSH_SOLIDCOLOR			|
+		(bpp_to_depth(par->crtc.bpp) << 8)	|
+		GMC_SRC_DSTCOLOR			|
+		GMC_BYTE_ORDER_MSB_TO_LSB		|
+		GMC_DP_CONVERSION_TEMP_6500		|
+		ROP3_PATCOPY				|
+		GMC_DP_SRC_RECT				|
+		GMC_3D_FCN_EN_CLR			|
+		GMC_DST_CLR_CMP_FCN_CLEAR		|
+		GMC_AUX_CLIP_CLEAR			|
+		GMC_WRITE_MASK_SET);
+
     wait_for_fifo(8, info);
 
     /* clear the line drawing registers */
@@ -563,12 +668,12 @@
     aty_st_le32(DST_BRES_DEC, 0);
 
     /* set brush color registers */
-    aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF);
-    aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000);
+    aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */
+    aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */
 
     /* set source color registers */
-    aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF);
-    aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000);
+    aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF);   /* white */
+    aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000);   /* black */
 
     /* default write mask */
     aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
@@ -578,39 +683,33 @@
 }
 
 
-    /*
-     * CRTC programming
-     */
-
 /* convert bpp values to their register representation */
 static u32
 bpp_to_depth(u32 bpp)
 {
     if (bpp <= 8)
-	return 2;
-    else if (bpp <= 15)
-	return 3;
+	return DST_8BPP;
     else if (bpp <= 16)
-#if 0	/* force 15bpp */
-	return 4;
-#else
-	return 3;
-#endif
+        return DST_15BPP;
     else if (bpp <= 24)
-	return 5;
+	return DST_24BPP;
     else if (bpp <= 32)
-	return 6;
+	return DST_32BPP;
 
     return -EINVAL;
 }
 
 
+    /*
+     * CRTC programming
+     */
+
+/* Program the CRTC registers */
 static void
 aty128_set_crtc(const struct aty128_crtc *crtc,
 		const struct fb_info_aty128 *info)
 {
     aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
-    // aty_st_le32(CRTC_EXT_CNTL, crtc->ext_cntl);
     aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
     aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
     aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total);
@@ -630,8 +729,9 @@
     u32 left, right, upper, lower, hslen, vslen, sync, vmode;
     u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
     u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
-    u32 depth;
+    u32 depth, bytpp;
     u8 hsync_strt_pix[5] = { 0, 0x12, 9, 6, 5 };
+    u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 };
 
     /* input */
     xres = var->xres;
@@ -666,60 +766,74 @@
     if (vyres < yres + yoffset)
 	vyres = yres + yoffset;
 
-    if (bpp <= 8)
-	bpp = 8;
-    else if (bpp <= 16)
-	bpp = 16;
-    else if (bpp <= 32)
-	bpp = 32;
+    depth = bpp_to_depth(bpp);
 
-    if (vxres * vyres * (bpp/8) > info->vram_size)
-	return -EINVAL;
+    /* make sure we didn't get an invalid depth */
+    if (depth == -EINVAL) {
+        printk(KERN_ERR "aty128fb: Invalid depth\n");
+        return -EINVAL;
+    }
 
-    h_disp = xres / 8 - 1;
-    h_total = (xres + right + hslen + left) / 8 - 1;
+   bytpp = mode_bytpp[depth];
+
+    /* make sure there is enough video ram for the mode */
+    if ((u32)(vxres * vyres * bytpp) > info->vram_size) {
+        printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
+        return -EINVAL;
+    }
+
+    h_disp = (xres/8) - 1;
+    h_total = (((xres + right + hslen + left) / 8) - 1) & 0xFFFFL;
 
     v_disp = yres - 1;
-    v_total = yres + upper + vslen + lower - 1;
+    v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL;
+
+    /* check to make sure h_total and v_total are in range */
+    if ((h_total/8 - 1) > 0x1ff || (v_total - 1) > 0x7FF) {
+        printk(KERN_ERR "aty128fb: invalid width ranges\n");
+        return -EINVAL;
+    }
 
-    h_sync_wid = hslen / 8;
+    h_sync_wid = (hslen+7)/8;
     if (h_sync_wid == 0)
 	h_sync_wid = 1;
-    else if (h_sync_wid > 0x3f)
+    else if (h_sync_wid > 0x3f)        /* 0x3f = max hwidth */
 	h_sync_wid = 0x3f;
 
-    h_sync_strt = (xres + right - 8) + hsync_strt_pix[bpp/8];
+    h_sync_strt = h_disp + (right/8);
 
-    v_disp = yres - 1;
     v_sync_wid = vslen;
     if (v_sync_wid == 0)
 	v_sync_wid = 1;
-    else if (v_sync_wid > 0x1f)
+    else if (v_sync_wid > 0x1f)        /* 0x1f = max vwidth */
 	v_sync_wid = 0x1f;
     
-    v_sync_strt = yres + lower - 1;
+    v_sync_strt = v_disp + lower;
 
-    h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : (1 << 23);
-    v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : (1 << 23);
-
-    depth = bpp_to_depth(bpp);
+    h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+    v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+    
     c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
 
-    crtc->gen_cntl = 0x03000000 | c_sync | depth << 8;
+    crtc->gen_cntl = 0x03000000L | c_sync | (depth << 8);
 
-    crtc->h_total = (h_disp << 16) | (h_total & 0x0000FFFF);
-    crtc->v_total = (v_disp << 16) | (v_total & 0x0000FFFF);
+    crtc->h_total = h_total | (h_disp << 16);
+    crtc->v_total = v_total | (v_disp << 16);
 
-    crtc->h_sync_strt_wid = (h_sync_wid << 16) | (h_sync_strt) | h_sync_pol;
-    crtc->v_sync_strt_wid = (v_sync_wid << 16) | (v_sync_strt) | v_sync_pol;
+    crtc->h_sync_strt_wid = hsync_strt_pix[bytpp] | (h_sync_strt << 3) |
+                (h_sync_wid << 16) | (h_sync_pol << 23);
+    crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
+                (v_sync_pol << 23);
 
-    crtc->pitch = xres / 8;
+    crtc->pitch = xres >> 3;
 
     crtc->offset = 0;
     crtc->offset_cntl = 0;
 
     crtc->vxres = vxres;
     crtc->vyres = vyres;
+    crtc->xoffset = xoffset;
+    crtc->yoffset = yoffset;
     crtc->bpp = bpp;
 
     return 0;
@@ -727,27 +841,85 @@
 
 
 static int
+aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
+{
+
+    /* fill in pixel info */
+    switch (pix_width) {
+    case CRTC_PIX_WIDTH_8BPP:
+        var->bits_per_pixel = 8;
+	var->red.offset = 0;
+	var->red.length = 8;
+	var->green.offset = 0;
+	var->green.length = 8;
+	var->blue.offset = 0;
+	var->blue.length = 8;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	break;
+    case CRTC_PIX_WIDTH_15BPP:
+    case CRTC_PIX_WIDTH_16BPP:
+	var->bits_per_pixel = 16;
+	var->red.offset = 10;
+	var->red.length = 5;
+	var->green.offset = 5;
+	var->green.length = 5;
+	var->blue.offset = 0;
+	var->blue.length = 5;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	break;
+    case CRTC_PIX_WIDTH_24BPP:
+        var->bits_per_pixel = 24;
+        var->red.offset = 16;
+        var->red.length = 8;
+        var->green.offset = 8;
+        var->green.length = 8;
+        var->blue.offset = 0;
+        var->blue.length = 8;
+        var->transp.offset = 0;
+        var->transp.length = 0;
+        break;
+    case CRTC_PIX_WIDTH_32BPP:
+        var->bits_per_pixel = 32;
+	var->red.offset = 16;
+	var->red.length = 8;
+	var->green.offset = 8;
+	var->green.length = 8;
+	var->blue.offset = 0;
+	var->blue.length = 8;
+	var->transp.offset = 24;
+	var->transp.length = 8;
+	break;
+    default:
+        printk(KERN_ERR "Invalid pixel width\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+static int
 aty128_crtc_to_var(const struct aty128_crtc *crtc,
 			struct fb_var_screeninfo *var)
 {
-#ifdef notyet	/* xoffset and yoffset are not correctly calculated */
-    u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
+    u32 xres, yres, left, right, upper, lower, hslen, vslen, sync;
     u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
     u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
     u32 pix_width;
 
     h_total = crtc->h_total & 0x1ff;
     h_disp = (crtc->h_total>>16) & 0xff;
-    h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
-        ((crtc->h_sync_strt_wid>>4) & 0x100);
-    h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
-    h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
-    h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
+    h_sync_strt = (crtc->h_sync_strt_wid>>3) & 0x1ff;
+    h_sync_dly = crtc->h_sync_strt_wid & 0x7;
+    h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x3f;
+    h_sync_pol = (crtc->h_sync_strt_wid>>23) & 0x1;
     v_total = crtc->v_total & 0x7ff;
     v_disp = (crtc->v_total>>16) & 0x7ff;
     v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
     v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
-    v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
+    v_sync_pol = (crtc->v_sync_strt_wid>>23) & 0x1;
     c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
     pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
 
@@ -760,88 +932,15 @@
     lower = v_sync_strt-v_disp;
     vslen = v_sync_wid;
     sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
-        (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
-        (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
+           (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+           (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
 
-    switch (pix_width) {
-#if 0
-    case CRTC_PIX_WIDTH_4BPP:
-        bpp = 4;
-        var->red.offset = 0;
-        var->red.length = 8;
-        var->green.offset = 0;
-        var->green.length = 8;
-        var->blue.offset = 0;
-        var->blue.length = 8;
-        var->transp.offset = 0;
-        var->transp.length = 0;
-        break;
-#endif
-    case CRTC_PIX_WIDTH_8BPP:
-        bpp = 8;
-        var->red.offset = 0;
-        var->red.length = 8;
-        var->green.offset = 0;
-        var->green.length = 8;
-        var->blue.offset = 0;
-        var->blue.length = 8;
-        var->transp.offset = 0;
-        var->transp.length = 0;
-        break;
-    case CRTC_PIX_WIDTH_15BPP:
-        bpp = 16;
-        var->red.offset = 10;
-        var->red.length = 5;
-        var->green.offset = 5;
-        var->green.length = 5;
-        var->blue.offset = 0;
-        var->blue.length = 5;
-        var->transp.offset = 0;
-        var->transp.length = 0;
-        break;
-    case CRTC_PIX_WIDTH_16BPP:
-        bpp = 16;
-        var->red.offset = 11;
-        var->red.length = 5;
-        var->green.offset = 5;
-        var->green.length = 6;
-        var->blue.offset = 0;
-        var->blue.length = 5;
-        var->transp.offset = 0;
-        var->transp.length = 0;
-        break;
-    case CRTC_PIX_WIDTH_24BPP:
-        bpp = 24;
-        var->red.offset = 16;
-        var->red.length = 8;
-        var->green.offset = 8;
-        var->green.length = 8;
-        var->blue.offset = 0;
-        var->blue.length = 8;
-        var->transp.offset = 0;
-        var->transp.length = 0;
-        break;
-    case CRTC_PIX_WIDTH_32BPP:
-        bpp = 32;
-        var->red.offset = 16;
-        var->red.length = 8;
-        var->green.offset = 8;
-        var->green.length = 8;
-        var->blue.offset = 0;
-        var->blue.length = 8;
-        var->transp.offset = 24;
-        var->transp.length = 8;
-        break;
-    default:
-        printk(KERN_ERR "Invalid pixel width\n");
-    }
+    aty128_bpp_to_var(pix_width, var);
 
-//Godda do math for xoffset and yoffset: does not exist in crtc
     var->xres = xres;
     var->yres = yres;
     var->xres_virtual = crtc->vxres;
     var->yres_virtual = crtc->vyres;
-    var->bits_per_pixel = bpp;
     var->xoffset = crtc->xoffset;
     var->yoffset = crtc->yoffset;
     var->left_margin = left;
@@ -853,59 +952,6 @@
     var->sync = sync;
     var->vmode = FB_VMODE_NONINTERLACED;
 
-#endif /* notyet */
-    return 0;
-}
-
-static int
-aty128_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
-{
-    /* fill in pixel info */
-    switch (bpp) {
-    case 8:
-	var->red.offset = 0;
-	var->red.length = 8;
-	var->green.offset = 0;
-	var->green.length = 8;
-	var->blue.offset = 0;
-	var->blue.length = 8;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	break;
-    case 15:
-	var->bits_per_pixel = 16;
-	var->red.offset = 10;
-	var->red.length = 5;
-	var->green.offset = 5;
-	var->green.length = 5;
-	var->blue.offset = 0;
-	var->blue.length = 5;
-	var->transp.offset = 15;
-	var->transp.length = 1;
-	break;
-    case 16:
-	var->bits_per_pixel = 16;
-	var->red.offset = 11;
-	var->red.length = 5;
-	var->green.offset = 5;
-	var->green.length = 6;
-	var->blue.offset = 0;
-	var->blue.length = 5;
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	break;
-    case 32:
-	var->red.offset = 16;
-	var->red.length = 8;
-	var->green.offset = 8;
-	var->green.length = 8;
-	var->blue.offset = 0;
-	var->blue.length = 8;
-	var->transp.offset = 24;
-	var->transp.length = 8;
-	break;
-    }
-
     return 0;
 }
 
@@ -914,16 +960,22 @@
 aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
 {
     int div3;
+
     unsigned char post_conv[] =	/* register values for post dividers */
-	{ 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
+        { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
 
     /* select PPLL_DIV_3 */
     aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
 
-    /* reset ppll */
+    /* reset PLL */
     aty_st_pll(PPLL_CNTL,
 		aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
 
+    /* write the reference divider */
+    aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider & 0x3ff);
+    aty_pll_writeupdate(info);
+    aty_pll_wait_readupdate(info);
+
     div3 = aty_ld_pll(PPLL_DIV_3);
 
     div3 &= ~PPLL_FB3_DIV_MASK;
@@ -947,22 +999,23 @@
 
 
 static int
-aty128_var_to_pll(u32 vclk_per, struct aty128_pll *pll,
+aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
 			const struct fb_info_aty128 *info)
 {
     const struct aty128_constants c = info->constants;
     unsigned char post_dividers [] = {1,2,4,8,3,6,12};
-    u32 output_freq, vclk;
+    u32 output_freq;
+    u32 vclk;        /* in .01 MHz */
     int i;
     u32 n, d;
 
-    vclk = 100000000 / vclk_per;	/* convert units to 10 kHz */
+    vclk = 100000000 / period_in_ps;	/* convert units to 10 kHz */
 
     /* adjust pixel clock if necessary */
     if (vclk > c.ppll_max)
 	vclk = c.ppll_max;
     if (vclk * 12 < c.ppll_min)
-	vclk = c.ppll_min;
+	vclk = c.ppll_min/12;
 
     /* now, find an acceptable divider */
     for (i = 0; i < sizeof(post_dividers); i++) {
@@ -970,17 +1023,20 @@
 	if (output_freq >= c.ppll_min && output_freq <= c.ppll_max)
 	    break;
     }
-    pll->post_divider = post_dividers[i];
 
     /* calculate feedback divider */
     n = c.ref_divider * output_freq;
     d = c.dotclock;
-    pll->feedback_divider = round_div(n, d);
 
+    pll->post_divider = post_dividers[i];
+    pll->feedback_divider = round_div(n, d);
     pll->vclk = vclk;
+
 #ifdef DEBUG
-    printk("post %x  feedback %x vlck %x output %x\n",
-	   pll->post_divider, pll->feedback_divider, vclk, output_freq);
+    printk(KERN_DEBUG "var_to_pll: post %d feedback %d vlck %d output %d ref_divider %d\n", 
+           pll->post_divider, pll->feedback_divider, vclk, output_freq,
+           c.ref_divider);
+    printk(KERN_DEBUG "var_to_pll: vclk_per: %d\n", period_in_ps);
 #endif
 
     return 0;
@@ -988,9 +1044,11 @@
 
 
 static int
-aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var)
+aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var,
+		const struct fb_info_aty128 *info)
 {
-    /* TODO */
+    var->pixclock = 100000000 / pll->vclk;
+
     return 0;
 }
 
@@ -1017,6 +1075,7 @@
     s32 x, b, p, ron, roff;
     u32 n, d;
 
+    /* 15bpp is really 16bpp */
     if (bpp == 15)
 	bpp = 16;
 
@@ -1033,7 +1092,7 @@
 	x;
 
 #ifdef DEBUG
-    printk("x %x\n", x);
+    printk(KERN_DEBUG "x %x\n", x);
 #endif
     b = 0;
     while (x) {
@@ -1048,13 +1107,13 @@
     x = round_div(n, d);
     roff = x * (fifo_depth - 4);
     if ((ron + m->Rloop) >= roff) {
-	printk("Mode out of range\n");
+	printk(KERN_ERR "Mode out of range\n");
 	return -EINVAL;
     }
 
 #ifdef DEBUG
-    printk("p: %x rloop: %x x: %x ron: %x roff: %x\n", p, m->Rloop, x,
-	ron, roff);
+    printk(KERN_DEBUG "p: %x rloop: %x x: %x ron: %x roff: %x\n", p,
+                       m->Rloop, x, ron, roff);
 #endif
     dsp->dda_config = p << 16 | m->Rloop << 20 | x;
     dsp->dda_on_off = ron << 16 | roff;
@@ -1073,6 +1132,9 @@
     u32 config;
     
     info->current_par = *par;
+    
+    if (info->blitter_may_be_busy)
+        wait_for_idle(info);
 
     /* clear all registers that may interfere with mode setting */
     aty_st_le32(OVR_CLR, 0);
@@ -1083,7 +1145,7 @@
     aty_st_le32(MPP_GP_CONFIG, 0);
     aty_st_le32(SUBPIC_CNTL, 0);
     aty_st_le32(VIPH_CONTROL, 0);
-    aty_st_le32(I2C_CNTL_1, 0);
+    aty_st_le32(I2C_CNTL_1, 0);         /* turn off i2c */
     aty_st_le32(GEN_INT_CNTL, 0);	/* turn off interrupts */
     aty_st_le32(CAP0_TRIG_CNTL, 0);
     aty_st_le32(CAP1_TRIG_CNTL, 0);
@@ -1104,8 +1166,10 @@
 #endif
 
     aty_st_le32(CONFIG_CNTL, config);
-
     aty_st_8(CRTC_EXT_CNTL + 1, 0);	/* turn the video back on */
+
+    if (par->accel_flags & FB_ACCELF_TEXT)
+        aty128_init_engine(par, info);
 }
 
 
@@ -1127,6 +1191,10 @@
 }
 
 
+    /*
+     *  encode/decode the User Defined Part of the Display
+     */
+
 static int
 aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par,
 			const struct fb_info_aty128 *info)
@@ -1158,17 +1226,19 @@
 {
     int err;
 
-    //memset(var, 0, sizeof(struct fb_var_screeninfo));
-
-    /* XXX aty128_*_to_var() aren't fully implemented! */
     if ((err = aty128_crtc_to_var(&par->crtc, var)))
 	return err;
 
-    if ((err = aty128_pll_to_var(&par->pll, var)))
+    if ((err = aty128_pll_to_var(&par->pll, var, info)))
 	return err;
 
-    if ((err = aty128_bpp_to_var(var->bits_per_pixel, var)))
-	return err;
+    var->red.msb_right = 0;
+    var->green.msb_right = 0;
+    var->blue.msb_right = 0;
+    var->transp.msb_right = 0;
+
+    var->nonstd = 0;
+    var->activate = 0;
 
     var->height = -1;
     var->width = -1;
@@ -1210,6 +1280,26 @@
 
     display = (con >= 0) ? &fb_display[con] : fb->disp;
 
+    /* basic (in)sanity checks */
+    if (!var->xres)
+        var->xres = 1;
+    if (!var->yres)
+        var->yres = 1;
+    if (var->xres > var->xres_virtual)
+        var->xres_virtual = var->xres;
+    if (var->yres > var->yres_virtual)
+        var->yres_virtual = var->yres;
+    if (var->bits_per_pixel <= 8)
+        var->bits_per_pixel = 8;
+    else if (var->bits_per_pixel <= 16)
+        var->bits_per_pixel = 16;
+    else if (var->bits_per_pixel <= 24)
+        var->bits_per_pixel = 24;
+    else if (var->bits_per_pixel <= 32)
+        var->bits_per_pixel = 32;
+    else
+        return -EINVAL;
+
     if ((err = aty128_decode_var(var, &par, info)))
 	return err;
 
@@ -1230,8 +1320,9 @@
 	oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
 
 	struct fb_fix_screeninfo fix;
+
 	aty128_encode_fix(&fix, &par, info);
-	display->screen_base = (char *) info->frame_buffer;
+        display->screen_base = (char *)info->frame_buffer;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
@@ -1242,13 +1333,11 @@
 	display->inverse = 0;
 
 	accel = var->accel_flags & FB_ACCELF_TEXT;
-	aty128_set_disp(display, info, var->bits_per_pixel, accel);
+        aty128_set_disp(display, info, par.crtc.bpp, accel);
 
-#if 0	/* acceleration is not ready */
 	if (accel)
-	    display->scrollmode = 0;
+	    display->scrollmode = SCROLL_YNOMOVE;
 	else
-#endif
 	    display->scrollmode = SCROLL_YREDRAW;
 
 	if (info->fb_info.changevar)
@@ -1264,6 +1353,26 @@
 	do_install_cmap(con, &info->fb_info);
     } 
 
+#ifdef CONFIG_FB_COMPAT_XPMAC
+    if (console_fb_info == &info->fb_info) {
+	int vmode, cmode;
+
+	display_info.width = var->xres;
+	display_info.height = var->yres;
+	display_info.depth = var->bits_per_pixel;
+	display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8;
+	if (mac_var_to_vmode(var, &vmode, &cmode))
+	    display_info.mode = 0;
+	else
+	    display_info.mode = vmode;
+	strcpy(info->fb_info.modename, aty128fb_name);
+	display_info.fb_address = info->frame_buffer_phys;
+	display_info.cmap_adr_address = 0;
+	display_info.cmap_data_address = 0;
+	display_info.disp_reg_address = info->regbase_phys;
+    }
+#endif
+
     return 0;
 }
 
@@ -1275,24 +1384,29 @@
     switch (bpp) {
 #ifdef FBCON_HAS_CFB8
     case 8:
-	disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;
+	info->dispsw = accel ? fbcon_aty128_8 : fbcon_cfb8;
+        disp->dispsw = &info->dispsw;
 	break;
 #endif
 #ifdef FBCON_HAS_CFB16
+    case 15:
     case 16:
-	disp->dispsw = &fbcon_cfb16;
+	info->dispsw = accel ? fbcon_aty128_16 : fbcon_cfb16;
+        disp->dispsw = &info->dispsw;
 	disp->dispsw_data = info->fbcon_cmap.cfb16;
 	break;
 #endif
 #ifdef FBCON_HAS_CFB24
     case 24:
-	disp->dispsw = &fbcon_cfb24;
+	info->dispsw = accel ? fbcon_aty128_24 : fbcon_cfb24;
+        disp->dispsw = &info->dispsw;
 	disp->dispsw_data = info->fbcon_cmap.cfb24;
 	break;
 #endif
 #ifdef FBCON_HAS_CFB32
     case 32:
-	disp->dispsw = &fbcon_cfb32;
+	info->dispsw = accel ? fbcon_aty128_32 : fbcon_cfb32;
+        disp->dispsw = &info->dispsw;
 	disp->dispsw_data = info->fbcon_cmap.cfb32;
 	break;
 #endif
@@ -1310,21 +1424,23 @@
     memset(fix, 0, sizeof(struct fb_fix_screeninfo));
     
     strcpy(fix->id, aty128fb_name);
-    fix->smem_start = (long) info->frame_buffer_phys;
-    fix->smem_len = info->vram_size;
+    fix->smem_start = (long)info->frame_buffer_phys;
+    fix->smem_len = (u32)info->vram_size;
 
-    fix->mmio_start = (long) info->regbase_phys;
+    fix->mmio_start = (long)info->regbase_phys;
     fix->mmio_len = 0x1fff;
 
     fix->type = FB_TYPE_PACKED_PIXELS;
+    fix->type_aux = 0;
     fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
     fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
-					: FB_VISUAL_DIRECTCOLOR;
-
+                                     : FB_VISUAL_DIRECTCOLOR;
+    fix->ywrapstep = 0;
     fix->xpanstep = 8;
     fix->ypanstep = 1;
 
     fix->accel = FB_ACCEL_ATI_RAGE128;
+
     return;
 }
 
@@ -1344,6 +1460,7 @@
 	aty128_decode_var(&fb_display[con].var, &par, info); 
 
     aty128_encode_fix(fix, &par, info);
+
     return 0;            
 }
 
@@ -1355,10 +1472,29 @@
      */
 static int
 aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
+			   struct fb_info *fb)
 {
-    if (var->xoffset != 0 || var->yoffset != 0)
-	return -EINVAL;
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+    struct aty128fb_par *par = &info->current_par;
+    u32 xoffset, yoffset;
+    u32 offset;
+    u32 xres, yres;
+
+    xres = (((par->crtc.h_total >> 16) & 0xff) + 1) * 8;
+    yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
+
+    xoffset = (var->xoffset +7) & ~7;
+    yoffset = var->yoffset;
+
+    if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
+        return -EINVAL;
+
+    par->crtc.xoffset = xoffset;
+    par->crtc.yoffset = yoffset;
+
+    offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6;
+
+    aty_st_le32(CRTC_OFFSET, offset);
 
     return 0;
 }
@@ -1372,8 +1508,7 @@
 aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			struct fb_info *info)
 {
-    if (!info->display_fg ||
-	con == info->display_fg->vc_num) /* current console ? */        
+    if (con == currcon) /* current console? */
 	return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
 	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -1381,6 +1516,7 @@
 	int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
 	fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
     }
+
     return 0;
 }
 
@@ -1400,21 +1536,22 @@
     else
 	disp = info->disp;
     if (!disp->cmap.len) {      /* no colormap allocated? */
-	int size = (disp->var.bits_per_pixel <= 16) ? 256 : 32;
+        int size = (disp->var.bits_per_pixel <= 8) ? 256 : 32;
 	if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
 	    return err;
     }
-    if (!info->display_fg || con == info->display_fg->vc_num)
-/* current console? */
+
+    if (con == currcon) /* current console? */
 	return fb_set_cmap(cmap, kspc, aty128_setcolreg, info);
     else
 	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+
     return 0;                
 }
 
 
     /*
-     *  Virtual Frame Buffer Specific ioctls
+     *  Frame Buffer Specific ioctls
      */
 
 static int
@@ -1425,6 +1562,7 @@
 }
 
 
+#ifndef MODULE
 int __init
 aty128fb_setup(char *options)
 {
@@ -1445,9 +1583,17 @@
 		    break;
 	    memcpy(fontname, this_opt + 5, i);
 	    fontname[i] = 0;
+	} else if (!strncmp(this_opt, "noaccel", 7)) {
+	    noaccel = 1;
 	}
+#ifdef CONFIG_MTRR
+        else if(!strncmp(this_opt, "nomtrr", 6)) {
+            mtrr = 0;
+        }
+#endif /* CONFIG_MTRR */
 #if defined(CONFIG_PPC)
-	if (!strncmp(this_opt, "vmode:", 6)) {
+        /* vmode and cmode depreciated */
+	else if (!strncmp(this_opt, "vmode:", 6)) {
             unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
             if (vmode > 0 && vmode <= VMODE_MAX)
                 default_vmode = vmode;
@@ -1468,26 +1614,20 @@
 		break;
             }
         }
-#endif
-#ifdef CONFIG_MTRR
-	if(mtrr) {
-		ACCESS_FBINFO(mtrr.vram) =
-			mtrr_add(video_base_phys, ACCESS_FBINFO(video.len),
-				MTRR_TYPE_WRCOMB, 1);
-		ACCESS_FBINFO(mtrr.valid_vram) = 1;
-		printk(KERN_INFO "aty128fb: MTRR set to ON\n");
-	}
-#endif
+#endif /* CONFIG_PPC */
+        else
+            mode_option = this_opt;
     }
     return 0;
 }
+#endif /* !MODULE */
 
 
     /*
      *  Initialisation
      */
 
-static int
+static int __init
 aty128_init(struct fb_info_aty128 *info, const char *name)
 {
     struct fb_var_screeninfo var;
@@ -1496,7 +1636,7 @@
     u8 chip_rev;
 
     if (!register_test(info)) {
-	printk("Can't write to video registers\n");
+	printk(KERN_ERR "Can't write to video registers\n");
 	return 0;
     }
 
@@ -1505,44 +1645,14 @@
 
     chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
 
-    /* TODO be more verbose */
-    printk("aty128fb: Rage128 [rev 0x%x] ", chip_rev);
+    /* TODO: be more verbose */
+    printk(KERN_INFO "aty128fb: Rage128 [chip rev 0x%x] [card rev %x] ",
+                      chip_rev, info->card_revision);
 
     if (info->vram_size % (1024 * 1024) == 0)
-	printk("%dM ", info->vram_size / (1024*1024));
+	printk("%dM \n", info->vram_size / (1024*1024));
     else
-	printk("%dk ", info->vram_size / 1024);
-
-    var = default_var;
-
-#ifdef CONFIG_PMAC
-
-    if (default_vmode == VMODE_NVRAM) {
-#ifdef CONFIG_NVRAM
-	default_vmode = nvram_read_byte(NV_VMODE);
-	if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-#endif /* CONFIG_NVRAM */
-	    default_vmode = VMODE_CHOOSE;
-    }
-
-    if (default_cmode == CMODE_NVRAM) {
-#ifdef CONFIG_NVRAM
-	default_cmode = nvram_read_byte(NV_CMODE);
-	if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
-#endif /* CONFIG_NVRAM */
-	    default_vmode = VMODE_CHOOSE;
-    }
-
-    if (default_vmode != VMODE_CHOOSE &&
-	mac_vmode_to_var(default_vmode, default_cmode, &var))
-	var = default_var;
-
-#endif /* CONFIG_PMAC */
-
-    if (aty128_decode_var(&var, &info->default_par, info)) {
-	printk("Cannot set default mode.\n");
-	return 0;
-    }
+	printk("%dk \n", info->vram_size / 1024);
 
     /* fill in info */
     strcpy(info->fb_info.modename, aty128fb_name);
@@ -1555,6 +1665,39 @@
     info->fb_info.blank = &aty128fbcon_blank;
     info->fb_info.flags = FBINFO_FLAG_DEFAULT;
 
+#ifdef MODULE
+    var = default_var;
+#else
+    memset(&var, 0, sizeof(var));
+#ifdef CONFIG_PMAC
+    if (default_vmode == VMODE_CHOOSE) {
+        var = default_var;
+#endif /* CONFIG_PMAC */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)
+    if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
+                      &defaultmode, 8))
+        var = default_var;
+#endif
+
+#ifdef CONFIG_PMAC
+    } else {
+        if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+            var = default_var;
+#endif /* CONFIG_PMAC */
+#endif /* MODULE */
+
+    if (noaccel)
+        var.accel_flags &= ~FB_ACCELF_TEXT;
+    else
+        var.accel_flags |= FB_ACCELF_TEXT;
+
+    if (aty128_decode_var(&var, &info->default_par, info)) {
+	printk(KERN_ERR "Cannot set default mode.\n");
+	return 0;
+    }
+
+    /* load up the palette with default colors */
     for (j = 0; j < 16; j++) {
         k = color_table[j];
         info->palette[j].red = default_red[k];
@@ -1563,8 +1706,8 @@
     }
 
     dac = aty_ld_le32(DAC_CNTL) & 15;	/* preserve lower three bits */
-    dac |= DAC_8BIT_EN;			/* set 8 bit dac */
-    dac |= (0xFF << 24);		/* set DAC mask */
+    dac |= DAC_8BIT_EN;			/* set 8 bit dac             */
+    dac |= DAC_MASK;			/* set DAC mask              */
     aty_st_le32(DAC_CNTL, dac);
 
     /* turn off bus mastering, just in case */
@@ -1573,116 +1716,179 @@
     aty128fb_set_var(&var, -1, &info->fb_info);
     aty128_init_engine(&info->default_par, info);
 
-    printk("\n");
+    board_list = aty128_board_list_add(board_list, info);
+
     if (register_framebuffer(&info->fb_info) < 0)
 	return 0;
 
-    printk("fb%d: %s frame buffer device on %s\n",
+    printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
 	   GET_FB_IDX(info->fb_info.node), aty128fb_name, name);
 
     return 1;	/* success! */
 }
 
 
+/* add a new card to the list  ++ajoshi */
+static struct
+fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128 *board_list,
+                                       struct fb_info_aty128 *new_node)
+{
+    struct fb_info_aty128 *i_p = board_list;
+
+    new_node->next = NULL;
+    if(board_list == NULL)
+	return new_node;
+    while(i_p->next != NULL)
+	i_p = i_p->next;
+    i_p->next = new_node;
+
+    return board_list;
+}
+
+
 void __init
 aty128fb_init(void)
 {
 #if defined(CONFIG_FB_OF)
-/* let offb handle init */
+    /* let offb handle init */
 #elif defined (CONFIG_PCI)
     aty128pci_probe();
 #endif
 }
 
 
-void
+#ifndef CONFIG_FB_OF
+void __init
 aty128pci_probe(void)
 {
     struct pci_dev *pdev = NULL;
-    struct fb_info_aty128 *info;
-    unsigned long fb_addr, reg_addr;
+    const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
+
+    while(aci->name != NULL) {
+	pdev = pci_find_device(aci->vendor, aci->device, NULL);
+	while(pdev != NULL) {
+            if(aty128_pci_register(pdev, aci) > 0)
+                return;
+            pdev = pci_find_device(aci->vendor, aci->device, pdev);
+	}
+	aci++;
+    }
+
+    return;
+}
+
+
+/* register a card    ++ajoshi */
+static int __init
+aty128_pci_register(struct pci_dev *pdev,
+                               const struct aty128_chip_info *aci)
+{
+    struct fb_info_aty128 *info = NULL;
+    unsigned long fb_addr, reg_addr = 0;
     u16 tmp;
 
-    while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
-	if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
-	    struct resource *rp;
-
-	    /* FIXME add other known R128 device ID's */
-	    switch (pdev->device) {
-	    case 0x5245:
-	    case 0x5246:
-	    case 0x524B:
-	    case 0x524C:
-		break;
-	    default:
-		continue;
-	    }
-
-	    rp = &pdev->resource[0];
-	    fb_addr = rp->start;
-	    if (!fb_addr)
-		continue;
-	    fb_addr &= PCI_BASE_ADDRESS_MEM_MASK;
-
-	    rp = &pdev->resource[2];
-	    reg_addr = rp->start;
-	    if (!reg_addr)
-		continue;
-	    reg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
-
-	    info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC);
-	    if (!info) {
-		printk("aty128fb: can't alloc fb_info_aty128\n");
-		return;
-	    }
-	    memset(info, 0, sizeof(struct fb_info_aty128));
-
-	    info->regbase_phys = reg_addr;
-	    info->regbase = (unsigned long) ioremap(reg_addr, 0x1FFF);
-
-	    if (!info->regbase) {
-		kfree(info);
-		return;
-	    }
-
-	    info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
-
-	    info->frame_buffer = fb_addr;
-	    info->frame_buffer = (unsigned long)
-				    ioremap(fb_addr, info->vram_size);
-
-	    if (!info->frame_buffer) {
-		kfree(info);
-		return;
-	    }
-
-	    pci_read_config_word(pdev, PCI_COMMAND, &tmp);
-	    if (!(tmp & PCI_COMMAND_MEMORY)) {
-		tmp |= PCI_COMMAND_MEMORY;
-		pci_write_config_word(pdev, PCI_COMMAND, tmp);
-	    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)
+    struct resource *rp;
 
-#if defined(CONFIG_PPC)
-	    aty128_timings(info);
+    rp = &pdev->resource[0];
+    fb_addr = rp->start;
+    fb_addr &= PCI_BASE_ADDRESS_MEM_MASK;
+
+    request_mem_region (rp->start, rp->end - rp->start + 1, "aty128fb");
+
+    rp = &pdev->resource[2];
+    reg_addr = rp->start;
+    reg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
+
+    if (!reg_addr) {
+        release_mem_region (pdev->resource[0].start,
+                            pdev->resource[0].end -
+                            pdev->resource[0].start + 1);
+        return -1;
+    }
 #else
-            if (!aty128find_ROM(info)) {
-                printk("Rage128 BIOS not located.  Guessing...\n");
-                aty128_timings(info);
-            }
-            else
-                aty128_get_pllinfo(info);
+    fb_addr = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+    reg_addr = pdev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK;
+    if (!reg_addr)
+        return -1;
 #endif
 
-	    if (!aty128_init(info, "PCI")) {
-		kfree(info);
-		return;
-	    }
-	}
+    info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC);
+    if(!info) {
+        printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
+	goto unmap_out;
+    }
+    memset(info, 0, sizeof(struct fb_info_aty128));
+
+    info->pdev = pdev;
+
+    info->regbase_phys = reg_addr;
+    info->regbase = ioremap(reg_addr, 0x1FFF);
+
+    if (!info->regbase)
+        goto err_out;
+
+    pci_read_config_word(pdev, 0x08, &tmp);
+    info->card_revision = tmp;
+
+    info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+
+    info->frame_buffer_phys = fb_addr;
+    info->frame_buffer = (unsigned long)ioremap(fb_addr, info->vram_size);
+
+    if (!info->frame_buffer)
+        goto err_out;
+
+    pci_read_config_word(pdev, PCI_COMMAND, &tmp);
+    if (!(tmp & PCI_COMMAND_MEMORY)) {
+        tmp |= PCI_COMMAND_MEMORY;
+        pci_write_config_word(pdev, PCI_COMMAND, tmp);
+    }
+
+#if defined(CONFIG_PPC)
+    aty128_timings(info);
+#else
+    if (!aty128find_ROM(info)) {
+        printk(KERN_INFO "Rage128 BIOS not located.  Guessing...\n");
+        aty128_timings(info);
     }
+    else
+        aty128_get_pllinfo(info);
+#endif
+#ifdef CONFIG_MTRR
+    if (mtrr) {
+        info->mtrr.vram = mtrr_add(info->frame_buffer_phys, info->vram_size,
+                                   MTRR_TYPE_WRCOMB, 1);
+        info->mtrr.vram_valid = 1;
+        /* let there be speed */
+        printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
+    }
+#endif /* CONFIG_MTRR */
+
+    if (!aty128_init(info, "PCI"))
+        goto err_out;
+
+    return 0;
+
+err_out:
+    kfree (info);
+unmap_out:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)
+    release_mem_region (pdev->resource[0].start,
+			pdev->resource[0].end -
+			pdev->resource[0].start + 1);
+    release_mem_region (pdev->resource[2].start,
+			pdev->resource[2].end -
+			pdev->resource[2].start + 1);
+#endif
+
+    return -1;
 }
+#endif /* ! CONFIG_FB_OF */
 
 
-static int
+#ifndef CONFIG_PPC
+static int __init
 aty128find_ROM(struct fb_info_aty128 *info)
 {
     u32 segstart;
@@ -1691,20 +1897,18 @@
     char *rom;
     int stage;
     int i;
-    char aty_rom_sig[] = "761295520";
-    char R128_sig[] = "R128";
+    char aty_rom_sig[] = "761295520";   /* ATI ROM Signature      */
+    char R128_sig[] = "R128";           /* Rage128 ROM identifier */
     int flag = 0;
-DBG("E  aty128find_ROM");
 
-    for (segstart = 0x000c0000; segstart < 0x000f0000; segstart += 0x00001000) {
+    for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
         stage = 1;
 
         rom_base = (char *) ioremap(segstart, 0x1000);
         rom_base1 = (char *) (rom_base+1);
 
-        if ((*rom_base == 0x55) && (((*rom_base1) & 0xff) == 0xaa)) {
+        if ((*rom_base == 0x55) && (((*rom_base1) & 0xff) == 0xaa))
             stage = 2;
-        }
 
         if (stage != 2) {
             iounmap(rom_base);
@@ -1726,6 +1930,7 @@
         }
         rom = rom_base;
 
+        /* ATI signature found.  Let's see if it's a Rage128 */
         for (i = 0; (i < 512) && (stage != 4); i++) {
             if (R128_sig[0] == *rom) {
                 if (strncmp(R128_sig, rom, strlen(R128_sig)) == 0) {
@@ -1739,38 +1944,36 @@
             continue;
         }
 
-        printk("Rage128 BIOS located at segment %4.4X\n", (u32)rom_base);
-        info->BIOS_SEG = (u32)rom_base;
+        printk(KERN_INFO "aty128fb: Rage128 BIOS located at segment %4.4X\n",
+                         (u32)rom_base);
+        info->BIOS_SEG = rom_base;
         flag = 1;
-
         break;
     }
-DBG("L  aty128find_ROM");
     return (flag);
 }
 
 
-static void
+static void __init
 aty128_get_pllinfo(struct fb_info_aty128 *info)
 {   
-    u32 bios_header;
-    u32 *header_ptr;
+    void *bios_header;
+    void *header_ptr;
     u16 bios_header_offset, pll_info_offset;
     PLL_BLOCK pll;
-DBG("E  aty128_get_pllinfo");
 
     bios_header = info->BIOS_SEG + 0x48L;
-    header_ptr = (u32 *)bios_header;
+    header_ptr = bios_header;
 
-    bios_header_offset = (u16)*header_ptr;
-    bios_header = info->BIOS_SEG + (u32)bios_header_offset;
+    bios_header_offset = readw(header_ptr);
+    bios_header = info->BIOS_SEG + bios_header_offset;
     bios_header += 0x30;
 
-    header_ptr = (u32 *)bios_header;
-    pll_info_offset = (u16)*header_ptr;
-    header_ptr = (u32 *)(info->BIOS_SEG + (u32)pll_info_offset);
+    header_ptr = bios_header;
+    pll_info_offset = readw(header_ptr);
+    header_ptr = info->BIOS_SEG + pll_info_offset;
 
-    memcpy(&pll, header_ptr, 50);
+    memcpy_fromio(&pll, header_ptr, 50);
 
     info->constants.ppll_max = pll.PCLK_max_freq;
     info->constants.ppll_min = pll.PCLK_min_freq;
@@ -1778,9 +1981,20 @@
     info->constants.ref_divider = (u32)pll.PCLK_ref_divider;
     info->constants.dotclock = (u32)pll.PCLK_ref_freq;
 
+    aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider);
+    aty_pll_writeupdate(info);
+
     info->constants.fifo_width = 128;
     info->constants.fifo_depth = 32;
 
+#ifdef DEBUG
+    printk(KERN_DEBUG "get_pllinfo: ppll_max %d ppll_min %d xclk %d "
+                      "ref_divider %d dotclock %d\n", 
+                   info->constants.ppll_max, info->constants.ppll_min,
+                   info->constants.xclk, info->constants.ref_divider,
+                   info->constants.dotclock);
+#endif
+
     switch(aty_ld_le32(MEM_CNTL) & 0x03) {
     case 0:
         info->mem = &sdr_128; 
@@ -1795,13 +2009,17 @@
         info->mem = &sdr_sgram;
     }       
 
-DBG("L  aty128get_pllinfo");
+    /* free up to-be unused resources */
+    if (info->BIOS_SEG)
+        iounmap(info->BIOS_SEG);
+
     return;
 }           
+#endif /* ! CONFIG_PPC */
 
 
 #ifdef CONFIG_FB_OF
-void
+void __init
 aty128fb_of_init(struct device_node *dp)
 {
     unsigned long addr, reg_addr, fb_addr;
@@ -1815,25 +2033,25 @@
 	reg_addr = dp->addrs[2].address;
 	break;
     default:
-	printk("aty128fb: TODO unexpected addresses\n");
+	printk(KERN_ERR "aty128fb: TODO unexpected addresses\n");
 	return;
     }
 
     addr = (unsigned long) ioremap(reg_addr, 0x1FFF);
     if (!addr) {
-	printk("aty128fb: can't map memory registers\n");
+	printk(KERN_ERR "aty128fb: can't map memory registers\n");
 	return;
     }
 
     info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC);
     if (!info) {
-	printk("aty128fb: can't alloc fb_info_aty128\n");
+	printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
 	return;
     }
-    memset(info, 0, sizeof(struct fb_info_aty128));
+    memset((void *) info, 0, sizeof(struct fb_info_aty128));
 
     info->regbase_phys = reg_addr;
-    info->regbase = addr;
+    info->regbase = (void *) addr;
 
     /* enabled memory-space accesses using config-space command register */
     if (pci_device_loc(dp, &bus, &devfn) == 0) {
@@ -1846,45 +2064,48 @@
 
     info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
     info->frame_buffer_phys = fb_addr;
-    info->frame_buffer = (unsigned long) ioremap(fb_addr, info->vram_size);
-
-    /*
-     * TODO find OF values/hints.
-     *
-     * If we are booted from BootX, the MacOS ATI driver will likely have
-     * left useful tidbits in the DeviceRegistry.
-     */
+    info->frame_buffer = (void *) ioremap(fb_addr, info->vram_size);
 
     if (!info->frame_buffer) {
-	printk("aty128fb: can't map frame buffer\n");
-	return;
+        printk(KERN_ERR "aty128fb: can't map frame buffer\n");
+        kfree(info);
+        return;
     }
 
+    /* fall back to defaults */
     aty128_timings(info);
 
     if (!aty128_init(info, dp->full_name)) {
 	kfree(info);
 	return;
     }
-}
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+    if (!console_fb_info)
+	console_fb_info = &info->fb_info;
 #endif
+}
+#endif /* CONFIG_FB_OF */
 
 
 /* fill in known card constants if pll_block is not available */
-static void
+static void __init
 aty128_timings(struct fb_info_aty128 *info)
 {
     /* TODO make an attempt at probing */
-
-    info->constants.dotclock = 2950;
+    if (!info->constants.dotclock)
+        info->constants.dotclock = 2950;
 
     /* from documentation */
-    info->constants.ppll_min = 12500;
-    info->constants.ppll_max = 25000;	/* 23000 on some cards? */
+    if (!info->constants.ppll_min)
+        info->constants.ppll_min = 12500;
+    if (!info->constants.ppll_max)
+        info->constants.ppll_max = 25000;    /* 23000 on some cards? */
 
 #if 1
-    /* XXX TODO. Calculate properly. Fix OF's pll ideas. */
-    info->constants.ref_divider = 0x3b;
+    /* XXX TODO. Calculuate properly. Fix OF's pll ideas. */
+    if (!info->constants.ref_divider)
+        info->constants.ref_divider = 0x3b;
     aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider);
     aty_pll_writeupdate(info);
 
@@ -1895,7 +2116,8 @@
 #endif
 
     /* TODO. Calculate */
-    info->constants.xclk = 0x1d4d;	/* same as mclk */
+    if (!info->constants.xclk)
+        info->constants.xclk = 0x1d4d;	  /* same as mclk */
 
     info->constants.fifo_width = 128;
     info->constants.fifo_depth = 32;
@@ -1919,27 +2141,23 @@
 static int
 aty128fbcon_switch(int con, struct fb_info *fb)
 {
-    currcon = con;
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+    struct aty128fb_par par;
 
     /* Do we have to save the colormap? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, 1, aty128_getcolreg, fb);
+    	fb_get_cmap(&fb_display[currcon].cmap, 1, aty128_getcolreg, fb);
 
-#if 1
-    aty128fb_set_var(&fb_display[con].var, con, fb);
-#else
-{
-    struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
-    struct aty128fb_par par;
+    /* set the current console */
+    currcon = con;
 
     aty128_decode_var(&fb_display[con].var, &par, info);
     aty128_set_par(&par, info);
-    aty128_set_disp(&fb_display[con], info,
-	fb_display[con].var.bits_per_pixel);
+
+    aty128_set_disp(&fb_display[con], info, par.crtc.bpp,
+        par.accel_flags & FB_ACCELF_TEXT);
 
     do_install_cmap(con, fb);
-}
-#endif
 
     return 1;
 }
@@ -1948,7 +2166,6 @@
     /*
      *  Blank the display.
      */
-
 static void
 aty128fbcon_blank(int blank, struct fb_info *fb)
 {
@@ -1983,6 +2200,7 @@
     *green = (info->palette[regno].green<<8) | info->palette[regno].green;
     *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
     *transp = 0;
+
     return 0;
 }
 
@@ -1996,7 +2214,7 @@
 aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                          u_int transp, struct fb_info *fb)
 {
-    struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
     u32 col;
 
     if (regno > 255)
@@ -2009,32 +2227,47 @@
     info->palette[regno].green = green;
     info->palette[regno].blue = blue;
 
-    aty_st_8(PALETTE_INDEX, regno);
-    col = red << 16 | green << 8 | blue;
+    /* initialize gamma ramp for hi-color+ */
+    if ((info->current_par.crtc.bpp > 8) && (regno == 0)) {
+        int i;
+
+        for (i=16; i<256; i++) {
+            aty_st_8(PALETTE_INDEX, i);
+            col = (i << 16) | (i << 8) | i;
+            aty_st_le32(PALETTE_DATA, col);
+        }
+    }
+
+    /* initialize palette */
+    if (info->current_par.crtc.bpp == 16)
+        aty_st_8(PALETTE_INDEX, (regno << 3));
+    else
+        aty_st_8(PALETTE_INDEX, regno);
+    col = (red << 16) | (green << 8) | blue;
     aty_st_le32(PALETTE_DATA, col);
 
     if (regno < 16)
 	switch (info->current_par.crtc.bpp) {
 #ifdef FBCON_HAS_CFB16
-	case 16:
+	case 9 ... 16:
 	    info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
-		regno;
+                regno;
 	    break;
 #endif
 #ifdef FBCON_HAS_CFB24
-	case 24:
+	case 17 ... 24:
 	    info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
 		regno;
 	    break;
 #endif
 #ifdef FBCON_HAS_CFB32
-	case 32:
-	    {
-		u32 i;
-		i = (regno << 8) | regno;
-		info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
-	    }
+	case 25 ... 32: {
+            u32 i;
+
+            i = (regno << 8) | regno;
+            info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
 	    break;
+        }
 #endif
 	}
     return 0;
@@ -2046,6 +2279,7 @@
 {
     if (con != currcon)
 	return;
+
     if (fb_display[con].cmap.len)
 	fb_set_cmap(&fb_display[con].cmap, 1, aty128_setcolreg, info);
     else {
@@ -2063,10 +2297,12 @@
 aty128_rectdraw(s16 x, s16 y, u16 width, u16 height,
 		struct fb_info_aty128 *info)
 {
-    /* perform rectangle fill */
+    /* perform rectangle operation */
     wait_for_fifo(2, info);
     aty_st_le32(DST_Y_X, (y << 16) | x);
     aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
+
+    info->blitter_may_be_busy = 1;
 }
 
 
@@ -2075,42 +2311,35 @@
 		u_int width, u_int height,
 		struct fb_info_aty128 *info)
 {
-    u32 direction = DST_LAST_PEL;
-    u32 pitch_value;
-
-    if (!width || !height)
-        return;
+    u32 save_dp_datatype, save_dp_cntl;
 
-    pitch_value = info->current_par.crtc.vxres;
-    if (info->current_par.crtc.bpp == 24) {
-        /* In 24 bpp, the engine is in 8 bpp - this requires that all */
-        /* horizontal coordinates and widths must be adjusted */
-        pitch_value *= 3;
-        srcx *= 3;
-        dstx *= 3;
-        width *= 3;
-    }
-    
-    if (srcy < dsty) {
-        dsty += height - 1;
-        srcy += height - 1;
-    } else
-        direction |= DST_Y_TOP_TO_BOTTOM;
-
-    if (srcx < dstx) {
-        dstx += width - 1;
-        srcx += width - 1;
-    } else
-        direction |= DST_X_LEFT_TO_RIGHT;
+    wait_for_fifo(2, info);
+    save_dp_datatype = aty_ld_le32(DP_DATATYPE);
+    save_dp_cntl = aty_ld_le32(DP_CNTL);
 
-    wait_for_fifo(4, info);
-    aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
+    wait_for_fifo(6, info);
+    aty_st_le32(DP_DATATYPE, (0 | BRUSH_SOLIDCOLOR << 16) | SRC_DSTCOLOR);
     aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
-    aty_st_le32(DP_CNTL, direction);
-    aty_st_le32(DP_DATATYPE, aty_ld_le32(DP_DATATYPE) | SRC_DSTCOLOR);
-    aty128_rectdraw(dstx, dsty, width, height, info);
+    aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+    aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
+    aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
+    aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
+
+    wait_for_fifo(2, info);
+    aty_st_le32(DP_DATATYPE, save_dp_datatype);
+    aty_st_le32(DP_CNTL, save_dp_cntl); 
+
+    info->blitter_may_be_busy = 1;
+
+    wait_for_idle(info);
 }
 
+
+    /*
+     * Text mode accelerated functions
+     */
+
+
 static void
 fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
 			int height, int width)
@@ -2126,25 +2355,225 @@
 			(struct fb_info_aty128 *)p->fb_info);
 }
 
+
+/* TODO: Fix accel and add to these structs */
 #ifdef FBCON_HAS_CFB8
+static void fbcon_aty8_putc(struct vc_data *conp, struct display *p,
+                            int c, int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb8_putc(conp, p, c, yy, xx);
+}
+
+
+static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
+                             const unsigned short *s, int count,
+                             int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty8_clear_margins(struct vc_data *conp,
+                                     struct display *p, int bottom_only)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb8_clear_margins(conp, p, bottom_only);
+}
+
 static struct display_switch fbcon_aty128_8 = {
-    fbcon_cfb8_setup, fbcon_aty128_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
-    fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+    fbcon_cfb8_setup, fbcon_aty128_bmove, fbcon_cfb8_clear,
+    fbcon_aty8_putc, fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL,
+    fbcon_aty8_clear_margins,
+    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB16
+static void fbcon_aty16_putc(struct vc_data *conp, struct display *p,
+                            int c, int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb16_putc(conp, p, c, yy, xx);
+}
+
+
+static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
+                             const unsigned short *s, int count,
+                             int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty16_clear_margins(struct vc_data *conp,
+                                     struct display *p, int bottom_only)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb16_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_aty128_16 = {
+    fbcon_cfb16_setup, fbcon_aty128_bmove, fbcon_cfb16_clear,
+    fbcon_aty16_putc, fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL,
+    fbcon_aty16_clear_margins,
+    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB24
+static void fbcon_aty24_putc(struct vc_data *conp, struct display *p,
+                            int c, int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb24_putc(conp, p, c, yy, xx);
+}
+
+
+static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
+                             const unsigned short *s, int count,
+                             int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty24_clear_margins(struct vc_data *conp,
+                                     struct display *p, int bottom_only)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb24_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_aty128_24 = {
+    fbcon_cfb24_setup, fbcon_aty128_bmove, fbcon_cfb24_clear,
+    fbcon_aty24_putc, fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL,
+    fbcon_aty24_clear_margins,
+    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB32
+static void fbcon_aty32_putc(struct vc_data *conp, struct display *p,
+                            int c, int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb32_putc(conp, p, c, yy, xx);
+}
+
+
+static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
+                             const unsigned short *s, int count,
+                             int yy, int xx)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty32_clear_margins(struct vc_data *conp,
+                                     struct display *p, int bottom_only)
+{
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+    if (fb->blitter_may_be_busy)
+        wait_for_idle(fb);
+
+    fbcon_cfb32_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_aty128_32 = {
+    fbcon_cfb32_setup, fbcon_aty128_bmove, fbcon_cfb32_clear,
+    fbcon_aty32_putc, fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL,
+    fbcon_aty32_clear_margins,
     FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 
-#if defined(MODULE) && defined(DEBUG)
-int
+#if defined(MODULE)
+MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>, Anthony Tong "
+              "<atong@uiuc.edu>");
+MODULE_DESCRIPTION("FBDev driver for ATI Rage128 cards");
+
+int __init
 init_module(void)
 {
     aty128pci_probe();
     return 0;
 }
 
-void
+void __exit
 cleanup_module(void)
 {
-/* XXX unregister! */
+    struct fb_info_aty128 *info = board_list;
+
+    while (board_list) {
+        info = board_list;
+        board_list = board_list->next;
+
+        unregister_framebuffer(&info->fb_info);
+#ifdef CONFIG_MTRR
+        if (info->mtrr.vram_valid)
+            mtrr_del(info->mtrr.vram, info->frame_buffer_phys,
+                     info->vram_size);
+#endif /* CONFIG_MTRR */
+        iounmap(info->regbase);
+        iounmap(&info->frame_buffer);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)
+        release_mem_region(info->pdev->resource[0].start,
+                           info->pdev->resource[0].end -
+                           info->pdev->resource[0].start + 1);
+        release_mem_region(info->pdev->resource[2].start,
+                           info->pdev->resource[2].end -
+                           info->pdev->resource[2].start + 1);
+#endif
+
+        kfree(info);
+    }
 }
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.42/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.3.42/linux/drivers/video/atyfb.c	Tue Jan 11 22:31:43 2000
+++ linux/drivers/video/atyfb.c	Thu Feb 10 12:16:38 2000
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.136 2000/01/06 23:53:29 davem Exp $
+/*  $Id: atyfb.c,v 1.138 2000/02/10 02:52:12 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -460,7 +460,7 @@
 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			 u_int transp, struct fb_info *fb);
 static void do_install_cmap(int con, struct fb_info *info);
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
 static int read_aty_sense(const struct fb_info_aty *info);
 #endif
 
@@ -499,8 +499,8 @@
 static const char *mode_option __initdata = NULL;
 #endif
 
-#ifdef CONFIG_PMAC
-#ifdef CONFIG_NVRAM
+#ifdef CONFIG_PPC
+#ifdef CONFIG_NVRAM_NOT_DEFINED
 static int default_vmode __initdata = VMODE_NVRAM;
 static int default_cmode __initdata = CMODE_NVRAM;
 #else
@@ -571,7 +571,7 @@
     u32 val;
 
     temp = info->ati_regbase;
-    asm volatile("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
+    asm volatile("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b" (regindex), "r" (temp));
     return val;
 #elif defined(__mc68000__)
     return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex)));
@@ -587,7 +587,7 @@
     unsigned long temp;
 
     temp = info->ati_regbase;
-    asm volatile("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
+    asm volatile("stwbrx %0,%1,%2;eieio" : : "r" (val), "b" (regindex), "r" (temp) :
 	"memory");
 #elif defined(__mc68000__)
     *((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val);
@@ -765,9 +765,7 @@
     aty_st_8(DAC_W_INDEX, offset & 0xff, info);
     /* left addr byte */
     aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info);
-    eieio();
     aty_st_8(DAC_MASK, val, info);
-    eieio();
     aty_st_8(DAC_CNTL, 0, info);
 }
 
@@ -775,10 +773,8 @@
 {
     /* write addr byte */
     aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
-    eieio();
     /* write the register value */
     aty_st_8(CLOCK_CNTL + 2, val, info);
-    eieio();
     aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
 }
 
@@ -788,14 +784,12 @@
 
     /* write addr byte */
     aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
-    eieio();
     /* read the register value */
     res = aty_ld_8(CLOCK_CNTL + 2, info);
-    eieio();
     return res;
 }
 
-#ifdef CONFIG_PMAC
+#if defined(CONFIG_PPC)
 
     /*
      *  Apple monitor sense
@@ -835,7 +829,7 @@
     return sense;
 }
 
-#endif /* CONFIG_PMAC */
+#endif /* defined(CONFIG_PPC) */
 
 /* ------------------------------------------------------------------------- */
 
@@ -2489,7 +2483,7 @@
 	init_engine(par, info);
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
-    if (console_fb_info == &info->fb_info) {
+    if (!console_fb_info || console_fb_info == &info->fb_info) {
 	struct fb_var_screeninfo var;
 	int vmode, cmode;
 	display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
@@ -3276,7 +3270,7 @@
     struct display *disp;
     const char *chipname = NULL, *ramname = NULL, *xtal;
     int pll, mclk, gtb_memsize;
-#ifdef CONFIG_PMAC
+#if defined(CONFIG_PPC)
     int sense;
 #endif
     u8 pll_ref_div;
@@ -3365,11 +3359,15 @@
 	    } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
 		       Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
 		       Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
-		       Gx == LD_CHIP_ID || Gx == LG_CHIP_ID ||
+		       Gx == LD_CHIP_ID ||
 		       Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
 		/* RAGE PRO or LT PRO */
 		pll = 230;
 		mclk = 100;
+	    } else if (Gx == LG_CHIP_ID) {
+		/* Rage LT */
+		pll = 230;
+		mclk = 63;
 	    } else {
 		/* other RAGE */
 		pll = 135;
@@ -3538,43 +3536,47 @@
     var = default_var;
 #else /* !MODULE */
     memset(&var, 0, sizeof(var));
-#ifdef CONFIG_PMAC
-    /*
-     *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
-     *         applies to all Mac video cards
-     */
-    if (mode_option) {
-	if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
-	    var = default_var;
-    } else {
+#ifdef CONFIG_PPC
+    if (_machine == _MACH_Pmac) {
+	    /*
+	     *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
+	     *         applies to all Mac video cards
+	     */
+	    if (mode_option) {
+		if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
+		    var = default_var;
+	    } else {
 #ifdef CONFIG_NVRAM
-	if (default_vmode == VMODE_NVRAM) {
-	    default_vmode = nvram_read_byte(NV_VMODE);
-	    if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-		default_vmode = VMODE_CHOOSE;
-	}
+		if (default_vmode == VMODE_NVRAM) {
+		    default_vmode = nvram_read_byte(NV_VMODE);
+		    if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+			default_vmode = VMODE_CHOOSE;
+		}
 #endif
-	if (default_vmode == VMODE_CHOOSE) {
-	    if (Gx == LG_CHIP_ID)
-		/* G3 PowerBook with 1024x768 LCD */
-		default_vmode = VMODE_1024_768_60;
-	    else {
-		sense = read_aty_sense(info);
-		default_vmode = mac_map_monitor_sense(sense);
-	    }
-	}
-	if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-	    default_vmode = VMODE_640_480_60;
+		if (default_vmode == VMODE_CHOOSE) {
+		    if (Gx == LG_CHIP_ID)
+			/* G3 PowerBook with 1024x768 LCD */
+			default_vmode = VMODE_1024_768_60;
+		    else {
+			sense = read_aty_sense(info);
+			default_vmode = mac_map_monitor_sense(sense);
+		    }
+		}
+		if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+		    default_vmode = VMODE_640_480_60;
 #ifdef CONFIG_NVRAM
-	if (default_cmode == CMODE_NVRAM)
-	    default_cmode = nvram_read_byte(NV_CMODE);
+		if (default_cmode == CMODE_NVRAM)
+		    default_cmode = nvram_read_byte(NV_CMODE);
 #endif
-	if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
-	    default_cmode = CMODE_8;
-	if (mac_vmode_to_var(default_vmode, default_cmode, &var))
-	    var = default_var;
+		if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+		    default_cmode = CMODE_8;
+		if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+		    var = default_var;
+	    }
     }
-#else /* !CONFIG_PMAC */
+    else if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
+	var = default_var;
+#else /* !CONFIG_PPC */
 #ifdef __sparc__
     if (mode_option) {
     	if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
@@ -3585,7 +3587,7 @@
     if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
 	var = default_var;
 #endif /* !__sparc__ */
-#endif /* !CONFIG_PMAC */
+#endif /* !CONFIG_PPC */
 #endif /* !MODULE */
     if (noaccel)
         var.accel_flags &= ~FB_ACCELF_TEXT;
@@ -4264,7 +4266,6 @@
 	i |= 0x2;	/*DAC_CNTL|0x2 turns off the extra brightness for gt*/
     aty_st_8(DAC_CNTL, i, info);
     aty_st_8(DAC_MASK, 0xff, info);
-    eieio();
     scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
 	     (info->current_par.crtc.bpp == 16)) ? 3 : 0;
     info->aty_cmap_regs->windex = regno << scale;
diff -u --recursive --new-file v2.3.42/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.3.42/linux/drivers/video/chipsfb.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/video/chipsfb.c	Wed Feb  9 19:43:57 2000
@@ -727,9 +727,20 @@
 		int nb = p->var.yres * p->fix.line_length;
 
 		switch (when) {
+		case PBOOK_SLEEP_REQUEST:
+			p->save_framebuffer = vmalloc(nb);
+			if (p->save_framebuffer == NULL)
+				return PBOOK_SLEEP_REFUSE;
+			break;
+		case PBOOK_SLEEP_REJECT:
+			if (p->save_framebuffer) {
+				vfree(p->save_framebuffer);
+				p->save_framebuffer = 0;
+			}
+			break;
+
 		case PBOOK_SLEEP_NOW:
 			chipsfb_blank(1, (struct fb_info *)p);
-			p->save_framebuffer = vmalloc(nb);
 			if (p->save_framebuffer)
 				memcpy(p->save_framebuffer,
 				       p->frame_buffer, nb);
diff -u --recursive --new-file v2.3.42/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.3.42/linux/drivers/video/controlfb.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/video/controlfb.c	Wed Feb  9 19:43:57 2000
@@ -528,17 +528,23 @@
 	p->sense = read_control_sense(p);
 	printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);
 	/* Try to pick a video mode out of NVRAM if we have one. */
-	par->vmode = nvram_read_byte(NV_VMODE);
-	if(par->vmode <= 0 || par->vmode > VMODE_MAX || !control_reg_init[par->vmode - 1])
-		par->vmode = VMODE_CHOOSE;
-	if(par->vmode == VMODE_CHOOSE)
-		par->vmode = mac_map_monitor_sense(p->sense);
-	if(!control_reg_init[par->vmode - 1])
-		par->vmode = VMODE_640_480_60;
+	if (default_vmode == VMODE_NVRAM) {
+		par->vmode = nvram_read_byte(NV_VMODE);
+		if(par->vmode <= 0 || par->vmode > VMODE_MAX || !control_reg_init[par->vmode - 1])
+			par->vmode = VMODE_CHOOSE;
+		if(par->vmode == VMODE_CHOOSE)
+			par->vmode = mac_map_monitor_sense(p->sense);
+		if(!control_reg_init[par->vmode - 1])
+			par->vmode = VMODE_640_480_60;
+	} else
+		par->vmode=default_vmode;
 
-	par->cmode = nvram_read_byte(NV_CMODE);
-	if(par->cmode < CMODE_8 || par->cmode > CMODE_32)
-		par->cmode = CMODE_8;
+	if (default_cmode == CMODE_NVRAM){
+		par->cmode = nvram_read_byte(NV_CMODE);
+		if(par->cmode < CMODE_8 || par->cmode > CMODE_32)
+			par->cmode = CMODE_8;}
+	else
+		par->cmode=default_cmode;
 	/*
 	 * Reduce the pixel size if we don't have enough VRAM.
 	 */
diff -u --recursive --new-file v2.3.42/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.3.42/linux/drivers/video/cyber2000fb.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/video/cyber2000fb.c	Sun Feb  6 17:45:25 2000
@@ -29,13 +29,6 @@
 #include <video/fbcon-cfb16.h>
 #include <video/fbcon-cfb24.h>
 
-/*
- *    Some defaults
- */
-#define DEFAULT_XRES	640
-#define DEFAULT_YRES	480
-#define DEFAULT_BPP	8
-
 #define MMIO_SIZE	0x000c0000
 
 static char			*CyberRegs;
diff -u --recursive --new-file v2.3.42/linux/drivers/video/cyber2000fb.h linux/drivers/video/cyber2000fb.h
--- v2.3.42/linux/drivers/video/cyber2000fb.h	Tue Dec 14 01:27:24 1999
+++ linux/drivers/video/cyber2000fb.h	Sun Feb  6 17:45:25 2000
@@ -84,119 +84,43 @@
 #define VISUALID_16M		4
 #define VISUALID_32K		6
 
-#define K_CAP_X2_CTL1		0x49
-
-#define CAP_X_START		0x60
-#define CAP_X_END		0x62
-#define CAP_Y_START		0x64
-#define CAP_Y_END		0x66
-#define CAP_DDA_X_INIT		0x68
-#define CAP_DDA_X_INC		0x6a
-#define CAP_DDA_Y_INIT		0x6c
-#define CAP_DDA_Y_INC		0x6e
-
-#define EXT_FIFO_CTL		0x74
-
-#define CAP_PIP_X_START		0x80
-#define CAP_PIP_X_END		0x82
-#define CAP_PIP_Y_START		0x84
-#define CAP_PIP_Y_END		0x86
-
-#define CAP_NEW_CTL1		0x88
-
-#define CAP_NEW_CTL2		0x89
-
-#define CAP_MODE1		0xa4
-#define CAP_MODE1_8BIT			0x01	/* enable 8bit capture mode	*/
-#define CAP_MODE1_CCIR656		0x02	/* CCIR656 mode			*/
-#define CAP_MODE1_IGNOREVGT		0x04	/* ignore VGT			*/
-#define CAP_MODE1_ALTFIFO		0x10	/* use alternate FIFO for capture */
-#define CAP_MODE1_SWAPUV		0x20	/* swap UV bytes		*/
-#define CAP_MODE1_MIRRORY		0x40	/* mirror vertically		*/
-#define CAP_MODE1_MIRRORX		0x80	/* mirror horizontally		*/
-
-#define CAP_MODE2		0xa5
-
-#define Y_TV_CTL		0xae
-
-#define EXT_MEM_START		0xc0		/* ext start address 21 bits */
-#define HOR_PHASE_SHIFT		0xc2		/* high 3 bits */
-#define EXT_SRC_WIDTH		0xc3		/* ext offset phase  10 bits */
-#define EXT_SRC_HEIGHT		0xc4		/* high 6 bits */
-#define EXT_X_START		0xc5		/* ext->screen, 16 bits */
-#define EXT_X_END		0xc7		/* ext->screen, 16 bits */
-#define EXT_Y_START		0xc9		/* ext->screen, 16 bits */
-#define EXT_Y_END		0xcb		/* ext->screen, 16 bits */
-#define EXT_SRC_WIN_WIDTH	0xcd		/* 8 bits */
-#define EXT_COLOUR_COMPARE	0xce		/* 24 bits */
-#define EXT_DDA_X_INIT		0xd1		/* ext->screen 16 bits */
-#define EXT_DDA_X_INC		0xd3		/* ext->screen 16 bits */
-#define EXT_DDA_Y_INIT		0xd5		/* ext->screen 16 bits */
-#define EXT_DDA_Y_INC		0xd7		/* ext->screen 16 bits */
-
-#define VID_FIFO_CTL		0xd9
-
-#define VID_CAP_VFC		0xdb
-#define VID_CAP_VFC_YUV422		0x00	/* formats - does this cause conversion? */
-#define VID_CAP_VFC_RGB555		0x01
-#define VID_CAP_VFC_RGB565		0x02
-#define VID_CAP_VFC_RGB888_24		0x03
-#define VID_CAP_VFC_RGB888_32		0x04
-#define VID_CAP_VFC_DUP_PIX_ZOON	0x08	/* duplicate pixel zoom			*/
-#define VID_CAP_VFC_MOD_3RD_PIX		0x20	/* modify 3rd duplicated pixel		*/
-#define VID_CAP_VFC_DBL_H_PIX		0x40	/* double horiz pixels			*/
-#define VID_CAP_VFC_UV128		0x80	/* UV data offset by 128		*/
-
-#define VID_DISP_CTL1		0xdc
-#define VID_DISP_CTL1_INTRAM		0x01	/* video pixels go to internal RAM	*/
-#define VID_DISP_CTL1_IGNORE_CCOMP	0x02	/* ignore colour compare registers	*/
-#define VID_DISP_CTL1_NOCLIP		0x04	/* do not clip to 16235,16240		*/
-#define VID_DISP_CTL1_UV_AVG		0x08	/* U/V data is averaged			*/
-#define VID_DISP_CTL1_Y128		0x10	/* Y data offset by 128			*/
-#define VID_DISP_CTL1_VINTERPOL_OFF	0x20	/* vertical interpolation off		*/
-#define VID_DISP_CTL1_VID_OUT_WIN_FULL	0x40	/* video out window full		*/
-#define VID_DISP_CTL1_ENABLE_VID_WINDOW	0x80	/* enable video window			*/
-
-#define VID_FIFO_CTL1		0xdd
-
-#define VFAC_CTL1		0xe8
-#define VFAC_CTL1_CAPTURE		0x01	/* capture enable			*/
-#define VFAC_CTL1_VFAC_ENABLE		0x02	/* vfac enable				*/
-#define VFAC_CTL1_FREEZE_CAPTURE	0x04	/* freeze capture			*/
-#define VFAC_CTL1_FREEZE_CAPTURE_SYNC	0x08	/* sync freeze capture			*/
-#define VFAC_CTL1_VALIDFRAME_SRC	0x10	/* select valid frame source		*/
-#define VFAC_CTL1_PHILIPS		0x40	/* select Philips mode			*/
-#define VFAC_CTL1_MODVINTERPOLCLK	0x80	/* modify vertical interpolation clocl	*/
+#define FUNC_CTL		0x3c
+#define FUNC_CTL_EXTREGENBL		0x80	/* enable access to 0xbcxxx		*/
 
-#define VFAC_CTL2		0xe9
-#define VFAC_CTL2_INVERT_VIDDATAVALID	0x01	/* invert video data valid		*/
-#define VFAC_CTL2_INVERT_GRAPHREADY	0x02	/* invert graphic ready output sig	*/
-#define VFAC_CTL2_INVERT_DATACLK	0x04	/* invert data clock signal		*/
-#define VFAC_CTL2_INVERT_HSYNC		0x08	/* invert hsync input			*/
-#define VFAC_CTL2_INVERT_VSYNC		0x10	/* invert vsync input			*/
-#define VFAC_CTL2_INVERT_FRAME		0x20	/* invert frame odd/even input		*/
-#define VFAC_CTL2_INVERT_BLANK		0x40	/* invert blank output			*/
-#define VFAC_CTL2_INVERT_OVSYNC		0x80	/* invert other vsync input		*/
-
-#define VFAC_CTL3		0xea
-#define VFAC_CTL3_CAP_IRQ		0x40	/* enable capture interrupt		*/
-
-#define CAP_MEM_START		0xeb		/* 18 bits */
-#define CAP_MAP_WIDTH		0xed		/* high 6 bits */
-#define CAP_PITCH		0xee		/* 8 bits */
-
-#define CAP_CTL_MISC		0xef
-#define CAP_CTL_MISC_HDIV		0x01
-#define CAP_CTL_MISC_HDIV4		0x02
-#define CAP_CTL_MISC_ODDEVEN		0x04
-#define CAP_CTL_MISC_HSYNCDIV2		0x08
-#define CAP_CTL_MISC_SYNCTZHIGH		0x10
-#define CAP_CTL_MISC_SYNCTZOR		0x20
-#define CAP_CTL_MISC_DISPUSED		0x80
-
-#define REG_BANK		0xfa
-#define REG_BANK_Y			0x01
-#define REG_BANK_K			0x05
+#define BIU_BM_CONTROL		0x3e
+#define BIU_BM_CONTROL_ENABLE		0x01	/* enable bus-master			*/
+#define BIU_BM_CONTROL_BURST		0x02	/* enable burst				*/
+#define BIU_BM_CONTROL_BACK2BACK	0x04	/* enable back to back			*/
+
+#define X_V2_VID_MEM_START	0x40
+#define X_V2_VID_SRC_WIDTH	0x43
+#define X_V2_X_START		0x45
+#define X_V2_X_END		0x47
+#define X_V2_Y_START		0x49
+#define X_V2_Y_END		0x4b
+#define X_V2_VID_SRC_WIN_WIDTH	0x4d
+
+#define Y_V2_DDA_X_INC		0x43
+#define Y_V2_DDA_Y_INC		0x47
+#define Y_V2_VID_FIFO_CTL	0x49
+#define Y_V2_VID_FMT		0x4b
+#define Y_V2_VID_DISP_CTL1	0x4c
+#define Y_V2_VID_FIFO_CTL1	0x4d
+
+#define J_X2_VID_MEM_START	0x40
+#define J_X2_VID_SRC_WIDTH	0x43
+#define J_X2_X_START		0x47
+#define J_X2_X_END		0x49
+#define J_X2_Y_START		0x4b
+#define J_X2_Y_END		0x4d
+#define J_X2_VID_SRC_WIN_WIDTH	0x4f
+
+#define K_X2_DDA_X_INIT		0x40
+#define K_X2_DDA_X_INC		0x42
+#define K_X2_DDA_Y_INIT		0x44
+#define K_X2_DDA_Y_INC		0x46
+#define K_X2_VID_FMT		0x48
+#define K_X2_VID_DISP_CTL1	0x49
 
 #define K_CAP_X2_CTL1		0x49
 
@@ -221,57 +145,57 @@
 #define CAP_NEW_CTL2		0x89
 
 #define CAP_MODE1		0xa4
-#define CAP_MODE1_8BIT			0x01	/* enable 8bit capture mode	*/
-#define CAP_MODE1_CCIR656		0x02	/* CCIR656 mode			*/
-#define CAP_MODE1_IGNOREVGT		0x04	/* ignore VGT			*/
-#define CAP_MODE1_ALTFIFO		0x10	/* use alternate FIFO for capture */
-#define CAP_MODE1_SWAPUV		0x20	/* swap UV bytes		*/
-#define CAP_MODE1_MIRRORY		0x40	/* mirror vertically		*/
-#define CAP_MODE1_MIRRORX		0x80	/* mirror horizontally		*/
+#define CAP_MODE1_8BIT			0x01	/* enable 8bit capture mode		*/
+#define CAP_MODE1_CCIR656		0x02	/* CCIR656 mode				*/
+#define CAP_MODE1_IGNOREVGT		0x04	/* ignore VGT				*/
+#define CAP_MODE1_ALTFIFO		0x10	/* use alternate FIFO for capture	*/
+#define CAP_MODE1_SWAPUV		0x20	/* swap UV bytes			*/
+#define CAP_MODE1_MIRRORY		0x40	/* mirror vertically			*/
+#define CAP_MODE1_MIRRORX		0x80	/* mirror horizontally			*/
 
 #define CAP_MODE2		0xa5
 
 #define Y_TV_CTL		0xae
 
-#define EXT_MEM_START		0xc0		/* ext start address 21 bits */
-#define HOR_PHASE_SHIFT		0xc2		/* high 3 bits */
-#define EXT_SRC_WIDTH		0xc3		/* ext offset phase  10 bits */
-#define EXT_SRC_HEIGHT		0xc4		/* high 6 bits */
-#define EXT_X_START		0xc5		/* ext->screen, 16 bits */
-#define EXT_X_END		0xc7		/* ext->screen, 16 bits */
-#define EXT_Y_START		0xc9		/* ext->screen, 16 bits */
-#define EXT_Y_END		0xcb		/* ext->screen, 16 bits */
-#define EXT_SRC_WIN_WIDTH	0xcd		/* 8 bits */
-#define EXT_COLOUR_COMPARE	0xce		/* 24 bits */
-#define EXT_DDA_X_INIT		0xd1		/* ext->screen 16 bits */
-#define EXT_DDA_X_INC		0xd3		/* ext->screen 16 bits */
-#define EXT_DDA_Y_INIT		0xd5		/* ext->screen 16 bits */
-#define EXT_DDA_Y_INC		0xd7		/* ext->screen 16 bits */
-
-#define VID_FIFO_CTL		0xd9
-
-#define VID_CAP_VFC		0xdb
-#define VID_CAP_VFC_YUV422		0x00	/* formats - does this cause conversion? */
-#define VID_CAP_VFC_RGB555		0x01
-#define VID_CAP_VFC_RGB565		0x02
-#define VID_CAP_VFC_RGB888_24		0x03
-#define VID_CAP_VFC_RGB888_32		0x04
-#define VID_CAP_VFC_DUP_PIX_ZOON	0x08	/* duplicate pixel zoom			*/
-#define VID_CAP_VFC_MOD_3RD_PIX		0x20	/* modify 3rd duplicated pixel		*/
-#define VID_CAP_VFC_DBL_H_PIX		0x40	/* double horiz pixels			*/
-#define VID_CAP_VFC_UV128		0x80	/* UV data offset by 128		*/
-
-#define VID_DISP_CTL1		0xdc
-#define VID_DISP_CTL1_INTRAM		0x01	/* video pixels go to internal RAM	*/
-#define VID_DISP_CTL1_IGNORE_CCOMP	0x02	/* ignore colour compare registers	*/
-#define VID_DISP_CTL1_NOCLIP		0x04	/* do not clip to 16235,16240		*/
-#define VID_DISP_CTL1_UV_AVG		0x08	/* U/V data is averaged			*/
-#define VID_DISP_CTL1_Y128		0x10	/* Y data offset by 128			*/
-#define VID_DISP_CTL1_VINTERPOL_OFF	0x20	/* vertical interpolation off		*/
-#define VID_DISP_CTL1_VID_OUT_WIN_FULL	0x40	/* video out window full		*/
-#define VID_DISP_CTL1_ENABLE_VID_WINDOW	0x80	/* enable video window			*/
+#define EXT_MEM_START		0xc0		/* ext start address 21 bits		*/
+#define HOR_PHASE_SHIFT		0xc2		/* high 3 bits				*/
+#define EXT_SRC_WIDTH		0xc3		/* ext offset phase  10 bits		*/
+#define EXT_SRC_HEIGHT		0xc4		/* high 6 bits				*/
+#define EXT_X_START		0xc5		/* ext->screen, 16 bits			*/
+#define EXT_X_END		0xc7		/* ext->screen, 16 bits			*/
+#define EXT_Y_START		0xc9		/* ext->screen, 16 bits			*/
+#define EXT_Y_END		0xcb		/* ext->screen, 16 bits			*/
+#define EXT_SRC_WIN_WIDTH	0xcd		/* 8 bits				*/
+#define EXT_COLOUR_COMPARE	0xce		/* 24 bits				*/
+#define EXT_DDA_X_INIT		0xd1		/* ext->screen 16 bits			*/
+#define EXT_DDA_X_INC		0xd3		/* ext->screen 16 bits			*/
+#define EXT_DDA_Y_INIT		0xd5		/* ext->screen 16 bits			*/
+#define EXT_DDA_Y_INC		0xd7		/* ext->screen 16 bits			*/
+
+#define EXT_VID_FIFO_CTL	0xd9
+
+#define EXT_VID_FMT		0xdb
+#define EXT_VID_FMT_YUV422		0x00	/* formats - does this cause conversion? */
+#define EXT_VID_FMT_RGB555		0x01
+#define EXT_VID_FMT_RGB565		0x02
+#define EXT_VID_FMT_RGB888_24		0x03
+#define EXT_VID_FMT_RGB888_32		0x04
+#define EXT_VID_FMT_DUP_PIX_ZOON	0x08	/* duplicate pixel zoom			*/
+#define EXT_VID_FMT_MOD_3RD_PIX		0x20	/* modify 3rd duplicated pixel		*/
+#define EXT_VID_FMT_DBL_H_PIX		0x40	/* double horiz pixels			*/
+#define EXT_VID_FMT_UV128		0x80	/* UV data offset by 128		*/
+
+#define EXT_VID_DISP_CTL1	0xdc
+#define EXT_VID_DISP_CTL1_INTRAM	0x01	/* video pixels go to internal RAM	*/
+#define EXT_VID_DISP_CTL1_IGNORE_CCOMP	0x02	/* ignore colour compare registers	*/
+#define EXT_VID_DISP_CTL1_NOCLIP	0x04	/* do not clip to 16235,16240		*/
+#define EXT_VID_DISP_CTL1_UV_AVG	0x08	/* U/V data is averaged			*/
+#define EXT_VID_DISP_CTL1_Y128		0x10	/* Y data offset by 128			*/
+#define EXT_VID_DISP_CTL1_VINTERPOL_OFF	0x20	/* vertical interpolation off		*/
+#define EXT_VID_DISP_CTL1_FULL_WIN	0x40	/* video out window full		*/
+#define EXT_VID_DISP_CTL1_ENABLE_WINDOW	0x80	/* enable video window			*/
 
-#define VID_FIFO_CTL1		0xdd
+#define EXT_VID_FIFO_CTL1	0xdd
 
 #define VFAC_CTL1		0xe8
 #define VFAC_CTL1_CAPTURE		0x01	/* capture enable			*/
@@ -293,10 +217,11 @@
 #define VFAC_CTL2_INVERT_OVSYNC		0x80	/* invert other vsync input		*/
 
 #define VFAC_CTL3		0xea
+#define VFAC_CTL3_CAP_IRQ		0x40	/* enable capture interrupt		*/
 
-#define CAP_MEM_START		0xeb		/* 18 bits */
-#define CAP_MAP_WIDTH		0xed		/* high 6 bits */
-#define CAP_PITCH		0xee		/* 8 bits */
+#define CAP_MEM_START		0xeb		/* 18 bits				*/
+#define CAP_MAP_WIDTH		0xed		/* high 6 bits				*/
+#define CAP_PITCH		0xee		/* 8 bits				*/
 
 #define CAP_CTL_MISC		0xef
 #define CAP_CTL_MISC_HDIV		0x01
@@ -308,10 +233,27 @@
 #define CAP_CTL_MISC_DISPUSED		0x80
 
 #define REG_BANK		0xfa
+#define REG_BANK_X			0x00
 #define REG_BANK_Y			0x01
+#define REG_BANK_W			0x02
+#define REG_BANK_T			0x03
+#define REG_BANK_J			0x04
 #define REG_BANK_K			0x05
 
-
+/*
+ * Bus-master
+ */
+#define BM_ADDRESS_LOW		0xbc080
+#define BM_ADDRESS_HIGH		0xbc084
+#define BM_LENGTH		0xbc088
+#define BM_CONTROL		0xbc08c
+#define BM_CONTROL_ENABLE		0x01	/* enable transfer			*/
+#define BM_CONTROL_INIT			0x04	/* initialise status & count		*/
+#define BM_COUNT		0xbc090		/* read-only				*/
+
+/*
+ * Graphics Co-processor
+ */
 #define CO_CMD_L_PATTERN_FGCOL	0x8000
 #define CO_CMD_L_INC_LEFT	0x0004
 #define CO_CMD_L_INC_UP		0x0002
diff -u --recursive --new-file v2.3.42/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.42/linux/drivers/video/fbmem.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/video/fbmem.c	Wed Feb  9 11:42:35 2000
@@ -550,17 +550,12 @@
 }
 
 static struct file_operations fb_fops = {
-	NULL,		/* lseek	*/
-	fb_read,	/* read		*/
-	fb_write,	/* write	*/
-	NULL,		/* readdir 	*/
-	NULL,		/* poll 	*/
-	fb_ioctl,	/* ioctl 	*/
-	fb_mmap,	/* mmap		*/
-	fb_open,	/* open 	*/
-	NULL,		/* flush	*/
-	fb_release,	/* release 	*/
-	NULL		/* fsync 	*/
+	read:		fb_read,
+	write:		fb_write,
+	ioctl:		fb_ioctl,
+	mmap:		fb_mmap,
+	open:		fb_open,
+	release:	fb_release,
 };
 
 int
@@ -720,6 +715,8 @@
 
 EXPORT_SYMBOL(register_framebuffer);
 EXPORT_SYMBOL(unregister_framebuffer);
+EXPORT_SYMBOL(registered_fb);
+EXPORT_SYMBOL(num_registered_fb);
 #if 1 /* to go away in 2.4.0 */
 EXPORT_SYMBOL(GET_FB_IDX);
 #endif
diff -u --recursive --new-file v2.3.42/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.3.42/linux/drivers/video/offb.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/video/offb.c	Wed Feb  9 19:43:57 2000
@@ -51,6 +51,7 @@
     struct { u_char red, green, blue, pad; } palette[256];
     volatile unsigned char *cmap_adr;
     volatile unsigned char *cmap_data;
+    int is_rage_128;
     union {
 #ifdef FBCON_HAS_CFB16
 	u16 cfb16[16];
@@ -107,7 +108,8 @@
 static int offb_init_driver(struct device_node *);
 static void offb_init_nodriver(struct device_node *);
 static void offb_init_fb(const char *name, const char *full_name, int width,
-		      int height, int depth, int pitch, unsigned long address);
+		      int height, int depth, int pitch, unsigned long address,
+		      struct device_node *dp);
 
     /*
      *  Interface to the low level console driver
@@ -390,7 +392,7 @@
 			 boot_infos->dispDeviceRect[2],
 			 boot_infos->dispDeviceRect[3],
 			 boot_infos->dispDeviceDepth,
-			 boot_infos->dispDeviceRowBytes, addr);
+			 boot_infos->dispDeviceRowBytes, addr, NULL);
 	}
     }
 
@@ -518,13 +520,14 @@
 	    address += 0x1000;
     }
     offb_init_fb(dp->name, dp->full_name, width, height, depth,
-		 pitch, address);
+		 pitch, address, dp);
     
 }
 
 static void offb_init_fb(const char *name, const char *full_name,
 				    int width, int height, int depth,
-				    int pitch, unsigned long address)
+				    int pitch, unsigned long address,
+				    struct device_node *dp)
 {
     int i;
     struct fb_fix_screeninfo *fix;
@@ -569,10 +572,18 @@
     fix->type = FB_TYPE_PACKED_PIXELS;
     fix->type_aux = 0;
 
+    info->is_rage_128 = 0;
     if (depth == 8)
     {
     	/* XXX kludge for ati */
-    	if (strncmp(name, "ATY,", 4) == 0) {
+	if (strncmp(name, "ATY,Rage128", 11) == 0) {
+	    if (dp) {
+		unsigned long regbase = dp->addrs[2].address;
+		info->cmap_adr = ioremap(regbase, 0x1FFF) + 0x00b0;
+		info->cmap_data = info->cmap_adr + 4;
+		info->is_rage_128 = 1;
+	    }
+	} else if (strncmp(name, "ATY,", 4) == 0) {
 		unsigned long base = address & 0xff000000UL;
 		info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
 		info->cmap_data = info->cmap_adr + 1;
@@ -853,12 +864,17 @@
 
     *info2->cmap_adr = regno;/* On some chipsets, add << 3 in 15 bits */
     mach_eieio();
-    *info2->cmap_data = red;
-    mach_eieio();
-    *info2->cmap_data = green;
-    mach_eieio();
-    *info2->cmap_data = blue;
-    mach_eieio();
+    if (info2->is_rage_128) {
+    	out_le32((unsigned int *)info2->cmap_data,
+    		(red << 16 | green << 8 | blue));
+    } else {
+	*info2->cmap_data = red;
+    	mach_eieio();
+    	*info2->cmap_data = green;
+    	mach_eieio();
+    	*info2->cmap_data = blue;
+    	mach_eieio();
+    }
 
     if (regno < 16)
 	switch (info2->var.bits_per_pixel) {
diff -u --recursive --new-file v2.3.42/linux/drivers/zorro/proc.c linux/drivers/zorro/proc.c
--- v2.3.42/linux/drivers/zorro/proc.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/zorro/proc.c	Wed Feb  9 11:42:35 2000
@@ -73,17 +73,8 @@
 }
 
 static struct file_operations proc_bus_zorro_operations = {
-	proc_bus_zorro_lseek,
-	proc_bus_zorro_read,
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* can't fsync */
+	llseek:		proc_bus_zorro_lseek,
+	read:		proc_bus_zorro_read,
 };
 
 static struct inode_operations proc_bus_zorro_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/Config.in linux/fs/Config.in
--- v2.3.42/linux/fs/Config.in	Fri Jan 28 15:09:08 2000
+++ linux/fs/Config.in	Sun Feb  6 18:43:21 2000
@@ -15,8 +15,7 @@
 
 dep_tristate 'Apple Macintosh filesystem support (EXPERIMENTAL)' CONFIG_HFS_FS $CONFIG_EXPERIMENTAL
 
-dep_tristate 'BFS filesystem (read only) support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
-dep_bool '  BFS filesystem write support (DANGEROUS)' CONFIG_BFS_FS_WRITE $CONFIG_BFS_FS
+dep_tristate 'BFS filesystem support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
 
 # msdos filesystems
 tristate 'DOS FAT fs support' CONFIG_FAT_FS
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/Makefile linux/fs/adfs/Makefile
--- v2.3.42/linux/fs/adfs/Makefile	Wed Jun 24 14:30:09 1998
+++ linux/fs/adfs/Makefile	Sun Feb  6 17:45:25 2000
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
 O_TARGET := adfs.o
-O_OBJS   := dir.o file.o inode.o map.o namei.o super.o
+O_OBJS   := dir.o dir_f.o dir_fplus.o file.o inode.o map.o super.o
 M_OBJS   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/adfs.h linux/fs/adfs/adfs.h
--- v2.3.42/linux/fs/adfs/adfs.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/adfs/adfs.h	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,134 @@
+/* Internal data structures for ADFS */
+
+#define ADFS_FREE_FRAG		 0
+#define ADFS_BAD_FRAG		 1
+#define ADFS_ROOT_FRAG		 2
+
+#define ADFS_NDA_OWNER_READ	(1 << 0)
+#define ADFS_NDA_OWNER_WRITE	(1 << 1)
+#define ADFS_NDA_LOCKED		(1 << 2)
+#define ADFS_NDA_DIRECTORY	(1 << 3)
+#define ADFS_NDA_EXECUTE	(1 << 4)
+#define ADFS_NDA_PUBLIC_READ	(1 << 5)
+#define ADFS_NDA_PUBLIC_WRITE	(1 << 6)
+
+#include "dir_f.h"
+
+/*
+ * Directory handling
+ */
+struct adfs_dir {
+	struct super_block	*sb;
+
+	int			nr_buffers;
+	struct buffer_head	*bh[4];
+	unsigned int		pos;
+	unsigned int		parent_id;
+
+	struct adfs_dirheader	dirhead;
+	union  adfs_dirtail	dirtail;
+};
+
+/*
+ * This is the overall maximum name length
+ */
+#define ADFS_MAX_NAME_LEN	256
+struct object_info {
+	__u32		parent_id;		/* parent object id	*/
+	__u32		file_id;		/* object id		*/
+	__u32		loadaddr;		/* load address		*/
+	__u32		execaddr;		/* execution address	*/
+	__u32		size;			/* size			*/
+	__u8		attr;			/* RISC OS attributes	*/
+	unsigned char	name_len;		/* name length		*/
+	char		name[ADFS_MAX_NAME_LEN];/* file name		*/
+};
+
+struct adfs_dir_ops {
+	int	(*read)(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir);
+	int	(*setpos)(struct adfs_dir *dir, unsigned int fpos);
+	int	(*getnext)(struct adfs_dir *dir, struct object_info *obj);
+	int	(*update)(struct adfs_dir *dir, struct object_info *obj);
+	int	(*create)(struct adfs_dir *dir, struct object_info *obj);
+	int	(*remove)(struct adfs_dir *dir, struct object_info *obj);
+	void	(*free)(struct adfs_dir *dir);
+};
+
+struct adfs_discmap {
+	struct buffer_head	*dm_bh;
+	__u32			dm_startblk;
+	unsigned int		dm_startbit;
+	unsigned int		dm_endbit;
+};
+
+/* dir stuff */
+
+
+/* Inode stuff */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+int adfs_get_block(struct inode *inode, long block,
+		   struct buffer_head *bh, int create);
+#else
+int adfs_bmap(struct inode *inode, int block);
+#endif
+struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
+void adfs_read_inode(struct inode *inode);
+void adfs_write_inode(struct inode *inode);
+int adfs_notify_change(struct dentry *dentry, struct iattr *attr);
+
+/* map.c */
+extern int adfs_map_lookup(struct super_block *sb, int frag_id, int offset);
+extern unsigned int adfs_map_free(struct super_block *sb);
+
+/* Misc */
+void __adfs_error(struct super_block *sb, const char *function,
+		  const char *fmt, ...);
+#define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
+
+/* namei.c */
+extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry);
+
+/* super.c */
+
+/*
+ * Inodes and file operations
+ */
+
+/* dir_*.c */
+extern struct inode_operations adfs_dir_inode_operations;
+extern struct adfs_dir_ops adfs_f_dir_ops;
+extern struct adfs_dir_ops adfs_fplus_dir_ops;
+
+extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
+
+/* file.c */
+extern struct inode_operations adfs_file_inode_operations;
+
+extern inline __u32 signed_asl(__u32 val, signed int shift)
+{
+	if (shift >= 0)
+		val <<= shift;
+	else
+		val >>= -shift;
+	return val;
+}
+
+/*
+ * Calculate the address of a block in an object given the block offset
+ * and the object identity.
+ *
+ * The root directory ID should always be looked up in the map [3.4]
+ */
+extern inline int
+__adfs_block_map(struct super_block *sb, unsigned int object_id,
+		 unsigned int block)
+{
+	if (object_id & 255) {
+		unsigned int off;
+
+		off = (object_id & 255) - 1;
+		block += off << sb->u.adfs_sb.s_log2sharesize;
+	}
+
+	return adfs_map_lookup(sb, object_id >> 8, block);
+}
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/dir.c linux/fs/adfs/dir.c
--- v2.3.42/linux/fs/adfs/dir.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/adfs/dir.c	Thu Feb 10 12:16:57 2000
@@ -1,345 +1,302 @@
 /*
- *  linux/fs/adfs/dir.c
+ * linux/fs/adfs/dir.c
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1999 Russell King
+ *
+ * Common directory handling for ADFS
  */
-
+#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
 #include <linux/sched.h>
 #include <linux/stat.h>
 
-static ssize_t adfs_dirread (struct file *filp, char *buf,
-			     size_t siz, loff_t *ppos)
-{
-	return -EISDIR;
-}
-
-static int adfs_readdir (struct file *, void *, filldir_t);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
 
-static struct file_operations adfs_dir_operations = {
-	NULL,			/* lseek - default */
-	adfs_dirread,		/* read */
-	NULL,			/* write - bad */
-	adfs_readdir,		/* readdir */
-	NULL,			/* select - default */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync,		/* fsync */
-	NULL,			/* fasync */
-};
+#include "adfs.h"
 
 /*
- * directories can handle most operations...
+ * For future.  This should probably be per-directory.
  */
-struct inode_operations adfs_dir_inode_operations = {
-	&adfs_dir_operations,	/* default directory file-ops */
-	NULL,			/* create */
-	adfs_lookup,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* read link */
-	NULL,			/* follow link */
-	NULL,			/* get_block */
-	NULL,			/* read page */
-	NULL,			/* write page */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
-};
+static rwlock_t adfs_dir_lock;
 
-unsigned int adfs_val (unsigned char *p, int len)
+static int
+adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-	unsigned int val = 0;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block *sb = filp->f_dentry->d_sb;
+	struct adfs_dir_ops *ops = sb->u.adfs_sb.s_dir;
+	struct object_info obj;
+	struct adfs_dir dir;
+	int ret;
+
+	ret = ops->read(sb, inode->i_ino, inode->i_size, &dir);
+	if (ret)
+		goto out;
+
+	switch (filp->f_pos) {
+	case 0:
+		if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0)
+			goto free_out;
+		filp->f_pos += 1;
+
+	case 1:
+		if (filldir(dirent, "..", 2, 1, dir.parent_id) < 0)
+			goto free_out;
+		filp->f_pos += 1;
 
-	switch (len) {
-	case 4:
-		val |= p[3] << 24;
-	case 3:
-		val |= p[2] << 16;
-	case 2:
-		val |= p[1] << 8;
 	default:
-		val |= p[0];
+		break;
 	}
-	return val;
-}
-
-static unsigned int adfs_filetype (unsigned int load)
-{
-	if ((load & 0xfff00000) != 0xfff00000)
-		return (unsigned int) -1;
-	return (load >> 8) & 0xfff;
-}
-
-static unsigned int adfs_time (unsigned int load, unsigned int exec)
-{
-	unsigned int high, low;
 
-	/* Check for unstamped files.  */
-	if ((load & 0xfff00000) != 0xfff00000)
-		return 0;
+	read_lock(&adfs_dir_lock);
 
-	high = ((load << 24) | (exec >> 8));
-	low  =  exec & 255;
+	ret = ops->setpos(&dir, filp->f_pos - 2);
+	if (ret)
+		goto unlock_out;
+	while (ops->getnext(&dir, &obj) == 0) {
+		if (filldir(dirent, obj.name, obj.name_len,
+			    filp->f_pos, obj.file_id) < 0)
+			goto unlock_out;
+		filp->f_pos += 1;
+	}
 
-	/* Files dated pre 1970.  */
-	if (high < 0x336e996a)
-		return 0;
+unlock_out:
+	read_unlock(&adfs_dir_lock);
 
-	high -= 0x336e996a;
+free_out:
+	ops->free(&dir);
 
-	/* Files dated post 2038 ish.  */
-	if (high > 0x31ffffff)
-		return 0x7fffffff;
-
-	/* 65537 = h256,l1
-	 * (h256 % 100) = 56         h256 / 100 = 2
-	 *    56 << 8 = 14336           2 * 256 = 512
-	 *      + l1 = 14337
-	 *        / 100 = 143
-	 *          + 512 = 655
-	 */
-	return (((high % 100) << 8) + low) / 100 + (high / 100 << 8);
+out:
+	return ret;
 }
 
-int adfs_readname (char *buf, char *ptr, int maxlen)
+int
+adfs_dir_update(struct super_block *sb, struct object_info *obj)
 {
-	int size = 0;
-	while (*ptr >= ' ' && maxlen--) {
-		switch (*ptr) {
-		case '/':
-			*buf++ = '.';
-			break;
-		default:
-			*buf++ = *ptr;
-			break;
-		}
-		ptr++;
-		size ++;
-	}
-	*buf = '\0';
-	return size;
-}
-
-int adfs_dir_read_parent (struct inode *inode, struct buffer_head **bhp)
-{
-	struct super_block *sb;
-	int i, size;
+	struct adfs_dir_ops *ops = sb->u.adfs_sb.s_dir;
+	struct adfs_dir dir;
+	int ret = -EINVAL;
 
-	sb = inode->i_sb;
-
-	size = 2048 >> sb->s_blocksize_bits;
-
-	for (i = 0; i < size; i++) {
-		int block;
-
-		block = adfs_parent_bmap (inode, i);
-		if (block)
-			bhp[i] = bread (sb->s_dev, block, sb->s_blocksize);
-		else
-			adfs_error (sb, "adfs_dir_read_parent",
-				    "directory %lu with a hole at offset %d", inode->i_ino, i);
-		if (!block || !bhp[i]) {
-			int j;
-			for (j = i - 1; j >= 0; j--)
-				brelse (bhp[j]);
-			return 0;
-		}
+	printk(KERN_INFO "adfs_dir_update: object %06X in dir %06X\n",
+		 obj->file_id, obj->parent_id);
+#if 0
+	if (!ops->update) {
+		ret = -EINVAL;
+		goto out;
 	}
-	return i;
+
+	ret = ops->read(sb, obj->parent_id, 0, &dir);
+	if (ret)
+		goto out;
+
+	write_lock(&adfs_dir_lock);
+	ret = ops->update(&dir, obj);
+	write_unlock(&adfs_dir_lock);
+
+	ops->free(&dir);
+out:
+#endif
+	return ret;
 }
 
-int adfs_dir_read (struct inode *inode, struct buffer_head **bhp)
+static int
+adfs_match(struct qstr *name, struct object_info *obj)
 {
-	struct super_block *sb;
-	int i, size;
+	int i;
 
-	if (!inode || !S_ISDIR(inode->i_mode))
+	if (name->len != obj->name_len)
 		return 0;
 
-	sb = inode->i_sb;
+	for (i = 0; i < name->len; i++) {
+		char c1, c2;
 
-	size = inode->i_size >> sb->s_blocksize_bits;
+		c1 = name->name[i];
+		c2 = obj->name[i];
 
-	for (i = 0; i < size; i++) {
-		int block;
+		if (c1 >= 'A' && c1 <= 'Z')
+			c1 += 'a' - 'A';
+		if (c2 >= 'A' && c2 <= 'Z')
+			c2 += 'a' - 'A';
 
-		block = adfs_bmap (inode, i);
-		if (block)
-			bhp[i] = bread (sb->s_dev, block, sb->s_blocksize);
-		else
-			adfs_error (sb, "adfs_dir_read",
-				    "directory %lX,%lX with a hole at offset %d",
-				    inode->i_ino, inode->u.adfs_i.file_id, i);
-		if (!block || !bhp[i]) {
-			int j;
-			for (j = i - 1; j >= 0; j--)
-				brelse (bhp[j]);
+		if (c1 != c2)
 			return 0;
-		}
 	}
-	return i;
+	return 1;
 }
 
-int adfs_dir_check (struct inode *inode, struct buffer_head **bhp, int buffers, union adfs_dirtail *dtp)
+static int
+adfs_dir_lookup_byname(struct inode *inode, struct qstr *name, struct object_info *obj)
 {
-	struct adfs_dirheader dh;
-	union adfs_dirtail dt;
+	struct super_block *sb = inode->i_sb;
+	struct adfs_dir_ops *ops = sb->u.adfs_sb.s_dir;
+	struct adfs_dir dir;
+	int ret;
+
+	ret = ops->read(sb, inode->i_ino, inode->i_size, &dir);
+	if (ret)
+		goto out;
+
+	if (inode->u.adfs_i.parent_id != dir.parent_id) {
+		adfs_error(sb, "parent directory changed under me! (%lx but got %lx)\n",
+			   inode->u.adfs_i.parent_id, dir.parent_id);
+		ret = -EIO;
+		goto free_out;
+	}
 
-	memcpy (&dh, bhp[0]->b_data, sizeof (dh));
-	memcpy (&dt, bhp[3]->b_data + 471, sizeof(dt));
+	obj->parent_id = inode->i_ino;
 
-	if (memcmp (&dh.startmasseq, &dt.new.endmasseq, 5) ||
-	    (memcmp (&dh.startname, "Nick", 4) &&
-	     memcmp (&dh.startname, "Hugo", 4))) {
-		adfs_error (inode->i_sb, "adfs_check_dir",
-			    "corrupted directory inode %lX,%lX",
-			    inode->i_ino, inode->u.adfs_i.file_id);
-		return 1;
+	/*
+	 * '.' is handled by reserved_lookup() in fs/namei.c
+	 */
+	if (name->len == 2 && name->name[0] == '.' && name->name[1] == '.') {
+		/*
+		 * Currently unable to fill in the rest of 'obj',
+		 * but this is better than nothing.  We need to
+		 * ascend one level to find it's parent.
+		 */
+		obj->name_len = 0;
+		obj->file_id  = obj->parent_id;
+		goto free_out;
 	}
-	if (dtp)
-		*dtp = dt;
-	return 0;
-}
 
-void adfs_dir_free (struct buffer_head **bhp, int buffers)
-{
-	int i;
+	read_lock(&adfs_dir_lock);
 
-	for (i = buffers - 1; i >= 0; i--)
-		brelse (bhp[i]);
+	ret = ops->setpos(&dir, 0);
+	if (ret)
+		goto unlock_out;
+
+	ret = -ENOENT;
+	while (ops->getnext(&dir, obj) == 0) {
+		if (adfs_match(name, obj)) {
+			ret = 0;
+			break;
+		}
+	}
+
+unlock_out:
+	read_unlock(&adfs_dir_lock);
+
+free_out:
+	ops->free(&dir);
+out:
+	return ret;
 }
 
-/* convert a disk-based directory entry to a Linux ADFS directory entry */
-static inline void
-adfs_dirent_to_idirent(struct adfs_idir_entry *ide, struct adfs_direntry *de)
+static ssize_t
+adfs_dir_no_read(struct file *filp, char *buf, size_t siz, loff_t *ppos)
 {
-	ide->name_len =	adfs_readname(ide->name, de->dirobname, ADFS_NAME_LEN);
-	ide->file_id  = adfs_val(de->dirinddiscadd, 3);
-	ide->size     = adfs_val(de->dirlen, 4);
-	ide->mode     = de->newdiratts;
-	ide->mtime    = adfs_time(adfs_val(de->dirload, 4), adfs_val(de->direxec, 4));
-	ide->filetype = adfs_filetype(adfs_val(de->dirload, 4));
+	return -EISDIR;
 }
 
-int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp,
-		  int buffers, int pos, unsigned long parent_object_id,
-		  struct adfs_idir_entry *ide)
-{
-	struct adfs_direntry de;
-	int thissize, buffer, offset;
+static struct file_operations adfs_dir_operations = {
+	read:		adfs_dir_no_read,
+	readdir:	adfs_readdir,
+	fsync:		file_fsync,
+};
 
-	offset = pos & (sb->s_blocksize - 1);
-	buffer = pos >> sb->s_blocksize_bits;
+static int
+adfs_hash(struct dentry *parent, struct qstr *qstr)
+{
+	const unsigned int name_len = parent->d_sb->u.adfs_sb.s_namelen;
+	const unsigned char *name;
+	unsigned long hash;
+	int i;
 
-	if (buffer > buffers)
+	if (qstr->len < name_len)
 		return 0;
 
-	thissize = sb->s_blocksize - offset;
-	if (thissize > 26)
-		thissize = 26;
-
-	memcpy (&de, bhp[buffer]->b_data + offset, thissize);
-	if (thissize != 26)
-		memcpy (((char *)&de) + thissize, bhp[buffer + 1]->b_data, 26 - thissize);
+	/*
+	 * Truncate the name in place, avoids
+	 * having to define a compare function.
+	 */
+	qstr->len = i = name_len;
+	name = qstr->name;
+	hash = init_name_hash();
+	while (i--) {
+		char c;
+
+		c = *name++;
+		if (c >= 'A' && c <= 'Z')
+			c += 'a' - 'A';
 
-	if (!de.dirobname[0])
-		return 0;
+		hash = partial_name_hash(c, hash);
+	}
+	qstr->hash = end_name_hash(hash);
 
-	ide->inode_no = adfs_inode_generate (parent_object_id, pos);
-	adfs_dirent_to_idirent(ide, &de);
-	return 1;
+	return 0;
 }
 
-int adfs_dir_find_entry (struct super_block *sb, struct buffer_head **bhp,
-			 int buffers, unsigned int pos,
-			 struct adfs_idir_entry *ide)
+/*
+ * Compare two names, taking note of the name length
+ * requirements of the underlying filesystem.
+ */
+static int
+adfs_compare(struct dentry *parent, struct qstr *entry, struct qstr *name)
 {
-	struct adfs_direntry de;
-	int offset, buffer, thissize;
-
-	offset = pos & (sb->s_blocksize - 1);
-	buffer = pos >> sb->s_blocksize_bits;
-
-	if (buffer > buffers)
-		return 0;
-
-	thissize = sb->s_blocksize - offset;
-	if (thissize > 26)
-		thissize = 26;
-
-	memcpy (&de, bhp[buffer]->b_data + offset, thissize);
-	if (thissize != 26)
-		memcpy (((char *)&de) + thissize, bhp[buffer + 1]->b_data, 26 - thissize);
-
-	if (!de.dirobname[0])
-		return 0;
+	int i;
 
-	adfs_dirent_to_idirent(ide, &de);
-	return 1;
-}	
+	if (entry->len != name->len)
+		return 1;
 
-static int adfs_readdir (struct file *filp, void *dirent, filldir_t filldir)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-	struct super_block *sb;
-	struct buffer_head *bh[4];
-	union  adfs_dirtail dt;
-	unsigned long parent_object_id, dir_object_id;
-	int buffers, pos;
-
-	sb = inode->i_sb;
-
-	if (filp->f_pos > ADFS_NUM_DIR_ENTRIES + 2)
-		return -ENOENT;
-
-	if (!(buffers = adfs_dir_read (inode, bh))) {
-		adfs_error (sb, "adfs_readdir", "unable to read directory");
-		return -EINVAL;
-	}
+	for (i = 0; i < name->len; i++) {
+		char a, b;
 
-	if (adfs_dir_check (inode, bh, buffers, &dt)) {
-		adfs_dir_free (bh, buffers);
-		return -ENOENT;
-	}
+		a = entry->name[i];
+		b = name->name[i];
 
-	parent_object_id = adfs_val (dt.new.dirparent, 3);
-	dir_object_id = adfs_inode_objid (inode);
+		if (a >= 'A' && a <= 'Z')
+			a += 'a' - 'A';
+		if (b >= 'A' && b <= 'Z')
+			b += 'a' - 'A';
 
-	if (filp->f_pos < 2) {
-		if (filp->f_pos < 1) {
-			if (filldir (dirent, ".", 1, 0, inode->i_ino) < 0)
-				return 0;
-			filp->f_pos ++;
-		}
-		if (filldir (dirent, "..", 2, 1,
-			     adfs_inode_generate (parent_object_id, 0)) < 0)
-			return 0;
-		filp->f_pos ++;
+		if (a != b)
+			return 1;
 	}
+	return 0;
+}
 
-	pos = 5 + (filp->f_pos - 2) * 26;
-	while (filp->f_pos < 79) {
-		struct adfs_idir_entry ide;
-
-		if (!adfs_dir_get (sb, bh, buffers, pos, dir_object_id, &ide))
-			break;
+struct dentry_operations adfs_dentry_operations = {
+	NULL,		/* revalidate */
+	adfs_hash,
+	adfs_compare,
+	NULL,		/* delete  = called by dput */
+	NULL,		/* release - called by d_free */
+	NULL		/* iput    - called by dentry_iput */
+};
 
-		if (filldir (dirent, ide.name, ide.name_len, filp->f_pos, ide.inode_no) < 0)
-			return 0;
-		filp->f_pos ++;
-		pos += 26;
+struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = NULL;
+	struct object_info obj;
+	int error;
+
+	dentry->d_op = &adfs_dentry_operations;	
+	error = adfs_dir_lookup_byname(dir, &dentry->d_name, &obj);
+	if (error == 0) {
+		error = -EACCES;
+		/*
+		 * This only returns NULL if get_empty_inode
+		 * fails.
+		 */
+		inode = adfs_iget(dir->i_sb, &obj);
+		if (inode)
+			error = 0;
 	}
-	adfs_dir_free (bh, buffers);
-	return 0;
+	d_add(dentry, inode);
+	return ERR_PTR(error);
 }
+
+/*
+ * directories can handle most operations...
+ */
+struct inode_operations adfs_dir_inode_operations = {
+	&adfs_dir_operations,	/* default directory file-ops */
+	NULL,			/* create		*/
+	adfs_lookup,		/* lookup		*/
+};
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/dir_f.c linux/fs/adfs/dir_f.c
--- v2.3.42/linux/fs/adfs/dir_f.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/adfs/dir_f.c	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,479 @@
+/*
+ *  linux/fs/adfs/dir_f.c
+ *
+ * Copyright (C) 1997-1999 Russell King
+ *
+ * E and F format directory handling
+ */
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/adfs_fs.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
+#include "adfs.h"
+#include "dir_f.h"
+
+static void adfs_f_free(struct adfs_dir *dir);
+
+/*
+ * Read an (unaligned) value of length 1..4 bytes
+ */
+static inline unsigned int adfs_readval(unsigned char *p, int len)
+{
+	unsigned int val = 0;
+
+	switch (len) {
+	case 4:		val |= p[3] << 24;
+	case 3:		val |= p[2] << 16;
+	case 2:		val |= p[1] << 8;
+	default:	val |= p[0];
+	}
+	return val;
+}
+
+static inline void adfs_writeval(unsigned char *p, int len, unsigned int val)
+{
+	switch (len) {
+	case 4:		p[3] = val >> 24;
+	case 3:		p[2] = val >> 16;
+	case 2:		p[1] = val >> 8;
+	default:	p[0] = val;
+	}
+}
+
+static inline int adfs_readname(char *buf, char *ptr, int maxlen)
+{
+	char *old_buf = buf;
+
+	while (*ptr >= ' ' && maxlen--) {
+		if (*ptr == '/')
+			*buf++ = '.';
+		else
+			*buf++ = *ptr;
+		ptr++;
+	}
+	*buf = '\0';
+
+	return buf - old_buf;
+}
+
+static inline void adfs_writename(char *to, char *from, int maxlen)
+{
+	int i;
+
+	for (i = 0; i < maxlen; i++) {
+		if (from[i] == '\0')
+			break;
+		if (from[i] == '.')
+			to[i] = '/';
+		else
+			to[i] = from[i];
+	}
+
+	for (; i < maxlen; i++)
+		to[i] = '\0';
+}
+
+#define ror13(v) ((v >> 13) | (v << 19))
+
+#define dir_u8(idx)				\
+	({ int _buf = idx >> blocksize_bits;	\
+	   int _off = idx - (_buf << blocksize_bits);\
+	  *(u8 *)(bh[_buf]->b_data + _off);	\
+	})
+
+#define dir_u32(idx)				\
+	({ int _buf = idx >> blocksize_bits;	\
+	   int _off = idx - (_buf << blocksize_bits);\
+	  *(u32 *)(bh[_buf]->b_data + _off);	\
+	})
+
+#define bufoff(_bh,_idx)			\
+	({ int _buf = _idx >> blocksize_bits;	\
+	   int _off = _idx - (_buf << blocksize_bits);\
+	  (u8 *)(_bh[_buf]->b_data + _off);	\
+	})
+
+/*
+ * There are some algorithms that are nice in
+ * assembler, but a bitch in C...  This is one
+ * of them.
+ */
+static u8
+adfs_dir_checkbyte(const struct adfs_dir *dir)
+{
+	struct buffer_head * const *bh = dir->bh;
+	const int blocksize_bits = dir->sb->s_blocksize_bits;
+	union { u32 *ptr32; u8 *ptr8; } ptr, end;
+	u32 dircheck = 0;
+	int last = 5 - 26;
+	int i = 0;
+
+	/*
+	 * Accumulate each word up to the last whole
+	 * word of the last directory entry.  This
+	 * can spread across several buffer heads.
+	 */
+	do {
+		last += 26;
+		do {
+			dircheck = cpu_to_le32(dir_u32(i)) ^ ror13(dircheck);
+
+			i += sizeof(u32);
+		} while (i < (last & ~3));
+	} while (dir_u8(last) != 0);
+
+	/*
+	 * Accumulate the last few bytes.  These
+	 * bytes will be within the same bh.
+	 */
+	if (i != last) {
+		ptr.ptr8 = bufoff(bh, i);
+		end.ptr8 = ptr.ptr8 + last - i;
+
+		do
+			dircheck = *ptr.ptr8++ ^ ror13(dircheck);
+		while (ptr.ptr8 < end.ptr8);
+	}
+
+	/*
+	 * The directory tail is in the final bh
+	 * Note that contary to the RISC OS PRMs,
+	 * the first few bytes are NOT included
+	 * in the check.  All bytes are in the
+	 * same bh.
+	 */
+	ptr.ptr8 = bufoff(bh, 2008);
+	end.ptr8 = ptr.ptr8 + 36;
+
+	do {
+		unsigned int v = *ptr.ptr32++;
+		dircheck = cpu_to_le32(v) ^ ror13(dircheck);
+	} while (ptr.ptr32 < end.ptr32);
+
+	return (dircheck ^ (dircheck >> 8) ^ (dircheck >> 16) ^ (dircheck >> 24)) & 0xff;
+}
+
+/*
+ * Read and check that a directory is valid
+ */
+int
+adfs_dir_read(struct super_block *sb, unsigned long object_id,
+	      unsigned int size, struct adfs_dir *dir)
+{
+	const unsigned int blocksize_bits = sb->s_blocksize_bits;
+	int blk = 0;
+
+	/*
+	 * Directories which are not a multiple of 2048 bytes
+	 * are considered bad v2 [3.6]
+	 */
+	if (size & 2047)
+		goto bad_dir;
+
+	size >>= blocksize_bits;
+
+	dir->nr_buffers = 0;
+	dir->sb = sb;
+
+	for (blk = 0; blk < size; blk++) {
+		int phys;
+
+		phys = __adfs_block_map(sb, object_id, blk);
+		if (!phys) {
+			adfs_error(sb, "dir object %lX has a hole at offset %d",
+				   object_id, blk);
+			goto release_buffers;
+		}
+
+		dir->bh[blk] = bread(sb->s_dev, phys, sb->s_blocksize);
+		if (!dir->bh[blk])
+			goto release_buffers;
+	}
+
+	memcpy(&dir->dirhead, bufoff(dir->bh, 0), sizeof(dir->dirhead));
+	memcpy(&dir->dirtail, bufoff(dir->bh, 2007), sizeof(dir->dirtail));
+
+	if (dir->dirhead.startmasseq != dir->dirtail.new.endmasseq ||
+	    memcmp(&dir->dirhead.startname, &dir->dirtail.new.endname, 4))
+		goto bad_dir;
+
+	if (memcmp(&dir->dirhead.startname, "Nick", 4) &&
+	    memcmp(&dir->dirhead.startname, "Hugo", 4))
+		goto bad_dir;
+
+	if (adfs_dir_checkbyte(dir) != dir->dirtail.new.dircheckbyte)
+		goto bad_dir;
+
+	dir->nr_buffers = blk;
+
+	return 0;
+
+bad_dir:
+	adfs_error(sb, "corrupted directory fragment %lX",
+		   object_id);
+release_buffers:
+	for (blk -= 1; blk >= 0; blk -= 1)
+		brelse(dir->bh[blk]);
+
+	dir->sb = NULL;
+
+	return -EIO;
+}
+
+/*
+ * convert a disk-based directory entry to a Linux ADFS directory entry
+ */
+static inline void
+adfs_dir2obj(struct object_info *obj, struct adfs_direntry *de)
+{
+	obj->name_len =	adfs_readname(obj->name, de->dirobname, ADFS_F_NAME_LEN);
+	obj->file_id  = adfs_readval(de->dirinddiscadd, 3);
+	obj->loadaddr = adfs_readval(de->dirload, 4);
+	obj->execaddr = adfs_readval(de->direxec, 4);
+	obj->size     = adfs_readval(de->dirlen,  4);
+	obj->attr     = de->newdiratts;
+}
+
+/*
+ * convert a Linux ADFS directory entry to a disk-based directory entry
+ */
+static inline void
+adfs_obj2dir(struct adfs_direntry *de, struct object_info *obj)
+{
+	adfs_writeval(de->dirinddiscadd, 3, obj->file_id);
+	adfs_writeval(de->dirload, 4, obj->loadaddr);
+	adfs_writeval(de->direxec, 4, obj->execaddr);
+	adfs_writeval(de->dirlen,  4, obj->size);
+	de->newdiratts = obj->attr;
+}
+
+/*
+ * get a directory entry.  Note that the caller is responsible
+ * for holding the relevent locks.
+ */
+int
+__adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
+{
+	struct super_block *sb = dir->sb;
+	struct adfs_direntry de;
+	int thissize, buffer, offset;
+
+	buffer = pos >> sb->s_blocksize_bits;
+
+	if (buffer > dir->nr_buffers)
+		return -EINVAL;
+
+	offset = pos & (sb->s_blocksize - 1);
+	thissize = sb->s_blocksize - offset;
+	if (thissize > 26)
+		thissize = 26;
+
+	memcpy(&de, dir->bh[buffer]->b_data + offset, thissize);
+	if (thissize != 26)
+		memcpy(((char *)&de) + thissize, dir->bh[buffer + 1]->b_data,
+		       26 - thissize);
+
+	if (!de.dirobname[0])
+		return -ENOENT;
+
+	adfs_dir2obj(obj, &de);
+
+	return 0;
+}
+
+int
+__adfs_dir_put(struct adfs_dir *dir, int pos, struct object_info *obj)
+{
+	struct super_block *sb = dir->sb;
+	struct adfs_direntry de;
+	int thissize, buffer, offset;
+
+	buffer = pos >> sb->s_blocksize_bits;
+
+	if (buffer > dir->nr_buffers)
+		return -EINVAL;
+
+	offset = pos & (sb->s_blocksize - 1);
+	thissize = sb->s_blocksize - offset;
+	if (thissize > 26)
+		thissize = 26;
+
+	/*
+	 * Get the entry in total
+	 */
+	memcpy(&de, dir->bh[buffer]->b_data + offset, thissize);
+	if (thissize != 26)
+		memcpy(((char *)&de) + thissize, dir->bh[buffer + 1]->b_data,
+		       26 - thissize);
+
+	/*
+	 * update it
+	 */
+	adfs_obj2dir(&de, obj);
+
+	/*
+	 * Put the new entry back
+	 */
+	memcpy(dir->bh[buffer]->b_data + offset, &de, thissize);
+	if (thissize != 26)
+		memcpy(dir->bh[buffer + 1]->b_data, ((char *)&de) + thissize,
+		       26 - thissize);
+
+	return 0;
+}
+
+/*
+ * the caller is responsible for holding the necessary
+ * locks.
+ */
+static int
+adfs_dir_find_entry(struct adfs_dir *dir, unsigned long object_id)
+{
+	int pos, ret;
+
+	ret = -ENOENT;
+
+	for (pos = 5; pos < ADFS_NUM_DIR_ENTRIES * 26 + 5; pos += 26) {
+		struct object_info obj;
+
+		if (!__adfs_dir_get(dir, pos, &obj))
+			break;
+
+		if (obj.file_id == object_id) {
+			ret = pos;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
+adfs_f_read(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir)
+{
+	int ret;
+
+	if (sz != ADFS_NEWDIR_SIZE)
+		return -EIO;
+
+	ret = adfs_dir_read(sb, id, sz, dir);
+	if (ret)
+		adfs_error(sb, "unable to read directory");
+	else
+		dir->parent_id = adfs_readval(dir->dirtail.new.dirparent, 3);
+
+	return ret;
+}
+
+static int
+adfs_f_setpos(struct adfs_dir *dir, unsigned int fpos)
+{
+	if (fpos >= ADFS_NUM_DIR_ENTRIES)
+		return -ENOENT;
+
+	dir->pos = 5 + fpos * 26;
+	return 0;
+}
+
+static int
+adfs_f_getnext(struct adfs_dir *dir, struct object_info *obj)
+{
+	unsigned int ret;
+
+	ret = __adfs_dir_get(dir, dir->pos, obj);
+	if (ret == 0)
+		dir->pos += 26;
+
+	return ret;
+}
+
+static int
+adfs_f_update(struct adfs_dir *dir, struct object_info *obj)
+{
+	struct super_block *sb = dir->sb;
+	int ret, i;
+
+	ret = adfs_dir_find_entry(dir, obj->file_id);
+	if (ret < 0) {
+		adfs_error(dir->sb, "unable to locate entry to update");
+		goto out;
+	}
+
+	__adfs_dir_put(dir, ret, obj);
+ 
+	/*
+	 * Increment directory sequence number
+	 */
+	dir->bh[0]->b_data[0] += 1;
+	dir->bh[dir->nr_buffers - 1]->b_data[sb->s_blocksize - 6] += 1;
+
+	ret = adfs_dir_checkbyte(dir);
+	/*
+	 * Update directory check byte
+	 */
+	dir->bh[dir->nr_buffers - 1]->b_data[sb->s_blocksize - 1] = ret;
+
+#if 1
+	{
+	const unsigned int blocksize_bits = sb->s_blocksize_bits;
+
+	memcpy(&dir->dirhead, bufoff(dir->bh, 0), sizeof(dir->dirhead));
+	memcpy(&dir->dirtail, bufoff(dir->bh, 2007), sizeof(dir->dirtail));
+
+	if (dir->dirhead.startmasseq != dir->dirtail.new.endmasseq ||
+	    memcmp(&dir->dirhead.startname, &dir->dirtail.new.endname, 4))
+		goto bad_dir;
+
+	if (memcmp(&dir->dirhead.startname, "Nick", 4) &&
+	    memcmp(&dir->dirhead.startname, "Hugo", 4))
+		goto bad_dir;
+
+	if (adfs_dir_checkbyte(dir) != dir->dirtail.new.dircheckbyte)
+		goto bad_dir;
+	}
+#endif
+	for (i = dir->nr_buffers - 1; i >= 0; i--)
+		mark_buffer_dirty(dir->bh[i], 1);
+
+	ret = 0;
+out:
+	return ret;
+#if 1
+bad_dir:
+	adfs_error(dir->sb, "whoops!  I broke a directory!");
+	return -EIO;
+#endif
+}
+
+static void
+adfs_f_free(struct adfs_dir *dir)
+{
+	int i;
+
+	for (i = dir->nr_buffers - 1; i >= 0; i--) {
+		brelse(dir->bh[i]);
+		dir->bh[i] = NULL;
+	}
+
+	dir->nr_buffers = 0;
+	dir->sb = NULL;
+}
+
+struct adfs_dir_ops adfs_f_dir_ops = {
+	adfs_f_read,
+	adfs_f_setpos,
+	adfs_f_getnext,
+	adfs_f_update,
+	NULL,
+	NULL,
+	adfs_f_free
+};
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/dir_f.h linux/fs/adfs/dir_f.h
--- v2.3.42/linux/fs/adfs/dir_f.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/adfs/dir_f.h	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,61 @@
+/*
+ * linux/fs/adfs/dir_f.h
+ *
+ * Copyright (C) 1999 Russell King
+ *
+ * Structures of directories on the F format disk
+ */
+#ifndef ADFS_DIR_F_H
+#define ADFS_DIR_F_H
+
+/*
+ * Directory header
+ */
+struct adfs_dirheader {
+	unsigned char startmasseq;
+	unsigned char startname[4];
+};
+
+#define ADFS_NEWDIR_SIZE	2048
+#define ADFS_NUM_DIR_ENTRIES	77
+
+/*
+ * Directory entries
+ */
+struct adfs_direntry {
+#define ADFS_F_NAME_LEN 10
+	char dirobname[ADFS_F_NAME_LEN];
+	__u8 dirload[4];
+	__u8 direxec[4];
+	__u8 dirlen[4];
+	__u8 dirinddiscadd[3];
+	__u8 newdiratts;
+};
+
+/*
+ * Directory tail
+ */
+union adfs_dirtail {
+	struct {
+		unsigned char dirlastmask;
+		char dirname[10];
+		unsigned char dirparent[3];
+		char dirtitle[19];
+		unsigned char reserved[14];
+		unsigned char endmasseq;
+		unsigned char endname[4];
+		unsigned char dircheckbyte;
+	} old;
+	struct {
+		unsigned char dirlastmask;
+		unsigned char reserved[2];
+		unsigned char dirparent[3];
+		char dirtitle[19];
+		char dirname[10];
+		unsigned char endmasseq;
+		unsigned char endname[4];
+		unsigned char dircheckbyte;
+	} new;
+};
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/dir_fplus.c linux/fs/adfs/dir_fplus.c
--- v2.3.42/linux/fs/adfs/dir_fplus.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/adfs/dir_fplus.c	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,182 @@
+/*
+ *  linux/fs/adfs/dir_fplus.c
+ *
+ * Copyright (C) 1997-1999 Russell King
+ */
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/adfs_fs.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
+#include "adfs.h"
+#include "dir_fplus.h"
+
+static int
+adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir)
+{
+	struct adfs_bigdirheader *h;
+	struct adfs_bigdirtail *t;
+	unsigned long block;
+	unsigned int blk, size;
+	int i, ret = -EIO;
+
+	dir->nr_buffers = 0;
+
+	block = __adfs_block_map(sb, id, 0);
+	if (!block) {
+		adfs_error(sb, "dir object %X has a hole at offset 0", id);
+		goto out;
+	}
+
+	dir->bh[0] = bread(sb->s_dev, block, sb->s_blocksize);
+	if (!dir->bh[0])
+		goto out;
+	dir->nr_buffers += 1;
+
+	h = (struct adfs_bigdirheader *)dir->bh[0]->b_data;
+	size = le32_to_cpu(h->bigdirsize);
+	if (size != sz) {
+		printk(KERN_WARNING "adfs: adfs_fplus_read: directory header size\n"
+				" does not match directory size\n");
+	}
+
+	if (h->bigdirversion[0] != 0 || h->bigdirversion[1] != 0 ||
+	    h->bigdirversion[2] != 0 || size & 2047 ||
+	    h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME))
+		goto out;
+
+	size >>= sb->s_blocksize_bits;
+	for (blk = 1; blk < size; blk++) {
+		block = __adfs_block_map(sb, id, blk);
+		if (!block) {
+			adfs_error(sb, "dir object %X has a hole at offset %d", id, blk);
+			goto out;
+		}
+
+		dir->bh[blk] = bread(sb->s_dev, block, sb->s_blocksize);
+		if (!dir->bh[blk])
+			goto out;
+		dir->nr_buffers = blk;
+	}
+
+	t = (struct adfs_bigdirtail *)(dir->bh[size - 1]->b_data + (sb->s_blocksize - 8));
+
+	if (t->bigdirendname != cpu_to_le32(BIGDIRENDNAME) ||
+	    t->bigdirendmasseq != h->startmasseq ||
+	    t->reserved[0] != 0 || t->reserved[1] != 0)
+		goto out;
+
+	dir->parent_id = le32_to_cpu(h->bigdirparent);
+	dir->sb = sb;
+	return 0;
+out:
+	for (i = 0; i < dir->nr_buffers; i++)
+		brelse(dir->bh[i]);
+	dir->sb = NULL;
+	return ret;
+}
+
+static int
+adfs_fplus_setpos(struct adfs_dir *dir, unsigned int fpos)
+{
+	struct adfs_bigdirheader *h = (struct adfs_bigdirheader *)dir->bh[0]->b_data;
+	int ret = -ENOENT;
+
+	if (fpos <= le32_to_cpu(h->bigdirentries)) {
+		dir->pos = fpos;
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static void
+dir_memcpy(struct adfs_dir *dir, unsigned int offset, void *to, int len)
+{
+	struct super_block *sb = dir->sb;
+	unsigned int buffer, partial, remainder;
+
+	buffer = offset >> sb->s_blocksize_bits;
+	offset &= sb->s_blocksize - 1;
+
+	partial = sb->s_blocksize - offset;
+
+	if (partial >= len)
+		memcpy(to, dir->bh[buffer]->b_data + offset, len);
+	else {
+		char *c = (char *)to;
+
+		remainder = len - partial;
+
+		memcpy(c, dir->bh[buffer]->b_data + offset, partial);
+		memcpy(c + partial, dir->bh[buffer + 1]->b_data, remainder);
+	}
+}
+
+static int
+adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
+{
+	struct adfs_bigdirheader *h = (struct adfs_bigdirheader *)dir->bh[0]->b_data;
+	struct adfs_bigdirentry bde;
+	unsigned int offset;
+	int i, ret = -ENOENT;
+
+	if (dir->pos >= le32_to_cpu(h->bigdirentries))
+		goto out;
+
+	offset = offsetof(struct adfs_bigdirheader, bigdirname);
+	offset += ((le32_to_cpu(h->bigdirnamelen) + 4) & ~3);
+	offset += dir->pos * sizeof(struct adfs_bigdirentry);
+
+	dir_memcpy(dir, offset, &bde, sizeof(struct adfs_bigdirentry));
+
+	obj->loadaddr = le32_to_cpu(bde.bigdirload);
+	obj->execaddr = le32_to_cpu(bde.bigdirexec);
+	obj->size     = le32_to_cpu(bde.bigdirlen);
+	obj->file_id  = le32_to_cpu(bde.bigdirindaddr);
+	obj->attr     = le32_to_cpu(bde.bigdirattr);
+	obj->name_len = le32_to_cpu(bde.bigdirobnamelen);
+
+	offset = offsetof(struct adfs_bigdirheader, bigdirname);
+	offset += ((le32_to_cpu(h->bigdirnamelen) + 4) & ~3);
+	offset += le32_to_cpu(h->bigdirentries) * sizeof(struct adfs_bigdirentry);
+	offset += le32_to_cpu(bde.bigdirobnameptr);
+
+	dir_memcpy(dir, offset, obj->name, obj->name_len);
+	for (i = 0; i < obj->name_len; i++)
+		if (obj->name[i] == '/')
+			obj->name[i] = '.';
+
+	dir->pos += 1;
+	ret = 0;
+out:
+	return ret;
+}
+
+static void
+adfs_fplus_free(struct adfs_dir *dir)
+{
+	int i;
+
+	for (i = 0; i < dir->nr_buffers; i++)
+		brelse(dir->bh[i]);
+	dir->sb = NULL;
+}
+
+struct adfs_dir_ops adfs_fplus_dir_ops = {
+	adfs_fplus_read,
+	adfs_fplus_setpos,
+	adfs_fplus_getnext,
+	NULL,
+	NULL,
+	NULL,
+	adfs_fplus_free
+};
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/dir_fplus.h linux/fs/adfs/dir_fplus.h
--- v2.3.42/linux/fs/adfs/dir_fplus.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/adfs/dir_fplus.h	Sun Feb  6 17:45:25 2000
@@ -0,0 +1,41 @@
+/*
+ * linux/fs/adfs/dir_fplus.h
+ *
+ * Copyright (C) 1999 Russell King
+ *
+ * Structures of directories on the F+ format disk
+ */
+
+#define ADFS_FPLUS_NAME_LEN	255
+
+#define BIGDIRSTARTNAME ('S' | 'B' << 8 | 'P' << 16 | 'r' << 24)
+#define BIGDIRENDNAME	('o' | 'v' << 8 | 'e' << 16 | 'n' << 24)
+
+struct adfs_bigdirheader {
+	__u8	startmasseq;
+	__u8	bigdirversion[3];
+	__u32	bigdirstartname;
+	__u32	bigdirnamelen;
+	__u32	bigdirsize;
+	__u32	bigdirentries;
+	__u32	bigdirnamesize;
+	__u32	bigdirparent;
+	char	bigdirname[1];
+};
+
+struct adfs_bigdirentry {
+	__u32	bigdirload;
+	__u32	bigdirexec;
+	__u32	bigdirlen;
+	__u32	bigdirindaddr;
+	__u32	bigdirattr;
+	__u32	bigdirobnamelen;
+	__u32	bigdirobnameptr;
+};
+
+struct adfs_bigdirtail {
+	__u32	bigdirendname;
+	__u8	bigdirendmasseq;
+	__u8	reserved[2];
+	__u8	bigdircheckbyte;
+};
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/file.c linux/fs/adfs/file.c
--- v2.3.42/linux/fs/adfs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/adfs/file.c	Thu Feb 10 12:16:57 2000
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/adfs/file.c
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1999 Russell King
  * from:
  *
  *  linux/fs/ext2/file.c
@@ -19,7 +19,7 @@
  *
  *  adfs regular file handling primitives           
  */
-
+#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
@@ -27,42 +27,21 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 
+#include "adfs.h"
+
 /*
  * We have mostly NULLs here: the current defaults are OK for
  * the adfs filesystem.
  */
 static struct file_operations adfs_file_operations = {
-	NULL,			/* lseek - default	*/
-	generic_file_read,	/* read			*/
-	NULL,			/* write		*/
-	NULL,			/* readdir - bad	*/
-	NULL,			/* select - default	*/
-	NULL,			/* ioctl		*/
-	generic_file_mmap,	/* mmap			*/
-	NULL,			/* open - not special	*/
-	NULL,			/* flush		*/
-	NULL,			/* release		*/
-	file_fsync,		/* fsync		*/
-	NULL,			/* fasync		*/
+	read:		generic_file_read,
+	mmap:		generic_file_mmap,
+	fsync:		file_fsync,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+	write:		generic_file_write,
+#endif
 };
 
 struct inode_operations adfs_file_inode_operations = {
-	&adfs_file_operations,	/* default file operations	*/
-	NULL,			/* create			*/
-	NULL,			/* lookup			*/
-	NULL,			/* link				*/
-	NULL,			/* unlink			*/
-	NULL,			/* symlink			*/
-	NULL,			/* mkdir			*/
-	NULL,			/* rmdir			*/
-	NULL,			/* mknod			*/
-	NULL,			/* rename			*/
-	NULL,			/* readlink			*/
-	NULL,			/* follow_link			*/
-	adfs_bmap,		/* get_block			*/
-	block_read_full_page,	/* readpage			*/
-	NULL,			/* writepage			*/
-	NULL,			/* truncate			*/
-	NULL,			/* permission			*/
-	NULL			/* revalidate			*/
+	&adfs_file_operations,	/* default file operations */
 };
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/inode.c linux/fs/adfs/inode.c
--- v2.3.42/linux/fs/adfs/inode.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/adfs/inode.c	Thu Feb 10 12:16:57 2000
@@ -1,9 +1,9 @@
 /*
  *  linux/fs/adfs/inode.c
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1999 Russell King
  */
-
+#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
@@ -13,210 +13,367 @@
 #include <linux/locks.h>
 #include <linux/mm.h>
 
+#include "adfs.h"
+
 /*
- * Old Inode numbers:
- *  bit 30 - 16		FragID of parent object
- *  bit 15		0			1
- *  bit 14 - 0		FragID of object	Offset into parent FragID
- *
- * New Inode numbers:
- *  Inode = Frag ID of parent (14) + Frag Offset (8) + (index into directory + 1)(8)
+ * Lookup/Create a block at offset 'block' into 'inode'.  We currently do
+ * not support creation of new blocks, so we return -EIO for this case.
  */
-#define inode_frag(ino)		((ino) >> 8)
-#define inode_idx(ino)		((ino) & 0xff)
-#define inode_dirindex(idx)	(((idx) & 0xff) * 26 - 21)
-
-#define frag_id(x)		(((x) >> 8) & 0x7fff)
-#define off(x)			(((x) & 0xff) ? (((x) & 0xff) - 1) << sb->u.adfs_sb.s_dr->log2sharesize : 0)
-
-static inline int adfs_inode_validate_no (struct super_block *sb, unsigned int inode_no)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+int
+adfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
 {
-	unsigned long max_frag_id;
+	if (block < 0)
+		goto abort_negative;
+
+	if (!create) {
+		if (block >= inode->i_blocks)
+			goto abort_toobig;
+
+		block = __adfs_block_map(inode->i_sb, inode->i_ino, block);
+		if (block) {
+			bh->b_dev = inode->i_dev;
+			bh->b_blocknr = block;
+			bh->b_state |= (1UL << BH_Mapped);
+		}
+		return 0;
+	}
+	/* don't support allocation of blocks yet */
+	return -EIO;
 
-	max_frag_id = sb->u.adfs_sb.s_map_size * sb->u.adfs_sb.s_ids_per_zone;
+abort_negative:
+	adfs_error(inode->i_sb, "block %d < 0", block);
+	return -EIO;
 
-	return (inode_no & 0x800000ff) ||
-	       (frag_id (inode_frag (inode_no)) > max_frag_id) ||
-	       (frag_id (inode_frag (inode_no)) < 2);
+abort_toobig:
+	return 0;
 }
-
-int adfs_inode_validate (struct inode *inode)
+static int adfs_writepage(struct dentry *dentry, struct page *page)
 {
-	struct super_block *sb = inode->i_sb;
+	return block_write_full_page(page,adfs_get_block);
+}
+static int adfs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,adfs_get_block);
+}
+static int adfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page,from,to,adfs_get_block,
+		&((struct inode*)page->mapping->host)->u.adfs_i.mmu_private);
+}
+static int _adfs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,adfs_get_block);
+}
+struct address_space_operations adfs_aops = {
+	readpage: adfs_readpage,
+	writepage: adfs_writepage,
+	prepare_write: adfs_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: _adfs_bmap
+};
+#else
+int adfs_bmap(struct inode *inode, int block)
+{
+	if (block >= inode->i_blocks)
+		return 0;
 
-	return adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00) ||
-	       adfs_inode_validate_no (sb, inode->u.adfs_i.file_id << 8);
+	return __adfs_block_map(inode->i_sb, inode->i_ino, block);
 }
+#endif
 
-unsigned long adfs_inode_generate (unsigned long parent_id, int diridx)
+static inline unsigned int
+adfs_filetype(struct inode *inode)
 {
-	if (!parent_id)
-		return -1;
+	unsigned int type;
 
-	if (diridx)
-		diridx = (diridx + 21) / 26;
+	if (inode->u.adfs_i.stamped)
+		type = (inode->u.adfs_i.loadaddr >> 8) & 0xfff;
+	else
+		type = (unsigned int) -1;
 
-	return (parent_id << 8) | diridx;
+	return type;
 }
 
-unsigned long adfs_inode_objid (struct inode *inode)
+/*
+ * Convert ADFS attributes and filetype to Linux permission.
+ */
+static umode_t
+adfs_atts2mode(struct super_block *sb, struct inode *inode)
 {
-	if (adfs_inode_validate (inode)) {
-		adfs_error (inode->i_sb, "adfs_inode_objid",
-			    "bad inode number: %lu (%X,%X)",
-			    inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id);
-		return 0;
+	unsigned int filetype, attr = inode->u.adfs_i.attr;
+	umode_t mode, rmask;
+
+	if (attr & ADFS_NDA_DIRECTORY) {
+		mode = S_IRUGO & sb->u.adfs_sb.s_owner_mask;
+		return S_IFDIR | S_IXUGO | mode;
 	}
 
-	return inode->u.adfs_i.file_id;
-}
+	filetype = adfs_filetype(inode);
 
-int adfs_bmap (struct inode *inode, int block)
-{
-	struct super_block *sb = inode->i_sb;
-	unsigned int blk;
+	switch (filetype) {
+	case 0xfc0:	/* LinkFS */
+		return S_IFLNK|S_IRWXUGO;
+
+	case 0xfe6:	/* UnixExec */
+		rmask = S_IRUGO | S_IXUGO;
+		break;
 
-	if (adfs_inode_validate (inode)) {
-		adfs_error (sb, "adfs_bmap",
-			    "bad inode number: %lu (%X,%X)",
-			    inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id);
-		return 0;
+	default:
+		rmask = S_IRUGO;
 	}
 
-	if (block < 0) {
-		adfs_error(sb, "adfs_bmap", "block(%d) < 0", block);
-		return 0;
-	}
+	mode = S_IFREG;
 
-	if (block > inode->i_blocks)
-		return 0;
+	if (attr & ADFS_NDA_OWNER_READ)
+		mode |= rmask & sb->u.adfs_sb.s_owner_mask;
 
-	block += off(inode->u.adfs_i.file_id);
+	if (attr & ADFS_NDA_OWNER_WRITE)
+		mode |= S_IWUGO & sb->u.adfs_sb.s_owner_mask;
 
-	if (frag_id(inode->u.adfs_i.file_id) == ADFS_ROOT_FRAG)
-		blk = sb->u.adfs_sb.s_map_block + block;
-	else
-		blk = adfs_map_lookup (sb, frag_id(inode->u.adfs_i.file_id), block);
-	return blk;
+	if (attr & ADFS_NDA_PUBLIC_READ)
+		mode |= rmask & sb->u.adfs_sb.s_other_mask;
+
+	if (attr & ADFS_NDA_PUBLIC_WRITE)
+		mode |= S_IWUGO & sb->u.adfs_sb.s_other_mask;
+	return mode;
 }
 
-unsigned int adfs_parent_bmap (struct inode *inode, int block)
+/*
+ * Convert Linux permission to ADFS attribute.  We try to do the reverse
+ * of atts2mode, but there is not a 1:1 translation.
+ */
+static int
+adfs_mode2atts(struct super_block *sb, struct inode *inode)
 {
-	struct super_block *sb = inode->i_sb;
-	unsigned int blk, fragment;
+	umode_t mode;
+	int attr;
 
-	if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) {
-		adfs_error (sb, "adfs_parent_bmap",
-			    "bad inode number: %lu (%X,%X)",
-			    inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id);
-		return 0;
-	}
+	/* FIXME: should we be able to alter a link? */
+	if (S_ISLNK(inode->i_mode))
+		return inode->u.adfs_i.attr;
 
-	fragment = inode_frag (inode->i_ino);
-	if (frag_id (fragment) == ADFS_ROOT_FRAG)
-		blk = sb->u.adfs_sb.s_map_block + off(fragment) + block;
+	if (S_ISDIR(inode->i_mode))
+		attr = ADFS_NDA_DIRECTORY;
 	else
-		blk = adfs_map_lookup (sb, frag_id (fragment), off(fragment) + block);
-	return blk;	
+		attr = 0;
+
+	mode = inode->i_mode & sb->u.adfs_sb.s_owner_mask;
+	if (mode & S_IRUGO)
+		attr |= ADFS_NDA_OWNER_READ;
+	if (mode & S_IWUGO)
+		attr |= ADFS_NDA_OWNER_WRITE;
+
+	mode = inode->i_mode & sb->u.adfs_sb.s_other_mask;
+	mode &= ~sb->u.adfs_sb.s_owner_mask;
+	if (mode & S_IRUGO)
+		attr |= ADFS_NDA_PUBLIC_READ;
+	if (mode & S_IWUGO)
+		attr |= ADFS_NDA_PUBLIC_WRITE;
+
+	return attr;
 }
 
-static int adfs_atts2mode(struct super_block *sb, unsigned char mode, unsigned int filetype)
+/*
+ * Convert an ADFS time to Unix time.  ADFS has a 40-bit centi-second time
+ * referenced to 1 Jan 1900 (til 2248)
+ */
+static unsigned int
+adfs_adfs2unix_time(struct inode *inode)
 {
-	int omode = 0;
+	unsigned int high, low;
 
-	if (filetype == 0xfc0 /* LinkFS */) {
-		omode = S_IFLNK|S_IRUSR|S_IWUSR|S_IXUSR|
-				S_IRGRP|S_IWGRP|S_IXGRP|
-				S_IROTH|S_IWOTH|S_IXOTH;
-	} else {
-		if (mode & ADFS_NDA_DIRECTORY) {
-			omode |= S_IRUGO & sb->u.adfs_sb.s_owner_mask;
-			omode |= S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH;
-		} else
-			omode |= S_IFREG;
-
-		if (mode & ADFS_NDA_OWNER_READ) {
-			omode |= S_IRUGO & sb->u.adfs_sb.s_owner_mask;
-			if (filetype == 0xfe6 /* UnixExec */)
-				omode |= S_IXUGO & sb->u.adfs_sb.s_owner_mask;
-		}
+	if (inode->u.adfs_i.stamped == 0)
+		return CURRENT_TIME;
 
-		if (mode & ADFS_NDA_OWNER_WRITE)
-			omode |= S_IWUGO & sb->u.adfs_sb.s_owner_mask;
+	high = inode->u.adfs_i.loadaddr << 24;
+	low  = inode->u.adfs_i.execaddr;
 
-		if (mode & ADFS_NDA_PUBLIC_READ) {
-			omode |= S_IRUGO & sb->u.adfs_sb.s_other_mask;
-			if (filetype == 0xfe6 /* UnixExec */)
-				omode |= S_IXUGO & sb->u.adfs_sb.s_other_mask;
-		}
+	high |= low >> 8;
+	low  &= 255;
 
-		if (mode & ADFS_NDA_PUBLIC_WRITE)
-			omode |= S_IWUGO & sb->u.adfs_sb.s_other_mask;
-	}
-	return omode;
+	/* Files dated pre  01 Jan 1970 00:00:00. */
+	if (high < 0x336e996a)
+		return 0;
+
+	/* Files dated post 18 Jan 2038 03:14:05. */
+	if (high >= 0x656e9969)
+		return 0x7ffffffd;
+
+	/* discard 2208988800 (0x336e996a00) seconds of time */
+	high -= 0x336e996a;
+
+	/* convert 40-bit centi-seconds to 32-bit seconds */
+	return (((high % 100) << 8) + low) / 100 + (high / 100 << 8);
 }
 
-void adfs_read_inode (struct inode *inode)
+/*
+ * Convert an Unix time to ADFS time.  We only do this if the entry has a
+ * time/date stamp already.
+ */
+static void
+adfs_unix2adfs_time(struct inode *inode, unsigned int secs)
 {
-	struct super_block *sb;
-	struct buffer_head *bh[4];
-	struct adfs_idir_entry ide;
-	int buffers;
+	unsigned int high, low;
 
-	sb = inode->i_sb;
-	inode->i_uid = sb->u.adfs_sb.s_uid;
-	inode->i_gid = sb->u.adfs_sb.s_gid;
-	inode->i_version = ++event;
+	if (inode->u.adfs_i.stamped) {
+		/* convert 32-bit seconds to 40-bit centi-seconds */
+		low  = (secs & 255) * 100;
+		high = (secs / 256) * 100 + (low << 8) + 0x336e996a;
+
+		inode->u.adfs_i.loadaddr = (high >> 24) |
+				(inode->u.adfs_i.loadaddr & ~0xff);
+		inode->u.adfs_i.execaddr = (low & 255) | (high << 8);
+	}
+}
 
-	if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) {
-		adfs_error (sb, "adfs_read_inode",
-			    "bad inode number: %lu", inode->i_ino);
-		goto bad;
-	}
-
-	if (frag_id(inode_frag (inode->i_ino)) == ADFS_ROOT_FRAG &&
-	    inode_idx (inode->i_ino) == 0) {
-		/* root dir */
-		inode->i_mode	 = S_IRWXUGO | S_IFDIR;
-		inode->i_nlink	 = 2;
-		inode->i_size	 = ADFS_NEWDIR_SIZE;
-		inode->i_blksize = PAGE_SIZE;
-		inode->i_blocks  = inode->i_size >> sb->s_blocksize_bits;
-		inode->i_mtime   =
-		inode->i_atime   =
-		inode->i_ctime   = 0;
-		inode->u.adfs_i.file_id = inode_frag (inode->i_ino);
-	} else {
-		if (!(buffers = adfs_dir_read_parent (inode, bh)))
-			goto bad;
-
-		if (adfs_dir_check (inode, bh, buffers, NULL)) {
-			adfs_dir_free (bh, buffers);
-			goto bad;
-		}
+/*
+ * Fill in the inode information from the object information.
+ *
+ * Note that this is an inode-less filesystem, so we can't use the inode
+ * number to reference the metadata on the media.  Instead, we use the
+ * inode number to hold the object ID, which in turn will tell us where
+ * the data is held.  We also save the parent object ID, and with these
+ * two, we can locate the metadata.
+ *
+ * This does mean that we rely on an objects parent remaining the same at
+ * all times - we cannot cope with a cross-directory rename (yet).
+ */
+struct inode *
+adfs_iget(struct super_block *sb, struct object_info *obj)
+{
+	struct inode *inode;
 
-		if (!adfs_dir_find_entry (sb, bh, buffers, inode_dirindex (inode->i_ino), &ide)) {
-			adfs_dir_free (bh, buffers);
-			goto bad;
-		}
-		adfs_dir_free (bh, buffers);
-		inode->i_mode	 = adfs_atts2mode(sb, ide.mode, ide.filetype);
-		inode->i_nlink	 = 2;
-		inode->i_size    = ide.size;
-		inode->i_blksize = PAGE_SIZE;
-		inode->i_blocks	 = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
-		inode->i_mtime	 =
-		inode->i_atime   =
-		inode->i_ctime   = ide.mtime;
-		inode->u.adfs_i.file_id = ide.file_id;
-	}
+	inode = get_empty_inode();
+	if (!inode)
+		goto out;
+
+	inode->i_version = ++event;
+	inode->i_sb	 = sb;
+	inode->i_dev	 = sb->s_dev;
+	inode->i_uid	 = sb->u.adfs_sb.s_uid;
+	inode->i_gid	 = sb->u.adfs_sb.s_gid;
+	inode->i_ino	 = obj->file_id;
+	inode->i_size	 = obj->size;
+	inode->i_nlink	 = 2;
+	inode->i_blksize = PAGE_SIZE;
+	inode->i_blocks	 = (inode->i_size + sb->s_blocksize - 1) >>
+			    sb->s_blocksize_bits;
+
+	/*
+	 * we need to save the parent directory ID so that
+	 * write_inode can update the directory information
+	 * for this file.  This will need special handling
+	 * for cross-directory renames.
+	 */
+	inode->u.adfs_i.parent_id = obj->parent_id;
+	inode->u.adfs_i.loadaddr  = obj->loadaddr;
+	inode->u.adfs_i.execaddr  = obj->execaddr;
+	inode->u.adfs_i.attr      = obj->attr;
+	inode->u.adfs_i.stamped	  = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
+
+	inode->i_mode	 = adfs_atts2mode(sb, inode);
+	inode->i_mtime	 =
+	inode->i_atime	 =
+	inode->i_ctime	 = adfs_adfs2unix_time(inode);
 
 	if (S_ISDIR(inode->i_mode))
-		inode->i_op	 = &adfs_dir_inode_operations;
-	else if (S_ISREG(inode->i_mode))
+		inode->i_op	= &adfs_dir_inode_operations;
+	else if (S_ISREG(inode->i_mode)) {
 		inode->i_op	 = &adfs_file_inode_operations;
-	return;
+		inode->i_mapping->a_ops = &adfs_aops;
+		inode->u.adfs_i.mmu_private = inode->i_size;
+	}
+
+	insert_inode_hash(inode);
+
+out:
+	return inode;
+}
 
-bad:
+/*
+ * This is no longer a valid way to obtain the metadata associated with the
+ * inode number on this filesystem.  This means that this filesystem cannot
+ * be shared via NFS.
+ */
+void adfs_read_inode(struct inode *inode)
+{
+	adfs_error(inode->i_sb, "unsupported method of reading inode");
 	make_bad_inode(inode);
+}
+
+/*
+ * Validate and convert a changed access mode/time to their ADFS equivalents.
+ * adfs_write_inode will actually write the information back to the directory
+ * later.
+ */
+int
+adfs_notify_change(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	unsigned int ia_valid = attr->ia_valid;
+	int error;
+
+	error = inode_change_ok(inode, attr);
+
+	/*
+	 * we can't change the UID or GID of any file -
+	 * we have a global UID/GID in the superblock
+	 */
+	if ((ia_valid & ATTR_UID && attr->ia_uid != sb->u.adfs_sb.s_uid) ||
+	    (ia_valid & ATTR_GID && attr->ia_gid != sb->u.adfs_sb.s_gid))
+		error = -EPERM;
+
+	if (error)
+		goto out;
+
+	if (ia_valid & ATTR_SIZE)
+		inode->i_size = attr->ia_size;
+	if (ia_valid & ATTR_MTIME) {
+		inode->i_mtime = attr->ia_mtime;
+		adfs_unix2adfs_time(inode, attr->ia_mtime);
+	}
+	/*
+	 * FIXME: should we make these == to i_mtime since we don't
+	 * have the ability to represent them in our filesystem?
+	 */
+	if (ia_valid & ATTR_ATIME)
+		inode->i_atime = attr->ia_atime;
+	if (ia_valid & ATTR_CTIME)
+		inode->i_ctime = attr->ia_ctime;
+	if (ia_valid & ATTR_MODE) {
+		inode->u.adfs_i.attr = adfs_mode2atts(sb, inode);
+		inode->i_mode = adfs_atts2mode(sb, inode);
+	}
+
+	/*
+	 * FIXME: should we be marking this inode dirty even if
+	 * we don't have any metadata to write back?
+	 */
+	if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
+		mark_inode_dirty(inode);
+out:
+	return error;
+}
+
+/*
+ * write an existing inode back to the directory, and therefore the disk.
+ * The adfs-specific inode data has already been updated by
+ * adfs_notify_change()
+ */
+void adfs_write_inode(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct object_info obj;
+
+	obj.file_id	= inode->i_ino;
+	obj.name_len	= 0;
+	obj.parent_id	= inode->u.adfs_i.parent_id;
+	obj.loadaddr	= inode->u.adfs_i.loadaddr;
+	obj.execaddr	= inode->u.adfs_i.execaddr;
+	obj.attr	= inode->u.adfs_i.attr;
+	obj.size	= inode->i_size;
+
+	adfs_dir_update(sb, &obj);
 }
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/map.c linux/fs/adfs/map.c
--- v2.3.42/linux/fs/adfs/map.c	Tue Jan 20 16:44:58 1998
+++ linux/fs/adfs/map.c	Wed Feb  9 18:48:03 2000
@@ -1,108 +1,302 @@
 /*
  *  linux/fs/adfs/map.c
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1999 Russell King
  */
-
+#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
 
-static inline unsigned int
-adfs_convert_map_to_sector (const struct super_block *sb, unsigned int mapoff)
-{
-	if (sb->u.adfs_sb.s_map2blk >= 0)
-		mapoff <<= sb->u.adfs_sb.s_map2blk;
-	else
-		mapoff >>= -sb->u.adfs_sb.s_map2blk;
-	return mapoff;
-}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
 
-static inline unsigned int
-adfs_convert_sector_to_map (const struct super_block *sb, unsigned int secoff)
-{
-	if (sb->u.adfs_sb.s_map2blk >= 0)
-		secoff >>= sb->u.adfs_sb.s_map2blk;
-	else
-		secoff <<= -sb->u.adfs_sb.s_map2blk;
-	return secoff;
-}
+#include "adfs.h"
 
-static int lookup_zone (struct super_block *sb, int zone, int frag_id, int *offset)
-{
-	unsigned int mapptr, idlen, mapsize;
-	unsigned long *map;
+/*
+ * For the future...
+ */
+static rwlock_t adfs_map_lock;
 
-	map     = ((unsigned long *)sb->u.adfs_sb.s_map[zone]->b_data) + 1;
-	zone    =
-	mapptr  = zone == 0 ? (ADFS_DR_SIZE << 3) : 0;
-	idlen   = sb->u.adfs_sb.s_idlen;
-	mapsize = sb->u.adfs_sb.s_zonesize;
+/*
+ * return the map bit offset of the fragment frag_id in
+ * the zone dm.
+ * Note that the loop is optimised for best asm code -
+ * look at the output of:
+ *  gcc -D__KERNEL__ -O2 -I../../include -o - -S map.c
+ */
+static int
+lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen,
+	    const unsigned int frag_id, unsigned int *offset)
+{
+	const unsigned int mapsize = dm->dm_endbit;
+	const unsigned int idmask = (1 << idlen) - 1;
+	unsigned long *map = ((unsigned long *)dm->dm_bh->b_data) + 1;
+	unsigned int start = dm->dm_startbit;
+	unsigned int mapptr;
 
 	do {
-		unsigned long v1, v2;
-		unsigned int start;
+		unsigned long frag;
 
-		v1 = map[mapptr>>5];
-		v2 = map[(mapptr>>5)+1];
+		/*
+		 * get fragment id
+		 */
+		//asm("@ get fragment id start");
+		{
+			unsigned long v2;
+			unsigned int tmp;
 
-		v1 = (v1 >> (mapptr & 31)) | (v2 << (32 - (mapptr & 31)));
-		start = mapptr;
-		mapptr += idlen;
+			tmp = start >> 5;
+
+			frag = le32_to_cpu(map[tmp]);
+			v2   = le32_to_cpu(map[tmp + 1]);
+
+			tmp  = start & 31;
 
-		v2 = map[mapptr >> 5] >> (mapptr & 31);
-		if (!v2) {
-			mapptr = (mapptr + 32) & ~31;
-			for (; (v2 = map[mapptr >> 5]) == 0 && mapptr < mapsize; mapptr += 32);
+			frag = (frag >> tmp) | (v2 << (32 - tmp));
+
+			frag &= idmask;
 		}
-		for (; (v2 & 255) == 0; v2 >>= 8, mapptr += 8);
-		for (; (v2 & 1) == 0; v2 >>= 1, mapptr += 1);
-		mapptr += 1;
-
-		if ((v1 & ((1 << idlen) - 1)) == frag_id) {
-			int length = mapptr - start;
-			if (*offset >= length)
-				*offset -= length;
-			else
-				return start + *offset - zone;
+		//asm("@ get fragment id end");
+
+		mapptr = start + idlen;
+
+		/*
+		 * find end of fragment
+		 */
+		//asm("@ find end of fragment start");
+		{
+			unsigned long v2;
+
+			while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
+				mapptr = (mapptr & ~31) + 32;
+				if (mapptr >= mapsize)
+					goto error;
+			}
+
+			mapptr += 1 + ffz(~v2);
 		}
+		//asm("@ find end of fragment end");
+
+		if (frag == frag_id)
+			goto found;
+again:
+		start = mapptr;
 	} while (mapptr < mapsize);
+
+error:
 	return -1;
+
+found:
+	{
+		int length = mapptr - start;
+		if (*offset >= length) {
+			*offset -= length;
+			goto again;
+		}
+	}
+	return start + *offset;
 }
 
-int adfs_map_lookup (struct super_block *sb, int frag_id, int offset)
+/*
+ * Scan the free space map, for this zone, calculating the total
+ * number of map bits in each free space fragment.
+ *
+ * Note: idmask is limited to 15 bits [3.2]
+ */
+static unsigned int
+scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
 {
-	unsigned int start_zone, zone, max_zone, mapoff, secoff;
+	const unsigned int mapsize = dm->dm_endbit + 32;
+	const unsigned int idlen  = asb->s_idlen;
+	const unsigned int frag_idlen = idlen <= 15 ? idlen : 15;
+	const unsigned int idmask = (1 << frag_idlen) - 1;
+	unsigned long *map = (unsigned long *)dm->dm_bh->b_data;
+	unsigned int start = 8, mapptr;
+	unsigned long frag;
+	unsigned long total = 0;
+
+	/*
+	 * get fragment id
+	 */
+	//asm("@ get fragment id start");
+	{
+		unsigned long v2;
+		unsigned int tmp;
+
+		tmp = start >> 5;
 
-	zone = start_zone = frag_id / sb->u.adfs_sb.s_ids_per_zone;
-	max_zone = sb->u.adfs_sb.s_map_size;
+		frag = le32_to_cpu(map[tmp]);
+		v2   = le32_to_cpu(map[tmp + 1]);
 
-	if (start_zone >= max_zone) {
-		adfs_error (sb, "adfs_map_lookup", "fragment %X is invalid (zone = %d, max = %d)",
-			    frag_id, start_zone, max_zone);
-		return 0;
+		tmp  = start & 31;
+
+		frag = (frag >> tmp) | (v2 << (32 - tmp));
+
+		frag &= idmask;
 	}
+	//asm("@ get fragment id end");
 
-	/* Convert sector offset to map offset */
-	mapoff = adfs_convert_sector_to_map (sb, offset);
-	/* Calculate sector offset into map block */
-	secoff = offset - adfs_convert_map_to_sector (sb, mapoff);
+	/*
+	 * If the freelink is null, then no free fragments
+	 * exist in this zone.
+	 */
+	if (frag == 0)
+		return 0;
 
 	do {
-		int result = lookup_zone (sb, zone, frag_id, &mapoff);
+		start += frag;
+
+		/*
+		 * get fragment id
+		 */
+		//asm("@ get fragment id start");
+		{
+			unsigned long v2;
+			unsigned int tmp;
+
+			tmp = start >> 5;
+
+			frag = le32_to_cpu(map[tmp]);
+			v2   = le32_to_cpu(map[tmp + 1]);
+
+			tmp  = start & 31;
 
-		if (result != -1) {
-			result += zone ? (zone * sb->u.adfs_sb.s_zonesize) - (ADFS_DR_SIZE << 3): 0;
-			return adfs_convert_map_to_sector (sb, result) + secoff;
+			frag = (frag >> tmp) | (v2 << (32 - tmp));
+
+			frag &= idmask;
+		}
+		//asm("@ get fragment id end");
+
+		mapptr = start + idlen;
+
+		/*
+		 * find end of fragment
+		 */
+		//asm("@ find end of fragment start");
+		{
+			unsigned long v2;
+
+			while ((v2 = map[mapptr >> 5] >> (mapptr & 31)) == 0) {
+				mapptr = (mapptr & ~31) + 32;
+				if (mapptr >= mapsize)
+					goto error;
+			}
+
+			mapptr += 1 + ffz(~v2);
 		}
+		//asm("@ find end of fragment end");
+
+		total += mapptr - start;
+	} while (frag >= idlen + 1);
+
+	if (frag != 0)
+		printk(KERN_ERR "adfs: undersized free fragment\n");
+
+	return total;
+error:
+	printk(KERN_ERR "adfs: oversized free fragment\n");
+	return 0;
+}
+
+static int
+scan_map(struct adfs_sb_info *asb, unsigned int zone,
+	 const unsigned int frag_id, unsigned int mapoff)
+{
+	const unsigned int idlen = asb->s_idlen;
+	struct adfs_discmap *dm, *dm_end;
+	int result;
+
+	dm	= asb->s_map + zone;
+	zone	= asb->s_map_size;
+	dm_end	= asb->s_map + zone;
+
+	do {
+		result = lookup_zone(dm, idlen, frag_id, &mapoff);
+
+		if (result != -1)
+			goto found;
+
+		dm ++;
+		if (dm == dm_end)
+			dm = asb->s_map;
+	} while (--zone > 0);
+
+	return -1;
+found:
+	result -= dm->dm_startbit;
+	result += dm->dm_startblk;
 
-		zone ++;
-		if (zone >= max_zone)
-			zone = 0;
+	return result;
+}
+
+/*
+ * calculate the amount of free blocks in the map.
+ *
+ *              n=1
+ *  total_free = E(free_in_zone_n)
+ *              nzones
+ */
+unsigned int
+adfs_map_free(struct super_block *sb)
+{
+	struct adfs_sb_info *asb = &sb->u.adfs_sb;
+	struct adfs_discmap *dm;
+	unsigned int total = 0;
+	unsigned int zone;
+
+	dm   = asb->s_map;
+	zone = asb->s_map_size;
+
+	do {
+		total += scan_free_map(asb, dm++);
+	} while (--zone > 0);
+
+	return signed_asl(total, asb->s_map2blk);
+}
 
-	} while (zone != start_zone);
+int adfs_map_lookup (struct super_block *sb, int frag_id, int offset)
+{
+	struct adfs_sb_info *asb = &sb->u.adfs_sb;
+	unsigned int zone, mapoff;
+	int result;
+
+	/*
+	 * map & root fragment is special - it starts in the center of the
+	 * disk.  The other fragments start at zone (frag / ids_per_zone)
+	 */
+	if (frag_id == ADFS_ROOT_FRAG)
+		zone = asb->s_map_size >> 1;
+	else
+		zone = frag_id / asb->s_ids_per_zone;
+
+	if (zone >= asb->s_map_size)
+		goto bad_fragment;
+
+	/* Convert sector offset to map offset */
+	mapoff = signed_asl(offset, -asb->s_map2blk);
+
+	read_lock(&adfs_map_lock);
+	result = scan_map(asb, zone, frag_id, mapoff);
+	read_unlock(&adfs_map_lock);
+
+	if (result > 0) {
+		unsigned int secoff;
+
+		/* Calculate sector offset into map block */
+		secoff = offset - signed_asl(mapoff, asb->s_map2blk);
+		return secoff + signed_asl(result, asb->s_map2blk);
+	}
 
-	adfs_error (sb, "adfs_map_lookup", "fragment %X at offset %d not found in map (start zone %d)",
-		    frag_id, offset, start_zone);
+	adfs_error(sb, "fragment %04X at offset %d not found in map",
+		   frag_id, offset);
+	return 0;
+
+bad_fragment:
+	adfs_error(sb, "fragment %X is invalid (zone = %d, max = %d)",
+		   frag_id, zone, asb->s_map_size);
 	return 0;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/namei.c linux/fs/adfs/namei.c
--- v2.3.42/linux/fs/adfs/namei.c	Thu May 13 10:53:59 1999
+++ linux/fs/adfs/namei.c	Wed Dec 31 16:00:00 1969
@@ -1,113 +0,0 @@
-/*
- *  linux/fs/adfs/namei.c
- *
- * Copyright (C) 1997 Russell King
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/adfs_fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-
-/*
- * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure
- */
-static int adfs_match (int len, const char * const name, struct adfs_idir_entry *de)
-{
-	int i;
-
-	if (!de || len > ADFS_NAME_LEN)
-		return 0;
-	/*
-	 * "" means "." ---> so paths like "/usr/lib//libc.a" work
-	 */
-	if (!len && de->name_len == 1 && de->name[0] == '.' &&
-	    de->name[1] == '\0')
-		return 1;
-	if (len != de->name_len)
-		return 0;
-
-	for (i = 0; i < len; i++)
-		if ((de->name[i] ^ name[i]) & 0x5f)
-			return 0;
-	return 1;
-}
-
-static int adfs_find_entry (struct inode *dir, const char * const name, int namelen,
-			    struct adfs_idir_entry *ide)
-{
-	struct super_block *sb;
-	struct buffer_head *bh[4];
-	union  adfs_dirtail dt;
-	unsigned long parent_object_id, dir_object_id;
-	int buffers, pos;
-
-	sb = dir->i_sb;
-
-	if (adfs_inode_validate (dir)) {
-		adfs_error (sb, "adfs_find_entry",
-			    "invalid inode number: %lu", dir->i_ino);
-		return 0;
-	}
-
-	if (!(buffers = adfs_dir_read (dir, bh))) {
-		adfs_error (sb, "adfs_find_entry", "unable to read directory");
-		return 0;
-	}
-
-	if (adfs_dir_check (dir, bh, buffers, &dt)) {
-		adfs_dir_free (bh, buffers);
-		return 0;
-	}
-
-	parent_object_id = adfs_val (dt.new.dirparent, 3);
-	dir_object_id = adfs_inode_objid (dir);
-
-	if (namelen == 2 && name[0] == '.' && name[1] == '.') {
-		ide->name_len = 2;
-		ide->name[0] = ide->name[1] = '.';
-		ide->name[2] = '\0';
-		ide->inode_no = adfs_inode_generate (parent_object_id, 0);
-		adfs_dir_free (bh, buffers);
-		return 1;
-	}
-
-	pos = 5;
-
-	do {
-		if (!adfs_dir_get (sb, bh, buffers, pos, dir_object_id, ide))
-			break;
-
-		if (adfs_match (namelen, name, ide)) {
-			adfs_dir_free (bh, buffers);
-			return pos;
-		}
-		pos += 26;
-	} while (1);
-	adfs_dir_free (bh, buffers);
-	return 0;
-}
-
-struct dentry *adfs_lookup (struct inode *dir, struct dentry *dentry)
-{
-	struct inode *inode = NULL;
-	struct adfs_idir_entry de;
-	unsigned long ino;
-
-	if (dentry->d_name.len > ADFS_NAME_LEN)
-		return ERR_PTR(-ENAMETOOLONG);
-
-	if (adfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de)) {
-		ino = de.inode_no;
-		inode = iget (dir->i_sb, ino);
-
-		if (!inode)
-			return ERR_PTR(-EACCES);
-	}
-	d_add(dentry, inode);
-	return NULL;
-}
diff -u --recursive --new-file v2.3.42/linux/fs/adfs/super.c linux/fs/adfs/super.c
--- v2.3.42/linux/fs/adfs/super.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/adfs/super.c	Sun Feb  6 17:45:25 2000
@@ -1,9 +1,9 @@
 /*
  *  linux/fs/adfs/super.c
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1999 Russell King
  */
-
+#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -21,12 +21,11 @@
 
 #include <stdarg.h>
 
-static void adfs_put_super(struct super_block *sb);
-static int adfs_remount(struct super_block *sb, int *flags, char *data);
-static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
-void adfs_read_inode(struct inode *inode);
+#include "adfs.h"
+#include "dir_f.h"
+#include "dir_fplus.h"
 
-void adfs_error(struct super_block *sb, const char *function, const char *fmt, ...)
+void __adfs_error(struct super_block *sb, const char *function, const char *fmt, ...)
 {
 	char error_buf[128];
 	va_list args;
@@ -40,7 +39,74 @@
 		function ? function : "", error_buf);
 }
 
-static unsigned char adfs_calczonecheck(struct super_block *sb, char *map)
+static int adfs_checkdiscrecord(struct adfs_discrecord *dr)
+{
+	int i;
+
+	/* sector size must be 256, 512 or 1024 bytes */
+	if (dr->log2secsize != 8 &&
+	    dr->log2secsize != 9 &&
+	    dr->log2secsize != 10)
+		return 1;
+
+	/* idlen must be at least log2secsize + 3 */
+	if (dr->idlen < dr->log2secsize + 3)
+		return 1;
+
+	/* we cannot have such a large disc that we
+	 * are unable to represent sector offsets in
+	 * 32 bits.  This works out at 2.0 TB.
+	 */
+	if (dr->disc_size_high >> dr->log2secsize)
+		return 1;
+
+	/*
+	 * The following checks are not required for F+
+	 * stage 1.
+	 */
+#if 0
+	/* idlen must be smaller be no greater than 15 */
+	if (dr->idlen > 15)
+		return 1;
+
+	/* nzones must be less than 128 for the root
+	 * directory to be addressable
+	 */
+	if (dr->nzones >= 128 && dr->nzones_high == 0)
+		return 1;
+
+	/* root must be of the form 0x2.. */
+	if ((le32_to_cpu(dr->root) & 0xffffff00) != 0x00000200)
+		return 1;
+#else
+	/*
+	 * Stage 2 F+ does not require the following check
+	 */
+#if 0
+	/* idlen must be no greater than 16 v2 [1.0] */
+	if (dr->idlen > 16)
+		return 1;
+
+	/* we can't handle F+ discs yet */
+	if (dr->format_version || dr->root_size)
+		return 1;
+
+#else
+	/* idlen must be no greater than 19 v2 [1.0] */
+	if (dr->idlen > 19)
+		return 1;
+#endif
+#endif
+
+	/* reserved bytes should be zero */
+	for (i = 0; i < sizeof(dr->unused52); i++)
+		if (dr->unused52[i] != 0)
+			return 1;
+
+	return 0;
+}
+
+static unsigned char adfs_calczonecheck(struct super_block *sb, unsigned char *map)
 {
 	unsigned int v0, v1, v2, v3;
 	int i;
@@ -64,46 +130,34 @@
 	return v0 ^ v1 ^ v2 ^ v3;
 }
 
-static int adfs_checkmap(struct super_block *sb)
+static int adfs_checkmap(struct super_block *sb, struct adfs_discmap *dm)
 {
 	unsigned char crosscheck = 0, zonecheck = 1;
 	int i;
 
 	for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) {
-		char *map;
+		unsigned char *map;
+
+		map = dm[i].dm_bh->b_data;
 
-		map = sb->u.adfs_sb.s_map[i]->b_data;
 		if (adfs_calczonecheck(sb, map) != map[0]) {
-			adfs_error(sb, "adfs_checkmap", "zone %d fails zonecheck", i);
+			adfs_error(sb, "zone %d fails zonecheck", i);
 			zonecheck = 0;
 		}
 		crosscheck ^= map[3];
 	}
 	if (crosscheck != 0xff)
-		adfs_error(sb, "adfs_checkmap", "crosscheck != 0xff");
+		adfs_error(sb, "crosscheck != 0xff");
 	return crosscheck == 0xff && zonecheck;
 }
 
-static struct super_operations adfs_sops = {
-	adfs_read_inode,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	adfs_put_super,
-	NULL,
-	adfs_statfs,
-	adfs_remount
-};
-
 static void adfs_put_super(struct super_block *sb)
 {
 	int i;
 
 	for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
-		brelse(sb->u.adfs_sb.s_map[i]);
+		brelse(sb->u.adfs_sb.s_map[i].dm_bh);
 	kfree(sb->u.adfs_sb.s_map);
-	brelse(sb->u.adfs_sb.s_sbh);
 	MOD_DEC_USE_COUNT;
 }
 
@@ -159,13 +213,107 @@
 	return parse_options(sb, data);
 }
 
+static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+	struct adfs_sb_info *asb = &sb->u.adfs_sb;
+	struct statfs tmp;
+
+	tmp.f_type    = ADFS_SUPER_MAGIC;
+	tmp.f_namelen = asb->s_namelen;
+	tmp.f_bsize   = sb->s_blocksize;
+	tmp.f_blocks  = asb->s_size;
+	tmp.f_files   = asb->s_ids_per_zone * asb->s_map_size;
+	tmp.f_bavail  =
+	tmp.f_bfree   = adfs_map_free(sb);
+	tmp.f_ffree   = tmp.f_bfree * tmp.f_files / tmp.f_blocks;
+
+	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static struct super_operations adfs_sops = {
+	adfs_read_inode,	/* read_inode		*/
+	adfs_write_inode,	/* write_inode		*/
+	NULL,			/* put_inode		*/
+	NULL,			/* delete_inode		*/
+	adfs_notify_change,	/* notify_change	*/
+	adfs_put_super,		/* put_super		*/
+	NULL,			/* write_super		*/
+	adfs_statfs,		/* statfs		*/
+	adfs_remount,		/* remount_fs		*/
+	NULL,			/* clear_inode		*/
+	NULL			/* umount_begin		*/
+};
+
+static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_discrecord *dr)
+{
+	struct adfs_discmap *dm;
+	unsigned int map_addr, zone_size, nzones;
+	int i, zone;
+
+	nzones    = sb->u.adfs_sb.s_map_size;
+	zone_size = (8 << dr->log2secsize) - le16_to_cpu(dr->zone_spare);
+	map_addr  = (nzones >> 1) * zone_size -
+		     ((nzones > 1) ? ADFS_DR_SIZE_BITS : 0);
+	map_addr  = signed_asl(map_addr, sb->u.adfs_sb.s_map2blk);
+
+	sb->u.adfs_sb.s_ids_per_zone = zone_size / (sb->u.adfs_sb.s_idlen + 1);
+
+	dm = kmalloc(nzones * sizeof(*dm), GFP_KERNEL);
+	if (dm == NULL) {
+		adfs_error(sb, "not enough memory");
+		return NULL;
+	}
+
+	for (zone = 0; zone < nzones; zone++, map_addr++) {
+		dm[zone].dm_startbit = 0;
+		dm[zone].dm_endbit   = zone_size;
+		dm[zone].dm_startblk = zone * zone_size - ADFS_DR_SIZE_BITS;
+		dm[zone].dm_bh       = bread(sb->s_dev, map_addr, sb->s_blocksize);
+
+		if (!dm[zone].dm_bh) {
+			adfs_error(sb, "unable to read map");
+			goto error_free;
+		}
+	}
+
+	/* adjust the limits for the first and last map zones */
+	i = zone - 1;
+	dm[0].dm_startblk = 0;
+	dm[0].dm_startbit = ADFS_DR_SIZE_BITS;
+	dm[i].dm_endbit   = (dr->disc_size_high << (32 - dr->log2bpmb)) +
+			    (dr->disc_size >> dr->log2bpmb) +
+			    (ADFS_DR_SIZE_BITS - i * zone_size);
+
+	if (adfs_checkmap(sb, dm))
+		return dm;
+
+	adfs_error(sb, NULL, "map corrupted");
+
+error_free:
+	while (--zone >= 0)
+		brelse(dm[zone].dm_bh);
+
+	kfree(dm);
+	return NULL;
+}
+
+static inline unsigned long adfs_discsize(struct adfs_discrecord *dr, int block_bits)
+{
+	unsigned long discsize;
+
+	discsize  = le32_to_cpu(dr->disc_size_high) << (32 - block_bits);
+	discsize |= le32_to_cpu(dr->disc_size) >> block_bits;
+
+	return discsize;
+}
+
 struct super_block *adfs_read_super(struct super_block *sb, void *data, int silent)
 {
 	struct adfs_discrecord *dr;
 	struct buffer_head *bh;
+	struct object_info root_obj;
 	unsigned char *b_data;
 	kdev_t dev = sb->s_dev;
-	int i, j;
 
 	/* set default options */
 	sb->u.adfs_sb.s_uid = 0;
@@ -180,7 +328,7 @@
 	lock_super(sb);
 	set_blocksize(dev, BLOCK_SIZE);
 	if (!(bh = bread(dev, ADFS_DISCRECORD / BLOCK_SIZE, BLOCK_SIZE))) {
-		adfs_error(sb, NULL, "unable to read superblock");
+		adfs_error(sb, "unable to read superblock");
 		goto error_unlock;
 	}
 
@@ -192,8 +340,19 @@
 				"%s.\n", kdevname(dev));
 		goto error_free_bh;
 	}
+
 	dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
 
+	/*
+	 * Do some sanity checks on the ADFS disc record
+	 */
+	if (adfs_checkdiscrecord(dr)) {
+		if (!silent)
+			printk("VPS: Can't find an adfs filesystem on dev "
+				"%s.\n", kdevname(dev));
+		goto error_free_bh;
+	}
+
 	sb->s_blocksize_bits = dr->log2secsize;
 	sb->s_blocksize = 1 << sb->s_blocksize_bits;
 	if (sb->s_blocksize != BLOCK_SIZE &&
@@ -204,13 +363,13 @@
 		set_blocksize(dev, sb->s_blocksize);
 		bh = bread(dev, ADFS_DISCRECORD / sb->s_blocksize, sb->s_blocksize);
 		if (!bh) {
-			adfs_error(sb, NULL, "couldn't read superblock on "
+			adfs_error(sb, "couldn't read superblock on "
 				"2nd try.");
 			goto error_unlock;
 		}
 		b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize);
 		if (adfs_checkbblk(b_data)) {
-			adfs_error(sb, NULL, "disc record mismatch, very weird!");
+			adfs_error(sb, "disc record mismatch, very weird!");
 			goto error_free_bh;
 		}
 		dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET);
@@ -221,92 +380,66 @@
 				"%s.\n", kdevname(dev));
 		goto error_free_bh;
 	}
-	/* blocksize on this device should now be set to the adfs log2secsize */
-
-	sb->u.adfs_sb.s_sbh		= bh;
-	sb->u.adfs_sb.s_dr		= dr;
 
-	/* s_zone_size = size of 1 zone (1 sector) * bits_in_byte - zone_spare =>
-	 * number of map bits in a zone
-	 */
-	sb->u.adfs_sb.s_zone_size	= (8 << dr->log2secsize) - dr->zone_spare;
-
-	/* s_ids_per_zone = bit size of 1 zone / min. length of fragment block =>
-	 * number of ids in one zone
+	/*
+	 * blocksize on this device should now be set to the ADFS log2secsize
 	 */
-	sb->u.adfs_sb.s_ids_per_zone	= sb->u.adfs_sb.s_zone_size / (dr->idlen + 1);
 
-	/* s_idlen = length of 1 id */
-	sb->u.adfs_sb.s_idlen		= dr->idlen;
+	sb->s_magic		 = ADFS_SUPER_MAGIC;
+	sb->u.adfs_sb.s_idlen	 = dr->idlen;
+	sb->u.adfs_sb.s_map_size = dr->nzones | (dr->nzones_high << 8);
+	sb->u.adfs_sb.s_map2blk	 = dr->log2bpmb - dr->log2secsize;
+	sb->u.adfs_sb.s_size     = adfs_discsize(dr, sb->s_blocksize_bits);
+	sb->u.adfs_sb.s_version  = dr->format_version;
+	sb->u.adfs_sb.s_log2sharesize = dr->log2sharesize;
 
-	/* map size (in sectors) = number of zones */
-	sb->u.adfs_sb.s_map_size	= dr->nzones;
-
-	/* zonesize = size of sector - zonespare */
-	sb->u.adfs_sb.s_zonesize	= (sb->s_blocksize << 3) - dr->zone_spare;
-
-	/* map start (in sectors) = start of zone (number of zones) / 2 */
-	sb->u.adfs_sb.s_map_block	= (dr->nzones >> 1) * sb->u.adfs_sb.s_zone_size -
-					   ((dr->nzones > 1) ? 8 * ADFS_DR_SIZE : 0);
-
-	/* (signed) number of bits to shift left a map address to a sector address */
-	sb->u.adfs_sb.s_map2blk		= dr->log2bpmb - dr->log2secsize;
-
-	if (sb->u.adfs_sb.s_map2blk >= 0)
-		sb->u.adfs_sb.s_map_block <<= sb->u.adfs_sb.s_map2blk;
-	else
-		sb->u.adfs_sb.s_map_block >>= -sb->u.adfs_sb.s_map2blk;
-
-	printk(KERN_DEBUG "ADFS: zone size %d, IDs per zone %d, map address %X size %d sectors\n",
-		sb->u.adfs_sb.s_zone_size, sb->u.adfs_sb.s_ids_per_zone,
-		sb->u.adfs_sb.s_map_block, sb->u.adfs_sb.s_map_size);
-	printk(KERN_DEBUG "ADFS: sector size %d, map bit size %d, share size %d\n",
-		1 << dr->log2secsize, 1 << dr->log2bpmb,
-		1 << (dr->log2secsize + dr->log2sharesize));
-
-	sb->s_magic = ADFS_SUPER_MAGIC;
-
-	sb->u.adfs_sb.s_map = kmalloc(sb->u.adfs_sb.s_map_size *
-				sizeof(struct buffer_head *), GFP_KERNEL);
-	if (sb->u.adfs_sb.s_map == NULL) {
-		adfs_error(sb, NULL, "not enough memory");
+	sb->u.adfs_sb.s_map = adfs_read_map(sb, dr);
+	if (!sb->u.adfs_sb.s_map)
 		goto error_free_bh;
-	}
 
-	for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) {
-		sb->u.adfs_sb.s_map[i] = bread(dev,
-						sb->u.adfs_sb.s_map_block + i,
-						sb->s_blocksize);
-		if (!sb->u.adfs_sb.s_map[i]) {
-			for (j = 0; j < i; j++)
-				brelse(sb->u.adfs_sb.s_map[j]);
-			kfree(sb->u.adfs_sb.s_map);
-			adfs_error(sb, NULL, "unable to read map");
-			goto error_free_bh;
-		}
-	}
-	if (!adfs_checkmap(sb)) {
-		for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
-			brelse(sb->u.adfs_sb.s_map[i]);
-		adfs_error(sb, NULL, "map corrupted");
-		goto error_free_bh;
-	}
+	brelse(bh);
 
-	dr = (struct adfs_discrecord *)(sb->u.adfs_sb.s_map[0]->b_data + 4);
+	/*
+	 * set up enough so that we can read an inode
+	 */
+	sb->s_op = &adfs_sops;
 	unlock_super(sb);
 
+	dr = (struct adfs_discrecord *)(sb->u.adfs_sb.s_map[0].dm_bh->b_data + 4);
+
+	root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root);
+	root_obj.name_len  = 0;
+	root_obj.loadaddr  = 0;
+	root_obj.execaddr  = 0;
+	root_obj.size	   = ADFS_NEWDIR_SIZE;
+	root_obj.attr	   = ADFS_NDA_DIRECTORY   | ADFS_NDA_OWNER_READ |
+			     ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ;
+
 	/*
-	 * set up enough so that it can read an inode
+	 * If this is a F+ disk with variable length directories,
+	 * get the root_size from the disc record.
 	 */
-	sb->s_op = &adfs_sops;
-	sb->u.adfs_sb.s_root = adfs_inode_generate(dr->root, 0);
-	sb->s_root = d_alloc_root(iget(sb, sb->u.adfs_sb.s_root));
+	if (sb->u.adfs_sb.s_version) {
+		root_obj.size = dr->root_size;
+		sb->u.adfs_sb.s_dir     = &adfs_fplus_dir_ops;
+		sb->u.adfs_sb.s_namelen = ADFS_FPLUS_NAME_LEN;
+	} else {
+		sb->u.adfs_sb.s_dir     = &adfs_f_dir_ops;
+		sb->u.adfs_sb.s_namelen = ADFS_F_NAME_LEN;
+	}
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+	sb->s_root = d_alloc_root(adfs_iget(sb, &root_obj));
+#else
+	sb->s_root = d_alloc_root(adfs_iget(sb, &root_obj), NULL);
+#endif
 	if (!sb->s_root) {
+		int i;
+
 		for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
-			brelse(sb->u.adfs_sb.s_map[i]);
-		brelse(bh);
-		adfs_error(sb, NULL, "get root inode failed\n");
+			brelse(sb->u.adfs_sb.s_map[i].dm_bh);
+		kfree(sb->u.adfs_sb.s_map);
+		adfs_error(sb, "get root inode failed\n");
 		goto error_dec_use;
 	}
 	return sb;
@@ -320,65 +453,6 @@
 error:
 	sb->s_dev = 0;
 	return NULL;
-}
-
-static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
-{
-	struct statfs tmp;
-	const unsigned int nidlen = sb->u.adfs_sb.s_idlen + 1;
-
-	tmp.f_type = ADFS_SUPER_MAGIC;
-	tmp.f_bsize = sb->s_blocksize;
-	tmp.f_blocks = sb->u.adfs_sb.s_dr->disc_size_high << (32 - sb->s_blocksize_bits) |
-		       sb->u.adfs_sb.s_dr->disc_size >> sb->s_blocksize_bits;
-	tmp.f_files = tmp.f_blocks >> nidlen;
-	{
-		unsigned int i, j = 0;
-		const unsigned mask = (1 << (nidlen - 1)) - 1;
-		for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) {
-			const char *map = sb->u.adfs_sb.s_map[i]->b_data;
-			unsigned freelink, mapindex = 24;
-			j -= nidlen;
-			do {
-				unsigned char k, l, m;
-				unsigned off = (mapindex - nidlen) >> 3;
-				unsigned rem;
-				const unsigned boff = mapindex & 7;
-
-				/* get next freelink */
-
-				k = map[off++];
-				l = map[off++];
-				m = map[off++];
-				freelink = (m << 16) | (l << 8) | k;
-				rem = freelink >> (boff + nidlen - 1);
-				freelink = (freelink >> boff) & mask;
-				mapindex += freelink;
-
-				/* find its length and add it to running total */
-
-				while (rem == 0) {
-					j += 8;
-					rem = map[off++];
-				}
-				if ((rem & 0xff) == 0) j+=8, rem>>=8;
-				if ((rem & 0xf) == 0) j+=4, rem>>=4;
-				if ((rem & 0x3) == 0) j+=2, rem>>=2;
-				if ((rem & 0x1) == 0) j+=1;
-				j += nidlen - boff;
-				if (freelink <= nidlen) break;
-			} while (mapindex < 8 * sb->s_blocksize);
-			if (mapindex > 8 * sb->s_blocksize)
-				adfs_error(sb, NULL, "oversized free fragment\n");
-			else if (freelink)
-				adfs_error(sb, NULL, "undersized free fragment\n");
-		}
-		tmp.f_bfree = tmp.f_bavail = j <<
-			(sb->u.adfs_sb.s_dr->log2bpmb - sb->s_blocksize_bits);
-	}
-	tmp.f_ffree = tmp.f_bfree >> nidlen;
-	tmp.f_namelen = ADFS_NAME_LEN;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
 }
 
 static struct file_system_type adfs_fs_type = {
diff -u --recursive --new-file v2.3.42/linux/fs/affs/dir.c linux/fs/affs/dir.c
--- v2.3.42/linux/fs/affs/dir.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/affs/dir.c	Thu Feb 10 12:16:57 2000
@@ -28,17 +28,9 @@
 static ssize_t affs_dir_read(struct file *, char *, size_t, loff_t *);
 
 static struct file_operations affs_dir_operations = {
-	NULL,			/* lseek - default */
-	affs_dir_read,		/* read */
-	NULL,			/* write - bad */
-	affs_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync		/* default fsync */
+	read:		affs_dir_read,
+	readdir:	affs_readdir,
+	fsync:		file_fsync,
 };
 
 /*
@@ -55,14 +47,6 @@
 	affs_rmdir,		/* rmdir */
 	NULL,			/* mknod */
 	affs_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permissions */
-	NULL			/* revalidate */
 };
 
 static ssize_t
diff -u --recursive --new-file v2.3.42/linux/fs/affs/file.c linux/fs/affs/file.c
--- v2.3.42/linux/fs/affs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/affs/file.c	Thu Feb 10 12:16:57 2000
@@ -44,19 +44,10 @@
 static int alloc_ext_cache(struct inode *inode);
 
 static struct file_operations affs_file_operations = {
-	NULL,			/* lseek - default */
-	generic_file_read,	/* read */
-	affs_file_write,	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	file_fsync,		/* brute force, but works */
-	NULL,			/* fasync */
-	NULL			/* lock */
+	read:		generic_file_read,
+	write:		affs_file_write,
+	mmap:		generic_file_mmap,
+	fsync:		file_fsync,
 };
 
 struct inode_operations affs_file_inode_operations = {
@@ -72,28 +63,15 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	affs_bmap,		/* get_block */
-	block_read_full_page,	/* readpage */
-	NULL,			/* writepage */
 	affs_truncate,		/* truncate */
 	NULL,			/* permission */
 	NULL			/* revalidate */
 };
 
 static struct file_operations affs_file_operations_ofs = {
-	NULL,			/* lseek - default */
-	affs_file_read_ofs,	/* read */
-	affs_file_write_ofs,	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	file_fsync,		/* brute force, but works */
-	NULL,			/* fasync */
-	NULL			/* lock */
+	read:		affs_file_read_ofs,
+	write:		affs_file_write_ofs,
+	fsync:		file_fsync,
 };
 
 struct inode_operations affs_file_inode_operations_ofs = {
@@ -109,9 +87,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	affs_truncate,		/* truncate */
 	NULL,			/* permission */
 	NULL			/* revalidate */
@@ -340,6 +315,37 @@
 	affs_brelse(bh);
 	return key;
 }
+
+/* AFFS is currently broken */
+static int affs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
+{
+	BUG();
+	return -1;
+}
+static int affs_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,affs_get_block);
+}
+static int affs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,affs_get_block);
+}
+static int affs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page,from,to,affs_get_block,
+		&((struct inode*)page->mapping->host)->u.affs_i.mmu_private);
+}
+static int _affs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,affs_get_block);
+}
+struct address_space_operations affs_aops = {
+	readpage: affs_readpage,
+	writepage: affs_writepage,
+	prepare_write: affs_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: _affs_bmap
+};
 
 /* With the affs, getting a random block from a file is not
  * a simple business. Since this fs does not allow holes,
diff -u --recursive --new-file v2.3.42/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.3.42/linux/fs/affs/inode.c	Sun Mar  7 15:25:23 1999
+++ linux/fs/affs/inode.c	Thu Feb 10 12:16:57 2000
@@ -166,16 +166,20 @@
 	if (S_ISREG(inode->i_mode)) {
 		if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
 			inode->i_op = &affs_file_inode_operations_ofs;
-		} else {
-			inode->i_op = &affs_file_inode_operations;
+			return;
 		}
+		inode->i_op = &affs_file_inode_operations;
+		inode->i_mapping->a_ops = &affs_aops;
+		inode->u.affs_i.mmu_private = inode->i_size;
 	} else if (S_ISDIR(inode->i_mode)) {
 		/* Maybe it should be controlled by mount parameter? */
 		inode->i_mode |= S_ISVTX;
 		inode->i_op = &affs_dir_inode_operations;
 	}
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &affs_symlink_inode_operations;
+	else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_data.a_ops = &affs_symlink_aops;
+	}
 }
 
 void
diff -u --recursive --new-file v2.3.42/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.3.42/linux/fs/affs/namei.c	Sat May 15 23:43:05 1999
+++ linux/fs/affs/namei.c	Thu Feb 10 12:16:57 2000
@@ -275,9 +275,11 @@
 	pr_debug("AFFS: ino=%lu\n",inode->i_ino);
 	if (dir->i_sb->u.affs_sb.s_flags & SF_OFS)
 		inode->i_op = &affs_file_inode_operations_ofs;
-	else
+	else {
 		inode->i_op = &affs_file_inode_operations;
-
+		inode->i_mapping->a_ops = &affs_aops;
+		inode->u.affs_i.mmu_private = inode->i_size;
+	}
 	error = affs_add_entry(dir,NULL,inode,dentry,ST_FILE);
 	if (error)
 		goto out_iput;
@@ -401,7 +403,8 @@
 	if (!inode)
 		goto out;
 
-	inode->i_op   = &affs_symlink_inode_operations;
+	inode->i_op = &page_symlink_inode_operations;
+	inode->i_data.a_ops = &affs_symlink_aops;
 	inode->i_mode = S_IFLNK | 0777;
 	inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode);
 	error = -EIO;
diff -u --recursive --new-file v2.3.42/linux/fs/affs/symlink.c linux/fs/affs/symlink.c
--- v2.3.42/linux/fs/affs/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/affs/symlink.c	Thu Feb 10 12:16:57 2000
@@ -71,8 +71,6 @@
 	return err;
 }
 
-struct inode_operations affs_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
+struct address_space_operations affs_symlink_aops = {
 	readpage:	affs_symlink_readpage,
 };
diff -u --recursive --new-file v2.3.42/linux/fs/autofs/dir.c linux/fs/autofs/dir.c
--- v2.3.42/linux/fs/autofs/dir.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/autofs/dir.c	Thu Feb 10 12:16:57 2000
@@ -43,30 +43,12 @@
 }
 
 static struct file_operations autofs_dir_operations = {
-	NULL,			/* llseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	autofs_dir_readdir,	/* readdir */
+	readdir:	autofs_dir_readdir,
 };
 
 struct inode_operations autofs_dir_inode_operations = {
 	&autofs_dir_operations,	/* file operations */
 	NULL,			/* create */
 	autofs_dir_lookup,	/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
diff -u --recursive --new-file v2.3.42/linux/fs/autofs/init.c linux/fs/autofs/init.c
--- v2.3.42/linux/fs/autofs/init.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/autofs/init.c	Thu Feb 10 12:22:03 2000
@@ -31,8 +31,8 @@
 	unregister_filesystem(&autofs_fs_type);
 }
 
-module_init(init_autofs_fs) 
-module_exit(exit_autofs_fs)
+module_init(init_autofs_fs);
+module_exit(exit_autofs_fs);
 
 #ifdef DEBUG
 void autofs_say(const char *name, int len)
diff -u --recursive --new-file v2.3.42/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.3.42/linux/fs/autofs/root.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/autofs/root.c	Thu Feb 10 12:16:57 2000
@@ -24,12 +24,8 @@
 static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
 
 static struct file_operations autofs_root_operations = {
-        NULL,                   /* llseek */
-        NULL,                   /* read */
-        NULL,                   /* write */
-        autofs_root_readdir,    /* readdir */
-        NULL,                   /* poll */
-        autofs_root_ioctl,	/* ioctl */
+	readdir:	autofs_root_readdir,
+	ioctl:		autofs_root_ioctl,
 };
 
 struct inode_operations autofs_root_inode_operations = {
@@ -41,16 +37,6 @@
         autofs_root_symlink,    /* symlink */
         autofs_root_mkdir,      /* mkdir */
         autofs_root_rmdir,      /* rmdir */
-        NULL,                   /* mknod */
-        NULL,                   /* rename */
-        NULL,                   /* readlink */
-        NULL,                   /* follow_link */
-        NULL,                   /* get_block */
-        NULL,                   /* readpage */
-        NULL,                   /* writepage */
-        NULL,                   /* truncate */
-        NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
diff -u --recursive --new-file v2.3.42/linux/fs/autofs4/autofs_i.h linux/fs/autofs4/autofs_i.h
--- v2.3.42/linux/fs/autofs4/autofs_i.h	Fri Jan 28 15:09:08 2000
+++ linux/fs/autofs4/autofs_i.h	Wed Feb  9 21:33:39 2000
@@ -12,7 +12,7 @@
 
 /* Internal header file for autofs */
 
-#include <linux/auto_fs.h>
+#include <linux/auto_fs4.h>
 #include <linux/list.h>
 
 /* This is the range of ioctl() numbers we claim as ours */
diff -u --recursive --new-file v2.3.42/linux/fs/autofs4/inode.c linux/fs/autofs4/inode.c
--- v2.3.42/linux/fs/autofs4/inode.c	Tue Feb  1 01:35:44 2000
+++ linux/fs/autofs4/inode.c	Mon Feb  7 21:03:56 2000
@@ -140,7 +140,8 @@
 	*gid = current->gid;
 	*pgrp = current->pgrp;
 
-	*minproto = *maxproto = AUTOFS_MAX_PROTO_VERSION;
+	*minproto = AUTOFS_MIN_PROTO_VERSION;
+	*maxproto = AUTOFS_MAX_PROTO_VERSION;
 
 	*pipefd = -1;
 
diff -u --recursive --new-file v2.3.42/linux/fs/autofs4/waitq.c linux/fs/autofs4/waitq.c
--- v2.3.42/linux/fs/autofs4/waitq.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/autofs4/waitq.c	Sun Feb  6 18:50:55 2000
@@ -86,7 +86,7 @@
 	
 static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
 				 struct autofs_wait_queue *wq,
-				 enum autofs_packet_type type)
+				 int type)
 {
 	union autofs_packet_union pkt;
 	size_t pktsz;
diff -u --recursive --new-file v2.3.42/linux/fs/bad_inode.c linux/fs/bad_inode.c
--- v2.3.42/linux/fs/bad_inode.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/bad_inode.c	Thu Feb 10 12:16:57 2000
@@ -30,19 +30,19 @@
 
 static struct file_operations bad_file_ops =
 {
-	EIO_ERROR,		/* lseek */
-	EIO_ERROR,		/* read */
-	EIO_ERROR,		/* write */
-	EIO_ERROR,		/* readdir */
-	EIO_ERROR,		/* select */
-	EIO_ERROR,		/* ioctl */
-	EIO_ERROR,		/* mmap */
-	EIO_ERROR,		/* open */
-	EIO_ERROR,		/* flush */
-	EIO_ERROR,		/* release */
-	EIO_ERROR,		/* fsync */
-	EIO_ERROR,		/* fasync */
-	EIO_ERROR,		/* lock */
+	llseek:		EIO_ERROR,
+	read:		EIO_ERROR,
+	write:		EIO_ERROR,
+	readdir:	EIO_ERROR,
+	poll:		EIO_ERROR,
+	ioctl:		EIO_ERROR,
+	mmap:		EIO_ERROR,
+	open:		EIO_ERROR,
+	flush:		EIO_ERROR,
+	release:	EIO_ERROR,
+	fsync:		EIO_ERROR,
+	fasync:		EIO_ERROR,
+	lock:		EIO_ERROR,
 };
 
 struct inode_operations bad_inode_ops =
@@ -59,9 +59,6 @@
 	EIO_ERROR,		/* rename */
 	EIO_ERROR,		/* readlink */
 	bad_follow_link,	/* follow_link */
-	EIO_ERROR,		/* get_block */
-	EIO_ERROR,		/* readpage */
-	EIO_ERROR,		/* writepage */
 	EIO_ERROR,		/* truncate */
 	EIO_ERROR,		/* permission */
 	EIO_ERROR		/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/fs/bfs/bfs_defs.h linux/fs/bfs/bfs_defs.h
--- v2.3.42/linux/fs/bfs/bfs_defs.h	Sun Nov  7 16:37:34 1999
+++ linux/fs/bfs/bfs_defs.h	Sun Feb  6 18:43:21 2000
@@ -5,7 +5,6 @@
 #define su_lf_ioff	u.bfs_sb.si_lf_ioff
 #define su_lf_sblk	u.bfs_sb.si_lf_sblk
 #define su_lf_eblk	u.bfs_sb.si_lf_eblk
-#define su_bmap		u.bfs_sb.si_bmap
 #define su_imap		u.bfs_sb.si_imap
 #define su_sbh		u.bfs_sb.si_sbh
 #define su_bfs_sb	u.bfs_sb.si_bfs_sb
@@ -13,3 +12,6 @@
 #define iu_dsk_ino	u.bfs_i.i_dsk_ino
 #define iu_sblock	u.bfs_i.i_sblock
 #define iu_eblock	u.bfs_i.i_eblock
+
+#define printf(format, args...) \
+	printk(KERN_ERR "BFS-fs: " __FUNCTION__ "(): " format, ## args)
diff -u --recursive --new-file v2.3.42/linux/fs/bfs/dir.c linux/fs/bfs/dir.c
--- v2.3.42/linux/fs/bfs/dir.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/bfs/dir.c	Thu Feb 10 12:16:57 2000
@@ -14,9 +14,9 @@
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(x...)	printk(x)
+#define dprintf(x...)	printf(x)
 #else
-#define DBG(x...)
+#define dprintf(x...)
 #endif
 
 static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino);
@@ -38,14 +38,13 @@
 	int block;
 
 	if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) {
-		printk(KERN_ERR "BFS-fs: %s(): Bad inode or not a directory %s:%08lx\n",
-			__FUNCTION__, bdevname(dev), dir->i_ino);
+		printf("Bad inode or not a directory %s:%08lx\n", bdevname(dev), dir->i_ino);
 		return -EBADF;
 	}
 
 	if (f->f_pos & (BFS_DIRENT_SIZE-1)) {
-		printk(KERN_ERR "BFS-fs: %s(): Bad f_pos=%08lx for %s:%08lx\n", 
-			__FUNCTION__, (unsigned long)f->f_pos, bdevname(dev), dir->i_ino);
+		printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos, 
+			bdevname(dev), dir->i_ino);
 		return -EBADF;
 	}
 
@@ -77,18 +76,9 @@
 }
 
 static struct file_operations bfs_dir_operations = {
-	llseek:			NULL,
 	read:			bfs_dir_read,
-	write:			NULL,
 	readdir:		bfs_readdir,
-	poll:			NULL,
-	ioctl:			NULL,
-	mmap:			NULL,
-	open:			NULL,
-	flush:			NULL,
-	release:		NULL,
 	fsync:			file_fsync,
-	fasync:			NULL,
 };
 
 extern void dump_imap(const char *, struct super_block *);
@@ -117,6 +107,7 @@
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_blocks = inode->i_blksize = 0;
 	inode->i_op = &bfs_file_inops;
+	inode->i_mapping->a_ops = &bfs_aops;
 	inode->i_mode = mode;
 	inode->i_ino = inode->iu_dsk_ino = ino;
 	inode->iu_sblock = inode->iu_eblock = 0;
@@ -189,9 +180,8 @@
 		goto out_brelse;
 
 	if (!inode->i_nlink) {
-		printk(KERN_WARNING 
-		"BFS-fs: %s(): unlinking non-existent file %s:%lu (nlink=%d)\n",
-		__FUNCTION__, bdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
+		printf("unlinking non-existent file %s:%lu (nlink=%d)\n", bdevname(inode->i_dev), 
+				inode->i_ino, inode->i_nlink);
 		inode->i_nlink = 1;
 	}
 	de->ino = 0;
@@ -276,14 +266,6 @@
 	rmdir:			NULL,
 	mknod:			NULL,
 	rename:			bfs_rename,
-	readlink:		NULL,
-	follow_link:		NULL,
-	get_block:		NULL,
-	readpage:		NULL,
-	writepage:		NULL,
-	truncate:		NULL,
-	permission:		NULL,
-	revalidate:		NULL
 };
 
 static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino)
@@ -294,7 +276,7 @@
 	kdev_t dev;
 	int i;
 
-	DBG(KERN_ERR "BFS-fs: %s(%s,%d)\n", __FUNCTION__, name, namelen);
+	dprintf("name=%s, namelen=%d\n", name, namelen);
 
 	if (!namelen)
 		return -ENOENT;
diff -u --recursive --new-file v2.3.42/linux/fs/bfs/file.c linux/fs/bfs/file.c
--- v2.3.42/linux/fs/bfs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/bfs/file.c	Thu Feb 10 12:16:58 2000
@@ -5,68 +5,149 @@
  */
 
 #include <linux/fs.h>
+#include <linux/locks.h>
 #include <linux/bfs_fs.h>
+#include <linux/smp_lock.h>
 #include "bfs_defs.h"
 
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(x...)	printk(x)
+#define dprintf(x...)	printf(x)
 #else
-#define DBG(x...)
+#define dprintf(x...)
 #endif
 
-static ssize_t bfs_file_write(struct file * f, const char * buf, size_t count, loff_t *ppos)
-{
-	return generic_file_write(f, buf, count, ppos, block_write_partial_page);
-}
-
 static struct file_operations bfs_file_operations = {
-	llseek:			NULL,
 	read:			generic_file_read,
-	write:			bfs_file_write,
-	readdir:		NULL,
-	poll:			NULL,
-	ioctl:			NULL,
+	write:			generic_file_write,
 	mmap:			generic_file_mmap,
-	open:			NULL,
-	flush:			NULL,
-	release:		NULL,
-	fsync:			NULL,
-	fasync:			NULL,
 };
 
+static int bfs_move_block(unsigned long from, unsigned long to, kdev_t dev)
+{
+	struct buffer_head *bh, *new = NULL;
+
+	bh = bread(dev, from, BFS_BSIZE);
+	if (!bh)
+		return -EIO;
+	new = getblk(dev, to, BFS_BSIZE);
+	memcpy(new->b_data, bh->b_data, bh->b_size);
+	mark_buffer_dirty(new, 1);
+	bforget(bh);
+	brelse(new);
+	return 0;
+}
+
+static int bfs_move_blocks(kdev_t dev, unsigned long start, unsigned long end, 
+				unsigned long where)
+{
+	unsigned long i;
+
+	dprintf("%08lx-%08lx->%08lx\n", start, end, where);
+	for (i = start; i <= end; i++)
+		if(bfs_move_block(i, where + i, dev)) {
+			dprintf("failed to move block %08lx -> %08lx\n", i, where + i);
+			return -EIO;
+		}
+	return 0;
+}
+
 static int bfs_get_block(struct inode * inode, long block, 
 	struct buffer_head * bh_result, int create)
 {
-	long phys = inode->iu_sblock + block;
-	if (!create || phys <= inode->iu_eblock) {
+	long phys, next_free_block;
+	int err;
+	struct super_block *s = inode->i_sb;
+
+	if (block < 0 || block > s->su_blocks)
+		return -EIO;
+
+	phys = inode->iu_sblock + block;
+	if (!create) {
+		if (phys <= inode->iu_eblock) {
+			dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
+			bh_result->b_dev = inode->i_dev;
+			bh_result->b_blocknr = phys;
+			bh_result->b_state |= (1UL << BH_Mapped);
+		}
+		return 0;
+	}
+
+	/* if the file is not empty and the requested block is within the range
+	   of blocks allocated for this file, we can grant it */
+	if (inode->i_size && phys <= inode->iu_eblock) {
+		dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", create, block, phys);
 		bh_result->b_dev = inode->i_dev;
 		bh_result->b_blocknr = phys;
 		bh_result->b_state |= (1UL << BH_Mapped);
 		return 0;
-	} 
-	/* no support for file migration, working on it */
-	return -EIO;
+	}
+
+	/* the rest has to be protected against itself */
+	lock_kernel();
+
+	/* if the last data block for this file is the last allocated block, we can
+	   extend the file trivially, without moving it anywhere */
+	if (inode->iu_eblock == s->su_lf_eblk) {
+		dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", create, block, phys);
+		bh_result->b_dev = inode->i_dev;
+		bh_result->b_blocknr = phys;
+		bh_result->b_state |= (1UL << BH_Mapped);
+		s->su_lf_eblk = inode->iu_eblock = inode->iu_sblock + block;
+		mark_inode_dirty(inode);
+		mark_buffer_dirty(s->su_sbh, 1);
+		err = 0;
+		goto out;
+	}
+
+	/* Ok, we have to move this entire file to the next free block */
+	next_free_block = s->su_lf_eblk + 1;
+	if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */
+		err = bfs_move_blocks(inode->i_dev, inode->iu_sblock, inode->iu_eblock, next_free_block);
+		if (err) {
+			dprintf("failed to move ino=%08lx -> possible fs corruption\n", inode->i_ino);
+			goto out;
+		}
+	} else
+		err = 0;
+
+	inode->iu_sblock = next_free_block;
+	s->su_lf_eblk = inode->iu_eblock = next_free_block + block;
+	mark_inode_dirty(inode);
+	mark_buffer_dirty(s->su_sbh, 1);
+	bh_result->b_dev = inode->i_dev;
+	bh_result->b_blocknr = inode->iu_sblock + block;
+	bh_result->b_state |= (1UL << BH_Mapped);
+out:
+	unlock_kernel();
+	return err;
+}
+
+static int bfs_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,bfs_get_block);
 }
+static int bfs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,bfs_get_block);
+}
+static int bfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page,from,to,bfs_get_block);
+}
+static int bfs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,bfs_get_block);
+}
+struct address_space_operations bfs_aops = {
+	readpage: bfs_readpage,
+	writepage: bfs_writepage,
+	prepare_write: bfs_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: bfs_bmap
+};
 
 struct inode_operations bfs_file_inops = {
 	default_file_ops:	&bfs_file_operations,
-	create:			NULL,
-	lookup:			NULL,
-	link:			NULL,
-	unlink:			NULL,
-	symlink:		NULL,
-	mkdir:			NULL,
-	rmdir:			NULL,
-	mknod:			NULL,
-	rename:			NULL,
-	readlink:		NULL,
-	follow_link:		NULL,
-	get_block:		bfs_get_block,	
-	readpage:		block_read_full_page,
-	writepage:		block_write_full_page,
-	truncate:		NULL,
-	permission:		NULL,
-	revalidate:		NULL
 };
diff -u --recursive --new-file v2.3.42/linux/fs/bfs/inode.c linux/fs/bfs/inode.c
--- v2.3.42/linux/fs/bfs/inode.c	Thu Nov 11 20:11:49 1999
+++ linux/fs/bfs/inode.c	Thu Feb 10 12:16:58 2000
@@ -5,7 +5,6 @@
  *	From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -18,15 +17,15 @@
 #include "bfs_defs.h"
 
 MODULE_AUTHOR("Tigran A. Aivazian");
-MODULE_DESCRIPTION("UnixWare BFS filesystem for Linux");
+MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
 EXPORT_NO_SYMBOLS;
 
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(x...)	printk(x)
+#define dprintf(x...)	printf(x)
 #else
-#define DBG(x...)
+#define dprintf(x...)
 #endif
 
 void dump_imap(const char *prefix, struct super_block * s);
@@ -40,8 +39,7 @@
 	int block, off;
 
 	if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
-		printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n", 
-			__FUNCTION__, bdevname(dev), ino);
+		printf("Bad inode number %s:%08lx\n", bdevname(dev), ino);
 		make_bad_inode(inode);
 		return;
 	}
@@ -49,8 +47,7 @@
 	block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
 	bh = bread(dev, block, BFS_BSIZE);
 	if (!bh) {
-		printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
-			__FUNCTION__, bdevname(dev), ino);
+		printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
 		make_bad_inode(inode);
 		return;
 	}
@@ -65,6 +62,7 @@
 	} else if (di->i_vtype == BFS_VREG) {
 		inode->i_mode |= S_IFREG;
 		inode->i_op = &bfs_file_inops;
+		inode->i_mapping->a_ops = &bfs_aops;
 	} else 
 		inode->i_op = NULL;
 
@@ -94,16 +92,14 @@
 	int block, off;
 
 	if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
-		printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n", 
-			__FUNCTION__, bdevname(dev), ino);
+		printf("Bad inode number %s:%08lx\n", bdevname(dev), ino);
 		return;
 	}
 
 	block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
 	bh = bread(dev, block, BFS_BSIZE);
 	if (!bh) {
-		printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
-			__FUNCTION__, bdevname(dev), ino);
+		printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
 		return;
 	}
 
@@ -140,30 +136,12 @@
 	int block, off;
 	struct super_block * s = inode->i_sb;
 
-	DBG(KERN_ERR "%s(ino=%08lx)\n", __FUNCTION__, inode->i_ino);
+	dprintf("ino=%08lx\n", inode->i_ino);
 
-	if (!inode)
+	if (!inode || !inode->i_dev || inode->i_count > 1 || inode->i_nlink || !s)
 		return;
-	if (!inode->i_dev) {
-		printk(KERN_ERR "BFS-fs: free_inode(%08lx) !dev\n", inode->i_ino);
-		return;
-	}
-	if (inode->i_count > 1) {
-		printk(KERN_ERR "BFS-fs: free_inode(%08lx) count=%d\n", 
-			inode->i_ino, inode->i_count);
-		return;
-	}
-	if (inode->i_nlink) {
-		printk(KERN_ERR "BFS-fs: free_inode(%08lx) nlink=%d\n", 
-			inode->i_ino, inode->i_nlink);
-		return;
-	}
-	if (!inode->i_sb) {
-		printk(KERN_ERR "BFS-fs: free_inode(%08lx) !sb\n", inode->i_ino);
-		return;
-	}
 	if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > inode->i_sb->su_lasti) {
-		printk(KERN_ERR "BFS-fs: free_inode(%08lx) invalid ino\n", inode->i_ino);
+		printf("invalid ino=%08lx\n", inode->i_ino);
 		return;
 	}
 	
@@ -173,8 +151,7 @@
 	block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
 	bh = bread(dev, block, BFS_BSIZE);
 	if (!bh) {
-		printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
-			__FUNCTION__, bdevname(dev), ino);
+		printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
 		return;
 	}
 	off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
@@ -189,6 +166,14 @@
 	di->i_sblock = 0;
 	mark_buffer_dirty(bh, 1);
 	brelse(bh);
+
+	/* if this was the last file, make the previous 
+	   block "last files last block" even if there is no real file there,
+	   saves us 1 gap */
+	if (s->su_lf_eblk == inode->iu_eblock) {
+		s->su_lf_eblk = inode->iu_sblock - 1;
+		mark_buffer_dirty(s->su_sbh, 1);
+	}
 	clear_inode(inode);
 }
 
@@ -196,7 +181,6 @@
 {
 	brelse(s->su_sbh);
 	kfree(s->su_imap);
-	kfree(s->su_bmap);
 	MOD_DEC_USE_COUNT;
 }
 
@@ -251,7 +235,7 @@
 		else
 			strcat(tmpbuf, "0");
 	}
-	printk(KERN_ERR "BFS-fs: %s: lasti=%d <%s>\n", prefix, s->su_lasti, tmpbuf);
+	printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, s->su_lasti, tmpbuf);
 	free_page((unsigned long)tmpbuf);
 #endif
 }
@@ -263,7 +247,7 @@
 	struct buffer_head * bh;
 	struct bfs_super_block * bfs_sb;
 	struct inode * inode;
-	int i, imap_len, bmap_len;
+	int i, imap_len;
 
 	MOD_INC_USE_COUNT;
 	lock_super(s);
@@ -272,58 +256,43 @@
 	s->s_blocksize = BFS_BSIZE;
 	s->s_blocksize_bits = BFS_BSIZE_BITS;
 
-	/* read ahead 8K to get inodes as we'll need them in a tick */
-	bh = breada(dev, 0, BFS_BSIZE, 0, 8192);
+	bh = bread(dev, 0, BFS_BSIZE);
 	if(!bh)
 		goto out;
 	bfs_sb = (struct bfs_super_block *)bh->b_data;
 	if (bfs_sb->s_magic != BFS_MAGIC) {
 		if (!silent)
-			printk(KERN_ERR "BFS-fs: No BFS filesystem on %s (magic=%08x)\n", 
-					bdevname(dev), bfs_sb->s_magic);
+			printf("No BFS filesystem on %s (magic=%08x)\n", 
+				bdevname(dev), bfs_sb->s_magic);
 		goto out;
 	}
 	if (BFS_UNCLEAN(bfs_sb, s) && !silent)
-		printk(KERN_WARNING "BFS-fs: %s is unclean\n", bdevname(dev));
+		printf("%s is unclean, continuing\n", bdevname(dev));
 
-#ifndef CONFIG_BFS_FS_WRITE
-	s->s_flags |= MS_RDONLY; 
-#endif
 	s->s_magic = BFS_MAGIC;
 	s->su_bfs_sb = bfs_sb;
 	s->su_sbh = bh;
 	s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 
 			+ BFS_ROOT_INO - 1;
 
-	bmap_len = sizeof(struct bfs_bmap) * s->su_lasti;
-	s->su_bmap = kmalloc(bmap_len, GFP_KERNEL);
-	if (!s->su_bmap)
-		goto out;
-	memset(s->su_bmap, 0, bmap_len);
 	imap_len = s->su_lasti/8 + 1;
 	s->su_imap = kmalloc(imap_len, GFP_KERNEL);
-	if (!s->su_imap) {
-		kfree(s->su_bmap);
+	if (!s->su_imap)
 		goto out;
-	}
 	memset(s->su_imap, 0, imap_len);
-	for (i=0; i<BFS_ROOT_INO; i++) {
-		s->su_bmap[i].start = s->su_bmap[i].end = 0;
+	for (i=0; i<BFS_ROOT_INO; i++) 
 		set_bit(i, s->su_imap);
-	}
 
 	s->s_op = &bfs_sops;
 	inode = iget(s, BFS_ROOT_INO);
 	if (!inode) {
 		kfree(s->su_imap);
-		kfree(s->su_bmap);
 		goto out;
 	}
 	s->s_root = d_alloc_root(inode);
 	if (!s->s_root) {
 		iput(inode);
 		kfree(s->su_imap);
-		kfree(s->su_bmap);
 		goto out;
 	}
 
@@ -335,10 +304,9 @@
 	s->su_lf_ioff = 0;
 	for (i=BFS_ROOT_INO; i<=s->su_lasti; i++) {
 		inode = iget(s,i);
-		if (inode->iu_dsk_ino == 0) {
+		if (inode->iu_dsk_ino == 0)
 			s->su_freei++;
-			s->su_bmap[i].start = s->su_bmap[i].end = 0;
-		} else {
+		else {
 			set_bit(i, s->su_imap);
 			s->su_freeb -= inode->i_blocks;
 			if (inode->iu_eblock > s->su_lf_eblk) {
@@ -346,8 +314,6 @@
 				s->su_lf_sblk = inode->iu_sblock;
 				s->su_lf_ioff = BFS_INO2OFF(i);
 			}
-			s->su_bmap[i].start = inode->iu_sblock;
-			s->su_bmap[i].end = inode->iu_eblock;
 		}
 		iput(inode);
 	}
diff -u --recursive --new-file v2.3.42/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.3.42/linux/fs/binfmt_elf.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/binfmt_elf.c	Mon Feb  7 19:45:28 2000
@@ -405,7 +405,7 @@
 	int elf_exec_fileno;
 	int retval, size, i;
 	unsigned long elf_entry, interp_load_addr = 0;
-	unsigned long start_code, end_code, end_data;
+	unsigned long start_code, end_code, start_data, end_data;
 	struct elfhdr elf_ex;
 	struct elfhdr interp_elf_ex;
   	struct exec interp_ex;
@@ -462,6 +462,7 @@
 
 	start_code = ~0UL;
 	end_code = 0;
+	start_data = 0;
 	end_data = 0;
 
 	for (i = 0; i < elf_ex.e_phnum; i++) {
@@ -578,6 +579,7 @@
 		goto out_free_dentry;
 
 	/* OK, This is the point of no return */
+	current->mm->start_data = 0;
 	current->mm->end_data = 0;
 	current->mm->end_code = 0;
 	current->mm->mmap = NULL;
@@ -642,7 +644,10 @@
 		}
 		k = elf_ppnt->p_vaddr;
 		if (k < start_code) start_code = k;
+		if (start_data < k) start_data = k;
+
 		k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
+
 		if (k > elf_bss)
 			elf_bss = k;
 		if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
@@ -661,6 +666,7 @@
 	elf_brk += load_bias;
 	start_code += load_bias;
 	end_code += load_bias;
+	start_data += load_bias;
 	end_data += load_bias;
 
 	if (elf_interpreter) {
@@ -718,6 +724,7 @@
 	current->mm->start_brk = current->mm->brk = elf_brk;
 	current->mm->end_code = end_code;
 	current->mm->start_code = start_code;
+	current->mm->start_data = start_data;
 	current->mm->end_data = end_data;
 	current->mm->start_stack = bprm->p;
 
@@ -732,6 +739,7 @@
 	printk("(start_brk) %lx\n" , (long) current->mm->start_brk);
 	printk("(end_code) %lx\n" , (long) current->mm->end_code);
 	printk("(start_code) %lx\n" , (long) current->mm->start_code);
+	printk("(start_data) %lx\n" , (long) current->mm->start_data);
 	printk("(end_data) %lx\n" , (long) current->mm->end_data);
 	printk("(start_stack) %lx\n" , (long) current->mm->start_stack);
 	printk("(brk) %lx\n" , (long) current->mm->brk);
diff -u --recursive --new-file v2.3.42/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.3.42/linux/fs/block_dev.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/block_dev.c	Wed Feb  9 19:10:14 2000
@@ -70,39 +70,53 @@
 			if (chars != blocksize)
 				fn = bread;
 			bh = fn(dev, block, blocksize);
+			if (!bh)
+				return written ? written : -EIO;
+			if (!buffer_uptodate(bh))
+				wait_on_buffer(bh);
 		}
 #else
 		bh = getblk(dev, block, blocksize);
+		if (!bh)
+			return written ? written : -EIO;
 
-		if (chars != blocksize && !buffer_uptodate(bh)) {
-		  if(!filp->f_reada ||
-		     !read_ahead[MAJOR(dev)]) {
-		    /* We do this to force the read of a single buffer */
-		    brelse(bh);
-		    bh = bread(dev,block,blocksize);
-		  } else {
-		    /* Read-ahead before write */
-		    blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
-		    if (block + blocks > size) blocks = size - block;
-		    if (blocks > NBUF) blocks=NBUF;
+		if (!buffer_uptodate(bh))
+		{
+		  if (chars == blocksize)
+		    wait_on_buffer(bh);
+		  else
+		  {
 		    bhlist[0] = bh;
-		    for(i=1; i<blocks; i++){
-		      bhlist[i] = getblk (dev, block+i, blocksize);
-		      if(!bhlist[i]){
-			while(i >= 0) brelse(bhlist[i--]);
-			return written ? written : -EIO;
-		      };
-		    };
+		    if (!filp->f_reada || !read_ahead[MAJOR(dev)]) {
+		      /* We do this to force the read of a single buffer */
+		      blocks = 1;
+		    } else {
+		      /* Read-ahead before write */
+		      blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
+		      if (block + blocks > size) blocks = size - block;
+		      if (blocks > NBUF) blocks=NBUF;
+		      if (!blocks) blocks = 1;
+		      for(i=1; i<blocks; i++)
+		      {
+		        bhlist[i] = getblk (dev, block+i, blocksize);
+		        if (!bhlist[i])
+			{
+			  while(i >= 0) brelse(bhlist[i--]);
+			  return written ? written : -EIO;
+		        }
+		      }
+		    }
 		    ll_rw_block(READ, blocks, bhlist);
 		    for(i=1; i<blocks; i++) brelse(bhlist[i]);
 		    wait_on_buffer(bh);
-		      
+		    if (!buffer_uptodate(bh)) {
+			  brelse(bh);
+			  return written ? written : -EIO;
+		    }
 		  };
 		};
 #endif
 		block++;
-		if (!bh)
-			return written ? written : -EIO;
 		p = offset + bh->b_data;
 		offset = 0;
 		*ppos += chars;
@@ -522,7 +536,7 @@
 	if (sb && invalidate_inodes(sb))
 		printk("VFS: busy inodes on changed media.\n");
 
-	invalidate_buffers(dev);
+	destroy_buffers(dev);
 
 	if (bdops->revalidate)
 		bdops->revalidate(dev);
diff -u --recursive --new-file v2.3.42/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.42/linux/fs/buffer.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/buffer.c	Thu Feb 10 12:16:58 2000
@@ -94,6 +94,7 @@
 kmem_cache_t *bh_cachep;
 
 static int grow_buffers(int size);
+static void __refile_buffer(struct buffer_head *);
 
 /* This is used by some architectures to estimate available memory. */
 atomic_t buffermem_pages = ATOMIC_INIT(0);
@@ -277,11 +278,14 @@
 
 void sync_dev(kdev_t dev)
 {
-	sync_buffers(dev, 0);
 	sync_supers(dev);
 	sync_inodes(dev);
-	sync_buffers(dev, 0);
 	DQUOT_SYNC(dev);
+	/* sync all the dirty buffers out to disk only _after_ all the
+	   high level layers finished generated buffer dirty data
+	   (or we'll return with some buffer still dirty on the blockdevice
+	   so breaking the semantics of this call) */
+	sync_buffers(dev, 0);
 	/*
 	 * FIXME(eric) we need to sync the physical devices here.
 	 * This is because some (scsi) controllers have huge amounts of
@@ -323,7 +327,9 @@
 	struct inode * inode = dentry->d_inode;
 	struct super_block * sb;
 	kdev_t dev;
+	int ret;
 
+	lock_kernel();
 	/* sync the inode to buffers */
 	write_inode_now(inode);
 
@@ -335,7 +341,9 @@
 
 	/* .. finally sync the buffers to disk */
 	dev = inode->i_dev;
-	return sync_buffers(dev, 1);
+	ret = sync_buffers(dev, 1);
+	unlock_kernel();
+	return ret;
 }
 
 asmlinkage long sys_fsync(unsigned int fd)
@@ -345,7 +353,6 @@
 	struct inode * inode;
 	int err;
 
-	lock_kernel();
 	err = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -371,7 +378,6 @@
 out_putf:
 	fput(file);
 out:
-	unlock_kernel();
 	return err;
 }
 
@@ -382,7 +388,6 @@
 	struct inode * inode;
 	int err;
 
-	lock_kernel();
 	err = -EBADF;
 	file = fget(fd);
 	if (!file)
@@ -408,44 +413,9 @@
 out_putf:
 	fput(file);
 out:
-	unlock_kernel();
 	return err;
 }
 
-void invalidate_buffers(kdev_t dev)
-{
-	int nlist;
-
-	spin_lock(&lru_list_lock);
-	for(nlist = 0; nlist < NR_LIST; nlist++) {
-		struct buffer_head * bh;
-		int i;
-	retry:
-		bh = lru_list[nlist];
-		if (!bh)
-			continue;
-		for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bh->b_next_free) {
-			if (bh->b_dev != dev)
-				continue;
-			if (buffer_locked(bh)) {
-				atomic_inc(&bh->b_count);
-				spin_unlock(&lru_list_lock);
-				wait_on_buffer(bh);
-				spin_lock(&lru_list_lock);
-				atomic_dec(&bh->b_count);
-				goto retry;
-			}
-			if (atomic_read(&bh->b_count))
-				continue;
-			clear_bit(BH_Protected, &bh->b_state);
-			clear_bit(BH_Uptodate, &bh->b_state);
-			clear_bit(BH_Dirty, &bh->b_state);
-			clear_bit(BH_Req, &bh->b_state);
-		}
-	}
-	spin_unlock(&lru_list_lock);
-}
-
 /* After several hours of tedious analysis, the following hash
  * function won.  Do not mess with it... -DaveM
  */
@@ -464,10 +434,12 @@
 
 static __inline__ void __hash_unlink(struct buffer_head *bh)
 {
-	if (bh->b_next)
-		bh->b_next->b_pprev = bh->b_pprev;
-	*(bh->b_pprev) = bh->b_next;
-	bh->b_pprev = NULL;
+	if (bh->b_pprev) {
+		if (bh->b_next)
+			bh->b_next->b_pprev = bh->b_pprev;
+		*(bh->b_pprev) = bh->b_next;
+		bh->b_pprev = NULL;
+	}
 }
 
 static void __insert_into_lru_list(struct buffer_head * bh, int blist)
@@ -514,17 +486,12 @@
 	bh->b_next_free = bh->b_prev_free = NULL;
 }
 
-/* The following two functions must operate atomically
- * because they control the visibility of a buffer head
- * to the rest of the kernel.
- */
-static __inline__ void __remove_from_queues(struct buffer_head *bh)
+/* must be called with both the hash_table_lock and the lru_list_lock
+   held */
+static void __remove_from_queues(struct buffer_head *bh)
 {
-	write_lock(&hash_table_lock);
-	if (bh->b_pprev)
-		__hash_unlink(bh);
+	__hash_unlink(bh);
 	__remove_from_lru_list(bh, bh->b_list);
-	write_unlock(&hash_table_lock);
 }
 
 static void insert_into_queues(struct buffer_head *bh)
@@ -547,6 +514,8 @@
 	struct bh_free_head *head = &free_list[BUFSIZE_INDEX(bh->b_size)];
 	struct buffer_head **bhp = &head->list;
 
+	bh->b_state = 0;
+
 	spin_lock(&head->lock);
 	bh->b_dev = B_FREE;
 	if(!*bhp) {
@@ -604,11 +573,73 @@
 	return 0;
 }
 
+/* If invalidate_buffers() will trash dirty buffers, it means some kind
+   of fs corruption is going on. Trashing dirty data always imply losing
+   information that was supposed to be just stored on the physical layer
+   by the user.
+
+   Thus invalidate_buffers in general usage is not allwowed to trash dirty
+   buffers. For example ioctl(FLSBLKBUF) expects dirty data to be preserved.
+
+   NOTE: In the case where the user removed a removable-media-disk even if
+   there's still dirty data not synced on disk (due a bug in the device driver
+   or due an error of the user), by not destroying the dirty buffers we could
+   generate corruption also on the next media inserted, thus a parameter is
+   necessary to handle this case in the most safe way possible (trying
+   to not corrupt also the new disk inserted with the data belonging to
+   the old now corrupted disk). Also for the ramdisk the natural thing
+   to do in order to release the ramdisk memory is to destroy dirty buffers.
+
+   These are two special cases. Normal usage imply the device driver
+   to issue a sync on the device (without waiting I/O completation) and
+   then an invalidate_buffers call that doesn't trashes dirty buffers. */
+void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
+{
+	int i, nlist, slept;
+	struct buffer_head * bh, * bh_next;
+
+ retry:
+	slept = 0;
+	spin_lock(&lru_list_lock);
+	for(nlist = 0; nlist < NR_LIST; nlist++) {
+		bh = lru_list[nlist];
+		if (!bh)
+			continue;
+		for (i = nr_buffers_type[nlist]; i > 0 ; bh = bh_next, i--) {
+			bh_next = bh->b_next_free;
+			if (bh->b_dev != dev)
+				continue;
+			if (buffer_locked(bh)) {
+				atomic_inc(&bh->b_count);
+				spin_unlock(&lru_list_lock);
+				wait_on_buffer(bh);
+				slept = 1;
+				spin_lock(&lru_list_lock);
+				atomic_dec(&bh->b_count);
+			}
+
+			write_lock(&hash_table_lock);
+			if (!atomic_read(&bh->b_count) &&
+			    (destroy_dirty_buffers || !buffer_dirty(bh))) {
+				__remove_from_queues(bh);
+				put_last_free(bh);
+			}
+			write_unlock(&hash_table_lock);
+			if (slept)
+				goto out;
+		}
+	}
+out:
+	spin_unlock(&lru_list_lock);
+	if (slept)
+		goto retry;
+}
+
 void set_blocksize(kdev_t dev, int size)
 {
 	extern int *blksize_size[];
-	int i, nlist;
-	struct buffer_head * bh, *bhnext;
+	int i, nlist, slept;
+	struct buffer_head * bh, * bh_next;
 
 	if (!blksize_size[MAJOR(dev)])
 		return;
@@ -626,41 +657,53 @@
 	sync_buffers(dev, 2);
 	blksize_size[MAJOR(dev)][MINOR(dev)] = size;
 
-	/* We need to be quite careful how we do this - we are moving entries
-	 * around on the free list, and we can get in a loop if we are not careful.
-	 */
+ retry:
+	slept = 0;
+	spin_lock(&lru_list_lock);
 	for(nlist = 0; nlist < NR_LIST; nlist++) {
-	repeat:
-		spin_lock(&lru_list_lock);
 		bh = lru_list[nlist];
-		for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bhnext) {
-			if(!bh)
-				break;
-
-			bhnext = bh->b_next_free; 
-			if (bh->b_dev != dev)
-				 continue;
-			if (bh->b_size == size)
-				 continue;
+		if (!bh)
+			continue;
+		for (i = nr_buffers_type[nlist]; i > 0 ; bh = bh_next, i--) {
+			bh_next = bh->b_next_free;
+			if (bh->b_dev != dev || bh->b_size == size)
+				continue;
 			if (buffer_locked(bh)) {
 				atomic_inc(&bh->b_count);
 				spin_unlock(&lru_list_lock);
 				wait_on_buffer(bh);
+				slept = 1;
+				spin_lock(&lru_list_lock);
 				atomic_dec(&bh->b_count);
-				goto repeat;
-			}
-			if (bh->b_dev == dev && bh->b_size != size) {
-				clear_bit(BH_Dirty, &bh->b_state);
-				clear_bit(BH_Uptodate, &bh->b_state);
-				clear_bit(BH_Req, &bh->b_state);
 			}
-			if (atomic_read(&bh->b_count) == 0) {
+
+			write_lock(&hash_table_lock);
+			if (!atomic_read(&bh->b_count)) {
+				if (buffer_dirty(bh))
+					printk(KERN_WARNING
+					       "set_blocksize: dev %s buffer_dirty %lu size %hu\n",
+					       kdevname(dev), bh->b_blocknr, bh->b_size);
 				__remove_from_queues(bh);
 				put_last_free(bh);
+			} else {
+				if (atomic_set_buffer_clean(bh))
+					__refile_buffer(bh);
+				clear_bit(BH_Uptodate, &bh->b_state);
+				printk(KERN_WARNING
+				       "set_blocksize: "
+				       "b_count %d, dev %s, block %lu, from %p\n",
+				       atomic_read(&bh->b_count), bdevname(bh->b_dev),
+				       bh->b_blocknr, __builtin_return_address(0));
 			}
+			write_unlock(&hash_table_lock);
+			if (slept)
+				goto out;
 		}
-		spin_unlock(&lru_list_lock);
 	}
+ out:
+	spin_unlock(&lru_list_lock);
+	if (slept)
+		goto retry;
 }
 
 /*
@@ -785,30 +828,31 @@
 		atomic_set(&bh->b_count, 1);
 	}
 	spin_unlock(&free_list[isize].lock);
-	if (!bh)
-		goto refill;
 
-	/* OK, FINALLY we know that this buffer is the only one of its kind,
-	 * we hold a reference (b_count>0), it is unlocked, and it is clean.
+	/*
+	 * OK, FINALLY we know that this buffer is the only one of
+	 * its kind, we hold a reference (b_count>0), it is unlocked,
+	 * and it is clean.
 	 */
-	init_buffer(bh, end_buffer_io_sync, NULL);
-	bh->b_dev = dev;
-	bh->b_blocknr = block;
-	bh->b_state = 1 << BH_Mapped;
+	if (bh) {
+		init_buffer(bh, end_buffer_io_sync, NULL);
+		bh->b_dev = dev;
+		bh->b_blocknr = block;
+		bh->b_state = 1 << BH_Mapped;
 
-	/* Insert the buffer into the regular lists */
-	insert_into_queues(bh);
-	goto out;
+		/* Insert the buffer into the regular lists */
+		insert_into_queues(bh);
+	out:
+		touch_buffer(bh);
+		return bh;
+	}
 
 	/*
 	 * If we block while refilling the free list, somebody may
 	 * create the buffer first ... search the hashes again.
 	 */
-refill:
 	refill_freelist(size);
 	goto repeat;
-out:
-	return bh;
 }
 
 /* -1 -> no need to flush
@@ -820,11 +864,13 @@
 
 	dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
 	tot = nr_free_buffer_pages();
-	hard_dirty_limit = tot * bdf_prm.b_un.nfract / 100;
-	soft_dirty_limit = hard_dirty_limit >> 1;
+	tot -= size_buffers_type[BUF_PROTECTED] >> PAGE_SHIFT;
 
-	if (dirty > soft_dirty_limit)
-	{
+	dirty *= 200;
+	soft_dirty_limit = tot * bdf_prm.b_un.nfract;
+	hard_dirty_limit = soft_dirty_limit * 2;
+
+	if (dirty > soft_dirty_limit) {
 		if (dirty > hard_dirty_limit)
 			return 1;
 		return 0;
@@ -848,29 +894,39 @@
 	wakeup_bdflush(state);
 }
 
-static inline void __mark_dirty(struct buffer_head *bh, int flag)
+static __inline__ void __mark_dirty(struct buffer_head *bh, int flag)
 {
 	bh->b_flushtime = jiffies + (flag ? bdf_prm.b_un.age_super : bdf_prm.b_un.age_buffer);
-	clear_bit(BH_New, &bh->b_state);
 	refile_buffer(bh);
 }
 
+/* atomic version, the user must call balance_dirty() by hand
+   as soon as it become possible to block */
 void __mark_buffer_dirty(struct buffer_head *bh, int flag)
 {
-	__mark_dirty(bh, flag);
+	if (!atomic_set_buffer_dirty(bh))
+		__mark_dirty(bh, flag);
+}
+
+void mark_buffer_dirty(struct buffer_head *bh, int flag)
+{
+	__mark_buffer_dirty(bh, flag);
+	balance_dirty(bh->b_dev);
 }
 
 /*
  * A buffer may need to be moved from one buffer list to another
  * (e.g. in case it is not shared any more). Handle this.
  */
-static __inline__ void __refile_buffer(struct buffer_head *bh)
+static void __refile_buffer(struct buffer_head *bh)
 {
 	int dispose = BUF_CLEAN;
 	if (buffer_locked(bh))
 		dispose = BUF_LOCKED;
 	if (buffer_dirty(bh))
 		dispose = BUF_DIRTY;
+	if (buffer_protected(bh))
+		dispose = BUF_PROTECTED;
 	if (dispose != bh->b_list) {
 		__remove_from_lru_list(bh, bh->b_list);
 		bh->b_list = dispose;
@@ -890,8 +946,6 @@
  */
 void __brelse(struct buffer_head * buf)
 {
-	touch_buffer(buf);
-
 	if (atomic_read(&buf->b_count)) {
 		atomic_dec(&buf->b_count);
 		return;
@@ -912,12 +966,10 @@
 	write_lock(&hash_table_lock);
 	if (!atomic_dec_and_test(&buf->b_count) || buffer_locked(buf))
 		goto in_use;
-	if (buf->b_pprev)
-		__hash_unlink(buf);
+	__hash_unlink(buf);
 	write_unlock(&hash_table_lock);
 	__remove_from_lru_list(buf, buf->b_list);
 	spin_unlock(&lru_list_lock);
-	buf->b_state = 0;
 	put_last_free(buf);
 	return;
 
@@ -1218,13 +1270,13 @@
 
 static void unmap_buffer(struct buffer_head * bh)
 {
-	if (buffer_mapped(bh))
-	{
+	if (buffer_mapped(bh)) {
 		mark_buffer_clean(bh);
 		wait_on_buffer(bh);
 		clear_bit(BH_Uptodate, &bh->b_state);
 		clear_bit(BH_Mapped, &bh->b_state);
 		clear_bit(BH_Req, &bh->b_state);
+		clear_bit(BH_New, &bh->b_state);
 	}
 }
 
@@ -1303,30 +1355,25 @@
 
 static void unmap_underlying_metadata(struct buffer_head * bh)
 {
-#if 0
-	if (buffer_new(bh)) {
-		struct buffer_head *old_bh;
+	struct buffer_head *old_bh;
 
-		old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
-		if (old_bh) {
-			unmap_buffer(old_bh);
-			/* Here we could run brelse or bforget. We use
-			   bforget because it will try to put the buffer
-			   in the freelist. */
-			__bforget(old_bh);
-		}
+	old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
+	if (old_bh) {
+		unmap_buffer(old_bh);
+		/* Here we could run brelse or bforget. We use
+		   bforget because it will try to put the buffer
+		   in the freelist. */
+		__bforget(old_bh);
 	}
-#endif
 }
 
 /*
  * block_write_full_page() is SMP-safe - currently it's still
  * being called with the kernel lock held, but the code is ready.
  */
-int block_write_full_page(struct dentry *dentry, struct page *page)
+static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block)
 {
-	struct inode *inode = dentry->d_inode;
-	int err, i;
+	int err, i, need_balance_dirty = 0;
 	unsigned long block;
 	struct buffer_head *bh, *head;
 
@@ -1337,17 +1384,11 @@
 		create_empty_buffers(page, inode, inode->i_sb->s_blocksize);
 	head = page->buffers;
 
-	/* The page cache is now PAGE_CACHE_SIZE aligned, period.  We handle old a.out
-	 * and others via unaligned private mappings.
-	 */
 	block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 
 	bh = head;
 	i = 0;
 	do {
-		if (!bh)
-			BUG();
-
 		/*
 		 * If the buffer isn't up-to-date, we can't be sure
 		 * that the buffer has been initialized with the proper
@@ -1358,18 +1399,25 @@
 		 */
 		bh->b_end_io = end_buffer_io_sync;
 		if (!buffer_mapped(bh)) {
-			err = inode->i_op->get_block(inode, block, bh, 1);
+			err = get_block(inode, block, bh, 1);
 			if (err)
 				goto out;
-			unmap_underlying_metadata(bh);
+			if (buffer_new(bh))
+				unmap_underlying_metadata(bh);
 		}
 		set_bit(BH_Uptodate, &bh->b_state);
-		mark_buffer_dirty(bh,0);
+		if (!atomic_set_buffer_dirty(bh)) {
+			__mark_dirty(bh, 0);
+			need_balance_dirty = 1;
+		}
 
 		bh = bh->b_this_page;
 		block++;
 	} while (bh != head);
 
+	if (need_balance_dirty)
+		balance_dirty(bh->b_dev);
+
 	SetPageUptodate(page);
 	return 0;
 out:
@@ -1377,13 +1425,12 @@
 	return err;
 }
 
-int block_write_zero_range(struct inode *inode, struct page *page,
-		unsigned zerofrom, unsigned from, unsigned to,
-		const char * buf)
+static int __block_prepare_write(struct inode *inode, struct page *page,
+		unsigned from, unsigned to, get_block_t *get_block)
 {
-	unsigned zeroto = 0, block_start, block_end;
+	unsigned block_start, block_end;
 	unsigned long block;
-	int err = 0, partial = 0, need_balance_dirty = 0;
+	int err = 0;
 	unsigned blocksize, bbits;
 	struct buffer_head *bh, *head, *wait[2], **wait_bh=wait;
 	char *kaddr = (char *)kmap(page);
@@ -1396,35 +1443,31 @@
 	bbits = inode->i_sb->s_blocksize_bits;
 	block = page->index << (PAGE_CACHE_SHIFT - bbits);
 
-	/*
-	 * First pass - map what needs to be mapped, initiate reads
-	 * on the boundaries if needed (i.e. if block is partially covered
-	 * _and_ is not up-to-date _and_ is not new).
-	 */
 	for(bh = head, block_start = 0; bh != head || !block_start;
 	    block++, block_start=block_end, bh = bh->b_this_page) {
 		if (!bh)
 			BUG();
 		block_end = block_start+blocksize;
-		if (block_end <= zerofrom)
+		if (block_end <= from)
 			continue;
 		if (block_start >= to)
 			break;
 		bh->b_end_io = end_buffer_io_sync;
 		if (!buffer_mapped(bh)) {
-			err = inode->i_op->get_block(inode, block, bh, 1);
+			err = get_block(inode, block, bh, 1);
 			if (err)
 				goto out;
-			unmap_underlying_metadata(bh);
-		}
-		if (buffer_new(bh)) {
-			zeroto = block_end;
-			if (block_start < zerofrom)
-				zerofrom = block_start;
-			continue;
+			if (buffer_new(bh)) {
+				unmap_underlying_metadata(bh);
+				if (block_end > to)
+					memset(kaddr+to, 0, block_end-to);
+				if (block_start < from)
+					memset(kaddr+block_start, 0, from-block_start);
+				continue;
+			}
 		}
 		if (!buffer_uptodate(bh) &&
-		     (block_start < zerofrom || block_end > to)) {
+		     (block_start < from || block_end > to)) {
 			ll_rw_block(READ, 1, &bh);
 			*wait_bh++=bh;
 		}
@@ -1438,44 +1481,31 @@
 		if (!buffer_uptodate(*wait_bh))
 			goto out;
 	}
-	/*
-	 * Now we can copy the data.
-	 */
-	if (zerofrom < from)
-		memset(kaddr+zerofrom, 0, from-zerofrom);
-	if (from < to)
-		err = copy_from_user(kaddr+from, buf, to-from);
-	if (to < zeroto)
-		memset(kaddr+to, 0, zeroto-to);
-	else
-		zeroto = to;
-	if (err < 0)
-		goto out;
-	/*
-	 * Second pass: check if all out-of-range blocks are up-to-date
-	 * and mark the rest up-to-date and dirty.
-	 *
-	 * NOTE! This also does a direct dirty balace check,
-	 * rather than relying on bdflush just waking up every
-	 * once in a while. This is to catch (and slow down)
-	 * the processes that write tons of buffer..
-	 *
-	 * Note how we do NOT want to do this in the full block
-	 * case: full pages are flushed not by the people who
-	 * dirtied them, but by people who need memory. And we
-	 * should not penalize them for somebody else writing
-	 * lots of dirty pages.
-	 */
-	for(bh = head, block_start = 0;
+	return 0;
+out:
+	return err;
+}
+
+static int __block_commit_write(struct inode *inode, struct page *page,
+		unsigned from, unsigned to)
+{
+	unsigned block_start, block_end;
+	int partial = 0, need_balance_dirty = 0;
+	unsigned blocksize;
+	struct buffer_head *bh, *head;
+
+	blocksize = inode->i_sb->s_blocksize;
+
+	for(bh = head = page->buffers, block_start = 0;
 	    bh != head || !block_start;
 	    block_start=block_end, bh = bh->b_this_page) {
 		block_end = block_start + blocksize;
-		if (block_end <= zerofrom || block_start >= zeroto) {
+		if (block_end <= from || block_start >= to) {
 			if (!buffer_uptodate(bh))
 				partial = 1;
 		} else {
 			set_bit(BH_Uptodate, &bh->b_state);
-			if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
+			if (!atomic_set_buffer_dirty(bh)) {
 				__mark_dirty(bh, 0);
 				need_balance_dirty = 1;
 			}
@@ -1492,51 +1522,202 @@
 	 */
 	if (!partial)
 		SetPageUptodate(page);
-	kunmap(page);
 	return 0;
-out:
-	ClearPageUptodate(page);
-	kunmap(page);
-	return err;
 }
 
-int block_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+/*
+ * Generic "read page" function for block devices that have the normal
+ * get_block functionality. This is most of the block device filesystems.
+ * Reads the page asynchronously --- the unlock_buffer() and
+ * mark_buffer_uptodate() functions propagate buffer state into the
+ * page struct once IO has completed.
+ */
+static inline int __block_read_full_page(struct inode *inode, struct page *page,
+		get_block_t *get_block)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	int err;
+	unsigned long iblock;
+	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
+	unsigned int blocksize, blocks;
+	unsigned long kaddr = 0;
+	int nr, i;
 
 	if (!PageLocked(page))
-		BUG();
-	if (offset < 0 || offset >= PAGE_SIZE)
-		BUG();
-	if (bytes+offset < 0 || bytes+offset > PAGE_SIZE)
-		BUG();
+		PAGE_BUG(page);
+	blocksize = inode->i_sb->s_blocksize;
+	if (!page->buffers)
+		create_empty_buffers(page, inode, blocksize);
+	head = page->buffers;
+
+	blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
+	iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+	bh = head;
+	nr = 0;
+	i = 0;
+
+	do {
+		if (buffer_uptodate(bh))
+			continue;
+
+		if (!buffer_mapped(bh)) {
+			get_block(inode, iblock, bh, 0);
+			if (!buffer_mapped(bh)) {
+				if (!kaddr)
+					kaddr = kmap(page);
+				memset((char *)(kaddr + i*blocksize), 0, blocksize);
+				set_bit(BH_Uptodate, &bh->b_state);
+				continue;
+			}
+		}
 
-	err = block_write_range(inode, page, offset, bytes, buf);
-	return err ? err : bytes;
+		init_buffer(bh, end_buffer_io_async, NULL);
+		atomic_inc(&bh->b_count);
+		arr[nr] = bh;
+		nr++;
+	} while (i++, iblock++, (bh = bh->b_this_page) != head);
+
+	++current->maj_flt;
+	if (nr) {
+		if (Page_Uptodate(page))
+			BUG();
+		ll_rw_block(READ, nr, arr);
+	} else {
+		/*
+		 * all buffers are uptodate - we can set the page
+		 * uptodate as well.
+		 */
+		SetPageUptodate(page);
+		UnlockPage(page);
+	}
+	if (kaddr)
+		kunmap(page);
+	return 0;
 }
 
 /*
  * For moronic filesystems that do not allow holes in file.
- * we allow offset==PAGE_SIZE, bytes==0
+ * We may have to extend the file.
  */
 
-int block_write_cont_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+int cont_prepare_write(struct page *page, unsigned offset, unsigned to, get_block_t *get_block, unsigned long *bytes)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	int err;
-	unsigned zerofrom = offset;
+	struct address_space *mapping = page->mapping;
+	struct inode *inode = (struct inode*)mapping->host;
+	struct page *new_page;
+	unsigned long pgpos;
+	long status;
+	unsigned zerofrom;
+	unsigned blocksize = inode->i_sb->s_blocksize;
+	char *kaddr;
+
+	while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) {
+		status = -ENOMEM;
+		new_page = grab_cache_page(mapping, pgpos);
+		if (!new_page)
+			goto out;
+		/* we might sleep */
+		if (*bytes>>PAGE_CACHE_SHIFT != pgpos) {
+			UnlockPage(new_page);
+			page_cache_release(new_page);
+			continue;
+		}
+		zerofrom = *bytes & ~PAGE_CACHE_MASK;
+		if (zerofrom & (blocksize-1)) {
+			*bytes |= (blocksize-1);
+			(*bytes)++;
+		}
+		status = __block_prepare_write(inode, new_page, zerofrom,
+						PAGE_CACHE_SIZE, get_block);
+		if (status)
+			goto out_unmap;
+		kaddr = (char*)page_address(page);
+		memset(kaddr+zerofrom, 0, PAGE_CACHE_SIZE-zerofrom);
+		__block_commit_write(inode, new_page, zerofrom, to);
+		kunmap(new_page);
+		UnlockPage(new_page);
+		page_cache_release(new_page);
+	}
+
+	if (page->index < pgpos) {
+		/* completely inside the area */
+		zerofrom = offset;
+	} else {
+		/* page covers the boundary, find the boundary offset */
+		zerofrom = *bytes & ~PAGE_CACHE_MASK;
 
-	if (page->index > (inode->i_size >> PAGE_CACHE_SHIFT))
-		zerofrom = 0;
-	else if (page->index == (inode->i_size >> PAGE_CACHE_SHIFT) &&
-		 offset > (inode->i_size & ~PAGE_CACHE_MASK))
-		zerofrom = inode->i_size & ~PAGE_CACHE_MASK;
-	err = block_write_zero_range(inode, page, zerofrom,offset,offset+bytes,
-					buf);
-	return err ? err : bytes;
+		/* if we will expand the thing last block will be filled */
+		if (to > zerofrom && (zerofrom & (blocksize-1))) {
+			*bytes |= (blocksize-1);
+			(*bytes)++;
+		}
+
+		/* starting below the boundary? Nothing to zero out */
+		if (offset <= zerofrom)
+			zerofrom = offset;
+	}
+	status = __block_prepare_write(inode, page, zerofrom, to, get_block);
+	if (status)
+		goto out1;
+	kaddr = (char*)page_address(page);
+	if (zerofrom < offset) {
+		memset(kaddr+zerofrom, 0, offset-zerofrom);
+		__block_commit_write(inode, page, zerofrom, offset);
+	}
+	return 0;
+out1:
+	ClearPageUptodate(page);
+	kunmap(page);
+	return status;
+
+out_unmap:
+	ClearPageUptodate(new_page);
+	kunmap(new_page);
+	UnlockPage(new_page);
+	page_cache_release(new_page);
+out:
+	return status;
 }
 
+int block_prepare_write(struct page *page, unsigned from, unsigned to,
+			get_block_t *get_block)
+{
+	struct inode *inode = (struct inode*)page->mapping->host;
+	int err = __block_prepare_write(inode, page, from, to, get_block);
+	if (err) {
+		ClearPageUptodate(page);
+		kunmap(page);
+	}
+	return err;
+}
+
+int generic_commit_write(struct file *file, struct page *page,
+		unsigned from, unsigned to)
+{
+	__block_commit_write((struct inode*)page->mapping->host,page,from,to);
+	kunmap(page);
+	return 0;
+}
+
+int block_write_full_page(struct page *page, get_block_t *get_block)
+{
+	struct inode *inode = (struct inode*)page->mapping->host;
+	return __block_write_full_page(inode, page, get_block);
+}
+
+int block_read_full_page(struct page *page, get_block_t *get_block)
+{
+	struct inode *inode = (struct inode*)page->mapping->host;
+	return __block_read_full_page(inode, page, get_block);
+}
+
+int generic_block_bmap(struct address_space *mapping, long block, get_block_t *get_block)
+{
+	struct buffer_head tmp;
+	struct inode *inode = (struct inode*)mapping->host;
+	tmp.b_state = 0;
+	tmp.b_blocknr = 0;
+	get_block(inode, block, &tmp, 0);
+	return tmp.b_blocknr;
+}
 
 /*
  * IO completion routine for a buffer_head being used for kiobuf IO: we
@@ -1814,93 +1995,22 @@
 	return 0;
 }
 
-/*
- * Generic "read page" function for block devices that have the normal
- * get_block functionality. This is most of the block device filesystems.
- * Reads the page asynchronously --- the unlock_buffer() and
- * mark_buffer_uptodate() functions propagate buffer state into the
- * page struct once IO has completed.
- */
-static inline int __block_read_full_page(struct inode *inode, struct page *page)
-{
-	unsigned long iblock;
-	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
-	unsigned int blocksize, blocks;
-	unsigned long kaddr = 0;
-	int nr, i;
-
-	if (!PageLocked(page))
-		PAGE_BUG(page);
-	blocksize = inode->i_sb->s_blocksize;
-	if (!page->buffers)
-		create_empty_buffers(page, inode, blocksize);
-	head = page->buffers;
-
-	blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
-	iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
-	bh = head;
-	nr = 0;
-	i = 0;
-
-	do {
-		if (buffer_uptodate(bh))
-			continue;
-
-		if (!buffer_mapped(bh)) {
-			inode->i_op->get_block(inode, iblock, bh, 0);
-			if (!buffer_mapped(bh)) {
-				if (!kaddr)
-					kaddr = kmap(page);
-				memset((char *)(kaddr + i*blocksize), 0, blocksize);
-				set_bit(BH_Uptodate, &bh->b_state);
-				continue;
-			}
-		}
-
-		init_buffer(bh, end_buffer_io_async, NULL);
-		atomic_inc(&bh->b_count);
-		arr[nr] = bh;
-		nr++;
-	} while (i++, iblock++, (bh = bh->b_this_page) != head);
-
-	++current->maj_flt;
-	if (nr) {
-		if (Page_Uptodate(page))
-			BUG();
-		ll_rw_block(READ, nr, arr);
-	} else {
-		/*
-		 * all buffers are uptodate - we can set the page
-		 * uptodate as well.
-		 */
-		SetPageUptodate(page);
-		UnlockPage(page);
-	}
-	if (kaddr)
-		kunmap(page);
-	return 0;
-}
-
-int block_read_full_page(struct dentry *dentry, struct page *page)
-{
-	return __block_read_full_page(dentry->d_inode, page);
-}
-
 int block_symlink(struct inode *inode, const char *symname, int len)
 {
-	struct page *page = grab_cache_page(&inode->i_data, 0);
-	mm_segment_t fs;
+	struct address_space *mapping = inode->i_mapping;
+	struct page *page = grab_cache_page(mapping, 0);
 	int err = -ENOMEM;
+	char *kaddr;
 
 	if (!page)
 		goto fail;
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = block_write_range(inode, page, 0, len-1, symname);
-	set_fs(fs);
-	inode->i_size = len-1;
+	err = mapping->a_ops->prepare_write(page, 0, len-1);
 	if (err)
-		goto fail_write;
+		goto fail_map;
+	kaddr = (char*)page_address(page);
+	memcpy(kaddr, symname, len-1);
+	mapping->a_ops->commit_write(NULL, page, 0, len-1);
+	inode->i_size = len-1;
 	/*
 	 * Notice that we are _not_ going to block here - end of page is
 	 * unmapped, so this will only try to map the rest of page, see
@@ -1908,14 +2018,15 @@
 	 * ->i_size will be enough for everything) and zero it out.
 	 * OTOH it's obviously correct and should make the page up-to-date.
 	 */
-	err = __block_read_full_page(inode, page);
+	err = mapping->a_ops->readpage(NULL, page);
 	wait_on_page(page);
 	page_cache_release(page);
 	if (err < 0)
 		goto fail;
 	mark_inode_dirty(inode);
 	return 0;
-fail_write:
+fail_map:
+	inode->i_size = len-1;
 	UnlockPage(page);
 	page_cache_release(page);
 fail:
@@ -2000,7 +2111,7 @@
  */
 int try_to_free_buffers(struct page * page)
 {
-	struct buffer_head * tmp, * bh = page->buffers;
+	struct buffer_head * tmp, * p, * bh = page->buffers;
 	int index = BUFSIZE_INDEX(bh->b_size);
 	int ret;
 
@@ -2009,7 +2120,7 @@
 	spin_lock(&free_list[index].lock);
 	tmp = bh;
 	do {
-		struct buffer_head * p = tmp;
+		p = tmp;
 
 		tmp = tmp->b_this_page;
 		if (buffer_busy(p))
@@ -2025,13 +2136,10 @@
 		/* The buffer can be either on the regular
 		 * queues or on the free list..
 		 */
-		if (p->b_dev == B_FREE) {
+		if (p->b_dev != B_FREE)
+			__remove_from_queues(p);
+		else
 			__remove_from_free_list(p, index);
-		} else {
-			if (p->b_pprev)
-				__hash_unlink(p);
-			__remove_from_lru_list(p, p->b_list);
-		}
 		__put_unused_buffer_head(p);
 	} while (tmp != bh);
 	spin_unlock(&unused_list_lock);
@@ -2051,7 +2159,8 @@
 
 busy_buffer_page:
 	/* Uhhuh, start writeback so that we don't end up with all dirty pages */
-	wakeup_bdflush(0);
+	if (buffer_dirty(p))
+		wakeup_bdflush(0);
 	ret = 0;
 	goto out;
 }
@@ -2065,7 +2174,7 @@
 	int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
 	int protected = 0;
 	int nlist;
-	static char *buf_types[NR_LIST] = { "CLEAN", "LOCKED", "DIRTY" };
+	static char *buf_types[NR_LIST] = { "CLEAN", "LOCKED", "DIRTY", "PROTECTED", };
 #endif
 
 	printk("Buffer memory:   %6dkB\n",
@@ -2091,10 +2200,16 @@
 				used++, lastused = found;
 			bh = bh->b_next_free;
 		} while (bh != lru_list[nlist]);
-		printk("%8s: %d buffers, %d used (last=%d), "
+		{
+			int tmp = nr_buffers_type[nlist];
+			if (found != tmp)
+				printk("%9s: BUG -> found %d, reported %d\n",
+				       buf_types[nlist], found, tmp);
+		}
+		printk("%9s: %d buffers, %lu kbyte, %d used (last=%d), "
 		       "%d locked, %d protected, %d dirty\n",
-		       buf_types[nlist], found, used, lastused,
-		       locked, protected, dirty);
+		       buf_types[nlist], found, size_buffers_type[nlist]>>10,
+		       used, lastused, locked, protected, dirty);
 	}
 	spin_unlock(&lru_list_lock);
 #endif
@@ -2184,8 +2299,7 @@
 	if (current == bdflush_tsk)
 		return;
 
-	if (!block)
-	{
+	if (!block) {
 		wake_up_process(bdflush_tsk);
 		return;
 	}
@@ -2210,7 +2324,7 @@
    as all dirty buffers lives _only_ in the DIRTY lru list.
    As we never browse the LOCKED and CLEAN lru lists they are infact
    completly useless. */
-static void flush_dirty_buffers(int check_flushtime)
+static int flush_dirty_buffers(int check_flushtime)
 {
 	struct buffer_head * bh, *next;
 	int flushed = 0, i;
@@ -2220,29 +2334,24 @@
 	bh = lru_list[BUF_DIRTY];
 	if (!bh)
 		goto out_unlock;
-	for (i = nr_buffers_type[BUF_DIRTY]; i-- > 0; bh = next)
-	{
+	for (i = nr_buffers_type[BUF_DIRTY]; i-- > 0; bh = next) {
 		next = bh->b_next_free;
 
-		if (!buffer_dirty(bh))
-		{
+		if (!buffer_dirty(bh)) {
 			__refile_buffer(bh);
 			continue;
 		}
 		if (buffer_locked(bh))
 			continue;
 
-		if (check_flushtime)
-		{
-			/* The dirty lru list is chronogical ordered so
+		if (check_flushtime) {
+			/* The dirty lru list is chronologically ordered so
 			   if the current bh is not yet timed out,
 			   then also all the following bhs
 			   will be too young. */
 			if (time_before(jiffies, bh->b_flushtime))
 				goto out_unlock;
-		}
-		else
-		{
+		} else {
 			if (++flushed > bdf_prm.b_un.ndirty)
 				goto out_unlock;
 		}
@@ -2259,6 +2368,8 @@
 	}
  out_unlock:
 	spin_unlock(&lru_list_lock);
+
+	return flushed;
 }
 
 /* 
@@ -2342,6 +2453,7 @@
  */
 int bdflush(void * unused) 
 {
+	int flushed;
 	/*
 	 *	We have a bare-bones task_struct, and really should fill
 	 *	in a few more things so "top" and /proc/2/{exe,root,cwd}
@@ -2363,7 +2475,7 @@
 	for (;;) {
 		CHECK_EMERGENCY_SYNC
 
-		flush_dirty_buffers(0);
+		flushed = flush_dirty_buffers(0);
 
 		/* If wakeup_bdflush will wakeup us
 		   after our bdflush_done wakeup, then
@@ -2378,10 +2490,10 @@
 		/*
 		 * If there are still a lot of dirty buffers around,
 		 * skip the sleep and flush some more. Otherwise, we
-		 * sleep for a while.
+		 * go to sleep waiting a wakeup.
 		 */
-		if (balance_dirty_state(NODEV) < 0)
-			schedule_timeout(5*HZ);
+		if (!flushed || balance_dirty_state(NODEV) < 0)
+			schedule();
 		/* Remember to mark us as running otherwise
 		   the next schedule will block. */
 		__set_current_state(TASK_RUNNING);
@@ -2413,24 +2525,19 @@
 	for (;;) {
 		/* update interval */
 		interval = bdf_prm.b_un.interval;
-		if (interval)
-		{
+		if (interval) {
 			tsk->state = TASK_INTERRUPTIBLE;
 			schedule_timeout(interval);
-		}
-		else
-		{
+		} else {
 		stop_kupdate:
 			tsk->state = TASK_STOPPED;
 			schedule(); /* wait for SIGCONT */
 		}
 		/* check for sigstop */
-		if (signal_pending(tsk))
-		{
+		if (signal_pending(tsk)) {
 			int stopped = 0;
 			spin_lock_irq(&tsk->sigmask_lock);
-			if (sigismember(&tsk->signal, SIGSTOP))
-			{
+			if (sigismember(&tsk->signal, SIGSTOP)) {
 				sigdelset(&tsk->signal, SIGSTOP);
 				stopped = 1;
 			}
diff -u --recursive --new-file v2.3.42/linux/fs/coda/cnode.c linux/fs/coda/cnode.c
--- v2.3.42/linux/fs/coda/cnode.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/coda/cnode.c	Thu Feb 10 12:16:58 2000
@@ -39,12 +39,62 @@
                 inode->i_op = &coda_file_inode_operations;
         else if (S_ISDIR(inode->i_mode))
                 inode->i_op = &coda_dir_inode_operations;
-        else if (S_ISLNK(inode->i_mode))
-                inode->i_op = &coda_symlink_inode_operations;
-        else
+        else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_data.a_ops = &coda_symlink_aops;
+	} else
                 init_special_inode(inode, inode->i_mode, attr->va_rdev);
 }
 
+struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
+			 struct coda_vattr * attr)
+{
+	struct inode *inode;
+	struct coda_sb_info *sbi= coda_sbp(sb);
+	struct coda_inode_info *cii;
+	ino_t ino = attr->va_fileid;
+
+	inode = iget(sb, ino);
+	if ( !inode ) { 
+		CDEBUG(D_CNODE, "coda_iget: no inode\n");
+		return NULL;
+	}
+
+	/* check if the inode is already initialized */
+	cii = ITOC(inode);
+	if (cii->c_magic == CODA_CNODE_MAGIC)
+		goto out;
+
+	/* Initialize the Coda inode info structure */
+	memset(cii, 0, (int) sizeof(struct coda_inode_info));
+	cii->c_magic = CODA_CNODE_MAGIC;
+	cii->c_fid   = *fid;
+	cii->c_flags = 0;
+	cii->c_vnode = inode;
+	INIT_LIST_HEAD(&(cii->c_cnhead));
+	INIT_LIST_HEAD(&(cii->c_volrootlist));
+
+	coda_fill_inode(inode, attr);
+
+	/* check if it is a weird fid (hashed fid != ino), f.i mountpoints
+	   repair object, expanded local-global conflict trees, etc.
+	 */
+	if ( coda_f2i(fid) == ino )
+		goto out;
+
+	/* check if we expect this weird fid */
+	if ( !coda_fid_is_weird(fid) )
+		printk("Coda: unknown weird fid: ino %ld, fid %s."
+		       "Tell Peter.\n", (long)ino, coda_f2s(&cii->c_fid));
+
+	/* add the inode to a global list so we can find it back later */
+	list_add(&cii->c_volrootlist, &sbi->sbi_volroothead);
+	CDEBUG(D_CNODE, "Added %ld, %s to volroothead\n",
+	       (long)ino, coda_f2s(&cii->c_fid));
+out:
+	return inode;
+}
+
 /* this is effectively coda_iget:
    - get attributes (might be cached)
    - get the inode for the fid using vfs iget
@@ -54,16 +104,12 @@
 int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
 {
         struct coda_inode_info *cnp;
-	struct coda_sb_info *sbi= coda_sbp(sb);
         struct coda_vattr attr;
         int error;
-	ino_t ino;
         
         ENTRY;
 
-        /* 
-	 * We get inode numbers from Venus -- see venus source
-	 */
+	/* We get inode numbers from Venus -- see venus source */
 
 	error = venus_getattr(sb, fid, &attr);
 	if ( error ) {
@@ -74,53 +120,29 @@
 	    return error;
 	} 
 
-	ino = attr.va_fileid;
-        *inode = iget(sb, ino);
-        if ( !*inode ) {
-                printk("coda_cnode_make: iget failed\n");
+	*inode = coda_iget(sb, fid, &attr);
+	if ( !(*inode) ) {
+		printk("coda_cnode_make: coda_iget failed\n");
                 return -ENOMEM;
         }
 
 	cnp = ITOC(*inode);
-	/* see if we've got it already */
-	if  ( cnp->c_magic != 0 && coda_fideq(fid, &cnp->c_fid)) {
+	/* see if it is the right one (we might have an inode collision) */
+	if  ( coda_fideq(fid, &cnp->c_fid) ) {
+		CDEBUG(D_DOWNCALL,
+		       "Done making inode: ino %ld, count %d with %s\n",
+		       (*inode)->i_ino, (*inode)->i_count, 
+		       coda_f2s(&cnp->c_fid));
+		EXIT;
 		return 0;
 	}
 
-	/* not fresh: collision */
-	if  ( cnp->c_magic != 0 ) {
-               printk("coda_cnode_make on initialized inode %ld, old %s new
-%s!\n",
+	/* collision */
+	printk("coda_cnode_make on initialized inode %ld, old %s new %s!\n",
                       (*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid));
                iput(*inode);
-               return -ENOENT;
-        }
- 
-       memset(cnp, 0, (int) sizeof(struct coda_inode_info));
-       cnp->c_fid = *fid;
-       cnp->c_magic = CODA_CNODE_MAGIC;
-       cnp->c_flags = 0;
-       cnp->c_vnode = *inode;
-       INIT_LIST_HEAD(&(cnp->c_cnhead));
-       INIT_LIST_HEAD(&(cnp->c_volrootlist));
-
-	/* fill in the inode attributes */
-	if ( coda_f2i(fid) != ino ) {
-	        if ( !coda_fid_is_weird(fid) ) 
-		        printk("Coda: unknown weird fid: ino %ld, fid %s."
-			       "Tell Peter.\n", (long)ino, coda_f2s(&cnp->c_fid));
-		list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
-		CDEBUG(D_UPCALL, "Added %ld ,%s to volroothead\n",
-		       (long)ino, coda_f2s(&cnp->c_fid));
-	}
-
-        coda_fill_inode(*inode, &attr);
-	CDEBUG(D_DOWNCALL, "Done making inode: ino %ld,  count %d with %s\n",
-	        (*inode)->i_ino, (*inode)->i_count, 
-	       coda_f2s(&cnp->c_fid));
-
         EXIT;
-        return 0;
+	return -ENOENT;
 }
 
 
@@ -183,11 +205,13 @@
 			       coda_f2s(&cii->c_fid), cii->c_vnode->i_ino);
 			if ( coda_fideq(&cii->c_fid, fid) ) {
 				inode = cii->c_vnode;
-				CDEBUG(D_INODE, "volume root, found %ld\n", cii->c_vnode->i_ino);
+				CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino);
 				if ( cii->c_magic != CODA_CNODE_MAGIC )
 					printk("%s: Bad magic in inode, tell Peter.\n", 
 					       __FUNCTION__);
-				return cii->c_vnode;
+
+				iget(sb, inode->i_ino);
+				return inode;
 			}
 			
 		}
@@ -224,7 +248,6 @@
 	}
 
 	CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
-	iput(inode);	
 	return inode;
 }
 
diff -u --recursive --new-file v2.3.42/linux/fs/coda/coda_linux.c linux/fs/coda/coda_linux.c
--- v2.3.42/linux/fs/coda/coda_linux.c	Tue Jul  6 19:08:33 1999
+++ linux/fs/coda/coda_linux.c	Thu Feb 10 12:16:58 2000
@@ -102,7 +102,6 @@
 	        return 1;
 
 	return 0;
-
 }
 
 
@@ -290,7 +289,6 @@
                 vattr->va_ctime.tv_sec = iattr->ia_ctime;
                 vattr->va_ctime.tv_nsec = 0;
 	}
-        
 }
 
 void print_vattr(struct coda_vattr *attr)
diff -u --recursive --new-file v2.3.42/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.3.42/linux/fs/coda/dir.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/coda/dir.c	Thu Feb 10 12:16:58 2000
@@ -77,26 +77,16 @@
 	coda_rename,	        /* rename */
 	NULL,	                /* readlink */
 	NULL,	                /* follow_link */
-	NULL,		        /* get_block */
-	NULL,	                /* readpage */
-	NULL,		        /* writepage */
 	NULL,	                /* truncate */
 	coda_permission,        /* permission */
         coda_revalidate_inode   /* revalidate */
 };
 
 struct file_operations coda_dir_operations = {
-        NULL,                   /* lseek */
-        NULL,                   /* read -- bad  */
-        NULL,                   /* write */
-        coda_readdir,           /* readdir */
-        NULL,                   /* select */
-        NULL,                   /* ioctl */
-        NULL,                   /* mmap */
-        coda_open,              /* open */
-	NULL,
-        coda_release,           /* release */
-	coda_fsync,             /* fsync */
+	readdir:	coda_readdir,
+	open:		coda_open,
+	release:	coda_release,
+	fsync:		coda_fsync,
 };
 
 
@@ -206,7 +196,6 @@
 }
 
 
-
 /* creation routines: create, mknod, mkdir, link, symlink */
 
 static int coda_create(struct inode *dir, struct dentry *de, int mode)
@@ -267,7 +256,8 @@
 
 	coda_vfs_stat.create++;
 
-	CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",name, length, mode, rdev);
+	CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",
+	       name, length, mode, rdev);
 
 	if (coda_isroot(dir) && coda_iscontrol(name, length))
 		return -EPERM;
@@ -528,7 +518,6 @@
 }
 
 
-
 /* file operations for directories */
 int coda_readdir(struct file *file, void *dirent,  filldir_t filldir)
 {
@@ -607,11 +596,11 @@
 	coda_load_creds(cred);
 	f->private_data = cred;
 
-        if (  cnp->c_ovp ) {
+	if (  cnp->c_ovp )
 		iput(cnp->c_ovp);
-		cnp->c_ovp = NULL;
-	}
+
 	cnp->c_ovp = cont_inode; 
+	i->i_mapping = cont_inode->i_mapping;
         cnp->c_ocount++;
 
         CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", 
@@ -626,7 +615,7 @@
 int coda_release(struct inode *i, struct file *f)
 {
         struct coda_inode_info *cnp;
-        int error;
+	int error = 0;
         unsigned short flags = (f->f_flags) & (~O_EXCL);
 	unsigned short cflags = coda_flags_to_cflags(flags);
 	struct coda_cred *cred;
@@ -652,14 +641,17 @@
 
         --cnp->c_ocount;
 
-        if (flags & (O_WRONLY | O_RDWR)) {
+	if ( flags & (O_WRONLY | O_RDWR) )
                 --cnp->c_owrite;
-        }
 
+	/* Venus closing a container file? don't bother making the upcall. */
+	if ( current->pid != coda_upc_comm.vc_pid ) {
 	error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred);
+	}
 
-	CODA_FREE(cred, sizeof(*cred));
 	f->private_data = NULL;
+	if (cred)
+		CODA_FREE(cred, sizeof(*cred));
 
         CDEBUG(D_FILE, "coda_release: result: %d\n", error);
         return error;
@@ -857,19 +849,18 @@
 	if ( cii->c_flags == 0 )
 		return 0;
 
-	/* Venus closed the device .... */
-	if ( cii->c_flags & C_DYING ) { 
-		make_bad_inode(inode);
-		return -EIO;
-	}
+	/* Venus accessing a container file, don't try to revalidate */
+	if ( current->pid == coda_upc_comm.vc_pid )
+		return 0;
 
+	/* Venus closed the device .... */
+	if ( cii->c_flags & C_DYING )
+		goto return_bad_inode;
 	
 	if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
 		error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
-		if ( error ) { 
-			make_bad_inode(inode);
-			return -EIO;
-		}
+		if ( error )
+			goto return_bad_inode;
 
 		/* this inode may be lost if:
 		   - it's ino changed 
@@ -887,12 +878,9 @@
 		}
 
 		/* the following can happen when a local fid is replaced 
-		   with a global one, here we lose and declar the inode bad */
-		if (inode->i_ino != old_ino) {
-			make_bad_inode(inode);
-			inode->i_mode = old_mode;
-			return -EIO;
-		}
+		   with a global one, here we lose and declare the inode bad */
+		if (inode->i_ino != old_ino)
+			goto return_bad_inode;
 		
 		if ( cii->c_flags ) 
 			coda_flag_inode_children(inode, C_FLUSH);
@@ -901,5 +889,14 @@
 	}
 
 	return 0;
+
+return_bad_inode:
+	if ( cii->c_ovp ) {
+		iput(cii->c_ovp);
+		inode->i_mapping = &inode->i_data;
+		cii->c_ovp = NULL;
+	}
+	make_bad_inode(inode);
+	return -EIO;
 }
 
diff -u --recursive --new-file v2.3.42/linux/fs/coda/file.c linux/fs/coda/file.c
--- v2.3.42/linux/fs/coda/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/coda/file.c	Thu Feb 10 12:16:58 2000
@@ -14,6 +14,7 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
+#include <linux/smp_lock.h>
 #include <asm/segment.h>
 #include <linux/string.h>
 #include <asm/uaccess.h>
@@ -26,9 +27,6 @@
 #include <linux/coda_proc.h>
 
 /* file operations */
-static int coda_readpage(struct dentry *dentry, struct page * page);
-static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
-static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
 static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
 
 /* also exported from this file (used for dirs) */
@@ -47,57 +45,21 @@
 	NULL,		        /* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	coda_readpage,    	/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
         coda_permission,        /* permission */
         coda_revalidate_inode   /* revalidate */
 };
 
 struct file_operations coda_file_operations = {
-	NULL,		        /* lseek - default should work for coda */
-	coda_file_read,         /* read */
-	coda_file_write,        /* write */
-	NULL,          		/* readdir */
-	NULL,			/* select - default */
-	NULL,		        /* ioctl */
-	coda_file_mmap,         /* mmap */
-	coda_open,              /* open */
-	NULL,
-	coda_release,           /* release */
-	coda_fsync,		/* fsync */
-	NULL,                   /* fasync */
-	NULL                    /* lock */
+	read:		generic_file_read,
+	write:		generic_file_write,
+	mmap:		coda_file_mmap,
+	open:		coda_open,
+	release:	coda_release,
+	fsync:		coda_fsync,
 };
-
-/*  File file operations */
-static int coda_readpage(struct dentry * dentry, struct page * page)
-{
-	struct inode *coda_inode = dentry->d_inode;
-	struct dentry cont_dentry;
-        struct coda_inode_info *cii;
-
-        ENTRY;
-	coda_vfs_stat.readpage++;
-        
-        cii = ITOC(coda_inode);
-
-        if ( ! cii->c_ovp ) {
-		printk("coda_readpage: no open inode for ino %ld, %s\n", 
-		       coda_inode->i_ino, dentry->d_name.name);
-                return -ENXIO;
-        }
-       
-        cont_dentry.d_inode = cii->c_ovp;
-
-        CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", 
-	       coda_inode->i_ino, cii->c_ovp->i_ino, page->index);
-
-        block_read_full_page(&cont_dentry, page);
-        EXIT;
-        return 0;
-}
+ 
+/*  File operations */
 
 static int coda_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
@@ -115,89 +77,6 @@
 	return res;
 }
 
-static ssize_t coda_file_read(struct file *coda_file, char *buff, 
-			   size_t count, loff_t *ppos)
-{
-        struct coda_inode_info *cnp;
-	struct inode *coda_inode = coda_file->f_dentry->d_inode;
-        struct inode *cont_inode = NULL;
-        struct file  cont_file;
-	struct dentry cont_dentry;
-        int result = 0;
-
-	ENTRY;
-	coda_vfs_stat.file_read++;
-
-        cnp = ITOC(coda_inode);
-        CHECK_CNODE(cnp);
-	
-        cont_inode = cnp->c_ovp;
-        if ( cont_inode == NULL ) {
-                printk("coda_file_read: cached inode is 0!\n");
-                return -1;
-        }
-
-        coda_prepare_openfile(coda_inode, coda_file, cont_inode, 
-			      &cont_file, &cont_dentry);
-
-        if (!cont_file.f_op || ! cont_file.f_op->read) { 
-                printk( "container file has no read in file operations.\n");
-                return -1;
-        }
-
-        result = cont_file.f_op->read(&cont_file , buff, count, 
-				      &(cont_file.f_pos));
-
-        CDEBUG(D_FILE, "ops at %p result %d, count %ld, position: %d\n", 
-	       cont_file.f_op, result, (long)count, (int)cont_file.f_pos);
-
-        coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
-        return result;
-}
-
-
-static ssize_t coda_file_write(struct file *coda_file, const char *buff, 
-			    size_t count, loff_t *ppos)
-{
-        struct coda_inode_info *cnp;
-	struct inode *coda_inode = coda_file->f_dentry->d_inode;
-        struct inode *cont_inode = NULL;
-        struct file  cont_file;
-	struct dentry cont_dentry;
-        int result = 0;
-
-        ENTRY;
-	coda_vfs_stat.file_write++;
-
-        cnp = ITOC(coda_inode);
-        CHECK_CNODE(cnp);
-
-        cont_inode = cnp->c_ovp;
-        if ( cont_inode == NULL ) {
-                printk("coda_file_write: cached inode is 0!\n");
-                return -1; 
-        }
-
-        coda_prepare_openfile(coda_inode, coda_file, cont_inode, 
-			      &cont_file, &cont_dentry);
-
-        if (!cont_file.f_op || !cont_file.f_op->write) {
-                printk("coda_file_write: container file has no file ops.\n");
-                return -1;
-        }
-
-	down(&cont_inode->i_sem);
-        result = cont_file.f_op->write(&cont_file , buff, count, 
-				       &(cont_file.f_pos));
-	up(&cont_inode->i_sem);
-        coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
-	
-	if (result)
-		cnp->c_flags |= C_VATTR;
-
-        return result;
-}
-
 int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
 {
         struct coda_inode_info *cnp;
@@ -213,12 +92,14 @@
 	      S_ISLNK(coda_inode->i_mode)))
 		return -EINVAL;
 
+	lock_kernel();
         cnp = ITOC(coda_inode);
         CHECK_CNODE(cnp);
 
         cont_inode = cnp->c_ovp;
         if ( cont_inode == NULL ) {
                 printk("coda_file_write: cached inode is 0!\n");
+		unlock_kernel();
                 return -1; 
         }
 
@@ -235,6 +116,7 @@
 	up(&cont_inode->i_sem);
 
         coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
+	unlock_kernel();
         return result;
 }
 /* 
@@ -284,8 +166,8 @@
         *ind = iget(sbptr, ino);
 
         if ( *ind == NULL ) {
-                printk("coda_inode_grab: iget(dev: %d, ino: %ld) 
-                       returns NULL.\n", dev, (long)ino);
+		printk("coda_inode_grab: iget(dev: %d, ino: %ld) "
+		       "returns NULL.\n", dev, (long)ino);
                 return -ENOENT;
         }
 	CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op);
diff -u --recursive --new-file v2.3.42/linux/fs/coda/inode.c linux/fs/coda/inode.c
--- v2.3.42/linux/fs/coda/inode.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/coda/inode.c	Thu Feb 10 12:16:58 2000
@@ -52,7 +52,9 @@
 	coda_put_super,	        /* put_super */
 	NULL,			/* write_super */
 	coda_statfs,   		/* statfs */
-	NULL			/* remount_fs */
+	NULL,			/* remount_fs */
+	NULL,			/* no clear inode */
+	NULL			/* umount attempt begin */
 };
 
 static struct super_block * coda_read_super(struct super_block *sb, 
@@ -163,15 +165,16 @@
 	return;
 }
 
-static void coda_put_inode(struct inode *in) 
+static void coda_put_inode(struct inode *inode) 
 {
 	ENTRY;
 
-        CDEBUG(D_INODE,"ino: %ld, count %d\n", in->i_ino, in->i_count);
-
-	if ( in->i_count == 1 ) 
-		in->i_nlink = 0;
+	CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, inode->i_count);
 		
+	if ( inode->i_count == 1 ) {
+                write_inode_now(inode);
+		inode->i_nlink = 0;
+        }
 }
 
 static void coda_delete_inode(struct inode *inode)
@@ -189,15 +192,17 @@
 		return;
 	}
 
-
-	if ( ! list_empty(&cii->c_volrootlist) )
+	if ( ! list_empty(&cii->c_volrootlist) ) {
 		list_del(&cii->c_volrootlist);
+		INIT_LIST_HEAD(&cii->c_volrootlist);
+        }
 
         open_inode = cii->c_ovp;
         if ( open_inode ) {
                 CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n",  
 		       open_inode->i_ino,  open_inode->i_count);
                 cii->c_ovp = NULL;
+		inode->i_mapping = &inode->i_data;
                 iput(open_inode);
         }
 	
diff -u --recursive --new-file v2.3.42/linux/fs/coda/pioctl.c linux/fs/coda/pioctl.c
--- v2.3.42/linux/fs/coda/pioctl.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/coda/pioctl.c	Thu Feb 10 12:16:58 2000
@@ -46,26 +46,15 @@
 	NULL,		        /* rename */
 	NULL,	                /* readlink */
 	NULL,	                /* follow_link */
-	NULL,		        /* get_block */
-	NULL,	                /* readpage */
-	NULL,		        /* writepage */
 	NULL,	                /* truncate */
 	coda_ioctl_permission,  /* permission */
         NULL                    /* revalidate */
 };
 
 struct file_operations coda_ioctl_operations = {
-	NULL,		        /* lseek - default should work for coda */
-	NULL,                   /* read */
-	NULL,                   /* write */
-	NULL,          		/* readdir */
-	NULL,			/* select - default */
-	coda_pioctl,	        /* ioctl */
-	NULL,                   /* mmap */
-	coda_ioctl_open,        /* open */
-	NULL,
-	coda_ioctl_release,     /* release */
-	NULL,		        /* fsync */
+	ioctl:		coda_pioctl,
+	open:		coda_ioctl_open,
+	release:	coda_ioctl_release,
 };
 
 /* the coda pioctl inode ops */
@@ -79,7 +68,6 @@
 /* The pioctl file ops*/
 int coda_ioctl_open(struct inode *i, struct file *f)
 {
-
         ENTRY;
 
         CDEBUG(D_PIOCTL, "File inode number: %ld\n", 
diff -u --recursive --new-file v2.3.42/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.3.42/linux/fs/coda/psdev.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/coda/psdev.c	Thu Feb 10 12:16:58 2000
@@ -76,6 +76,21 @@
 	return mask;
 }
 
+static int coda_psdev_ioctl(struct inode * inode, struct file * filp, 
+			    unsigned int cmd, unsigned long arg)
+{
+	unsigned int data;
+
+	switch(cmd) {
+	case CIOC_KERNEL_VERSION:
+		data = CODA_KERNEL_VERSION;
+		return put_user(data, (int *) arg);
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
 
 /*
  *	Receive a message written by Venus to the psdev
@@ -246,7 +261,6 @@
 	vcp->vc_inuse++;
 	MOD_INC_USE_COUNT;
 
-
 	if ( file->f_flags == O_RDWR ) {
 		vcp->vc_pid = current->pid;
 		vcp->vc_seq = 0;
@@ -262,7 +276,6 @@
 }
 
 
-
 static int coda_psdev_release(struct inode * inode, struct file * file)
 {
         struct venus_comm *vcp = &coda_upc_comm;
@@ -298,6 +311,7 @@
 			CODA_FREE(req, (u_int)sizeof(struct upc_req));
 			continue;
 		}
+		req->uc_flags |= REQ_ABORT;
 		wake_up(&req->uc_sleep);
         }
         
@@ -305,6 +319,7 @@
 	CDEBUG(D_PSDEV, "wake up processing clients\n");
 	while ( (lh = lh->next) != &vcp->vc_processing) {
 		req = list_entry(lh, struct upc_req, uc_chain);
+		req->uc_flags |= REQ_ABORT;
 	        wake_up(&req->uc_sleep);
         }
 	CDEBUG(D_PSDEV, "Done.\n");
@@ -315,19 +330,12 @@
 
 
 static struct file_operations coda_psdev_fops = {
-      NULL,                  /* llseek */
-      coda_psdev_read,       /* read */
-      coda_psdev_write,      /* write */
-      NULL,		     /* coda_psdev_readdir */
-      coda_psdev_poll,       /* poll */
-      NULL,                  /* ioctl */
-      NULL,		     /* coda_psdev_mmap */
-      coda_psdev_open,       /* open */
-      NULL,
-      coda_psdev_release,    /* release */
-      NULL,                  /* fsync */
-      NULL,                  /* fasync */
-      NULL                   /* lock */
+	read:		coda_psdev_read,
+	write:		coda_psdev_write,
+	poll:		coda_psdev_poll,
+	ioctl:		coda_psdev_ioctl,
+	open:		coda_psdev_open,
+	release:	coda_psdev_release,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/fs/coda/symlink.c linux/fs/coda/symlink.c
--- v2.3.42/linux/fs/coda/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/coda/symlink.c	Thu Feb 10 12:16:58 2000
@@ -48,8 +48,6 @@
 	return error;
 }
 
-struct inode_operations coda_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
+struct address_space_operations coda_symlink_aops = {
 	readpage:	coda_symlink_filler
 };
diff -u --recursive --new-file v2.3.42/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.3.42/linux/fs/coda/sysctl.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/coda/sysctl.c	Thu Feb 10 12:16:58 2000
@@ -109,7 +109,8 @@
 	"open_by_path",   /* 31 */
 	"resolve     ",   /* 32 */
 	"reintegrate ",   /* 33 */
-	"statfs      "    /* 34 */
+	"statfs      ",   /* 34 */
+	"make_cinode "    /* 35 */
 };
 
 
@@ -214,8 +215,8 @@
 		return 0;
   
 	time_avg = get_time_average( pentry );
-	return 
-	        sqr_root( (pentry->time_squared_sum / pentry->count) - 
+
+	return sqr_root( (pentry->time_squared_sum / pentry->count) - 
 			    time_avg * time_avg );
 }
 
diff -u --recursive --new-file v2.3.42/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.3.42/linux/fs/coda/upcall.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/coda/upcall.c	Thu Feb 10 12:16:58 2000
@@ -24,6 +24,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
@@ -392,7 +393,7 @@
 		if ( retlen > *length )
 		        retlen = *length;
 		*length = retlen;
-		result =  (char *)outp + (int)outp->coda_readlink.data;
+		result =  (char *)outp + (long)outp->coda_readlink.data;
 		memcpy(buffer, result, retlen);
 		*(buffer + retlen) = '\0';
 	}
@@ -541,7 +542,7 @@
         inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
      
         /* get the data out of user space */
-        if ( copy_from_user((char*)inp + (int)inp->coda_ioctl.data,
+        if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
 			    data->vi.in, data->vi.in_size) ) {
 	        error = EINVAL;
 	        goto exit;
@@ -567,7 +568,7 @@
 		if ( error ) goto exit;
 
 		if (copy_to_user(data->vi.out, 
-				 (char *)outp + (int)outp->coda_ioctl.data, 
+				 (char *)outp + (long)outp->coda_ioctl.data, 
 				 data->vi.out_size)) {
 		        error = EINVAL;
 			goto exit;
@@ -630,7 +631,7 @@
 			set_current_state(TASK_UNINTERRUPTIBLE);
 
 		/* got a reply */
-		if ( vmp->uc_flags & REQ_WRITE )
+		if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
 			break;
 
 		if ( !coda_hard && signal_pending(current) ) {
@@ -660,7 +661,8 @@
 	}
 
 	CDEBUG(D_SPECIAL, "begin: %ld.%06ld, elapsed: %ld.%06ld\n",
-		begin.tv_sec, begin.tv_usec, end.tv_sec, end.tv_usec);
+		begin.tv_sec, (unsigned long)begin.tv_usec,
+		end.tv_sec, (unsigned long)end.tv_usec);
 
 	return 	((end.tv_sec * 1000000) + end.tv_usec);
 }
@@ -844,7 +846,6 @@
 
 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
 {
-
 	/* Handle invalidation requests. */
           if ( !sb || !sb->s_root || !sb->s_root->d_inode) { 
 	          printk("coda_downcall: opcode %d, no sb!\n", opcode);
@@ -877,7 +878,8 @@
 	  case CODA_ZAPDIR : {
 	          struct inode *inode;
 		  ViceFid *fid = &out->coda_zapdir.CodaFid;
-		  CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid));
+			CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n",
+			       coda_f2s(fid));
 		  clstats(CODA_ZAPDIR);
 
 		  inode = coda_fid_to_inode(fid, sb);
@@ -887,6 +889,7 @@
 			  coda_flag_inode_children(inode, C_PURGE);
 			  CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino);
 	                  coda_flag_inode(inode, C_VATTR);
+				iput(inode);
 		  } else 
 			  CDEBUG(D_DOWNCALL, "zapdir: no inode\n");
 		  
@@ -897,11 +900,14 @@
 	          struct inode *inode;
 		  struct ViceFid *fid = &out->coda_zapfile.CodaFid;
 		  clstats(CODA_ZAPFILE);
-		  CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
+			CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n",
+			       coda_f2s(fid));
 		  inode = coda_fid_to_inode(fid, sb);
 		  if ( inode ) {
-			  CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n", inode->i_ino);
+				CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n",
+				       inode->i_ino);
 	                  coda_flag_inode(inode, C_VATTR);
+				iput(inode);
 		  } else 
 			  CDEBUG(D_DOWNCALL, "zapfile: no inode\n");
 		  return 0;
@@ -910,18 +916,61 @@
 	  case CODA_PURGEFID : {
 	          struct inode *inode;
 		  ViceFid *fid = &out->coda_purgefid.CodaFid;
-		  CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid));
+			CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n",
+			       coda_f2s(fid));
 		  clstats(CODA_PURGEFID);
 		  inode = coda_fid_to_inode(fid, sb);
 		  if ( inode ) { 
-			  CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", inode->i_ino);
+				CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n",
+				       inode->i_ino);
 			  coda_flag_inode_children(inode, C_PURGE);
 			  coda_purge_dentries(inode);
+				iput(inode);
 		  }else 
 			  CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
 		  return 0;
 	  }
 
+	case CODA_MAKE_CINODE : {
+			struct inode *inode;
+			ViceFid *fid = &out->coda_make_cinode.CodaFid;
+			struct coda_vattr *attr = &out->coda_make_cinode.attr;
+			int fd = out->coda_make_cinode.fd;
+			struct file *file;
+			CDEBUG(D_DOWNCALL, "make_cinode: fid = %s, ino = %ld\n",
+			       coda_f2s(fid), attr->va_fileid);
+
+			inode = coda_iget(sb, fid, attr);
+			if ( !inode ) { 
+				CDEBUG(D_DOWNCALL, "make_cinode: no inode\n");
+				return -EINVAL;
+			}
+
+			file = fget(fd);
+			if ( !file ) { 
+				CDEBUG(D_DOWNCALL, "make_cinode: no file\n");
+				iput(inode);
+				return -EINVAL;
+			}
+
+			inode->u.coda_i.c_ovp = file->f_dentry->d_inode;
+			inode->i_mapping = file->f_dentry->d_inode->i_mapping;
+			file->f_dentry->d_inode = inode;
+			file->f_op = &coda_file_operations;
+
+			/*
+			   Unhash the dentry of the container file, as it is
+			   still owned by the fs that stores the container
+			   file. A more reliable solution would be to create
+			   an new dentry owned by Coda, but that would require
+			   knowledge of the internals of the dcache.
+			 */
+			d_drop(file->f_dentry);
+
+			fput(file);
+			return 0;
+		}
+                              
 	  case CODA_REPLACE : {
 	          struct inode *inode;
 		  ViceFid *oldfid = &out->coda_replace.OldFid;
@@ -932,6 +981,7 @@
 		  if ( inode ) { 
 			  CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino);
 			  coda_replace_fid(inode, oldfid, newfid);
+				iput(inode);
 		  }else 
 			  CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
 		  
@@ -941,5 +991,3 @@
 	  return 0;
 }
 
-
-                
diff -u --recursive --new-file v2.3.42/linux/fs/cramfs/inflate/zconf.h linux/fs/cramfs/inflate/zconf.h
--- v2.3.42/linux/fs/cramfs/inflate/zconf.h	Wed Dec 29 13:13:20 1999
+++ linux/fs/cramfs/inflate/zconf.h	Wed Feb  9 18:48:03 2000
@@ -83,8 +83,8 @@
 typedef void FAR *voidpf;
 typedef void     *voidp;
 
-#include <sys/types.h> /* for off_t */
-#include <unistd.h>    /* for SEEK_* and off_t */
+#include <linux/types.h> /* for off_t */
+#include <linux/unistd.h>    /* for SEEK_* and off_t */
 #define z_off_t  off_t
 
 #endif /* _ZCONF_H */
diff -u --recursive --new-file v2.3.42/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- v2.3.42/linux/fs/cramfs/inode.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/cramfs/inode.c	Thu Feb 10 12:16:58 2000
@@ -25,7 +25,7 @@
 static struct super_operations cramfs_ops;
 static struct inode_operations cramfs_file_inode_operations;
 static struct inode_operations cramfs_dir_inode_operations;
-static struct inode_operations cramfs_symlink_inode_operations;
+static struct address_space_operations cramfs_aops;
 
 /* These two macros may change in future, to provide better st_ino
    semantics. */
@@ -51,13 +51,15 @@
 				       result in GNU find, even
 				       without -noleaf option. */
 		insert_inode_hash(inode);
-		if (S_ISREG(inode->i_mode))
+		if (S_ISREG(inode->i_mode)) {
 			inode->i_op = &cramfs_file_inode_operations;
-		else if (S_ISDIR(inode->i_mode))
+			inode->i_data.a_ops = &cramfs_aops;
+		} else if (S_ISDIR(inode->i_mode))
 			inode->i_op = &cramfs_dir_inode_operations;
-		else if (S_ISLNK(inode->i_mode))
-			inode->i_op = &cramfs_symlink_inode_operations;
-		else {
+		else if (S_ISLNK(inode->i_mode)) {
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_data.a_ops = &cramfs_aops;
+		} else {
 			inode->i_size = 0;
 			init_special_inode(inode, inode->i_mode, cramfs_inode->size);
 		}
@@ -344,53 +346,9 @@
 	return 0;
 }
 
-static struct page *get_symlink_page(struct dentry *dentry)
-{
-	return read_cache_page(&dentry->d_inode->i_data, 0, (filler_t *)cramfs_readpage, dentry);
-}
-
-static int cramfs_readlink(struct dentry *dentry, char *buffer, int len)
-{
-	struct inode *inode = dentry->d_inode;
-	int retval;
-
-	if (!inode || !S_ISLNK(inode->i_mode))
-		return -EBADF;
-
-	retval = inode->i_size;
-	if (retval) {
-		int len;
-		struct page *page = get_symlink_page(dentry);
-
-		if (IS_ERR(page))
-			return PTR_ERR(page);
-		wait_on_page(page);
-		len = retval;
-		retval = -EIO;
-		if (Page_Uptodate(page)) {
-			retval = -EFAULT;
-			if (!copy_to_user(buffer, (void *) page_address(page), len))
-				retval = len;
-		}
-		page_cache_release(page);
-	}
-	return retval;
-}
-
-static struct dentry *cramfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
-{
-	struct page *page = get_symlink_page(dentry);
-	struct dentry *result;
-
-	if (IS_ERR(page)) {
-		dput(base);
-		return ERR_PTR(PTR_ERR(page));
-	}
-
-	result = lookup_dentry((void *) page_address(page), base, follow);
-	page_cache_release(page);
-	return result;
-}
+static struct address_space_operations cramfs_aops = {
+	readpage: cramfs_readpage
+};
 
 /*
  * Our operations:
@@ -398,99 +356,25 @@
  * A regular file can be read and mmap'ed.
  */
 static struct file_operations cramfs_file_operations = {
-	NULL,			/* lseek - default */
-	generic_file_read,	/* read */
-	NULL,			/* write - bad */
-	NULL,			/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
+	read:		generic_file_read,
+	mmap:		generic_file_mmap,
 };
 
 /*
  * A directory can only readdir
  */
 static struct file_operations cramfs_directory_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read */
-	NULL,			/* write - bad */
-	cramfs_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
+	readdir:	cramfs_readdir,
 };
 
 static struct inode_operations cramfs_file_inode_operations = {
 	&cramfs_file_operations,
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	cramfs_readpage,	/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static struct inode_operations cramfs_dir_inode_operations = {
 	&cramfs_directory_operations,
 	NULL,			/* create */
 	cramfs_lookup,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
-};
-
-static struct inode_operations cramfs_symlink_inode_operations = {
-	NULL,			/* symlinks do not have files */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	cramfs_readlink,		/* readlink */
-	cramfs_follow_link,	/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static struct super_operations cramfs_ops = {
diff -u --recursive --new-file v2.3.42/linux/fs/devices.c linux/fs/devices.c
--- v2.3.42/linux/fs/devices.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/devices.c	Wed Feb  9 11:42:35 2000
@@ -157,7 +157,7 @@
  * depending on the special file...
  */
 static struct file_operations def_chr_fops = {
-	open:	chrdev_open
+	open:		chrdev_open,
 };
 
 static struct inode_operations chrdev_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/devpts/root.c linux/fs/devpts/root.c
--- v2.3.42/linux/fs/devpts/root.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/devpts/root.c	Thu Feb 10 12:16:58 2000
@@ -21,31 +21,13 @@
 static int devpts_revalidate(struct dentry *, int);
 
 static struct file_operations devpts_root_operations = {
-	NULL,                   /* llseek */
-	NULL,                   /* read */
-	NULL,                   /* write */
-	devpts_root_readdir,    /* readdir */
+	readdir:	devpts_root_readdir,
 };
 
 struct inode_operations devpts_root_inode_operations = {
 	&devpts_root_operations, /* file operations */
 	NULL,                   /* create */
 	devpts_root_lookup,     /* lookup */
-	NULL,                   /* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,                   /* mknod */
-	NULL,                   /* rename */
-	NULL,                   /* readlink */
-	NULL,                   /* follow_link */
-	NULL,                   /* get_block */
-	NULL,                   /* readpage */
-	NULL,                   /* writepage */
-	NULL,                   /* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static struct dentry_operations devpts_dentry_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/efs/dir.c linux/fs/efs/dir.c
--- v2.3.42/linux/fs/efs/dir.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/efs/dir.c	Thu Feb 10 12:16:58 2000
@@ -9,41 +9,13 @@
 static int efs_readdir(struct file *, void *, filldir_t);
 
 static struct file_operations efs_dir_operations = {
-	NULL,			/* lseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	efs_readdir,		/* readdir */
-	NULL,			/* poll */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
+	readdir:	efs_readdir,
 };
 
-extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
-
 struct inode_operations efs_dir_inode_operations = {
 	&efs_dir_operations,	/* default directory file-ops */
 	NULL,			/* create */
 	efs_lookup,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	efs_get_block,		/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
diff -u --recursive --new-file v2.3.42/linux/fs/efs/file.c linux/fs/efs/file.c
--- v2.3.42/linux/fs/efs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/efs/file.c	Thu Feb 10 12:16:58 2000
@@ -62,37 +62,10 @@
 }
 
 static struct file_operations efs_file_operations = {
-	NULL,			/* lseek */
-	generic_file_read,	/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	NULL,			/* ioctl */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
+	read:		generic_file_read,
+	mmap:		generic_file_mmap,
 };
 
 struct inode_operations efs_file_inode_operations = {
 	&efs_file_operations,	/* default file operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	efs_get_block,		/* get_block */
-	block_read_full_page,	/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
diff -u --recursive --new-file v2.3.42/linux/fs/efs/inode.c linux/fs/efs/inode.c
--- v2.3.42/linux/fs/efs/inode.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/efs/inode.c	Thu Feb 10 12:16:58 2000
@@ -10,6 +10,20 @@
 #include <linux/efs_fs.h>
 #include <linux/efs_fs_sb.h>
 
+extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
+static int efs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,efs_get_block);
+}
+static int _efs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,efs_get_block);
+}
+struct address_space_operations efs_aops = {
+	readpage: efs_readpage,
+	bmap: _efs_bmap
+};
+
 static inline void extent_copy(efs_extent *src, efs_extent *dst) {
 	/*
 	 * this is slightly evil. it doesn't just copy
@@ -126,9 +140,11 @@
 			break;
 		case S_IFREG:
 			inode->i_op = &efs_file_inode_operations;
+			inode->i_data.a_ops = &efs_aops;
 			break;
 		case S_IFLNK:
-			inode->i_op = &efs_symlink_inode_operations;
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_data.a_ops = &efs_symlink_aops;
 			break;
 		case S_IFCHR:
 		case S_IFBLK:
diff -u --recursive --new-file v2.3.42/linux/fs/efs/symlink.c linux/fs/efs/symlink.c
--- v2.3.42/linux/fs/efs/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/efs/symlink.c	Thu Feb 10 12:16:58 2000
@@ -48,8 +48,6 @@
 	return err;
 }
 
-struct inode_operations efs_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
+struct address_space_operations efs_symlink_aops = {
 	readpage:	efs_symlink_readpage
 };
diff -u --recursive --new-file v2.3.42/linux/fs/exec.c linux/fs/exec.c
--- v2.3.42/linux/fs/exec.c	Tue Jan  4 13:57:17 2000
+++ linux/fs/exec.c	Mon Feb  7 19:45:28 2000
@@ -265,7 +265,7 @@
  * This routine is used to map in a page into an address space: needed by
  * execve() for the initial stack and environment pages.
  */
-static void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address)
+void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address)
 {
 	pgd_t * pgd;
 	pmd_t * pmd;
diff -u --recursive --new-file v2.3.42/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v2.3.42/linux/fs/ext2/dir.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/ext2/dir.c	Thu Feb 10 12:16:58 2000
@@ -31,18 +31,10 @@
 static int ext2_readdir(struct file *, void *, filldir_t);
 
 static struct file_operations ext2_dir_operations = {
-	NULL,			/* lseek - default */
-	ext2_dir_read,		/* read */
-	NULL,			/* write - bad */
-	ext2_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	ext2_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	ext2_sync_file,		/* fsync */
-	NULL,			/* fasync */
+	read:		ext2_dir_read,
+	readdir:	ext2_readdir,
+	ioctl:		ext2_ioctl,
+	fsync:		ext2_sync_file,
 };
 
 /*
@@ -59,14 +51,6 @@
 	ext2_rmdir,		/* rmdir */
 	ext2_mknod,		/* mknod */
 	ext2_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 int ext2_check_dir_entry (const char * function, struct inode * dir,
diff -u --recursive --new-file v2.3.42/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.3.42/linux/fs/ext2/file.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/ext2/file.c	Thu Feb 10 12:16:58 2000
@@ -21,13 +21,6 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 
-
-
-#define	NBUF	32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
 static loff_t ext2_file_lseek(struct file *, loff_t, int);
 static int ext2_open_file (struct inode *, struct file *);
 
@@ -73,40 +66,6 @@
 	return offset;
 }
 
-static inline void remove_suid(struct inode *inode)
-{
-	unsigned int mode;
-
-	/* set S_IGID if S_IXGRP is set, and always set S_ISUID */
-	mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
-	/* was any of the uid bits set? */
-	mode &= inode->i_mode;
-	if (mode && !capable(CAP_FSETID)) {
-		inode->i_mode &= ~mode;
-		mark_inode_dirty(inode);
-	}
-}
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-ext2_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	ssize_t retval;
-
-	retval = generic_file_write(file, buf, count,
-						 ppos, block_write_partial_page);
-	if (retval > 0) {
-		struct inode *inode = file->f_dentry->d_inode;
-		remove_suid(inode);
-		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-		mark_inode_dirty(inode);
-	}
-	return retval;
-}
-
 /*
  * Called when an inode is released. Note that this is different
  * from ext2_file_open: open gets called at every open, but release
@@ -137,37 +96,17 @@
  * the ext2 filesystem.
  */
 static struct file_operations ext2_file_operations = {
-	ext2_file_lseek,	/* lseek */
-	generic_file_read,	/* read */
-	ext2_file_write,	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	ext2_ioctl,		/* ioctl */
-	generic_file_mmap,	/* mmap */
-	ext2_open_file,
-	NULL,			/* flush */
-	ext2_release_file,	/* release */
-	ext2_sync_file,		/* fsync */
-	NULL,			/* fasync */
+	llseek:		ext2_file_lseek,
+	read:		generic_file_read,
+	write:		generic_file_write,
+	ioctl:		ext2_ioctl,
+	mmap:		generic_file_mmap,
+	open:		ext2_open_file,
+	release:	ext2_release_file,
+	fsync:		ext2_sync_file,
 };
 
 struct inode_operations ext2_file_inode_operations = {
-	&ext2_file_operations,/* default file operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	ext2_get_block,		/* get_block */
-	block_read_full_page,	/* readpage */
-	block_write_full_page,	/* writepage */
-	ext2_truncate,		/* truncate */
-	NULL,			/* permission */
-	NULL,			/* revalidate */
+	&ext2_file_operations,
+	truncate:	ext2_truncate,
 };
diff -u --recursive --new-file v2.3.42/linux/fs/ext2/fsync.c linux/fs/ext2/fsync.c
--- v2.3.42/linux/fs/ext2/fsync.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/ext2/fsync.c	Wed Feb  9 14:55:34 2000
@@ -24,8 +24,7 @@
 
 #include <linux/fs.h>
 #include <linux/locks.h>
-
-
+#include <linux/smp_lock.h>
 
 
 #define blocksize	(EXT2_BLOCK_SIZE(inode->i_sb))
@@ -130,6 +129,7 @@
 	int wait, err = 0;
 	struct inode *inode = dentry->d_inode;
 
+	lock_kernel();
 	if (S_ISLNK(inode->i_mode) && !(inode->i_blocks))
 		/*
 		 * Don't sync fast links!
@@ -152,5 +152,6 @@
 	}
 skip:
 	err |= ext2_sync_inode (inode);
+	unlock_kernel();
 	return err ? -EIO : 0;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.3.42/linux/fs/ext2/inode.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/ext2/inode.c	Thu Feb 10 12:16:58 2000
@@ -408,7 +408,7 @@
 	return result;
 }
 
-int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
 {
 	int ret, err, new;
 	struct buffer_head *bh;
@@ -610,6 +610,30 @@
 	return NULL;
 }
 
+static int ext2_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,ext2_get_block);
+}
+static int ext2_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,ext2_get_block);
+}
+static int ext2_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page,from,to,ext2_get_block);
+}
+static int ext2_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,ext2_get_block);
+}
+struct address_space_operations ext2_aops = {
+	readpage: ext2_readpage,
+	writepage: ext2_writepage,
+	prepare_write: ext2_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: ext2_bmap
+};
+
 void ext2_read_inode (struct inode * inode)
 {
 	struct buffer_head * bh;
@@ -719,15 +743,19 @@
 	if (inode->i_ino == EXT2_ACL_IDX_INO ||
 	    inode->i_ino == EXT2_ACL_DATA_INO)
 		/* Nothing to do */ ;
-	else if (S_ISREG(inode->i_mode))
+	else if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext2_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
+		inode->i_mapping->a_ops = &ext2_aops;
+	} else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &ext2_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = inode->i_blocks
-				?&ext2_symlink_inode_operations
-				:&ext2_fast_symlink_inode_operations;
-	else 
+	else if (S_ISLNK(inode->i_mode)) {
+		if (!inode->i_blocks)
+			inode->i_op = &ext2_fast_symlink_inode_operations;
+		else {
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_mapping->a_ops = &ext2_aops;
+		}
+	} else 
 		init_special_inode(inode, inode->i_mode,
 				   le32_to_cpu(raw_inode->i_block[0]));
 	brelse (bh);
diff -u --recursive --new-file v2.3.42/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.3.42/linux/fs/ext2/namei.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/ext2/namei.c	Thu Feb 10 12:16:58 2000
@@ -384,6 +384,7 @@
 		return err;
 
 	inode->i_op = &ext2_file_inode_operations;
+	inode->i_mapping->a_ops = &ext2_aops;
 	inode->i_mode = mode;
 	mark_inode_dirty(inode);
 	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
@@ -696,7 +697,8 @@
 	inode->i_mode = S_IFLNK | S_IRWXUGO;
 
 	if (l > sizeof (inode->u.ext2_i.i_data)) {
-		inode->i_op = &ext2_symlink_inode_operations;
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_mapping->a_ops = &ext2_aops;
 		err = block_symlink(inode, symname, l);
 		if (err)
 			goto out_no_entry;
diff -u --recursive --new-file v2.3.42/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c
--- v2.3.42/linux/fs/ext2/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/ext2/symlink.c	Thu Feb 10 12:16:58 2000
@@ -1,6 +1,8 @@
 /*
  *  linux/fs/ext2/symlink.c
  *
+ * Only fast symlinks left here - the rest is done by generic code. AV, 1999
+ *
  * Copyright (C) 1992, 1993, 1994, 1995
  * Remy Card (card@masi.ibp.fr)
  * Laboratoire MASI - Institut Blaise Pascal
@@ -16,7 +18,6 @@
  */
 
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
 
 static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
@@ -33,11 +34,4 @@
 struct inode_operations ext2_fast_symlink_inode_operations = {
 	readlink:	ext2_readlink,
 	follow_link:	ext2_follow_link,
-};
-
-struct inode_operations ext2_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
-	get_block:	ext2_get_block,
-	readpage:	block_read_full_page,
 };
diff -u --recursive --new-file v2.3.42/linux/fs/fat/cache.c linux/fs/fat/cache.c
--- v2.3.42/linux/fs/fat/cache.c	Mon Aug  9 11:43:49 1999
+++ linux/fs/fat/cache.c	Thu Feb 10 12:16:58 2000
@@ -283,7 +283,7 @@
 			return 0;
 		return sector+sb->dir_start;
 	}
-	if (sector >= (MSDOS_I(inode)->i_realsize>>9))
+	if (sector >= MSDOS_I(inode)->mmu_private>>9)
 		return 0;
 	cluster = sector/sb->cluster_size;
 	offset = sector % sb->cluster_size;
diff -u --recursive --new-file v2.3.42/linux/fs/fat/dir.c linux/fs/fat/dir.c
--- v2.3.42/linux/fs/fat/dir.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/fat/dir.c	Wed Feb  9 11:42:35 2000
@@ -41,17 +41,10 @@
 }
 
 struct file_operations fat_dir_operations = {
-	NULL,			/* lseek - default */
-	fat_dir_read,		/* read */
-	NULL,			/* write - bad */
-	fat_readdir,		/* readdir */
-	NULL,			/* select v2.0.x/poll v2.1.x - default */
-	fat_dir_ioctl,		/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync		/* fsync */
+	read:		fat_dir_read,
+	readdir:	fat_readdir,
+	ioctl:		fat_dir_ioctl,
+	fsync:		file_fsync,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.3.42/linux/fs/fat/file.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/fat/file.c	Thu Feb 10 12:16:58 2000
@@ -31,17 +31,10 @@
 #define Printk(x) printk x
 
 static struct file_operations fat_file_operations = {
-	NULL,			/* lseek - default */
-	fat_file_read,		/* read */
-	fat_file_write,		/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select v2.0.x/poll v2.1.x - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-	NULL,			/* flush */
-	NULL,			/* release */
-	file_fsync		/* fsync */
+	read:		fat_file_read,
+	write:		fat_file_write,
+	mmap:		generic_file_mmap,
+	fsync:		file_fsync,
 };
 
 struct inode_operations fat_file_inode_operations = {
@@ -57,12 +50,7 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	fat_get_block,		/* get_block */
-	block_read_full_page,	/* readpage */
-	NULL,			/* writepage */
 	fat_truncate,		/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 ssize_t fat_file_read(
@@ -88,7 +76,7 @@
 	}
 	if (!create)
 		return 0;
-	if (iblock<<9 != MSDOS_I(inode)->i_realsize) {
+	if (iblock<<9 != MSDOS_I(inode)->mmu_private) {
 		BUG();
 		return -EIO;
 	}
@@ -96,7 +84,7 @@
 		if (fat_add_cluster(inode))
 			return -ENOSPC;
 	}
-	MSDOS_I(inode)->i_realsize+=SECTOR_SIZE;
+	MSDOS_I(inode)->mmu_private += 512;
 	phys=fat_bmap(inode, iblock);
 	if (!phys)
 		BUG();
@@ -107,30 +95,6 @@
 	return 0;
 }
 
-static int fat_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
-{
-	struct dentry *dentry = file->f_dentry;
-	struct inode *inode = dentry->d_inode;
-	struct page *new_page;
-	unsigned long pgpos;
-	long status;
-
-	while((pgpos=MSDOS_I(inode)->i_realsize>>PAGE_CACHE_SHIFT)<page->index){
-		status = -ENOMEM;
-		new_page = grab_cache_page(&inode->i_data, pgpos);
-		if (!new_page)
-			goto out;
-		status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
-		UnlockPage(new_page);
-		page_cache_release(new_page);
-		if (status < 0)
-			goto out;
-	}
-	status = block_write_cont_page(file, page, offset, bytes, buf);
-out:
-	return status;
-}
-
 ssize_t fat_file_write(
 	struct file *filp,
 	const char *buf,
@@ -152,8 +116,7 @@
 	struct inode *inode = filp->f_dentry->d_inode;
 	int retval;
 
-	retval = generic_file_write(filp, buf, count, ppos,
-					fat_write_partial_page);
+	retval = generic_file_write(filp, buf, count, ppos);
 	if (retval > 0) {
 		inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
@@ -173,7 +136,7 @@
 	if (IS_IMMUTABLE(inode))
 		return /* -EPERM */;
 	cluster = SECTOR_SIZE*sbi->cluster_size;
-	MSDOS_I(inode)->i_realsize = ((inode->i_size-1) | (SECTOR_SIZE-1)) + 1;
+	MSDOS_I(inode)->mmu_private = inode->i_size;
 	fat_free(inode,(inode->i_size+(cluster-1))>>sbi->cluster_bits);
 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
 	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
diff -u --recursive --new-file v2.3.42/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.3.42/linux/fs/fat/inode.c	Mon Dec 20 18:48:22 1999
+++ linux/fs/fat/inode.c	Thu Feb 10 12:16:58 2000
@@ -397,7 +397,7 @@
 		((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) *
 		    sbi->cluster_size;
 	MSDOS_I(inode)->i_logstart = 0;
-	MSDOS_I(inode)->i_realsize = inode->i_size;
+	MSDOS_I(inode)->mmu_private = inode->i_size;
 
 	MSDOS_I(inode)->i_attrs = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
@@ -746,6 +746,31 @@
 	return 0;
 }
 
+static int fat_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,fat_get_block);
+}
+static int fat_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,fat_get_block);
+}
+static int fat_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page,from,to,fat_get_block,
+		&MSDOS_I((struct inode*)page->mapping->host)->mmu_private);
+}
+static int _fat_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,fat_get_block);
+}
+static struct address_space_operations fat_aops = {
+	readpage: fat_readpage,
+	writepage: fat_writepage,
+	prepare_write: fat_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: _fat_bmap
+};
+
 /* doesn't deal with root inode */
 static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 {
@@ -788,7 +813,7 @@
 					break;
 				}
 			}
-		MSDOS_I(inode)->i_realsize = inode->i_size;
+		MSDOS_I(inode)->mmu_private = inode->i_size;
 	} else { /* not a directory */
 		inode->i_mode = MSDOS_MKMODE(de->attr,
 		    ((IS_NOEXEC(inode) || 
@@ -796,7 +821,6 @@
 		       !is_exec(de->ext)))
 		    	? S_IRUGO|S_IWUGO : S_IRWXUGO)
 		    & ~sbi->options.fs_umask) | S_IFREG;
-	        inode->i_op = &fat_file_inode_operations;
 		MSDOS_I(inode)->i_start = CF_LE_W(de->start);
 		if (sbi->fat_bits == 32) {
 			MSDOS_I(inode)->i_start |=
@@ -805,7 +829,9 @@
 		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
 		inode->i_nlink = 1;
 		inode->i_size = CF_LE_L(de->size);
-		MSDOS_I(inode)->i_realsize = ((inode->i_size-1)|(SECTOR_SIZE-1))+1;
+	        inode->i_op = &fat_file_inode_operations;
+		inode->i_mapping->a_ops = &fat_aops;
+		MSDOS_I(inode)->mmu_private = inode->i_size;
 	}
 	if(de->attr & ATTR_SYS)
 		if (sbi->options.sys_immutable)
diff -u --recursive --new-file v2.3.42/linux/fs/fat/misc.c linux/fs/fat/misc.c
--- v2.3.42/linux/fs/fat/misc.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/fat/misc.c	Thu Feb 10 12:16:58 2000
@@ -311,7 +311,7 @@
 		    ~(SECTOR_SIZE-1);
 	}
 	inode->i_size += SECTOR_SIZE*cluster_size;
-	MSDOS_I(inode)->i_realsize += SECTOR_SIZE*cluster_size;
+	MSDOS_I(inode)->mmu_private += SECTOR_SIZE*cluster_size;
 	mark_inode_dirty(inode);
 	return res;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/fifo.c linux/fs/fifo.c
--- v2.3.42/linux/fs/fifo.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/fifo.c	Wed Feb  9 11:42:35 2000
@@ -153,7 +153,7 @@
  * depending on the access mode of the file...
  */
 static struct file_operations def_fifo_fops = {
-	open:	fifo_open,	/* will set read or write pipe_fops */
+	open:		fifo_open,	/* will set read or write pipe_fops */
 };
 
 struct inode_operations fifo_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c
--- v2.3.42/linux/fs/hfs/dir_cap.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/hfs/dir_cap.c	Thu Feb 10 12:16:58 2000
@@ -58,18 +58,9 @@
 #define DOT_ROOTINFO	(&hfs_cap_reserved2[0])
 
 static struct file_operations hfs_cap_dir_operations = {
-	NULL,			/* lseek - default */
-	hfs_dir_read,		/* read - invalid */
-	NULL,			/* write - bad */
-	cap_readdir,		/* readdir */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap - none */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync,		/* fsync - default */
-	NULL,			/* fasync - default */
+	read:		hfs_dir_read,
+	readdir:	cap_readdir,
+	fsync:		file_fsync,
 };
 
 struct inode_operations hfs_cap_ndir_inode_operations = {
@@ -83,56 +74,18 @@
 	hfs_rmdir,		/* rmdir */
 	NULL,			/* mknod */
 	hfs_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 struct inode_operations hfs_cap_fdir_inode_operations = {
 	&hfs_cap_dir_operations,/* default directory file-ops */
 	NULL,			/* create */
 	cap_lookup,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 struct inode_operations hfs_cap_rdir_inode_operations = {
 	&hfs_cap_dir_operations,/* default directory file-ops */
 	hfs_create,		/* create */
 	cap_lookup,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 /*================ File-local functions ================*/
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c
--- v2.3.42/linux/fs/hfs/dir_dbl.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/hfs/dir_dbl.c	Thu Feb 10 12:16:58 2000
@@ -57,18 +57,9 @@
 #define PCNT_ROOTINFO	(&hfs_dbl_reserved2[1])
 
 static struct file_operations hfs_dbl_dir_operations = {
-	NULL,			/* lseek - default */
-	hfs_dir_read,		/* read - invalid */
-	NULL,			/* write - bad */
-	dbl_readdir,		/* readdir */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap - none */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync,		/* fsync - default */
-        NULL,			/* fasync - default */
+	read:		hfs_dir_read,
+	readdir:	dbl_readdir,
+	fsync:		file_fsync,
 };
 
 struct inode_operations hfs_dbl_dir_inode_operations = {
@@ -82,14 +73,6 @@
 	dbl_rmdir,		/* rmdir */
 	NULL,			/* mknod */
 	dbl_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c
--- v2.3.42/linux/fs/hfs/dir_nat.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/hfs/dir_nat.c	Thu Feb 10 12:16:58 2000
@@ -63,19 +63,9 @@
 #define ROOTINFO        (&hfs_nat_reserved2[0])
 
 static struct file_operations hfs_nat_dir_operations = {
-	NULL,			/* lseek - default */
-	hfs_dir_read,		/* read - invalid */
-	NULL,			/* write - bad */
-	nat_readdir,		/* readdir */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap - none */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync,		/* fsync - default */
-        NULL,			/* fasync - default */
-	NULL                    /* lock - none */
+	read:		hfs_dir_read,
+	readdir:	nat_readdir,
+	fsync:		file_fsync,
 };
 
 struct inode_operations hfs_nat_ndir_inode_operations = {
@@ -89,14 +79,6 @@
 	nat_rmdir,		/* rmdir */
 	NULL,			/* mknod */
 	hfs_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL                    /* revalidate */
 };
 
 struct inode_operations hfs_nat_hdir_inode_operations = {
@@ -110,14 +92,6 @@
 	NULL,			/* rmdir */
 	NULL,			/* mknod */
 	nat_hdr_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL                    /* revalidate */
 };
 
 /*================ File-local functions ================*/
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/file.c linux/fs/hfs/file.c
--- v2.3.42/linux/fs/hfs/file.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/hfs/file.c	Thu Feb 10 12:16:58 2000
@@ -28,24 +28,14 @@
 static hfs_rwret_t hfs_file_write(struct file *, const char *, hfs_rwarg_t,
 				  loff_t *);
 static void hfs_file_truncate(struct inode *);
-static int hfs_get_block(struct inode *, long, struct buffer_head *, int);
 
 /*================ Global variables ================*/
 
 static struct file_operations hfs_file_operations = {
-	NULL,			/* lseek - default */
-	hfs_file_read,		/* read */
-	hfs_file_write,		/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	file_fsync,		/* fsync - default */
-        NULL,			/* fasync - default */
-        NULL			/* lock - none */
+	read:		hfs_file_read,
+	write:		hfs_file_write,
+	mmap:		generic_file_mmap,
+	fsync:		file_fsync,
 };
 
 struct inode_operations hfs_file_inode_operations = {
@@ -61,12 +51,7 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	hfs_get_block,		/* get_block */
-	block_read_full_page,	/* readpage */
-	NULL,			/* writepage */
 	hfs_file_truncate,	/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 /*================ Variable-like macros ================*/
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/file_cap.c linux/fs/hfs/file_cap.c
--- v2.3.42/linux/fs/hfs/file_cap.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/hfs/file_cap.c	Thu Feb 10 12:16:58 2000
@@ -47,19 +47,9 @@
 /*================ Global variables ================*/
 
 static struct file_operations hfs_cap_info_operations = {
-	NULL,			/* lseek - default */
-	cap_info_read,		/* read */
-	cap_info_write,		/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap - not yet */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync,		/* fsync - default */
-	NULL,			/* fasync - default */
-	NULL			/* lock - none */
+	read:		cap_info_read,
+	write:		cap_info_write,
+	fsync:		file_fsync,
 };
 
 struct inode_operations hfs_cap_info_inode_operations = {
@@ -75,12 +65,7 @@
 	NULL,				/* rename */
 	NULL,				/* readlink */
 	NULL,				/* follow_link */
-	NULL,				/* get_block - none */
-	NULL,				/* readpage */
-	NULL,				/* writepage */
 	cap_info_truncate,		/* truncate */
-	NULL,				/* permission */
-	NULL				/* revalidata */
 };
 
 /*================ File-local functions ================*/
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- v2.3.42/linux/fs/hfs/file_hdr.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/hfs/file_hdr.c	Thu Feb 10 12:16:58 2000
@@ -48,19 +48,9 @@
 /*================ Global variables ================*/
 
 static struct file_operations hfs_hdr_operations = {
-	NULL,			/* lseek - default */
-	hdr_read,		/* read */
-	hdr_write,		/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap - XXX: not yet */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync,		/* fsync - default */
-        NULL,			/* fasync - default */
-        NULL			/* lock - none */
+	read:		hdr_read,
+	write:		hdr_write,
+	fsync:		file_fsync,
 };
 
 struct inode_operations hfs_hdr_inode_operations = {
@@ -76,13 +66,7 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block - XXX: not available since
-				   header part has no disk block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	hdr_truncate,		/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/hfs.h linux/fs/hfs/hfs.h
--- v2.3.42/linux/fs/hfs/hfs.h	Wed May 12 13:26:20 1999
+++ linux/fs/hfs/hfs.h	Thu Feb 10 12:16:58 2000
@@ -494,6 +494,9 @@
 extern void hfs_extent_adj(struct hfs_fork *);
 extern void hfs_extent_free(struct hfs_fork *);
 
+/* file.c */
+extern int hfs_get_block(struct inode *, long, struct buffer_head *, int);
+
 /* mdb.c */
 extern struct hfs_mdb *hfs_mdb_get(hfs_sysmdb, int, hfs_s32);
 extern void hfs_mdb_commit(struct hfs_mdb *, int);
diff -u --recursive --new-file v2.3.42/linux/fs/hfs/inode.c linux/fs/hfs/inode.c
--- v2.3.42/linux/fs/hfs/inode.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/hfs/inode.c	Thu Feb 10 12:16:58 2000
@@ -184,6 +184,31 @@
 	return 0;
 }
 
+static int hfs_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,hfs_get_block);
+}
+static int hfs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,hfs_get_block);
+}
+static int hfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page,from,to,hfs_get_block,
+		&((struct inode*)page->mapping->host)->u.hfs_i.mmu_private);
+}
+static int hfs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,hfs_get_block);
+}
+struct address_space_operations hfs_aops = {
+	readpage: hfs_readpage,
+	writepage: hfs_writepage,
+	prepare_write: hfs_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: hfs_bmap
+};
+
 /*
  * __hfs_iget()
  *
@@ -308,6 +333,8 @@
 		init_file_inode(inode, (type == HFS_CAP_DATA) ?
 						HFS_FK_DATA : HFS_FK_RSRC);
 		inode->i_op = &hfs_file_inode_operations;
+		inode->i_mapping->a_ops = &hfs_aops;
+		inode->u.hfs_i.mmu_private = inode->i_size;
 	} else { /* Directory */
 		struct hfs_dir *hdir = &entry->u.dir;
 
@@ -361,6 +388,8 @@
 	} else if (entry->type == HFS_CDR_FIL) {
 		init_file_inode(inode, HFS_FK_DATA);
 		inode->i_op = &hfs_file_inode_operations;
+		inode->i_mapping->a_ops = &hfs_aops;
+		inode->u.hfs_i.mmu_private = inode->i_size;
 	} else { /* Directory */
 		struct hfs_dir *hdir = &entry->u.dir;
 
@@ -402,6 +431,8 @@
 	} else if (entry->type == HFS_CDR_FIL) {
 		init_file_inode(inode, HFS_FK_DATA);
 		inode->i_op = &hfs_file_inode_operations;
+		inode->i_mapping->a_ops = &hfs_aops;
+		inode->u.hfs_i.mmu_private = inode->i_size;
 	} else { /* Directory */
 		struct hfs_dir *hdir = &entry->u.dir;
 
diff -u --recursive --new-file v2.3.42/linux/fs/hpfs/dir.c linux/fs/hpfs/dir.c
--- v2.3.42/linux/fs/hpfs/dir.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/hpfs/dir.c	Thu Feb 10 12:16:58 2000
@@ -8,7 +8,7 @@
 
 #include "hpfs_fn.h"
 
-int hpfs_dir_read(struct file *filp, char *name, size_t len, loff_t *loff)
+ssize_t hpfs_dir_read(struct file *filp, char *name, size_t len, loff_t *loff)
 {
 	return -EISDIR;
 }
@@ -242,6 +242,8 @@
 		if (!de->directory) {
 			if (result->i_size == -1) {
 				result->i_size = de->file_size;
+				result->i_data.a_ops = &hpfs_aops;
+				result->u.hpfs_i.mmu_private = result->i_size;
 			/*
 			 * i_blocks should count the fnode and any anodes.
 			 * We count 1 for the fnode and don't bother about
diff -u --recursive --new-file v2.3.42/linux/fs/hpfs/file.c linux/fs/hpfs/file.c
--- v2.3.42/linux/fs/hpfs/file.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/hpfs/file.c	Thu Feb 10 12:16:58 2000
@@ -54,6 +54,7 @@
 	if (IS_IMMUTABLE(i)) return /*-EPERM*/;
 	i->i_hpfs_n_secs = 0;
 	i->i_blocks = 1 + ((i->i_size + 511) >> 9);
+	i->u.hpfs_i.mmu_private = i->i_size;
 	hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
 	hpfs_write_inode(i);
 }
@@ -61,63 +62,60 @@
 int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
 {
 	secno s;
-	if (iblock < inode->i_blocks - 1) {
-		s = hpfs_bmap(inode, iblock);
+	s = hpfs_bmap(inode, iblock);
+	if (s) {
 		bh_result->b_dev = inode->i_dev;
 		bh_result->b_blocknr = s;
 		bh_result->b_state |= (1UL << BH_Mapped);
 		return 0;
 	}
 	if (!create) return 0;
-	if (iblock > inode->i_blocks - 1) {
-		//hpfs_error(inode->i_sb, "hpfs_get_block beyond file end (requested %08x, inode size %08x", (int)iblock, (int)inode->i_blocks - 1);
-		printk("HPFS: could not write beyond file end. This is known bug.\n");
-		return -EFSERROR;
+	if (iblock<<9 != inode->u.hpfs_i.mmu_private) {
+		BUG();
+		return -EIO;
 	}
 	if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {
 		hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1);
 		return -ENOSPC;
 	}
 	inode->i_blocks++;
+	inode->u.hpfs_i.mmu_private += 512;
 	bh_result->b_dev = inode->i_dev;
 	bh_result->b_blocknr = s;
 	bh_result->b_state |= (1UL << BH_Mapped) | (1UL << BH_New);
 	return 0;
 }
 
-static int hpfs_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int hpfs_writepage(struct dentry *dentry, struct page *page)
 {
-	struct dentry *dentry = file->f_dentry;
-	struct inode *inode = dentry->d_inode;
-	struct page *new_page;
-	unsigned long pgpos;
-	long status;
-
-	pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
-	while (pgpos < page->index) {
-		status = -ENOMEM;
-		new_page = grab_cache_page(&inode->i_data, pgpos);
-		if (!new_page)
-			goto out;
-		status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
-		UnlockPage(new_page);
-		page_cache_release(new_page);
-		if (status < 0)
-			goto out;
-		pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
-	}
-	status = block_write_cont_page(file, page, offset, bytes, buf);
-out:
-	return status;
+	return block_write_full_page(page,hpfs_get_block);
 }
-
+static int hpfs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,hpfs_get_block);
+}
+static int hpfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page,from,to,hpfs_get_block,
+		&((struct inode*)page->mapping->host)->u.hpfs_i.mmu_private);
+}
+static int _hpfs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,hpfs_get_block);
+}
+struct address_space_operations hpfs_aops = {
+	readpage: hpfs_readpage,
+	writepage: hpfs_writepage,
+	prepare_write: hpfs_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: _hpfs_bmap
+};
 
 ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
 	ssize_t retval;
 
-	retval = generic_file_write(file, buf, count,
-				    ppos, hpfs_write_partial_page);
+	retval = generic_file_write(file, buf, count, ppos);
 	if (retval > 0) {
 		struct inode *inode = file->f_dentry->d_inode;
 		inode->i_mtime = CURRENT_TIME;
diff -u --recursive --new-file v2.3.42/linux/fs/hpfs/hpfs_fn.h linux/fs/hpfs/hpfs_fn.h
--- v2.3.42/linux/fs/hpfs/hpfs_fn.h	Fri Jan 28 15:09:08 2000
+++ linux/fs/hpfs/hpfs_fn.h	Thu Feb 10 12:16:58 2000
@@ -224,7 +224,7 @@
 
 /* dir.c */
 
-int hpfs_dir_read(struct file *, char *, size_t, loff_t *);
+ssize_t hpfs_dir_read(struct file *, char *, size_t, loff_t *);
 int hpfs_dir_release(struct inode *, struct file *);
 loff_t hpfs_dir_lseek(struct file *, loff_t, int);
 int hpfs_readdir(struct file *, void *, filldir_t);
@@ -314,3 +314,5 @@
 unsigned hpfs_count_one_bitmap(struct super_block *, secno);
 int hpfs_statfs(struct super_block *, struct statfs *, int);
 struct super_block *hpfs_read_super(struct super_block *, void *, int);
+
+extern struct address_space_operations hpfs_aops;
diff -u --recursive --new-file v2.3.42/linux/fs/hpfs/inode.c linux/fs/hpfs/inode.c
--- v2.3.42/linux/fs/hpfs/inode.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/hpfs/inode.c	Thu Feb 10 12:16:58 2000
@@ -10,19 +10,12 @@
 
 static const struct file_operations hpfs_file_ops =
 {
-	NULL,				/* lseek - default */
-	generic_file_read,		/* read */
-	hpfs_file_write,		/* write */
-	NULL,				/* readdir - bad */
-	NULL,				/* poll - default */
-	NULL,				/* ioctl - default */
-	generic_file_mmap,		/* mmap */
-	hpfs_open,			/* open */
-	NULL,				/* flush */
-	hpfs_file_release,		/* release */
-	hpfs_file_fsync,		/* fsync */
-	NULL,				/* fasync */
-	NULL,				/* lock */
+	read:		generic_file_read,
+	write:		hpfs_file_write,
+	mmap:		generic_file_mmap,
+	open:		hpfs_open,
+	release:	hpfs_file_release,
+	fsync:		hpfs_file_fsync,
 };
 
 static const struct inode_operations hpfs_file_iops =
@@ -39,29 +32,17 @@
 	NULL,				/* rename */
 	NULL,				/* readlink */
 	NULL,				/* follow_link */
-	&hpfs_get_block,		/* get_block */
-	block_read_full_page,		/* readpage */
-	block_write_full_page,		/* writepage */
 	hpfs_truncate,			/* truncate */
-	NULL,				/* permission */
-	NULL,				/* revalidate */
 };
 
 static const struct file_operations hpfs_dir_ops =
 {
-	hpfs_dir_lseek,			/* lseek */
-	hpfs_dir_read,			/* read */
-	NULL,				/* write - bad */
-	hpfs_readdir,			/* readdir */
-	NULL,				/* poll - default */
-	NULL,				/* ioctl - default */
-	NULL,				/* mmap */
-	hpfs_open,			/* open */
-	NULL,				/* flush */
-	hpfs_dir_release,		/* no special release code */
-	hpfs_file_fsync,		/* fsync */
-	NULL,				/* fasync */
-	NULL,				/* lock */
+	llseek:		hpfs_dir_lseek,
+	read:		hpfs_dir_read,
+	readdir:	hpfs_readdir,
+	open:		hpfs_open,
+	release:	hpfs_dir_release,
+	fsync:		hpfs_file_fsync,
 };
 
 static const struct inode_operations hpfs_dir_iops =
@@ -76,20 +57,9 @@
 	hpfs_rmdir,			/* rmdir */
 	hpfs_mknod,			/* mknod */
 	hpfs_rename,			/* rename */
-	NULL,				/* readlink */
-	NULL,				/* follow_link */
-	NULL,				/* get_block */
-	NULL,				/* readpage */
-	NULL,				/* writepage */
-	NULL,				/* truncate */
-	NULL,				/* permission */
-	NULL				/* revalidate */
 };
 
-const struct inode_operations hpfs_symlink_iops =
-{
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
+struct address_space_operations hpfs_symlink_aops = {
 	readpage:	hpfs_symlink_readpage
 };
 
@@ -164,7 +134,8 @@
 		if ((ea = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &ea_size))) {
 			kfree(ea);
 			i->i_mode = S_IFLNK | 0777;
-			i->i_op = (struct inode_operations *) &hpfs_symlink_iops;
+			i->i_op = &page_symlink_inode_operations;
+			i->i_data.a_ops = &hpfs_symlink_aops;
 			i->i_nlink = 1;
 			i->i_size = ea_size;
 			i->i_blocks = 1;
@@ -219,6 +190,8 @@
 		i->i_nlink = 1;
 		i->i_size = fnode->file_size;
 		i->i_blocks = ((i->i_size + 511) >> 9) + 1;
+		i->i_data.a_ops = &hpfs_aops;
+		i->u.hpfs_i.mmu_private = i->i_size;
 	}
 	brelse(bh);
 }
diff -u --recursive --new-file v2.3.42/linux/fs/hpfs/namei.c linux/fs/hpfs/namei.c
--- v2.3.42/linux/fs/hpfs/namei.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/hpfs/namei.c	Thu Feb 10 12:16:58 2000
@@ -138,7 +138,11 @@
 		result->i_hpfs_ea_size = 0;
 		if (dee.read_only) result->i_mode &= ~0222;
 		if (result->i_blocks == -1) result->i_blocks = 1;
-		if (result->i_size == -1) result->i_size = 0;
+		if (result->i_size == -1) {
+			result->i_size = 0;
+			result->i_data.a_ops = &hpfs_aops;
+			result->u.hpfs_i.mmu_private = 0;
+		}
 		if (result->i_uid != current->fsuid ||
 		    result->i_gid != current->fsgid ||
 		    result->i_mode != (mode | S_IFREG)) {
@@ -221,7 +225,7 @@
 	return -ENOSPC;
 }
 
-extern const struct inode_operations hpfs_symlink_iops;
+extern struct address_space_operations hpfs_symlink_aops;
 
 int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
 {
@@ -268,7 +272,8 @@
 		result->i_gid = current->fsgid;
 		result->i_blocks = 1;
 		result->i_size = strlen(symlink);
-		result->i_op = (struct inode_operations *) &hpfs_symlink_iops;
+		result->i_op = &page_symlink_inode_operations;
+		result->i_data.a_ops = &hpfs_symlink_aops;
 		if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) {
 			hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
 			mark_buffer_dirty(bh, 1);
diff -u --recursive --new-file v2.3.42/linux/fs/inode.c linux/fs/inode.c
--- v2.3.42/linux/fs/inode.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/inode.c	Thu Feb 10 12:16:58 2000
@@ -474,6 +474,8 @@
 	memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
 	inode->i_pipe = NULL;
 	inode->i_bdev = NULL;
+	inode->i_mapping = &inode->i_data;
+	inode->i_mapping->host = (void*)inode;
 }
 
 /*
@@ -719,15 +721,10 @@
 
 int bmap(struct inode * inode, int block)
 {
-	struct buffer_head tmp;
-
-	if (inode->i_op && inode->i_op->get_block) {
-		tmp.b_state = 0;
-		tmp.b_blocknr = 0;
-		inode->i_op->get_block(inode, block, &tmp, 0);
-		return tmp.b_blocknr;
-	}
-	return 0;
+	int res = 0;
+	if (inode->i_mapping->a_ops->bmap)
+		res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
+	return res;
 }
 
 /*
diff -u --recursive --new-file v2.3.42/linux/fs/ioctl.c linux/fs/ioctl.c
--- v2.3.42/linux/fs/ioctl.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/ioctl.c	Thu Feb 10 12:16:58 2000
@@ -19,21 +19,18 @@
 	switch (cmd) {
 		case FIBMAP:
 		{
-			struct buffer_head tmp;
-
-			if (inode->i_op == NULL)
-				return -EBADF;
-		    	if (inode->i_op->get_block == NULL)
+			struct address_space *mapping = inode->i_mapping;
+			int res;
+			/* do we support this mess? */
+			if (!mapping->a_ops->bmap)
 				return -EINVAL;
 			if (!capable(CAP_SYS_RAWIO))
 				return -EPERM;
 			if ((error = get_user(block, (int *) arg)) != 0)
 				return error;
 
-			tmp.b_state = 0;
-			tmp.b_blocknr = 0;
-			inode->i_op->get_block(inode, block, &tmp, 0);
-			return put_user(tmp.b_blocknr, (int *) arg);
+			res = mapping->a_ops->bmap(mapping, block);
+			return put_user(res, (int *) arg);
 		}
 		case FIGETBSZ:
 			if (inode->i_sb == NULL)
diff -u --recursive --new-file v2.3.42/linux/fs/isofs/Makefile linux/fs/isofs/Makefile
--- v2.3.42/linux/fs/isofs/Makefile	Wed Jun 24 14:30:10 1998
+++ linux/fs/isofs/Makefile	Thu Feb 10 12:16:58 2000
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
 O_TARGET := isofs.o
-O_OBJS   := namei.o inode.o file.o dir.o util.o rock.o symlink.o
+O_OBJS   := namei.o inode.o file.o dir.o util.o rock.o
 
 ifdef CONFIG_JOLIET
 O_OBJS += joliet.o
diff -u --recursive --new-file v2.3.42/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v2.3.42/linux/fs/isofs/dir.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/isofs/dir.c	Thu Feb 10 12:16:58 2000
@@ -28,16 +28,7 @@
 
 static struct file_operations isofs_dir_operations =
 {
-	NULL,			/* lseek - default */
-	NULL,			/* read */
-	NULL,			/* write - bad */
-	isofs_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* fsync */
+	readdir:	isofs_readdir,
 };
 
 /*
@@ -48,21 +39,6 @@
 	&isofs_dir_operations,	/* default directory file-ops */
 	NULL,			/* create */
 	isofs_lookup,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static int isofs_name_translate(char * old, int len, char * new)
diff -u --recursive --new-file v2.3.42/linux/fs/isofs/file.c linux/fs/isofs/file.c
--- v2.3.42/linux/fs/isofs/file.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/isofs/file.c	Thu Feb 10 12:16:58 2000
@@ -22,36 +22,10 @@
  * the isofs filesystem.
  */
 static struct file_operations isofs_file_operations = {
-	NULL,			/* lseek - default */
-	generic_file_read,	/* read */
-	NULL,			/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL			/* fsync */
+	read:		generic_file_read,
+	mmap:		generic_file_mmap,
 };
 
 struct inode_operations isofs_file_inode_operations = {
 	&isofs_file_operations,	/* default file operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	isofs_get_block,	/* get_block */
-	block_read_full_page,	/* readpage */
-	NULL,			/* writepage */
-	NULL,	       		/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
diff -u --recursive --new-file v2.3.42/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.3.42/linux/fs/isofs/inode.c	Thu Jan  6 12:57:48 2000
+++ linux/fs/isofs/inode.c	Thu Feb 10 12:16:58 2000
@@ -1006,6 +1006,19 @@
 	return 0;
 }
 
+static int isofs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,isofs_get_block);
+}
+static int _isofs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,isofs_get_block);
+}
+static struct address_space_operations isofs_aops = {
+	readpage: isofs_readpage,
+	bmap: _isofs_bmap
+};
+
 static void test_and_set_uid(uid_t *p, uid_t value)
 {
 	if(value) {
@@ -1254,13 +1267,15 @@
 	} else
 #endif IGNORE_WRONG_MULTI_VOLUME_SPECS
 	{
-	  if (S_ISREG(inode->i_mode))
+	  if (S_ISREG(inode->i_mode)) {
 	    inode->i_op = &isofs_file_inode_operations;
-	  else if (S_ISDIR(inode->i_mode))
+	    inode->i_data.a_ops = &isofs_aops;
+	  } else if (S_ISDIR(inode->i_mode))
 	    inode->i_op = &isofs_dir_inode_operations;
-	  else if (S_ISLNK(inode->i_mode))
-	    inode->i_op = &isofs_symlink_inode_operations;
-	  else
+	  else if (S_ISLNK(inode->i_mode)) {
+	    inode->i_op = &page_symlink_inode_operations;
+	    inode->i_data.a_ops = &isofs_symlink_aops;
+	  } else
 	    /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
 	    init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev));
 	}
diff -u --recursive --new-file v2.3.42/linux/fs/isofs/rock.c linux/fs/isofs/rock.c
--- v2.3.42/linux/fs/isofs/rock.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/isofs/rock.c	Thu Feb 10 12:16:58 2000
@@ -445,7 +445,7 @@
 /* readpage() for symlinks: reads symlink contents into the page and either
    makes it uptodate and returns 0 or returns error (-EIO) */
 
-int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page)
+static int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page)
 {
 	struct inode *inode = dentry->d_inode;
 	char *link = (char*)kmap(page);
@@ -540,3 +540,7 @@
 	UnlockPage(page);
 	return -EIO;
 }
+
+struct address_space_operations isofs_symlink_aops = {
+	readpage:	rock_ridge_symlink_readpage
+};
diff -u --recursive --new-file v2.3.42/linux/fs/isofs/symlink.c linux/fs/isofs/symlink.c
--- v2.3.42/linux/fs/isofs/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/isofs/symlink.c	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-/*
- *  linux/fs/isofs/symlink.c
- *
- *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  isofs symlink handling code.  This is only used with the Rock Ridge
- *  extensions to iso9660
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/iso_fs.h>
-#include <linux/stat.h>
-#include <linux/malloc.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations isofs_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
-	readpage:	rock_ridge_symlink_readpage
-};
diff -u --recursive --new-file v2.3.42/linux/fs/lockd/svc.c linux/fs/lockd/svc.c
--- v2.3.42/linux/fs/lockd/svc.c	Thu May 13 14:53:04 1999
+++ linux/fs/lockd/svc.c	Thu Feb 10 12:16:38 2000
@@ -308,13 +308,13 @@
 
 #ifdef MODULE
 /* New module support in 2.1.18 */
-#if LINUX_VERSION_CODE >= 0x020112
-  EXPORT_NO_SYMBOLS;
-  MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
-  MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
-  MODULE_PARM(nlm_grace_period, "10-240l");
-  MODULE_PARM(nlm_timeout, "3-20l");
-#endif
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
+MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
+MODULE_PARM(nlm_grace_period, "10-240l");
+MODULE_PARM(nlm_timeout, "3-20l");
+
 int
 init_module(void)
 {
diff -u --recursive --new-file v2.3.42/linux/fs/lockd/xdr.c linux/fs/lockd/xdr.c
--- v2.3.42/linux/fs/lockd/xdr.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/lockd/xdr.c	Mon Feb  7 19:45:28 2000
@@ -95,8 +95,8 @@
 
 	if ((len = ntohl(*p++)) != sizeof(*f)) {
 		printk(KERN_NOTICE
-			"lockd: bad fhandle size %u (should be %lu)\n",
-			len, (unsigned long) sizeof(*f));
+			"lockd: bad fhandle size %x (should be %Zu)\n",
+			len, sizeof(*f));
 		return NULL;
 	}
 	memcpy(f, p, sizeof(*f));
diff -u --recursive --new-file v2.3.42/linux/fs/minix/Makefile linux/fs/minix/Makefile
--- v2.3.42/linux/fs/minix/Makefile	Wed Jun 24 14:30:10 1998
+++ linux/fs/minix/Makefile	Thu Feb 10 12:16:58 2000
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
 O_TARGET := minix.o
-O_OBJS   := bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o
+O_OBJS   := bitmap.o truncate.o namei.o inode.o file.o dir.o fsync.o
 M_OBJS   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/fs/minix/dir.c linux/fs/minix/dir.c
--- v2.3.42/linux/fs/minix/dir.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/minix/dir.c	Thu Feb 10 12:16:58 2000
@@ -23,17 +23,9 @@
 static int minix_readdir(struct file *, void *, filldir_t);
 
 static struct file_operations minix_dir_operations = {
-	NULL,			/* lseek - default */
-	minix_dir_read,		/* read */
-	NULL,			/* write - bad */
-	minix_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync		/* default fsync */
+	read:		minix_dir_read,
+	readdir:	minix_readdir,
+	fsync:		file_fsync,
 };
 
 /*
@@ -50,14 +42,6 @@
 	minix_rmdir,		/* rmdir */
 	minix_mknod,		/* mknod */
 	minix_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static int minix_readdir(struct file * filp,
diff -u --recursive --new-file v2.3.42/linux/fs/minix/file.c linux/fs/minix/file.c
--- v2.3.42/linux/fs/minix/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/minix/file.c	Thu Feb 10 12:16:58 2000
@@ -18,60 +18,21 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#define	NBUF	32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
 
 /*
- * Write to a file (through the page cache).
- */
-static ssize_t
-minix_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	return generic_file_write(file, buf, count,
-				  ppos, block_write_partial_page);
-}
-
-/*
  * We have mostly NULLs here: the current defaults are OK for
  * the minix filesystem.
  */
 static struct file_operations minix_file_operations = {
-	NULL,			/* lseek - default */
-	generic_file_read,	/* read */
-	minix_file_write,	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-	NULL,			/* flush */
-	NULL,			/* release */
-	minix_sync_file,	/* fsync */
-	NULL,			/* fasync */
+	read:		generic_file_read,
+	write:		generic_file_write,
+	mmap:		generic_file_mmap,
+	fsync:		minix_sync_file,
 };
 
 struct inode_operations minix_file_inode_operations = {
-	&minix_file_operations,	/* default file operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	minix_get_block,	/* get_block */
-	block_read_full_page,	/* readpage */
-	block_write_full_page,	/* writepage */
-	minix_truncate,		/* truncate */
-	NULL,			/* permission */
-	NULL,			/* revalidate */
+	&minix_file_operations,
+	truncate:	minix_truncate,
 };
diff -u --recursive --new-file v2.3.42/linux/fs/minix/fsync.c linux/fs/minix/fsync.c
--- v2.3.42/linux/fs/minix/fsync.c	Tue Jun 29 09:22:08 1999
+++ linux/fs/minix/fsync.c	Wed Feb  9 18:52:20 2000
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/locks.h>
+#include <linux/smp_lock.h>
 
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
@@ -148,10 +149,7 @@
 {
 	int wait, err = 0;
 	
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	     S_ISLNK(inode->i_mode)))
-		return -EINVAL;
-
+	lock_kernel();
 	for (wait=0; wait<=1; wait++)
 	{
 		err |= V1_sync_direct(inode, wait);
@@ -159,6 +157,7 @@
 		err |= V1_sync_dindirect(inode, inode->u.minix_i.u.i1_data + 8, wait);
 	}
 	err |= minix_sync_inode (inode);
+	unlock_kernel();
 	return (err < 0) ? -EIO : 0;
 }
 
@@ -309,10 +308,7 @@
 {
 	int wait, err = 0;
 	
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	     S_ISLNK(inode->i_mode)))
-		return -EINVAL;
-
+	lock_kernel();
 	for (wait=0; wait<=1; wait++)
 	{
 		err |= V2_sync_direct(inode, wait);
@@ -324,6 +320,7 @@
 		      (unsigned long *) inode->u.minix_i.u.i2_data + 9, wait);
 	}
 	err |= minix_sync_inode (inode);
+	unlock_kernel();
 	return (err < 0) ? -EIO : 0;
 }
 
@@ -336,6 +333,10 @@
 {
 	struct inode *inode = dentry->d_inode;
 	
+	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+	     S_ISLNK(inode->i_mode)))
+		return -EINVAL;
+
 	if (INODE_VERSION(inode) == MINIX_V1)
 		return V1_minix_sync_file(inode, file);
 	else
diff -u --recursive --new-file v2.3.42/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.3.42/linux/fs/minix/inode.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/minix/inode.c	Thu Feb 10 12:16:58 2000
@@ -968,7 +968,7 @@
 	goto abort;
 }
 
-int minix_get_block(struct inode *inode, long block,
+static int minix_get_block(struct inode *inode, long block,
 		    struct buffer_head *bh_result, int create)
 {
 	if (INODE_VERSION(inode) == MINIX_V1)
@@ -1016,6 +1016,30 @@
 	return NULL;
 }
 
+static int minix_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,minix_get_block);
+}
+static int minix_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,minix_get_block);
+}
+static int minix_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page,from,to,minix_get_block);
+}
+static int minix_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,minix_get_block);
+}
+struct address_space_operations minix_aops = {
+	readpage: minix_readpage,
+	writepage: minix_writepage,
+	prepare_write: minix_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: minix_bmap
+};
+
 /*
  * The minix V1 function to read an inode.
  */
@@ -1053,13 +1077,15 @@
 	inode->i_blocks = inode->i_blksize = 0;
 	for (block = 0; block < 9; block++)
 		inode->u.minix_i.u.i1_data[block] = raw_inode->i_zone[block];
-	if (S_ISREG(inode->i_mode))
+	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &minix_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
+		inode->i_mapping->a_ops = &minix_aops;
+	} else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &minix_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &minix_symlink_inode_operations;
-	else
+	else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_mapping->a_ops = &minix_aops;
+	} else
 		init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
 	brelse(bh);
 }
@@ -1103,13 +1129,15 @@
 	inode->i_blocks = inode->i_blksize = 0;
 	for (block = 0; block < 10; block++)
 		inode->u.minix_i.u.i2_data[block] = raw_inode->i_zone[block];
-	if (S_ISREG(inode->i_mode))
+	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &minix_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
+		inode->i_mapping->a_ops = &minix_aops;
+	} else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &minix_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &minix_symlink_inode_operations;
-	else
+	else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_mapping->a_ops = &minix_aops;
+	} else
 		init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
 	brelse(bh);
 }
diff -u --recursive --new-file v2.3.42/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.3.42/linux/fs/minix/namei.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/minix/namei.c	Thu Feb 10 12:16:59 2000
@@ -219,6 +219,7 @@
 	if (!inode)
 		return -ENOSPC;
 	inode->i_op = &minix_file_inode_operations;
+	inode->i_mapping->a_ops = &minix_aops;
 	inode->i_mode = mode;
 	mark_inode_dirty(inode);
 	error = minix_add_entry(dir, dentry->d_name.name,
@@ -477,7 +478,8 @@
 		goto out;
 
 	inode->i_mode = S_IFLNK | 0777;
-	inode->i_op = &minix_symlink_inode_operations;
+	inode->i_op = &page_symlink_inode_operations;
+	inode->i_mapping->a_ops = &minix_aops;
 	err = block_symlink(inode, symname, i);
 	if (err)
 		goto fail;
diff -u --recursive --new-file v2.3.42/linux/fs/minix/symlink.c linux/fs/minix/symlink.c
--- v2.3.42/linux/fs/minix/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/minix/symlink.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/*
- *  linux/fs/minix/symlink.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  minix symlink handling code
- *
- *  Code removed. 1999, AV ;-)
- */
-
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations minix_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
-	get_block:	minix_get_block,
-	readpage:	block_read_full_page
-};
diff -u --recursive --new-file v2.3.42/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.3.42/linux/fs/msdos/namei.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/msdos/namei.c	Thu Feb 10 12:16:59 2000
@@ -595,14 +595,6 @@
 	msdos_rmdir,		/* rmdir */
 	NULL,			/* mknod */
 	msdos_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL,                   /* revalidate */
 };
 
 static void msdos_put_super_callback(struct super_block *sb)
diff -u --recursive --new-file v2.3.42/linux/fs/namei.c linux/fs/namei.c
--- v2.3.42/linux/fs/namei.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/namei.c	Thu Feb 10 12:16:59 2000
@@ -1386,8 +1386,8 @@
 static char *page_getlink(struct dentry * dentry, struct page **ppage)
 {
 	struct page * page;
-	page = read_cache_page(&dentry->d_inode->i_data, 0,
-				(filler_t *)dentry->d_inode->i_op->readpage,
+	struct address_space *mapping = dentry->d_inode->i_mapping;
+	page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage,
 				dentry);
 	if (IS_ERR(page))
 		goto sync_fail;
@@ -1429,3 +1429,8 @@
 	}
 	return res;
 }
+
+struct inode_operations page_symlink_inode_operations = {
+	readlink:	page_readlink,
+	follow_link:	page_follow_link,
+};
diff -u --recursive --new-file v2.3.42/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.3.42/linux/fs/ncpfs/dir.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/ncpfs/dir.c	Thu Feb 10 12:16:59 2000
@@ -47,17 +47,9 @@
 		      
 static struct file_operations ncp_dir_operations =
 {
-	NULL,			/* lseek - default */
-	ncp_dir_read,		/* read - bad */
-	NULL,			/* write - bad */
-	ncp_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	ncp_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* fsync */
+	read:		ncp_dir_read,
+	readdir:	ncp_readdir,
+	ioctl:		ncp_ioctl,
 };
 
 struct inode_operations ncp_dir_inode_operations =
@@ -78,9 +70,6 @@
 	ncp_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	NULL,			/* permission */
 	NULL,			/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c
--- v2.3.42/linux/fs/ncpfs/file.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/ncpfs/file.c	Thu Feb 10 12:16:59 2000
@@ -277,17 +277,11 @@
 
 static struct file_operations ncp_file_operations =
 {
-	NULL,			/* lseek - default */
-	ncp_file_read,		/* read */
-	ncp_file_write,		/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	ncp_ioctl,		/* ioctl */
-	ncp_mmap,		/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	ncp_fsync,		/* fsync */
+	read:		ncp_file_read,
+	write:		ncp_file_write,
+	ioctl:		ncp_ioctl,
+	mmap:		ncp_mmap,
+	fsync:		ncp_fsync,
 };
 
 struct inode_operations ncp_file_inode_operations =
@@ -304,9 +298,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	NULL,			/* permission */
 	NULL			/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.3.42/linux/fs/ncpfs/inode.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/ncpfs/inode.c	Thu Feb 10 12:16:59 2000
@@ -51,7 +51,7 @@
 
 extern struct dentry_operations ncp_dentry_operations;
 #ifdef CONFIG_NCPFS_EXTRAS
-extern struct inode_operations ncp_symlink_inode_operations;
+extern struct address_space_operations ncp_symlink_aops;
 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
 #endif
 
@@ -226,7 +226,8 @@
 			inode->i_op = &ncp_dir_inode_operations;
 #ifdef CONFIG_NCPFS_EXTRAS
 		} else if (S_ISLNK(inode->i_mode)) {
-			inode->i_op = &ncp_symlink_inode_operations;
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_data.a_ops = &ncp_symlink_aops;
 #endif
 		}
 		insert_inode_hash(inode);
diff -u --recursive --new-file v2.3.42/linux/fs/ncpfs/symlink.c linux/fs/ncpfs/symlink.c
--- v2.3.42/linux/fs/ncpfs/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/ncpfs/symlink.c	Thu Feb 10 12:16:59 2000
@@ -96,9 +96,7 @@
 /*
  * symlinks can't do much...
  */
-struct inode_operations ncp_symlink_inode_operations={
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
+struct address_space_operations ncp_symlink_aops = {
 	readpage:	ncp_symlink_readpage,
 };
 	
diff -u --recursive --new-file v2.3.42/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.3.42/linux/fs/nfs/dir.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/nfs/dir.c	Thu Feb 10 12:16:59 2000
@@ -52,17 +52,10 @@
 		      struct inode *, struct dentry *);
 
 static struct file_operations nfs_dir_operations = {
-	NULL,			/* lseek - default */
-	nfs_dir_read,		/* read - bad */
-	NULL,			/* write - bad */
-	nfs_readdir,		/* readdir */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	nfs_open,		/* open */
-	NULL,			/* flush */
-	nfs_release,		/* release */
-	NULL			/* fsync */
+	read:		nfs_dir_read,
+	readdir:	nfs_readdir,
+	open:		nfs_open,
+	release:	nfs_release,
 };
 
 struct inode_operations nfs_dir_inode_operations = {
@@ -78,9 +71,6 @@
 	nfs_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	NULL,			/* permission */
 	nfs_revalidate,		/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.3.42/linux/fs/nfs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/nfs/file.c	Thu Feb 10 12:16:59 2000
@@ -41,19 +41,14 @@
 static int  nfs_fsync(struct file *, struct dentry *dentry);
 
 static struct file_operations nfs_file_operations = {
-	NULL,			/* lseek - default */
-	nfs_file_read,		/* read */
-	nfs_file_write,		/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select - default */
-	NULL,			/* ioctl - default */
-	nfs_file_mmap,		/* mmap */
-	nfs_open,		/* open */
-	nfs_file_flush,		/* flush */
-	nfs_release,		/* release */
-	nfs_fsync,		/* fsync */
-	NULL,			/* fasync */
-	nfs_lock,		/* lock */
+	read:		nfs_file_read,
+	write:		nfs_file_write,
+	mmap:		nfs_file_mmap,
+	open:		nfs_open,
+	flush:		nfs_file_flush,
+	release:	nfs_release,
+	fsync:		nfs_fsync,
+	lock:		nfs_lock,
 };
 
 struct inode_operations nfs_file_inode_operations = {
@@ -69,9 +64,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	nfs_readpage,		/* readpage */
-	nfs_writepage,		/* writepage */
 	NULL,			/* truncate */
 	NULL,			/* permission */
 	nfs_revalidate,		/* revalidate */
@@ -146,11 +138,13 @@
 
 	dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
+	lock_kernel();
 	status = nfs_wb_file(inode, file);
 	if (!status) {
 		status = file->f_error;
 		file->f_error = 0;
 	}
+	unlock_kernel();
 	return status;
 }
 
@@ -163,21 +157,29 @@
  * If the writer ends up delaying the write, the writer needs to
  * increment the page use counts until he is done with the page.
  */
-static int nfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int nfs_prepare_write(struct page *page, unsigned offset, unsigned to)
+{
+	kmap(page);
+	return 0;
+}
+static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
 	long status;
 
-	bytes -= copy_from_user((u8*)kmap(page) + offset, buf, bytes);
 	kunmap(page);
-	status = -EFAULT;
-	if (bytes) {
-		lock_kernel();
-		status = nfs_updatepage(file, page, offset, bytes);
-		unlock_kernel();
-	}
+	lock_kernel();
+	status = nfs_updatepage(file, page, offset, to-offset);
+	unlock_kernel();
 	return status;
 }
 
+struct address_space_operations nfs_file_aops = {
+	readpage: nfs_readpage,
+	writepage: nfs_writepage,
+	prepare_write: nfs_prepare_write,
+	commit_write: nfs_commit_write
+};
+
 /* 
  * Write to a file (through the page cache).
  */
@@ -203,7 +205,7 @@
 	if (!count)
 		goto out;
 
-	result = generic_file_write(file, buf, count, ppos, nfs_write_one_page);
+	result = generic_file_write(file, buf, count, ppos);
 out:
 	return result;
 
diff -u --recursive --new-file v2.3.42/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.3.42/linux/fs/nfs/inode.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/nfs/inode.c	Thu Feb 10 12:16:59 2000
@@ -473,9 +473,10 @@
 		NFS_FILEID(inode) = fattr->fileid;
 		NFS_FSID(inode) = fattr->fsid;
 		inode->i_mode = fattr->mode;
-		if (S_ISREG(inode->i_mode))
+		if (S_ISREG(inode->i_mode)) {
 			inode->i_op = &nfs_file_inode_operations;
-		else if (S_ISDIR(inode->i_mode))
+			inode->i_data.a_ops = &nfs_file_aops;
+		} else if (S_ISDIR(inode->i_mode))
 			inode->i_op = &nfs_dir_inode_operations;
 		else if (S_ISLNK(inode->i_mode))
 			inode->i_op = &nfs_symlink_inode_operations;
diff -u --recursive --new-file v2.3.42/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.3.42/linux/fs/nfs/write.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/nfs/write.c	Thu Feb 10 12:16:59 2000
@@ -479,7 +479,7 @@
 	if (req->wb_bytes == PAGE_SIZE)
 		SetPageUptodate(page);
 
-	retval = count;
+	retval = 0;
 	if (synchronous) {
 		int status = wait_on_write_request(req);
 		if (status) {
diff -u --recursive --new-file v2.3.42/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.3.42/linux/fs/nfsd/nfsctl.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/nfsd/nfsctl.c	Thu Feb 10 12:16:38 2000
@@ -29,13 +29,7 @@
 #include <linux/nfsd/xdr.h>
 #include <linux/nfsd/syscall.h>
 
-#if LINUX_VERSION_CODE >= 0x020100
 #include <asm/uaccess.h>
-#else
-# define copy_from_user		memcpy_fromfs
-# define copy_to_user		memcpy_tofs
-# define access_ok		!verify_area
-#endif
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
@@ -249,10 +243,8 @@
 
 #ifdef MODULE
 /* New-style module support since 2.1.18 */
-#if LINUX_VERSION_CODE >= 131346
 EXPORT_NO_SYMBOLS;
 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
-#endif
 
 extern int (*do_nfsservctl)(int, void *, void *);
 
diff -u --recursive --new-file v2.3.42/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.3.42/linux/fs/nfsd/vfs.c	Tue Feb  1 01:35:44 2000
+++ linux/fs/nfsd/vfs.c	Thu Feb 10 12:16:38 2000
@@ -39,9 +39,7 @@
 #include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
 
-#if LINUX_VERSION_CODE >= 0x020100
 #include <asm/uaccess.h>
-#endif
 
 #define NFSDDBG_FACILITY		NFSDDBG_FILEOP
 #define NFSD_PARANOIA
diff -u --recursive --new-file v2.3.42/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.3.42/linux/fs/ntfs/fs.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/ntfs/fs.c	Thu Feb 10 12:16:59 2000
@@ -405,44 +405,14 @@
 }
 
 static struct file_operations ntfs_file_operations_nommap = {
-	NULL, /* lseek */
-	ntfs_read,
+	read:		ntfs_read,
 #ifdef CONFIG_NTFS_RW
-	ntfs_write,
-#else
-	NULL,
+	write:		ntfs_write,
 #endif
-	NULL, /* readdir */
-	NULL, /* select */
-	NULL, /* ioctl */
-	NULL, /* mmap */
-	NULL, /* open */
-	NULL, /* flush */
-	NULL, /* release */
-	NULL, /* fsync */
-	NULL, /* fasync */
-	NULL, /* lock */
 };
 
 static struct inode_operations ntfs_inode_operations_nobmap = {
 	&ntfs_file_operations_nommap,
-	NULL, /* create */
-	NULL, /* lookup */
-	NULL, /* link */
-	NULL, /* unlink */
-	NULL, /* symlink */
-	NULL, /* mkdir */
-	NULL, /* rmdir */
-	NULL, /* mknod */
-	NULL, /* rename */
-	NULL, /* readlink */
-	NULL, /* follow_link */
-	NULL, /* get_block */
-	NULL, /* readpage */
-	NULL, /* writepage */
-	NULL, /* truncate */
-	NULL, /* permission */
-	NULL, /* revalidate */
 };
 
 #ifdef CONFIG_NTFS_RW
@@ -583,52 +553,28 @@
 	return (ret==-1) ? 0:ret;
 }
 
+/* It's fscking broken. */
+
+static int ntfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
+{
+	BUG();
+	return -1;
+}
+
 static struct file_operations ntfs_file_operations = {
-	NULL, /* lseek */
-	ntfs_read,
+	read:		ntfs_read,
+	mmap:		generic_file_mmap,
 #ifdef CONFIG_NTFS_RW
-	ntfs_write,
-#else
-	NULL,
+	write:		ntfs_write,
 #endif
-	NULL, /* readdir */
-	NULL, /* select */
-	NULL, /* ioctl */
-	generic_file_mmap,
-	NULL, /* open */
-	NULL, /* flush */
-	NULL, /* release */
-	NULL, /* fsync */
-	NULL, /* fasync */
-	NULL, /* lock */
 };
 
 static struct inode_operations ntfs_inode_operations = {
 	&ntfs_file_operations,
-	NULL, /* create */
-	NULL, /* lookup */
-	NULL, /* link */
-	NULL, /* unlink */
-	NULL, /* symlink */
-	NULL, /* mkdir */
-	NULL, /* rmdir */
-	NULL, /* mknod */
-	NULL, /* rename */
-	NULL, /* readlink */
-	NULL, /* follow_link */
-	ntfs_bmap, /* get_block */
-	block_read_full_page, /* readpage */
-	NULL, /* writepage */
-	NULL, /* truncate */
-	NULL, /* permission */
-	NULL, /* revalidate */
 };
 
 static struct file_operations ntfs_dir_operations = {
-	NULL, /* lseek */
-	NULL, /* read */
-	NULL, /* write */
-	ntfs_readdir, /* readdir */
+	readdir:	ntfs_readdir,
 };
 
 static struct inode_operations ntfs_dir_inode_operations = {
@@ -650,16 +596,32 @@
 	NULL, /* rmdir */
 	NULL, /* mknod */
 	NULL, /* rename */
-	NULL, /* readlink */
-	NULL, /* follow_link */
-	NULL, /* get_block */
-	NULL, /* readpage */
-	NULL, /* writepage */
-	NULL, /* truncate */
-	NULL, /* permission */
-	NULL, /* revalidate */
 };
 
+static int ntfs_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,ntfs_get_block);
+}
+static int ntfs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,ntfs_get_block);
+}
+static int ntfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page,from,to,ntfs_get_block,
+		&((struct inode*)page->mapping->host)->u.ntfs_i.mmu_private);
+}
+static int _ntfs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,ntfs_get_block);
+}
+struct address_space_operations ntfs_aops = {
+	readpage: ntfs_readpage,
+	writepage: ntfs_writepage,
+	prepare_write: ntfs_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: _ntfs_bmap
+};
 /* ntfs_read_inode is called by the Virtual File System (the kernel layer that
  * deals with filesystems) when iget is called requesting an inode not already
  * present in the inode table. Typically filesystems have separate
@@ -735,8 +697,13 @@
 	}
 	else
 	{
-		inode->i_op=can_mmap ? &ntfs_inode_operations : 
-			&ntfs_inode_operations_nobmap;
+		if (can_mmap) {
+			inode->i_op = &ntfs_inode_operations;
+			inode->i_mapping->a_ops = &ntfs_aops;
+			inode->u.ntfs_i.mmu_private = inode->i_size;
+		} else {
+			inode->i_op=&ntfs_inode_operations_nobmap;
+		}
 		inode->i_mode=S_IFREG|S_IRUGO;
 	}
 #ifdef CONFIG_NTFS_RW
diff -u --recursive --new-file v2.3.42/linux/fs/open.c linux/fs/open.c
--- v2.3.42/linux/fs/open.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/open.c	Thu Feb 10 12:40:49 2000
@@ -898,16 +898,9 @@
  */
 asmlinkage long sys_vhangup(void)
 {
-	int ret = -EPERM;
-
-	if (!capable(CAP_SYS_TTY_CONFIG))
-		goto out;
-	/* If there is a controlling tty, hang it up */
-	lock_kernel();
-	if (current->tty)
+	if (capable(CAP_SYS_TTY_CONFIG)) {
 		tty_vhangup(current->tty);
-	unlock_kernel();
-	ret = 0;
-out:
-	return ret;
+		return 0;
+	}
+	return -EPERM;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/openpromfs/inode.c linux/fs/openpromfs/inode.c
--- v2.3.42/linux/fs/openpromfs/inode.c	Tue Jan  4 13:57:18 2000
+++ linux/fs/openpromfs/inode.c	Thu Feb 10 12:16:59 2000
@@ -1,4 +1,4 @@
-/* $Id: inode.c,v 1.3 2000/01/04 10:02:29 jj Exp $
+/* $Id: inode.c,v 1.4 2000/02/09 22:35:50 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
@@ -553,17 +553,9 @@
 }
 
 static struct file_operations openpromfs_prop_ops = {
-	NULL,			/* lseek - default */
-	property_read,		/* read */
-	property_write,		/* write - bad */
-	NULL,			/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	property_release,	/* no special release code */
-	NULL			/* can't fsync */
+	read:		property_read,
+	write:		property_write,
+	release:	property_release,
 };
 
 static struct inode_operations openpromfs_prop_inode_ops = {
@@ -571,17 +563,7 @@
 };
 
 static struct file_operations openpromfs_nodenum_ops = {
-	NULL,			/* lseek - default */
-	nodenum_read,		/* read */
-	NULL,			/* write - bad */
-	NULL,			/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
+	read:		nodenum_read,
 };
 
 static struct inode_operations openpromfs_nodenum_inode_ops = {
@@ -589,17 +571,7 @@
 };
 
 static struct file_operations openprom_alias_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	openpromfs_readdir,	/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
+	readdir:	openpromfs_readdir,
 };
 
 static struct inode_operations openprom_alias_inode_operations = {
@@ -608,19 +580,6 @@
 	openpromfs_lookup,	/* lookup */
 	NULL,			/* link */
 	openpromfs_unlink,	/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 extern struct inode_operations openprom_inode_operations;
@@ -1019,10 +978,7 @@
 
 
 static struct file_operations openprom_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	openpromfs_readdir,	/* readdir */
+	readdir:	openpromfs_readdir,
 };
 
 static struct inode_operations openprom_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.3.42/linux/fs/partitions/check.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/partitions/check.c	Tue Feb  8 11:37:29 2000
@@ -18,6 +18,7 @@
 #include <linux/major.h>
 #include <linux/blk.h>
 #include <linux/init.h>
+#include <linux/raid/md.h>
 
 #include "check.h"
 
@@ -315,6 +316,9 @@
 	else
 #endif
 	rd_load();
+#endif
+#ifdef CONFIG_BLK_DEV_MD
+	autodetect_raid();
 #endif
 #ifdef CONFIG_MD_BOOT
 	md_setup_drive();
diff -u --recursive --new-file v2.3.42/linux/fs/partitions/mac.c linux/fs/partitions/mac.c
--- v2.3.42/linux/fs/partitions/mac.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/partitions/mac.c	Wed Feb  9 19:43:53 2000
@@ -28,6 +28,14 @@
  * Code to understand MacOS partition tables.
  */
 
+static inline void mac_fix_string(char *stg, int len)
+{
+	int i;
+
+	for (i = len - 1; i >= 0 && stg[i] == ' '; i--)
+		stg[i] = 0;
+}
+
 int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor)
 {
 	struct buffer_head *bh;
@@ -35,7 +43,8 @@
 	int dev_bsize, dev_pos, pos;
 	unsigned secsize;
 #ifdef CONFIG_PPC
-	int first_bootable = 1;
+	int found_root = 0;
+	int found_root_goodness = 0;
 #endif
 	struct mac_partition *part;
 	struct mac_driver_desc *md;
@@ -93,16 +102,49 @@
 		 * If this is the first bootable partition, tell the
 		 * setup code, in case it wants to make this the root.
 		 */
-		if ( (_machine == _MACH_Pmac) && first_bootable
-		    && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
-		    && strcasecmp(part->processor, "powerpc") == 0) {
-			note_bootable_part(dev, blk);
-			first_bootable = 0;
+		if (_machine == _MACH_Pmac) {
+			int goodness = 0;
+
+			mac_fix_string(part->processor, 16);
+			mac_fix_string(part->name, 32);
+			mac_fix_string(part->type, 32);					
+		    
+			if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
+			    && strcasecmp(part->processor, "powerpc") == 0)
+				goodness++;
+
+			if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
+			    || strcasecmp(part->type, "Linux_PPC") == 0) {
+				int i, l;
+
+				goodness++;
+				l = strlen(part->name);
+				if (strcmp(part->name, "/") == 0)
+					goodness++;
+				for (i = 0; i <= l - 4; ++i) {
+					if (strnicmp(part->name + i, "root",
+						     4) == 0) {
+						goodness += 2;
+						break;
+					}
+				}
+				if (strnicmp(part->name, "swap", 4) == 0)
+					goodness--;
+			}
+
+			if (goodness > found_root_goodness) {
+				found_root = blk;
+				found_root_goodness = goodness;
+			}
 		}
 #endif /* CONFIG_PPC */
 
 		++first_part_minor;
 	}
+#ifdef CONFIG_PPC
+	if (found_root_goodness)
+		note_bootable_part(dev, found_root);
+#endif
 	brelse(bh);
 	printk("\n");
 	return 1;
diff -u --recursive --new-file v2.3.42/linux/fs/pipe.c linux/fs/pipe.c
--- v2.3.42/linux/fs/pipe.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/pipe.c	Wed Feb  9 11:42:35 2000
@@ -462,101 +462,73 @@
  * are also used in linux/fs/fifo.c to do operations on FIFOs.
  */
 struct file_operations connecting_fifo_fops = {
-	pipe_lseek,
-	connect_read,
-	bad_pipe_w,
-	NULL,		/* no readdir */
-	connect_poll,
-	pipe_ioctl,
-	NULL,		/* no mmap on pipes.. surprise */
-	pipe_read_open,
-	NULL,		/* flush */
-	pipe_read_release,
-	NULL
+	llseek:		pipe_lseek,
+	read:		connect_read,
+	write:		bad_pipe_w,
+	poll:		connect_poll,
+	ioctl:		pipe_ioctl,
+	open:		pipe_read_open,
+	release:	pipe_read_release,
 };
 
 struct file_operations read_fifo_fops = {
-	pipe_lseek,
-	pipe_read,
-	bad_pipe_w,
-	NULL,		/* no readdir */
-	fifo_poll,
-	pipe_ioctl,
-	NULL,		/* no mmap on pipes.. surprise */
-	pipe_read_open,
-	NULL,		/* flush */
-	pipe_read_release,
-	NULL
+	llseek:		pipe_lseek,
+	read:		pipe_read,
+	write:		bad_pipe_w,
+	poll:		fifo_poll,
+	ioctl:		pipe_ioctl,
+	open:		pipe_read_open,
+	release:	pipe_read_release,
 };
 
 struct file_operations write_fifo_fops = {
-	pipe_lseek,
-	bad_pipe_r,
-	pipe_write,
-	NULL,		/* no readdir */
-	fifo_poll,
-	pipe_ioctl,
-	NULL,		/* mmap */
-	pipe_write_open,
-	NULL,		/* flush */
-	pipe_write_release,
-	NULL
+	llseek:		pipe_lseek,
+	read:		bad_pipe_r,
+	write:		pipe_write,
+	poll:		fifo_poll,
+	ioctl:		pipe_ioctl,
+	open:		pipe_write_open,
+	release:	pipe_write_release,
 };
 
 struct file_operations rdwr_fifo_fops = {
-	pipe_lseek,
-	pipe_read,
-	pipe_write,
-	NULL,		/* no readdir */
-	fifo_poll,
-	pipe_ioctl,
-	NULL,		/* mmap */
-	pipe_rdwr_open,
-	NULL,		/* flush */
-	pipe_rdwr_release,
-	NULL
+	llseek:		pipe_lseek,
+	read:		pipe_read,
+	write:		pipe_write,
+	poll:		fifo_poll,
+	ioctl:		pipe_ioctl,
+	open:		pipe_rdwr_open,
+	release:	pipe_rdwr_release,
 };
 
 struct file_operations read_pipe_fops = {
-	pipe_lseek,
-	pipe_read,
-	bad_pipe_w,
-	NULL,		/* no readdir */
-	pipe_poll,
-	pipe_ioctl,
-	NULL,		/* no mmap on pipes.. surprise */
-	pipe_read_open,
-	NULL,		/* flush */
-	pipe_read_release,
-	NULL
+	llseek:		pipe_lseek,
+	read:		pipe_read,
+	write:		bad_pipe_w,
+	poll:		pipe_poll,
+	ioctl:		pipe_ioctl,
+	open:		pipe_read_open,
+	release:	pipe_read_release,
 };
 
 struct file_operations write_pipe_fops = {
-	pipe_lseek,
-	bad_pipe_r,
-	pipe_write,
-	NULL,		/* no readdir */
-	pipe_poll,
-	pipe_ioctl,
-	NULL,		/* mmap */
-	pipe_write_open,
-	NULL,		/* flush */
-	pipe_write_release,
-	NULL
+	llseek:		pipe_lseek,
+	read:		bad_pipe_r,
+	write:		pipe_write,
+	poll:		pipe_poll,
+	ioctl:		pipe_ioctl,
+	open:		pipe_write_open,
+	release:	pipe_write_release,
 };
 
 struct file_operations rdwr_pipe_fops = {
-	pipe_lseek,
-	pipe_read,
-	pipe_write,
-	NULL,		/* no readdir */
-	pipe_poll,
-	pipe_ioctl,
-	NULL,		/* mmap */
-	pipe_rdwr_open,
-	NULL,		/* flush */
-	pipe_rdwr_release,
-	NULL
+	llseek:		pipe_lseek,
+	read:		pipe_read,
+	write:		pipe_write,
+	poll:		pipe_poll,
+	ioctl:		pipe_ioctl,
+	open:		pipe_rdwr_open,
+	release:	pipe_rdwr_release,
 };
 
 static struct inode * get_pipe_inode(void)
diff -u --recursive --new-file v2.3.42/linux/fs/proc/Makefile linux/fs/proc/Makefile
--- v2.3.42/linux/fs/proc/Makefile	Wed Dec 29 13:13:20 1999
+++ linux/fs/proc/Makefile	Mon Feb  7 09:56:47 2000
@@ -10,9 +10,6 @@
 O_TARGET := proc.o
 O_OBJS   := inode.o root.o base.o generic.o array.o \
 		kmsg.o proc_tty.o proc_misc.o kcore.o
-ifdef CONFIG_OMIRR
-O_OBJS   := $(O_OBJS) omirr.o
-endif
 OX_OBJS  := procfs_syms.o
 M_OBJS   := 
 
diff -u --recursive --new-file v2.3.42/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.3.42/linux/fs/proc/array.c	Thu Nov 18 20:25:37 1999
+++ linux/fs/proc/array.c	Thu Feb 10 12:41:10 2000
@@ -133,8 +133,7 @@
 					   TASK_INTERRUPTIBLE |
 					   TASK_UNINTERRUPTIBLE |
 					   TASK_ZOMBIE |
-					   TASK_STOPPED |
-					   TASK_SWAPPING);
+					   TASK_STOPPED);
 	const char **p = &task_state_array[0];
 
 	while (state) {
diff -u --recursive --new-file v2.3.42/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.3.42/linux/fs/proc/base.c	Tue Feb  1 01:35:44 2000
+++ linux/fs/proc/base.c	Thu Feb 10 12:16:59 2000
@@ -15,7 +15,6 @@
 
 #include <asm/uaccess.h>
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
@@ -206,8 +205,7 @@
 }
 
 static struct file_operations proc_maps_operations = {
-	NULL,		/* array_lseek */
-	pid_maps_read,
+	read:		pid_maps_read,
 };
 
 struct inode_operations proc_maps_inode_operations = {
@@ -258,8 +256,7 @@
 }
 
 static struct file_operations proc_info_file_operations = {
-    NULL,			/* lseek   */
-    proc_info_read,		/* read	   */
+	read:		proc_info_read,
 };
 
 static struct inode_operations proc_info_inode_operations = {
@@ -348,9 +345,8 @@
 }
 
 static struct file_operations proc_mem_operations = {
-	NULL,		/* lseek - default */
-	mem_read,
-	mem_write,
+	read:		mem_read,
+	write:		mem_write,
 };
 
 static struct inode_operations proc_mem_inode_operations = {
@@ -366,9 +362,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	proc_permission,	/* permission */
 	NULL			/* revalidate */
@@ -456,18 +449,8 @@
 }
 
 static struct inode_operations proc_pid_link_inode_operations = {
-	NULL,			/* file-operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	proc_pid_readlink,	/* readlink */
-	proc_pid_follow_link,	/* follow_link */
+	readlink:	proc_pid_readlink,
+	follow_link:	proc_pid_follow_link
 };
 
 /* reading from directory - bad */
@@ -761,10 +744,8 @@
 }
 
 static struct file_operations proc_fd_operations = {
-	NULL,			/* lseek - default */
-	proc_dir_read,		/* read - bad */
-	NULL,			/* write - bad */
-	proc_readfd,		/* readdir */
+	read: proc_dir_read,		/* read - bad */
+	readdir: proc_readfd,		/* readdir */
 };
 
 /*
@@ -783,9 +764,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	proc_permission,	/* permission */
 };
@@ -882,10 +860,8 @@
 }
 
 static struct file_operations proc_base_operations = {
-	NULL,			/* lseek - default */
-	proc_dir_read,		/* read - bad */
-	NULL,			/* write - bad */
-	proc_base_readdir,	/* readdir */
+	read: proc_dir_read,		/* read - bad */
+	readdir: proc_base_readdir,	/* readdir */
 };
 
 static struct inode_operations proc_base_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/proc/generic.c linux/fs/proc/generic.c
--- v2.3.42/linux/fs/proc/generic.c	Fri Jan 21 18:19:17 2000
+++ linux/fs/proc/generic.c	Wed Feb  9 11:42:35 2000
@@ -32,9 +32,9 @@
 }
 
 static struct file_operations proc_file_operations = {
-    proc_file_lseek,	/* lseek   */
-    proc_file_read,	/* read	   */
-    proc_file_write,	/* write   */
+	llseek:		proc_file_lseek,
+	read:		proc_file_read,
+	write:		proc_file_write,
 };
 
 static struct inode_operations proc_file_inode_operations = {
@@ -337,10 +337,7 @@
  * the /proc directory.
  */
 static struct file_operations proc_dir_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	proc_readdir,		/* readdir */
+	readdir:		proc_readdir,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/fs/proc/kcore.c linux/fs/proc/kcore.c
--- v2.3.42/linux/fs/proc/kcore.c	Wed Dec 29 13:13:20 1999
+++ linux/fs/proc/kcore.c	Wed Feb  9 11:42:35 2000
@@ -27,14 +27,8 @@
 static ssize_t read_kcore(struct file *, char *, size_t, loff_t *);
 
 static struct file_operations proc_kcore_operations = {
-	NULL,           /* lseek */
-	read_kcore,
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	open_kcore
+	read:		read_kcore,
+	open:		open_kcore,
 };
 
 struct inode_operations proc_kcore_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c
--- v2.3.42/linux/fs/proc/kmsg.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/proc/kmsg.c	Wed Feb  9 11:42:35 2000
@@ -46,17 +46,10 @@
 
 
 static struct file_operations proc_kmsg_operations = {
-	NULL,		/* kmsg_lseek */
-	kmsg_read,
-	NULL,		/* kmsg_write */
-	NULL,		/* kmsg_readdir */
-	kmsg_poll,	/* kmsg_poll */
-	NULL,		/* kmsg_ioctl */
-	NULL,		/* mmap */
-	kmsg_open,
-	NULL,		/* flush */
-	kmsg_release,
-	NULL		/* can't fsync */
+	read:		kmsg_read,
+	poll:		kmsg_poll,
+	open:		kmsg_open,
+	release:	kmsg_release,
 };
 
 struct inode_operations proc_kmsg_inode_operations = {
diff -u --recursive --new-file v2.3.42/linux/fs/proc/omirr.c linux/fs/proc/omirr.c
--- v2.3.42/linux/fs/proc/omirr.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/proc/omirr.c	Wed Dec 31 16:00:00 1969
@@ -1,279 +0,0 @@
-/*
- * fs/proc/omirr.c  -  online mirror support
- *
- * (C) 1997 Thomas Schoebel-Theuer
- */
-
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/omirr.h>
-#include <asm/uaccess.h>
-
-static int nr_omirr_open = 0;
-static int cleared_flag = 0;
-
-static char * buffer = NULL;
-static int read_pos, write_pos;
-static int clip_pos, max_pos;
-static DECLARE_WAIT_QUEUE_HEAD(read_wait);
-static DECLARE_WAIT_QUEUE_HEAD(write_wait);
-
-static /*inline*/ int reserve_write_space(int len)
-{
-	int rest = max_pos - write_pos;
-
-	if(rest < len) {
-		clip_pos = write_pos;
-		write_pos = 0;
-		rest = max_pos;
-	}
-	while(read_pos > write_pos && read_pos <= write_pos+len) {
-		if(!nr_omirr_open)
-			return 0;
-		interruptible_sleep_on(&write_wait);
-	}
-	return 1;
-}
-
-static /*inline*/ void write_space(int len)
-{
-	write_pos += len;
-	wake_up_interruptible(&read_wait);
-}
-
-static /*inline*/ int reserve_read_space(int len)
-{
-	int rest = clip_pos - read_pos;
-
-	if(!rest) {
-		read_pos = 0;
-		rest = clip_pos;
-		clip_pos = max_pos;
-	}
-	if(len > rest)
-		len = rest;
-	while(read_pos == write_pos) {
-		interruptible_sleep_on(&read_wait);
-	}
-	rest = write_pos - read_pos;
-	if(rest > 0 && rest < len)
-		len = rest;
-	return len;
-}
-
-static /*inline*/ void read_space(int len)
-{
-	read_pos += len;
-	if(read_pos >= clip_pos) {
-		read_pos = 0;
-		clip_pos = max_pos;
-	}
-	wake_up_interruptible(&write_wait);
-}
-
-static /*inline*/ void init_buffer(char * initxt)
-{
-	int len = initxt ? strlen(initxt) : 0;
-
-	if(!buffer) {
-		buffer = (char*)__get_free_page(GFP_USER);
-		max_pos = clip_pos = PAGE_SIZE;
-	}
-	read_pos = write_pos = 0;
-	memcpy(buffer, initxt, len);
-	write_space(len);
-}
-
-static int omirr_open(struct inode * inode, struct file * file)
-{
-	if(nr_omirr_open)
-		return -EAGAIN;
-	nr_omirr_open++;
-	if(!buffer)
-		init_buffer(NULL);
-	return 0;
-}
-
-static int omirr_release(struct inode * inode, struct file * file)
-{
-	nr_omirr_open--;
-	read_space(0);
-	return 0;
-}
-
-static long omirr_read(struct inode * inode, struct file * file,
-		       char * buf, unsigned long count)
-{
-	char * tmp;
-	int len;
-	int error = 0;
-
-	if(!count)
-		goto done;
-	error = -EINVAL;
-	if(!buf || count < 0)
-		goto done;
-	
-	error = verify_area(VERIFY_WRITE, buf, count);
-	if(error)
-		goto done;
-	
-	error = -EAGAIN;
-	if((file->f_flags & O_NONBLOCK) && read_pos == write_pos)
-		goto done;
-
-	error = len = reserve_read_space(count);
-	tmp = buffer + read_pos;
-	while(len) {
-		put_user(*tmp++, buf++);
-		len--;
-	}
-	read_space(error);
-done:
-	return error;		
-}
-
-int compute_name(struct dentry * entry, char * buf)
-{
-	int len;
-
-	if(IS_ROOT(entry)) {
-		*buf = '/';
-		return 1;
-	}
-	len = compute_name(entry->d_parent, buf);
-	if(len > 1) {
-		buf[len++] = '/';
-	}
-	memcpy(buf+len, entry->d_name, entry->d_len);
-	return len + entry->d_len;
-}
-
-int _omirr_print(struct dentry * ent1, struct dentry * ent2, 
-		struct qstr * suffix, const char * fmt,
-		 va_list args1, va_list args2)
-{
-	int count = strlen(fmt) + 10; /* estimate */
-	const char * tmp = fmt;
-	char lenbuf[8];
-	int res;
-
-	if(!buffer)
-		init_buffer(NULL);
-	while(*tmp) {
-		while(*tmp && *tmp++ != '%') ;
-		if(*tmp) {
-			if(*tmp == 's') {
-				char * str = va_arg(args1, char*);
-				count += strlen(str);
-			} else {
-				(void)va_arg(args1, int);
-				count += 8; /* estimate */
-			}
-		}
-	}
-	if(ent1) {
-		struct dentry * dent = ent1;
-		while(dent && !IS_ROOT(dent)) {
-			count += dent->d_len + 1;
-			dent = dent->d_parent;
-		}
-		count++;
-		if(ent2) {
-			dent = ent2;
-			while(dent && !IS_ROOT(dent)) {
-				count += dent->d_len + 1;
-				dent = dent->d_parent;
-			}
-		count++;
-		}
-		if(suffix)
-			count += suffix->len + 1;
-	}
-	
-	if((nr_omirr_open | cleared_flag) && reserve_write_space(count)) {
-		cleared_flag = 0;
-		res = vsprintf(buffer+write_pos+4, fmt, args2) + 4;
-		if(res > count)
-			printk("omirr: format estimate was wrong\n");
-		if(ent1) {
-			res += compute_name(ent1, buffer+write_pos+res);
-			if(ent2) {
-				buffer[write_pos+res++] = '\0';
-				res += compute_name(ent2, buffer+write_pos+res);
-			}
-			if(suffix) {
-				buffer[write_pos+res++] = '/';
-				memcpy(buffer+write_pos+res,
-				       suffix->name, suffix->len);
-				res += suffix->len;
-			}
-			buffer[write_pos+res++] = '\0';
-			buffer[write_pos+res++] = '\n';
-		}
-		sprintf(lenbuf, "%04d", res);
-		memcpy(buffer+write_pos, lenbuf, 4);
-	} else {
-		if(!cleared_flag) {
-			cleared_flag = 1;
-			init_buffer("0007 Z\n");
-		}
-		res = 0;
-	}
-	write_space(res);
-	return res;
-}
-
-int omirr_print(struct dentry * ent1, struct dentry * ent2, 
-		struct qstr * suffix, const char * fmt, ...)
-{
-	va_list args1, args2;
-	int res;
-
-	/* I don't know whether I could make a simple copy of the va_list,
-	 * so for the safe way...
-	 */
-	va_start(args1, fmt);
-	va_start(args2, fmt);
-	res = _omirr_print(ent1, ent2, suffix, fmt, args1, args2);
-	va_end(args2);
-	va_end(args1);
-	return res;
-}
-
-int omirr_printall(struct inode * inode, const char * fmt, ...)
-{
-	int res = 0;
-	struct dentry * tmp = inode->i_dentry;
-
-	if(tmp) do {
-		va_list args1, args2;
-		va_start(args1, fmt);
-		va_start(args2, fmt);
-		res += _omirr_print(tmp, NULL, NULL, fmt, args1, args2);
-		va_end(args2);
-		va_end(args1);
-		tmp = tmp->d_next;
-	} while(tmp != inode->i_dentry);
-	return res;
-}
-
-static struct file_operations omirr_operations = {
-    NULL,	/* omirr_lseek */
-    omirr_read,
-    NULL,	/* omirr_write */
-    NULL,	/* omirr_readdir */
-    NULL,	/* omirr_select */
-    NULL,	/* omirr_ioctl */
-    NULL,	/* mmap */
-    omirr_open,
-    NULL,	/* flush */
-    omirr_release,
-    NULL,	/* fsync */
-    NULL,       /* fasync */
-};
-
-struct inode_operations proc_omirr_inode_operations = {
-	&omirr_operations,
-};
diff -u --recursive --new-file v2.3.42/linux/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- v2.3.42/linux/fs/proc/proc_misc.c	Tue Nov 23 22:42:21 1999
+++ linux/fs/proc/proc_misc.c	Wed Feb  9 18:48:03 2000
@@ -29,6 +29,7 @@
 #include <linux/smp.h>
 #include <linux/signal.h>
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -592,9 +593,8 @@
 }
 
 static struct file_operations proc_profile_operations = {
-	NULL,           /* lseek */
-	read_profile,
-	write_profile,
+	read:		read_profile,
+	write:		write_profile,
 };
 
 static struct inode_operations proc_profile_inode_operations = {
@@ -617,7 +617,7 @@
 	0, &proc_profile_inode_operations
 };
 
-void proc_misc_init(void)
+void __init proc_misc_init(void)
 {
 	static struct {
 		char *name;
diff -u --recursive --new-file v2.3.42/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.3.42/linux/fs/proc/procfs_syms.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/proc/procfs_syms.c	Wed Feb  9 18:48:03 2000
@@ -2,6 +2,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 
 extern struct proc_dir_entry *proc_sys_root;
 
@@ -26,7 +27,7 @@
 	NULL
 };
 
-int init_proc_fs(void)
+int __init init_proc_fs(void)
 {
 	return register_filesystem(&proc_fs_type) == 0;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.3.42/linux/fs/proc/root.c	Wed Dec 29 13:13:20 1999
+++ linux/fs/proc/root.c	Wed Feb  9 11:42:35 2000
@@ -143,10 +143,7 @@
  * directory handling functions for that..
  */
 static struct file_operations proc_root_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	proc_root_readdir,	/* readdir */
+	readdir: proc_root_readdir,
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/fs/qnx4/Makefile linux/fs/qnx4/Makefile
--- v2.3.42/linux/fs/qnx4/Makefile	Mon Aug 31 13:01:35 1998
+++ linux/fs/qnx4/Makefile	Thu Feb 10 12:16:59 2000
@@ -8,8 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := qnx4.o
-O_OBJS   := inode.o dir.o namei.o file.o bitmap.o symlinks.o truncate.o \
-fsync.o
+O_OBJS   := inode.o dir.o namei.o file.o bitmap.o truncate.o fsync.o
 M_OBJS   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/fs/qnx4/file.c linux/fs/qnx4/file.c
--- v2.3.42/linux/fs/qnx4/file.c	Wed Dec 29 13:13:21 1999
+++ linux/fs/qnx4/file.c	Thu Feb 10 12:16:59 2000
@@ -17,130 +17,6 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/qnx4_fs.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/malloc.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-
-#ifdef CONFIG_QNX4FS_RW
-static ssize_t qnx4_file_write(struct file *filp, const char *buf,
-			       size_t count, loff_t * ppos)
-{
-	struct dentry *dentry = filp->f_dentry;
-	struct inode *inode = dentry->d_inode;
-	struct qnx4_inode_info *qnx4_ino;
-	struct buffer_head *bh;
-	ssize_t result = -EBUSY, c;
-	off_t pos;
-	unsigned long start, block, extent_end;
-	char *p;
-
-	QNX4DEBUG(("qnx4: file_write(%s/%s (%d), %lu@%lu)\n",
-		   dentry->d_parent->d_name.name, dentry->d_name.name,
-	  inode->i_count, (unsigned long) count, (unsigned long) *ppos));
-	if (inode == NULL) {
-		printk("qnx4: NULL inode for file_write\n");
-		return -EINVAL;
-	}
-	qnx4_ino = &inode->u.qnx4_i;
-	if (S_ISREG(inode->i_mode) == 0) {
-		printk("qnx4: write to non-file, mode %07o\n", inode->i_mode);
-		return -EINVAL;
-	}
-	if (count == 0) {
-		goto out;
-	}
-	if (filp->f_flags & O_APPEND) {
-		pos = inode->i_size;
-	} else {
-		pos = *ppos;
-	}
-	start = qnx4_ino->i_first_xtnt.xtnt_blk + ((pos >> 9) * 0) - 1;
-	result = 0;
-	extent_end = start + qnx4_ino->i_first_xtnt.xtnt_size - 1;
-	QNX4DEBUG(("qnx4: extent length : [%lu] bytes\n",
-		   qnx4_ino->i_first_xtnt.xtnt_size));
-	while (result < count) {
-		block = start + pos / QNX4_BLOCK_SIZE;
-		if (block > extent_end) {
-			if (qnx4_is_free(inode->i_sb, block) <= 0) {
-				printk("qnx4: next inode is busy -> write aborted.\n");
-				result = -ENOSPC;
-				break;
-			}
-		}
-		if ((bh = bread(inode->i_dev, block,
-				QNX4_BLOCK_SIZE)) == NULL) {
-			printk("qnx4: I/O error on write.\n");
-			result = -EIO;
-			goto out;
-		}
-		if (bh == NULL) {
-			if (result != 0) {
-				result = -ENOSPC;
-			}
-			break;
-		}
-		if (block > extent_end) {
-			qnx4_set_bitmap(inode->i_sb, block, 1);
-			extent_end++;
-			qnx4_ino->i_first_xtnt.xtnt_size = extent_end - start + 1;
-		}
-		c = QNX4_BLOCK_SIZE - (pos % QNX4_BLOCK_SIZE);
-		if (c > count - result) {
-			c = count - result;
-		}
-		if (c != QNX4_BLOCK_SIZE && buffer_uptodate(bh) == 0) {
-			ll_rw_block(WRITE, 1, &bh);
-			wait_on_buffer(bh);
-			if (buffer_uptodate(bh) == 0) {
-				brelse(bh);
-				if (result != 0) {
-					result = -EIO;
-				}
-				break;
-			}
-		}
-		p = bh->b_data + (pos % QNX4_BLOCK_SIZE);
-		c -= copy_from_user(p, buf, c);
-		if (c == 0) {
-			brelse(bh);
-			if (result == 0) {
-				result = -EFAULT;
-			}
-			break;
-		}
-//		update_vm_cache(inode, pos, p, c);
-		mark_buffer_uptodate(bh, 1);
-		mark_buffer_dirty(bh, 0);
-		brelse(bh);
-		pos += c;
-		buf += c;
-		result += c;
-	}
-	if (pos > inode->i_size) {
-		inode->i_size = pos;
-	}
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	*ppos = pos;
-	mark_inode_dirty(inode);
-
-      out:
-	return result;
-}
-#endif
 
 /*
  * We have mostly NULL's here: the current defaults are ok for
@@ -150,7 +26,7 @@
 {
 	read:			generic_file_read,
 #ifdef CONFIG_QNX4FS_RW
-	write:			qnx4_file_write,
+	write:			generic_file_write,
 #endif
 	mmap:			generic_file_mmap,
 #ifdef CONFIG_QNX4FS_RW
@@ -161,10 +37,7 @@
 struct inode_operations qnx4_file_inode_operations =
 {
 	default_file_ops:	&qnx4_file_operations,
-	get_block:		qnx4_get_block,
-	readpage:		block_read_full_page,
 #ifdef CONFIG_QNX4FS_RW
-	writepage:		block_write_full_page,
 	truncate:		qnx4_truncate,
 #endif
 };
diff -u --recursive --new-file v2.3.42/linux/fs/qnx4/fsync.c linux/fs/qnx4/fsync.c
--- v2.3.42/linux/fs/qnx4/fsync.c	Tue Jun 29 09:22:08 1999
+++ linux/fs/qnx4/fsync.c	Wed Feb  9 18:52:20 2000
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/locks.h>
+#include <linux/smp_lock.h>
 
 #include <linux/fs.h>
 #include <linux/qnx4_fs.h>
@@ -156,10 +157,12 @@
 	      S_ISLNK(inode->i_mode)))
 		return -EINVAL;
 
+	lock_kernel();
 	for (wait = 0; wait <= 1; wait++) {
 		err |= sync_direct(inode, wait);
 	}
 	err |= qnx4_sync_inode(inode);
+	unlock_kernel();
 	return (err < 0) ? -EIO : 0;
 }
 
diff -u --recursive --new-file v2.3.42/linux/fs/qnx4/inode.c linux/fs/qnx4/inode.c
--- v2.3.42/linux/fs/qnx4/inode.c	Tue Feb  1 01:35:44 2000
+++ linux/fs/qnx4/inode.c	Thu Feb 10 12:16:59 2000
@@ -423,6 +423,31 @@
 	return;
 }
 
+static int qnx4_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,qnx4_get_block);
+}
+static int qnx4_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,qnx4_get_block);
+}
+static int qnx4_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return cont_prepare_write(page,from,to,qnx4_get_block,
+		&((struct inode*)page->mapping->host)->u.qnx4_i.mmu_private);
+}
+static int qnx4_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,qnx4_get_block);
+}
+struct address_space_operations qnx4_aops = {
+	readpage: qnx4_readpage,
+	writepage: qnx4_writepage,
+	prepare_write: qnx4_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: qnx4_bmap
+};
+
 static void qnx4_read_inode(struct inode *inode)
 {
 	struct buffer_head *bh;
@@ -461,14 +486,17 @@
 	inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
 
 	memcpy(&inode->u.qnx4_i, (struct qnx4_inode_info *) raw_inode, QNX4_DIR_ENTRY_SIZE);
-	inode->i_op = &qnx4_file_inode_operations;
-	if (S_ISREG(inode->i_mode))
+	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &qnx4_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
+		inode->i_mapping->a_ops = &qnx4_aops;
+		inode->u.qnx4_i.mmu_private = inode->i_size;
+	} else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &qnx4_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &qnx4_symlink_inode_operations;
-	else
+	else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_mapping->a_ops = &qnx4_aops;
+		inode->u.qnx4_i.mmu_private = inode->i_size;
+	} else
 		/* HUH??? Where is device number? Oh, well... */
 		init_special_inode(inode, inode->i_mode, 0);
 
diff -u --recursive --new-file v2.3.42/linux/fs/qnx4/symlinks.c linux/fs/qnx4/symlinks.c
--- v2.3.42/linux/fs/qnx4/symlinks.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/qnx4/symlinks.c	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/* 
- * QNX4 file system, Linux implementation.
- * 
- * Version : 0.2.1
- * 
- * Using parts of the xiafs filesystem.
- * 
- * History :
- * 
- * 28-05-1998 by Richard Frowijn : first release.
- * 21-06-1998 by Frank Denis : ugly changes to make it compile on Linux 2.1.99+
- */
-
-#include <linux/fs.h>
-#include <linux/qnx4_fs.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations qnx4_symlink_inode_operations =
-{
-	readlink:		page_readlink,
-	follow_link:		page_follow_link,
-	get_block:		qnx4_get_block,
-	readpage:		block_read_full_page,
-};
diff -u --recursive --new-file v2.3.42/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.3.42/linux/fs/romfs/inode.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/romfs/inode.c	Thu Feb 10 12:16:59 2000
@@ -446,47 +446,21 @@
 
 /* Mapping from our types to the kernel */
 
+static struct address_space_operations romfs_aops = {
+	readpage: romfs_readpage
+};
+
 static struct file_operations romfs_file_operations = {
-	NULL,			/* lseek - default */
-        generic_file_read,	/* read */
-	NULL,			/* write - bad */
-	NULL,			/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
+	read:		generic_file_read,
+	mmap:		generic_file_mmap,
 };
 
 static struct inode_operations romfs_file_inode_operations = {
 	&romfs_file_operations,
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block -- not really */
-	romfs_readpage,		/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static struct file_operations romfs_dir_operations = {
-	NULL,			/* lseek - default */
-        NULL,			/* read */
-	NULL,			/* write - bad */
-	romfs_readdir,		/* readdir */
+	readdir:	romfs_readdir,
 };
 
 /* Merged dir/symlink op table.  readdir/lookup/readlink/follow_link
@@ -497,27 +471,6 @@
 	&romfs_dir_operations,
 	NULL,			/* create */
 	romfs_lookup,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
-};
-
-static struct inode_operations romfs_link_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
-	readpage:	romfs_readpage
 };
 
 static mode_t romfs_modemap[] =
@@ -531,7 +484,7 @@
 	NULL,				/* hardlink, handled elsewhere */
 	&romfs_dir_inode_operations,
 	&romfs_file_inode_operations,
-	&romfs_link_inode_operations,
+	&page_symlink_inode_operations,
 	NULL,				/* device/fifo/socket nodes, */
 	NULL,				/*   set by init_special_inode */
 	NULL,
@@ -587,6 +540,8 @@
 		i->i_mode = ino;
 		if (S_ISDIR(ino))
 			i->i_size = i->u.romfs_i.i_metasize;
+		else
+			i->i_data.a_ops = &romfs_aops;
 	} else {
 		/* depending on MBZ for sock/fifos */
 		nextfh = ntohl(ri.spec);
diff -u --recursive --new-file v2.3.42/linux/fs/select.c linux/fs/select.c
--- v2.3.42/linux/fs/select.c	Tue Feb  1 01:35:44 2000
+++ linux/fs/select.c	Tue Feb  8 14:55:35 2000
@@ -43,6 +43,39 @@
  * Linus noticed.  -- jrs
  */
 
+static poll_table* alloc_wait(int nfds)
+{
+	poll_table* out;
+	poll_table* walk;
+
+	out = (poll_table *) __get_free_page(GFP_KERNEL);
+	if(out==NULL)
+		return NULL;
+	out->nr = 0;
+	out->entry = (struct poll_table_entry *)(out + 1);
+	out->next = NULL;
+	nfds -=__MAX_POLL_TABLE_ENTRIES;
+	walk = out;
+	while(nfds > 0) {
+		poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL);
+		if (!tmp) {
+			while(out != NULL) {
+				tmp = out->next;
+				free_page((unsigned long)out);
+				out = tmp;
+			}
+			return NULL;
+		}
+		tmp->nr = 0;
+		tmp->entry = (struct poll_table_entry *)(tmp + 1);
+		tmp->next = NULL;
+		walk->next = tmp;
+		walk = tmp;
+		nfds -=__MAX_POLL_TABLE_ENTRIES;
+	}
+	return out;
+}
+
 static void free_wait(poll_table * p)
 {
 	struct poll_table_entry * entry;
@@ -67,7 +100,6 @@
 	for (;;) {
 		if (p->nr < __MAX_POLL_TABLE_ENTRIES) {
 			struct poll_table_entry * entry;
-ok_table:
 		 	entry = p->entry + p->nr;
 		 	get_file(filp);
 		 	entry->filp = filp;
@@ -77,17 +109,6 @@
 			p->nr++;
 			return;
 		}
-		if (p->next == NULL) {
-			poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL);
-			if (!tmp)
-				return;
-			tmp->nr = 0;
-			tmp->entry = (struct poll_table_entry *)(tmp + 1);
-			tmp->next = NULL;
-			p->next = tmp;
-			p = tmp;
-			goto ok_table;
-		}
 		p = p->next;
 	}
 }
@@ -152,33 +173,28 @@
 
 int do_select(int n, fd_set_bits *fds, long *timeout)
 {
-	poll_table *wait_table, *wait;
+	poll_table *wait, *orig_wait;
 	int retval, i, off;
 	long __timeout = *timeout;
 
-	wait = wait_table = NULL;
-	if (__timeout) {
-		wait_table = (poll_table *) __get_free_page(GFP_KERNEL);
-		if (!wait_table)
-			return -ENOMEM;
-
-		wait_table->nr = 0;
-		wait_table->entry = (struct poll_table_entry *)(wait_table + 1);
-		wait_table->next = NULL;
-		wait = wait_table;
-	}
+	orig_wait = wait = NULL;
 
-	read_lock(&current->files->file_lock);
+ 	read_lock(&current->files->file_lock);
 	retval = max_select_fd(n, fds);
 	read_unlock(&current->files->file_lock);
 
-	lock_kernel();
 	if (retval < 0)
-		goto out;
+		return retval;
 	n = retval;
+	if (__timeout) {
+ 		orig_wait = wait = alloc_wait(n);
+ 		if (!wait)
+			return -ENOMEM;
+ 	}
 	retval = 0;
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
+		lock_kernel();
 		for (i = 0 ; i < n; i++) {
 			unsigned long bit = BIT(i);
 			unsigned long mask;
@@ -211,6 +227,7 @@
 				wait = NULL;
 			}
 		}
+		unlock_kernel();
 		wait = NULL;
 		if (retval || !__timeout || signal_pending(current))
 			break;
@@ -218,15 +235,12 @@
 	}
 	current->state = TASK_RUNNING;
 
-out:
-	if (*timeout)
-		free_wait(wait_table);
+	free_wait(orig_wait);
 
 	/*
 	 * Up-to-date the caller timeout.
 	 */
 	*timeout = __timeout;
-	unlock_kernel();
 	return retval;
 }
 
@@ -334,29 +348,36 @@
 
 #define POLLFD_PER_PAGE  ((PAGE_SIZE) / sizeof(struct pollfd))
 
-static void do_pollfd(struct pollfd * fdp, poll_table * wait, int *count)
+static void do_pollfd(unsigned int num, struct pollfd * fdpage,
+	poll_table ** pwait, int *count)
 {
-	int fd;
-	unsigned int mask;
+	int i;
 
-	mask = 0;
-	fd = fdp->fd;
-	if (fd >= 0) {
-		struct file * file = fget(fd);
-		mask = POLLNVAL;
-		if (file != NULL) {
-			mask = DEFAULT_POLLMASK;
-			if (file->f_op && file->f_op->poll)
-			mask = file->f_op->poll(file, wait);
-			mask &= fdp->events | POLLERR | POLLHUP;
-			fput(file);
-		}
-		if (mask) {
-			wait = NULL;
-			(*count)++;
+	for (i = 0; i < num; i++) {
+		int fd;
+		unsigned int mask;
+		struct pollfd *fdp;
+
+		mask = 0;
+		fdp = fdpage+i;
+		fd = fdp->fd;
+		if (fd >= 0) {
+			struct file * file = fget(fd);
+			mask = POLLNVAL;
+			if (file != NULL) {
+				mask = DEFAULT_POLLMASK;
+				if (file->f_op && file->f_op->poll)
+					mask = file->f_op->poll(file, *pwait);
+				mask &= fdp->events | POLLERR | POLLHUP;
+				fput(file);
+			}
+			if (mask) {
+				*pwait = NULL;
+				(*count)++;
+			}
 		}
+		fdp->revents = mask;
 	}
-	fdp->revents = mask;
 }
 
 static int do_poll(unsigned int nfds, unsigned int nchunks, unsigned int nleft, 
@@ -365,16 +386,13 @@
 	int count = 0;
 
 	for (;;) {
-		unsigned int i, j;
+		unsigned int i;
 
 		set_current_state(TASK_INTERRUPTIBLE);
 		for (i=0; i < nchunks; i++)
-			for (j = 0; j < POLLFD_PER_PAGE; j++)
-				do_pollfd(fds[i] + j, wait, &count);
+			do_pollfd(POLLFD_PER_PAGE, fds[i], &wait, &count);
 		if (nleft)
-			for (j = 0; j < nleft; j++)
-				do_pollfd(fds[nchunks] + j, wait, &count);
-
+			do_pollfd(nleft, fds[nchunks], &wait, &count);
 		wait = NULL;
 		if (count || !timeout || signal_pending(current))
 			break;
@@ -388,7 +406,7 @@
 {
 	int i, j, fdcount, err;
 	struct pollfd **fds;
-	poll_table *wait_table = NULL, *wait = NULL;
+	poll_table *wait = NULL;
 	int nchunks, nleft;
 
 	/* Do a sanity check on nfds ... */
@@ -403,16 +421,12 @@
 			timeout = MAX_SCHEDULE_TIMEOUT;
 	}
 
-	err = -ENOMEM;
 	if (timeout) {
-		wait_table = (poll_table *) __get_free_page(GFP_KERNEL);
-		if (!wait_table)
-			goto out;
-		wait_table->nr = 0;
-		wait_table->entry = (struct poll_table_entry *)(wait_table + 1);
-		wait_table->next = NULL;
-		wait = wait_table;
+		wait = alloc_wait(nfds);
+		if (!wait)
+			return -ENOMEM;
 	}
+	err = -ENOMEM;
 
 	fds = NULL;
 	if (nfds != 0) {
@@ -473,7 +487,6 @@
 	if (nfds != 0)
 		kfree(fds);
 out:
-	if (wait)
-		free_wait(wait_table);
+	free_wait(wait);
 	return err;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.3.42/linux/fs/smbfs/dir.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/smbfs/dir.c	Thu Feb 10 12:16:59 2000
@@ -32,17 +32,10 @@
 
 static struct file_operations smb_dir_operations =
 {
-	NULL,			/* lseek - default */
-	smb_dir_read,		/* read - bad */
-	NULL,			/* write - bad */
-	smb_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	smb_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	smb_dir_open,		/* open(struct inode *, struct file *) */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* fsync */
+	read:		smb_dir_read,
+	readdir:	smb_readdir,
+	ioctl:		smb_ioctl,
+	open:		smb_dir_open,
 };
 
 struct inode_operations smb_dir_inode_operations =
@@ -59,9 +52,6 @@
 	smb_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	NULL,			/* permission */
 	smb_revalidate_inode,	/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.3.42/linux/fs/smbfs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/smbfs/file.c	Thu Feb 10 12:16:59 2000
@@ -260,20 +260,31 @@
  * If the writer ends up delaying the write, the writer needs to
  * increment the page use counts until he is done with the page.
  */
-static int smb_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int smb_prepare_write(struct page *page, unsigned offset, unsigned to)
+{
+	kmap(page);
+	return 0;
+}
+
+static int smb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
 	int status;
 
-	bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
 	status = -EFAULT;
-	if (bytes) {
-		lock_kernel();
-		status = smb_updatepage(file, page, offset, bytes);
-		unlock_kernel();
-	}
+	lock_kernel();
+	status = smb_updatepage(file, page, offset, to-offset);
+	unlock_kernel();
+	kunmap(page);
 	return status;
 }
 
+struct address_space_operations smb_file_aops = {
+	readpage: smb_readpage,
+	writepage: smb_writepage,
+	prepare_write: smb_prepare_write,
+	commit_write: smb_commit_write
+};
+
 /* 
  * Write to a file (through the page cache).
  */
@@ -305,7 +316,7 @@
 
 	if (count > 0)
 	{
-		result = generic_file_write(file, buf, count, ppos, smb_write_one_page);
+		result = generic_file_write(file, buf, count, ppos);
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
 (long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime,
@@ -367,19 +378,13 @@
 
 static struct file_operations smb_file_operations =
 {
-	NULL,			/* lseek - default */
-	smb_file_read,		/* read */
-	smb_file_write,		/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	smb_ioctl,		/* ioctl */
-	smb_file_mmap,		/* mmap(struct file*, struct vm_area_struct*) */
-	smb_file_open,		/* open(struct inode*, struct file*) */
-	NULL,			/* flush */
-	smb_file_release,	/* release(struct inode*, struct file*) */
-	smb_fsync,		/* fsync(struct file*, struct dentry*) */
-	NULL,			/* fasync(struct file*, int) */
-	NULL			/* lock(struct file*, int, struct file_lock*) */
+	read:		smb_file_read,
+	write:		smb_file_write,
+	ioctl:		smb_ioctl,
+	mmap:		smb_file_mmap,
+	open:		smb_file_open,
+	release:	smb_file_release,
+	fsync:		smb_fsync,
 };
 
 struct inode_operations smb_file_inode_operations =
@@ -396,9 +401,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	smb_readpage,		/* readpage */
-	smb_writepage,		/* writepage */
 	NULL,			/* truncate */
 	smb_file_permission,	/* permission */
 	smb_revalidate_inode,	/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.3.42/linux/fs/smbfs/inode.c	Fri Oct 15 15:25:14 1999
+++ linux/fs/smbfs/inode.c	Thu Feb 10 12:16:59 2000
@@ -82,9 +82,10 @@
 	result->i_ino = fattr->f_ino;
 	memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i));
 	smb_set_inode_attr(result, fattr);
-	if (S_ISREG(result->i_mode))
+	if (S_ISREG(result->i_mode)) {
 		result->i_op = &smb_file_inode_operations;
-	else if (S_ISDIR(result->i_mode))
+		result->i_data.a_ops = &smb_file_aops;
+	} else if (S_ISDIR(result->i_mode))
 		result->i_op = &smb_dir_inode_operations;
 	else
 		result->i_op = NULL;
diff -u --recursive --new-file v2.3.42/linux/fs/stat.c linux/fs/stat.c
--- v2.3.42/linux/fs/stat.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/stat.c	Mon Feb  7 19:45:28 2000
@@ -284,7 +284,7 @@
 
 
 /* ---------- LFS-64 ----------- */
-#if !defined(__alpha__)
+#if !defined(__alpha__) && !defined(__ia64__)
 
 static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
 {
diff -u --recursive --new-file v2.3.42/linux/fs/super.c linux/fs/super.c
--- v2.3.42/linux/fs/super.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/super.c	Wed Feb  9 19:10:14 2000
@@ -1378,7 +1378,10 @@
 		bdev = do_umount(old_root_dev,1, 0);
 		if (!IS_ERR(bdev)) {
 			printk("okay\n");
-			invalidate_buffers(old_root_dev);
+			/* special: the old device driver is going to be
+			   a ramdisk and the point of this call is to free its
+			   protected memory (even if dirty). */
+			destroy_buffers(old_root_dev);
 			if (bdev) {
 				blkdev_put(bdev, BDEV_FS);
 				bdput(bdev);
diff -u --recursive --new-file v2.3.42/linux/fs/sysv/Makefile linux/fs/sysv/Makefile
--- v2.3.42/linux/fs/sysv/Makefile	Thu Jun 25 10:57:35 1998
+++ linux/fs/sysv/Makefile	Thu Feb 10 12:16:59 2000
@@ -8,8 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
 O_TARGET := sysv.o
-O_OBJS   := ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \
-		fsync.o truncate.o
+O_OBJS   := ialloc.o balloc.o inode.o file.o dir.o namei.o fsync.o truncate.o
 M_OBJS   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/fs/sysv/dir.c linux/fs/sysv/dir.c
--- v2.3.42/linux/fs/sysv/dir.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/sysv/dir.c	Thu Feb 10 12:16:59 2000
@@ -30,17 +30,9 @@
 static int sysv_readdir(struct file *, void *, filldir_t);
 
 static struct file_operations sysv_dir_operations = {
-	NULL,			/* lseek - default */
-	sysv_dir_read,		/* read */
-	NULL,			/* write - bad */
-	sysv_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	file_fsync		/* default fsync */
+	read:		sysv_dir_read,
+	readdir:	sysv_readdir,
+	fsync:		file_fsync,
 };
 
 /*
@@ -57,14 +49,6 @@
 	sysv_rmdir,		/* rmdir */
 	sysv_mknod,		/* mknod */
 	sysv_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
diff -u --recursive --new-file v2.3.42/linux/fs/sysv/file.c linux/fs/sysv/file.c
--- v2.3.42/linux/fs/sysv/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/sysv/file.c	Thu Feb 10 12:16:59 2000
@@ -23,59 +23,18 @@
 #include <linux/locks.h>
 #include <linux/pagemap.h>
 
-#include <asm/uaccess.h>
-
-#define	NBUF	32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-sysv_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	return generic_file_write(file, buf, count,
-				  ppos, block_write_partial_page);
-}
-
 /*
  * We have mostly NULLs here: the current defaults are OK for
  * the coh filesystem.
  */
 static struct file_operations sysv_file_operations = {
-	NULL,			/* lseek - default */
-	generic_file_read,	/* read */
-	sysv_file_write,	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-	NULL,			/* flush */
-	NULL,			/* release */
-	sysv_sync_file,		/* fsync */
-	NULL,			/* fasync */
+	read:		generic_file_read,
+	write:		generic_file_write,
+	mmap:		generic_file_mmap,
+	fsync:		sysv_sync_file,
 };
 
 struct inode_operations sysv_file_inode_operations = {
-	&sysv_file_operations,	/* default file operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	sysv_get_block,		/* get_block */
-	block_read_full_page,	/* readpage */
-	block_write_full_page,	/* writepage */
-	sysv_truncate,		/* truncate */
-	NULL,   		/* permission */
-	NULL			/* revalidate */
+	&sysv_file_operations,
+	truncate:	sysv_truncate,
 };
diff -u --recursive --new-file v2.3.42/linux/fs/sysv/fsync.c linux/fs/sysv/fsync.c
--- v2.3.42/linux/fs/sysv/fsync.c	Tue Jun 29 09:22:08 1999
+++ linux/fs/sysv/fsync.c	Thu Feb 10 12:16:59 2000
@@ -16,9 +16,9 @@
 
 #include <linux/errno.h>
 #include <linux/stat.h>
-
 #include <linux/fs.h>
 #include <linux/sysv_fs.h>
+#include <linux/smp_lock.h>
 
 
 /* return values: 0 means OK/done, 1 means redo, -1 means I/O error. */
@@ -187,6 +187,7 @@
 	     S_ISLNK(inode->i_mode)))
 		return -EINVAL;
 
+	lock_kernel();
 	for (wait=0; wait<=1; wait++) {
 		err |= sync_direct(inode, wait);
 		err |= sync_indirect(inode, inode->u.sysv_i.i_data+10, 0, wait);
@@ -194,5 +195,6 @@
 		err |= sync_tindirect(inode, inode->u.sysv_i.i_data+12, 0, wait);
 	}
 	err |= sysv_sync_inode (inode);
+	unlock_kernel();
 	return (err < 0) ? -EIO : 0;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.3.42/linux/fs/sysv/inode.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/sysv/inode.c	Thu Feb 10 12:16:59 2000
@@ -832,7 +832,7 @@
 	return result;
 }
 
-int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+static int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
 {
 	struct super_block *sb;
 	int ret, err, new;
@@ -961,6 +961,30 @@
 	return NULL;
 }
 
+static int sysv_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,sysv_get_block);
+}
+static int sysv_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,sysv_get_block);
+}
+static int sysv_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page,from,to,sysv_get_block);
+}
+static int sysv_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,sysv_get_block);
+}
+struct address_space_operations sysv_aops = {
+	readpage: sysv_readpage,
+	writepage: sysv_writepage,
+	prepare_write: sysv_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: sysv_bmap
+};
+
 #ifdef __BIG_ENDIAN
 
 static inline unsigned long read3byte (unsigned char * p)
@@ -1059,13 +1083,15 @@
 		for (block = 0; block < 10+1+1+1; block++)
 			inode->u.sysv_i.i_data[block] =
 				read3byte(&raw_inode->i_a.i_addb[3*block]);
-	if (S_ISREG(inode->i_mode))
+	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &sysv_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
+		inode->i_mapping->a_ops = &sysv_aops;
+	} else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &sysv_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &sysv_symlink_inode_operations;
-	else
+	else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_mapping->a_ops = &sysv_aops;
+	} else
 		init_special_inode(inode, inode->i_mode,raw_inode->i_a.i_rdev);
 	brelse(bh);
 }
diff -u --recursive --new-file v2.3.42/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.3.42/linux/fs/sysv/namei.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/sysv/namei.c	Thu Feb 10 12:16:59 2000
@@ -204,6 +204,7 @@
 	if (!inode) 
 		return -ENOSPC;
 	inode->i_op = &sysv_file_inode_operations;
+	inode->i_mapping->a_ops = &sysv_aops;
 	inode->i_mode = mode;
 	mark_inode_dirty(inode);
 	error = sysv_add_entry(dir, dentry->d_name.name,
@@ -455,7 +456,8 @@
 		goto out;
 
 	inode->i_mode = S_IFLNK | 0777;
-	inode->i_op = &sysv_symlink_inode_operations;
+	inode->i_op = &page_symlink_inode_operations;
+	inode->i_mapping->a_ops = &sysv_aops;
 	err = block_symlink(inode, symname, l);
 	if (err)
 		goto out_no_entry;
diff -u --recursive --new-file v2.3.42/linux/fs/sysv/symlink.c linux/fs/sysv/symlink.c
--- v2.3.42/linux/fs/sysv/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/sysv/symlink.c	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/*
- *  linux/fs/sysv/symlink.c
- *
- *  minix/symlink.c
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  coh/symlink.c
- *  Copyright (C) 1993  Pascal Haible, Bruno Haible
- *
- *  sysv/symlink.c
- *  Copyright (C) 1993  Bruno Haible
- *
- *  SystemV/Coherent symlink handling code
- */
-
-#include <linux/sysv_fs.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations sysv_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
-	get_block:	sysv_get_block,
-	readpage:	block_read_full_page
-};
diff -u --recursive --new-file v2.3.42/linux/fs/udf/dir.c linux/fs/udf/dir.c
--- v2.3.42/linux/fs/udf/dir.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/dir.c	Thu Feb 10 12:16:59 2000
@@ -50,19 +50,9 @@
 /* readdir and lookup functions */
 
 static struct file_operations udf_dir_operations = {
-	NULL,			/* lllseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	udf_readdir,	/* readdir */
-	NULL,			/* poll */
-	udf_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	udf_sync_file,	/* fsync */
-	NULL,			/* fasync */
-	NULL			/* lock */
+	readdir:	udf_readdir,
+	ioctl:		udf_ioctl,
+	fsync:		udf_sync_file,
 };
 
 struct inode_operations udf_dir_inode_operations = {
@@ -90,14 +80,6 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 #endif
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/fs/udf/file.c linux/fs/udf/file.c
--- v2.3.42/linux/fs/udf/file.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/file.c	Thu Feb 10 12:16:59 2000
@@ -72,110 +72,119 @@
 	return offset;
 }
 
-static inline void remove_suid(struct inode * inode)
+static int udf_adinicb_readpage(struct dentry *dentry, struct page * page)
 {
-	unsigned int mode;
+	struct inode *inode = dentry->d_inode;
 
-	/* set S_IGID if S_IXGRP is set, and always set S_ISUID */
-	mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
-	/* was any of the uid bits set? */
-	mode &= inode->i_mode;
-	if (mode && !capable(CAP_FSETID))
-	{
-		inode->i_mode &= ~mode;
-		mark_inode_dirty(inode);
-	}
-}
-
-static ssize_t udf_file_write(struct file * file, const char * buf,
-	size_t count, loff_t *ppos)
-{
-	ssize_t retval;
-	struct inode *inode = file->f_dentry->d_inode;
+	struct buffer_head *bh;
+	unsigned long kaddr = 0;
 
-	retval = generic_file_write(file, buf, count, ppos, block_write_partial_page);
+	if (!PageLocked(page))
+		PAGE_BUG(page);
 
-	if (retval > 0)
-	{
-		remove_suid(inode);
-		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-		UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
-		mark_inode_dirty(inode);
-	}
-	return retval;
+	kaddr = kmap(page);
+	memset((char *)kaddr, 0, PAGE_CACHE_SIZE);
+	bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
+	ll_rw_block (READ, 1, &bh);
+	wait_on_buffer(bh);
+	memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode),
+		inode->i_size);
+	brelse(bh);
+	SetPageUptodate(page);
+	kunmap(page);
+	UnlockPage(page);
+	return 0;
 }
 
-int udf_write_partial_page_adinicb(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int udf_adinicb_writepage(struct dentry *dentry, struct page *page)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	int err = 0, block;
+	struct inode *inode = dentry->d_inode;
+
 	struct buffer_head *bh;
 	unsigned long kaddr = 0;
 
 	if (!PageLocked(page))
 		BUG();
-	if (offset < 0 || offset >= (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode)))
-		BUG();
-	if (bytes+offset < 0 || bytes+offset > (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode)))
-		BUG();
 
 	kaddr = kmap(page);
-	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-	bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
+	bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
 	if (!buffer_uptodate(bh))
 	{
 		ll_rw_block (READ, 1, &bh);
 		wait_on_buffer(bh);
 	}
-	err = copy_from_user((char *)kaddr + offset, buf, bytes);
+	memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr,
+		inode->i_size);
+	ll_rw_block (WRITE, 1, &bh);
+	wait_on_buffer(bh);
+	brelse(bh);
+	SetPageUptodate(page);
+	kunmap(page);
+	return 0;
+}
+
+static int udf_adinicb_prepare_write(struct page *page, unsigned offset, unsigned to)
+{
+	kmap(page);
+	return 0;
+}
+
+static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct buffer_head *bh;
+	char *kaddr = (char*)page_address(page);
+	bh = bread (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
+	if (!buffer_uptodate(bh)) {
+		ll_rw_block (READ, 1, &bh);
+		wait_on_buffer(bh);
+	}
 	memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
-		(char *)kaddr + offset, bytes);
+		kaddr + offset, to-offset);
 	mark_buffer_dirty(bh, 0);
 	brelse(bh);
 	kunmap(page);
 	SetPageUptodate(page);
-	return bytes;
+	return 0;
 }
 
-static ssize_t udf_file_write_adinicb(struct file * file, const char * buf,
+struct address_space_operations udf_adinicb_aops = {
+	readpage: udf_adinicb_readpage,
+	writepage: udf_adinicb_writepage,
+	prepare_write: udf_adinicb_prepare_write,
+	commit_write: udf_adinicb_commit_write
+};
+
+static ssize_t udf_file_write(struct file * file, const char * buf,
 	size_t count, loff_t *ppos)
 {
 	ssize_t retval;
 	struct inode *inode = file->f_dentry->d_inode;
 	int err, pos;
 
-	if (file->f_flags & O_APPEND)
-		pos = inode->i_size;
-	else
-		pos = *ppos;
+	if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+		if (file->f_flags & O_APPEND)
+			pos = inode->i_size;
+		else
+			pos = *ppos;
 
-	if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
-		pos + count))
-	{
-		udf_expand_file_adinicb(file, pos + count, &err);
-		if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
-		{
-			udf_debug("udf_expand_adinicb: err=%d\n", err);
-			return err;
+		if (inode->i_sb->s_blocksize <
+		    (udf_file_entry_alloc_offset(inode) + pos + count)) {
+			udf_expand_file_adinicb(file, pos + count, &err);
+			if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+				udf_debug("udf_expand_adinicb: err=%d\n", err);
+				return err;
+			}
+		} else {
+			if (pos + count > inode->i_size)
+				UDF_I_LENALLOC(inode) = pos + count;
+			else
+				UDF_I_LENALLOC(inode) = inode->i_size;
 		}
-		else
-			return udf_file_write(file, buf, count, ppos);
-	}
-	else
-	{
-		if (pos + count > inode->i_size)
-			UDF_I_LENALLOC(inode) = pos + count;
-		else
-			UDF_I_LENALLOC(inode) = inode->i_size;
 	}
 
-	retval = generic_file_write(file, buf, count, ppos, udf_write_partial_page_adinicb);
-
-	if (retval > 0)
-	{
-		remove_suid(inode);
-		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+	retval = generic_file_write(file, buf, count, ppos);
+	if (retval > 0) {
 		UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
 		mark_inode_dirty(inode);
 	}
@@ -338,83 +347,19 @@
 }
 
 static struct file_operations udf_file_operations = {
-	udf_file_llseek,		/* llseek */
-	generic_file_read,		/* read */
-	udf_file_write,			/* write */
-	NULL,					/* readdir */
-	NULL,					/* poll */
-	udf_ioctl,				/* ioctl */
-	generic_file_mmap,		/* mmap */
-	udf_open_file,			/* open */
-	NULL,					/* flush */
-	udf_release_file,		/* release */
-	udf_sync_file,			/* fsync */
-	NULL,					/* fasync */
-	NULL					/* lock */
+	llseek:		udf_file_llseek,
+	read:		generic_file_read,
+	write:		udf_file_write,
+	ioctl:		udf_ioctl,
+	mmap:		generic_file_mmap,
+	open:		udf_open_file,
+	release:	udf_release_file,
+	fsync:		udf_sync_file,
 };
 
 struct inode_operations udf_file_inode_operations = {
 	&udf_file_operations,
-	NULL,					/* create */
-	NULL,					/* lookup */
-	NULL,					/* link */
-	NULL,					/* unlink */
-	NULL,					/* symlink */
-	NULL,					/* mkdir */
-	NULL,					/* rmdir */
-	NULL,					/* mknod */
-	NULL,					/* rename */
-	NULL,					/* readlink */
-	NULL,					/* follow_link */
-	udf_get_block,			/* get_block */
-	block_read_full_page,	/* readpage */
-	block_write_full_page,	/* writepage */
-#if CONFIG_UDF_RW == 1
-	udf_truncate,			/* truncate */
-#else
-	NULL,					/* truncate */
-#endif
-	NULL,					/* permission */
-	NULL					/* revalidate */
-};
-
-static struct file_operations udf_file_operations_adinicb = {
-	udf_file_llseek,		/* llseek */
-	generic_file_read,		/* read */
-	udf_file_write_adinicb,	/* write */
-	NULL,					/* readdir */
-	NULL,					/* poll */
-	udf_ioctl,				/* ioctl */
-	NULL,					/* mmap */
-	NULL, 					/* open */
-	NULL,					/* flush */
-	udf_release_file,		/* release */
-	udf_sync_file_adinicb,	/* fsync */
-	NULL,					/* fasync */
-	NULL					/* lock */
-};
-
-struct inode_operations udf_file_inode_operations_adinicb = {
-	&udf_file_operations_adinicb,
-	NULL,					/* create */
-	NULL,					/* lookup */
-	NULL,					/* link */
-	NULL,					/* unlink */
-	NULL,					/* symlink */
-	NULL,					/* mkdir */
-	NULL,					/* rmdir */
-	NULL,					/* mknod */
-	NULL,					/* rename */
-	NULL,					/* readlink */
-	NULL,					/* follow_link */
-	udf_get_block,			/* get_block */
-	udf_readpage_adinicb,	/* readpage */
-	udf_writepage_adinicb,	/* writepage */
 #if CONFIG_UDF_RW == 1
-	udf_truncate_adinicb,	/* truncate */
-#else
-	NULL,					/* truncate */
+	truncate:	udf_truncate,
 #endif
-	NULL,					/* permission */
-	NULL					/* revalidate */
 };
diff -u --recursive --new-file v2.3.42/linux/fs/udf/fsync.c linux/fs/udf/fsync.c
--- v2.3.42/linux/fs/udf/fsync.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/fsync.c	Thu Feb 10 12:16:59 2000
@@ -27,6 +27,7 @@
 
 #include <linux/fs.h>
 #include <linux/locks.h>
+#include <linux/smp_lock.h>
 #include <linux/udf_fs.h>
 #include "udf_i.h"
 
@@ -100,6 +101,7 @@
 	int wait, err = 0;
 	struct inode *inode = dentry->d_inode;
 
+	lock_kernel();
 	if (S_ISLNK(inode->i_mode) && !(inode->i_blocks)) 
 	{
 		/*
@@ -116,10 +118,6 @@
 	}
 skip:
 	err |= udf_sync_inode (inode);
+	unlock_kernel();
 	return err ? -EIO : 0;
-}
-
-int udf_sync_file_adinicb(struct file * file, struct dentry *dentry)
-{
-	return udf_sync_inode(dentry->d_inode) ? -EIO : 0;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/udf/inode.c linux/fs/udf/inode.c
--- v2.3.42/linux/fs/udf/inode.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/inode.c	Thu Feb 10 12:16:59 2000
@@ -56,6 +56,7 @@
 static void udf_update_extents(struct inode *,
 	long_ad [EXTENT_MERGE_SIZE], int, int,
 	lb_addr, Uint32, struct buffer_head **);
+static int udf_get_block(struct inode *, long, struct buffer_head *, int);
 
 /*
  * udf_put_inode
@@ -96,7 +97,7 @@
 {
 	inode->i_size = 0;
 	if (inode->i_blocks)
-		inode->i_op->truncate(inode);
+		udf_truncate(inode);
 	udf_free_inode(inode);
 }
 
@@ -117,6 +118,30 @@
 	return result;
 }
 
+static int udf_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,udf_get_block);
+}
+static int udf_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,udf_get_block);
+}
+static int udf_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page,from,to,udf_get_block);
+}
+static int udf_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,udf_get_block);
+}
+static struct address_space_operations udf_aops = {
+	readpage: udf_readpage,
+	writepage: udf_writepage,
+	prepare_write: udf_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: udf_bmap
+};
+
 void udf_expand_file_adinicb(struct file * filp, int newsize, int * err)
 {
 	struct inode * inode = filp->f_dentry->d_inode;
@@ -124,12 +149,13 @@
 	struct page *page;
 	unsigned long kaddr = 0;
 
+	/* from now on we have normal address_space methods */
+	inode->i_data.a_ops = &udf_aops;
+
 	if (!UDF_I_LENALLOC(inode))
 	{
 		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
 		mark_inode_dirty(inode);
-		inode->i_op = &udf_file_inode_operations;
-		filp->f_op = inode->i_op->default_file_ops;
 		return;
 	}
 
@@ -156,14 +182,12 @@
 	mark_buffer_dirty(bh, 1);
 	udf_release_data(bh);
 
-	block_write_full_page(filp->f_dentry, page);
+	inode->i_data.a_ops->writepage(filp->f_dentry, page);
 	UnlockPage(page);
 	page_cache_release(page);
 
 	mark_inode_dirty(inode);
 	inode->i_version ++;
-	inode->i_op = &udf_file_inode_operations;
-	filp->f_op = inode->i_op->default_file_ops;
 }
 
 struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
@@ -251,34 +275,7 @@
 	return dbh;
 }
 
-struct buffer_head * udf_getblk(struct inode * inode, long block,
-	int create, int * err)
-{
-	struct buffer_head dummy;
-	int error;
-
-	dummy.b_state = 0;
-	dummy.b_blocknr = -1000;
-	error = udf_get_block(inode, block, &dummy, create);
-	*err = error;
-	if (!error & buffer_mapped(&dummy))
-	{
-		struct buffer_head *bh;
-		bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
-		if (buffer_new(&dummy))
-		{
-			if (!buffer_uptodate(bh))
-				wait_on_buffer(bh);
-			memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
-			mark_buffer_uptodate(bh, 1);
-			mark_buffer_dirty(bh, 1);
-		}
-		return bh;
-	}
-	return NULL;
-}
-
-int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create)
+static int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create)
 {
 	int err, new;
 	struct buffer_head *bh;
@@ -335,6 +332,33 @@
 	goto abort;
 }
 
+struct buffer_head * udf_getblk(struct inode * inode, long block,
+	int create, int * err)
+{
+	struct buffer_head dummy;
+	int error;
+
+	dummy.b_state = 0;
+	dummy.b_blocknr = -1000;
+	error = udf_get_block(inode, block, &dummy, create);
+	*err = error;
+	if (!error & buffer_mapped(&dummy))
+	{
+		struct buffer_head *bh;
+		bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
+		if (buffer_new(&dummy))
+		{
+			if (!buffer_uptodate(bh))
+				wait_on_buffer(bh);
+			memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
+			mark_buffer_uptodate(bh, 1);
+			mark_buffer_dirty(bh, 1);
+		}
+		return bh;
+	}
+	return NULL;
+}
+
 static struct buffer_head * inode_getblk(struct inode * inode, long block,
 	int *err, long *phys, int *new)
 {
@@ -1061,9 +1085,10 @@
 		case FILE_TYPE_NONE:
 		{
 			if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
-				inode->i_op = &udf_file_inode_operations_adinicb;
+				inode->i_data.a_ops = &udf_adinicb_aops;
 			else
-				inode->i_op = &udf_file_inode_operations;
+				inode->i_data.a_ops = &udf_aops;
+			inode->i_op = &udf_file_inode_operations;
 			inode->i_mode |= S_IFREG;
 			break;
 		}
@@ -1084,7 +1109,8 @@
 		}
 		case FILE_TYPE_SYMLINK:
 		{
-			inode->i_op = &udf_symlink_inode_operations;
+			inode->i_data.a_ops = &udf_symlink_aops;
+			inode->i_op = &page_symlink_inode_operations;
 			inode->i_mode = S_IFLNK|S_IRWXUGO;
 			break;
 		}
@@ -1952,59 +1978,4 @@
 	ret = udf_locked_block_map(inode, block);
 	unlock_kernel();
 	return ret;
-}
-
-int udf_readpage_adinicb (struct dentry *dentry, struct page * page)
-{
-	struct inode *inode = dentry->d_inode;
-
-	struct buffer_head *bh;
-	int block;
-	unsigned long kaddr = 0;
-
-	if (!PageLocked(page))
-		PAGE_BUG(page);
-
-	kaddr = kmap(page);
-	memset((char *)kaddr, 0, PAGE_CACHE_SIZE);
-	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-	bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
-	ll_rw_block (READ, 1, &bh);
-	wait_on_buffer(bh);
-	memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode),
-		inode->i_size);
-	brelse(bh);
-	SetPageUptodate(page);
-	kunmap(page);
-	UnlockPage(page);
-	return 0;
-}
-
-int udf_writepage_adinicb (struct dentry *dentry, struct page *page)
-{
-	struct inode *inode = dentry->d_inode;
-
-	struct buffer_head *bh;
-	int block;
-	unsigned long kaddr = 0;
-
-	if (!PageLocked(page))
-		BUG();
-
-	kaddr = kmap(page);
-	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-	bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
-	if (!buffer_uptodate(bh))
-	{
-		ll_rw_block (READ, 1, &bh);
-		wait_on_buffer(bh);
-	}
-	memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr,
-		inode->i_size);
-	ll_rw_block (WRITE, 1, &bh);
-	wait_on_buffer(bh);
-	brelse(bh);
-	SetPageUptodate(page);
-	kunmap(page);
-	return 0;
 }
diff -u --recursive --new-file v2.3.42/linux/fs/udf/namei.c linux/fs/udf/namei.c
--- v2.3.42/linux/fs/udf/namei.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/namei.c	Thu Feb 10 12:16:59 2000
@@ -642,7 +642,8 @@
 	if (!inode)
 		return err;
 
-	inode->i_op = &udf_file_inode_operations_adinicb;
+	inode->i_data.a_ops = &udf_adinicb_aops;
+	inode->i_op = &udf_file_inode_operations;
 	inode->i_mode = mode;
 	mark_inode_dirty(inode);
 
@@ -970,7 +971,8 @@
 		goto out;
 
 	inode->i_mode = S_IFLNK | S_IRWXUGO;
-	inode->i_op = &udf_symlink_inode_operations;
+	inode->i_data.a_ops = &udf_symlink_aops;
+	inode->i_op = &page_symlink_inode_operations;
 
 	bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
 	ea = bh->b_data + udf_file_entry_alloc_offset(inode);
diff -u --recursive --new-file v2.3.42/linux/fs/udf/symlink.c linux/fs/udf/symlink.c
--- v2.3.42/linux/fs/udf/symlink.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/symlink.c	Thu Feb 10 12:16:59 2000
@@ -121,23 +121,6 @@
 /*
  * symlinks can't do much...
  */
-struct inode_operations udf_symlink_inode_operations = {
-	NULL,				/* no file-operations */
-	NULL,				/* create */
-	NULL,				/* lookup */
-	NULL,				/* link */
-	NULL,				/* unlink */
-	NULL,				/* symlink */
-	NULL,				/* mkdir */
-	NULL,				/* rmdir */
-	NULL,				/* mknod */
-	NULL,				/* rename */
-	page_readlink,		/* readlink */
-	page_follow_link,	/* follow_link */
-	NULL,				/* get_block */
-	udf_symlink_filler,	/* readpage */
-	NULL,				/* writepage */
-	NULL,				/* truncate */
-	NULL,				/* permission */
-	NULL				/* revalidate */
+struct address_space_operations udf_symlink_aops = {
+	readpage:	udf_symlink_filler,
 };
diff -u --recursive --new-file v2.3.42/linux/fs/udf/truncate.c linux/fs/udf/truncate.c
--- v2.3.42/linux/fs/udf/truncate.c	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/truncate.c	Thu Feb 10 12:16:59 2000
@@ -188,21 +188,10 @@
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		return;
 
-	udf_trunc(inode);
-
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	mark_inode_dirty(inode);
-}
-
-void udf_truncate_adinicb(struct inode * inode)
-{
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-			S_ISLNK(inode->i_mode)))
-		return;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return;
-
-	UDF_I_LENALLOC(inode) = inode->i_size;
+	if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+		UDF_I_LENALLOC(inode) = inode->i_size;
+	else
+		udf_trunc(inode);
 
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty(inode);
diff -u --recursive --new-file v2.3.42/linux/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h
--- v2.3.42/linux/fs/udf/udfdecl.h	Fri Jan 28 15:09:09 2000
+++ linux/fs/udf/udfdecl.h	Thu Feb 10 12:16:59 2000
@@ -63,8 +63,8 @@
 
 extern struct inode_operations udf_dir_inode_operations;
 extern struct inode_operations udf_file_inode_operations;
-extern struct inode_operations udf_file_inode_operations_adinicb;
-extern struct inode_operations udf_symlink_inode_operations;
+extern struct address_space_operations udf_adinicb_aops;
+extern struct address_space_operations udf_symlink_aops;
 
 struct udf_fileident_bh
 {
@@ -137,9 +137,6 @@
 extern void udf_expand_file_adinicb(struct file *, int, int *);
 extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *);
 extern struct buffer_head * udf_getblk(struct inode *, long, int, int *);
-extern int udf_get_block(struct inode *, long, struct buffer_head *, int);
-extern int udf_readpage_adinicb (struct dentry *, struct page *);
-extern int udf_writepage_adinicb (struct dentry *, struct page *);
 extern struct buffer_head * udf_bread(struct inode *, int, int, int *);
 extern void udf_read_inode(struct inode *);
 extern void udf_put_inode(struct inode *);
@@ -187,14 +184,12 @@
 /* truncate.c */
 extern void udf_trunc(struct inode *);
 extern void udf_truncate(struct inode *);
-extern void udf_truncate_adinicb(struct inode *);
 
 /* balloc.c */
 extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32);
 extern int udf_alloc_blocks(const struct inode *, Uint16, Uint32, Uint32);
 extern int udf_new_block(const struct inode *, Uint16, Uint32, int *);
 extern int udf_sync_file(struct file *, struct dentry *);
-extern int udf_sync_file_adinicb(struct file *, struct dentry *);
 
 /* directory.c */
 extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *);
diff -u --recursive --new-file v2.3.42/linux/fs/ufs/dir.c linux/fs/ufs/dir.c
--- v2.3.42/linux/fs/ufs/dir.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/ufs/dir.c	Thu Feb 10 12:16:59 2000
@@ -178,18 +178,8 @@
 }
 
 static struct file_operations ufs_dir_operations = {
-	NULL,			/* lseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	ufs_readdir,		/* readdir */
-	NULL,			/* select */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	file_fsync,		/* fsync */
-	NULL,			/* fasync */
+	readdir:	ufs_readdir,
+	fsync:		file_fsync,
 };
 
 struct inode_operations ufs_dir_inode_operations = {
@@ -205,9 +195,6 @@
 	ufs_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	ufs_permission,		/* permission */
 	NULL			/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/fs/ufs/file.c linux/fs/ufs/file.c
--- v2.3.42/linux/fs/ufs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/ufs/file.c	Thu Feb 10 12:16:59 2000
@@ -36,11 +36,6 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 
-#define	NBUF	32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
 /*
  * Make sure the offset never goes beyond the 32-bit mark..
  */
@@ -72,86 +67,18 @@
 	return retval;
 }
 
-static inline void remove_suid(struct inode *inode)
-{
-	unsigned int mode;
-
-	/* set S_IGID if S_IXGRP is set, and always set S_ISUID */
-	mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
-	/* was any of the uid bits set? */
-	mode &= inode->i_mode;
-	if (mode && !suser()) {
-		inode->i_mode &= ~mode;
-		mark_inode_dirty(inode);
-	}
-}
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-ufs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	ssize_t retval;
-
-	retval = generic_file_write(file, buf, count,
-				    ppos, block_write_partial_page);
-	if (retval > 0) {
-		struct inode *inode = file->f_dentry->d_inode;
-		remove_suid(inode);
-		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-		mark_inode_dirty(inode);
-	}
-	return retval;
-}
-
-/*
- * Called when an inode is released. Note that this is different
- * from ufs_open: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
- */
-static int ufs_release_file (struct inode * inode, struct file * filp)
-{
-	return 0;
-}
-
 /*
  * We have mostly NULL's here: the current defaults are ok for
  * the ufs filesystem.
  */
 static struct file_operations ufs_file_operations = {
-	ufs_file_lseek,	/* lseek */
-	generic_file_read,	/* read */
-	ufs_file_write, 	/* write */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL, 			/* ioctl */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-	NULL,			/* flush */
-	ufs_release_file,	/* release */
-	NULL, 			/* fsync */
-	NULL,			/* fasync */
+	llseek:		ufs_file_lseek,
+	read:		generic_file_read,
+	write:		generic_file_write,
+	mmap:		generic_file_mmap,
 };
 
 struct inode_operations ufs_file_inode_operations = {
-	&ufs_file_operations,/* default file operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	ufs_getfrag_block,	/* get_block */
-	block_read_full_page,	/* readpage */
-	block_write_full_page,	/* writepage */
-	ufs_truncate,		/* truncate */
-	NULL, 			/* permission */
-	NULL			/* revalidate */
+	&ufs_file_operations,
+	truncate:	ufs_truncate,
 };
diff -u --recursive --new-file v2.3.42/linux/fs/ufs/inode.c linux/fs/ufs/inode.c
--- v2.3.42/linux/fs/ufs/inode.c	Tue Jan 11 22:31:44 2000
+++ linux/fs/ufs/inode.c	Thu Feb 10 12:16:59 2000
@@ -395,7 +395,7 @@
 	return result;
 }
 
-int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create)
+static int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
@@ -540,6 +540,30 @@
 	return NULL;
 }
 
+static int ufs_writepage(struct dentry *dentry, struct page *page)
+{
+	return block_write_full_page(page,ufs_getfrag_block);
+}
+static int ufs_readpage(struct dentry *dentry, struct page *page)
+{
+	return block_read_full_page(page,ufs_getfrag_block);
+}
+static int ufs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+	return block_prepare_write(page,from,to,ufs_getfrag_block);
+}
+static int ufs_bmap(struct address_space *mapping, long block)
+{
+	return generic_block_bmap(mapping,block,ufs_getfrag_block);
+}
+struct address_space_operations ufs_aops = {
+	readpage: ufs_readpage,
+	writepage: ufs_writepage,
+	prepare_write: ufs_prepare_write,
+	commit_write: generic_commit_write,
+	bmap: ufs_bmap
+};
+
 void ufs_read_inode (struct inode * inode)
 {
 	struct super_block * sb;
@@ -619,15 +643,19 @@
 
 	inode->i_op = NULL;
 
-	if (S_ISREG(inode->i_mode))
+	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ufs_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
+		inode->i_mapping->a_ops = &ufs_aops;
+	} else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &ufs_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = inode->i_blocks
-				?&ufs_symlink_inode_operations
-				:&ufs_fast_symlink_inode_operations;
-	else
+	else if (S_ISLNK(inode->i_mode)) {
+		if (!inode->i_blocks)
+			inode->i_op = &ufs_fast_symlink_inode_operations;
+		else {
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_mapping->a_ops = &ufs_aops;
+		}
+	} else
 		init_special_inode(inode, inode->i_mode,
 				   SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
 
diff -u --recursive --new-file v2.3.42/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.3.42/linux/fs/ufs/namei.c	Tue Jan  4 13:57:18 2000
+++ linux/fs/ufs/namei.c	Thu Feb 10 12:16:59 2000
@@ -424,6 +424,7 @@
 	if (!inode)
 		return err;
 	inode->i_op = &ufs_file_inode_operations;
+	inode->i_mapping->a_ops = &ufs_aops;
 	inode->i_mode = mode;
 	mark_inode_dirty(inode);
 	bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
@@ -776,7 +777,8 @@
 
 	if (l > sb->u.ufs_sb.s_uspi->s_maxsymlinklen) {
 		/* slow symlink */
-		inode->i_op = &ufs_symlink_inode_operations;
+		inode->i_op = &page_symlink_inode_operations;
+		inode->i_mapping->a_ops = &ufs_aops;
 		err = block_symlink(inode, symname, l);
 		if (err)
 			goto out_no_entry;
diff -u --recursive --new-file v2.3.42/linux/fs/ufs/symlink.c linux/fs/ufs/symlink.c
--- v2.3.42/linux/fs/ufs/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/ufs/symlink.c	Thu Feb 10 12:16:59 2000
@@ -1,6 +1,8 @@
 /*
  *  linux/fs/ufs/symlink.c
  *
+ * Only fast symlinks left here - the rest is done by generic code. AV, 1999
+ *
  * Copyright (C) 1998
  * Daniel Pirkl <daniel.pirkl@emai.cz>
  * Charles University, Faculty of Mathematics and Physics
@@ -24,7 +26,6 @@
  */
 
 #include <linux/fs.h>
-#include <linux/ufs_fs.h>
 
 static int ufs_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
@@ -41,11 +42,4 @@
 struct inode_operations ufs_fast_symlink_inode_operations = {
 	readlink:	ufs_readlink,
 	follow_link:	ufs_follow_link,
-};
-
-struct inode_operations ufs_symlink_inode_operations = {
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
-	get_block:	ufs_getfrag_block,
-	readpage:	block_read_full_page
 };
diff -u --recursive --new-file v2.3.42/linux/fs/umsdos/Makefile linux/fs/umsdos/Makefile
--- v2.3.42/linux/fs/umsdos/Makefile	Mon Aug  9 11:43:49 1999
+++ linux/fs/umsdos/Makefile	Thu Feb 10 12:17:00 2000
@@ -8,8 +8,7 @@
 # Note 2:  the CFLAGS definitions are now in the main makefile.
 O_TARGET := umsdos.o
 
-O_OBJS   := dir.o  inode.o ioctl.o mangle.o namei.o \
-		rdir.o symlink.o emd.o check.o
+O_OBJS   := dir.o  inode.o ioctl.o mangle.o namei.o rdir.o emd.o check.o
 
 M_OBJS   := $(O_TARGET)
 
diff -u --recursive --new-file v2.3.42/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v2.3.42/linux/fs/umsdos/dir.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/umsdos/dir.c	Thu Feb 10 12:17:00 2000
@@ -802,17 +802,9 @@
 
 static struct file_operations umsdos_dir_operations =
 {
-	NULL,			/* lseek - default */
-	dummy_dir_read,		/* read */
-	NULL,			/* write - bad */
-	UMSDOS_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	UMSDOS_ioctl_dir,	/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* fsync */
+	read:		dummy_dir_read,
+	readdir:	UMSDOS_readdir,
+	ioctl:		UMSDOS_ioctl_dir,
 };
 
 struct inode_operations umsdos_dir_inode_operations =
@@ -827,12 +819,4 @@
 	UMSDOS_rmdir,		/* rmdir */
 	UMSDOS_mknod,		/* mknod */
 	UMSDOS_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* followlink */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
diff -u --recursive --new-file v2.3.42/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.3.42/linux/fs/umsdos/inode.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/umsdos/inode.c	Thu Feb 10 12:17:00 2000
@@ -155,7 +155,8 @@
 	} else if (S_ISDIR (inode->i_mode)) {
 		umsdos_setup_dir(dentry);
 	} else if (S_ISLNK (inode->i_mode)) {
-		inode->i_op = &umsdos_symlink_inode_operations;
+		/* address_space operations already set */
+		inode->i_op = &page_symlink_inode_operations;
 	} else
 		init_special_inode(inode, inode->i_mode,
 					kdev_t_to_nr(inode->i_rdev));
diff -u --recursive --new-file v2.3.42/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v2.3.42/linux/fs/umsdos/rdir.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/umsdos/rdir.c	Thu Feb 10 12:17:00 2000
@@ -220,17 +220,9 @@
  */
 static struct file_operations umsdos_rdir_operations =
 {
-	NULL,			/* lseek - default */
-	dummy_dir_read,		/* read */
-	NULL,			/* write - bad */
-	UMSDOS_rreaddir,	/* readdir */
-	NULL,			/* poll - default */
-	UMSDOS_ioctl_dir,	/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* fsync */
+	read:		dummy_dir_read,
+	readdir:	UMSDOS_rreaddir,
+	ioctl:		UMSDOS_ioctl_dir,
 };
 
 struct inode_operations umsdos_rdir_inode_operations =
@@ -245,12 +237,4 @@
 	UMSDOS_rrmdir,		/* rmdir */
 	NULL,			/* mknod */
 	msdos_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* followlink */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* get_block */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
diff -u --recursive --new-file v2.3.42/linux/fs/umsdos/symlink.c linux/fs/umsdos/symlink.c
--- v2.3.42/linux/fs/umsdos/symlink.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/umsdos/symlink.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/*
- *  linux/fs/umsdos/file.c
- *
- *  Written 1992 by Jacques Gelinas
- *      inspired from linux/fs/msdos/file.c Werner Almesberger
- *
- *  Extended MS-DOS regular file handling primitives
- *
- *  Wow. It looks like we could support them on FAT with little (if any)
- *  problems. Oh, well...
- */
-
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-
-struct inode_operations umsdos_symlink_inode_operations =
-{
-	readlink:	page_readlink,
-	follow_link:	page_follow_link,
-	get_block:	fat_get_block,
-	readpage:	block_read_full_page
-};
diff -u --recursive --new-file v2.3.42/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.3.42/linux/fs/vfat/namei.c	Mon Dec 20 18:48:22 1999
+++ linux/fs/vfat/namei.c	Thu Feb 10 12:17:00 2000
@@ -1276,14 +1276,6 @@
 	vfat_rmdir,		/* rmdir */
 	NULL,			/* mknod */
 	vfat_rename,		/* rename */
-	NULL,			/* readlink */
-	NULL,			/* followlink */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
 
 struct super_block *vfat_read_super(struct super_block *sb,void *data,
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h
--- v2.3.42/linux/include/asm-alpha/bitops.h	Tue Jun 22 10:46:52 1999
+++ linux/include/asm-alpha/bitops.h	Wed Feb  9 19:47:20 2000
@@ -76,8 +76,8 @@
 	:"Ir" (1UL << (nr & 31)), "m" (*m));
 }
 
-extern __inline__ unsigned long test_and_set_bit(unsigned long nr,
-						 volatile void * addr)
+extern __inline__ int test_and_set_bit(unsigned long nr,
+				       volatile void * addr)
 {
 	unsigned long oldbit;
 	unsigned long temp;
@@ -101,8 +101,8 @@
 	return oldbit != 0;
 }
 
-extern __inline__ unsigned long test_and_clear_bit(unsigned long nr,
-						   volatile void * addr)
+extern __inline__ int test_and_clear_bit(unsigned long nr,
+					 volatile void * addr)
 {
 	unsigned long oldbit;
 	unsigned long temp;
@@ -126,8 +126,8 @@
 	return oldbit != 0;
 }
 
-extern __inline__ unsigned long test_and_change_bit(unsigned long nr,
-						    volatile void * addr)
+extern __inline__ int test_and_change_bit(unsigned long nr,
+					  volatile void * addr)
 {
 	unsigned long oldbit;
 	unsigned long temp;
@@ -149,9 +149,9 @@
 	return oldbit != 0;
 }
 
-extern __inline__ unsigned long test_bit(int nr, volatile void * addr)
+extern __inline__ int test_bit(int nr, volatile void * addr)
 {
-	return 1UL & (((const int *) addr)[nr >> 5] >> (nr & 31));
+	return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
 }
 
 /*
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_apecs.h linux/include/asm-alpha/core_apecs.h
--- v2.3.42/linux/include/asm-alpha/core_apecs.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-alpha/core_apecs.h	Tue Feb  8 12:01:59 2000
@@ -1,7 +1,6 @@
 #ifndef __ALPHA_APECS__H__
 #define __ALPHA_APECS__H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/compiler.h>
 
@@ -66,19 +65,10 @@
    for most other things they are identical. It didn't seem reasonable to
    make the AVANTI support pay for the limitations of the XL. It is true,
    however, that an XL kernel will run on an AVANTI without problems.
-*/
-#define APECS_XL_DMA_WIN1_BASE		(64UL*1024*1024)
-#define APECS_XL_DMA_WIN1_SIZE		(64UL*1024*1024)
-#define APECS_XL_DMA_WIN1_SIZE_PARANOID	(48UL*1024*1024)
-#define APECS_XL_DMA_WIN2_BASE		(1UL*1024*1024*1024)
-#define APECS_XL_DMA_WIN2_SIZE		(1UL*1024*1024*1024)
-
-
-/* These are for normal APECS family machines, AVANTI/MUSTANG/EB64/PC64.  */
-
-#define APECS_DMA_WIN_BASE		(1UL*1024*1024*1024)
-#define APECS_DMA_WIN_SIZE		(1UL*1024*1024*1024)
 
+   %%% All of this should be obviated by the ability to route
+   everything through the iommu.
+*/
 
 /*
  * 21071-DA Control and Status registers.
@@ -370,64 +360,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-
-/*
- * NOTE: we fudge the window 1 maximum as 48Mb instead of 64Mb, to prevent 
- * virt_to_bus() from returning an address in the first window, for a
- * data area that goes beyond the 64Mb first DMA window. Sigh...
- * This MUST match with <asm/dma.h> MAX_DMA_ADDRESS for consistency, but
- * we can't just use that here, because of header file looping... :-(
- */
-
-__EXTERN_INLINE unsigned long apecs_virt_to_bus(void * address)
-{
-	unsigned long paddr = virt_to_phys(address);
-	return paddr + APECS_DMA_WIN_BASE;
-}
-
-static inline unsigned long apecs_xl_virt_to_bus(void * address)
-{
-	unsigned long paddr = virt_to_phys(address);
-	if (paddr < APECS_XL_DMA_WIN1_SIZE_PARANOID)
-		return paddr + APECS_XL_DMA_WIN1_BASE;
-	else
-		return paddr + APECS_XL_DMA_WIN2_BASE;
-}
-
-__EXTERN_INLINE void * apecs_bus_to_virt(unsigned long address)
-{
-	/*
-	 * This check is a sanity check but also ensures that bus
-	 * address 0 maps to virtual address 0 which is useful to
-	 * detect null "pointers" (the NCR driver is much simpler if
-	 * NULL pointers are preserved).
-	 */
-	if (address < APECS_DMA_WIN_BASE)
-		return 0;
-	return phys_to_virt(address - APECS_DMA_WIN_BASE);
-}
-
-static inline void * apecs_xl_bus_to_virt(unsigned long address)
-{
-	/*
-	 * This check is a sanity check but also ensures that bus
-	 * address 0 maps to virtual address 0 which is useful to
-	 * detect null "pointers" (the NCR driver is much simpler if
-	 * NULL pointers are preserved).
-	 */
-	if (address < APECS_XL_DMA_WIN1_BASE)
-		return 0;
-	else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE))
-		address -= APECS_XL_DMA_WIN1_BASE;
-	else /* should be more checking here, maybe? */
-		address -= APECS_XL_DMA_WIN2_BASE;
-	return phys_to_virt(address);
-}
-
-/*
  * I/O functions:
  *
  * Unlike Jensen, the APECS machines have no concept of local
@@ -578,14 +510,6 @@
 #undef vulp
 
 #ifdef __WANT_IO_DEF
-
-#ifdef CONFIG_ALPHA_XL
-#define virt_to_bus	apecs_xl_virt_to_bus
-#define bus_to_virt	apecs_xl_bus_to_virt
-#else
-#define virt_to_bus	apecs_virt_to_bus
-#define bus_to_virt	apecs_bus_to_virt
-#endif
 
 #define __inb		apecs_inb
 #define __inw		apecs_inw
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h
--- v2.3.42/linux/include/asm-alpha/core_cia.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-alpha/core_cia.h	Mon Feb  7 20:09:05 2000
@@ -77,20 +77,6 @@
 #define CIA_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define CIA_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define CIA_DMA_WIN_BASE		(1UL*1024*1024*1024)
-#define CIA_DMA_WIN_SIZE		(2UL*1024*1024*1024)
-
-/* Window 0 at 1GB size 1GB mapping to 0.  */
-#define CIA_DMA_WIN0_BASE_DEFAULT      (1UL*1024*1024*1024)
-#define CIA_DMA_WIN0_SIZE_DEFAULT      (1UL*1024*1024*1024)
-#define CIA_DMA_WIN0_TRAN_DEFAULT      (0UL)
-
-/* Window 1 at 2GB size 1GB mapping to 1GB.  */
-#define CIA_DMA_WIN1_BASE_DEFAULT      (2UL*1024*1024*1024)
-#define CIA_DMA_WIN1_SIZE_DEFAULT      (1UL*1024*1024*1024)
-#define CIA_DMA_WIN1_TRAN_DEFAULT      (1UL*1024*1024*1024)
-
-
 /*
  * 21171-CA Control and Status Registers (p4-1)
  */
@@ -289,21 +275,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-
-__EXTERN_INLINE unsigned long cia_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + CIA_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * cia_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address - CIA_DMA_WIN_BASE);
-}
-
-/*
  * I/O functions:
  *
  * CIA (the 2117x PCI/memory support chipset for the EV5 (21164)
@@ -491,8 +462,6 @@
 
 #ifdef __WANT_IO_DEF
 
-#define virt_to_bus	cia_virt_to_bus
-#define bus_to_virt	cia_bus_to_virt
 #define __inb		cia_inb
 #define __inw		cia_inw
 #define __inl		cia_inl
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_irongate.h linux/include/asm-alpha/core_irongate.h
--- v2.3.42/linux/include/asm-alpha/core_irongate.h	Wed Dec 15 10:43:17 1999
+++ linux/include/asm-alpha/core_irongate.h	Mon Feb  7 20:09:05 2000
@@ -22,13 +22,8 @@
  * and I/O address space. Memory address space resides in the lower
  * half of the physical address space (PA[43]=0) and I/O address space
  * resides in the upper half of the physical address space (PA[43]=1).
- *
  */
 
-#define IRONGATE_DMA_WIN_BASE		 (0UL)
-#define IRONGATE_DMA_WIN_SIZE		 (0UL)
-
-
 /*
  * Irongate CSR map.  Some of the CSRs are 8 or 16 bits, but all access
  * through the routines given is 32-bit.
@@ -393,21 +388,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-
-__EXTERN_INLINE unsigned long irongate_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + IRONGATE_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * irongate_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address - IRONGATE_DMA_WIN_BASE);
-}
-
-/*
  * I/O functions:
  *
  * IRONGATE (AMD-751) PCI/memory support chip for the EV6 (21264) and
@@ -512,9 +492,6 @@
 #undef vulp
 
 #ifdef __WANT_IO_DEF
-
-#define virt_to_bus	irongate_virt_to_bus
-#define bus_to_virt	irongate_bus_to_virt
 
 #define __inb		irongate_inb
 #define __inw		irongate_inw
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_lca.h linux/include/asm-alpha/core_lca.h
--- v2.3.42/linux/include/asm-alpha/core_lca.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-alpha/core_lca.h	Mon Feb  7 20:09:05 2000
@@ -55,10 +55,6 @@
  * ugh).
  */
 
-#define LCA_DMA_WIN_BASE	(1UL*1024*1024*1024)
-#define LCA_DMA_WIN_SIZE	(1UL*1024*1024*1024)
-
-
 /*
  * Memory Controller registers:
  */
@@ -209,29 +205,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-
-__EXTERN_INLINE unsigned long lca_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + LCA_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * lca_bus_to_virt(unsigned long address)
-{
-	/*
-	 * This check is a sanity check but also ensures that bus
-	 * address 0 maps to virtual address 0 which is useful to
-	 * detect null "pointers" (the NCR driver is much simpler if
-	 * NULL pointers are preserved).
-	 */
-	if (address < LCA_DMA_WIN_BASE)
-		return 0;
-	return phys_to_virt(address - LCA_DMA_WIN_BASE);
-}
-
-/*
  * I/O functions:
  *
  * Unlike Jensen, the Noname machines have no concept of local
@@ -387,8 +360,6 @@
 
 #ifdef __WANT_IO_DEF
 
-#define virt_to_bus	lca_virt_to_bus
-#define bus_to_virt	lca_bus_to_virt
 #define __inb		lca_inb
 #define __inw		lca_inw
 #define __inl		lca_inl
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_mcpcia.h linux/include/asm-alpha/core_mcpcia.h
--- v2.3.42/linux/include/asm-alpha/core_mcpcia.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-alpha/core_mcpcia.h	Mon Feb  7 20:09:05 2000
@@ -72,13 +72,10 @@
  *
  */
 
-#define MCPCIA_MEM_MASK 0x07ffffff /* SPARSE Mem region mask is 27 bits */
-
-#define MCPCIA_DMA_WIN_BASE		(2UL*1024*1024*1024)
-#define MCPCIA_DMA_WIN_SIZE		(2UL*1024*1024*1024)
-
 #define MCPCIA_MID(m)		((unsigned long)(m) << 33)
 
+#define MCPCIA_MEM_MASK 0x07ffffff /* SPARSE Mem region mask is 27 bits */
+
 /*
  * Memory spaces:
  */
@@ -198,21 +195,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-
-__EXTERN_INLINE unsigned long mcpcia_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + MCPCIA_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * mcpcia_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address - MCPCIA_DMA_WIN_BASE);
-}
-
-/*
  * I/O functions:
  *
  * MCPCIA, the RAWHIDE family PCI/memory support chipset for the EV5 (21164)
@@ -451,9 +433,6 @@
 #undef vulp
 
 #ifdef __WANT_IO_DEF
-
-#define virt_to_bus	mcpcia_virt_to_bus
-#define bus_to_virt	mcpcia_bus_to_virt
 
 #define __inb		mcpcia_inb
 #define __inw		mcpcia_inw
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_polaris.h linux/include/asm-alpha/core_polaris.h
--- v2.3.42/linux/include/asm-alpha/core_polaris.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-alpha/core_polaris.h	Mon Feb  7 20:09:05 2000
@@ -36,14 +36,6 @@
 #define POLARIS_W_CMD		(POLARIS_DENSE_CONFIG_BASE+4)
 #define POLARIS_W_STATUS	(POLARIS_DENSE_CONFIG_BASE+6)
 
-/* No HAE address.  Polaris has no concept of an HAE, since it
- * supports transfers of all sizes in dense space.
- */
-
-#define POLARIS_DMA_WIN_BASE	0x80000000UL	/* fixed, 2G @ 2G */
-#define POLARIS_DMA_WIN_SIZE	0x80000000UL	/* fixed, 2G @ 2G */
-
-
 /*
  * Data structure for handling POLARIS machine checks:
  */
@@ -61,16 +53,6 @@
 #define __IO_EXTERN_INLINE
 #endif
 
-__EXTERN_INLINE unsigned long polaris_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + POLARIS_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * polaris_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address - POLARIS_DMA_WIN_BASE);
-}
-
 /*
  * I/O functions:
  *
@@ -187,9 +169,6 @@
 #undef vulp
 
 #ifdef __WANT_IO_DEF
-
-#define virt_to_bus     polaris_virt_to_bus
-#define bus_to_virt     polaris_bus_to_virt
 
 #define __inb           polaris_inb
 #define __inw           polaris_inw
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_pyxis.h linux/include/asm-alpha/core_pyxis.h
--- v2.3.42/linux/include/asm-alpha/core_pyxis.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-alpha/core_pyxis.h	Mon Feb  7 20:09:05 2000
@@ -71,20 +71,6 @@
 #define PYXIS_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define PYXIS_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define PYXIS_DMA_WIN_BASE		(1UL*1024*1024*1024)
-#define PYXIS_DMA_WIN_SIZE		(2UL*1024*1024*1024)
-
-/* Window 0 at 1GB size 1GB mapping 0 */
-#define PYXIS_DMA_WIN0_BASE_DEFAULT	(1UL*1024*1024*1024)
-#define PYXIS_DMA_WIN0_SIZE_DEFAULT	(1UL*1024*1024*1024)
-#define PYXIS_DMA_WIN0_TRAN_DEFAULT	(0UL)
-
-/* Window 0 at 2GB size 1GB mapping 1GB */
-#define PYXIS_DMA_WIN1_BASE_DEFAULT	(2UL*1024*1024*1024)
-#define PYXIS_DMA_WIN1_SIZE_DEFAULT	(1UL*1024*1024*1024)
-#define PYXIS_DMA_WIN1_TRAN_DEFAULT	(1UL*1024*1024*1024)
-
-
 /*
  *  General Registers
  */
@@ -272,22 +258,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-
-__EXTERN_INLINE unsigned long pyxis_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + PYXIS_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * pyxis_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address - PYXIS_DMA_WIN_BASE);
-}
-
-
-/*
  * I/O functions:
  *
  * PYXIS, the 21174 PCI/memory support chipset for the EV56 (21164A)
@@ -429,9 +399,6 @@
 #undef vulp
 
 #ifdef __WANT_IO_DEF
-
-#define virt_to_bus	pyxis_virt_to_bus
-#define bus_to_virt	pyxis_bus_to_virt
 
 #define __inb		pyxis_inb
 #define __inw		pyxis_inw
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_t2.h linux/include/asm-alpha/core_t2.h
--- v2.3.42/linux/include/asm-alpha/core_t2.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-alpha/core_t2.h	Mon Feb  7 20:09:05 2000
@@ -21,9 +21,6 @@
 
 #define T2_MEM_R1_MASK 0x03ffffff  /* Mem sparse region 1 mask is 26 bits */
 
-#define T2_DMA_WIN_BASE		(1UL*1024*1024*1024)
-#define T2_DMA_WIN_SIZE		(1UL*1024*1024*1024)
-
 /* GAMMA-SABLE is a SABLE with EV5-based CPUs */
 #define _GAMMA_BIAS		0x8000000000UL
 
@@ -322,21 +319,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-
-__EXTERN_INLINE unsigned long t2_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + T2_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * t2_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address - T2_DMA_WIN_BASE);
-}
-
-/*
  * I/O functions:
  *
  * T2 (the core logic PCI/memory support chipset for the SABLE
@@ -534,8 +516,6 @@
 
 #ifdef __WANT_IO_DEF
 
-#define virt_to_bus	t2_virt_to_bus
-#define bus_to_virt	t2_bus_to_virt
 #define __inb		t2_inb
 #define __inw		t2_inw
 #define __inl		t2_inl
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h
--- v2.3.42/linux/include/asm-alpha/core_tsunami.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-alpha/core_tsunami.h	Mon Feb  7 20:09:05 2000
@@ -15,26 +15,6 @@
  *
  */
 
-/*
- * We must actually use 2 windows to direct-map the 2GB space, because
- * of an "idiot-syncracy" of the CYPRESS chip used on DS20 and others.
- * It may respond to a PCI bus address in the last 1MB of the 4GB
- * address range, and that is where real memory may appear.
- *
- * Sigh...
- */
-#define TSUNAMI_DMA_WIN_BASE		(1UL*1024*1024*1024)
-#define TSUNAMI_DMA_WIN_SIZE		(2UL*1024*1024*1024)
-
-#define TSUNAMI_DMA_WIN0_BASE_DEFAULT	(1UL*1024*1024*1024)
-#define TSUNAMI_DMA_WIN0_SIZE_DEFAULT	(1UL*1024*1024*1024)
-#define TSUNAMI_DMA_WIN0_TRAN_DEFAULT	(0UL)
-
-#define TSUNAMI_DMA_WIN1_BASE_DEFAULT	(2UL*1024*1024*1024)
-#define TSUNAMI_DMA_WIN1_SIZE_DEFAULT	(1UL*1024*1024*1024)
-#define TSUNAMI_DMA_WIN1_TRAN_DEFAULT	(1UL*1024*1024*1024)
-
-
 /* XXX: Do we need to conditionalize on this?  */
 #ifdef USE_48_BIT_KSEG
 #define TS_BIAS 0x80000000000UL
@@ -309,20 +289,6 @@
 #endif
 
 /*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-__EXTERN_INLINE unsigned long tsunami_virt_to_bus(void * address)
-{
-	return virt_to_phys(address) + TSUNAMI_DMA_WIN_BASE;
-}
-
-__EXTERN_INLINE void * tsunami_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address - TSUNAMI_DMA_WIN_BASE);
-}
-
-/*
  * I/O functions:
  *
  * TSUNAMI, the 21??? PCI/memory support chipset for the EV6 (21264)
@@ -438,9 +404,6 @@
 #undef vulp
 
 #ifdef __WANT_IO_DEF
-
-#define virt_to_bus	tsunami_virt_to_bus
-#define bus_to_virt	tsunami_bus_to_virt
 
 #define __inb		tsunami_inb
 #define __inw		tsunami_inw
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/hardirq.h linux/include/asm-alpha/hardirq.h
--- v2.3.42/linux/include/asm-alpha/hardirq.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-alpha/hardirq.h	Wed Feb  9 20:08:09 2000
@@ -23,6 +23,8 @@
 	(local_irq_count(__cpu) + local_bh_count(__cpu)) != 0;	\
 })
 
+#define in_irq() (local_irq_count(smp_processor_id()) != 0)
+
 #ifndef __SMP__
 
 #define hardirq_trylock(cpu)	(local_irq_count(cpu) == 0)
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.3.42/linux/include/asm-alpha/io.h	Wed Dec 15 10:43:17 1999
+++ linux/include/asm-alpha/io.h	Mon Feb  7 20:09:05 2000
@@ -51,7 +51,7 @@
 /*
  * Change virtual addresses to physical addresses and vv.
  */
-static inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(void *address)
 {
 	return (unsigned long)address - IDENT_ADDR;
 }
@@ -61,6 +61,36 @@
 	return (void *) (address + IDENT_ADDR);
 }
 
+/*
+ * Change addresses as seen by the kernel (virtual) to addresses as
+ * seen by a device (bus), and vice versa.
+ *
+ * Note that this only works for a limited range of kernel addresses,
+ * and very well may not span all memory.  Consider this interface 
+ * deprecated in favour of the mapping functions in <asm/pci.h>.
+ */
+extern unsigned long __direct_map_base;
+extern unsigned long __direct_map_size;
+
+static inline unsigned long virt_to_bus(void *address)
+{
+	unsigned long phys = virt_to_phys(address);
+	unsigned long bus = phys + __direct_map_base;
+	return phys <= __direct_map_size ? bus : 0;
+}
+
+static inline void *bus_to_virt(unsigned long address)
+{
+	void *virt;
+
+	/* This check is a sanity check but also ensures that bus address 0
+	   maps to virtual address 0 which is useful to detect null pointers
+	   (the NCR driver is much simpler if NULL pointers are preserved).  */
+	address -= __direct_map_base;
+	virt = phys_to_virt(address);
+	return (long)address <= 0 ? NULL : virt;
+}
+
 #else /* !__KERNEL__ */
 
 /*
@@ -81,9 +111,6 @@
 #ifdef CONFIG_ALPHA_GENERIC
 
 /* In a generic kernel, we always go through the machine vector.  */
-
-# define virt_to_bus(a)	alpha_mv.mv_virt_to_bus(a)
-# define bus_to_virt(a)	alpha_mv.mv_bus_to_virt(a)
 
 # define __inb		alpha_mv.mv_inb
 # define __inw		alpha_mv.mv_inw
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/jensen.h linux/include/asm-alpha/jensen.h
--- v2.3.42/linux/include/asm-alpha/jensen.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/jensen.h	Mon Feb  7 20:09:05 2000
@@ -80,24 +80,6 @@
 #endif
 
 /*
- * Change virtual addresses to bus addresses and vv.
- *
- * NOTE! On the Jensen, the physical address is the same
- * as the bus address, but this is not necessarily true on
- * other alpha hardware.
- */
-__EXTERN_INLINE unsigned long jensen_virt_to_bus(void * address)
-{
-	return virt_to_phys(address);
-}
-
-__EXTERN_INLINE void * jensen_bus_to_virt(unsigned long address)
-{
-	return phys_to_virt(address);
-}
-
-
-/*
  * Handle the "host address register". This needs to be set
  * to the high 7 bits of the EISA address.  This is also needed
  * for EISA IO addresses, which are only 16 bits wide (the
@@ -306,8 +288,6 @@
 
 #ifdef __WANT_IO_DEF
 
-#define virt_to_bus	jensen_virt_to_bus
-#define bus_to_virt	jensen_bus_to_virt
 #define __inb		jensen_inb
 #define __inw		jensen_inw
 #define __inl		jensen_inl
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/machvec.h linux/include/asm-alpha/machvec.h
--- v2.3.42/linux/include/asm-alpha/machvec.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-alpha/machvec.h	Mon Feb  7 20:09:05 2000
@@ -21,6 +21,7 @@
 struct linux_hose_info;
 struct pci_dev;
 struct pci_ops;
+struct pci_controler;
 
 struct alpha_machine_vector
 {
@@ -39,8 +40,8 @@
 	unsigned long min_io_address;
 	unsigned long min_mem_address;
 
-	unsigned long (*mv_virt_to_bus)(void *);
-	void * (*mv_bus_to_virt)(unsigned long);
+	void (*mv_pci_tbi)(struct pci_controler *hose,
+			   dma_addr_t start, dma_addr_t end);
 
 	unsigned int (*mv_inb)(unsigned long);
 	unsigned int (*mv_inw)(unsigned long);
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/mmu_context.h linux/include/asm-alpha/mmu_context.h
--- v2.3.42/linux/include/asm-alpha/mmu_context.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-alpha/mmu_context.h	Mon Feb  7 20:01:14 2000
@@ -22,6 +22,10 @@
 #include <asm/io.h>
 #endif
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
+
 extern inline unsigned long
 __reload_thread(struct thread_struct *pcb)
 {
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h
--- v2.3.42/linux/include/asm-alpha/pci.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-alpha/pci.h	Mon Feb  7 20:09:05 2000
@@ -1,27 +1,49 @@
 #ifndef __ALPHA_PCI_H
 #define __ALPHA_PCI_H
 
+#include <linux/spinlock.h>
+#include <asm/scatterlist.h>
 #include <asm/machvec.h>
 
 /*
  * The following structure is used to manage multiple PCI busses.
  */
 
+struct pci_dev;
 struct pci_bus;
 struct resource;
 
+/* A PCI IOMMU allocation arena.  There are typically two of these
+   regions per bus.  */
+/* ??? The 8400 has a 32-byte pte entry, and the entire table apparently
+   lives directly on the host bridge (no tlb?).  We don't support this
+   machine, but if we ever did, we'd need to parameterize all this quite
+   a bit further.  Probably with per-bus operation tables.  */
+
+struct pci_iommu_arena
+{
+	spinlock_t lock;
+	unsigned long *ptes;
+	dma_addr_t dma_base;
+	unsigned int size;
+	unsigned int alloc_hint;
+};
+
+/* A controler.  Used to manage multiple PCI busses.  */
+
 struct pci_controler {
-	/* Mandated.  */
 	struct pci_controler *next;
         struct pci_bus *bus;
 	struct resource *io_space;
 	struct resource *mem_space;
 
-	/* Alpha specific.  */
 	unsigned long config_space;
 	unsigned int index;
 	unsigned int first_busno;
 	unsigned int last_busno;
+
+	struct pci_iommu_arena *sg_pci;
+	struct pci_iommu_arena *sg_isa;
 };
 
 /* Override the logic in pci_scan_bus for skipping already-configured
@@ -32,5 +54,83 @@
 #define PCIBIOS_MIN_IO		alpha_mv.min_io_address
 #define PCIBIOS_MIN_MEM		alpha_mv.min_mem_address
 
-#endif /* __ALPHA_PCI_H */
+/* IOMMU controls.  */
+
+/* Allocate and map kernel buffer using consistant mode DMA for PCI
+   device.  Returns non-NULL cpu-view pointer to the buffer if
+   successful and sets *DMA_ADDRP to the pci side dma address as well,
+   else DMA_ADDRP is undefined.  */
+
+extern void *pci_alloc_consistent(struct pci_dev *, long, dma_addr_t *);
+
+/* Free and unmap a consistant DMA buffer.  CPU_ADDR and DMA_ADDR must
+   be values that were returned from pci_alloc_consistant.  SIZE must
+   be the same as what as passed into pci_alloc_consistant.
+   References to the memory and mappings assosciated with CPU_ADDR or
+   DMA_ADDR past this call are illegal.  */
+
+extern void pci_free_consistent(struct pci_dev *, long, void *, dma_addr_t);
+
+/* Map a single buffer of the indicate size for PCI DMA in streaming
+   mode.  The 32-bit PCI bus mastering address to use is returned.
+   Once the device is given the dma address, the device owns this memory
+   until either pci_unmap_single or pci_sync_single is performed.  */
+
+extern dma_addr_t pci_map_single(struct pci_dev *, void *, long);
+
+/* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
+   SIZE must match what was provided for in a previous pci_map_single
+   call.  All other usages are undefined.  After this call, reads by
+   the cpu to the buffer are guarenteed to see whatever the device
+   wrote there.  */
+
+extern void pci_unmap_single(struct pci_dev *, dma_addr_t, long);
+
+/* Map a set of buffers described by scatterlist in streaming mode for
+   PCI DMA.  This is the scather-gather version of the above
+   pci_map_single interface.  Here the scatter gather list elements
+   are each tagged with the appropriate PCI dma address and length.
+   They are obtained via sg_dma_{address,length}(SG).
+
+   NOTE: An implementation may be able to use a smaller number of DMA
+   address/length pairs than there are SG table elements.  (for
+   example via virtual mapping capabilities) The routine returns the
+   number of addr/length pairs actually used, at most nents.
+
+   Device ownership issues as mentioned above for pci_map_single are
+   the same here.  */
+
+extern int pci_map_sg(struct pci_dev *, struct scatterlist *, int);
+
+/* Unmap a set of streaming mode DMA translations.  Again, cpu read
+   rules concerning calls here are the same as for pci_unmap_single()
+   above.  */
+
+extern void pci_unmap_sg(struct pci_dev *, struct scatterlist *, int);
+
+/* Make physical memory consistant for a single streaming mode DMA
+   translation after a transfer.
+
+   If you perform a pci_map_single() but wish to interrogate the
+   buffer using the cpu, yet do not wish to teardown the PCI dma
+   mapping, you must call this function before doing so.  At the next
+   point you give the PCI dma address back to the card, the device
+   again owns the buffer.  */
+
+extern inline void
+pci_sync_single(struct pci_dev *dev, dma_addr_t dma_addr, long size)
+{
+	/* Nothing to do.  */
+}
+
+/* Make physical memory consistant for a set of streaming mode DMA
+   translations after a transfer.  The same as pci_dma_sync_single but
+   for a scatter-gather list, same rules and usage.  */
+
+extern inline void
+pci_sync_sg(struct pci_dev *dev, struct scatterlist *sg, int size)
+{
+	/* Nothing to do.  */
+}
 
+#endif /* __ALPHA_PCI_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/pgalloc.h linux/include/asm-alpha/pgalloc.h
--- v2.3.42/linux/include/asm-alpha/pgalloc.h	Tue Nov 23 22:42:21 1999
+++ linux/include/asm-alpha/pgalloc.h	Tue Feb  8 18:23:13 2000
@@ -145,6 +145,18 @@
 	flush_tlb_mm(mm);
 }
 
+/*
+ * Flush a specified range of user mapping page tables
+ * from TLB.
+ * Although Alpha uses VPTE caches, this can be a nop, as Alpha does
+ * not have finegrained tlb flushing, so it will flush VPTE stuff
+ * during next flush_tlb_range.
+ */
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+	unsigned long start, unsigned long end)
+{
+}
+
 #else /* __SMP__ */
 
 extern void flush_tlb_all(void);
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/scatterlist.h linux/include/asm-alpha/scatterlist.h
--- v2.3.42/linux/include/asm-alpha/scatterlist.h	Mon Dec 30 03:01:10 1996
+++ linux/include/asm-alpha/scatterlist.h	Mon Feb  7 20:09:05 2000
@@ -1,12 +1,19 @@
 #ifndef _ALPHA_SCATTERLIST_H
 #define _ALPHA_SCATTERLIST_H
 
+#include <linux/types.h>
+
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
-    char * alt_address; /* Location of actual if address is a 
-			 * dma indirect buffer.  NULL otherwise */
-    unsigned int length;
+	char *address;			/* Source/target vaddr.  */
+	char *alt_address;		/* Location of actual if address is a
+					   dma indirect buffer, else NULL.  */
+	dma_addr_t dma_address;
+	unsigned int length;
+	unsigned int dma_length;
 };
+
+#define sg_dma_address(sg) ((sg)->dma_address)
+#define sg_dma_len(sg)     ((sg)->dma_length)
 
 #define ISA_DMA_THRESHOLD (~0UL)
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.3.42/linux/include/asm-alpha/semaphore.h	Sat May 22 13:46:08 1999
+++ linux/include/asm-alpha/semaphore.h	Mon Feb  7 20:09:05 2000
@@ -5,7 +5,7 @@
  * SMP- and interrupt-safe semaphores..
  *
  * (C) Copyright 1996 Linus Torvalds
- * (C) Copyright 1996 Richard Henderson
+ * (C) Copyright 1996, 2000 Richard Henderson
  */
 
 #include <asm/current.h>
@@ -42,7 +42,7 @@
 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
 
-extern inline void sema_init (struct semaphore *sem, int val)
+extern inline void sema_init(struct semaphore *sem, int val)
 {
 	/*
 	 * Logically, 
@@ -110,8 +110,8 @@
 	__asm__ __volatile__ (
 		"/* semaphore down operation */\n"
 		"1:	ldl_l	$24,%1\n"
+		"	subl	$24,1,$28\n"
 		"	subl	$24,1,$24\n"
-		"	mov	$24,$28\n"
 		"	stl_c	$28,%1\n"
 		"	beq	$28,2f\n"
 		"	blt	$24,3f\n"
@@ -146,8 +146,8 @@
 	__asm__ __volatile__ (
 		"/* semaphore down interruptible operation */\n"
 		"1:	ldl_l	$24,%2\n"
+		"	subl	$24,1,$28\n"
 		"	subl	$24,1,$24\n"
-		"	mov	$24,$28\n"
 		"	stl_c	$28,%2\n"
 		"	beq	$28,2f\n"
 		"	blt	$24,3f\n"
@@ -247,11 +247,10 @@
 		"/* semaphore up operation */\n"
 		"	mb\n"
 		"1:	ldl_l	$24,%1\n"
+		"	addl	$24,1,$28\n"
 		"	addl	$24,1,$24\n"
-		"	mov	$24,$28\n"
 		"	stl_c	$28,%1\n"
 		"	beq	$28,2f\n"
-		"	mb\n"
 		"	ble	$24,3f\n"
 		"4:\n"
 		".section .text2,\"ax\"\n"
@@ -264,6 +263,294 @@
 		: "=r"(pv)
 		: "m"(sem->count), "r"(pv)
 		: "$24", "$28", "memory");
+}
+
+
+/* rw mutexes (should that be mutices? =) -- throw rw
+ * spinlocks and semaphores together, and this is what we
+ * end up with...
+ *
+ * The lock is initialized to BIAS.  This way, a writer
+ * subtracts BIAS ands gets 0 for the case of an uncontended
+ * lock.  Readers decrement by 1 and see a positive value
+ * when uncontended, negative if there are writers waiting
+ * (in which case it goes to sleep).
+ *
+ * The value 0x01000000 supports up to 128 processors and
+ * lots of processes.  BIAS must be chosen such that subtracting
+ * BIAS once per CPU will result in the int remaining
+ * negative.
+ * In terms of fairness, this should result in the lock
+ * flopping back and forth between readers and writers
+ * under heavy use.
+ *
+ *	      -ben
+ *
+ * Once we start supporting machines with more than 128 CPUs,
+ * we should go for using a 64bit atomic type instead of 32bit
+ * as counter. We shall probably go for bias 0x80000000 then,
+ * so that single sethi can set it.
+ *
+ *	      -jj
+ */
+
+#define RW_LOCK_BIAS		0x01000000
+
+struct rw_semaphore {
+	int			count;
+	/* bit 0 means read bias granted;
+	   bit 1 means write bias granted.  */
+	unsigned		granted;
+	wait_queue_head_t	wait;
+	wait_queue_head_t	write_bias_wait;
+#if WAITQUEUE_DEBUG
+	long			__magic;
+	atomic_t		readers;
+	atomic_t		writers;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
+#else
+#define __RWSEM_DEBUG_INIT	/* */
+#endif
+
+#define __RWSEM_INITIALIZER(name,count)					\
+	{ (count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+	  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)		\
+	  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
+
+#define __DECLARE_RWSEM_GENERIC(name,count) \
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
+
+#define DECLARE_RWSEM(name) \
+	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
+#define DECLARE_RWSEM_READ_LOCKED(name) \
+	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
+#define DECLARE_RWSEM_WRITE_LOCKED(name) \
+	__DECLARE_RWSEM_GENERIC(name, 0)
+
+extern inline void init_rwsem(struct rw_semaphore *sem)
+{
+	sem->count = RW_LOCK_BIAS;
+	sem->granted = 0;
+	init_waitqueue_head(&sem->wait);
+	init_waitqueue_head(&sem->write_bias_wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+	atomic_set(&sem->readers, 0);
+	atomic_set(&sem->writers, 0);
+#endif
+}
+
+/* All have custom assembly linkages.  */
+extern void __down_read_failed(struct rw_semaphore *sem);
+extern void __down_write_failed(struct rw_semaphore *sem);
+extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
+
+extern inline void down_read(struct rw_semaphore *sem)
+{
+	/* Given that we have to use particular hard registers to 
+	   communicate with __down_read_failed anyway, reuse them in 
+	   the atomic operation as well. 
+
+	   __down_read_failed takes the semaphore address in $24, the count
+	   we read in $25, and it's return address in $28. The pv is loaded
+	   as usual. The gp is clobbered (in the module case) as usual.  */
+
+	/* This little bit of silliness is to get the GP loaded for
+	   a function that ordinarily wouldn't.  Otherwise we could
+	   have it done by the macro directly, which can be optimized
+	   the linker.  */
+	register void *pv __asm__("$27");
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	pv = __down_read_failed;
+	__asm__ __volatile__(
+		"/* semaphore down_read operation */\n"
+		"1:	ldl_l	$24,%1\n"
+		"	subl	$24,1,$28\n"
+		"	subl	$24,1,$25\n"
+		"	stl_c	$28,%1\n"
+		"	beq	$28,2f\n"
+		"	blt	$25,3f\n"
+		"4:	mb\n"
+		".section .text2,\"ax\"\n"
+		"2:	br	1b\n"
+		"3:	lda	$24,%1\n"
+		"	jsr	$28,($27),__down_read_failed\n"
+		"	ldgp	$29,0($28)\n"
+		"	br	4b\n"
+		".previous"
+		: "=r"(pv)
+		: "m"(sem->count), "r"(pv)
+		: "$24", "$25", "$28", "memory");
+
+#if WAITQUEUE_DEBUG
+	if (sem->granted & 2)
+		BUG();
+	if (atomic_read(&sem->writers))
+		BUG();
+	atomic_inc(&sem->readers);
+#endif
+}
+
+extern inline void down_write(struct rw_semaphore *sem)
+{
+	/* Given that we have to use particular hard registers to 
+	   communicate with __down_write_failed anyway, reuse them in 
+	   the atomic operation as well. 
+
+	   __down_write_failed takes the semaphore address in $24, the count
+	   we read in $25, and it's return address in $28. The pv is loaded
+	   as usual. The gp is clobbered (in the module case) as usual.  */
+
+	/* This little bit of silliness is to get the GP loaded for
+	   a function that ordinarily wouldn't.  Otherwise we could
+	   have it done by the macro directly, which can be optimized
+	   the linker.  */
+	register void *pv __asm__("$27");
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	pv = __down_write_failed;
+	__asm__ __volatile__(
+		"/* semaphore down_write operation */\n"
+		"1:	ldl_l	$24,%1\n"
+		"	ldah	$28,%3($24)\n"
+		"	ldah	$25,%3($24)\n"
+		"	stl_c	$28,%1\n"
+		"	beq	$28,2f\n"
+		"	bne	$25,3f\n"
+		"4:	mb\n"
+		".section .text2,\"ax\"\n"
+		"2:	br	1b\n"
+		"3:	lda	$24,%1\n"
+		"	jsr	$28,($27),__down_write_failed\n"
+		"	ldgp	$29,0($28)\n"
+		"	br	4b\n"
+		".previous"
+		: "=r"(pv)
+		: "m"(sem->count), "r"(pv), "i"(-(RW_LOCK_BIAS >> 16))
+		: "$24", "$25", "$28", "memory");
+
+#if WAITQUEUE_DEBUG
+	if (atomic_read(&sem->writers))
+		BUG();
+	if (atomic_read(&sem->readers))
+		BUG();
+	if (sem->granted & 3)
+		BUG();
+	atomic_inc(&sem->writers);
+#endif
+}
+
+/* When a reader does a release, the only significant case is when
+  there was a writer waiting, and we've * bumped the count to 0: we must
+wake the writer up.  */
+
+extern inline void up_read(struct rw_semaphore *sem)
+{
+	/* Given that we have to use particular hard registers to 
+	   communicate with __rwsem_wake anyway, reuse them in 
+	   the atomic operation as well. 
+
+	   __rwsem_wake takes the semaphore address in $24, the
+	   number of waiting readers in $25, and it's return address
+	   in $28.  The pv is loaded as usual. The gp is clobbered
+	   (in the module case) as usual.  */
+
+	register void *pv __asm__("$27");
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+	if (sem->granted & 2)
+		BUG();
+	if (atomic_read(&sem->writers))
+		BUG();
+	atomic_dec(&sem->readers);
+#endif
+
+	pv = __rwsem_wake;
+	__asm__ __volatile__(
+		"/* semaphore up_read operation */\n"
+		"	mb\n"
+		"1:	ldl_l	$24,%1\n"
+		"	addl	$24,1,$28\n"
+		"	addl	$24,1,$24\n"
+		"	stl_c	$28,%1\n"
+		"	beq	$28,2f\n"
+		"	beq	$24,3f\n"
+		"4:\n"
+		".section .text2,\"ax\"\n"
+		"2:	br	1b\n"
+		"3:	lda	$24,%1\n"
+		"	mov	0,$25\n"
+		"	jsr	$28,($27),__rwsem_wake\n"
+		"	ldgp	$29,0($28)\n"
+		"	br	4b\n"
+		".previous"
+		: "=r"(pv)
+		: "m"(sem->count), "r"(pv)
+		: "$24", "$25", "$28", "memory");
+}
+
+/* releasing the writer is easy -- just release it and
+ * wake up any sleepers.
+ */
+extern inline void up_write(struct rw_semaphore *sem)
+{
+	/* Given that we have to use particular hard registers to 
+	   communicate with __rwsem_wake anyway, reuse them in 
+	   the atomic operation as well. 
+
+	   __rwsem_wake takes the semaphore address in $24, the
+	   number of waiting readers in $25, and it's return address
+	   in $28.  The pv is loaded as usual. The gp is clobbered
+	   (in the module case) as usual.  */
+
+	register void *pv __asm__("$27");
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+	if (sem->granted & 3)
+		BUG();
+	if (atomic_read(&sem->readers))
+		BUG();
+	if (atomic_read(&sem->writers) != 1)
+		BUG();
+	atomic_dec(&sem->writers);
+#endif
+
+	pv = __rwsem_wake;
+	__asm__ __volatile__(
+		"/* semaphore up_write operation */\n"
+		"	mb\n"
+		"1:	ldl_l	$24,%1\n"
+		"	ldah	$28,%3($24)\n"
+		"	stl_c	$28,%1\n"
+		"	beq	$28,2f\n"
+		"	blt	$24,3f\n"
+		"4:\n"
+		".section .text2,\"ax\"\n"
+		"2:	br	1b\n"
+		"3:	ldah	$25,%3($24)\n"
+		/* Only do the wake if we're no longer negative.  */
+		"	blt	$25,4b\n"
+		"	lda	$24,%1\n"
+		"	jsr	$28,($27),__rwsem_wake\n"
+		"	ldgp	$29,0($28)\n"
+		"	br	4b\n"
+		".previous"
+		: "=r"(pv)
+		: "m"(sem->count), "r"(pv), "i"(RW_LOCK_BIAS >> 16)
+		: "$24", "$25", "$28", "memory");
 }
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h
--- v2.3.42/linux/include/asm-alpha/smp.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-alpha/smp.h	Mon Feb  7 20:09:05 2000
@@ -42,7 +42,8 @@
 
 /* Map from cpu id to sequential logical cpu number.  This will only
    not be idempotent when cpus failed to come on-line.  */
-extern int cpu_number_map[NR_CPUS];
+extern int __cpu_number_map[NR_CPUS];
+#define cpu_number_map(cpu)  __cpu_number_map[cpu]
 
 /* The reverse map from sequential logical cpu number to cpu id.  */
 extern int __cpu_logical_map[NR_CPUS];
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/softirq.h linux/include/asm-alpha/softirq.h
--- v2.3.42/linux/include/asm-alpha/softirq.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-alpha/softirq.h	Wed Feb  9 20:08:09 2000
@@ -24,132 +24,9 @@
 	local_bh_count(cpu)--;
 }
 
-extern inline int cpu_bh_trylock(int cpu)
-{
-	return local_bh_count(cpu) ? 0 : (local_bh_count(cpu) = 1);
-}
-
-extern inline void cpu_bh_endlock(int cpu)
-{
-	local_bh_count(cpu) = 0;
-}
-
 #define local_bh_enable()	cpu_bh_enable(smp_processor_id())
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 
-#define get_active_bhs()	(bh_mask & bh_active)
-
-static inline void clear_active_bhs(unsigned long x)
-{
-	unsigned long temp;
-	__asm__ __volatile__(
-	"1:	ldq_l %0,%1\n"
-	"	bic %0,%2,%0\n"
-	"	stq_c %0,%1\n"
-	"	beq %0,2f\n"
-	".section .text2,\"ax\"\n"
-	"2:	br 1b\n"
-	".previous"
-	:"=&r" (temp), "=m" (bh_active)
-	:"Ir" (x), "m" (bh_active));
-}
-
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-	bh_base[nr] = routine;
-	atomic_set(&bh_mask_count[nr], 0);
-	bh_mask |= 1 << nr;
-}
-
-extern inline void remove_bh(int nr)
-{
-	bh_mask &= ~(1 << nr);
-	wmb();
-	bh_base[nr] = NULL;
-}
-
-extern inline void mark_bh(int nr)
-{
-	set_bit(nr, &bh_active);
-}
-
-#ifdef __SMP__
-
-/*
- * The locking mechanism for base handlers, to prevent re-entrancy,
- * is entirely private to an implementation, it should not be
- * referenced at all outside of this file.
- */
-extern atomic_t global_bh_lock;
-extern atomic_t global_bh_count;
-
-extern void synchronize_bh(void);
-
-static inline void start_bh_atomic(void)
-{
-	atomic_inc(&global_bh_lock);
-	synchronize_bh();
-}
-
-static inline void end_bh_atomic(void)
-{
-	atomic_dec(&global_bh_lock);
-}
-
-/* These are for the irq's testing the lock */
-static inline int softirq_trylock(int cpu)
-{
-	if (cpu_bh_trylock(cpu)) {
-		if (!test_and_set_bit(0, &global_bh_count)) {
-			if (atomic_read(&global_bh_lock) == 0)
-				return 1;
-			clear_bit(0, &global_bh_count);
-		}
-		cpu_bh_endlock(cpu);
-	}
-	return 0;
-}
-
-static inline void softirq_endlock(int cpu)
-{
-	cpu_bh_enable(cpu);
-	clear_bit(0, &global_bh_count);
-}
-
-#else
-
-extern inline void start_bh_atomic(void)
-{
-	local_bh_disable();
-}
-
-extern inline void end_bh_atomic(void)
-{
-	local_bh_enable();
-}
-
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)	cpu_bh_trylock(cpu)
-#define softirq_endlock(cpu)	cpu_bh_endlock(cpu)
-#define synchronize_bh()	barrier()
-
-#endif	/* SMP */
-
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-	bh_mask &= ~(1 << nr);
-	atomic_inc(&bh_mask_count[nr]);
-	synchronize_bh();
-}
-
-extern inline void enable_bh(int nr)
-{
-	if (atomic_dec_and_test(&bh_mask_count[nr]))
-		bh_mask |= 1 << nr;
-}
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
 
 #endif /* _ALPHA_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-alpha/types.h linux/include/asm-alpha/types.h
--- v2.3.42/linux/include/asm-alpha/types.h	Mon Jan 26 11:43:18 1998
+++ linux/include/asm-alpha/types.h	Mon Feb  7 20:09:05 2000
@@ -25,23 +25,9 @@
 typedef __signed__ int __s32;
 typedef unsigned int __u32;
 
-/*
- * There are 32-bit compilers for the alpha out there..
- */
-#if ((~0UL) == 0xffffffff)
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __signed__ long long __s64;
-typedef unsigned long long __u64;
-#endif
-
-#else
-
 typedef __signed__ long __s64;
 typedef unsigned long __u64;
 
-#endif
-
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
@@ -56,22 +42,15 @@
 typedef signed int s32;
 typedef unsigned int u32;
 
-/*
- * There are 32-bit compilers for the alpha out there..
- */
-#if ((~0UL) == 0xffffffff)
-
-typedef signed long long s64;
-typedef unsigned long long u64;
-#define BITS_PER_LONG 32
-
-#else
-
 typedef signed long s64;
 typedef unsigned long u64;
+
 #define BITS_PER_LONG 64
 
-#endif
+/* PCI dma addresses are 32-bits wide.  Ignore PCI64 for now, since
+   we'll typically be sending it all through iommu tables anyway.  */
+
+typedef u32 dma_addr_t;
 
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_TYPES_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/arch-arc/time.h linux/include/asm-arm/arch-arc/time.h
--- v2.3.42/linux/include/asm-arm/arch-arc/time.h	Mon Jul 19 09:52:57 1999
+++ linux/include/asm-arm/arch-arc/time.h	Sun Feb  6 17:45:25 2000
@@ -1,196 +1,30 @@
 /*
  * linux/include/asm-arm/arch-arc/time.h
  *
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-2000 Russell King.
  *
  * Changelog:
  *  24-Sep-1996	RMK	Created
  *  10-Oct-1996	RMK	Brought up to date with arch-sa110eval
  *  04-Dec-1997	RMK	Updated for new arch/arm/time.c
  */
-#include <asm/ioc.h>
-
-static long last_rtc_update = 0;	/* last time the cmos clock got updated */
-
-extern __inline__ unsigned long gettimeoffset (void)
-{
-	unsigned int count1, count2, status1, status2;
-	unsigned long offset = 0;
-
-	status1 = inb(IOC_IRQREQA);
-	barrier ();
-	outb (0, IOC_T0LATCH);
-	barrier ();
-	count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
-	barrier ();
-	status2 = inb(IOC_IRQREQA);
-	barrier ();
-	outb (0, IOC_T0LATCH);
-	barrier ();
-	count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
-
-	if (count2 < count1) {
-		/*
-		 * This means that we haven't just had an interrupt
-		 * while reading into status2.
-		 */
-		if (status2 & (1 << 5))
-			offset = tick;
-		count1 = count2;
-	} else if (count2 > count1) {
-		/*
-		 * We have just had another interrupt while reading
-		 * status2.
-		 */
-		offset += tick;
-		count1 = count2;
-	}
-
-	count1 = LATCH - count1;
-	/*
-	 * count1 = number of clock ticks since last interrupt
-	 */
-	offset += count1 * tick / LATCH;
-	return offset;
-}
-
-extern int iic_control (unsigned char, int, char *, int);
-
-static int set_rtc_time(unsigned long nowtime)
-{
-	char buf[5], ctrl;
-
-	if (iic_control(0xa1, 0, &ctrl, 1) != 0)
-		printk("RTC: failed to read control reg\n");
-
-	/*
-	 * Reset divider
-	 */
-	ctrl |= 0x80;
-
-	if (iic_control(0xa0, 0, &ctrl, 1) != 0)
-		printk("RTC: failed to stop the clock\n");
-
-	/*
-	 * We only set the time - we don't set the date.
-	 * This means that there is the possibility once
-	 * a day for the correction to disrupt the date.
-	 * We really ought to write the time and date, or
-	 * nothing at all.
-	 */
-	buf[0] = 0;
-	buf[1] = nowtime % 60;		nowtime /= 60;
-	buf[2] = nowtime % 60;		nowtime /= 60;
-	buf[3] = nowtime % 24;
-
-	BIN_TO_BCD(buf[1]);
-	BIN_TO_BCD(buf[2]);
-	BIN_TO_BCD(buf[3]);
-
-	if (iic_control(0xa0, 1, buf, 4) != 0)
-		printk("RTC: Failed to set the time\n");
-
-	/*
-	 * Re-enable divider
-	 */
-	ctrl &= ~0x80;
-
-	if (iic_control(0xa0, 0, &ctrl, 1) != 0)
-		printk("RTC: failed to start the clock\n");
-
-	return 0;
-}
-
-extern __inline__ unsigned long get_rtc_time(void)
-{
-	unsigned int year, i;
-	char buf[8];
-
-	/*
-	 * The year is not part of the RTC counter
-	 * registers, and is stored in RAM.  This
-	 * means that it will not be automatically
-	 * updated.
-	 */
-	if (iic_control(0xa1, 0xc0, buf, 1) != 0)
-		printk("RTC: failed to read the year\n");
-
-	/*
-	 * If the year is before 1970, then the year
-	 * is actually 100 in advance.  This gives us
-	 * a year 2070 bug...
-	 */
-	year = 1900 + buf[0];
-	if (year < 1970)
-		year += 100;
-
-	/*
-	 * Read the time and date in one go - this
-	 * will ensure that we don't get any effects
-	 * due to carry (the RTC latches the counters
-	 * during a read).
-	 */
-	if (iic_control(0xa1, 2, buf, 5) != 0) {
-		printk("RTC: failed to read the time and date\n");
-		memset(buf, 0, sizeof(buf));
-	}
-
-	/*
-	 * The RTC combines years with date and weekday
-	 * with month.  We need to mask off this extra
-	 * information before converting the date to
-	 * binary.
-	 */
-	buf[4] &= 0x1f;
-	buf[3] &= 0x3f;
-
-	for (i = 0; i < 5; i++)
-		BCD_TO_BIN(buf[i]);
-
-	return mktime(year, buf[4], buf[3], buf[2], buf[1], buf[0]);
-}
+extern void ioctime_init(void);
 
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	do_timer(regs);
-
-	/* If we have an externally synchronized linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec >= 50000 - (tick >> 1) &&
-	    xtime.tv_usec < 50000 + (tick >> 1)) {
-		if (set_rtc_time(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-	}
-
-	if (!user_mode(regs))
-		do_profile(instruction_pointer(regs));
+	do_set_rtc();
+	do_profile(regs);
 }
 
-static struct irqaction timerirq = {
-	timer_interrupt,
-	0,
-	0,
-	"timer",
-	NULL,
-	NULL
-};
-
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up timer interrupt.
  */
 extern __inline__ void setup_timer(void)
 {
-	outb(LATCH & 255, IOC_T0LTCHL);
-	outb(LATCH >> 8, IOC_T0LTCHH);
-	outb(0, IOC_T0GO);
+	ioctime_init();
 
-	xtime.tv_sec = get_rtc_time();
+	timer_irq.handler = timer_interrupt;
 
-	setup_arm_irq(IRQ_TIMER, &timerirq);
+	setup_arm_irq(IRQ_TIMER, &timer_irq);
 }
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/arch-cl7500/time.h linux/include/asm-arm/arch-cl7500/time.h
--- v2.3.42/linux/include/asm-arm/arch-cl7500/time.h	Tue Nov 23 22:42:21 1999
+++ linux/include/asm-arm/arch-cl7500/time.h	Sun Feb  6 17:45:25 2000
@@ -1,88 +1,19 @@
 /*
  * linux/include/asm-arm/arch-cl7500/time.h
  *
- * Copyright (c) 1996 Russell King.
- * Copyright (C) 1999 Nexus Electronics Ltd.
+ * Copyright (c) 1996-2000 Russell King.
  *
  * Changelog:
  *  24-Sep-1996	RMK	Created
  *  10-Oct-1996	RMK	Brought up to date with arch-sa110eval
  *  04-Dec-1997	RMK	Updated for new arch/arm/time.c
- *  10-Aug-1999	PJB	Converted for CL7500
  */
-#include <asm/iomd.h>
-
-static long last_rtc_update = 0;	/* last time the cmos clock got updated */
-
-extern __inline__ unsigned long gettimeoffset (void)
-{
-	unsigned long offset = 0;
-	unsigned int count1, count2, status1, status2;
-
-	status1 = IOMD_IRQREQA;
-	barrier ();
-	outb(0, IOMD_T0LATCH);
-	barrier ();
-	count1 = inb(IOMD_T0CNTL) | (inb(IOMD_T0CNTH) << 8);
-	barrier ();
-	status2 = inb(IOMD_IRQREQA);
-	barrier ();
-	outb(0, IOMD_T0LATCH);
-	barrier ();
-	count2 = inb(IOMD_T0CNTL) | (inb(IOMD_T0CNTH) << 8);
-
-	if (count2 < count1) {
-		/*
-		 * This means that we haven't just had an interrupt
-		 * while reading into status2.
-		 */
-		if (status2 & (1 << 5))
-			offset = tick;
-		count1 = count2;
-	} else if (count2 > count1) {
-		/*
-		 * We have just had another interrupt while reading
-		 * status2.
-		 */
-		offset += tick;
-		count1 = count2;
-	}
-
-	count1 = LATCH - count1;
-	/*
-	 * count1 = number of clock ticks since last interrupt
-	 */
-	offset += count1 * tick / LATCH;
-	return offset;
-}
-
-extern __inline__ unsigned long get_rtc_time(void)
-{
-	return mktime(1976, 06, 24, 0, 0, 0);
-}
-
-static int set_rtc_time(unsigned long nowtime)
-{
-	return 0;
-}
+extern void ioctime_init(void);
 
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	do_timer(regs);
-
-	/* If we have an externally synchronized linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec >= 50000 - (tick >> 1) &&
-	    xtime.tv_usec < 50000 + (tick >> 1)) {
-		if (set_rtc_time(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-	}
+	do_set_rtc();
 
 	{
 		/* Twinkle the lights. */
@@ -95,29 +26,17 @@
 		}
 	}
 
-	if (!user_mode(regs))
-		do_profile(instruction_pointer(regs));
+	do_profile(regs);
 }
 
-static struct irqaction timerirq = {
-	timer_interrupt,
-	0,
-	0,
-	"timer",
-	NULL,
-	NULL
-};
-
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up timer interrupt.
  */
 extern __inline__ void setup_timer(void)
 {
-	outb(LATCH & 255, IOMD_T0LTCHL);
-	outb(LATCH >> 8, IOMD_T0LTCHH);
-	outb(0, IOMD_T0GO);
+	ioctime_init();
 
-	xtime.tv_sec = get_rtc_time();
+	timer_irq.handler = timer_interrupt;
 
-	setup_arm_irq(IRQ_TIMER, &timerirq);
+	setup_arm_irq(IRQ_TIMER, &timer_irq);
 }
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/arch-ebsa110/time.h linux/include/asm-arm/arch-ebsa110/time.h
--- v2.3.42/linux/include/asm-arm/arch-ebsa110/time.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-ebsa110/time.h	Tue Feb  8 12:01:59 2000
@@ -12,11 +12,8 @@
  *  28-Dec-1998	APH	Made leds code optional
  */
 
-#include <linux/config.h>
 #include <asm/leds.h>
 
-#define IRQ_TIMER IRQ_EBSA110_TIMER0
-
 #define MCLK_47_8
 
 #if defined(MCLK_42_3)
@@ -32,52 +29,27 @@
 #define PIT1_COUNT 0x85A1
 #define DIVISOR 2
 #endif
- 
-extern __inline__ unsigned long gettimeoffset (void)
-{
-	return 0;
-}
 
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	*PIT_T1 = (PIT1_COUNT) & 0xff;
 	*PIT_T1 = (PIT1_COUNT) >> 8;
 
-#ifdef CONFIG_LEDS
-	{
-		static int count = 50;
-		if (--count == 0) {
-			count = 50;
-			leds_event(led_timer);
-		}
-	}
-#endif
-
-	{
 #ifdef DIVISOR
+	{
 		static unsigned int divisor;
 
-		if (divisor-- == 0) {
-			divisor = DIVISOR - 1;
-#else
-		{
-#endif
-			do_timer(regs);
-		}
+		if (divisor--)
+			return;
+		divisor = DIVISOR - 1;
 	}
+#endif
+	do_leds();
+	do_timer(regs);
 }
 
-static struct irqaction timerirq = {
-	timer_interrupt,
-	0,
-	0,
-	"timer",
-	NULL,
-	NULL
-};
-
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up timer interrupt.
  */
 extern __inline__ void setup_timer(void)
 {
@@ -93,12 +65,9 @@
 	*PIT_T1 = (PIT1_COUNT) & 0xff;
 	*PIT_T1 = (PIT1_COUNT) >> 8;
 
-	/*
-	 * Default the date to 1 Jan 1970 0:0:0
-	 * You will have to run a time daemon to set the
-	 * clock correctly at bootup
-	 */
-	xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
+	timer_irq.handler = timer_interrupt;
 
-	setup_arm_irq(IRQ_TIMER, &timerirq);
+	setup_arm_irq(IRQ_EBSA110_TIMER0, &timer_irq);
 }
+
+
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/arch-ebsa285/time.h linux/include/asm-arm/arch-ebsa285/time.h
--- v2.3.42/linux/include/asm-arm/arch-ebsa285/time.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-ebsa285/time.h	Tue Feb  8 12:01:59 2000
@@ -17,7 +17,6 @@
 #define RTC_PORT(x)		(rtc_base+(x))
 #define RTC_ALWAYS_BCD		0
 
-#include <linux/config.h>
 #include <linux/mc146818rtc.h>
 
 #include <asm/dec21285.h>
@@ -25,32 +24,6 @@
 #include <asm/system.h>
 
 static int rtc_base;
-static unsigned long (*gettimeoffset)(void);
-static int (*set_rtc_mmss)(unsigned long nowtime);
-static long last_rtc_update = 0;	/* last time the cmos clock got updated */
-
-#ifdef CONFIG_LEDS
-static void do_leds(void)
-{
-	static unsigned int count = 50;
-	static int last_pid;
-
-	if (current->pid != last_pid) {
-		last_pid = current->pid;
-		if (last_pid)
-			leds_event(led_idle_end);
-		else
-			leds_event(led_idle_start);
-	}
-		
-	if (--count == 0) {
-		count = 50;
-		leds_event(led_timer);
-	}
-}
-#else
-#define do_leds()
-#endif
 
 #define mSEC_10_from_14 ((14318180 + 100) / 200)
 
@@ -101,34 +74,10 @@
 		do_leds();
 
 	do_timer(regs);
-
-	/* If we have an externally synchronized linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec > 50000 - (tick >> 1) &&
-	    xtime.tv_usec < 50000 + (tick >> 1)) {
-		if (set_rtc_mmss(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-	}
-
-	if (!user_mode(regs))
-		do_profile(instruction_pointer(regs));
+	do_set_rtc();
+	do_profile(regs);
 }
 
-static struct irqaction isa_timer_irq = {
-	isa_timer_interrupt,
-	0,
-	0,
-	"timer",
-	NULL,
-	NULL
-};
-
 static unsigned long __init get_isa_cmos_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
@@ -175,11 +124,12 @@
 }
 
 static int
-set_isa_cmos_time(unsigned long nowtime)
+set_isa_cmos_time(void)
 {
 	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
 	unsigned char save_control, save_freq_select;
+	unsigned long nowtime = xtime.tv_sec;
 
 	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
 	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
@@ -228,60 +178,31 @@
 
 
 
-static unsigned long __ebsa285_text timer1_gettimeoffset (void)
+static unsigned long timer1_gettimeoffset (void)
 {
 	unsigned long value = LATCH - *CSR_TIMER1_VALUE;
 
 	return (tick * value) / LATCH;
 }
 
-static void __ebsa285_text timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	*CSR_TIMER1_CLR = 0;
 
 	/* Do the LEDs things */
 	do_leds();
-
 	do_timer(regs);
-
-	/* If we have an externally synchronized linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec > 50000 - (tick >> 1) &&
-	    xtime.tv_usec < 50000 + (tick >> 1)) {
-		if (set_rtc_mmss(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-	}
-
-	if (!user_mode(regs))
-		do_profile(instruction_pointer(regs));
-}
-
-static struct irqaction __ebsa285_data timer1_irq = {
-	timer1_interrupt,
-	0,
-	0,
-	"timer",
-	NULL,
-	NULL
-};
-
-static int
-set_dummy_time(unsigned long secs)
-{
-	return 1;
+	do_set_rtc();
+	do_profile(regs);
 }
 
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up timer interrupt.
  */
 extern __inline__ void setup_timer(void)
 {
+	int irq;
+
 	if (machine_is_co285())
 		/*
 		 * Add-in 21285s shouldn't access the RTC
@@ -321,18 +242,11 @@
 				printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
 
 			xtime.tv_sec = get_isa_cmos_time();
-			set_rtc_mmss = set_isa_cmos_time;
+			set_rtc = set_isa_cmos_time;
 		} else
 			rtc_base = 0;
 	}
 
-	if (!rtc_base) {
-		/*
-		 * Default the date to 1 Jan 1970 0:0:0
-		 */
-		xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
-		set_rtc_mmss = set_dummy_time;
-	}
 	if (machine_is_ebsa285() || machine_is_co285()) {
 		gettimeoffset = timer1_gettimeoffset;
 
@@ -340,7 +254,8 @@
 		*CSR_TIMER1_LOAD = LATCH;
 		*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
 
-		setup_arm_irq(IRQ_TIMER1, &timer1_irq);
+		timer_irq.handler = timer1_interrupt;
+		irq = IRQ_TIMER1;
 	} else {
 		/* enable PIT timer */
 		/* set for periodic (4) and LSB/MSB write (0x30) */
@@ -349,7 +264,8 @@
 		outb((mSEC_10_from_14/6) >> 8, 0x40);
 
 		gettimeoffset = isa_gettimeoffset;
-
-		setup_arm_irq(IRQ_ISA_TIMER, &isa_timer_irq);
+		timer_irq.handler = isa_timer_interrupt;
+		irq = IRQ_ISA_TIMER;
 	}
+	setup_arm_irq(IRQ_ISA_TIMER, &timer_irq);
 }
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/arch-nexuspci/time.h linux/include/asm-arm/arch-nexuspci/time.h
--- v2.3.42/linux/include/asm-arm/arch-nexuspci/time.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/arch-nexuspci/time.h	Sun Feb  6 17:45:25 2000
@@ -10,13 +10,6 @@
 #define UART_BASE		0xfff00000
 #define INTCONT			0xffe00000
 
-#define update_rtc()
-
-extern __inline__ unsigned long gettimeoffset (void)
-{
-	return 0;
-}
-
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	static int count = 50;
@@ -40,15 +33,6 @@
 	do_timer(regs);	
 }
 
-static struct irqaction timerirq = {
-	timer_interrupt,
-	0,
-	0,
-	"timer",
-	NULL,
-	NULL
-};
-
 extern __inline__ void setup_timer(void)
 {
 	int tick = 3686400 / 16 / 2 / 100;
@@ -58,12 +42,7 @@
 	writeb(0x80, UART_BASE + 8);
 	writeb(0x10, UART_BASE + 0x14);
 
-	/*
-	 * Default the date to 1 Jan 1970 0:0:0
-	 * You will have to run a time daemon to set the
-	 * clock correctly at bootup
-	 */
-	xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
+	timer_irq.handler = timer_interrupt;
 
-	setup_arm_irq(IRQ_TIMER, &timerirq);
+	setup_arm_irq(IRQ_TIMER, &timer_irq);
 }
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/arch-rpc/time.h linux/include/asm-arm/arch-rpc/time.h
--- v2.3.42/linux/include/asm-arm/arch-rpc/time.h	Mon Jul 19 09:52:57 1999
+++ linux/include/asm-arm/arch-rpc/time.h	Sun Feb  6 17:45:25 2000
@@ -1,204 +1,30 @@
 /*
  * linux/include/asm-arm/arch-rpc/time.h
  *
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-2000 Russell King.
  *
  * Changelog:
  *  24-Sep-1996	RMK	Created
  *  10-Oct-1996	RMK	Brought up to date with arch-sa110eval
  *  04-Dec-1997	RMK	Updated for new arch/arm/time.c
  */
-#include <asm/iomd.h>
-
-static long last_rtc_update = 0;	/* last time the cmos clock got updated */
-
-extern __inline__ unsigned long gettimeoffset (void)
-{
-	unsigned long offset = 0;
-	unsigned int count1, count2, status1, status2;
-
-	status1 = IOMD_IRQREQA;
-	barrier ();
-	outb(0, IOMD_T0LATCH);
-	barrier ();
-	count1 = inb(IOMD_T0CNTL) | (inb(IOMD_T0CNTH) << 8);
-	barrier ();
-	status2 = inb(IOMD_IRQREQA);
-	barrier ();
-	outb(0, IOMD_T0LATCH);
-	barrier ();
-	count2 = inb(IOMD_T0CNTL) | (inb(IOMD_T0CNTH) << 8);
-
-	if (count2 < count1) {
-		/*
-		 * This means that we haven't just had an interrupt
-		 * while reading into status2.
-		 */
-		if (status2 & (1 << 5))
-			offset = tick;
-		count1 = count2;
-	} else if (count2 > count1) {
-		/*
-		 * We have just had another interrupt while reading
-		 * status2.
-		 */
-		offset += tick;
-		count1 = count2;
-	}
-
-	count1 = LATCH - count1;
-	/*
-	 * count1 = number of clock ticks since last interrupt
-	 */
-	offset += count1 * tick / LATCH;
-	return offset;
-}
-
-extern int iic_control(unsigned char, int, char *, int);
-
-static int set_rtc_time(unsigned long nowtime)
-{
-	char buf[5], ctrl;
-
-	if (iic_control(0xa1, 0, &ctrl, 1) != 0)
-		printk("RTC: failed to read control reg\n");
-
-	/*
-	 * Reset divider
-	 */
-	ctrl |= 0x80;
-
-	if (iic_control(0xa0, 0, &ctrl, 1) != 0)
-		printk("RTC: failed to stop the clock\n");
-
-	/*
-	 * We only set the time - we don't set the date.
-	 * This means that there is the possibility once
-	 * a day for the correction to disrupt the date.
-	 * We really ought to write the time and date, or
-	 * nothing at all.
-	 */
-	buf[0] = 0;
-	buf[1] = nowtime % 60;		nowtime /= 60;
-	buf[2] = nowtime % 60;		nowtime /= 60;
-	buf[3] = nowtime % 24;
-
-	BIN_TO_BCD(buf[1]);
-	BIN_TO_BCD(buf[2]);
-	BIN_TO_BCD(buf[3]);
-
-	if (iic_control(0xa0, 1, buf, 4) != 0)
-		printk("RTC: Failed to set the time\n");
-
-	/*
-	 * Re-enable divider
-	 */
-	ctrl &= ~0x80;
-
-	if (iic_control(0xa0, 0, &ctrl, 1) != 0)
-		printk("RTC: failed to start the clock\n");
-
-	return 0;
-}
-
-extern __inline__ unsigned long get_rtc_time(void)
-{
-	unsigned int year, i;
-	char buf[8];
-
-	/*
-	 * The year is not part of the RTC counter
-	 * registers, and is stored in RAM.  This
-	 * means that it will not be automatically
-	 * updated.
-	 */
-	if (iic_control(0xa1, 0xc0, buf, 1) != 0)
-		printk("RTC: failed to read the year\n");
-
-	/*
-	 * If the year is before 1970, then the year
-	 * is actually 100 in advance.  This gives us
-	 * a year 2070 bug...
-	 */
-	year = 1900 + buf[0];
-	if (year < 1970)
-		year += 100;
-
-	/*
-	 * Read the time and date in one go - this
-	 * will ensure that we don't get any effects
-	 * due to carry (the RTC latches the counters
-	 * during a read).
-	 */
-	if (iic_control(0xa1, 2, buf, 5) != 0) {
-		printk("RTC: failed to read the time and date\n");
-		memset(buf, 0, sizeof(buf));
-	}
-
-	/*FIXME:
-	 * This doesn't seem to work.  Does RISC OS
-	 * actually use the RTC year?  It doesn't
-	 * seem to.  In that case, how does it update
-	 * the CMOS year?
-	 */
-	/*year += (buf[3] >> 6) & 3;*/
-
-	/*
-	 * The RTC combines years with date and weekday
-	 * with month.  We need to mask off this extra
-	 * information before converting the date to
-	 * binary.
-	 */
-	buf[4] &= 0x1f;
-	buf[3] &= 0x3f;
-
-	for (i = 0; i < 5; i++)
-		BCD_TO_BIN(buf[i]);
-
-	return mktime(year, buf[4], buf[3], buf[2], buf[1], buf[0]);
-}
+extern void ioctime_init(void);
 
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	do_timer(regs);
-
-	/* If we have an externally synchronized linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 */
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec >= 50000 - (tick >> 1) &&
-	    xtime.tv_usec < 50000 + (tick >> 1)) {
-		if (set_rtc_time(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-	}
-
-	if (!user_mode(regs))
-		do_profile(instruction_pointer(regs));
+	do_set_rtc();
+	do_profile(regs);
 }
 
-static struct irqaction timerirq = {
-	timer_interrupt,
-	0,
-	0,
-	"timer",
-	NULL,
-	NULL
-};
-
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up timer interrupt.
  */
 extern __inline__ void setup_timer(void)
 {
-	outb(LATCH & 255, IOMD_T0LTCHL);
-	outb(LATCH >> 8, IOMD_T0LTCHH);
-	outb(0, IOMD_T0GO);
+	ioctime_init();
 
-	xtime.tv_sec = get_rtc_time();
+	timer_irq.handler = timer_interrupt;
 
-	setup_arm_irq(IRQ_TIMER, &timerirq);
+	setup_arm_irq(IRQ_TIMER, &timer_irq);
 }
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/arch-sa1100/system.h linux/include/asm-arm/arch-sa1100/system.h
--- v2.3.42/linux/include/asm-arm/arch-sa1100/system.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-arm/arch-sa1100/system.h	Sun Feb  6 17:45:26 2000
@@ -41,6 +41,7 @@
 "	b	1f			@ Seems we must align the next \n" \
 "	.align 5			@ instruction on a cache line \n" \
 "1:	mcr	p15, 0, %0, c15, c8, 2	@ Wait for interrupts \n" \
+"	mov	r0, r0			@ insert NOP to ensure SA1100 re-awakes\n" \
 "	mcr	p15, 0, %0, c15, c1, 2	@ Reenable clock switching \n" \
 	: : "r" (&ICIP) : "cc" ); \
 	} while (0)
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/checksum.h linux/include/asm-arm/checksum.h
--- v2.3.42/linux/include/asm-arm/checksum.h	Tue Feb  1 01:35:44 2000
+++ linux/include/asm-arm/checksum.h	Sun Feb  6 17:45:26 2000
@@ -55,9 +55,9 @@
 	unsigned int sum, tmp1;
 
 	__asm__ __volatile__(
-	"sub	%2, %2, #5		@ ip_fast_csum
-	ldr	%0, [%1], #4
+	"ldr	%0, [%1], #4		@ ip_fast_csum
 	ldr	%3, [%1], #4
+	sub	%2, %2, #5
 	adds	%0, %0, %3
 	ldr	%3, [%1], #4
 	adcs	%0, %0, %3
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/mmu_context.h linux/include/asm-arm/mmu_context.h
--- v2.3.42/linux/include/asm-arm/mmu_context.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/mmu_context.h	Mon Feb  7 20:01:14 2000
@@ -17,6 +17,9 @@
 #define destroy_context(mm)		do { } while(0)
 #define init_new_context(tsk,mm)	do { } while(0)
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
 /*
  * This is the actual mm switch as far as the scheduler
  * is concerned.  No registers are touched.
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/pgalloc.h linux/include/asm-arm/pgalloc.h
--- v2.3.42/linux/include/asm-arm/pgalloc.h	Tue Nov 23 22:42:21 1999
+++ linux/include/asm-arm/pgalloc.h	Tue Feb  8 18:23:13 2000
@@ -14,6 +14,12 @@
  */
 #include <asm/proc/cache.h>
 
+extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm,
+					  unsigned long start,
+					  unsigned long end)
+{
+}
+
 /*
  * Page table cache stuff
  */
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/proc-armv/system.h linux/include/asm-arm/proc-armv/system.h
--- v2.3.42/linux/include/asm-arm/proc-armv/system.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/proc-armv/system.h	Sun Feb  6 17:45:26 2000
@@ -16,7 +16,6 @@
 	switch (size) {
 		case 1:	__asm__ __volatile__ ("swpb %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory");
 			break;
-		case 2:	abort ();
 		case 4:	__asm__ __volatile__ ("swp %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory");
 			break;
 		default: arm_invalidptr(xchg_str, size);
@@ -25,11 +24,9 @@
 }
 
 #define set_cr(x)					\
-	do {						\
 	__asm__ __volatile__(				\
 	"mcr	p15, 0, %0, c1, c0	@ set CR"	\
-	  : : "r" (x));					\
-	} while (0)
+	: : "r" (x))
 
 extern unsigned long cr_no_alignment;	/* defined in entry-armv.S */
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
@@ -42,76 +39,66 @@
  * Save the current interrupt enable state & disable IRQs
  */
 #define __save_flags_cli(x)					\
-	do {							\
-	  unsigned long temp;					\
-	  __asm__ __volatile__(					\
-	"mrs	%1, cpsr		@ save_flags_cli\n"	\
-"	and	%0, %1, #192\n"					\
-"	orr	%1, %1, #128\n"					\
-"	msr	cpsr, %1"					\
-	  : "=r" (x), "=r" (temp)				\
-	  :							\
-	  : "memory");						\
-	} while (0)
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ save_flags_cli\n"	\
+"	orr	%1, %0, #128\n"					\
+"	msr	cpsr_c, %1"					\
+	: "=r" (x), "=r" (temp)					\
+	:							\
+	: "memory");						\
+	})
 	
 /*
  * Enable IRQs
  */
 #define __sti()							\
-	do {							\
-	  unsigned long temp;					\
-	  __asm__ __volatile__(					\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
 	"mrs	%0, cpsr		@ sti\n"		\
 "	bic	%0, %0, #128\n"					\
-"	msr	cpsr, %0"					\
-	  : "=r" (temp)						\
-	  :							\
-	  : "memory");						\
-	} while(0)
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory");						\
+	})
 
 /*
  * Disable IRQs
  */
 #define __cli()							\
-	do {							\
-	  unsigned long temp;					\
-	  __asm__ __volatile__(					\
+	({							\
+		unsigned long temp;				\
+	__asm__ __volatile__(					\
 	"mrs	%0, cpsr		@ cli\n"		\
 "	orr	%0, %0, #128\n"					\
-"	msr	cpsr, %0"					\
-	  : "=r" (temp)						\
-	  :							\
-	  : "memory");						\
-	} while(0)
+"	msr	cpsr_c, %0"					\
+	: "=r" (temp)						\
+	:							\
+	: "memory");						\
+	})
 
 /*
  * save current IRQ & FIQ state
  */
 #define __save_flags(x)						\
-	do {							\
-	  __asm__ __volatile__(					\
+	__asm__ __volatile__(					\
 	"mrs	%0, cpsr		@ save_flags\n"		\
-"	and	%0, %0, #192"					\
 	  : "=r" (x)						\
 	  :							\
-	  : "memory");						\
-	} while (0)
+	  : "memory")
 
 /*
  * restore saved IRQ & FIQ state
  */
 #define __restore_flags(x)					\
-	do {							\
-	  unsigned long temp;					\
-	  __asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ restore_flags\n"	\
-"	bic	%0, %0, #192\n"					\
-"	orr	%0, %0, %1\n"					\
-"	msr	cpsr, %0"					\
-	  : "=&r" (temp)					\
-	  : "r" (x)						\
-	  : "memory");			\
-	} while (0)
+	__asm__ __volatile__(					\
+	"msr	cpsr_c, %0		@ restore_flags\n"	\
+	:							\
+	: "r" (x)						\
+	: "memory")
 
 /* For spinlocks etc */
 #define local_irq_save(x)	__save_flags_cli(x)
diff -u --recursive --new-file v2.3.42/linux/include/asm-arm/types.h linux/include/asm-arm/types.h
--- v2.3.42/linux/include/asm-arm/types.h	Sun Apr 12 11:42:16 1998
+++ linux/include/asm-arm/types.h	Sun Feb  6 17:45:26 2000
@@ -41,6 +41,10 @@
 
 #define BITS_PER_LONG 32
 
+/* Dma addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+
 #endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h
--- v2.3.42/linux/include/asm-i386/hardirq.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-i386/hardirq.h	Wed Feb  9 21:33:02 2000
@@ -12,6 +12,8 @@
 #define in_interrupt() ({ int __cpu = smp_processor_id(); \
 	(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
 
+#define in_irq() (local_irq_count[smp_processor_id()] != 0)
+
 #ifndef __SMP__
 
 #define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.3.42/linux/include/asm-i386/io.h	Tue Dec 14 01:27:24 1999
+++ linux/include/asm-i386/io.h	Thu Feb 10 12:36:40 2000
@@ -195,15 +195,15 @@
  */
 #define __ISA_IO_base ((char *)(PAGE_OFFSET))
 
-#define isa_readb(a) readb(__ISA_IO_base + (a))
-#define isa_readw(a) readw(__ISA_IO_base + (a))
-#define isa_readl(a) readl(__ISA_IO_base + (a))
-#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (a))
-#define isa_writew(w,a) writew(w,__ISA_IO_base + (a))
-#define isa_writel(l,a) writel(l,__ISA_IO_base + (a))
-#define isa_memset_io(a,b,c)		memset_io(__ISA_IO_base + (a),(b),(c))
-#define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),__ISA_IO_base + (b),(c))
-#define isa_memcpy_toio(a,b,c)		memcpy_toio(__ISA_IO_base + (a),(b),(c))
+#define isa_readb(a) readb(__ISA_IO_base + (unsigned long)(a))
+#define isa_readw(a) readw(__ISA_IO_base + (unsigned long)(a))
+#define isa_readl(a) readl(__ISA_IO_base + (unsigned long)(a))
+#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (unsigned long)(a))
+#define isa_writew(w,a) writew(w,__ISA_IO_base + (unsigned long)(a))
+#define isa_writel(l,a) writel(l,__ISA_IO_base + (unsigned long)(a))
+#define isa_memset_io(a,b,c)		memset_io(__ISA_IO_base + (unsigned long)(a),(b),(c))
+#define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),__ISA_IO_base + (unsigned long)(b),(c))
+#define isa_memcpy_toio(a,b,c)		memcpy_toio(__ISA_IO_base + (unsigned long)(a),(b),(c))
 
 
 /*
@@ -211,7 +211,7 @@
  */
 
 #define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),__io_virt(b),(c),(d))
-#define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d))
+#define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (unsigned long)(b)),(c),(d))
 
 static inline int check_signature(unsigned long io_addr,
 	const unsigned char *signature, int length)
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/md.h linux/include/asm-i386/md.h
--- v2.3.42/linux/include/asm-i386/md.h	Fri May  8 00:17:13 1998
+++ linux/include/asm-i386/md.h	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-/* $Id: md.h,v 1.1 1997/12/15 15:11:57 jj Exp $
- * md.h: High speed xor_block operation for RAID4/5 
- *
- */
- 
-#ifndef __ASM_MD_H
-#define __ASM_MD_H
-
-/* #define HAVE_ARCH_XORBLOCK */
-
-#define MD_XORBLOCK_ALIGNMENT	sizeof(long)
-
-#endif /* __ASM_MD_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/mmu_context.h linux/include/asm-i386/mmu_context.h
--- v2.3.42/linux/include/asm-i386/mmu_context.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-i386/mmu_context.h	Wed Feb  9 21:33:07 2000
@@ -1,6 +1,7 @@
 #ifndef __I386_MMU_CONTEXT_H
 #define __I386_MMU_CONTEXT_H
 
+#include <linux/config.h>
 #include <asm/desc.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
@@ -12,30 +13,46 @@
 #define init_new_context(tsk,mm)	do { } while (0)
 
 #ifdef __SMP__
-extern unsigned int cpu_tlbbad[NR_CPUS];
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+	if(cpu_tlbstate[cpu].state == TLBSTATE_OK)
+		cpu_tlbstate[cpu].state = TLBSTATE_LAZY;	
+}
+#else
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
 #endif
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
 {
+	set_bit(cpu, &next->cpu_vm_mask);
 	if (prev != next) {
 		/*
 		 * Re-load LDT if necessary
 		 */
 		if (prev->segments != next->segments)
 			load_LDT(next);
-
+#ifdef CONFIG_SMP
+		cpu_tlbstate[cpu].state = TLBSTATE_OK;
+		cpu_tlbstate[cpu].active_mm = next;
+#endif
 		/* Re-load page tables */
 		asm volatile("movl %0,%%cr3": :"r" (__pa(next->pgd)));
 		clear_bit(cpu, &prev->cpu_vm_mask);
 	}
 #ifdef __SMP__
 	else {
-		if(cpu_tlbbad[cpu])
+		int old_state = cpu_tlbstate[cpu].state;
+		cpu_tlbstate[cpu].state = TLBSTATE_OK;
+		if(cpu_tlbstate[cpu].active_mm != next)
+			BUG();
+		if(old_state == TLBSTATE_OLD)
 			local_flush_tlb();
 	}
-	cpu_tlbbad[cpu] = 0;
+
 #endif
-	set_bit(cpu, &next->cpu_vm_mask);
 }
 
 #define activate_mm(prev, next) \
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
--- v2.3.42/linux/include/asm-i386/page.h	Mon Dec 20 18:48:22 1999
+++ linux/include/asm-i386/page.h	Wed Feb  9 21:32:58 2000
@@ -37,10 +37,12 @@
 typedef struct { unsigned long long pte; } pte_t;
 typedef struct { unsigned long long pmd; } pmd_t;
 typedef struct { unsigned long long pgd; } pgd_t;
+#define PTE_MASK	(~(unsigned long long) (PAGE_SIZE-1))
 #else
 typedef struct { unsigned long pte; } pte_t;
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
+#define PTE_MASK	PAGE_MASK
 #endif
 
 typedef struct { unsigned long pgprot; } pgprot_t;
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/pgalloc.h linux/include/asm-i386/pgalloc.h
--- v2.3.42/linux/include/asm-i386/pgalloc.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-i386/pgalloc.h	Wed Feb  9 21:33:04 2000
@@ -187,6 +187,7 @@
  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  *  - flush_tlb_page(vma, vmaddr) flushes one page
  *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
  *
  * ..but the i386 has somewhat limited tlb flushing capabilities,
  * and page-granular flushes are available only on i486 and up.
@@ -220,11 +221,6 @@
 
 #else
 
-/*
- * We aren't very clever about this yet -  SMP could certainly
- * avoid some global flushes..
- */
-
 #include <asm/smp.h>
 
 #define local_flush_tlb() \
@@ -242,23 +238,24 @@
 	flush_tlb_mm(mm);
 }
 
-extern volatile unsigned long smp_invalidate_needed;
-extern unsigned int cpu_tlbbad[NR_CPUS];
+#define TLBSTATE_OK	1
+#define TLBSTATE_LAZY	2
+#define TLBSTATE_OLD	3
 
-static inline void do_flush_tlb_local(void)
+struct tlb_state
 {
-	unsigned long cpu = smp_processor_id();
-	struct mm_struct *mm = current->mm;
+	struct mm_struct *active_mm;
+	int state;
+};
+extern struct tlb_state cpu_tlbstate[NR_CPUS];
 
-	clear_bit(cpu, &smp_invalidate_needed);
-	if (mm) {
-		set_bit(cpu, &mm->cpu_vm_mask);
-		local_flush_tlb();
-	} else {
-		cpu_tlbbad[cpu] = 1;
-	}
-}
 
 #endif
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+	/* i386 does not keep any page table caches in TLB */
+}
 
 #endif /* _I386_PGALLOC_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.3.42/linux/include/asm-i386/pgtable.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-i386/pgtable.h	Wed Feb  9 21:33:01 2000
@@ -29,12 +29,13 @@
 
 #define __flush_tlb()							\
 	do {								\
-		__asm__ __volatile__					\
-			("movl %0, %%cr3;"				\
-				:					\
-				: "r" __pa(current->active_mm->pgd)	\
-				: "memory"				\
-		);							\
+		unsigned int tmpreg;					\
+									\
+		__asm__ __volatile__(					\
+			"movl %%cr3, %0;  # flush TLB \n"		\
+			"movl %0, %%cr3;              \n"		\
+			: "=r" (tmpreg)					\
+			:: "memory");					\
 	} while (0)
 
 /*
@@ -43,14 +44,16 @@
  */
 #define __flush_tlb_global()						\
 	do {								\
+		unsigned int tmpreg;					\
+									\
 		__asm__ __volatile__(					\
-			"movl %0, %%cr4; # turn off PGE \n"		\
-			"mov %2, %%cr3;  # flush TLB \n"		\
-			"mov %1, %%cr4;  # turn PGE back on \n"		\
-			:						\
-			: "r" (mmu_cr4_features),			\
-			  "r" (mmu_cr4_features & ~X86_CR4_PGE),	\
-			  "r" (__pa(current->active_mm->pgd))		\
+			"movl %1, %%cr4;  # turn off PGE     \n"	\
+			"movl %%cr3, %0;  # flush TLB        \n"	\
+			"movl %0, %%cr3;                     \n"	\
+			"movl %2, %%cr4;  # turn PGE back on \n"	\
+			: "=r" (tmpreg)					\
+			: "r" (mmu_cr4_features & ~X86_CR4_PGE),	\
+			  "r" (mmu_cr4_features)			\
 			: "memory");					\
 	} while (0)
 
@@ -151,7 +154,7 @@
 
 #define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
--- v2.3.42/linux/include/asm-i386/softirq.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-i386/softirq.h	Wed Feb  9 21:33:04 2000
@@ -9,133 +9,9 @@
 #define cpu_bh_disable(cpu)	do { local_bh_count[(cpu)]++; barrier(); } while (0)
 #define cpu_bh_enable(cpu)	do { barrier(); local_bh_count[(cpu)]--; } while (0)
 
-#define cpu_bh_trylock(cpu)	(local_bh_count[(cpu)] ? 0 : (local_bh_count[(cpu)] = 1))
-#define cpu_bh_endlock(cpu)	(local_bh_count[(cpu)] = 0)
-
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 #define local_bh_enable()	cpu_bh_enable(smp_processor_id())
 
-#define get_active_bhs()	(bh_mask & bh_active)
-#define clear_active_bhs(x)	atomic_clear_mask((x),&bh_active)
-
-extern spinlock_t i386_bh_lock;
-
-#ifdef __SMP__
-
-/*
- * The locking mechanism for base handlers, to prevent re-entrancy,
- * is entirely private to an implementation, it should not be
- * referenced at all outside of this file.
- */
-extern atomic_t global_bh_lock;
-extern atomic_t global_bh_count;
-
-extern void synchronize_bh(void);
-
-static inline void start_bh_atomic(void)
-{
-	atomic_inc(&global_bh_lock);
-	synchronize_bh();
-}
-
-static inline void end_bh_atomic(void)
-{
-	atomic_dec(&global_bh_lock);
-}
-
-/* These are for the IRQs testing the lock */
-static inline int softirq_trylock(int cpu)
-{
-	if (cpu_bh_trylock(cpu)) {
-		if (!test_and_set_bit(0,&global_bh_count)) {
-			if (atomic_read(&global_bh_lock) == 0)
-				return 1;
-			clear_bit(0,&global_bh_count);
-		}
-		cpu_bh_endlock(cpu);
-	}
-	return 0;
-}
-
-static inline void softirq_endlock(int cpu)
-{
-	cpu_bh_enable(cpu);
-	clear_bit(0,&global_bh_count);
-}
-
-#else
-
-extern inline void start_bh_atomic(void)
-{
-	local_bh_disable();
-	barrier();
-}
-
-extern inline void end_bh_atomic(void)
-{
-	barrier();
-	local_bh_enable();
-}
-
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)	(cpu_bh_trylock(cpu))
-#define softirq_endlock(cpu)	(cpu_bh_endlock(cpu))
-#define synchronize_bh()	barrier()
-
-#endif	/* SMP */
-
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-	unsigned long flags;
-
-	bh_base[nr] = routine;
-	atomic_set(&bh_mask_count[nr], 0);
-
-	spin_lock_irqsave(&i386_bh_lock, flags);
-	bh_mask |= 1 << nr;
-	spin_unlock_irqrestore(&i386_bh_lock, flags);
-}
-
-extern inline void remove_bh(int nr)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&i386_bh_lock, flags);
-	bh_mask &= ~(1 << nr);
-	spin_unlock_irqrestore(&i386_bh_lock, flags);
-
-	synchronize_bh();
-	bh_base[nr] = NULL;
-}
-
-extern inline void mark_bh(int nr)
-{
-	set_bit(nr, &bh_active);
-}
-
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&i386_bh_lock, flags);
-	bh_mask &= ~(1 << nr);
-	atomic_inc(&bh_mask_count[nr]);
-	spin_unlock_irqrestore(&i386_bh_lock, flags);
-	synchronize_bh();
-}
-
-extern inline void enable_bh(int nr)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&i386_bh_lock, flags);
-	if (atomic_dec_and_test(&bh_mask_count[nr]))
-		bh_mask |= 1 << nr;
-	spin_unlock_irqrestore(&i386_bh_lock, flags);
-}
+#define in_softirq() (local_bh_count[smp_processor_id()] != 0)
 
 #endif	/* __ASM_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-i386/spinlock.h linux/include/asm-i386/spinlock.h
--- v2.3.42/linux/include/asm-i386/spinlock.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-i386/spinlock.h	Wed Feb  9 21:32:58 2000
@@ -44,6 +44,7 @@
  */
 
 #define spin_unlock_wait(x)	do { barrier(); } while(((volatile spinlock_t *)(x))->lock)
+#define spin_is_locked(x)	((x)->lock != 0)
 
 #define spin_lock_string \
 	"\n1:\t" \
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/a.out.h linux/include/asm-ia64/a.out.h
--- v2.3.42/linux/include/asm-ia64/a.out.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/a.out.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,38 @@
+#ifndef _ASM_IA64_A_OUT_H
+#define _ASM_IA64_A_OUT_H
+
+/*
+ * No a.out format has been (or should be) defined so this file is
+ * just a dummy that allows us to get binfmt_elf compiled.  It
+ * probably would be better to clean up binfmt_elf.c so it does not
+ * necessarily depend on there being a.out support.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/types.h>
+
+struct exec
+{
+	unsigned long a_info;
+	unsigned long a_text;
+	unsigned long a_data;
+	unsigned long a_bss;
+	unsigned long a_entry;
+};
+
+#define N_TXTADDR(x)	0
+#define N_DATADDR(x)	0
+#define N_BSSADDR(x)	0
+#define N_DRSIZE(x)	0
+#define N_TRSIZE(x)	0
+#define N_SYMSIZE(x)	0
+#define N_TXTOFF(x)	0
+
+#ifdef __KERNEL__
+# define STACK_TOP	0xa000000000000000UL
+# define IA64_RBS_BOT	(STACK_TOP - 0x80000000L)	/* bottom of register backing store */
+#endif
+
+#endif /* _ASM_IA64_A_OUT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/acpi-ext.h linux/include/asm-ia64/acpi-ext.h
--- v2.3.42/linux/include/asm-ia64/acpi-ext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/acpi-ext.h	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,110 @@
+#ifndef _ASM_IA64_ACPI_EXT_H
+#define _ASM_IA64_ACPI_EXT_H
+
+/*
+ * Advanced Configuration and Power Infterface
+ * Based on 'ACPI Specification 1.0b' Febryary 2, 1999
+ * and 'IA-64 Extensions to the ACPI Specification' Rev 0.6
+ * 
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ */
+
+#include <linux/types.h>
+
+#define ACPI_RSDP_SIG "RSD PTR " /* Trailing space required */
+#define ACPI_RSDP_SIG_LEN 8
+typedef struct {
+	char signature[8];
+	u8 checksum;
+	char oem_id[6];
+	char reserved;		/* Must be 0 */
+	struct acpi_rsdt *rsdt;
+} acpi_rsdp_t;
+
+typedef struct {
+	char signature[4];
+	u32 length;
+	u8 revision;
+	u8 checksum;
+	char oem_id[6];
+	char oem_table_id[8];
+	u32 oem_revision;
+	u32 creator_id;
+	u32 creator_revision;
+	char reserved[4];
+} acpi_desc_table_hdr_t;
+
+#define ACPI_RSDT_SIG "RSDT"
+#define ACPI_RSDT_SIG_LEN 4
+typedef struct acpi_rsdt {
+	acpi_desc_table_hdr_t header;
+	unsigned long entry_ptrs[1];	/* Not really . . . */
+} acpi_rsdt_t;
+
+#define ACPI_SAPIC_SIG "SPIC"
+#define ACPI_SAPIC_SIG_LEN 4
+typedef struct {
+	acpi_desc_table_hdr_t header;
+	unsigned long interrupt_block;
+} acpi_sapic_t;
+
+/* SAPIC structure types */
+#define ACPI_ENTRY_LOCAL_SAPIC         0
+#define ACPI_ENTRY_IO_SAPIC            1
+#define ACPI_ENTRY_INT_SRC_OVERRIDE    2
+#define ACPI_ENTRY_PLATFORM_INT_SOURCE 3	/* Unimplemented */
+
+/* Local SAPIC flags */
+#define LSAPIC_ENABLED                (1<<0)
+#define LSAPIC_PERFORMANCE_RESTRICTED (1<<1)
+#define LSAPIC_PRESENT                (1<<2)
+
+typedef struct {
+	u8 type;
+	u8 length;
+	u16 acpi_processor_id;
+	u16 flags;
+	u8 id;
+	u8 eid;
+} acpi_entry_lsapic_t;
+
+typedef struct {
+	u8 type;
+	u8 length;
+	u16 reserved;
+	u32 irq_base;	/* start of IRQ's this IOSAPIC is responsible for. */
+	unsigned long address;	/* Address of this IOSAPIC */
+} acpi_entry_iosapic_t;
+
+/* Defines legacy IRQ->pin mapping */
+typedef struct {
+	u8 type;
+	u8 length;
+	u8 bus;	/* Constant 0 == ISA */
+	u8 isa_irq;	/* ISA IRQ # */
+	u8 pin;	/* called vector in spec; really IOSAPIC pin number */
+	u32 flags;	/* Edge/Level trigger & High/Low active */
+	u8 reserved[6];
+} acpi_entry_int_override_t;
+#define INT_OVERRIDE_ACTIVE_LOW    0x03
+#define INT_OVERRIDE_LEVEL_TRIGGER 0x0d
+
+typedef struct {
+	u8 type;
+	u8 length;
+	u32 flags;
+	u8 int_type;
+	u8 id;
+	u8 eid;
+	u8 iosapic_vector;
+	unsigned long reserved;
+	unsigned long global_vector;
+} acpi_entry_platform_src_t;
+
+extern int acpi_parse(acpi_rsdp_t *);
+extern const char *acpi_get_sysname (void);
+
+extern void (*acpi_idle) (void);	/* power-management idle function, if any */
+
+#endif /* _ASM_IA64_ACPI_EXT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/atomic.h linux/include/asm-ia64/atomic.h
--- v2.3.42/linux/include/asm-ia64/atomic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/atomic.h	Thu Feb 10 12:37:22 2000
@@ -0,0 +1,100 @@
+#ifndef _ASM_IA64_ATOMIC_H
+#define _ASM_IA64_ATOMIC_H
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ *
+ * NOTE: don't mess with the types below!  The "unsigned long" and
+ * "int" types were carefully placed so as to ensure proper operation
+ * of the macros.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <linux/types.h>
+
+#include <asm/system.h>
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
+
+/*
+ * On IA-64, counter must always be volatile to ensure that that the
+ * memory accesses are ordered.
+ */
+typedef struct { volatile __s32 counter; } atomic_t;
+
+#define ATOMIC_INIT(i)		((atomic_t) { (i) })
+
+#define atomic_read(v)		((v)->counter)
+#define atomic_set(v,i)		(((v)->counter) = (i))
+
+static __inline__ int
+ia64_atomic_add (int i, atomic_t *v)
+{
+	__s32 old, new;
+	CMPXCHG_BUGCHECK_DECL
+
+	do {
+		CMPXCHG_BUGCHECK(v);
+		old = atomic_read(v);
+		new = old + i;
+	} while (ia64_cmpxchg(v, old, old + i, sizeof(atomic_t)) != old);
+	return new;
+}
+
+static __inline__ int
+ia64_atomic_sub (int i, atomic_t *v)
+{
+	__s32 old, new;
+	CMPXCHG_BUGCHECK_DECL
+
+	do {
+		CMPXCHG_BUGCHECK(v);
+		old = atomic_read(v);
+		new = old - i;
+	} while (ia64_cmpxchg(v, old, new, sizeof(atomic_t)) != old);
+	return new;
+}
+
+/*
+ * Atomically add I to V and return TRUE if the resulting value is
+ * negative.
+ */
+static __inline__ int
+atomic_add_negative (int i, atomic_t *v)
+{
+	return ia64_atomic_add(i, v) < 0;
+}
+
+#define atomic_add_return(i,v)						\
+	((__builtin_constant_p(i) &&					\
+	  (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)		\
+	   || (i == -1) || (i == -4) || (i == -8) || (i == -16)))	\
+	 ? ia64_fetch_and_add(i, &(v)->counter)				\
+	 : ia64_atomic_add(i, v))
+
+#define atomic_sub_return(i,v)						\
+	((__builtin_constant_p(i) &&					\
+	  (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)		\
+	   || (i == -1) || (i == -4) || (i == -8) || (i == -16)))	\
+	 ? ia64_fetch_and_add(-(i), &(v)->counter)			\
+	 : ia64_atomic_sub(i, v))
+
+#define atomic_dec_return(v)		atomic_sub_return(1, (v))
+#define atomic_inc_return(v)		atomic_add_return(1, (v))
+
+#define atomic_sub_and_test(i,v)	(atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
+
+#define atomic_add(i,v)			atomic_add_return((i), (v))
+#define atomic_sub(i,v)			atomic_sub_return((i), (v))
+#define atomic_inc(v)			atomic_add(1, (v))
+#define atomic_dec(v)			atomic_sub(1, (v))
+
+#endif /* _ASM_IA64_ATOMIC_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/bitops.h linux/include/asm-ia64/bitops.h
--- v2.3.42/linux/include/asm-ia64/bitops.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/bitops.h	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,241 @@
+#ifndef _ASM_IA64_BITOPS_H
+#define _ASM_IA64_BITOPS_H
+
+/*
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 02/04/00 D. Mosberger  Require 64-bit alignment for bitops, per suggestion from davem
+ */
+
+#include <asm/system.h>
+
+/*
+ * These operations need to be atomic.  The address must be (at least)
+ * 32-bit aligned.  Note that there are driver (e.g., eepro100) which
+ * use these operations to operate on hw-defined data-structures, so
+ * we can't easily change these operations to force a bigger
+ * alignment.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+extern __inline__ void
+set_bit (int nr, volatile void *addr)
+{
+	__u32 bit, old, new;
+	volatile __u32 *m;
+	CMPXCHG_BUGCHECK_DECL
+
+	m = (volatile __u32 *) addr + (nr >> 5);
+	bit = 1 << (nr & 31);
+	do {
+		CMPXCHG_BUGCHECK(m);
+		old = *m;
+		new = old | bit;
+	} while (cmpxchg(m, old, new) != old);
+}
+
+extern __inline__ void
+clear_bit (int nr, volatile void *addr)
+{
+	__u32 mask, old, new;
+	volatile __u32 *m;
+	CMPXCHG_BUGCHECK_DECL
+
+	m = (volatile __u32 *) addr + (nr >> 5);
+	mask = ~(1 << (nr & 31));
+	do {
+		CMPXCHG_BUGCHECK(m);
+		old = *m;
+		new = old & mask;
+	} while (cmpxchg(m, old, new) != old);
+}
+
+extern __inline__ void
+change_bit (int nr, volatile void *addr)
+{
+	__u32 bit, old, new;
+	volatile __u32 *m;
+	CMPXCHG_BUGCHECK_DECL
+
+	m = (volatile __u32 *) addr + (nr >> 5);
+	bit = (1 << (nr & 31));
+	do {
+		CMPXCHG_BUGCHECK(m);
+		old = *m;
+		new = old ^ bit;
+	} while (cmpxchg(m, old, new) != old);
+}
+
+extern __inline__ int
+test_and_set_bit (int nr, volatile void *addr)
+{
+	__u32 bit, old, new;
+	volatile __u32 *m;
+	CMPXCHG_BUGCHECK_DECL
+
+	m = (volatile __u32 *) addr + (nr >> 5);
+	bit = 1 << (nr & 31);
+	do {
+		CMPXCHG_BUGCHECK(m);
+		old = *m;
+		new = old | bit;
+	} while (cmpxchg(m, old, new) != old);
+	return (old & bit) != 0;
+}
+
+extern __inline__ int
+test_and_clear_bit (int nr, volatile void *addr)
+{
+	__u32 mask, old, new;
+	volatile __u32 *m;
+	CMPXCHG_BUGCHECK_DECL
+
+	m = (volatile __u32 *) addr + (nr >> 5);
+	mask = ~(1 << (nr & 31));
+	do {
+		CMPXCHG_BUGCHECK(m);
+		old = *m;
+		new = old & mask;
+	} while (cmpxchg(m, old, new) != old);
+	return (old & ~mask) != 0;
+}
+
+extern __inline__ int
+test_and_change_bit (int nr, volatile void *addr)
+{
+	__u32 bit, old, new;
+	volatile __u32 *m;
+	CMPXCHG_BUGCHECK_DECL
+
+	m = (volatile __u32 *) addr + (nr >> 5);
+	bit = (1 << (nr & 31));
+	do {
+		CMPXCHG_BUGCHECK(m);
+		old = *m;
+		new = old ^ bit;
+	} while (cmpxchg(m, old, new) != old);
+	return (old & bit) != 0;
+}
+
+extern __inline__ int
+test_bit (int nr, volatile void *addr)
+{
+	return 1 & (((const volatile __u32 *) addr)[nr >> 5] >> (nr & 31));
+}
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+extern inline unsigned long
+ffz (unsigned long x)
+{
+	unsigned long result;
+
+	__asm__ ("popcnt %0=%1" : "=r" (result) : "r" (x & (~x - 1)));
+	return result;
+}
+
+#ifdef __KERNEL__
+
+/*
+ * Find the most significant bit that is set (undefined if no bit is
+ * set).
+ */
+static inline unsigned long
+ia64_fls (unsigned long x)
+{
+	double d = x;
+	long exp;
+
+	__asm__ ("getf.exp %0=%1" : "=r"(exp) : "f"(d));
+	return exp - 0xffff;
+}
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+#define ffs(x)	__builtin_ffs(x)
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+extern __inline__ unsigned long
+hweight64 (unsigned long x)
+{
+	unsigned long result;
+	__asm__ ("popcnt %0=%1" : "=r" (result) : "r" (x));
+	return result;
+}
+
+#define hweight32(x) hweight64 ((x) & 0xfffffffful)
+#define hweight16(x) hweight64 ((x) & 0xfffful)
+#define hweight8(x)  hweight64 ((x) & 0xfful)
+
+#endif /* __KERNEL__ */
+
+/*
+ * Find next zero bit in a bitmap reasonably efficiently..
+ */
+extern inline int
+find_next_zero_bit (void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
+	unsigned long result = offset & ~63UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 63UL;
+	if (offset) {
+		tmp = *(p++);
+		tmp |= ~0UL >> (64-offset);
+		if (size < 64)
+			goto found_first;
+		if (~tmp)
+			goto found_middle;
+		size -= 64;
+		result += 64;
+	}
+	while (size & ~63UL) {
+		if (~(tmp = *(p++)))
+			goto found_middle;
+		result += 64;
+		size -= 64;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	return result + ffz(tmp);
+}
+
+/*
+ * The optimizer actually does good code for this case..
+ */
+#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
+
+#ifdef __KERNEL__
+
+#define ext2_set_bit                 test_and_set_bit
+#define ext2_clear_bit               test_and_clear_bit
+#define ext2_test_bit                test_bit
+#define ext2_find_first_zero_bit     find_first_zero_bit
+#define ext2_find_next_zero_bit      find_next_zero_bit
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_set_bit(nr,addr)			test_and_set_bit(nr,addr)
+#define minix_clear_bit(nr,addr)		test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr)			test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size)	find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IA64_BITOPS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/break.h linux/include/asm-ia64/break.h
--- v2.3.42/linux/include/asm-ia64/break.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/break.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,21 @@
+#ifndef _ASM_IA64_BREAK_H
+#define _ASM_IA64_BREAK_H
+
+/*
+ * IA-64 Linux break numbers.
+ *
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/*
+ * OS-specific debug break numbers:
+ */
+#define __IA64_BREAK_KDB		0x80100
+
+/*
+ * OS-specific break numbers:
+ */
+#define __IA64_BREAK_SYSCALL		0x100000
+
+#endif /* _ASM_IA64_BREAK_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/bugs.h linux/include/asm-ia64/bugs.h
--- v2.3.42/linux/include/asm-ia64/bugs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/bugs.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,19 @@
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *	void check_bugs(void);
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/processor.h>
+
+/*
+ * I don't know of any ia-64 bugs yet..
+ */
+static void
+check_bugs (void)
+{
+}
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/byteorder.h linux/include/asm-ia64/byteorder.h
--- v2.3.42/linux/include/asm-ia64/byteorder.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/byteorder.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,40 @@
+#ifndef _ASM_IA64_BYTEORDER_H
+#define _ASM_IA64_BYTEORDER_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/types.h>
+
+static __inline__ __const__ __u64
+__ia64_swab64 (__u64 x)
+{
+	__u64 result;
+
+	__asm__ ("mux1 %0=%1,@rev" : "=r" (result) : "r" (x));
+	return result;
+}
+
+static __inline__ __const__ __u32
+__ia64_swab32 (__u32 x)
+{
+	return __ia64_swab64 (x) >> 32;
+}
+
+static __inline__ __const__ __u16
+__ia64_swab16(__u16 x)
+{
+	return __ia64_swab64 (x) >> 48;
+}
+
+#define __arch__swab64(x) __ia64_swab64 (x)
+#define __arch__swab32(x) __ia64_swab32 (x)
+#define __arch__swab16(x) __ia64_swab16 (x)
+
+#define __BYTEORDER_HAS_U64__
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_IA64_BYTEORDER_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/cache.h linux/include/asm-ia64/cache.h
--- v2.3.42/linux/include/asm-ia64/cache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/cache.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,12 @@
+#ifndef _ASM_IA64_CACHE_H
+#define _ASM_IA64_CACHE_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/* Bytes per L1 (data) cache line.  */
+#define L1_CACHE_BYTES		64
+
+#endif /* _ASM_IA64_CACHE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/checksum.h linux/include/asm-ia64/checksum.h
--- v2.3.42/linux/include/asm-ia64/checksum.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/checksum.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,99 @@
+#ifndef _ASM_IA64_CHECKSUM_H
+#define _ASM_IA64_CHECKSUM_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+extern unsigned short ip_fast_csum (unsigned char * iph, unsigned int ihl);
+
+/*
+ * Computes the checksum of the TCP/UDP pseudo-header returns a 16-bit
+ * checksum, already complemented
+ */
+extern unsigned short int csum_tcpudp_magic (unsigned long saddr,
+					     unsigned long daddr,
+					     unsigned short len,
+					     unsigned short proto,
+					     unsigned int sum);
+
+extern unsigned int csum_tcpudp_nofold (unsigned long saddr,
+					unsigned long daddr,
+					unsigned short len,
+					unsigned short proto,
+					unsigned int sum);
+
+/*
+ * Computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern unsigned int csum_partial (const unsigned char * buff, int len,
+				  unsigned int sum);
+
+/*
+ * Same as csum_partial, but copies from src while it checksums.
+ *
+ * Here it is even more important to align src and dst on a 32-bit (or
+ * even better 64-bit) boundary.
+ */
+extern unsigned int csum_partial_copy (const char *src, char *dst, int len,
+				       unsigned int sum);
+
+/*
+ * The same as csum_partial, but copies from user space (but on the
+ * ia-64 we have just one address space, so this is identical to the
+ * above).
+ *
+ * This is obsolete and will go away.
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+
+/*
+ * This is a new version of the above that records errors it finds in
+ * *errp, but continues and zeros the rest of the buffer.
+ */
+extern unsigned int csum_partial_copy_from_user (const char *src, char *dst,
+						 int len, unsigned int sum,
+						 int *errp);
+
+extern unsigned int csum_partial_copy_nocheck (const char *src, char *dst,
+					       int len, unsigned int sum);
+
+/*
+ * This routine is used for miscellaneous IP-like checksums, mainly in
+ * icmp.c
+ */
+extern unsigned short ip_compute_csum (unsigned char *buff, int len);
+
+/*
+ * Fold a partial checksum without adding pseudo headers.
+ */
+static inline unsigned short
+csum_fold (unsigned int sum)
+{
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return ~sum;
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+extern unsigned short int csum_ipv6_magic (struct in6_addr *saddr,
+					   struct in6_addr *daddr,
+					   __u16 len,
+					   unsigned short proto,
+					   unsigned int sum);
+
+#endif /* _ASM_IA64_CHECKSUM_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/current.h linux/include/asm-ia64/current.h
--- v2.3.42/linux/include/asm-ia64/current.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/current.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,13 @@
+#ifndef _ASM_IA64_CURRENT_H
+#define _ASM_IA64_CURRENT_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/* In kernel mode, thread pointer (r13) is used to point to the
+   current task structure.  */
+register struct task_struct *current asm ("r13");
+
+#endif /* _ASM_IA64_CURRENT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/delay.h linux/include/asm-ia64/delay.h
--- v2.3.42/linux/include/asm-ia64/delay.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/delay.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,90 @@
+#ifndef _ASM_IA64_DELAY_H
+#define _ASM_IA64_DELAY_H
+
+/*
+ * Delay routines using a pre-computed "cycles/usec" value.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/processor.h>
+
+extern __inline__ void
+ia64_set_itm (unsigned long val)
+{
+	__asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory");
+}
+
+extern __inline__ unsigned long
+ia64_get_itm (void)
+{
+	unsigned long result;
+
+	__asm__ __volatile__("mov %0=cr.itm;; srlz.d;;" : "=r"(result) :: "memory");
+	return result;
+}
+
+extern __inline__ void
+ia64_set_itv (unsigned char vector, unsigned char masked)
+{
+	if (masked > 1)
+		masked = 1;
+
+	__asm__ __volatile__("mov cr.itv=%0;; srlz.d;;"
+			     :: "r"((masked << 16) | vector) : "memory");
+}
+
+extern __inline__ void
+ia64_set_itc (unsigned long val)
+{
+	__asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory");
+}
+
+extern __inline__ unsigned long
+ia64_get_itc (void)
+{
+	unsigned long result;
+
+	__asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
+	return result;
+}
+
+extern __inline__ void
+__delay (unsigned long loops)
+{
+        unsigned long saved_ar_lc;
+
+	if (loops < 1)
+		return;
+
+	__asm__ __volatile__("mov %0=ar.lc;;" : "=r"(saved_ar_lc));
+	__asm__ __volatile__("mov ar.lc=%0;;" :: "r"(loops - 1));
+        __asm__ __volatile__("1:\tbr.cloop.sptk.few 1b;;");
+	__asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc));
+}
+
+extern __inline__ void
+udelay (unsigned long usecs)
+{
+#ifdef CONFIG_IA64_SOFTSDV_HACKS
+	while (usecs--)
+		;
+#else
+	unsigned long start = ia64_get_itc();
+	unsigned long cycles = usecs*my_cpu_data.cyc_per_usec;
+
+	while (ia64_get_itc() - start < cycles)
+		/* skip */;
+#endif	/* CONFIG_IA64_SOFTSDV_HACKS */
+}
+
+#endif /* _ASM_IA64_DELAY_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/div64.h linux/include/asm-ia64/div64.h
--- v2.3.42/linux/include/asm-ia64/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/div64.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,20 @@
+#ifndef _ASM_IA64_DIV64_H
+#define _ASM_IA64_DIV64_H
+
+/*
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
+ * This is incredibly hard on IA-64...
+ */
+
+#define do_div(n,base)						\
+({								\
+	int _res;						\
+	_res = ((unsigned long) (n)) % (unsigned) (base);	\
+	(n) = ((unsigned long) (n)) / (unsigned) (base);	\
+	_res;							\
+})
+
+#endif /* _ASM_IA64_DIV64_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/dma.h linux/include/asm-ia64/dma.h
--- v2.3.42/linux/include/asm-ia64/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/dma.h	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,36 @@
+#ifndef _ASM_IA64_DMA_H
+#define _ASM_IA64_DMA_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/io.h>		/* need byte IO */
+#include <linux/config.h>
+#include <linux/spinlock.h>	/* And spinlocks */
+#include <linux/delay.h>
+
+
+#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
+#define dma_outb	outb_p
+#else
+#define dma_outb	outb
+#endif
+
+#define dma_inb		inb
+
+#define MAX_DMA_CHANNELS	8
+#define MAX_DMA_ADDRESS		(~0UL)		/* no limits on DMAing, for now */
+
+extern spinlock_t  dma_spin_lock;
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
+
+#endif /* _ASM_IA64_DMA_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/efi.h linux/include/asm-ia64/efi.h
--- v2.3.42/linux/include/asm-ia64/efi.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/efi.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,233 @@
+#ifndef _ASM_IA64_EFI_H
+#define _ASM_IA64_EFI_H
+
+/*
+ * Extensible Firmware Interface
+ * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999
+ * 
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+#include <asm/page.h>
+#include <asm/system.h>
+
+#define EFI_SUCCESS		0
+#define EFI_INVALID_PARAMETER	2
+#define EFI_UNSUPPORTED		3
+#define EFI_BUFFER_TOO_SMALL	4
+
+typedef unsigned long efi_status_t;
+typedef u8 efi_bool_t;
+typedef u16 efi_char16_t;		/* UNICODE character */
+
+typedef struct {
+	u32 data1;
+	u16 data2;
+	u16 data3;
+	u8 data4[8];
+} efi_guid_t;
+
+/*
+ * Generic EFI table header
+ */
+typedef	struct {
+	u64 signature;
+	u32 revision;
+	u32 headersize;
+	u32 crc32;
+	u32 reserved;
+} efi_table_hdr_t;
+
+/*
+ * Memory map descriptor:
+ */
+
+/* Memory types: */
+#define EFI_RESERVED_TYPE		 0
+#define EFI_LOADER_CODE			 1
+#define EFI_LOADER_DATA			 2
+#define EFI_BOOT_SERVICES_CODE		 3
+#define EFI_BOOT_SERVICES_DATA		 4
+#define EFI_RUNTIME_SERVICES_CODE	 5
+#define EFI_RUNTIME_SERVICES_DATA	 6
+#define EFI_CONVENTIONAL_MEMORY		 7
+#define EFI_UNUSABLE_MEMORY		 8
+#define EFI_ACPI_RECLAIM_MEMORY		 9
+#define EFI_ACPI_MEMORY_NVS		10
+#define EFI_MEMORY_MAPPED_IO		11
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE	12
+#define EFI_PAL_CODE			13
+#define EFI_MAX_MEMORY_TYPE		14
+
+/* Attribute values: */
+#define EFI_MEMORY_UC		0x0000000000000001	/* uncached */
+#define EFI_MEMORY_WC		0x0000000000000002	/* write-coalescing */
+#define EFI_MEMORY_WT		0x0000000000000004	/* write-through */
+#define EFI_MEMORY_WB		0x0000000000000008	/* write-back */
+#define EFI_MEMORY_WP		0x0000000000001000	/* write-protect */
+#define EFI_MEMORY_RP		0x0000000000002000	/* read-protect */
+#define EFI_MEMORY_XP		0x0000000000004000	/* execute-protect */
+#define EFI_MEMORY_RUNTIME	0x8000000000000000	/* range requires runtime mapping */
+#define EFI_MEMORY_DESCRIPTOR_VERSION	1
+
+typedef struct {
+	u32 type;
+	u32 pad;
+	u64 phys_addr;
+	u64 virt_addr;
+	u64 num_pages;
+	u64 attribute;
+} efi_memory_desc_t;
+
+typedef int efi_freemem_callback_t (u64 start, u64 end, void *arg);
+
+/*
+ * Types and defines for Time Services
+ */
+#define EFI_TIME_ADJUST_DAYLIGHT 0x1
+#define EFI_TIME_IN_DAYLIGHT     0x2
+#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
+
+typedef struct {
+	u16 year;
+	u8 month;
+	u8 day;
+	u8 hour;
+	u8 minute;
+	u8 second;
+	u8 pad1;
+	u32 nanosecond;
+	s16 timezone;
+	u8 daylight;
+	u8 pad2;
+} efi_time_t;
+
+typedef struct {
+	u32 resolution;
+	u32 accuracy;
+	u8 sets_to_zero;
+} efi_time_cap_t;
+
+/*
+ * Types and defines for EFI ResetSystem
+ */
+#define EFI_RESET_COLD 0
+#define EFI_RESET_WARM 1
+
+/*
+ * EFI Runtime Services table
+ */
+#define EFI_RUNTIME_SERVICES_SIGNATURE 0x5652453544e5552
+#define EFI_RUNTIME_SERVICES_REVISION  0x00010000
+
+typedef struct {
+	efi_table_hdr_t hdr;
+	u64 get_time;
+	u64 set_time;
+	u64 get_wakeup_time;
+	u64 set_wakeup_time;
+	u64 set_virtual_address_map;
+	u64 convert_pointer;
+	u64 get_variable;
+	u64 get_next_variable;
+	u64 set_variable;
+	u64 get_next_high_mono_count;
+	u64 reset_system;
+} efi_runtime_services_t;
+
+typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
+typedef efi_status_t efi_set_time_t (efi_time_t *tm);
+typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
+					    efi_time_t *tm);
+typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
+typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
+					 unsigned long *data_size, void *data);
+typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
+					      efi_guid_t *vendor);
+typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 attr,
+					 unsigned long data_size, void *data);
+typedef efi_status_t efi_get_next_high_mono_count_t (u64 *count);
+typedef void efi_reset_system_t (int reset_type, efi_status_t status,
+				 unsigned long data_size, efi_char16_t *data);
+
+/*
+ *  EFI Configuration Table and GUID definitions
+ */
+
+#define MPS_TABLE_GUID    \
+    ((efi_guid_t) { 0xeb9d2d2f, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+
+#define ACPI_TABLE_GUID    \
+    ((efi_guid_t) { 0xeb9d2d30, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+
+#define SMBIOS_TABLE_GUID    \
+    ((efi_guid_t) { 0xeb9d2d31, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+	
+#define SAL_SYSTEM_TABLE_GUID    \
+    ((efi_guid_t) { 0xeb9d2d32, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+
+typedef struct {
+	efi_guid_t guid;
+	u64 table;
+} efi_config_table_t;
+
+#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
+#define EFI_SYSTEM_TABLE_REVISION  ((0 << 16) | (91))
+
+typedef struct {
+	efi_table_hdr_t hdr;
+	u64 fw_vendor;		/* physical addr of CHAR16 vendor string */
+	u32 fw_revision;
+	u64 con_in_handle;
+	u64 con_in;
+	u64 con_out_handle;
+	u64 con_out;
+	u64 stderr_handle;
+	u64 stderr;
+	u64 runtime;
+	u64 boottime;
+	u64 nr_tables;
+	u64 tables;
+} efi_system_table_t;
+
+/*
+ * All runtime access to EFI goes through this structure:
+ */
+extern struct efi {
+	efi_system_table_t *systab;	/* EFI system table */
+	void *mps;			/* MPS table */
+	void *acpi;			/* ACPI table */
+	void *smbios;			/* SM BIOS table */
+	void *sal_systab;		/* SAL system table */
+	void *boot_info;		/* boot info table */
+	efi_get_time_t *get_time;
+	efi_set_time_t *set_time;
+	efi_get_wakeup_time_t *get_wakeup_time;
+	efi_set_wakeup_time_t *set_wakeup_time;
+	efi_get_variable_t *get_variable;
+	efi_get_next_variable_t *get_next_variable;
+	efi_set_variable_t *set_variable;
+	efi_get_next_high_mono_count_t *get_next_high_mono_count;
+	efi_reset_system_t *reset_system;
+} efi;
+
+extern inline int
+efi_guidcmp (efi_guid_t left, efi_guid_t right)
+{
+	return memcmp(&left, &right, sizeof (efi_guid_t));
+}
+
+extern void efi_init (void);
+extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
+extern void efi_gettimeofday (struct timeval *tv);
+extern void efi_enter_virtual_mode (void);	/* switch EFI to virtual mode, if possible */
+
+#endif /* _ASM_IA64_EFI_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/elf.h linux/include/asm-ia64/elf.h
--- v2.3.42/linux/include/asm-ia64/elf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/elf.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,89 @@
+#ifndef _ASM_IA64_ELF_H
+#define _ASM_IA64_ELF_H
+
+/*
+ * ELF archtecture specific definitions.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/fpu.h>
+#include <asm/page.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x) == EM_IA_64)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_IA_64
+
+#define USE_ELF_CORE_DUMP
+
+/* always align to 64KB to allow for future page sizes of up to 64KB: */
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.
+ * Typical use of this is to invoke "./ld.so someprog" to test out a
+ * new version of the loader.  We need to make sure that it is out of
+ * the way of the program that it will "exec", and that there is
+ * sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x1000000)
+
+
+/*
+ * We use (abuse?) this macro to insert the (empty) vm_area that is
+ * used to map the register backing store.  I don't see any better
+ * place to do this, but we should discuss this with Linus once we can
+ * talk to him...
+ */
+extern void ia64_init_addr_space (void);
+#define ELF_PLAT_INIT(_r)	ia64_init_addr_space()
+
+/* ELF register definitions.  This is needed for core dump support.  */
+
+/*
+ * elf_gregset_t contains the application-level state in the following order:
+ *	r0-r31
+ *	NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
+ *	predicate registers (p0-p63)
+ *	b0-b7
+ *	ip cfm psr
+ *	ar.rsc ar.bsp ar.bspstore ar.rnat
+ *	ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
+ */
+#define ELF_NGREG	128	/* we really need just 72 but let's leave some headroom... */
+#define ELF_NFPREG	128	/* f0 and f1 could be omitted, but so what... */
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct ia64_fpreg elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+struct pt_regs;	/* forward declaration... */
+extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
+#define ELF_CORE_COPY_REGS(_dest,_regs)	ia64_elf_core_copy_regs(_regs, _dest);
+
+/* This macro yields a bitmask that programs can use to figure out
+   what instruction set this CPU supports.  */
+#define ELF_HWCAP 	0
+
+/* This macro yields a string that ld.so will use to load
+   implementation specific libraries for optimization.  Not terribly
+   relevant until we have real hardware to play with... */
+#define ELF_PLATFORM	0
+
+#ifdef __KERNEL__
+# define SET_PERSONALITY(EX,IBCS2)				\
+	(current->personality = (IBCS2) ? PER_SVR4 : PER_LINUX)
+#endif
+
+#endif /* _ASM_IA64_ELF_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/errno.h linux/include/asm-ia64/errno.h
--- v2.3.42/linux/include/asm-ia64/errno.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/errno.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,139 @@
+#ifndef _ASM_IA64_ERRNO_H
+#define _ASM_IA64_ERRNO_H
+
+/*
+ * This is derived from the Linux/x86 version.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	EDEADLK		35	/* Resource deadlock would occur */
+#define	ENAMETOOLONG	36	/* File name too long */
+#define	ENOLCK		37	/* No record locks available */
+#define	ENOSYS		38	/* Function not implemented */
+#define	ENOTEMPTY	39	/* Directory not empty */
+#define	ELOOP		40	/* Too many symbolic links encountered */
+#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
+#define	ENOMSG		42	/* No message of desired type */
+#define	EIDRM		43	/* Identifier removed */
+#define	ECHRNG		44	/* Channel number out of range */
+#define	EL2NSYNC	45	/* Level 2 not synchronized */
+#define	EL3HLT		46	/* Level 3 halted */
+#define	EL3RST		47	/* Level 3 reset */
+#define	ELNRNG		48	/* Link number out of range */
+#define	EUNATCH		49	/* Protocol driver not attached */
+#define	ENOCSI		50	/* No CSI structure available */
+#define	EL2HLT		51	/* Level 2 halted */
+#define	EBADE		52	/* Invalid exchange */
+#define	EBADR		53	/* Invalid request descriptor */
+#define	EXFULL		54	/* Exchange full */
+#define	ENOANO		55	/* No anode */
+#define	EBADRQC		56	/* Invalid request code */
+#define	EBADSLT		57	/* Invalid slot */
+
+#define	EDEADLOCK	EDEADLK
+
+#define	EBFONT		59	/* Bad font file format */
+#define	ENOSTR		60	/* Device not a stream */
+#define	ENODATA		61	/* No data available */
+#define	ETIME		62	/* Timer expired */
+#define	ENOSR		63	/* Out of streams resources */
+#define	ENONET		64	/* Machine is not on the network */
+#define	ENOPKG		65	/* Package not installed */
+#define	EREMOTE		66	/* Object is remote */
+#define	ENOLINK		67	/* Link has been severed */
+#define	EADV		68	/* Advertise error */
+#define	ESRMNT		69	/* Srmount error */
+#define	ECOMM		70	/* Communication error on send */
+#define	EPROTO		71	/* Protocol error */
+#define	EMULTIHOP	72	/* Multihop attempted */
+#define	EDOTDOT		73	/* RFS specific error */
+#define	EBADMSG		74	/* Not a data message */
+#define	EOVERFLOW	75	/* Value too large for defined data type */
+#define	ENOTUNIQ	76	/* Name not unique on network */
+#define	EBADFD		77	/* File descriptor in bad state */
+#define	EREMCHG		78	/* Remote address changed */
+#define	ELIBACC		79	/* Can not access a needed shared library */
+#define	ELIBBAD		80	/* Accessing a corrupted shared library */
+#define	ELIBSCN		81	/* .lib section in a.out corrupted */
+#define	ELIBMAX		82	/* Attempting to link in too many shared libraries */
+#define	ELIBEXEC	83	/* Cannot exec a shared library directly */
+#define	EILSEQ		84	/* Illegal byte sequence */
+#define	ERESTART	85	/* Interrupted system call should be restarted */
+#define	ESTRPIPE	86	/* Streams pipe error */
+#define	EUSERS		87	/* Too many users */
+#define	ENOTSOCK	88	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	89	/* Destination address required */
+#define	EMSGSIZE	90	/* Message too long */
+#define	EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	92	/* Protocol not available */
+#define	EPROTONOSUPPORT	93	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define	EOPNOTSUPP	95	/* Operation not supported on transport endpoint */
+#define	EPFNOSUPPORT	96	/* Protocol family not supported */
+#define	EAFNOSUPPORT	97	/* Address family not supported by protocol */
+#define	EADDRINUSE	98	/* Address already in use */
+#define	EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define	ENETDOWN	100	/* Network is down */
+#define	ENETUNREACH	101	/* Network is unreachable */
+#define	ENETRESET	102	/* Network dropped connection because of reset */
+#define	ECONNABORTED	103	/* Software caused connection abort */
+#define	ECONNRESET	104	/* Connection reset by peer */
+#define	ENOBUFS		105	/* No buffer space available */
+#define	EISCONN		106	/* Transport endpoint is already connected */
+#define	ENOTCONN	107	/* Transport endpoint is not connected */
+#define	ESHUTDOWN	108	/* Cannot send after transport endpoint shutdown */
+#define	ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define	ETIMEDOUT	110	/* Connection timed out */
+#define	ECONNREFUSED	111	/* Connection refused */
+#define	EHOSTDOWN	112	/* Host is down */
+#define	EHOSTUNREACH	113	/* No route to host */
+#define	EALREADY	114	/* Operation already in progress */
+#define	EINPROGRESS	115	/* Operation now in progress */
+#define	ESTALE		116	/* Stale NFS file handle */
+#define	EUCLEAN		117	/* Structure needs cleaning */
+#define	ENOTNAM		118	/* Not a XENIX named type file */
+#define	ENAVAIL		119	/* No XENIX semaphores available */
+#define	EISNAM		120	/* Is a named type file */
+#define	EREMOTEIO	121	/* Remote I/O error */
+#define	EDQUOT		122	/* Quota exceeded */
+
+#define	ENOMEDIUM	123	/* No medium found */
+#define	EMEDIUMTYPE	124	/* Wrong medium type */
+
+#endif /* _ASM_IA64_ERRNO_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/fcntl.h linux/include/asm-ia64/fcntl.h
--- v2.3.42/linux/include/asm-ia64/fcntl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/fcntl.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,73 @@
+#ifndef _ASM_IA64_FCNTL_H
+#define _ASM_IA64_FCNTL_H
+/*
+ * This is mostly compatible with Linux/x86.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/*
+ * open/fcntl - O_SYNC is only implemented on blocks devices and on
+ * files located on an ext2 file system
+ */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define FASYNC		 020000	/* fcntl, for BSD compatibility */
+#define O_DIRECT	 040000	/* direct disk access hint - currently ignored */
+#define O_LARGEFILE	0100000
+#define O_DIRECTORY	0200000	/* must be a directory */
+#define O_NOFOLLOW	0400000 /* don't follow links */
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get f_flags */
+#define F_SETFD		2	/* set f_flags */
+#define F_GETFL		3	/* more flags (cloexec) */
+#define F_SETFL		4
+#define F_GETLK		5
+#define F_SETLK		6
+#define F_SETLKW	7
+
+#define F_SETOWN	8	/*  for sockets. */
+#define F_GETOWN	9	/*  for sockets. */
+#define F_SETSIG	10	/*  for sockets. */
+#define F_GETSIG	11	/*  for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+struct flock {
+	short l_type;
+	short l_whence;
+	off_t l_start;
+	off_t l_len;
+	pid_t l_pid;
+};
+
+#endif /* _ASM_IA64_FCNTL_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/fpswa.h linux/include/asm-ia64/fpswa.h
--- v2.3.42/linux/include/asm-ia64/fpswa.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/fpswa.h	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,75 @@
+#ifndef _ASM_IA64_FPSWA_H
+#define _ASM_IA64_FPSWA_H
+
+/*
+ * Floating-point Software Assist
+ *
+ * Copyright (C) 1999 Intel Corporation.
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Goutham Rao <goutham.rao@intel.com>
+ */
+
+#if 0
+#define FPSWA_BUG
+#endif
+
+typedef struct {
+	/* 4 * 128 bits */
+	unsigned long fp_lp[4*2];
+} fp_state_low_preserved_t;
+
+typedef struct {
+	/* 10 * 128 bits */
+	unsigned long fp_lv[10 * 2];
+} fp_state_low_volatile_t;
+
+typedef	struct {
+	/* 16 * 128 bits */
+	unsigned long fp_hp[16 * 2];
+} fp_state_high_preserved_t;
+
+typedef struct {
+	/* 96 * 128 bits */
+	unsigned long fp_hv[96 * 2];
+} fp_state_high_volatile_t;
+
+/**
+ * floating point state to be passed to the FP emulation library by
+ * the trap/fault handler
+ */
+typedef struct {
+	unsigned long			bitmask_low64;
+	unsigned long			bitmask_high64;
+	fp_state_low_preserved_t	*fp_state_low_preserved;
+	fp_state_low_volatile_t		*fp_state_low_volatile;
+	fp_state_high_preserved_t	*fp_state_high_preserved;
+	fp_state_high_volatile_t	*fp_state_high_volatile;
+} fp_state_t;
+
+typedef struct {
+	unsigned long status;
+	unsigned long err0;
+	unsigned long err1;
+	unsigned long err2;
+} fpswa_ret_t;
+
+/**
+ * function header for the Floating Point software assist
+ * library. This function is invoked by the Floating point software
+ * assist trap/fault handler.
+ */
+typedef fpswa_ret_t (*efi_fpswa_t) (unsigned long trap_type, void *bundle, unsigned long *ipsr,
+				    unsigned long *fsr, unsigned long *isr, unsigned long *preds,
+				    unsigned long *ifs, fp_state_t *fp_state);
+
+/**
+ * This is the FPSWA library interface as defined by EFI.  We need to pass a 
+ * pointer to the interface itself on a call to the assist library
+ */
+typedef struct {
+	unsigned int	 revision;
+	unsigned int	 reserved;
+	efi_fpswa_t	 fpswa;
+} fpswa_interface_t;
+
+#endif /* _ASM_IA64_FPSWA_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/fpu.h linux/include/asm-ia64/fpu.h
--- v2.3.42/linux/include/asm-ia64/fpu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/fpu.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,65 @@
+#ifndef _ASM_IA64_FPU_H
+#define _ASM_IA64_FPU_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/types.h>
+
+/* floating point status register: */
+#define FPSR_TRAP_VD	(1 << 0)	/* invalid op trap disabled */
+#define FPSR_TRAP_DD	(1 << 1)	/* denormal trap disabled */
+#define FPSR_TRAP_ZD	(1 << 2)	/* zero-divide trap disabled */
+#define FPSR_TRAP_OD	(1 << 3)	/* overflow trap disabled */
+#define FPSR_TRAP_UD	(1 << 4)	/* underflow trap disabled */
+#define FPSR_TRAP_ID	(1 << 5)	/* inexact trap disabled */
+#define FPSR_S0(x)	((x) <<  6)
+#define FPSR_S1(x)	((x) << 19)
+#define FPSR_S2(x)	(__IA64_UL(x) << 32)
+#define FPSR_S3(x)	(__IA64_UL(x) << 45)
+
+/* floating-point status field controls: */
+#define FPSF_FTZ	(1 << 0)		/* flush-to-zero */
+#define FPSF_WRE	(1 << 1)		/* widest-range exponent */
+#define FPSF_PC(x)	(((x) & 0x3) << 2)	/* precision control */
+#define FPSF_RC(x)	(((x) & 0x3) << 4)	/* rounding control */
+#define FPSF_TD		(1 << 6)		/* trap disabled */
+
+/* floating-point status field flags: */
+#define FPSF_V		(1 <<  7)		/* invalid operation flag */
+#define FPSF_D		(1 <<  8)		/* denormal/unnormal operand flag */
+#define FPSF_Z		(1 <<  9)		/* zero divide (IEEE) flag */
+#define FPSF_O		(1 << 10)		/* overflow (IEEE) flag */
+#define FPSF_U		(1 << 11)		/* underflow (IEEE) flag */
+#define FPSF_I		(1 << 12)		/* inexact (IEEE) flag) */
+
+/* floating-point rounding control: */
+#define FPRC_NEAREST	0x0
+#define FPRC_NEGINF	0x1
+#define FPRC_POSINF	0x2
+#define FPRC_TRUNC	0x3
+
+#define FPSF_DEFAULT	(FPSF_PC (0x3) | FPSF_RC (FPRC_NEAREST))
+
+/* This default value is the same as HP-UX uses.  Don't change it
+   without a very good reason.  */
+#define FPSR_DEFAULT	(FPSR_TRAP_VD | FPSR_TRAP_DD | FPSR_TRAP_ZD	\
+			 | FPSR_TRAP_OD | FPSR_TRAP_UD | FPSR_TRAP_ID	\
+			 | FPSR_S0 (FPSF_DEFAULT)			\
+			 | FPSR_S1 (FPSF_DEFAULT | FPSF_TD | FPSF_WRE)	\
+			 | FPSR_S2 (FPSF_DEFAULT | FPSF_TD)		\
+			 | FPSR_S3 (FPSF_DEFAULT | FPSF_TD))
+
+# ifndef __ASSEMBLY__
+
+struct ia64_fpreg {
+	union {
+		unsigned long bits[2];
+	} u;
+} __attribute__ ((aligned (16)));
+
+# endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_IA64_FPU_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/hardirq.h linux/include/asm-ia64/hardirq.h
--- v2.3.42/linux/include/asm-ia64/hardirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/hardirq.h	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,76 @@
+#ifndef _ASM_IA64_HARDIRQ_H
+#define _ASM_IA64_HARDIRQ_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+
+extern unsigned int local_irq_count[NR_CPUS];
+extern unsigned long hardirq_no[NR_CPUS];
+
+/*
+ * Are we in an interrupt context? Either doing bottom half
+ * or hardware interrupt processing?
+ */
+
+#define in_interrupt()						\
+({								\
+	int __cpu = smp_processor_id();				\
+	(local_irq_count[__cpu] + local_bh_count[__cpu]) != 0;	\
+})
+
+#ifndef CONFIG_SMP
+# define hardirq_trylock(cpu)		(local_irq_count[cpu] == 0)
+# define hardirq_endlock(cpu)		((void) 0)
+
+# define hardirq_enter(cpu, irq)	(local_irq_count[cpu]++)
+# define hardirq_exit(cpu, irq)		(local_irq_count[cpu]--)
+
+# define synchronize_irq()		barrier()
+#else
+
+#include <linux/spinlock.h>
+
+#include <asm/atomic.h>
+#include <asm/smp.h>
+
+extern int global_irq_holder;
+extern spinlock_t global_irq_lock;
+extern atomic_t global_irq_count;
+
+static inline void release_irqlock(int cpu)
+{
+	/* if we didn't own the irq lock, just ignore.. */
+	if (global_irq_holder == cpu) {
+		global_irq_holder = NO_PROC_ID;
+		spin_unlock(&global_irq_lock);
+        }
+}
+
+static inline void hardirq_enter(int cpu, int irq)
+{
+	++local_irq_count[cpu];
+        atomic_inc(&global_irq_count);
+}
+
+static inline void hardirq_exit(int cpu, int irq)
+{
+	atomic_dec(&global_irq_count);
+        --local_irq_count[cpu];
+}
+
+static inline int hardirq_trylock(int cpu)
+{
+	return !local_irq_count[cpu] && !test_bit(0,&global_irq_lock);
+}
+
+#define hardirq_endlock(cpu)  ((void)0)
+
+extern void synchronize_irq(void);
+
+#endif /* CONFIG_SMP */
+#endif /* _ASM_IA64_HARDIRQ_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/hdreg.h linux/include/asm-ia64/hdreg.h
--- v2.3.42/linux/include/asm-ia64/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/hdreg.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,12 @@
+/*
+ *  linux/include/asm-ia64/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASM_IA64_HDREG_H
+#define __ASM_IA64_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASM_IA64_HDREG_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ia32.h linux/include/asm-ia64/ia32.h
--- v2.3.42/linux/include/asm-ia64/ia32.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ia32.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,313 @@
+#ifndef _ASM_IA64_IA32_H
+#define _ASM_IA64_IA32_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IA32_SUPPORT
+
+/*
+ * 32 bit structures for IA32 support.
+ */
+
+/* 32bit compatibility types */
+typedef unsigned int	       __kernel_size_t32;
+typedef int		       __kernel_ssize_t32;
+typedef int		       __kernel_ptrdiff_t32;
+typedef int		       __kernel_time_t32;
+typedef int		       __kernel_clock_t32;
+typedef int		       __kernel_pid_t32;
+typedef unsigned short	       __kernel_ipc_pid_t32;
+typedef unsigned short	       __kernel_uid_t32;
+typedef unsigned short	       __kernel_gid_t32;
+typedef unsigned short	       __kernel_dev_t32;
+typedef unsigned int	       __kernel_ino_t32;
+typedef unsigned short	       __kernel_mode_t32;
+typedef unsigned short	       __kernel_umode_t32;
+typedef short		       __kernel_nlink_t32;
+typedef int		       __kernel_daddr_t32;
+typedef int		       __kernel_off_t32;
+typedef unsigned int	       __kernel_caddr_t32;
+typedef long		       __kernel_loff_t32;
+typedef __kernel_fsid_t	       __kernel_fsid_t32;
+
+#define IA32_PAGE_SHIFT		12	/* 4KB pages */
+#define IA32_PAGE_SIZE		(1ULL << IA32_PAGE_SHIFT)
+
+/* fcntl.h */
+struct flock32 {
+       short l_type;
+       short l_whence;
+       __kernel_off_t32 l_start;
+       __kernel_off_t32 l_len;
+       __kernel_pid_t32 l_pid;
+       short __unused;
+};
+
+
+/* sigcontext.h */
+/*
+ * As documented in the iBCS2 standard..
+ *
+ * The first part of "struct _fpstate" is just the
+ * normal i387 hardware setup, the extra "status"
+ * word is used to save the coprocessor status word
+ * before entering the handler.
+ */
+struct _fpreg_ia32 {
+       unsigned short significand[4];
+       unsigned short exponent;
+};
+
+struct _fpstate_ia32 {
+       unsigned int    cw,
+		       sw,
+		       tag,
+		       ipoff,
+		       cssel,
+		       dataoff,
+		       datasel;
+       struct _fpreg_ia32      _st[8];
+       unsigned int    status;
+};
+
+struct sigcontext_ia32 {
+       unsigned short gs, __gsh;
+       unsigned short fs, __fsh;
+       unsigned short es, __esh;
+       unsigned short ds, __dsh;
+       unsigned int edi;
+       unsigned int esi;
+       unsigned int ebp;
+       unsigned int esp;
+       unsigned int ebx;
+       unsigned int edx;
+       unsigned int ecx;
+       unsigned int eax;
+       unsigned int trapno;
+       unsigned int err;
+       unsigned int eip;
+       unsigned short cs, __csh;
+       unsigned int eflags;
+       unsigned int esp_at_signal;
+       unsigned short ss, __ssh;
+       struct _fpstate_ia32 * fpstate;
+       unsigned int oldmask;
+       unsigned int cr2;
+};
+
+/* signal.h */
+#define _IA32_NSIG	       64
+#define _IA32_NSIG_BPW	       32
+#define _IA32_NSIG_WORDS	       (_IA32_NSIG / _IA32_NSIG_BPW)
+
+typedef struct {
+       unsigned int sig[_IA32_NSIG_WORDS];
+} sigset32_t;
+
+struct sigaction32 {
+       unsigned int  sa_handler;       /* Really a pointer, but need to deal 
+					  with 32 bits */
+       unsigned int sa_flags;
+       unsigned int sa_restorer;       /* Another 32 bit pointer */
+       sigset32_t sa_mask;     /* A 32 bit mask */
+};
+
+struct ucontext_ia32 {
+	unsigned long	  uc_flags;
+	struct ucontext_ia32  *uc_link;
+	stack_t		  uc_stack;
+	struct sigcontext_ia32 uc_mcontext;
+	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+};
+
+struct stat32 {
+       unsigned short st_dev;
+       unsigned short __pad1;
+       unsigned int st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned short __pad2;
+       unsigned int  st_size;
+       unsigned int  st_blksize;
+       unsigned int  st_blocks;
+       unsigned int  st_atime;
+       unsigned int  __unused1;
+       unsigned int  st_mtime;
+       unsigned int  __unused2;
+       unsigned int  st_ctime;
+       unsigned int  __unused3;
+       unsigned int  __unused4;
+       unsigned int  __unused5;
+};
+
+struct statfs32 {
+       int f_type;
+       int f_bsize;
+       int f_blocks;
+       int f_bfree;
+       int f_bavail;
+       int f_files;
+       int f_ffree;
+       __kernel_fsid_t32 f_fsid;
+       int f_namelen;  /* SunOS ignores this field. */
+       int f_spare[6];
+};
+
+/*
+ * IA-32 ELF specific definitions for IA-64.
+ */
+
+#define _ASM_IA64_ELF_H		/* Don't include elf.h */
+
+#include <linux/sched.h>
+#include <asm/processor.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x) == EM_386)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_386
+
+#define IA32_PAGE_OFFSET	0xc0000000
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.
+ * Typical use of this is to invoke "./ld.so someprog" to test out a
+ * new version of the loader.  We need to make sure that it is out of
+ * the way of the program that it will "exec", and that there is
+ * sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE		(IA32_PAGE_OFFSET/3 + 0x1000000)
+
+void ia64_elf32_init(struct pt_regs *regs);
+#define ELF_PLAT_INIT(_r)	ia64_elf32_init(_r)
+
+#define elf_addr_t	u32
+#define elf_caddr_t	u32
+
+/* ELF register definitions.  This is needed for core dump support.  */
+
+#define ELF_NGREG	128			/* XXX fix me */
+#define ELF_NFPREG	128			/* XXX fix me */
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+	unsigned long w0;
+	unsigned long w1;
+} elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+/* This macro yields a bitmask that programs can use to figure out
+   what instruction set this CPU supports.  */
+#define ELF_HWCAP 	0
+
+/* This macro yields a string that ld.so will use to load
+   implementation specific libraries for optimization.  Not terribly
+   relevant until we have real hardware to play with... */
+#define ELF_PLATFORM	0
+
+#ifdef __KERNEL__
+# define SET_PERSONALITY(EX,IBCS2)				\
+	(current->personality = (IBCS2) ? PER_SVR4 : PER_LINUX)
+#endif
+
+#define IA32_EFLAG	0x200
+
+/*
+ * IA-32 ELF specific definitions for IA-64.
+ */
+ 
+#define __USER_CS      0x23
+#define __USER_DS      0x2B
+
+#define SEG_LIM     32
+#define SEG_TYPE    52
+#define SEG_SYS     56
+#define SEG_DPL     57
+#define SEG_P       59
+#define SEG_DB      62
+#define SEG_G       63
+
+#define FIRST_TSS_ENTRY 6
+#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
+#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
+#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
+
+#define IA64_SEG_DESCRIPTOR(base, limit, segtype, nonsysseg, dpl, segpresent, segdb, granularity) \
+	       ((base)			       |       \
+		(limit << SEG_LIM)	       |       \
+		(segtype << SEG_TYPE)	       |       \
+		(nonsysseg << SEG_SYS)	       |       \
+		(dpl << SEG_DPL)	       |       \
+		(segpresent << SEG_P)	       |       \
+		(segdb << SEG_DB)	       |       \
+		(granularity << SEG_G))
+
+#define IA32_SEG_BASE 16
+#define IA32_SEG_TYPE 40
+#define IA32_SEG_SYS  44
+#define IA32_SEG_DPL  45
+#define IA32_SEG_P    47
+#define IA32_SEG_HIGH_LIMIT    48
+#define IA32_SEG_AVL   52
+#define IA32_SEG_DB    54
+#define IA32_SEG_G     55
+#define IA32_SEG_HIGH_BASE 56
+
+#define IA32_SEG_DESCRIPTOR(base, limit, segtype, nonsysseg, dpl, segpresent, avl, segdb, granularity) \
+	       ((limit & 0xFFFF)			       |       \
+		 (base & 0xFFFFFF << IA32_SEG_BASE)	       |       \
+		(segtype << IA32_SEG_TYPE)		       |       \
+		(nonsysseg << IA32_SEG_SYS)		       |       \
+		(dpl << IA32_SEG_DPL)			       |       \
+		(segpresent << IA32_SEG_P)		       |       \
+		(((limit >> 16) & 0xF) << IA32_SEG_HIGH_LIMIT) |       \
+		(avl << IA32_SEG_AVL)			       |       \
+		(segdb << IA32_SEG_DB)			       |       \
+		(granularity << IA32_SEG_G)		       |       \
+		(((base >> 24) & 0xFF) << IA32_SEG_HIGH_BASE)) 
+
+#define IA32_CR0       0x80000001      /* Enable PG and PE bits */
+#define IA32_CR4       0	       /* No architectural extensions */
+
+/*
+ *  IA32 floating point control registers starting values
+ */
+
+#define IA32_FSR_DEFAULT	0x555500000	/* set all tag bits */
+#define IA32_FCR_DEFAULT	0x33f		/* single precision, all masks */
+
+#define ia32_start_thread(regs,new_ip,new_sp) do {				\
+	set_fs(USER_DS);							\
+	ia64_psr(regs)->cpl = 3;	/* set user mode */			\
+	ia64_psr(regs)->ri = 0;		/* clear return slot number */		\
+	ia64_psr(regs)->is = 1;		/* IA-32 instruction set */		\
+	regs->cr_iip = new_ip;							\
+	regs->r12 = new_sp;							\
+	regs->ar_rnat = 0;							\
+	regs->loadrs = 0;							\
+} while (0)
+
+extern void ia32_gdt_init (void);
+extern long ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
+			       sigset_t *set, struct pt_regs *regs);
+extern void ia32_init_addr_space (struct pt_regs *regs);
+extern int ia32_setup_arg_pages (struct linux_binprm *bprm);
+
+#endif /* !CONFIG_IA32_SUPPORT */
+ 
+#endif /* _ASM_IA64_IA32_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ide.h linux/include/asm-ia64/ide.h
--- v2.3.42/linux/include/asm-ia64/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ide.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,115 @@
+/*
+ *  linux/include/asm-ia64/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the ia64 architecture specific IDE code.
+ */
+
+#ifndef __ASM_IA64_IDE_H
+#define __ASM_IA64_IDE_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+#define MAX_HWIFS	10
+#endif
+
+#define ide__sti()	__sti()
+
+static __inline__ int
+ide_default_irq (ide_ioreg_t base)
+{
+	switch (base) {
+		case 0x1f0: return 14;
+		case 0x170: return 15;
+		case 0x1e8: return 11;
+		case 0x168: return 10;
+		case 0x1e0: return 8;
+		case 0x160: return 12;
+		default:
+			return 0;
+	}
+}
+
+static __inline__ ide_ioreg_t
+ide_default_io_base (int index)
+{
+	switch (index) {
+		case 0:	return 0x1f0;
+		case 1:	return 0x170;
+		case 2: return 0x1e8;
+		case 3: return 0x168;
+		case 4: return 0x1e0;
+		case 5: return 0x160;
+		default:
+			return 0;
+	}
+}
+
+static __inline__ void
+ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+{
+	ide_ioreg_t reg = data_port;
+	int i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
+	if (irq != NULL)
+		*irq = 0;
+}
+
+static __inline__ void
+ide_init_default_hwifs (void)
+{
+#ifndef CONFIG_BLK_DEV_IDEPCI
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+}
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned head		: 4;	/* always zeros here */
+		unsigned unit		: 1;	/* drive select number, 0 or 1 */
+		unsigned bit5		: 1;	/* always 1 */
+		unsigned lba		: 1;	/* using LBA instead of CHS */
+		unsigned bit7		: 1;	/* always 1 */
+	} b;
+	} select_t;
+
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)		check_region((from), (extent))
+#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+#define ide_release_region(from,extent)		release_region((from), (extent))
+
+/*
+ * The following are not needed for the non-m68k ports
+ */
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_IA64_IDE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/io.h linux/include/asm-ia64/io.h
--- v2.3.42/linux/include/asm-ia64/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/io.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,446 @@
+#ifndef _ASM_IA64_IO_H
+#define _ASM_IA64_IO_H
+
+/*
+ * This file contains the definitions for the emulated IO instructions
+ * inb/inw/inl/outb/outw/outl and the "string versions" of the same
+ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
+ * versions of the single-IO instructions (inb_p/inw_p/..).
+ *
+ * This file is not meant to be obfuscating: it's just complicated to
+ * (a) handle it all in a way that makes gcc able to optimize it as
+ * well as possible and (b) trying to avoid writing the same thing
+ * over and over again with slight variations and possibly making a
+ * mistake somewhere.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+
+/* We don't use IO slowdowns on the ia64, but.. */
+#define __SLOW_DOWN_IO	do { } while (0)
+#define SLOW_DOWN_IO	do { } while (0)
+
+#define __IA64_UNCACHED_OFFSET	0xc000000000000000	/* region 6 */
+
+#define IO_SPACE_LIMIT 0xffff
+
+# ifdef __KERNEL__
+
+#include <asm/page.h>
+#include <asm/system.h>
+
+/*
+ * Change virtual addresses to physical addresses and vv.
+ */
+static inline unsigned long
+virt_to_phys (volatile void *address)
+{
+	return (unsigned long) address - PAGE_OFFSET;
+}
+
+static inline void*
+phys_to_virt(unsigned long address)
+{
+	return (void *) (address + PAGE_OFFSET);
+}
+
+#define bus_to_virt	phys_to_virt
+#define virt_to_bus	virt_to_phys
+
+# else /* !KERNEL */
+# endif /* !KERNEL */
+
+/*
+ * Memory fence w/accept.  This should never be used in code that is
+ * not IA-64 specific.
+ */
+#define __ia64_mf_a()	__asm__ __volatile__ ("mf.a" ::: "memory")
+
+extern inline const unsigned long
+__ia64_get_io_port_base (void)
+{
+	unsigned long addr;
+
+	__asm__ ("mov %0=ar.k0;;" : "=r"(addr));
+	return __IA64_UNCACHED_OFFSET | addr;
+}
+
+extern inline void*
+__ia64_mk_io_addr (unsigned long port)
+{
+	const unsigned long io_base = __ia64_get_io_port_base();
+	unsigned long addr;
+
+	addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
+	return (void *) addr;
+}
+
+/*
+ * For the in/out instructions, we need to do:
+ *
+ *	o "mf" _before_ doing the I/O access to ensure that all prior
+ *	  accesses to memory occur before the I/O access
+ *	o "mf.a" _after_ doing the I/O access to ensure that the access
+ *	  has completed before we're doing any other I/O accesses
+ *
+ * The former is necessary because we might be doing normal (cached) memory
+ * accesses, e.g., to set up a DMA descriptor table and then do an "outX()"
+ * to tell the DMA controller to start the DMA operation.  The "mf" ahead
+ * of the I/O operation ensures that the DMA table is correct when the I/O
+ * access occurs.
+ *
+ * The mf.a is necessary to ensure that all I/O access occur in program
+ * order. --davidm 99/12/07 
+ */
+
+extern inline unsigned int
+__inb (unsigned long port)
+{
+	volatile unsigned char *addr = __ia64_mk_io_addr(port);
+	unsigned char ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+extern inline unsigned int
+__inw (unsigned long port)
+{
+	volatile unsigned short *addr = __ia64_mk_io_addr(port);
+	unsigned short ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+extern inline unsigned int
+__inl (unsigned long port)
+{
+	volatile unsigned int *addr = __ia64_mk_io_addr(port);
+	unsigned int ret;
+
+	ret = *addr;
+	__ia64_mf_a();
+	return ret;
+}
+
+extern inline void
+__insb (unsigned long port, void *dst, unsigned long count)
+{
+	volatile unsigned char *addr = __ia64_mk_io_addr(port);
+	unsigned char *dp = dst;
+
+	__ia64_mf_a();
+	while (count--) {
+		*dp++ = *addr;
+	}
+	__ia64_mf_a();
+	return;
+}
+
+extern inline void
+__insw (unsigned long port, void *dst, unsigned long count)
+{
+	volatile unsigned short *addr = __ia64_mk_io_addr(port);
+	unsigned short *dp = dst;
+
+	__ia64_mf_a();
+	while (count--) {
+		*dp++ = *addr;
+	}
+	__ia64_mf_a();
+	return;
+}
+
+extern inline void
+__insl (unsigned long port, void *dst, unsigned long count)
+{
+	volatile unsigned int *addr = __ia64_mk_io_addr(port);
+	unsigned int *dp = dst;
+
+	__ia64_mf_a();
+	while (count--) {
+		*dp++ = *addr;
+	}
+	__ia64_mf_a();
+	return;
+}
+
+extern inline void
+__outb (unsigned char val, unsigned long port)
+{
+	volatile unsigned char *addr = __ia64_mk_io_addr(port);
+
+	*addr = val;
+	__ia64_mf_a();
+}
+
+extern inline void
+__outw (unsigned short val, unsigned long port)
+{
+	volatile unsigned short *addr = __ia64_mk_io_addr(port);
+
+	*addr = val;
+	__ia64_mf_a();
+}
+
+extern inline void
+__outl (unsigned int val, unsigned long port)
+{
+	volatile unsigned int *addr = __ia64_mk_io_addr(port);
+
+	*addr = val;
+	__ia64_mf_a();
+}
+
+extern inline void
+__outsb (unsigned long port, const void *src, unsigned long count)
+{
+	volatile unsigned char *addr = __ia64_mk_io_addr(port);
+	const unsigned char *sp = src;
+
+	while (count--) {
+		*addr = *sp++;
+	}
+	__ia64_mf_a();
+	return;
+}
+
+extern inline void
+__outsw (unsigned long port, const void *src, unsigned long count)
+{
+	volatile unsigned short *addr = __ia64_mk_io_addr(port);
+	const unsigned short *sp = src;
+
+	while (count--) {
+		*addr = *sp++;
+	}
+	__ia64_mf_a();
+	return;
+}
+
+extern inline void
+__outsl (unsigned long port, void *src, unsigned long count)
+{
+	volatile unsigned int *addr = __ia64_mk_io_addr(port);
+	const unsigned int *sp = src;
+
+	while (count--) {
+		*addr = *sp++;
+	}
+	__ia64_mf_a();
+	return;
+}
+
+#define inb		__inb
+#define inw		__inw
+#define inl		__inl
+#define insb		__insb
+#define insw		__insw
+#define insl		__insl
+#define outb		__outb
+#define outw		__outw
+#define outl		__outl
+#define outsb		__outsb
+#define outsw		__outsw
+#define outsl		__outsl
+
+/*
+ * The address passed to these functions are ioremap()ped already.
+ */
+extern inline unsigned long
+__readb (unsigned long addr)
+{
+	return *(volatile unsigned char *)addr;
+}
+
+extern inline unsigned long
+__readw (unsigned long addr)
+{
+	return *(volatile unsigned short *)addr;
+}
+
+extern inline unsigned long
+__readl (unsigned long addr)
+{
+	return *(volatile unsigned int *) addr;
+}
+
+extern inline unsigned long
+__readq (unsigned long addr)
+{
+	return *(volatile unsigned long *) addr;
+}
+
+extern inline void
+__writeb (unsigned char val, unsigned long addr)
+{
+	*(volatile unsigned char *) addr = val;
+}
+
+extern inline void
+__writew (unsigned short val, unsigned long addr)
+{
+	*(volatile unsigned short *) addr = val;
+}
+
+extern inline void
+__writel (unsigned int val, unsigned long addr)
+{
+	*(volatile unsigned int *) addr = val;
+}
+
+extern inline void
+__writeq (unsigned long val, unsigned long addr)
+{
+	*(volatile unsigned long *) addr = val;
+}
+
+#define readb		__readb
+#define readw		__readw
+#define readl		__readl
+#define readq		__readqq
+#define __raw_readb	readb
+#define __raw_readw	readw
+#define __raw_readl	readl
+#define __raw_readq	readq
+#define writeb		__writeb
+#define writew		__writew
+#define writel		__writel
+#define writeq		__writeq
+#define __raw_writeb	writeb
+#define __raw_writew	writew
+#define __raw_writeq	writeq
+
+#ifndef inb_p
+# define inb_p		inb
+#endif
+#ifndef inw_p
+# define inw_p		inw
+#endif
+#ifndef inl_p
+# define inl_p		inl
+#endif
+
+#ifndef outb_p
+# define outb_p		outb
+#endif
+#ifndef outw_p
+# define outw_p		outw
+#endif
+#ifndef outl_p
+# define outl_p		outl
+#endif
+
+/*
+ * An "address" in IO memory space is not clearly either an integer
+ * or a pointer. We will accept both, thus the casts.
+ *
+ * On ia-64, we access the physical I/O memory space through the
+ * uncached kernel region.
+ */
+static inline void *
+ioremap (unsigned long offset, unsigned long size)
+{
+	return (void *) (__IA64_UNCACHED_OFFSET | (offset));
+} 
+
+static inline void
+iounmap (void *addr)
+{
+}
+
+#define ioremap_nocache(o,s)	ioremap(o,s)
+
+# ifdef __KERNEL__
+
+/*
+ * String version of IO memory access ops:
+ */
+extern void __ia64_memcpy_fromio (void *, unsigned long, long);
+extern void __ia64_memcpy_toio (unsigned long, void *, long);
+extern void __ia64_memset_c_io (unsigned long, unsigned long, long);
+
+#define memcpy_fromio(to,from,len) \
+  __ia64_memcpy_fromio((to),(unsigned long)(from),(len))
+#define memcpy_toio(to,from,len) \
+  __ia64_memcpy_toio((unsigned long)(to),(from),(len))
+#define memset_io(addr,c,len) \
+  __ia64_memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
+
+#define __HAVE_ARCH_MEMSETW_IO
+#define memsetw_io(addr,c,len) \
+  _memset_c_io((unsigned long)(addr),0x0001000100010001UL*(u16)(c),(len))
+
+/*
+ * XXX - We don't have csum_partial_copy_fromio() yet, so we cheat here and 
+ * just copy it. The net code will then do the checksum later. Presently 
+ * only used by some shared memory 8390 Ethernet cards anyway.
+ */
+
+#define eth_io_copy_and_sum(skb,src,len,unused)		memcpy_fromio((skb)->data,(src),(len))
+
+#if 0
+
+/*
+ * XXX this is the kind of legacy stuff we want to get rid of with IA-64... --davidm 99/12/02
+ */
+
+/*
+ * This is used for checking BIOS signatures.  It's not clear at all
+ * why this is here.  This implementation seems to be the same on
+ * all architectures.  Strange.
+ */
+static inline int
+check_signature (unsigned long io_addr, const unsigned char *signature, int length)
+{
+	int retval = 0;
+	do {
+		if (readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
+
+#define RTC_PORT(x)		(0x70 + (x))
+#define RTC_ALWAYS_BCD		0
+
+#endif
+
+/*
+ * The caches on some architectures aren't DMA-coherent and have need
+ * to handle this in software.  There are two types of operations that
+ * can be applied to dma buffers.
+ *
+ * - dma_cache_inv(start, size) invalidates the affected parts of the
+ *   caches.  Dirty lines of the caches may be written back or simply
+ *   be discarded.  This operation is necessary before dma operations
+ *   to the memory.
+ *
+ * - dma_cache_wback(start, size) makes caches and memory coherent
+ *   by writing the content of the caches back to memory, if necessary
+ *   (cache flush).
+ *
+ * - dma_cache_wback_inv(start, size) Like dma_cache_wback() but the
+ *   function also invalidates the affected part of the caches as
+ *   necessary before DMA transfers from outside to memory.
+ *
+ * Fortunately, the IA-64 architecture mandates cache-coherent DMA, so
+ * these functions can be implemented as no-ops.
+ */
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
+# endif /* __KERNEL__ */
+#endif /* _ASM_IA64_IO_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ioctl.h linux/include/asm-ia64/ioctl.h
--- v2.3.42/linux/include/asm-ia64/ioctl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ioctl.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,77 @@
+#ifndef _ASM_IA64_IOCTL_H
+#define _ASM_IA64_IOCTL_H
+
+/*
+ * This is mostly derived from the Linux/x86 version.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The ia64 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_WRITE	1U
+#define _IOC_READ	2U
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif /* _ASM_IA64_IOCTL_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ioctls.h linux/include/asm-ia64/ioctls.h
--- v2.3.42/linux/include/asm-ia64/ioctls.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ioctls.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,87 @@
+#ifndef _ASM_IA64_IOCTLS_H
+#define _ASM_IA64_IOCTLS_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS		0x5401
+#define TCSETS		0x5402
+#define TCSETSW		0x5403
+#define TCSETSF		0x5404
+#define TCGETA		0x5405
+#define TCSETA		0x5406
+#define TCSETAW		0x5407
+#define TCSETAF		0x5408
+#define TCSBRK		0x5409
+#define TCXONC		0x540A
+#define TCFLSH		0x540B
+#define TIOCEXCL	0x540C
+#define TIOCNXCL	0x540D
+#define TIOCSCTTY	0x540E
+#define TIOCGPGRP	0x540F
+#define TIOCSPGRP	0x5410
+#define TIOCOUTQ	0x5411
+#define TIOCSTI		0x5412
+#define TIOCGWINSZ	0x5413
+#define TIOCSWINSZ	0x5414
+#define TIOCMGET	0x5415
+#define TIOCMBIS	0x5416
+#define TIOCMBIC	0x5417
+#define TIOCMSET	0x5418
+#define TIOCGSOFTCAR	0x5419
+#define TIOCSSOFTCAR	0x541A
+#define FIONREAD	0x541B
+#define TIOCINQ		FIONREAD
+#define TIOCLINUX	0x541C
+#define TIOCCONS	0x541D
+#define TIOCGSERIAL	0x541E
+#define TIOCSSERIAL	0x541F
+#define TIOCPKT		0x5420
+#define FIONBIO		0x5421
+#define TIOCNOTTY	0x5422
+#define TIOCSETD	0x5423
+#define TIOCGETD	0x5424
+#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
+#define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
+#define FIOCLEX		0x5451
+#define FIOASYNC	0x5452
+#define TIOCSERCONFIG	0x5453
+#define TIOCSERGWILD	0x5454
+#define TIOCSERSWILD	0x5455
+#define TIOCGLCKTRMIOS	0x5456
+#define TIOCSLCKTRMIOS	0x5457
+#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+
+/* Used for packet mode */
+#define TIOCPKT_DATA		 0
+#define TIOCPKT_FLUSHREAD	 1
+#define TIOCPKT_FLUSHWRITE	 2
+#define TIOCPKT_STOP		 4
+#define TIOCPKT_START		 8
+#define TIOCPKT_NOSTOP		16
+#define TIOCPKT_DOSTOP		32
+
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+#endif /* _ASM_IA64_IOCTLS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/iosapic.h linux/include/asm-ia64/iosapic.h
--- v2.3.42/linux/include/asm-ia64/iosapic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/iosapic.h	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,123 @@
+#ifndef __ASM_IA64_IOSAPIC_H
+#define __ASM_IA64_IOSAPIC_H
+
+#include <linux/config.h>
+
+#define	IO_SAPIC_DEFAULT_ADDR	0xFEC00000
+
+#define	IO_SAPIC_REG_SELECT	0x0
+#define	IO_SAPIC_WINDOW		0x10
+#define	IO_SAPIC_EOI		0x40
+
+#define	IO_SAPIC_VERSION	0x1
+
+/*
+ * Redirection table entry
+ */
+
+#define	IO_SAPIC_RTE_LOW(i)	(0x10+i*2)
+#define	IO_SAPIC_RTE_HIGH(i)	(0x11+i*2)
+
+
+#define	IO_SAPIC_DEST_SHIFT		16
+
+/*
+ * Delivery mode
+ */
+
+#define	IO_SAPIC_DELIVERY_SHIFT		8
+#define	IO_SAPIC_FIXED			0x0
+#define	IO_SAPIC_LOWEST_PRIORITY	0x1
+#define	IO_SAPIC_PMI			0x2
+#define	IO_SAPIC_NMI			0x4
+#define	IO_SAPIC_INIT			0x5
+#define	IO_SAPIC_EXTINT			0x7
+
+/*
+ * Interrupt polarity
+ */
+
+#define	IO_SAPIC_POLARITY_SHIFT		13
+#define	IO_SAPIC_POL_HIGH		0
+#define	IO_SAPIC_POL_LOW		1
+
+/*
+ * Trigger mode
+ */
+
+#define	IO_SAPIC_TRIGGER_SHIFT		15
+#define	IO_SAPIC_EDGE			0
+#define	IO_SAPIC_LEVEL			1
+
+/*
+ * Mask bit
+ */
+
+#define	IO_SAPIC_MASK_SHIFT		16
+#define	IO_SAPIC_UNMASK			0
+#define	IO_SAPIC_MSAK			1
+
+/*
+ * Bus types
+ */
+#define  BUS_ISA         0               /* ISA Bus */
+#define  BUS_PCI         1               /* PCI Bus */
+
+#ifndef CONFIG_IA64_PCI_FIRMWARE_IRQ
+struct intr_routing_entry {
+      unsigned char srcbus;
+      unsigned char srcbusno;
+      unsigned char srcbusirq;
+      unsigned char iosapic_pin;
+      unsigned char dstiosapic;
+      unsigned char mode;
+      unsigned char trigger;
+      unsigned char polarity;
+};
+
+extern        struct  intr_routing_entry      intr_routing[];
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <asm/irq.h>
+
+/*
+ * IOSAPIC Version Register return 32 bit structure like:
+ * {
+ *	unsigned int version   : 8;
+ *	unsigned int reserved1 : 8;
+ *	unsigned int pins      : 8;
+ *	unsigned int reserved2 : 8;
+ * }
+ */
+extern unsigned int iosapic_version(unsigned long);
+extern void iosapic_init(unsigned long);
+
+struct iosapic_vector {
+	unsigned long iosapic_base; /* IOSAPIC Base address */
+        char pin;		    /* IOSAPIC pin (-1 == No data) */
+	unsigned char bus;	    /* Bus number */
+	unsigned char baseirq;	    /* Base IRQ handled by this IOSAPIC */
+	unsigned char bustype;	    /* Bus type (ISA, PCI, etc) */
+	unsigned int busdata;	    /* Bus specific ID */
+        /* These bitfields use the values defined above */
+	unsigned char dmode        : 3;
+	unsigned char polarity     : 1;
+	unsigned char trigger      : 1; 
+	unsigned char UNUSED       : 3;
+};
+extern struct iosapic_vector iosapic_vector[NR_IRQS];
+
+#define iosapic_addr(v)     iosapic_vector[v].iosapic_base
+#define iosapic_pin(v)      iosapic_vector[v].pin
+#define iosapic_bus(v)      iosapic_vector[v].bus
+#define iosapic_baseirq(v)  iosapic_vector[v].baseirq
+#define iosapic_bustype(v)  iosapic_vector[v].bustype
+#define iosapic_busdata(v)  iosapic_vector[v].busdata
+#define iosapic_dmode(v)    iosapic_vector[v].dmode
+#define iosapic_trigger(v)  iosapic_vector[v].trigger
+#define iosapic_polarity(v) iosapic_vector[v].polarity
+
+# endif /* !__ASSEMBLY__ */
+#endif /* __ASM_IA64_IOSAPIC_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ipc.h linux/include/asm-ia64/ipc.h
--- v2.3.42/linux/include/asm-ia64/ipc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ipc.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,31 @@
+#ifndef __i386_IPC_H__
+#define __i386_IPC_H__
+
+/* 
+ * These are used to wrap system calls on x86.
+ *
+ * See arch/i386/kernel/sys_i386.c for ugly details..
+ */
+struct ipc_kludge {
+	struct msgbuf *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ipcbuf.h linux/include/asm-ia64/ipcbuf.h
--- v2.3.42/linux/include/asm-ia64/ipcbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ipcbuf.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,28 @@
+#ifndef _ASM_IA64_IPCBUF_H
+#define _ASM_IA64_IPCBUF_H
+
+/*
+ * The ipc64_perm structure for IA-64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit seq
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t	key;
+	__kernel_uid_t	uid;
+	__kernel_gid_t	gid;
+	__kernel_uid_t	cuid;
+	__kernel_gid_t	cgid;
+	__kernel_mode_t	mode;
+	unsigned short	seq;
+	unsigned short	__pad1;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif /* _ASM_IA64_IPCBUF_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/irq.h linux/include/asm-ia64/irq.h
--- v2.3.42/linux/include/asm-ia64/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/irq.h	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,120 @@
+#ifndef _ASM_IA64_IRQ_H
+#define _ASM_IA64_IRQ_H
+
+/*
+ * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * 11/24/98	S.Eranian 	updated TIMER_IRQ and irq_cannonicalize
+ * 01/20/99	S.Eranian	added keyboard interrupt
+ */
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+
+#include <asm/ptrace.h>
+
+#define NR_IRQS		256
+#define NR_ISA_IRQS	 16
+
+/*
+ * 0 special
+ *
+ * 1,3-14 are reserved from firmware
+ *
+ * 16-255 (vectored external interrupts) are available
+ *
+ * 15 spurious interrupt (see IVR)
+ *
+ * 16 lowest priority, 255 highest priority
+ *
+ * 15 classes of 16 interrupts each.
+ */
+#define IA64_MIN_VECTORED_IRQ	 16
+#define IA64_MAX_VECTORED_IRQ	255
+
+#define IA64_SPURIOUS_INT	0x0f
+#define PERFMON_IRQ		0x28	/* performanc monitor interrupt vector */
+#define TIMER_IRQ		0xef	/* use highest-prio group 15 interrupt for timer */
+#define IPI_IRQ			0xfe	/* inter-processor interrupt vector */
+#define CMC_IRQ			0xff	/* correctable machine-check interrupt vector */
+
+#define IA64_MIN_VECTORED_IRQ	 16
+#define IA64_MAX_VECTORED_IRQ	255
+
+extern __u8 irq_to_vector_map[IA64_MIN_VECTORED_IRQ];
+#define map_legacy_irq(x) (((x) < IA64_MIN_VECTORED_IRQ) ? irq_to_vector_map[(x)] : (x))
+
+#define IRQ_INPROGRESS	(1 << 0)	/* irq handler active */
+#define IRQ_ENABLED	(1 << 1)	/* irq enabled */
+#define IRQ_PENDING	(1 << 2)	/* irq pending */
+#define IRQ_REPLAY	(1 << 3)	/* irq has been replayed but not acked yet */
+#define IRQ_AUTODETECT	(1 << 4)	/* irq is being autodetected */
+#define IRQ_WAITING	(1 << 5)	/* used for autodetection: irq not yet seen yet */
+
+struct hw_interrupt_type {
+	const char *typename;
+	void (*init) (unsigned long addr);
+	void (*startup) (unsigned int irq);
+	void (*shutdown) (unsigned int irq);
+	int (*handle) (unsigned int irq, struct pt_regs *regs);
+	void (*enable) (unsigned int irq);
+	void (*disable) (unsigned int irq);
+};
+
+extern struct hw_interrupt_type irq_type_default;	/* dummy interrupt controller */
+extern struct hw_interrupt_type irq_type_ia64_internal;	/* CPU-internal interrupt controller */
+
+struct irq_desc {
+	unsigned int type;		/* type of interrupt (level vs. edge triggered) */
+	unsigned int status;		/* see above */
+	unsigned int depth;		/* disable depth for nested irq disables */
+	struct hw_interrupt_type *handler;
+	struct irqaction *action;	/* irq action list */
+};
+
+extern struct irq_desc irq_desc[NR_IRQS];
+
+extern spinlock_t irq_controller_lock;
+
+/* IA64 inter-cpu interrupt related definitions */
+
+/* Delivery modes for inter-cpu interrupts */
+enum {
+        IA64_IPI_DM_INT =       0x0,    /* pend an external interrupt */
+        IA64_IPI_DM_PMI =       0x2,    /* pend a PMI */
+        IA64_IPI_DM_NMI =       0x4,    /* pend an NMI (vector 2) */
+        IA64_IPI_DM_INIT =      0x5,    /* pend an INIT interrupt */
+        IA64_IPI_DM_EXTINT =    0x7,    /* pend an 8259-compatible interrupt. */
+};
+
+#define IA64_BUS_ID(cpu)        (cpu >> 8)
+#define IA64_LOCAL_ID(cpu)      (cpu & 0xff)
+
+static __inline__ int
+irq_cannonicalize (int irq)
+{
+	/*
+	 * We do the legacy thing here of pretending that irqs < 16
+	 * are 8259 irqs.
+	 */
+	return ((irq == 2) ? 9 : irq);
+}
+
+extern int invoke_irq_handlers (unsigned int irq, struct pt_regs *regs, struct irqaction *action);
+extern void disable_irq (unsigned int);
+extern void disable_irq_nosync (unsigned int);
+extern void enable_irq (unsigned int);
+extern void ipi_send (int cpu, int vector, int delivery_mode);
+
+#ifdef CONFIG_SMP
+  extern void irq_enter(int cpu, int irq);
+  extern void irq_exit(int cpu, int irq);
+  extern void handle_IPI(int irq, void *dev_id, struct pt_regs *regs);
+#else
+# define irq_enter(cpu, irq)	(++local_irq_count[cpu])
+# define irq_exit(cpu, irq)	(--local_irq_count[cpu])
+#endif
+
+#endif /* _ASM_IA64_IRQ_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/kdbsupport.h linux/include/asm-ia64/kdbsupport.h
--- v2.3.42/linux/include/asm-ia64/kdbsupport.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/kdbsupport.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,252 @@
+#ifndef _ASM_IA64_KDBSUPPORT_H
+#define _ASM_IA64_KDBSUPPORT_H
+
+/*
+ * Kernel Debugger Breakpoint Handler
+ *
+ * Copyright 1999, Silicon Graphics, Inc.
+ *
+ * Written March 1999 by Scott Lurndal at Silicon Graphics, Inc.
+ */
+
+#include <asm/ptrace.h>
+
+	/*
+	 * This file provides definitions for functions that
+	 * are dependent upon the product into which  kdb is
+	 * linked. 
+	 *
+	 * This version is for linux.
+	 */
+typedef void (*handler_t)(struct pt_regs *);
+typedef unsigned long k_machreg_t;
+
+unsigned long show_cur_stack_frame(struct pt_regs *, int, unsigned long *) ;
+
+extern char*         kbd_getstr(char *, size_t, char *);
+extern int           kdbinstalltrap(int, handler_t, handler_t*);
+extern int           kdbinstalldbreg(kdb_bp_t *);
+extern void          kdbremovedbreg(kdb_bp_t *);
+extern void          kdb_initbptab(void);
+extern int	     kdbgetregcontents(const char *, struct pt_regs *, unsigned long *);
+extern int	     kdbsetregcontents(const char *, struct pt_regs *, unsigned long);
+extern int	     kdbdumpregs(struct pt_regs *, const char *, const char *);
+
+typedef int kdbintstate_t;
+	
+extern void	     kdb_disableint(kdbintstate_t *);
+extern void	     kdb_restoreint(kdbintstate_t *);
+
+extern k_machreg_t   kdb_getpc(struct pt_regs *);
+extern int	     kdb_setpc(struct pt_regs *, k_machreg_t);
+
+extern int	     kdb_putword(unsigned long, unsigned long);
+extern int	     kdb_getcurrentframe(struct pt_regs *);
+
+/*
+ * kdb_db_trap is a processor dependent routine invoked
+ * from kdb() via the #db trap handler.   It handles breakpoints involving
+ * the processor debug registers and handles single step traps
+ * using the processor trace flag.
+ */
+
+#define KDB_DB_BPT	0	/* Straight breakpoint */
+#define KDB_DB_SS	1	/* Single Step trap */
+#define KDB_DB_SSB	2	/* Single Step, caller should continue */
+
+extern int 	     kdb_db_trap(struct pt_regs *, int);
+
+extern int	     kdb_allocdbreg(kdb_bp_t *);
+extern void          kdb_freedbreg(kdb_bp_t *);
+extern void	     kdb_initdbregs(void);
+
+extern void          kdb_setsinglestep(struct pt_regs *);
+
+	/*
+	 *  Support for ia32 architecture debug registers.
+	 */
+#define KDB_DBREGS	4	
+extern k_machreg_t dbregs[];
+
+#define DR6_BT  0x00008000
+#define DR6_BS	0x00004000
+#define DR6_BD  0x00002000
+
+#define DR6_B3  0x00000008
+#define DR6_B2	0x00000004
+#define DR6_B1  0x00000002
+#define DR6_B0	0x00000001
+
+#define DR7_RW_VAL(dr, drnum) \
+       (((dr) >> (16 + (4 * (drnum)))) & 0x3)
+
+#define DR7_RW_SET(dr, drnum, rw)                              \
+       do {                                                    \
+               (dr) &= ~(0x3 << (16 + (4 * (drnum))));         \
+               (dr) |= (((rw) & 0x3) << (16 + (4 * (drnum)))); \
+       } while (0)
+
+#define DR7_RW0(dr)       DR7_RW_VAL(dr, 0)
+#define DR7_RW0SET(dr,rw)  DR7_RW_SET(dr, 0, rw)
+#define DR7_RW1(dr)       DR7_RW_VAL(dr, 1)
+#define DR7_RW1SET(dr,rw)  DR7_RW_SET(dr, 1, rw)
+#define DR7_RW2(dr)       DR7_RW_VAL(dr, 2)
+#define DR7_RW2SET(dr,rw)  DR7_RW_SET(dr, 2, rw)
+#define DR7_RW3(dr)       DR7_RW_VAL(dr, 3)
+#define DR7_RW3SET(dr,rw)  DR7_RW_SET(dr, 3, rw)
+
+
+#define DR7_LEN_VAL(dr, drnum) \
+       (((dr) >> (18 + (4 * (drnum)))) & 0x3)
+
+#define DR7_LEN_SET(dr, drnum, rw)                             \
+       do {                                                    \
+               (dr) &= ~(0x3 << (18 + (4 * (drnum))));         \
+               (dr) |= (((rw) & 0x3) << (18 + (4 * (drnum)))); \
+       } while (0)
+
+#define DR7_LEN0(dr)        DR7_LEN_VAL(dr, 0)
+#define DR7_LEN0SET(dr,len)  DR7_LEN_SET(dr, 0, len)
+#define DR7_LEN1(dr)        DR7_LEN_VAL(dr, 1)
+#define DR7_LEN1SET(dr,len)  DR7_LEN_SET(dr, 1, len)
+#define DR7_LEN2(dr)        DR7_LEN_VAL(dr, 2)
+#define DR7_LEN2SET(dr,len)  DR7_LEN_SET(dr, 2, len)
+#define DR7_LEN3(dr)        DR7_LEN_VAL(dr, 3)
+#define DR7_LEN3SET(dr,len)  DR7_LEN_SET(dr, 3, len)
+
+#define DR7_G0(dr)    (((dr)>>1)&0x1)
+#define DR7_G0SET(dr) ((dr) |= 0x2)
+#define DR7_G0CLR(dr) ((dr) &= ~0x2)
+#define DR7_G1(dr)    (((dr)>>3)&0x1)
+#define DR7_G1SET(dr) ((dr) |= 0x8)
+#define DR7_G1CLR(dr) ((dr) &= ~0x8)
+#define DR7_G2(dr)    (((dr)>>5)&0x1)
+#define DR7_G2SET(dr) ((dr) |= 0x20)
+#define DR7_G2CLR(dr) ((dr) &= ~0x20)
+#define DR7_G3(dr)    (((dr)>>7)&0x1)
+#define DR7_G3SET(dr) ((dr) |= 0x80)
+#define DR7_G3CLR(dr) ((dr) &= ~0x80)
+
+#define DR7_L0(dr)    (((dr))&0x1)
+#define DR7_L0SET(dr) ((dr) |= 0x1)
+#define DR7_L0CLR(dr) ((dr) &= ~0x1)
+#define DR7_L1(dr)    (((dr)>>2)&0x1)
+#define DR7_L1SET(dr) ((dr) |= 0x4)
+#define DR7_L1CLR(dr) ((dr) &= ~0x4)
+#define DR7_L2(dr)    (((dr)>>4)&0x1)
+#define DR7_L2SET(dr) ((dr) |= 0x10)
+#define DR7_L2CLR(dr) ((dr) &= ~0x10)
+#define DR7_L3(dr)    (((dr)>>6)&0x1)
+#define DR7_L3SET(dr) ((dr) |= 0x40)
+#define DR7_L3CLR(dr) ((dr) &= ~0x40)
+
+#define DR7_GD		0x00002000		/* General Detect Enable */
+#define DR7_GE		0x00000200		/* Global exact */
+#define DR7_LE		0x00000100		/* Local exact */
+
+extern k_machreg_t kdb_getdr6(void);
+extern void kdb_putdr6(k_machreg_t);
+
+extern k_machreg_t kdb_getdr7(void);
+extern void kdb_putdr7(k_machreg_t);
+
+extern k_machreg_t kdb_getdr(int);
+extern void kdb_putdr(int, k_machreg_t);
+
+extern k_machreg_t kdb_getcr(int);
+
+extern void kdb_bp_install(void);
+extern void kdb_bp_remove(void);
+
+/*
+ * Support for setjmp/longjmp
+ */
+#define JB_BX   0
+#define JB_SI   1
+#define JB_DI   2
+#define JB_BP   3
+#define JB_SP   4
+#define JB_PC   5
+
+typedef struct __kdb_jmp_buf {
+	unsigned long   regs[6];
+} kdb_jmp_buf;
+
+extern int kdb_setjmp(kdb_jmp_buf *);
+extern void kdb_longjmp(kdb_jmp_buf *, int);
+
+extern kdb_jmp_buf  kdbjmpbuf;
+
+#define getprsregs(regs)	((struct switch_stack *)regs -1)
+
+#define BITMASK(bp,value)  (value << bp)
+
+/* bkpt support using break inst instead of IBP reg */
+
+/*
+ * Define certain specific instructions
+ */
+#define BREAK_INSTR             (0x00000080100L << 11)
+#define INST_SLOT0_MASK         (0x1ffffffffffL << 5)
+
+#if 0
+#define MAX_BREAKPOINTS         40
+#define PSR_SS                  40
+#endif
+
+/**
+ * IA-64 instruction format structures
+ */
+typedef union bundle {
+        struct {
+                long    low8;
+                long    high8;
+        } lform;
+        struct {
+                int     low_low4;
+                int     low_high4;
+                long    high8;
+        } iform;
+} bundle_t;
+
+#define BKPTMODE_DATAR	3
+#define BKPTMODE_IO   	2
+#define BKPTMODE_DATAW	1
+#define BKPTMODE_INST	0
+
+/* Some of the fault registers needed by kdb but not passed with
+ * regs or switch stack.
+ */
+typedef struct fault_regs {
+	unsigned long	isr ;
+	unsigned long	ifa ;
+	unsigned long	iim ;
+	unsigned long	itir ;
+} fault_regs_t ;
+
+/*
+ * State of kdb
+ */
+
+typedef struct kdb_state {
+        int     cmd_given ;
+        int     reason_for_entry ;
+        int     bkpt_handling_state ;
+	int	kdb_action ;
+} kdb_state_t ;
+
+#define BKPTSTATE_NOT_HANDLED 	0
+#define BKPTSTATE_HANDLED 	1
+
+#define CMDGIVEN_UNKNOWN	0	
+#define CMDGIVEN_SSTEP		1	
+#define CMDGIVEN_GO		2	
+
+#define ENTRYREASON_GO	 	0
+#define ENTRYREASON_SSTEP	1
+
+#define ACTION_UNKNOWN		0
+#define ACTION_NOBPINSTALL	1
+#define ACTION_NOPROMPT		2
+
+#endif /* _ASM_IA64_KDBSUPPORT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/keyboard.h linux/include/asm-ia64/keyboard.h
--- v2.3.42/linux/include/asm-ia64/keyboard.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/keyboard.h	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,70 @@
+#ifndef _ASM_IA64_KEYBOARD_H
+#define _ASM_IA64_KEYBOARD_H
+
+/*
+ * This file contains the ia-64 architecture specific keyboard
+ * definitions.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+# ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#define KEYBOARD_IRQ			1
+#define DISABLE_KBD_DURING_INTERRUPTS	0
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_pretranslate	pckbd_pretranslate
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		pckbd_leds
+#define kbd_init_hw		pckbd_init_hw
+#define kbd_sysrq_xlate		pckbd_sysrq_xlate
+
+#define INIT_KBD
+
+#define SYSRQ_KEY		0x54
+#if defined(CONFIG_KDB)
+#define E1_PAUSE  119                   /* PAUSE key */
+#endif
+
+/* resource allocation */
+#define kbd_request_region()
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input()	inb(KBD_DATA_REG)
+#define kbd_read_status()	inb(KBD_STATUS_REG)
+#define kbd_write_output(val)	outb(val, KBD_DATA_REG)
+#define kbd_write_command(val)	outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
+
+# endif /* __KERNEL__ */
+#endif /* _ASM_IA64_KEYBOARD_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/linux_logo.h linux/include/asm-ia64/linux_logo.h
--- v2.3.42/linux/include/asm-ia64/linux_logo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/linux_logo.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,49 @@
+/* $Id: linux_logo.h,v 1.6 1998/07/30 16:30:20 jj Exp $
+ * include/asm-ia64/linux_logo.h: This is a linux logo
+ *                                to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1998 David Mosberger (davidm@hpl.hp.com)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ *	     linux_logo_green[0],
+ *	     linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+ 
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "Linux/ia64 version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS 214
+
+#ifdef INCLUDE_LINUX_LOGO_DATA
+
+#define INCLUDE_LINUX_LOGOBW
+#define INCLUDE_LINUX_LOGO16
+
+#include <linux/linux_logo.h>
+
+#else
+
+/* prototypes only */
+extern unsigned char linux_logo_red[];
+extern unsigned char linux_logo_green[];
+extern unsigned char linux_logo_blue[];
+extern unsigned char linux_logo[];
+extern unsigned char linux_logo_bw[];
+extern unsigned char linux_logo16_red[];
+extern unsigned char linux_logo16_green[];
+extern unsigned char linux_logo16_blue[];
+extern unsigned char linux_logo16[];
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/machvec.h linux/include/asm-ia64/machvec.h
--- v2.3.42/linux/include/asm-ia64/machvec.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/machvec.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,108 @@
+/*
+ * Machine vector for IA-64.
+ * 
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) Srinivasa Thirumalachar <sprasad@engr.sgi.com>
+ * Copyright (C) Vijay Chander <vijay@engr.sgi.com>
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Copyright (C) David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#ifndef _ASM_IA64_MACHVEC_H
+#define _ASM_IA64_MACHVEC_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+/* forward declarations: */
+struct hw_interrupt_type;
+struct irq_desc;
+struct mm_struct;
+struct pt_regs;
+struct task_struct;
+struct timeval;
+struct vm_area_struct;
+
+typedef void ia64_mv_setup_t (char **);
+typedef void ia64_mv_irq_init_t (struct irq_desc *);
+typedef void ia64_mv_pci_fixup_t (void);
+typedef unsigned long ia64_mv_map_nr_t (unsigned long);
+typedef void ia64_mv_mca_init_t (void);
+typedef void ia64_mv_mca_handler_t (void);
+typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *);
+typedef void ia64_mv_log_print_t (void);
+
+# if defined (CONFIG_IA64_HP_SIM)
+#  include <asm/machvec_hpsim.h>
+# elif defined (CONFIG_IA64_DIG)
+#  include <asm/machvec_dig.h>
+# elif defined (CONFIG_IA64_SGI_SN1_SIM)
+#  include <asm/machvec_sgi_sn1_SIM.h>
+# elif defined (CONFIG_IA64_GENERIC)
+
+struct ia64_machine_vector {
+	const char *name;
+	ia64_mv_setup_t *setup;
+	ia64_mv_irq_init_t *irq_init;
+	ia64_mv_pci_fixup_t *pci_fixup;
+	ia64_mv_map_nr_t *map_nr;
+	ia64_mv_mca_init_t *mca_init;
+	ia64_mv_mca_handler_t *mca_handler;
+	ia64_mv_cmci_handler_t *cmci_handler;
+	ia64_mv_log_print_t *log_print;
+};
+
+#define MACHVEC_INIT(name)			\
+{						\
+	#name,					\
+	platform_setup,				\
+	platform_irq_init,			\
+	platform_pci_fixup,			\
+	platform_map_nr,			\
+	platform_mca_init,			\
+	platform_mca_handler,			\
+	platform_cmci_handler,			\
+	platform_log_print			\
+}
+
+# ifndef MACHVEC_INHIBIT_RENAMING
+#  define platform_name		ia64_mv.name
+#  define platform_setup	ia64_mv.setup
+#  define platform_irq_init	ia64_mv.irq_init
+#  define platform_map_nr	ia64_mv.map_nr
+#  define platform_mca_init	ia64_mv.mca_init
+#  define platform_mca_handler	ia64_mv.mca_handler
+#  define platform_cmci_handler	ia64_mv.cmci_handler
+#  define platform_log_print	ia64_mv.log_print
+# endif
+
+extern struct ia64_machine_vector ia64_mv;
+extern void machvec_noop (void);
+
+# else
+#  error Unknown configuration.  Update asm-ia64/machvec.h.
+# endif /* CONFIG_IA64_GENERIC */
+
+/*
+ * Define default versions so we can extend machvec for new platforms without having
+ * to update the machvec files for all existing platforms.
+ */
+#ifndef platform_setup
+# define platform_setup		((ia64_mv_setup_t *) machvec_noop)
+#endif
+#ifndef platform_irq_init
+# define platform_irq_init	((ia64_mv_irq_init_t *) machvec_noop)
+#endif
+#ifndef platform_mca_init
+# define platform_mca_init	((ia64_mv_mca_init_t *) machvec_noop)
+#endif
+#ifndef platform_mca_handler
+# define platform_mca_handler	((ia64_mv_mca_handler_t *) machvec_noop)
+#endif
+#ifndef platform_cmci_handler
+# define platform_cmci_handler	((ia64_mv_cmci_handler_t *) machvec_noop)
+#endif
+#ifndef platform_log_print
+# define platform_log_print	((ia64_mv_log_print_t *) machvec_noop)
+#endif
+
+#endif /* _ASM_IA64_MACHVEC_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/machvec_dig.h linux/include/asm-ia64/machvec_dig.h
--- v2.3.42/linux/include/asm-ia64/machvec_dig.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/machvec_dig.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,22 @@
+#ifndef _ASM_IA64_MACHVEC_DIG_h
+#define _ASM_IA64_MACHVEC_DIG_h
+
+extern ia64_mv_setup_t dig_setup;
+extern ia64_mv_irq_init_t dig_irq_init;
+extern ia64_mv_pci_fixup_t dig_pci_fixup;
+extern ia64_mv_map_nr_t map_nr_dense;
+
+/*
+ * This stuff has dual use!
+ *
+ * For a generic kernel, the macros are used to initialize the
+ * platform's machvec structure.  When compiling a non-generic kernel,
+ * the macros are used directly.
+ */
+#define platform_name		"dig"
+#define platform_setup		dig_setup
+#define platform_irq_init	dig_irq_init
+#define platform_pci_fixup	dig_pci_fixup
+#define platform_map_nr		map_nr_dense
+
+#endif /* _ASM_IA64_MACHVEC_DIG_h */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/machvec_hpsim.h linux/include/asm-ia64/machvec_hpsim.h
--- v2.3.42/linux/include/asm-ia64/machvec_hpsim.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/machvec_hpsim.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,20 @@
+#ifndef _ASM_IA64_MACHVEC_HPSIM_h
+#define _ASM_IA64_MACHVEC_HPSIM_h
+
+extern ia64_mv_setup_t hpsim_setup;
+extern ia64_mv_irq_init_t hpsim_irq_init;
+extern ia64_mv_map_nr_t map_nr_dense;
+
+/*
+ * This stuff has dual use!
+ *
+ * For a generic kernel, the macros are used to initialize the
+ * platform's machvec structure.  When compiling a non-generic kernel,
+ * the macros are used directly.
+ */
+#define platform_name		"hpsim"
+#define platform_setup		hpsim_setup
+#define platform_irq_init	hpsim_irq_init
+#define platform_map_nr		map_nr_dense
+
+#endif /* _ASM_IA64_MACHVEC_HPSIM_h */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/machvec_init.h linux/include/asm-ia64/machvec_init.h
--- v2.3.42/linux/include/asm-ia64/machvec_init.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/machvec_init.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,9 @@
+#define MACHVEC_INHIBIT_RENAMING
+
+#include <asm/machvec.h>
+
+#define MACHVEC_HELPER(name)									\
+ struct ia64_machine_vector machvec_##name __attribute__ ((unused, __section__ (".machvec")))	\
+	= MACHVEC_INIT(name);
+
+#define MACHVEC_DEFINE(name)	MACHVEC_HELPER(name)
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/machvec_sn1.h linux/include/asm-ia64/machvec_sn1.h
--- v2.3.42/linux/include/asm-ia64/machvec_sn1.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/machvec_sn1.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,20 @@
+#ifndef _ASM_IA64_MACHVEC_SN1_h
+#define _ASM_IA64_MACHVEC_SN1_h
+
+extern ia64_mv_setup_t sn1_setup;
+extern ia64_mv_irq_init_t sn1_irq_init;
+extern ia64_mv_map_nr_t sn1_map_nr;
+
+/*
+ * This stuff has dual use!
+ *
+ * For a generic kernel, the macros are used to initialize the
+ * platform's machvec structure.  When compiling a non-generic kernel,
+ * the macros are used directly.
+ */
+#define platform_name		"sn1"
+#define platform_setup		sn1_setup
+#define platform_irq_init	sn1_irq_init
+#define platform_map_nr		sn1_map_nr
+
+#endif /* _ASM_IA64_MACHVEC_SN1_h */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/mca.h linux/include/asm-ia64/mca.h
--- v2.3.42/linux/include/asm-ia64/mca.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/mca.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,143 @@
+/*
+ * File: 	mca.h
+ * Purpose: 	Machine check handling specific defines
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) Vijay Chander (vijay@engr.sgi.com)
+ * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+ */
+#ifndef _ASM_IA64_MCA_H
+#define _ASM_IA64_MCA_H
+
+#include <linux/types.h>
+#include <asm/param.h>
+#include <asm/sal.h>
+#include <asm/processor.h>
+
+/* These are the return codes from all the IA64_MCA specific interfaces */
+typedef	int ia64_mca_return_code_t;
+
+enum {
+	IA64_MCA_SUCCESS	=	0,
+	IA64_MCA_FAILURE	=	1
+};
+
+#define IA64_MCA_RENDEZ_TIMEOUT		(100 * HZ)	/* 1000 milliseconds */
+
+/* Interrupt vectors reserved for MC handling. */
+#define IA64_MCA_RENDEZ_INT_VECTOR	0xF3	/* Rendez interrupt */
+#define IA64_MCA_WAKEUP_INT_VECTOR	0x12	/* Wakeup interrupt */
+#define IA64_MCA_CMC_INT_VECTOR		0xF2	/* Correctable machine check interrupt */
+
+#define IA64_CMC_INT_DISABLE		0
+#define IA64_CMC_INT_ENABLE		1
+
+
+typedef u32 int_vector_t;
+typedef u64 millisec_t;
+
+typedef union cmcv_reg_u {
+	u64	cmcv_regval;
+	struct	{
+		u64  	cmcr_vector		: 8;
+		u64	cmcr_ignored1		: 47;
+		u64	cmcr_mask		: 1;
+		u64	cmcr_reserved1		: 3;
+		u64	cmcr_ignored2		: 1;
+		u64	cmcr_reserved2		: 4;
+	} cmcv_reg_s;
+
+} cmcv_reg_t;
+
+#define cmcv_mask		cmcv_reg_s.cmcr_mask
+#define cmcv_vector		cmcv_reg_s.cmcr_vector
+
+
+#define IA64_MCA_UCMC_HANDLER_SIZE	0x10
+#define IA64_INIT_HANDLER_SIZE		0x10
+
+enum {
+	IA64_MCA_RENDEZ_CHECKIN_NOTDONE	= 	0x0,
+	IA64_MCA_RENDEZ_CHECKIN_DONE 	= 	0x1
+};
+
+#define IA64_MAXCPUS	64	/* Need to do something about this */
+
+/* Information maintained by the MC infrastructure */
+typedef struct ia64_mc_info_s {
+	u64		imi_mca_handler;		
+	size_t		imi_mca_handler_size;
+	u64		imi_monarch_init_handler;
+	size_t		imi_monarch_init_handler_size;
+	u64		imi_slave_init_handler;
+	size_t		imi_slave_init_handler_size;
+	u8		imi_rendez_checkin[IA64_MAXCPUS];
+
+} ia64_mc_info_t;
+
+/* Possible rendez states passed from SAL to OS during MCA
+ * handoff
+ */
+enum {
+	IA64_MCA_RENDEZ_NOT_RQD 		= 	0x0,
+	IA64_MCA_RENDEZ_DONE_WITHOUT_INIT	=	0x1,
+	IA64_MCA_RENDEZ_DONE_WITH_INIT		=	0x2,
+	IA64_MCA_RENDEZ_FAILURE			=	-1
+};
+
+typedef struct ia64_mca_sal_to_os_state_s {
+	u64		imsto_os_gp;		/* GP of the os registered with the SAL */
+	u64		imsto_pal_proc;		/* PAL_PROC entry point - physical addr */
+	u64		imsto_sal_proc;		/* SAL_PROC entry point - physical addr */
+	u64		imsto_sal_gp;		/* GP of the SAL - physical */
+	u64		imsto_rendez_state;	/* Rendez state information */
+	u64		imsto_sal_check_ra;	/* Return address in SAL_CHECK while going
+						 * back to SAL from OS after MCA handling.
+						 */
+} ia64_mca_sal_to_os_state_t;
+
+enum {
+	IA64_MCA_CORRECTED 	= 	0x0,	/* Error has been corrected by OS_MCA */
+	IA64_MCA_WARM_BOOT	=	-1,	/* Warm boot of the system need from SAL */
+	IA64_MCA_COLD_BOOT	=	-2,	/* Cold boot of the system need from SAL */
+	IA64_MCA_HALT		=	-3	/* System to be halted by SAL */
+};
+	
+typedef struct ia64_mca_os_to_sal_state_s {
+	u64		imots_os_status;	/*   OS status to SAL as to what happened
+						 *   with the MCA handling.
+						 */
+	u64		imots_sal_gp;		/* GP of the SAL - physical */
+	u64		imots_new_min_state;	/* Pointer to structure containing
+						 * new values of registers in the min state
+						 * save area.
+						 */
+	u64		imots_sal_check_ra;	/* Return address in SAL_CHECK while going
+						 * back to SAL from OS after MCA handling.
+						 */
+} ia64_mca_os_to_sal_state_t;
+
+typedef int (*prfunc_t)(const char * fmt, ...);
+
+extern void mca_init(void);
+extern void ia64_os_mca_dispatch(void);
+extern void ia64_os_mca_dispatch_end(void);
+extern void ia64_mca_ucmc_handler(void);
+extern void ia64_monarch_init_handler(void);
+extern void ia64_slave_init_handler(void);
+extern void ia64_mca_rendez_int_handler(int,void *,struct pt_regs *);
+extern void ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *);
+extern void ia64_mca_cmc_int_handler(int,void *,struct pt_regs *);
+extern void ia64_log_print(int,int,prfunc_t);
+
+#define PLATFORM_CALL(fn, args)	printk("Platform call TBD\n")
+
+#undef 	MCA_TEST
+
+#if defined(MCA_TEST)
+# define MCA_DEBUG	printk
+#else
+# define MCA_DEBUG
+#endif
+
+#endif /* _ASM_IA64_MCA_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/mca_asm.h linux/include/asm-ia64/mca_asm.h
--- v2.3.42/linux/include/asm-ia64/mca_asm.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/mca_asm.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,299 @@
+/*
+ * File: 	mca_asm.h
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) Vijay Chander (vijay@engr.sgi.com)
+ * Copyright (C) Srinivasa Thirumalachar (sprasad@engr.sgi.com)
+ */
+#ifndef _ASM_IA64_MCA_ASM_H
+#define _ASM_IA64_MCA_ASM_H
+
+#define PSR_IC		13
+#define PSR_I		14
+#define	PSR_DT		17
+#define PSR_RT		27
+#define PSR_IT		36
+#define PSR_BN		44
+	
+/*
+ * This macro converts a instruction virtual address to a physical address
+ * Right now for simulation purposes the virtual addresses are
+ * direct mapped to physical addresses.
+ * 	1. Lop off bits 61 thru 63 in the virtual address
+ */
+#define INST_VA_TO_PA(addr)							\
+	dep 	addr	= 0, addr, 61, 3;
+/*
+ * This macro converts a data virtual address to a physical address
+ * Right now for simulation purposes the virtual addresses are
+ * direct mapped to physical addresses.
+ * 	1. Lop off bits 61 thru 63 in the virtual address
+ */
+#define DATA_VA_TO_PA(addr)							\
+	dep 	addr	= 0, addr, 61, 3;
+/*
+ * This macro converts a data physical address to a virtual address
+ * Right now for simulation purposes the virtual addresses are
+ * direct mapped to physical addresses.
+ *	1. Put 0x7 in bits 61 thru 63.
+ */
+#define DATA_PA_TO_VA(addr,temp)							\
+	mov	temp	= 0x7	;							\
+	dep	addr	= temp, addr, 61, 3;
+
+/*
+ * This macro jumps to the instruction at the given virtual address
+ * and starts execution in physical mode with all the address
+ * translations turned off.
+ *	1.	Save the current psr
+ *	2. 	Make sure that all the upper 32 bits are off
+ *
+ *	3.	Clear the interrupt enable and interrupt state collection bits
+ *		in the psr before updating the ipsr and iip.
+ *	
+ *	4.	Turn off the instruction, data and rse translation bits of the psr
+ *		and store the new value into ipsr
+ *		Also make sure that the interrupts are disabled.
+ *		Ensure that we are in little endian mode.
+ *		[psr.{rt, it, dt, i, be} = 0]
+ *
+ *	5.	Get the physical address corresponding to the virtual address
+ *		of the next instruction bundle and put it in iip.
+ *		(Using magic numbers 24 and 40 in the deposint instruction since
+ *		 the IA64_SDK code directly maps to lower 24bits as physical address
+ *		 from a virtual address).
+ *
+ *	6.	Do an rfi to move the values from ipsr to psr and iip to ip.
+ */
+#define  PHYSICAL_MODE_ENTER(temp1, temp2, start_addr, old_psr)				\
+	mov	old_psr = psr;								\
+	;;										\
+	dep	old_psr = 0, old_psr, 32, 32;						\
+	                                                                                \
+	mov	ar##.##rsc = r0 ;							\
+	;;										\
+	mov	temp2 = ar##.##bspstore;						\
+	;;										\
+	DATA_VA_TO_PA(temp2);								\
+	;;										\
+	mov	temp1 = ar##.##rnat;							\
+	;;										\
+	mov	ar##.##bspstore = temp2;						\
+	;;										\
+	mov	ar##.##rnat = temp1;							\
+	mov	temp1 = psr;								\
+	mov	temp2 = psr;								\
+	;;										\
+	                                                                                \
+	dep	temp2 = 0, temp2, PSR_IC, 2;						\
+	;;										\
+	mov	psr##.##l = temp2;							\
+	                                                                                \
+	dep	temp1 = 0, temp1, 32, 32;						\
+	;;										\
+ 	dep	temp1 = 0, temp1, PSR_IT, 1;						\
+	;;										\
+ 	dep	temp1 = 0, temp1, PSR_DT, 1;						\
+	;;										\
+ 	dep	temp1 = 0, temp1, PSR_RT, 1;						\
+	;;										\
+	dep	temp1 = 0, temp1, PSR_I, 1;						\
+	;;										\
+	movl	temp2 = start_addr;							\
+	mov	cr##.##ipsr = temp1;							\
+	;;										\
+	INST_VA_TO_PA(temp2);								\
+	mov	cr##.##iip = temp2;							\
+	mov	cr##.##ifs = r0;							\
+	DATA_VA_TO_PA(sp)								\
+	DATA_VA_TO_PA(gp)								\
+	;;										\
+	srlz##.##i;									\
+	;;										\
+	nop	1;									\
+	nop	2;									\
+	nop	1;									\
+	nop	2;									\
+	rfi;										\
+	;;
+
+/*
+ * This macro jumps to the instruction at the given virtual address
+ * and starts execution in virtual mode with all the address
+ * translations turned on.
+ *	1. 	Get the old saved psr
+ *	
+ *	2. 	Clear the interrupt enable and interrupt state collection bits
+ *		in the current psr.
+ *	
+ *	3.	Set the instruction translation bit back in the old psr
+ *		Note we have to do this since we are right now saving only the
+ *		lower 32-bits of old psr.(Also the old psr has the data and
+ *		rse translation bits on)
+ *	
+ *	4.	Set ipsr to this old_psr with "it" bit set and "bn" = 1.
+ *
+ *	5. 	Set iip to the virtual address of the next instruction bundle.
+ *
+ *	6.	Do an rfi to move ipsr to psr and iip to ip.
+ */
+
+#define VIRTUAL_MODE_ENTER(temp1, temp2, start_addr, old_psr)				\
+	mov	temp2 = psr;								\
+	;;										\
+	dep	temp2 = 0, temp2, PSR_IC, 2;						\
+	;;										\
+	mov	psr##.##l = temp2;							\
+	mov	ar##.##rsc = r0 ;							\
+	;;										\
+	mov	temp2 = ar##.##bspstore;						\
+	;;										\
+	DATA_PA_TO_VA(temp2,temp1);							\
+	;;										\
+	mov	temp1 = ar##.##rnat;							\
+	;;										\
+	mov	ar##.##bspstore = temp2;						\
+	;;										\
+	mov	ar##.##rnat = temp1;							\
+	;;										\
+	mov	temp1 = old_psr;							\
+	;;										\
+	mov	temp2 = 1	;							\
+	dep	temp1 = temp2, temp1, PSR_I,  1;					\
+	;;										\
+ 	dep	temp1 = temp2, temp1, PSR_IC, 1;					\
+	;;										\
+	dep	temp1 = temp2, temp1, PSR_IT, 1;					\
+	;;										\
+ 	dep	temp1 = temp2, temp1, PSR_DT, 1;					\
+	;;										\
+ 	dep	temp1 = temp2, temp1, PSR_RT, 1;					\
+	;;										\
+	dep	temp1 = temp2, temp1, PSR_BN, 1;					\
+	;;										\
+	                                                                                \
+	mov     cr##.##ipsr = temp1;							\
+	movl	temp2 = start_addr;							\
+	;;										\
+	mov	cr##.##iip = temp2;							\
+	DATA_PA_TO_VA(sp, temp1);							\
+	DATA_PA_TO_VA(gp, temp1);							\
+	;;										\
+	nop	1;									\
+	nop	2;									\
+	nop	1;									\
+	rfi;										\
+	;;
+
+/* 
+ * The following offsets capture the order in which the
+ * RSE related registers from the old context are
+ * saved onto the new stack frame.
+ *
+ *	+-----------------------+
+ *	|NDIRTY [BSP - BSPSTORE]|
+ *	+-----------------------+
+ *	| 	RNAT	      	|
+ *	+-----------------------+
+ *	| 	BSPSTORE      	|
+ *	+-----------------------+
+ *	| 	IFS	      	|
+ *	+-----------------------+
+ *	| 	PFS	      	|
+ *	+-----------------------+
+ *	| 	RSC	      	|
+ *	+-----------------------+ <-------- Bottom of new stack frame
+ */
+#define  rse_rsc_offset		0
+#define  rse_pfs_offset		(rse_rsc_offset+0x08)
+#define  rse_ifs_offset		(rse_pfs_offset+0x08)
+#define  rse_bspstore_offset	(rse_ifs_offset+0x08)
+#define  rse_rnat_offset	(rse_bspstore_offset+0x08)
+#define  rse_ndirty_offset	(rse_rnat_offset+0x08)
+
+/*
+ * rse_switch_context
+ *
+ *	1. Save old RSC onto the new stack frame
+ *	2. Save PFS onto new stack frame
+ *	3. Cover the old frame and start a new frame.
+ *	4. Save IFS onto new stack frame
+ *	5. Save the old BSPSTORE on the new stack frame
+ *	6. Save the old RNAT on the new stack frame
+ *	7. Write BSPSTORE with the new backing store pointer
+ *	8. Read and save the new BSP to calculate the #dirty registers
+ * NOTE: Look at pages 11-10, 11-11 in PRM Vol 2
+ */
+#define rse_switch_context(temp,p_stackframe,p_bspstore) 			\
+        ;; 									\
+        mov     temp=ar##.##rsc;; 						\
+        st8     [p_stackframe]=temp,8;; 					\
+        mov     temp=ar##.##pfs;; 						\
+        st8     [p_stackframe]=temp,8; 						\
+        cover ;;								\
+        mov     temp=cr##.##ifs;; 						\
+        st8     [p_stackframe]=temp,8;;	 					\
+        mov     temp=ar##.##bspstore;; 						\
+        st8     [p_stackframe]=temp,8;; 					\
+        mov     temp=ar##.##rnat;; 						\
+        st8     [p_stackframe]=temp,8; 						\
+        mov     ar##.##bspstore=p_bspstore;; 					\
+        mov     temp=ar##.##bsp;; 						\
+        sub     temp=temp,p_bspstore;;						\
+        st8     [p_stackframe]=temp,8
+
+/*
+ * rse_return_context
+ *	1. Allocate a zero-sized frame
+ *	2. Store the number of dirty registers RSC.loadrs field
+ *	3. Issue a loadrs to insure that any registers from the interrupted
+ *	   context which were saved on the new stack frame have been loaded
+ * 	   back into the stacked registers
+ *	4. Restore BSPSTORE
+ *	5. Restore RNAT
+ *	6. Restore PFS
+ *	7. Restore IFS
+ *	8. Restore RSC
+ *	9. Issue an RFI
+ */
+#define rse_return_context(psr_mask_reg,temp,p_stackframe) 			\
+        ;; 									\
+        alloc   temp=ar.pfs,0,0,0,0;						\
+        add     p_stackframe=rse_ndirty_offset,p_stackframe;;			\
+        ld8     temp=[p_stackframe];; 						\
+        shl     temp=temp,16;;							\
+        mov     ar##.##rsc=temp;; 						\
+        loadrs;;								\
+        add     p_stackframe=-rse_ndirty_offset+rse_bspstore_offset,p_stackframe;;\
+        ld8     temp=[p_stackframe];; 						\
+        mov     ar##.##bspstore=temp;; 						\
+        add     p_stackframe=-rse_bspstore_offset+rse_rnat_offset,p_stackframe;;\
+        ld8     temp=[p_stackframe];; 						\
+        mov     ar##.##rnat=temp;;						\
+        add     p_stackframe=-rse_rnat_offset+rse_pfs_offset,p_stackframe;;	\
+        ld8     temp=[p_stackframe];; 						\
+        mov     ar##.##pfs=temp;						\
+        add     p_stackframe=-rse_pfs_offset+rse_ifs_offset,p_stackframe;;	\
+        ld8     temp=[p_stackframe];; 						\
+        mov     cr##.##ifs=temp;						\
+        add     p_stackframe=-rse_ifs_offset+rse_rsc_offset,p_stackframe;;	\
+        ld8     temp=[p_stackframe];; 						\
+        mov     ar##.##rsc=temp ;						\
+        add     p_stackframe=-rse_rsc_offset,p_stackframe;			\
+        mov     temp=cr.ipsr;;							\
+        st8     [p_stackframe]=temp,8;						\
+        mov     temp=cr.iip;;							\
+        st8     [p_stackframe]=temp,-8;						\
+        mov     temp=psr;;							\
+        or      temp=temp,psr_mask_reg;;					\
+        mov     cr.ipsr=temp;;							\
+        mov     temp=ip;;							\
+        add     temp=0x30,temp;;						\
+        mov     cr.iip=temp;;							\
+        rfi;;									\
+        ld8     temp=[p_stackframe],8;;						\
+        mov     cr.ipsr=temp;;							\
+        ld8     temp=[p_stackframe];;						\
+        mov     cr.iip=temp
+
+#endif /* _ASM_IA64_MCA_ASM_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/mman.h linux/include/asm-ia64/mman.h
--- v2.3.42/linux/include/asm-ia64/mman.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/mman.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,38 @@
+#ifndef _ASM_IA64_MMAN_H
+#define _ASM_IA64_MMAN_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_NONE	0x0		/* page can not be accessed */
+
+#define MAP_SHARED	0x01		/* Share changes */
+#define MAP_PRIVATE	0x02		/* Changes are private */
+#define MAP_TYPE	0x0f		/* Mask for type of mapping */
+#define MAP_FIXED	0x10		/* Interpret addr exactly */
+#define MAP_ANONYMOUS	0x20		/* don't use a file */
+
+#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_GROWSUP	0x0200		/* register stack-like segment */
+#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
+#define MAP_LOCKED	0x2000		/* pages are locked */
+#define MAP_NORESERVE	0x4000		/* don't check for reservations */
+
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate the caches */
+#define MS_SYNC		4		/* synchronous memory sync */
+
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+/* compatibility flags */
+#define MAP_ANON	MAP_ANONYMOUS
+#define MAP_FILE	0
+
+#endif /* _ASM_IA64_MMAN_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/mmu_context.h linux/include/asm-ia64/mmu_context.h
--- v2.3.42/linux/include/asm-ia64/mmu_context.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/mmu_context.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,143 @@
+#ifndef _ASM_IA64_MMU_CONTEXT_H
+#define _ASM_IA64_MMU_CONTEXT_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+
+#include <asm/processor.h>
+
+/*
+ * Routines to manage the allocation of task context numbers.  Task
+ * context numbers are used to reduce or eliminate the need to perform
+ * TLB flushes due to context switches.  Context numbers are
+ * implemented using ia-64 region ids.  Since ia-64 TLBs do not
+ * guarantee that the region number is checked when performing a TLB
+ * lookup, we need to assign a unique region id to each region in a
+ * process.  We use the least significant three bits in a region id
+ * for this purpose.  On processors where the region number is checked
+ * in TLB lookups, we can get back those two bits by defining
+ * CONFIG_IA64_TLB_CHECKS_REGION_NUMBER.  The macro
+ * IA64_REGION_ID_BITS gives the number of bits in a region id.  The
+ * architecture manual guarantees this number to be in the range
+ * 18-24.
+ *
+ * A context number has the following format:
+ *
+ *  +--------------------+---------------------+
+ *  |  generation number |    region id        |
+ *  +--------------------+---------------------+
+ *
+ * A context number of 0 is considered "invalid".
+ *
+ * The generation number is incremented whenever we end up having used
+ * up all available region ids.  At that point with flush the entire
+ * TLB and reuse the first region id.  The new generation number
+ * ensures that when we context switch back to an old process, we do
+ * not inadvertently end up using its possibly reused region id.
+ * Instead, we simply allocate a new region id for that process.
+ *
+ * Copyright (C) 1998 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define IA64_REGION_ID_KERNEL	0 /* the kernel's region id (tlb.c depends on this being 0) */
+
+#define IA64_REGION_ID_BITS	18
+
+#ifdef CONFIG_IA64_TLB_CHECKS_REGION_NUMBER
+# define IA64_HW_CONTEXT_BITS	IA64_REGION_ID_BITS
+#else
+# define IA64_HW_CONTEXT_BITS	(IA64_REGION_ID_BITS - 3)
+#endif
+
+#define IA64_HW_CONTEXT_MASK	((1UL << IA64_HW_CONTEXT_BITS) - 1)
+
+extern unsigned long ia64_next_context;
+
+extern void get_new_mmu_context (struct mm_struct *mm);
+
+extern inline unsigned long
+ia64_rid (unsigned long context, unsigned long region_addr)
+{
+# ifdef CONFIG_IA64_TLB_CHECKS_REGION_NUMBER
+	return context;
+# else
+	return context << 3 | (region_addr >> 61);
+# endif
+}
+
+extern inline void
+get_mmu_context (struct mm_struct *mm)
+{
+	/* check if our ASN is of an older generation and thus invalid: */
+	if (((mm->context ^ ia64_next_context) & ~IA64_HW_CONTEXT_MASK) != 0) {
+		get_new_mmu_context(mm);
+	}
+}
+
+extern inline void
+init_new_context (struct task_struct *p, struct mm_struct *mm)
+{
+	mm->context = 0;
+}
+
+extern inline void
+destroy_context (struct mm_struct *mm)
+{
+	/* Nothing to do.  */
+}
+
+extern inline void
+reload_context (struct mm_struct *mm)
+{
+	unsigned long rid;
+	unsigned long rid_incr = 0;
+	unsigned long rr0, rr1, rr2, rr3, rr4;
+
+	rid = (mm->context & IA64_HW_CONTEXT_MASK);
+
+#ifndef CONFIG_IA64_TLB_CHECKS_REGION_NUMBER
+	rid <<= 3;	/* make space for encoding the region number */
+	rid_incr = 1 << 8;
+#endif
+
+	/* encode the region id, preferred page size, and VHPT enable bit: */
+	rr0 = (rid << 8) | (PAGE_SHIFT << 2) | 1;
+	rr1 = rr0 + 1*rid_incr;
+	rr2 = rr0 + 2*rid_incr;
+	rr3 = rr0 + 3*rid_incr;
+	rr4 = rr0 + 4*rid_incr;
+	ia64_set_rr(0x0000000000000000, rr0);
+	ia64_set_rr(0x2000000000000000, rr1);
+	ia64_set_rr(0x4000000000000000, rr2);
+	ia64_set_rr(0x6000000000000000, rr3);
+	ia64_set_rr(0x8000000000000000, rr4);
+	ia64_insn_group_barrier();
+	ia64_srlz_i();			/* srlz.i implies srlz.d */
+	ia64_insn_group_barrier();
+}
+
+/*
+ * Switch from address space PREV to address space NEXT.  Note that
+ * TSK may be NULL.
+ */
+static inline void
+switch_mm (struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+{
+	/*
+	 * We may get interrupts here, but that's OK because interrupt
+	 * handlers cannot touch user-space.
+	 */
+	__asm__ __volatile__ ("mov ar.k7=%0" :: "r"(__pa(next->pgd)));
+	get_mmu_context(next);
+	reload_context(next);
+}
+
+#define activate_mm(prev,next)					\
+	switch_mm((prev), (next), NULL, smp_processor_id())
+
+#endif /* _ASM_IA64_MMU_CONTEXT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/msgbuf.h linux/include/asm-ia64/msgbuf.h
--- v2.3.42/linux/include/asm-ia64/msgbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/msgbuf.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,27 @@
+#ifndef _ASM_IA64_MSGBUF_H
+#define _ASM_IA64_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for IA-64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused1;
+	unsigned long  __unused2;
+};
+
+#endif /* _ASM_IA64_MSGBUF_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/namei.h linux/include/asm-ia64/namei.h
--- v2.3.42/linux/include/asm-ia64/namei.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/namei.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,17 @@
+#ifndef _ASM_IA64_NAMEI_H
+#define _ASM_IA64_NAMEI_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+/*
+ * This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+#define __prefix_lookup_dentry(name, lookup_flags) \
+        do {} while (0)
+
+#endif /* _ASM_IA64_NAMEI_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/offsets.h linux/include/asm-ia64/offsets.h
--- v2.3.42/linux/include/asm-ia64/offsets.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/offsets.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,37 @@
+#ifndef _ASM_IA64_OFFSETS_H
+#define _ASM_IA64_OFFSETS_H
+
+/*
+ * DO NOT MODIFY
+ *
+ * This file was generated by arch/ia64/tools/print_offsets.
+ *
+ */
+
+#define PF_PTRACED_BIT			4
+
+#define IA64_TASK_SIZE			2752	/* 0xac0 */
+#define IA64_PT_REGS_SIZE		400	/* 0x190 */
+#define IA64_SWITCH_STACK_SIZE		560	/* 0x230 */
+#define IA64_SIGINFO_SIZE		136	/* 0x88 */
+
+#define IA64_TASK_FLAGS_OFFSET		8	/* 0x8 */
+#define IA64_TASK_SIGPENDING_OFFSET	16	/* 0x10 */
+#define IA64_TASK_NEED_RESCHED_OFFSET	40	/* 0x28 */
+#define IA64_TASK_THREAD_OFFSET		912	/* 0x390 */
+#define IA64_TASK_THREAD_KSP_OFFSET	912	/* 0x390 */
+#define IA64_TASK_PID_OFFSET		188	/* 0xbc */
+#define IA64_TASK_MM_OFFSET		88	/* 0x58 */
+#define IA64_PT_REGS_CR_IPSR_OFFSET	0	/* 0x0 */
+#define IA64_PT_REGS_R12_OFFSET		112	/* 0x70 */
+#define IA64_PT_REGS_R8_OFFSET		144	/* 0x90 */
+#define IA64_PT_REGS_R16_OFFSET		176	/* 0xb0 */
+#define IA64_SWITCH_STACK_B0_OFFSET	464	/* 0x1d0 */
+#define IA64_SWITCH_STACK_CALLER_UNAT_OFFSET 0	/* 0x0 */
+#define IA64_SIGCONTEXT_AR_BSP_OFFSET	72	/* 0x48 */
+#define IA64_SIGCONTEXT_AR_RNAT_OFFSET	80	/* 0x50 */
+#define IA64_SIGCONTEXT_FLAGS_OFFSET	0	/* 0x0 */
+#define IA64_SIGCONTEXT_CFM_OFFSET	48	/* 0x30 */
+#define IA64_SIGCONTEXT_FR6_OFFSET	560	/* 0x230 */
+
+#endif /* _ASM_IA64_OFFSETS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/page.h linux/include/asm-ia64/page.h
--- v2.3.42/linux/include/asm-ia64/page.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/page.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,134 @@
+#ifndef _ASM_IA64_PAGE_H
+#define _ASM_IA64_PAGE_H
+/*
+ * Pagetable related stuff.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+
+#include <asm/types.h>
+
+/*
+ * PAGE_SHIFT determines the actual kernel page size.
+ */
+#if defined(CONFIG_IA64_PAGE_SIZE_4KB)
+# define PAGE_SHIFT	12
+#elif defined(CONFIG_IA64_PAGE_SIZE_8KB)
+# define PAGE_SHIFT	13
+#elif defined(CONFIG_IA64_PAGE_SIZE_16KB)
+# define PAGE_SHIFT	14
+#elif defined(CONFIG_IA64_PAGE_SIZE_64KB)
+# define PAGE_SHIFT	16
+#else
+# error Unsupported page size!
+#endif
+
+#define PAGE_SIZE		(__IA64_UL_CONST(1) << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE - 1))
+#define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
+
+#ifdef __ASSEMBLY__
+# define __pa(x)		((x) - PAGE_OFFSET)
+# define __va(x)		((x) + PAGE_OFFSET)
+#else /* !__ASSEMBLY */
+# ifdef __KERNEL__
+#  define STRICT_MM_TYPECHECKS
+
+extern void clear_page (void *page);
+extern void copy_page (void *to, void *from);
+
+#  ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define pmd_val(x)	((x).pmd)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#  else /* !STRICT_MM_TYPECHECKS */
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)	(x)
+#define pmd_val(x)	(x)
+#define pgd_val(x)	(x)
+#define pgprot_val(x)	(x)
+
+#define __pte(x)	(x)
+#define __pgd(x)	(x)
+#define __pgprot(x)	(x)
+
+#  endif /* !STRICT_MM_TYPECHECKS */
+
+/*
+ * Note: the MAP_NR() macro can't use __pa() because MAP_NR(X) MUST
+ * map to something >= max_mapnr if X is outside the identity mapped
+ * kernel space.
+ */
+
+/*
+ * The dense variant can be used as long as the size of memory holes isn't
+ * very big.
+ */
+#define MAP_NR_DENSE(addr)	(((unsigned long) (addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+/*
+ * This variant works well for the SGI SN1 architecture (which does have huge
+ * holes in the memory address space).
+ */
+#define MAP_NR_SN1(addr)	(((unsigned long) (addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+#ifdef CONFIG_IA64_GENERIC
+# define MAP_NR(addr)	platform_map_nr(addr)
+#elif defined (CONFIG_IA64_SN_SN1_SIM)
+# define MAP_NR(addr)	MAP_NR_SN1(addr)
+#else
+# define MAP_NR(addr)	MAP_NR_DENSE(addr)
+#endif
+
+# endif /* __KERNEL__ */
+
+typedef union ia64_va {
+	struct {
+		unsigned long off : 61;		/* intra-region offset */
+		unsigned long reg :  3;		/* region number */
+	} f;
+	unsigned long l;
+	void *p;
+} ia64_va;
+
+/*
+ * Note: These macros depend on the fact that PAGE_OFFSET has all
+ * region bits set to 1 and all other bits set to zero.  They are
+ * expressed in this way to ensure they result in a single "dep"
+ * instruction.
+ */
+#define __pa(x)		({ia64_va _v; _v.l = (long) (x); _v.f.reg = 0; _v.l;})
+#define __va(x)		({ia64_va _v; _v.l = (long) (x); _v.f.reg = -1; _v.p;})
+
+#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+#define PAGE_BUG(page) do { BUG(); } while (0)
+
+#endif /* !ASSEMBLY */
+
+#define PAGE_OFFSET		0xe000000000000000
+
+#endif /* _ASM_IA64_PAGE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/pal.h linux/include/asm-ia64/pal.h
--- v2.3.42/linux/include/asm-ia64/pal.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/pal.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,1324 @@
+#ifndef _ASM_IA64_PAL_H
+#define _ASM_IA64_PAL_H
+
+/*
+ * Processor Abstraction Layer definitions.
+ *
+ * This is based on version 2.4 of the manual "Enhanced Mode Processor
+ * Abstraction Layer".
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
+ *
+ * 99/10/01	davidm	Make sure we pass zero for reserved parameters.
+ */
+
+/*
+ * Note that some of these calls use a static-register only calling
+ * convention which has nothing to do with the regular calling
+ * convention.
+ */
+#define PAL_CACHE_FLUSH		1	/* flush i/d cache */
+#define PAL_CACHE_INFO		2	/* get detailed i/d cache info */
+#define PAL_CACHE_INIT		3	/* initialize i/d cache */
+#define PAL_CACHE_SUMMARY	4	/* get summary of cache heirarchy */
+#define PAL_MEM_ATTRIB		5	/* list supported memory attributes */
+#define PAL_PTCE_INFO		6	/* purge TLB info */
+#define PAL_VM_INFO		7	/* return supported virtual memory features */
+#define PAL_VM_SUMMARY		8	/* return summary on supported vm features */
+#define PAL_BUS_GET_FEATURES	9	/* return processor bus interface features settings */
+#define PAL_BUS_SET_FEATURES	10	/* set processor bus features */
+#define PAL_DEBUG_INFO		11	/* get number of debug registers */
+#define PAL_FIXED_ADDR		12	/* get fixed component of processors's directed address */
+#define PAL_FREQ_BASE		13	/* base frequency of the platform */
+#define PAL_FREQ_RATIOS		14	/* ratio of processor, bus and ITC frequency */
+#define PAL_PERF_MON_INFO	15	/* return performance monitor info */
+#define PAL_PLATFORM_ADDR	16	/* set processor interrupt block and IO port space addr */
+#define PAL_PROC_GET_FEATURES	17	/* get configurable processor features & settings */
+#define PAL_PROC_SET_FEATURES	18	/* enable/disable configurable processor features */
+#define PAL_RSE_INFO		19	/* return rse information */
+#define PAL_VERSION		20	/* return version of PAL code */
+#define PAL_MC_CLEAR_LOG	21	/* clear all processor log info */
+#define PAL_MC_DRAIN		22	/* drain operations which could result in an MCA */
+#define PAL_MC_EXPECTED		23	/* set/reset expected MCA indicator */
+#define PAL_MC_DYNAMIC_STATE	24	/* get processor dynamic state */
+#define PAL_MC_ERROR_INFO	25	/* get processor MCA info and static state */
+#define PAL_MC_RESUME		26	/* Return to interrupted process */
+#define PAL_MC_REGISTER_MEM	27	/* Register memory for PAL to use during MCAs and inits */
+#define PAL_HALT		28	/* enter the low power HALT state */
+#define PAL_HALT_LIGHT		29	/* enter the low power light halt state*/
+#define PAL_COPY_INFO		30	/* returns info needed to relocate PAL */
+#define PAL_CACHE_LINE_INIT	31	/* init tags & data of cache line */
+#define PAL_PMI_ENTRYPOINT	32	/* register PMI memory entry points with the processor */
+#define PAL_ENTER_IA_32_ENV	33	/* enter IA-32 system environment */
+#define PAL_VM_PAGE_SIZE	34	/* return vm TC and page walker page sizes */
+
+#define PAL_MEM_FOR_TEST	37	/* get amount of memory needed for late processor test */
+#define PAL_CACHE_PROT_INFO	38	/* get i/d cache protection info */
+#define PAL_REGISTER_INFO	39	/* return AR and CR register information*/
+#define PAL_SHUTDOWN		40	/* enter processor shutdown state */
+
+#define PAL_COPY_PAL		256	/* relocate PAL procedures and PAL PMI */
+#define PAL_HALT_INFO		257	/* return the low power capabilities of processor */
+#define PAL_TEST_PROC		258	/* perform late processor self-test */
+#define PAL_CACHE_READ		259	/* read tag & data of cacheline for diagnostic testing */
+#define PAL_CACHE_WRITE		260	/* write tag & data of cacheline for diagnostic testing */
+#define PAL_VM_TR_READ		261	/* read contents of translation register */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/*
+ * Data types needed to pass information into PAL procedures and
+ * interpret information returned by them.
+ */
+
+/* Return status from the PAL procedure */
+typedef s64				pal_status_t;
+
+#define PAL_STATUS_SUCCESS		0	/* No error */
+#define PAL_STATUS_UNIMPLEMENTED	-1	/* Unimplemented procedure */
+#define PAL_STATUS_EINVAL		-2	/* Invalid argument */
+#define PAL_STATUS_ERROR		-3	/* Error */
+#define PAL_STATUS_CACHE_INIT_FAIL	-4	/* Could not initialize the 
+						 * specified level and type of
+						 * cache without sideeffects 
+						 * and "restrict" was 1
+						 */
+
+/* Processor cache level in the heirarchy */
+typedef u64				pal_cache_level_t;
+#define PAL_CACHE_LEVEL_L0		0	/* L0 */
+#define PAL_CACHE_LEVEL_L1		1	/* L1 */
+#define PAL_CACHE_LEVEL_L2		2	/* L2 */
+
+
+/* Processor cache type at a particular level in the heirarchy */
+
+typedef u64				pal_cache_type_t;
+#define PAL_CACHE_TYPE_INSTRUCTION	1	/* Instruction cache */
+#define PAL_CACHE_TYPE_DATA		2	/* Data or unified cache */
+#define PAL_CACHE_TYPE_INSTRUCTION_DATA	3	/* Both Data & Instruction */
+
+
+#define PAL_CACHE_FLUSH_NO_INVALIDATE	0	/* Don't invalidate clean lines */
+#define PAL_CACHE_FLUSH_INVALIDATE	1	/* Invalidate clean lines */
+
+/* Processor cache line size in bytes  */
+typedef int				pal_cache_line_size_t;
+
+/* Processor cache line state */
+typedef u64				pal_cache_line_state_t;
+#define PAL_CACHE_LINE_STATE_INVALID	0	/* Invalid */
+#define PAL_CACHE_LINE_STATE_SHARED	1	/* Shared */
+#define PAL_CACHE_LINE_STATE_EXCLUSIVE	2	/* Exclusive */
+#define PAL_CACHE_LINE_STATE_MODIFIED	3	/* Modified */
+
+typedef struct pal_freq_ratio {
+	u64 den : 32, num : 32;	/* numerator & denominator */
+} itc_ratio, proc_ratio;
+
+typedef	union  pal_cache_config_info_1_s {
+	struct {
+		u64		u		: 1,	/* 0 Unified cache ? */
+				reserved	: 5,	/* 7-3 Reserved */
+				at		: 2,	/* 2-1 Cache mem attr*/
+				associativity	: 8,	/* 16-8 Associativity*/
+				line_size	: 8,	/* 23-17 Line size */
+				stride		: 8,	/* 31-24 Stride */
+				store_latency	: 8,	/*39-32 Store latency*/
+				load_latency	: 8,	/* 47-40 Load latency*/
+				store_hints	: 8,	/* 55-48 Store hints*/
+				load_hints	: 8;	/* 63-56 Load hints */
+	} pcci1_bits;
+	u64			pcci1_data;
+} pal_cache_config_info_1_t;
+
+typedef	union  pal_cache_config_info_2_s {
+	struct {
+		u64		cache_size	: 32,	/*cache size in bytes*/
+
+
+				alias_boundary	: 8,	/* 39-32 aliased addr
+							 * separation for max
+							 * performance.
+							 */
+				tag_ls_bit	: 8,	/* 47-40 LSb of addr*/
+				tag_ms_bit	: 8,	/* 55-48 MSb of addr*/
+				reserved	: 8;	/* 63-56 Reserved */
+	} pcci2_bits;
+	u64			pcci2_data;
+} pal_cache_config_info_2_t;
+
+
+typedef struct pal_cache_config_info_s {
+	pal_status_t			pcci_status;
+	pal_cache_config_info_1_t	pcci_info_1;
+	pal_cache_config_info_2_t	pcci_info_2;
+	u64				pcci_reserved;
+} pal_cache_config_info_t;
+
+#define pcci_ld_hint		pcci_info_1.pcci1.load_hints
+#define pcci_st_hint		pcci_info_1.pcci1_bits.store_hints
+#define pcci_ld_latency		pcci_info_1.pcci1_bits.load_latency
+#define pcci_st_latency		pcci_info_1.pcci1_bits.store_latency
+#define pcci_stride		pcci_info_1.pcci1_bits.stride
+#define pcci_line_size		pcci_info_1.pcci1_bits.line_size
+#define pcci_assoc		pcci_info_1.pcci1_bits.associativity
+#define pcci_cache_attr		pcci_info_1.pcci1_bits.at
+#define pcci_unified		pcci_info_1.pcci1_bits.u
+#define pcci_tag_msb		pcci_info_2.pcci2_bits.tag_ms_bit
+#define pcci_tag_lsb		pcci_info_2.pcci2_bits.tag_ls_bit
+#define pcci_alias_boundary	pcci_info_2.pcci2_bits.alias_boundary
+#define pcci_cache_size		pcci_info_2.pcci2_bits.cache_size
+
+
+
+/* Possible values for cache attributes */
+
+#define PAL_CACHE_ATTR_WT		0	/* Write through cache */
+#define PAL_CACHE_ATTR_WB		1	/* Write back cache */
+#define PAL_CACHE_ATTR_WT_OR_WB		2	/* Either write thru or write 
+						 * back depending on TLB 
+						 * memory attributes
+						 */
+
+
+/* Possible values for cache hints */
+
+#define PAL_CACHE_HINT_TEMP_1		0	/* Temporal level 1 */
+#define PAL_CACHE_HINT_NTEMP_1		1	/* Non-temporal level 1 */
+#define PAL_CACHE_HINT_NTEMP_ALL	3	/* Non-temporal all levels */
+
+/* Processor cache protection  information */
+typedef union pal_cache_protection_element_u {
+	u32			pcpi_data;
+	struct {
+		u32		data_bits	: 8, /* # data bits covered by
+						      * each unit of protection
+						      */
+
+				tagprot_lsb	: 6, /* Least -do- */
+				tagprot_msb	: 6, /* Most Sig. tag address
+						      * bit that this 
+						      * protection covers.
+						      */
+				prot_bits	: 6, /* # of protection bits */
+				method		: 4, /* Protection method */
+			        t_d		: 2; /* Indicates which part
+						      * of the cache this 
+						      * protection encoding
+						      * applies.
+						      */
+	} pcp_info;
+} pal_cache_protection_element_t;
+
+#define pcpi_cache_prot_part	pcp_info.t_d
+#define pcpi_prot_method	pcp_info.method
+#define pcpi_prot_bits		pcp_info.prot_bits
+#define pcpi_tagprot_msb	pcp_info.tagprot_msb
+#define pcpi_tagprot_lsb	pcp_info.tagprot_lsb
+#define pcpi_data_bits		pcp_info.data_bits
+
+/* Processor cache part encodings */
+#define PAL_CACHE_PROT_PART_DATA	0	/* Data protection  */
+#define PAL_CACHE_PROT_PART_TAG		1	/* Tag  protection */
+#define PAL_CACHE_PROT_PART_TAG_DATA	2	/* Tag+data protection (tag is
+						 * more significant )
+						 */
+#define PAL_CACHE_PROT_PART_DATA_TAG	3	/* Data+tag protection (data is
+						 * more significant )
+						 */ 
+#define PAL_CACHE_PROT_PART_MAX		6
+
+
+typedef struct pal_cache_protection_info_s {
+	pal_status_t			pcpi_status;
+	pal_cache_protection_element_t	pcp_info[PAL_CACHE_PROT_PART_MAX];
+} pal_cache_protection_info_t;
+	
+
+/* Processor cache protection method encodings */
+#define PAL_CACHE_PROT_METHOD_NONE		0	/* No protection */
+#define PAL_CACHE_PROT_METHOD_ODD_PARITY	1	/* Odd parity */
+#define PAL_CACHE_PROT_METHOD_EVEN_PARITY	2	/* Even parity */
+#define PAL_CACHE_PROT_METHOD_ECC		3	/* ECC protection */
+
+
+/* Processor cache line identification in the heirarchy */
+typedef union pal_cache_line_id_u {
+	u64			pclid_data;
+	struct {
+		u64		cache_type	: 8,	/* 7-0 cache type */
+				level		: 8,	/* 15-8 level of the
+							 * cache in the 
+							 * heirarchy.
+							 */
+				way		: 8,	/* 23-16 way in the set
+							 */
+				part		: 8,	/* 31-24 part of the
+							 * cache 
+							 */
+				reserved	: 32;	/* 63-32 is reserved*/
+	} pclid_info_read;
+	struct {
+		u64		cache_type	: 8,	/* 7-0 cache type */
+				level		: 8,	/* 15-8 level of the
+							 * cache in the 
+							 * heirarchy.
+							 */
+				way		: 8,	/* 23-16 way in the set
+							 */
+				part		: 8,	/* 31-24 part of the
+							 * cache 
+							 */
+				mesi		: 8,	/* 39-32 cache line 
+							 * state
+							 */
+				start		: 8,	/* 47-40 lsb of data to
+							 * invert
+							 */
+				length		: 8,	/* 55-48 #bits to
+							 * invert 
+							 */
+				trigger		: 8;	/* 63-56 Trigger error
+							 * by doing a load 
+							 * after the write 
+						         */
+				
+	} pclid_info_write;
+} pal_cache_line_id_u_t;
+
+#define pclid_read_part		pclid_info_read.part
+#define pclid_read_way		pclid_info_read.way
+#define pclid_read_level	pclid_info_read.level
+#define pclid_read_cache_type	pclid_info_read.cache_type
+
+#define pclid_write_trigger	pclid_info_write.trigger
+#define pclid_write_length	pclid_info_write.length
+#define pclid_write_start	pclid_info_write.start
+#define pclid_write_mesi	pclid_info_write.mesi
+#define pclid_write_part	pclid_info_write.part
+#define pclid_write_way		pclid_info_write.way
+#define pclid_write_level	pclid_info_write.level
+#define pclid_write_cache_type	pclid_info_write.cache_type
+
+/* Processor cache line part encodings */
+#define PAL_CACHE_LINE_ID_PART_DATA		0	/* Data */
+#define PAL_CACHE_LINE_ID_PART_TAG		1	/* Tag */
+#define PAL_CACHE_LINE_ID_PART_DATA_PROT	2	/* Data protection */
+#define PAL_CACHE_LINE_ID_PART_TAG_PROT		3	/* Tag protection */
+#define PAL_CACHE_LINE_ID_PART_DATA_TAG_PROT	4	/* Data+tag 
+							 * protection
+							 */
+typedef struct pal_cache_line_info_s {
+	pal_status_t		pcli_status;		/* Return status of the read cache line 
+							 * info call.
+							 */
+	u64			pcli_data;		/* 64-bit data, tag, protection bits .. */
+	u64			pcli_data_len;		/* data length in bits */
+	pal_cache_line_state_t	pcli_cache_line_state;	/* mesi state */
+
+} pal_cache_line_info_t;
+
+
+/* Machine Check related crap */
+
+/* Pending event status bits  */
+typedef u64					pal_mc_pending_events_t;
+
+#define PAL_MC_PENDING_MCA			(1 << 0)
+#define PAL_MC_PENDING_INIT			(1 << 1)
+
+/* Error information type */
+typedef u64					pal_mc_info_index_t;
+
+#define PAL_MC_INFO_PROCESSOR			0	/* Processor */
+#define PAL_MC_INFO_CACHE_CHECK			1	/* Cache check */
+#define PAL_MC_INFO_TLB_CHECK			2	/* Tlb check */
+#define PAL_MC_INFO_BUS_CHECK			3	/* Bus check */
+#define PAL_MC_INFO_REQ_ADDR			4	/* Requestor address */
+#define PAL_MC_INFO_RESP_ADDR			5	/* Responder address */
+#define PAL_MC_INFO_TARGET_ADDR			6	/* Target address */
+#define PAL_MC_INFO_IMPL_DEP			7	/* Implementation 
+							 * dependent 
+							 */
+
+
+typedef struct pal_process_state_info_s {
+	u64		reserved1	: 2,
+			rz		: 1,	/* PAL_CHECK processor
+						 * rendezvous 
+						 * successful.
+						 */
+
+			ra		: 1,	/* PAL_CHECK attempted
+						 * a rendezvous.
+						 */
+			me		: 1,	/* Distinct multiple
+						 * errors occurred
+						 */
+
+			mn		: 1,	/* Min. state save 
+						 * area has been 
+						 * registered with PAL
+						 */
+
+			sy		: 1,	/* Storage integrity
+						 * synched 
+						 */
+
+
+			co		: 1,	/* Continuable */
+			ci		: 1,	/* MC isolated */
+			us		: 1,	/* Uncontained storage
+						 * damage.
+						 */
+
+
+			hd		: 1,	/* Non-essential hw
+						 * lost (no loss of
+						 * functionality) 
+						 * causing the 
+						 * processor to run in
+						 * degraded mode.
+						 */
+
+			tl		: 1,	/* 1 => MC occurred
+						 * after an instr was
+						 * executed but before
+						 * the trap that 
+						 * resulted from instr
+						 * execution was 
+						 * generated.
+						 * (Trap Lost )
+						 */
+			op		: 3,	/* Operation that
+						 * caused the machine
+						 * check
+						 */
+
+			dy		: 1,	/* Processor dynamic
+						 * state valid 
+						 */
+
+
+			in		: 1,	/* 0 = MC, 1 = INIT */
+			rs		: 1,	/* RSE valid */
+			cm		: 1,	/* MC corrected */
+			ex		: 1,	/* MC is expected */
+			cr		: 1,	/* Control regs valid*/
+			pc		: 1,	/* Perf cntrs valid */
+			dr		: 1,	/* Debug regs valid */
+			tr		: 1,	/* Translation regs
+						 * valid
+						 */
+			rr		: 1,	/* Region regs valid */
+			ar		: 1,	/* App regs valid */
+			br		: 1,	/* Branch regs valid */
+			pr		: 1,	/* Predicate registers
+						 * valid
+						 */
+
+			fp		: 1,	/* fp registers valid*/
+			b1		: 1,	/* Preserved bank one
+						 * general registers
+						 * are valid
+						 */
+			b0		: 1,	/* Preserved bank zero
+						 * general registers
+						 * are valid
+						 */
+			gr		: 1,	/* General registers
+						 * are valid 
+						 * (excl. banked regs)
+						 */
+			dsize		: 16,	/* size of dynamic 
+						 * state returned
+						 * by the processor
+						 */
+
+			reserved2	: 12,
+			cc		: 1,	/* Cache check */
+			tc		: 1,	/* TLB check */
+			bc		: 1,	/* Bus check */
+			uc		: 1;	/* Unknown check */
+
+} pal_processor_state_info_t;
+
+typedef struct pal_cache_check_info_s {
+	u64		reserved1	: 16,
+			way		: 5,	/* Way in which the 
+						 * error occurred 
+						 */
+			reserved2	: 1,
+			mc		: 1,	/* Machine check corrected */
+			tv		: 1,	/* Target address
+						 * structure is valid
+						 */
+
+			wv		: 1,	/* Way field valid */
+			op		: 3,	/* Type of cache 
+						 * operation that 
+						 * caused the machine
+						 * check.
+						 */
+
+			dl		: 1,	/* Failure in data part
+						 * of cache line
+						 */
+			tl		: 1,	/* Failure in tag part
+						 * of cache line
+						 */
+			dc		: 1,	/* Failure in dcache */
+			ic		: 1,	/* Failure in icache */
+			index		: 24,	/* Cache line index */
+			mv		: 1,	/* mesi valid */
+			mesi		: 3,	/* Cache line state */
+			level		: 4;	/* Cache level */
+
+} pal_cache_check_info_t;
+
+typedef struct pal_tlb_check_info_s {
+
+	u64		tr_slot		: 8,	/* Slot# of TR where
+						 * error occurred 
+						 */
+			reserved2	: 8,
+			dtr		: 1,	/* Fail in data TR */
+			itr		: 1,	/* Fail in inst TR */
+			dtc		: 1,	/* Fail in data TC */
+			itc		: 1,	/* Fail in inst. TC */
+			mc		: 1,	/* Machine check corrected */
+			reserved1	: 43;
+
+} pal_tlb_check_info_t;
+
+typedef struct pal_bus_check_info_s {
+	u64		size		: 5,	/* Xaction size*/
+			ib		: 1,	/* Internal bus error */
+			eb		: 1,	/* External bus error */
+			cc		: 1,	/* Error occurred 
+						 * during cache-cache
+						 * transfer.
+						 */
+			type		: 8,	/* Bus xaction type*/
+			sev		: 5,	/* Bus error severity*/
+			tv		: 1,	/* Targ addr valid */
+			rp		: 1,	/* Resp addr valid */
+			rq		: 1,	/* Req addr valid */
+			bsi		: 8,	/* Bus error status 
+						 * info
+						 */
+			mc		: 1,	/* Machine check corrected */
+			reserved1	: 31;
+} pal_bus_check_info_t;
+
+typedef union pal_mc_error_info_u {
+	u64				pmei_data;
+	pal_processor_state_info_t	pme_processor;
+	pal_cache_check_info_t		pme_cache;
+	pal_tlb_check_info_t		pme_tlb;
+	pal_bus_check_info_t		pme_bus;
+} pal_mc_error_info_t;
+
+#define pmci_proc_unknown_check			pme_processor.uc
+#define pmci_proc_bus_check			pme_processor.bc
+#define pmci_proc_tlb_check			pme_processor.tc
+#define pmci_proc_cache_check			pme_processor.cc
+#define pmci_proc_dynamic_state_size		pme_processor.dsize
+#define pmci_proc_gpr_valid			pme_processor.gr
+#define pmci_proc_preserved_bank0_gpr_valid	pme_processor.b0
+#define pmci_proc_preserved_bank1_gpr_valid	pme_processor.b1
+#define pmci_proc_fp_valid			pme_processor.fp
+#define pmci_proc_predicate_regs_valid		pme_processor.pr
+#define pmci_proc_branch_regs_valid		pme_processor.br
+#define pmci_proc_app_regs_valid		pme_processor.ar
+#define pmci_proc_region_regs_valid		pme_processor.rr
+#define pmci_proc_translation_regs_valid	pme_processor.tr
+#define pmci_proc_debug_regs_valid		pme_processor.dr
+#define pmci_proc_perf_counters_valid		pme_processor.pc
+#define pmci_proc_control_regs_valid		pme_processor.cr
+#define pmci_proc_machine_check_expected	pme_processor.ex
+#define pmci_proc_machine_check_corrected	pme_processor.cm
+#define pmci_proc_rse_valid			pme_processor.rs
+#define pmci_proc_machine_check_or_init		pme_processor.in
+#define pmci_proc_dynamic_state_valid		pme_processor.dy
+#define pmci_proc_operation			pme_processor.op
+#define pmci_proc_trap_lost			pme_processor.tl
+#define pmci_proc_hardware_damage		pme_processor.hd
+#define pmci_proc_uncontained_storage_damage	pme_processor.us
+#define pmci_proc_machine_check_isolated	pme_processor.ci
+#define pmci_proc_continuable			pme_processor.co
+#define pmci_proc_storage_intergrity_synced	pme_processor.sy
+#define pmci_proc_min_state_save_area_regd	pme_processor.mn
+#define	pmci_proc_distinct_multiple_errors	pme_processor.me
+#define pmci_proc_pal_attempted_rendezvous	pme_processor.ra
+#define pmci_proc_pal_rendezvous_complete	pme_processor.rz
+
+
+#define pmci_cache_level			pme_cache.level
+#define pmci_cache_line_state			pme_cache.mesi
+#define pmci_cache_line_state_valid		pme_cache.mv
+#define pmci_cache_line_index			pme_cache.index
+#define pmci_cache_instr_cache_fail		pme_cache.ic
+#define pmci_cache_data_cache_fail		pme_cache.dc
+#define pmci_cache_line_tag_fail		pme_cache.tl
+#define pmci_cache_line_data_fail		pme_cache.dl
+#define pmci_cache_operation			pme_cache.op
+#define pmci_cache_way_valid			pme_cache.wv
+#define pmci_cache_target_address_valid		pme_cache.tv
+#define pmci_cache_way				pme_cache.way
+#define pmci_cache_mc				pme_cache.mc
+
+#define pmci_tlb_instr_translation_cache_fail	pme_tlb.itc
+#define pmci_tlb_data_translation_cache_fail	pme_tlb.dtc
+#define pmci_tlb_instr_translation_reg_fail	pme_tlb.itr
+#define pmci_tlb_data_translation_reg_fail	pme_tlb.dtr
+#define pmci_tlb_translation_reg_slot		pme_tlb.tr_slot
+#define pmci_tlb_mc				pme_tlb.mc
+
+#define pmci_bus_status_info			pme_bus.bsi
+#define pmci_bus_req_address_valid		pme_bus.rq
+#define pmci_bus_resp_address_valid		pme_bus.rp
+#define pmci_bus_target_address_valid		pme_bus.tv
+#define pmci_bus_error_severity			pme_bus.sev
+#define pmci_bus_transaction_type		pme_bus.type
+#define pmci_bus_cache_cache_transfer		pme_bus.cc
+#define pmci_bus_transaction_size		pme_bus.size
+#define pmci_bus_internal_error			pme_bus.ib
+#define pmci_bus_external_error			pme_bus.eb
+#define pmci_bus_mc				pme_bus.mc
+
+
+typedef struct pal_min_state_area_s {
+	u64	pmsa_reserved[26];
+	u64	pmsa_xfs;
+	u64	pmsa_xpsr;
+	u64	pmsa_xip;
+	u64	pmsa_rsc;
+	u64	pmsa_br0;
+	u64	pmsa_pr;
+	u64	pmsa_bank0_gr[16];
+	u64	pmsa_gr[16];
+	u64	pmsa_nat_bits;
+} pal_min_state_area_t;
+
+
+struct ia64_pal_retval {
+	/*
+	 * A zero status value indicates call completed without error.
+	 * A negative status value indicates reason of call failure.
+	 * A positive status value indicates success but an
+	 * informational value should be printed (e.g., "reboot for
+	 * change to take effect").
+	 */
+	s64 status;
+	u64 v0;
+	u64 v1;
+	u64 v2;
+};
+
+/*
+ * Note: Currently unused PAL arguments are generally labeled
+ * "reserved" so the value specified in the PAL documentation
+ * (generally 0) MUST be passed.  Reserved parameters are not optional
+ * parameters.
+ */
+#ifdef __GCC_MULTIREG_RETVALS__
+  extern struct ia64_pal_retval ia64_pal_call_static (u64, u64, u64, u64); 
+  /*
+   * If multi-register return values are returned according to the
+   * ia-64 calling convention, we can call ia64_pal_call_static
+   * directly.
+   */
+# define PAL_CALL(iprv,a0,a1,a2,a3)	iprv = ia64_pal_call_static(a0,a1, a2, a3)
+#else
+  extern void ia64_pal_call_static (struct ia64_pal_retval *, u64, u64, u64, u64);
+  /*
+   * If multi-register return values are returned through an aggregate
+   * allocated in the caller, we need to use the stub implemented in
+   * sal-stub.S.
+   */
+# define PAL_CALL(iprv,a0,a1,a2,a3)	ia64_pal_call_static(&iprv, a0, a1, a2, a3)
+#endif
+
+typedef int (*ia64_pal_handler) (u64, ...);
+extern ia64_pal_handler ia64_pal;
+extern void ia64_pal_handler_init (void *);
+
+extern ia64_pal_handler ia64_pal;
+
+extern pal_cache_config_info_t		l0d_cache_config_info;
+extern pal_cache_config_info_t		l0i_cache_config_info;
+extern pal_cache_config_info_t		l1_cache_config_info;
+extern pal_cache_config_info_t		l2_cache_config_info;
+
+extern pal_cache_protection_info_t	l0d_cache_protection_info;
+extern pal_cache_protection_info_t	l0i_cache_protection_info;
+extern pal_cache_protection_info_t	l1_cache_protection_info;
+extern pal_cache_protection_info_t	l2_cache_protection_info;
+
+extern pal_cache_config_info_t		pal_cache_config_info_get(pal_cache_level_t,
+								  pal_cache_type_t);
+
+extern pal_cache_protection_info_t	pal_cache_protection_info_get(pal_cache_level_t,
+								      pal_cache_type_t);
+
+
+extern void				pal_error(int);
+
+
+/* Useful wrappers for the current list of pal procedures */
+
+typedef union pal_bus_features_u {
+	u64	pal_bus_features_val;
+	struct {
+		u64	pbf_reserved1				:	29;
+		u64	pbf_req_bus_parking			:	1;
+		u64	pbf_bus_lock_mask			:	1;
+		u64	pbf_enable_half_xfer_rate		:	1;
+		u64	pbf_reserved2				:	22;
+		u64	pbf_disable_xaction_queueing		:	1;
+		u64	pbf_disable_resp_err_check		:	1;
+		u64	pbf_disable_berr_check			:	1;
+		u64	pbf_disable_bus_req_internal_err_signal	:	1;
+		u64	pbf_disable_bus_req_berr_signal		:	1;
+		u64	pbf_disable_bus_init_event_check	:	1;
+		u64	pbf_disable_bus_init_event_signal	:	1;
+		u64	pbf_disable_bus_addr_err_check		:	1;
+		u64	pbf_disable_bus_addr_err_signal		:	1;
+		u64	pbf_disable_bus_data_err_check		:	1;
+	} pal_bus_features_s;
+} pal_bus_features_u_t; 
+
+extern void pal_bus_features_print (u64);
+
+/* Provide information about configurable processor bus features */
+extern inline s64 
+ia64_pal_bus_get_features (pal_bus_features_u_t *features_avail,
+			   pal_bus_features_u_t *features_status,
+			   pal_bus_features_u_t *features_control)
+{
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_BUS_GET_FEATURES, 0, 0, 0);
+	if (features_avail)
+		features_avail->pal_bus_features_val = iprv.v0;
+	if (features_status)
+		features_status->pal_bus_features_val = iprv.v1;
+	if (features_control)
+		features_control->pal_bus_features_val = iprv.v2;
+	return iprv.status;	
+}
+/* Enables/disables specific processor bus features */
+extern inline s64 
+ia64_pal_bus_set_features (pal_bus_features_u_t feature_select) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_BUS_SET_FEATURES, feature_select.pal_bus_features_val, 0, 0);
+	return iprv.status;
+}
+
+/* Flush the processor instruction or data caches */
+extern inline s64 
+ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 plat_ack) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, plat_ack); 
+	return iprv.status; 
+}
+
+
+/* Initialize the processor controlled caches */
+extern inline s64 
+ia64_pal_cache_init (u64 level, u64 cache_type, u64 restrict) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_CACHE_INIT, level, cache_type, restrict); 
+	return iprv.status; 
+}
+
+/* Initialize the tags and data of a data or unified cache line of 
+ * processor controlled cache to known values without the availability 
+ * of backing memory.
+ */
+extern inline s64 
+ia64_pal_cache_line_init (u64 physical_addr, u64 data_value) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_CACHE_LINE_INIT, physical_addr, data_value, 0);
+	return iprv.status; 
+}
+
+
+/* Read the data and tag of a processor controlled cache line for diags */
+extern inline s64 
+ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_CACHE_READ, line_id.pclid_data, physical_addr, 0);
+	return iprv.status; 
+}
+
+/* Return summary information about the heirarchy of caches controlled by the processor */
+extern inline s64 
+ia64_pal_cache_summary (u64 *cache_levels, u64 *unique_caches) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_CACHE_SUMMARY, 0, 0, 0);
+	if (cache_levels)
+		*cache_levels = iprv.v0;
+	if (unique_caches)
+		*unique_caches = iprv.v1;
+	return iprv.status; 
+}
+
+/* Write the data and tag of a processor-controlled cache line for diags */
+extern inline s64 
+ia64_pal_cache_write (pal_cache_line_id_u_t line_id, u64 physical_addr, u64 data) 
+{	
+	struct ia64_pal_retval iprv;	
+	PAL_CALL(iprv, PAL_CACHE_WRITE, line_id.pclid_data, physical_addr, data);
+	return iprv.status; 
+}
+
+
+/* Return the parameters needed to copy relocatable PAL procedures from ROM to memory */
+extern inline s64 
+ia64_pal_copy_info (u64 copy_type, u64 num_procs, u64 num_iopics,
+		    u64 *buffer_size, u64 *buffer_align) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_COPY_INFO, copy_type, num_procs, num_iopics); 
+	if (buffer_size)
+		*buffer_size = iprv.v0;
+	if (buffer_align)
+		*buffer_align = iprv.v1;
+	return iprv.status; 
+}
+
+/* Copy relocatable PAL procedures from ROM to memory */
+extern inline s64 
+ia64_pal_copy_pal (u64 target_addr, u64 alloc_size, u64 processor, u64 *pal_proc_offset) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_COPY_PAL, target_addr, alloc_size, processor);
+	if (pal_proc_offset)
+		*pal_proc_offset = iprv.v0;
+	return iprv.status; 
+}
+
+/* Return the number of instruction and data debug register pairs */
+extern inline s64 
+ia64_pal_debug_info (u64 *inst_regs,  u64 *data_regs) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_DEBUG_INFO, 0, 0, 0);
+	if (inst_regs)
+		*inst_regs = iprv.v0;
+	if (data_regs)
+		*data_regs = iprv.v1;
+
+	return iprv.status; 
+}
+
+#ifdef TBD
+/* Switch from IA64-system environment to IA-32 system environment */
+extern inline s64 
+ia64_pal_enter_ia32_env (ia32_env1, ia32_env2, ia32_env3) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_ENTER_IA_32_ENV, ia32_env1, ia32_env2, ia32_env3); 
+	return iprv.status; 
+}
+#endif
+
+/* Get unique geographical address of this processor on its bus */
+extern inline s64 
+ia64_pal_fixed_addr (u64 *global_unique_addr) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_FIXED_ADDR, 0, 0, 0);
+	if (global_unique_addr)
+		*global_unique_addr = iprv.v0;
+	return iprv.status; 
+}
+
+/* Get base frequency of the platform if generated by the processor */
+extern inline s64 
+ia64_pal_freq_base (u64 *platform_base_freq) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_FREQ_BASE, 0, 0, 0);
+	if (platform_base_freq)
+		*platform_base_freq = iprv.v0;
+	return iprv.status; 
+}
+
+/*
+ * Get the ratios for processor frequency, bus frequency and interval timer to
+ * to base frequency of the platform 
+ */
+extern inline s64 
+ia64_pal_freq_ratios (struct pal_freq_ratio *proc_ratio, struct pal_freq_ratio *bus_ratio,
+		      struct pal_freq_ratio *itc_ratio) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_FREQ_RATIOS, 0, 0, 0);
+	if (proc_ratio)
+		*(u64 *)proc_ratio = iprv.v0;
+	if (bus_ratio)
+		*(u64 *)bus_ratio = iprv.v1;
+	if (itc_ratio)
+		*(u64 *)itc_ratio = iprv.v2;
+	return iprv.status; 
+}
+
+/* Make the processor enter HALT or one of the implementation dependent low 
+ * power states where prefetching and execution are suspended and cache and
+ * TLB coherency is not maintained.
+ */
+extern inline s64 
+ia64_pal_halt (u64 halt_state) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_HALT, halt_state, 0, 0);
+	return iprv.status; 
+}
+typedef union pal_power_mgmt_info_u {
+	u64			ppmi_data;
+	struct {
+	       u64		exit_latency		: 16,
+				entry_latency		: 16,
+				power_consumption	: 32;
+	} pal_power_mgmt_info_s;
+} pal_power_mgmt_info_u_t;
+
+/* Return information about processor's optional power management capabilities. */
+extern inline s64 
+ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_HALT_INFO, (unsigned long) power_buf, 0, 0);
+	return iprv.status; 
+}
+
+/* Cause the processor to enter LIGHT HALT state, where prefetching and execution are
+ * suspended, but cache and TLB coherency is maintained.
+ */
+extern inline s64 
+ia64_pal_halt_light (void) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_HALT_LIGHT, 0, 0, 0);
+	return iprv.status; 
+}
+
+/* Clear all the processor error logging   registers and reset the indicator that allows
+ * the error logging registers to be written. This procedure also checks the pending
+ * machine check bit and pending INIT bit and reports their states.
+ */
+extern inline s64 
+ia64_pal_mc_clear_log (u64 *pending_vector) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MC_CLEAR_LOG, 0, 0, 0);
+	if (pending_vector)
+		*pending_vector = iprv.v0;
+	return iprv.status; 
+}
+
+/* Ensure that all outstanding transactions in a processor are completed or that any 
+ * MCA due to thes outstanding transaction is taken.
+ */
+extern inline s64 
+ia64_pal_mc_drain (void) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MC_DRAIN, 0, 0, 0);
+	return iprv.status; 
+}
+
+/* Return the machine check dynamic processor state */
+extern inline s64 
+ia64_pal_mc_dynamic_state (u64 offset, u64 *size, u64 *pds) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MC_DYNAMIC_STATE, offset, 0, 0);
+	if (size)
+		*size = iprv.v0;
+	if (pds)
+		*pds = iprv.v1;
+	return iprv.status; 
+}
+
+/* Return processor machine check information */
+extern inline s64 
+ia64_pal_mc_error_info (u64 info_index, u64 type_index, u64 *size, u64 *error_info) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MC_ERROR_INFO, info_index, type_index, 0);
+	if (size)
+		*size = iprv.v0;
+	if (error_info)
+		*error_info = iprv.v1;	
+	return iprv.status; 
+}
+
+/* Inform PALE_CHECK whether a machine check is expected so that PALE_CHECK willnot
+ * attempt to correct any expected machine checks.
+ */
+extern inline s64 
+ia64_pal_mc_expected (u64 expected, u64 *previous) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MC_EXPECTED, expected, 0, 0);
+	if (previous)
+		*previous = iprv.v0;
+	return iprv.status; 
+}
+
+/* Register a platform dependent location with PAL to which it can save
+ * minimal processor state in the event of a machine check or initialization
+ * event.
+ */
+extern inline s64
+ia64_pal_mc_register_mem (u64 physical_addr) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MC_REGISTER_MEM, physical_addr, 0, 0);
+	return iprv.status; 
+}
+
+/* Restore minimal architectural processor state, set CMC interrupt if necessary
+ * and resume execution
+ */
+extern inline s64 
+ia64_pal_mc_resume (u64 set_cmci, u64 save_ptr) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MC_RESUME, set_cmci, save_ptr, 0);
+	return iprv.status; 
+}
+
+/* Return the memory attributes implemented by the processor */
+extern inline s64 
+ia64_pal_mem_attrib (u64 *mem_attrib) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MEM_ATTRIB, 0, 0, 0);
+	if (mem_attrib)
+		*mem_attrib = iprv.v0;
+	return iprv.status; 
+}
+
+/* Return the amount of memory needed for second phase of processor
+ * self-test and the required alignment of memory.
+ */
+extern inline s64 
+ia64_pal_mem_for_test (u64 *bytes_needed, u64 *alignment)
+{
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_MEM_FOR_TEST, 0, 0, 0);
+	if (bytes_needed)
+		*bytes_needed = iprv.v0;
+	if (alignment)
+		*alignment = iprv.v1;
+	return iprv.status; 
+}
+
+typedef union pal_perf_mon_info_u {
+	u64			  ppmi_data;
+	struct {
+	       u64		generic		: 8,
+	       			width		: 8,
+		       		cycles		: 8,
+				retired		: 8,
+				reserved	: 32;
+	} pal_perf_mon_info_s;
+} pal_perf_mon_info_u_t;
+	       
+/* Return the performance monitor information about what can be counted
+ * and how to configure the monitors to count the desired events.
+ */
+extern inline s64 
+ia64_pal_perf_mon_info (u64 *pm_buffer, pal_perf_mon_info_u_t *pm_info) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_PERF_MON_INFO, (unsigned long) pm_buffer, 0, 0);
+	if (pm_info)
+		pm_info->ppmi_data = iprv.v0;
+	return iprv.status; 
+}
+
+/* Specifies the physical address of the processor interrupt block
+ * and I/O port space.
+ */
+extern inline s64 
+ia64_pal_platform_addr (u64 type, u64 physical_addr) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_PLATFORM_ADDR, type, physical_addr, 0);
+	return iprv.status; 
+}
+
+/* Set the SAL PMI entrypoint in memory */
+extern inline s64 
+ia64_pal_pmi_entrypoint (u64 sal_pmi_entry_addr) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_PMI_ENTRYPOINT, sal_pmi_entry_addr, 0, 0);
+	return iprv.status; 
+}
+
+#ifdef TBD
+struct pal_features_s;
+/* Provide information about configurable processor features */
+extern inline s64 
+ia64_pal_proc_get_features (struct pal_features_s *features_avail, 
+			    struct pal_features_s *features_status, 
+			    struct pal_features_s *features_control)
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_PROC_GET_FEATURES, 0, 0, 0);
+	return iprv.status; 
+}
+/* Enable/disable processor dependent features */
+extern inline s64 
+ia64_pal_proc_set_features (feature_select) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_PROC_SET_FEATURES, feature_select, 0, 0);
+	return iprv.status; 
+}
+
+#endif 
+/*
+ * Put everything in a struct so we avoid the global offset table whenever
+ * possible.
+ */
+typedef struct ia64_ptce_info_s {
+	u64		base;
+	u32 		count[2];
+	u32		stride[2];
+} ia64_ptce_info_t;
+
+/* Return the information required for the architected loop used to purge
+ * (initialize) the entire TC
+ */
+extern inline s64
+ia64_get_ptce (ia64_ptce_info_t *ptce)
+{
+	struct ia64_pal_retval iprv;
+
+	if (!ptce)
+		return -1;
+
+	PAL_CALL(iprv, PAL_PTCE_INFO, 0, 0, 0);
+	if (iprv.status == 0) {
+		ptce->base = iprv.v0;
+		ptce->count[0] = iprv.v1 >> 32;
+		ptce->count[1] = iprv.v1 & 0xffffffff;
+		ptce->stride[0] = iprv.v2 >> 32;
+		ptce->stride[1] = iprv.v2 & 0xffffffff;
+	}
+	return iprv.status;
+}
+
+/* Return info about implemented application and control registers. */
+extern inline s64 
+ia64_pal_register_info (u64 info_request, u64 *reg_info_1, u64 *reg_info_2) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_REGISTER_INFO, info_request, 0, 0);
+	if (reg_info_1)
+		*reg_info_1 = iprv.v0;
+	if (reg_info_2)
+		*reg_info_2 = iprv.v1;
+	return iprv.status;
+}	
+
+typedef union pal_hints_u {
+	u64			ph_data;
+	struct {
+	       u64		si		: 1,
+				li		: 1,
+				reserved	: 62;
+	} pal_hints_s;
+} pal_hints_u_t;
+
+/* Return information about the register stack and RSE for this processor 
+ * implementation.
+ */
+extern inline s64 
+ia64_pal_rse_info (u64 *num_phys_stacked, pal_hints_u_t *hints)
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_RSE_INFO, 0, 0, 0);
+	if (num_phys_stacked)
+		*num_phys_stacked = iprv.v0;
+	if (hints)
+		hints->ph_data = iprv.v1;
+	return iprv.status;	
+}
+
+/* Cause the processor to enter	SHUTDOWN state, where prefetching and execution are 
+ * suspended, but cause cache and TLB coherency to be maintained.
+ * This is usually called in IA-32 mode.
+ */
+extern inline s64 
+ia64_pal_shutdown (void) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_SHUTDOWN, 0, 0, 0);
+	return iprv.status; 
+}
+
+/* Perform the second phase of processor self-test. */
+extern inline s64 
+ia64_pal_test_proc (u64 test_addr, u64 test_size, u64 attributes, u64 *self_test_state)
+{
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_TEST_PROC, test_addr, test_size, attributes);
+	if (self_test_state)
+		*self_test_state = iprv.v0;
+	return iprv.status; 
+}
+
+typedef union  pal_version_u {
+	u64	pal_version_val;
+	struct {
+		u64	pv_pal_b_rev 		: 	8;
+		u64	pv_pal_b_model		:	8;
+		u64	pv_reserved1		:	8;
+		u64	pv_pal_vendor		:	8;
+		u64	pv_pal_a_rev		:	8;
+		u64	pv_pal_a_model		:	8;
+		u64	pv_reserved2		: 	16;
+	} pal_version_s;
+} pal_version_u_t;
+
+
+/* Return PAL version information */
+extern inline s64 
+ia64_pal_version (pal_version_u_t *pal_version) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_VERSION, 0, 0, 0);
+	if (pal_version)
+		pal_version->pal_version_val = iprv.v0;
+	return iprv.status; 
+}
+
+typedef union pal_tc_info_u {
+	u64			pti_val;
+	struct {
+	       u64		num_sets	:	8,
+				associativity	:	8,
+				num_entries	:	16,
+				pf		:	1,
+				unified		:	1,
+				reduce_tr	:	1,
+				reserved	:	29;
+	} pal_tc_info_s;
+} pal_tc_info_u_t;				
+				
+	       
+/* Return information about the virtual memory characteristics of the processor 
+ * implementation.
+ */
+extern inline s64 
+ia64_pal_vm_info (u64 tc_level, u64 tc_type,  pal_tc_info_u_t *tc_info, u64 *tc_pages)
+{
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_VM_INFO, tc_level, tc_type, 0);
+	if (tc_info)
+		tc_info->pti_val = iprv.v0;
+	if (tc_pages)
+		*tc_pages = iprv.v1;	
+	return iprv.status; 
+}
+
+/* Get page size information about the virtual memory characteristics of the processor 
+ * implementation.
+ */
+extern inline s64 
+ia64_pal_vm_page_size (u64 *tr_pages, u64 *vw_pages)
+{
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_VM_PAGE_SIZE, 0, 0, 0);
+	if (tr_pages)
+		*tr_pages = iprv.v0;
+	if (vw_pages)
+		*vw_pages = iprv.v1;	
+	return iprv.status; 
+}
+
+typedef union pal_vm_info_1_u {
+	u64			pvi1_val;
+	struct {
+		u64		vw		: 1,
+				phys_add_size	: 7,
+				key_size	: 16,
+				max_pkr		: 8,
+				hash_tag_id	: 8,
+				max_dtr_entry	: 8,
+				max_itr_entry	: 8,
+				max_unique_tcs	: 8,
+				num_tc_levels	: 8;
+	} pal_vm_info_1_s;
+} pal_vm_info_1_u_t;
+
+typedef union pal_vm_info_2_u {
+	u64			pvi2_val;
+	struct {
+		u64		impl_va_msb	: 8,
+				rid_size	: 8,
+				reserved	: 48;		
+	} pal_vm_info_2_s;
+} pal_vm_info_2_u_t;
+		
+/* Get summary information about the virtual memory characteristics of the processor 
+ * implementation.
+ */
+extern inline s64 
+ia64_pal_vm_summary (pal_vm_info_1_u_t *vm_info_1, pal_vm_info_2_u_t *vm_info_2) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_VM_SUMMARY, 0, 0, 0);
+	if (vm_info_1)
+		vm_info_1->pvi1_val = iprv.v0;
+	if (vm_info_2)
+		vm_info_2->pvi2_val = iprv.v1;
+	return iprv.status; 
+}
+
+typedef union pal_itr_valid_u {
+	u64			piv_val;
+	struct {
+	       u64		access_rights_valid	: 1,
+				priv_level_valid	: 1,
+				dirty_bit_valid		: 1,
+				mem_attr_valid		: 1,
+				reserved		: 60;
+	} pal_itr_valid_s;
+} pal_itr_valid_u_t;
+
+/* Read a translation register */
+extern inline s64 
+ia64_pal_vm_tr_read (u64 reg_num, u64 tr_type, u64 tr_buffer, pal_itr_valid_u_t *itr_valid) 
+{	
+	struct ia64_pal_retval iprv;
+	PAL_CALL(iprv, PAL_VM_TR_READ, reg_num, tr_type, tr_buffer);
+	if (itr_valid)
+		itr_valid->piv_val = iprv.v0;
+	return iprv.status; 
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_IA64_PAL_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/param.h linux/include/asm-ia64/param.h
--- v2.3.42/linux/include/asm-ia64/param.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/param.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,45 @@
+#ifndef _ASM_IA64_PARAM_H
+#define _ASM_IA64_PARAM_H
+
+/*
+ * Fundamental kernel parameters.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IA64_HP_SIM
+/*
+ * Yeah, simulating stuff is slow, so let us catch some breath between
+ * timer interrupts...
+ */
+# define HZ 20
+#endif
+
+#ifdef CONFIG_IA64_DIG
+# ifdef CONFIG_IA64_SOFTSDV_HACKS
+#  define HZ 20
+# else
+#  define HZ 100
+# endif
+#endif
+
+#ifndef HZ
+# define HZ	1024
+#endif
+
+#define EXEC_PAGESIZE	65536
+
+#ifndef NGROUPS
+# define NGROUPS	32
+#endif
+
+#ifndef NOGROUP
+# define NOGROUP	(-1)
+#endif
+
+#define MAXHOSTNAMELEN	64	/* max length of hostname */
+
+#endif /* _ASM_IA64_PARAM_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/pci.h linux/include/asm-ia64/pci.h
--- v2.3.42/linux/include/asm-ia64/pci.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/pci.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,148 @@
+#ifndef _ASM_IA64_PCI_H
+#define _ASM_IA64_PCI_H
+
+/*
+ * Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes or
+ * architectures with incomplete PCI setup by the loader.
+ */
+#define pcibios_assign_all_busses()     0
+
+#define PCIBIOS_MIN_IO		0x1000
+#define PCIBIOS_MIN_MEM		0x10000000
+
+/*
+ * Dynamic DMA mapping API.
+ * IA-64 has everything mapped statically.
+ */
+
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+
+struct pci_dev;
+
+/*
+ * Allocate and map kernel buffer using consistent mode DMA for a device.
+ * hwdev should be valid struct pci_dev pointer for PCI devices,
+ * NULL for PCI-like buses (ISA, EISA).
+ * Returns non-NULL cpu-view pointer to the buffer if successful and
+ * sets *dma_addrp to the pci side dma address as well, else *dma_addrp
+ * is undefined.
+ */
+extern void *pci_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle);
+
+/*
+ * Free and unmap a consistent DMA buffer.
+ * cpu_addr is what was returned from pci_alloc_consistent,
+ * size must be the same as what as passed into pci_alloc_consistent,
+ * and likewise dma_addr must be the same as what *dma_addrp was set to.
+ *
+ * References to the memory and mappings associated with cpu_addr/dma_addr
+ * past this call are illegal.
+ */
+extern void pci_free_consistent (struct pci_dev *hwdev, size_t size,
+				 void *vaddr, dma_addr_t dma_handle);
+
+/*
+ * Map a single buffer of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory
+ * until either pci_unmap_single or pci_dma_sync_single is performed.
+ */
+extern inline dma_addr_t
+pci_map_single (struct pci_dev *hwdev, void *ptr, size_t size)
+{
+	return virt_to_bus(ptr);
+}
+
+/*
+ * Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guarenteed to see
+ * whatever the device wrote there.
+ */
+extern inline void
+pci_unmap_single (struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size)
+{
+	/* Nothing to do */
+}
+
+/*
+ * Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+extern inline int
+pci_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+{
+	return nents;
+}
+
+/*
+ * Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+extern inline void
+pci_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+{
+	/* Nothing to do */
+}
+
+/*
+ * Make physical memory consistent for a single
+ * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, the
+ * device again owns the buffer.
+ */
+extern inline void
+pci_dma_sync_single (struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size)
+{
+	/* Nothing to do */
+}
+
+/*
+ * Make physical memory consistent for a set of streaming mode DMA
+ * translations after a transfer.
+ *
+ * The same as pci_dma_sync_single but for a scatter-gather list,
+ * same rules and usage.
+ */
+extern inline void
+pci_dma_sync_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems)
+{
+	/* Nothing to do */
+}
+
+/* These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg)	(virt_to_bus((sg)->address))
+#define sg_dma_len(sg)		((sg)->length)
+
+#endif /* _ASM_IA64_PCI_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/pgalloc.h linux/include/asm-ia64/pgalloc.h
--- v2.3.42/linux/include/asm-ia64/pgalloc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/pgalloc.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,257 @@
+#ifndef _ASM_IA64_PGALLOC_H
+#define _ASM_IA64_PGALLOC_H
+
+/*
+ * This file contains the functions and defines necessary to allocate
+ * page tables.
+ *
+ * This hopefully works with any (fixed) ia-64 page-size, as defined
+ * in <asm/page.h> (currently 8192).
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000, Goutham Rao <goutham.rao@intel.com>
+ */
+
+#include <linux/config.h>
+
+#include <linux/threads.h>
+
+#include <asm/mmu_context.h>
+#include <asm/processor.h>
+
+/*
+ * Very stupidly, we used to get new pgd's and pmd's, init their contents
+ * to point to the NULL versions of the next level page table, later on
+ * completely re-init them the same way, then free them up.  This wasted
+ * a lot of work and caused unnecessary memory traffic.  How broken...
+ * We fix this by caching them.
+ */
+#define pgd_quicklist		(my_cpu_data.pgd_quick)
+#define pmd_quicklist		(my_cpu_data.pmd_quick)
+#define pte_quicklist		(my_cpu_data.pte_quick)
+#define pgtable_cache_size	(my_cpu_data.pgtable_cache_sz)
+
+extern __inline__ pgd_t*
+get_pgd_slow (void)
+{
+	pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
+	if (ret)
+		clear_page(ret);
+	return ret;
+}
+
+extern __inline__ pgd_t*
+get_pgd_fast (void)
+{
+	unsigned long *ret = pgd_quicklist;
+
+	if (ret != NULL) {
+		pgd_quicklist = (unsigned long *)(*ret);
+		ret[0] = 0;
+		--pgtable_cache_size;
+	}
+	return (pgd_t *)ret;
+}
+
+extern __inline__ pgd_t*
+pgd_alloc (void)
+{
+	pgd_t *pgd;
+
+	pgd = get_pgd_fast();
+	if (!pgd)
+		pgd = get_pgd_slow();
+	return pgd;
+}
+
+extern __inline__ void
+free_pgd_fast (pgd_t *pgd)
+{
+	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+	pgd_quicklist = (unsigned long *) pgd;
+	++pgtable_cache_size;
+}
+
+extern __inline__ pmd_t *
+get_pmd_slow (void)
+{
+	pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+
+	if (pmd)
+		clear_page(pmd);
+	return pmd;
+}
+
+extern __inline__ pmd_t *
+get_pmd_fast (void)
+{
+	unsigned long *ret = (unsigned long *)pmd_quicklist;
+
+	if (ret != NULL) {
+		pmd_quicklist = (unsigned long *)(*ret);
+		ret[0] = 0;
+		--pgtable_cache_size;
+	}
+	return (pmd_t *)ret;
+}
+
+extern __inline__ void
+free_pmd_fast (pmd_t *pmd)
+{
+	*(unsigned long *)pmd = (unsigned long) pmd_quicklist;
+	pmd_quicklist = (unsigned long *) pmd;
+	++pgtable_cache_size;
+}
+
+extern __inline__ void
+free_pmd_slow (pmd_t *pmd)
+{
+	free_page((unsigned long)pmd);
+}
+
+extern pte_t *get_pte_slow (pmd_t *pmd, unsigned long address_preadjusted);
+
+extern __inline__ pte_t *
+get_pte_fast (void)
+{
+	unsigned long *ret = (unsigned long *)pte_quicklist;
+
+	if (ret != NULL) {
+		pte_quicklist = (unsigned long *)(*ret);
+		ret[0] = 0;
+		--pgtable_cache_size;
+	}
+	return (pte_t *)ret;
+}
+
+extern __inline__ void
+free_pte_fast (pte_t *pte)
+{
+	*(unsigned long *)pte = (unsigned long) pte_quicklist;
+	pte_quicklist = (unsigned long *) pte;
+	++pgtable_cache_size;
+}
+
+#define pte_free_kernel(pte)	free_pte_fast(pte)
+#define pte_free(pte)		free_pte_fast(pte)
+#define pmd_free_kernel(pmd)	free_pmd_fast(pmd)
+#define pmd_free(pmd)		free_pmd_fast(pmd)
+#define pgd_free(pgd)		free_pgd_fast(pgd)
+
+extern __inline__ pte_t*
+pte_alloc (pmd_t *pmd, unsigned long vmaddr)
+{
+	unsigned long offset;
+
+	offset = (vmaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	if (pmd_none(*pmd)) {
+		pte_t *pte_page = get_pte_fast();
+
+		if (!pte_page)
+			return get_pte_slow(pmd, offset);
+		pmd_set(pmd, pte_page);
+		return pte_page + offset;
+	}
+	if (pmd_bad(*pmd)) {
+		__handle_bad_pmd(pmd);
+		return NULL;
+	}
+	return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+extern __inline__ pmd_t*
+pmd_alloc (pgd_t *pgd, unsigned long vmaddr)
+{
+	unsigned long offset;
+
+	offset = (vmaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+	if (pgd_none(*pgd)) {
+		pmd_t *pmd_page = get_pmd_fast();
+
+		if (!pmd_page)
+			pmd_page = get_pmd_slow();
+		if (pmd_page) {
+			if (pgd_none(*pgd)) {
+				pgd_set(pgd, pmd_page);
+				return pmd_page + offset;
+			} else
+				free_pmd_fast(pmd_page);
+		} else
+			return NULL;
+	}
+	if (pgd_bad(*pgd)) {
+		__handle_bad_pgd(pgd);
+		return NULL;
+	}
+	return (pmd_t *) pgd_page(*pgd) + offset;
+}
+
+#define pte_alloc_kernel(pmd, addr)	pte_alloc(pmd, addr)
+#define pmd_alloc_kernel(pgd, addr)	pmd_alloc(pgd, addr)
+
+extern int do_check_pgt_cache (int, int);
+
+/*
+ * This establishes kernel virtual mappings (e.g., as a result of a
+ * vmalloc call).  Since ia-64 uses a separate kernel page table,
+ * there is nothing to do here... :)
+ */
+#define set_pgdir(vmaddr, entry)	do { } while(0)
+
+/*
+ * Now for some TLB flushing routines.  This is the kind of stuff that
+ * can be very expensive, so try to avoid them whenever possible.
+ */
+
+/*
+ * Flush everything (kernel mapping may also have changed due to
+ * vmalloc/vfree).
+ */
+extern void __flush_tlb_all (void);
+
+#ifdef CONFIG_SMP
+  extern void smp_flush_tlb_all (void);
+# define flush_tlb_all()	smp_flush_tlb_all()
+#else
+# define flush_tlb_all()	__flush_tlb_all()
+#endif
+
+/*
+ * Serialize usage of ptc.g:
+ */
+extern spinlock_t ptcg_lock;
+
+/*
+ * Flush a specified user mapping
+ */
+extern __inline__ void
+flush_tlb_mm (struct mm_struct *mm)
+{
+	if (mm) {
+		mm->context = 0;
+		if (mm == current->active_mm) {
+			/* This is called, e.g., as a result of exec().  */
+			get_new_mmu_context(mm);
+			reload_context(mm);
+		}
+	}
+}
+
+extern void flush_tlb_range (struct mm_struct *mm, unsigned long start, unsigned long end);
+
+/*
+ * Page-granular tlb flush.
+ *
+ * do a tbisd (type = 2) normally, and a tbis (type = 3)
+ * if it is an executable mapping.  We want to avoid the
+ * itlb flush, because that potentially also does a
+ * icache flush.
+ */
+static __inline__ void
+flush_tlb_page (struct vm_area_struct *vma, unsigned long addr)
+{
+	flush_tlb_range(vma->vm_mm, addr, addr + PAGE_SIZE);
+}
+
+#endif /* _ASM_IA64_PGALLOC_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/pgtable.h linux/include/asm-ia64/pgtable.h
--- v2.3.42/linux/include/asm-ia64/pgtable.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/pgtable.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,390 @@
+#ifndef _ASM_IA64_PGTABLE_H
+#define _ASM_IA64_PGTABLE_H
+
+/*
+ * This file contains the functions and defines necessary to modify and use
+ * the ia-64 page table tree.
+ *
+ * This hopefully works with any (fixed) ia-64 page-size, as defined
+ * in <asm/page.h> (currently 8192).
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/mman.h>
+#include <asm/page.h>
+#include <asm/types.h>
+
+/* Size of physical address space: */
+#define IA64_PHYS_BITS		50		/* EAS2.5 defines 50 bits of ppn */
+#define IA64_PHYS_SIZE		(__IA64_UL(1) << IA64_PHYS_BITS)
+
+/* Is ADDR a valid kernel address? */
+#define kern_addr_valid(addr)	((addr) >= TASK_SIZE)
+
+/* Is ADDR a valid physical address? */
+#define phys_addr_valid(addr)	((addr) < IA64_PHYS_SIZE)
+
+/*
+ * First, define the various bits in a PTE.  Note that the PTE format
+ * matches the VHPT short format, the firt doubleword of the VHPD long
+ * format, and the first doubleword of the TLB insertion format.
+ */
+#define _PAGE_P			(1 <<  0)	/* page present bit */
+#define _PAGE_MA_WB		(0x0 <<  2)	/* write back memory attribute */
+#define _PAGE_MA_UC		(0x4 <<  2)	/* uncacheable memory attribute */
+#define _PAGE_MA_UCE		(0x5 <<  2)	/* UC exported attribute */
+#define _PAGE_MA_WC		(0x6 <<  2)	/* write coalescing memory attribute */
+#define _PAGE_MA_NAT		(0x7 <<  2)	/* not-a-thing attribute */
+#define _PAGE_MA_MASK		(0x7 <<  2)
+#define _PAGE_PL_0		(0 <<  7)	/* privilege level 0 (kernel) */
+#define _PAGE_PL_1		(1 <<  7)	/* privilege level 1 (unused) */
+#define _PAGE_PL_2		(2 <<  7)	/* privilege level 2 (unused) */
+#define _PAGE_PL_3		(3 <<  7)	/* privilege level 3 (user) */
+#define _PAGE_PL_MASK		(3 <<  7)
+#define _PAGE_AR_R		(0 <<  9)	/* read only */
+#define _PAGE_AR_RX		(1 <<  9)	/* read & execute */
+#define _PAGE_AR_RW		(2 <<  9)	/* read & write */
+#define _PAGE_AR_RWX		(3 <<  9)	/* read, write & execute */
+#define _PAGE_AR_R_RW		(4 <<  9)	/* read / read & write */
+#define _PAGE_AR_RX_RWX		(5 <<  9)	/* read & exec / read, write & exec */
+#define _PAGE_AR_RWX_RW		(6 <<  9)	/* read, write & exec / read & write */
+#define _PAGE_AR_X_RX		(7 <<  9)	/* exec & promote / read & exec */
+#define _PAGE_AR_MASK		(7 <<  9)
+#define _PAGE_AR_SHIFT		9
+#define _PAGE_A			(1 <<  5)	/* page accessed bit */
+#define _PAGE_D			(1 <<  6)	/* page dirty bit */
+#define _PAGE_PPN_MASK		((IA64_PHYS_SIZE - 1) & ~0xfffUL)
+#define _PAGE_ED		(__IA64_UL(1) << 52)	/* exception deferral */
+#define _PAGE_PROTNONE		(__IA64_UL(1) << 63)
+
+#define _PFN_MASK		_PAGE_PPN_MASK
+#define _PAGE_CHG_MASK		(_PFN_MASK | _PAGE_A | _PAGE_D)
+
+#define _PAGE_SIZE_4K	12
+#define _PAGE_SIZE_8K	13
+#define _PAGE_SIZE_16K	14
+#define _PAGE_SIZE_64K	16
+#define _PAGE_SIZE_256K	18
+#define _PAGE_SIZE_1M	20
+#define _PAGE_SIZE_4M	22
+#define _PAGE_SIZE_16M	24
+#define _PAGE_SIZE_64M	26
+#define _PAGE_SIZE_256M	28
+
+#define __ACCESS_BITS		_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_MA_WB
+#define __DIRTY_BITS_NO_ED	_PAGE_A | _PAGE_P | _PAGE_D | _PAGE_MA_WB
+#define __DIRTY_BITS		_PAGE_ED | __DIRTY_BITS_NO_ED
+
+/*
+ * Definitions for first level:
+ *
+ * PGDIR_SHIFT determines what a first-level page table entry can map.
+ */
+#define PGDIR_SHIFT		(PAGE_SHIFT + 2*(PAGE_SHIFT-3))
+#define PGDIR_SIZE		(__IA64_UL(1) << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+#define PTRS_PER_PGD		(__IA64_UL(1) << (PAGE_SHIFT-3))
+#define USER_PTRS_PER_PGD	PTRS_PER_PGD
+
+/*
+ * Definitions for second level:
+ *
+ * PMD_SHIFT determines the size of the area a second-level page table
+ * can map.
+ */
+#define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3))
+#define PMD_SIZE	(__IA64_UL(1) << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+#define PTRS_PER_PMD	(__IA64_UL(1) << (PAGE_SHIFT-3))
+
+/*
+ * Definitions for third level:
+ */
+#define PTRS_PER_PTE	(__IA64_UL(1) << (PAGE_SHIFT-3))
+
+/* Number of pointers that fit on a page:  this will go away. */
+#define PTRS_PER_PAGE	(__IA64_UL(1) << (PAGE_SHIFT-3))
+
+# ifndef __ASSEMBLY__
+
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+
+/*
+ * All the normal masks have the "page accessed" bits on, as any time
+ * they are used, the page is accessed. They are cleared only by the
+ * page-out routines
+ */
+#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_A)
+#define PAGE_SHARED	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
+#define PAGE_READONLY	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
+#define PAGE_COPY	__pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
+#define PAGE_GATE	__pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
+#define PAGE_KERNEL	__pgprot(__DIRTY_BITS  | _PAGE_PL_0 | _PAGE_AR_RW)
+
+/*
+ * Next come the mappings that determine how mmap() protection bits
+ * (PROT_EXEC, PROT_READ, PROT_WRITE, PROT_NONE) get implemented.  The
+ * _P version gets used for a private shared memory segment, the _S
+ * version gets used for a shared memory segment with MAP_SHARED on.
+ * In a private shared memory segment, we do a copy-on-write if a task
+ * attempts to write to the page.
+ */
+	/* xwr */
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_READONLY	/* write to priv pg -> copy & make writable */
+#define __P011	PAGE_READONLY	/* ditto */
+#define __P100	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_X_RX)
+#define __P101	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX)
+#define __P110	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX)
+#define __P111	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX)
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED	/* we don't have (and don't need) write-only */
+#define __S011	PAGE_SHARED
+#define __S100	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_X_RX)
+#define __S101	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RX)
+#define __S110	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RWX)
+#define __S111	__pgprot(_PAGE_ED | _PAGE_A | _PAGE_P | _PAGE_PL_3 | _PAGE_AR_RWX)
+
+#define pgd_ERROR(e)	printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
+#define pmd_ERROR(e)	printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pte_ERROR(e)	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
+
+
+/*
+ * Some definitions to translate between mem_map, PTEs, and page
+ * addresses:
+ */
+
+/*
+ * Given a pointer to an mem_map[] entry, return the kernel virtual
+ * address corresponding to that page.
+ */
+#define page_address(page)	(PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+
+/*
+ * Given a PTE, return the index of the mem_map[] entry corresponding
+ * to the page frame the PTE.
+ */
+#define pte_pagenr(x)		((unsigned long) ((pte_val(x) & _PFN_MASK) >> PAGE_SHIFT))
+
+/*
+ * Now for some cache flushing routines.  This is the kind of stuff
+ * that can be very expensive, so try to avoid them whenever possible.
+ */
+
+/* Caches aren't brain-dead on the ia-64. */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(mm, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
+extern void ia64_flush_icache_page (unsigned long addr);
+
+#define flush_icache_page(pg)	ia64_flush_icache_page(page_address(pg))
+
+/*
+ * Now come the defines and routines to manage and access the three-level
+ * page table.
+ */
+
+/*
+ * On some architectures, special things need to be done when setting
+ * the PTE in a page table.  Nothing special needs to be on ia-64.
+ */
+#define set_pte(ptep, pteval)	(*(ptep) = (pteval))
+
+#define VMALLOC_START		(0xa000000000000000+2*PAGE_SIZE)
+#define VMALLOC_VMADDR(x)	((unsigned long)(x))
+#define VMALLOC_END		0xbfffffffffffffff
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero:  used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t ia64_bad_page (void);
+extern pmd_t *ia64_bad_pagetable (void);
+
+#define BAD_PAGETABLE	ia64_bad_pagetable()
+#define BAD_PAGE	ia64_bad_page()
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page,pgprot)							\
+({										\
+	pte_t __pte;								\
+										\
+	pte_val(__pte) = ((page - mem_map) << PAGE_SHIFT) | pgprot_val(pgprot);	\
+	__pte;									\
+})
+
+/* This takes a physical page address that is used by the remapping functions */
+#define mk_pte_phys(physpage, pgprot) \
+({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
+
+#define pte_modify(_pte, newprot) \
+	(__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
+
+#define page_pte_prot(page,prot)	mk_pte(page, prot)
+#define page_pte(page)			page_pte_prot(page, __pgprot(0))
+
+#define pte_none(pte) 			(!pte_val(pte))
+#define pte_present(pte)		(pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
+#define pte_clear(pte)			(pte_val(*(pte)) = 0UL)
+/* pte_page() returns the "struct page *" corresponding to the PTE: */
+#define pte_page(pte)			(mem_map + pte_pagenr(pte))
+
+#define pmd_set(pmdp, ptep) 		(pmd_val(*(pmdp)) = __pa(ptep))
+#define pmd_none(pmd)			(!pmd_val(pmd))
+#define pmd_bad(pmd)			(!phys_addr_valid(pmd_val(pmd)))
+#define pmd_present(pmd)		(pmd_val(pmd) != 0UL)
+#define pmd_clear(pmdp)			(pmd_val(*(pmdp)) = 0UL)
+#define pmd_page(pmd)			((unsigned long) __va(pmd_val(pmd) & _PFN_MASK))
+
+#define pgd_set(pgdp, pmdp)		(pgd_val(*(pgdp)) = __pa(pmdp))
+#define pgd_none(pgd)			(!pgd_val(pgd))
+#define pgd_bad(pgd)			(!phys_addr_valid(pgd_val(pgd)))
+#define pgd_present(pgd)		(pgd_val(pgd) != 0UL)
+#define pgd_clear(pgdp)			(pgd_val(*(pgdp)) = 0UL)
+#define pgd_page(pgd)			((unsigned long) __va(pgd_val(pgd) & _PFN_MASK))
+
+/*
+ * The following have defined behavior only work if pte_present() is true.
+ */
+#define pte_read(pte)		(((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) < 6)
+#define pte_write(pte)	((unsigned) (((pte_val(pte) & _PAGE_AR_MASK) >> _PAGE_AR_SHIFT) - 2) < 4)
+#define pte_dirty(pte)		(pte_val(pte) & _PAGE_D)
+#define pte_young(pte)		(pte_val(pte) & _PAGE_A)
+/*
+ * Note: we convert AR_RWX to AR_RX and AR_RW to AR_R by clearing the
+ * 2nd bit in the access rights:
+ */
+#define pte_wrprotect(pte)	(__pte(pte_val(pte) & ~_PAGE_AR_RW))
+#define pte_mkwrite(pte)	(__pte(pte_val(pte) | _PAGE_AR_RW))
+
+#define pte_mkold(pte)		(__pte(pte_val(pte) & ~_PAGE_A))
+#define pte_mkyoung(pte)	(__pte(pte_val(pte) | _PAGE_A))
+
+#define pte_mkclean(pte)	(__pte(pte_val(pte) & ~_PAGE_D))
+#define pte_mkdirty(pte)	(__pte(pte_val(pte) | _PAGE_D))
+
+/*
+ * Macro to make mark a page protection value as "uncacheable".  Note
+ * that "protection" is really a misnomer here as the protection value
+ * contains the memory attribute bits, dirty bits, and various other
+ * bits as well.
+ */
+#define pgprot_noncached(prot)	__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC)
+
+/* The offset in the 1-level directory is given by the 3 region bits
+   (61..63) and the seven level-1 bits (33-39).  */
+extern __inline__ pgd_t*
+pgd_offset (struct mm_struct *mm, unsigned long address)
+{
+	unsigned long region = address >> 61;
+	unsigned long l1index = (address >> PGDIR_SHIFT) & ((PTRS_PER_PGD >> 3) - 1);
+
+	return mm->pgd + ((region << (PAGE_SHIFT - 6)) | l1index);
+}
+
+/* In the kernel's mapped region we have a full 43 bit space available and completely
+   ignore the region number (since we know its in region number 5). */
+#define pgd_offset_k(addr) \
+	(init_mm.pgd + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)))
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir,addr) \
+	((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
+
+/* Find an entry in the third-level page table.. */
+#define pte_offset(dir,addr) \
+	((pte_t *) pmd_page(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+
+
+extern void __handle_bad_pgd (pgd_t *pgd);
+extern void __handle_bad_pmd (pmd_t *pmd);
+
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/*
+ * IA-64 doesn't have any external MMU info: the page tables contain
+ * all the necessary information.  However, we can use this macro
+ * to pre-install (override) a PTE that we know is needed anyhow.
+ *
+ * Asit says that on Itanium, it is generally faster to let the VHPT
+ * walker pick up a newly installed PTE (and VHPT misses should be
+ * extremely rare compared to normal misses).  Also, since
+ * pre-installing the PTE has the problem that we may evict another
+ * TLB entry needlessly because we don't know for sure whether we need
+ * to update the iTLB or dTLB, I tend to prefer this solution, too.
+ * Also, this avoids nasty issues with forward progress (what if the
+ * newly installed PTE gets replaced before we return to the previous
+ * execution context?).
+ *
+ */
+#if 0
+# define update_mmu_cache(vma,address,pte)
+#else
+# define update_mmu_cache(vma,address,pte)							\
+do {												\
+	/*											\
+	 * XXX fix me!!										\
+	 *											\
+	 * It's not clear this is a win.  We may end up pollute the				\
+	 * dtlb with itlb entries and vice versa (e.g., consider stack				\
+	 * pages that are normally marked executable).  It would be				\
+	 * better to insert the TLB entry for the TLB cache that we				\
+	 * know needs the new entry.  However, the update_mmu_cache()				\
+	 * arguments don't tell us whether we got here through a data				\
+	 * access or through an instruction fetch.  Talk to Linus to				\
+	 * fix this.										\
+	 *											\
+	 * If you re-enable this code, you must disable the ptc code in				\
+	 * Entry 20 of the ivt.									\
+	 */											\
+	unsigned long flags;									\
+												\
+	ia64_clear_ic(flags);									\
+	ia64_itc((vma->vm_flags & PROT_EXEC) ? 0x3 : 0x2, address, pte_val(pte), PAGE_SHIFT);	\
+	__restore_flags(flags);									\
+} while (0)
+#endif
+
+#define SWP_TYPE(entry)			(((entry).val >> 1) & 0xff)
+#define SWP_OFFSET(entry)		((entry).val >> 9)
+#define SWP_ENTRY(type,offset)		((swp_entry_t) { ((type) << 1) | ((offset) << 9) })
+#define pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x)		((pte_t) { (x).val })
+
+#define module_map	vmalloc
+#define module_unmap	vfree
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define PageSkip(page)		(0)
+
+#define io_remap_page_range remap_page_range	/* XXX is this right? */
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[1024];
+#define ZERO_PAGE(vaddr) (mem_map + MAP_NR(empty_zero_page))
+
+# endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_IA64_PGTABLE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/poll.h linux/include/asm-ia64/poll.h
--- v2.3.42/linux/include/asm-ia64/poll.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/poll.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,30 @@
+#ifndef _ASM_IA64_POLL_H
+#define _ASM_IA64_POLL_H
+
+/*
+ * poll(2) bit definitions.  Chosen to be compatible with Linux/x86.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define POLLIN		0x0001
+#define POLLPRI		0x0002
+#define POLLOUT		0x0004
+#define POLLERR		0x0008
+#define POLLHUP		0x0010
+#define POLLNVAL	0x0020
+
+#define POLLRDNORM	0x0040
+#define POLLRDBAND	0x0080
+#define POLLWRNORM	0x0100
+#define POLLWRBAND	0x0200
+#define POLLMSG		0x0400
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif /* _ASM_IA64_POLL_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/posix_types.h linux/include/asm-ia64/posix_types.h
--- v2.3.42/linux/include/asm-ia64/posix_types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/posix_types.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,121 @@
+#ifndef _ASM_IA64_POSIX_TYPES_H
+#define _ASM_IA64_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+typedef unsigned int	__kernel_dev_t;
+typedef unsigned int	__kernel_ino_t;
+typedef unsigned int	__kernel_mode_t;
+typedef unsigned int	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef long long	__kernel_loff_t;
+typedef int		__kernel_pid_t;
+typedef int		__kernel_ipc_pid_t;
+typedef unsigned int	__kernel_uid_t;
+typedef unsigned int	__kernel_gid_t;
+typedef unsigned long	__kernel_size_t;
+typedef long		__kernel_ssize_t;
+typedef long		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned long	__kernel_sigset_t;	/* at least 32 bits */
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+
+typedef struct {
+	int	val[2];
+} __kernel_fsid_t;
+
+typedef __kernel_uid_t __kernel_old_uid_t;
+typedef __kernel_gid_t __kernel_old_gid_t;
+typedef __kernel_uid_t __kernel_uid32_t;
+typedef __kernel_gid_t __kernel_gid32_t;
+
+# ifdef __KERNEL__
+
+#  ifndef __GNUC__
+
+#define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+#define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+#define	__FD_ISSET(d, set)	(((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
+#define	__FD_ZERO(set)	\
+  ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+
+#  else /* !__GNUC__ */
+
+/* With GNU C, use inline functions instead so args are evaluated only once: */
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, const __kernel_fd_set *p)
+{ 
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+{
+	unsigned long *tmp = p->fds_bits;
+	int i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+		      case 16:
+			tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+			tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+			return;
+
+		      case 8:
+			tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			return;
+
+		      case 4:
+			tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			return;
+		}
+	}
+	i = __FDSET_LONGS;
+	while (i) {
+		i--;
+		*tmp = 0;
+		tmp++;
+	}
+}
+
+#  endif /* !__GNUC__ */
+# endif /* __KERNEL__ */
+#endif /* _ASM_IA64_POSIX_TYPES_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/processor.h linux/include/asm-ia64/processor.h
--- v2.3.42/linux/include/asm-ia64/processor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/processor.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,786 @@
+#ifndef _ASM_IA64_PROCESSOR_H
+#define _ASM_IA64_PROCESSOR_H
+
+/*
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ *
+ * 11/24/98	S.Eranian	added ia64_set_iva()
+ * 12/03/99	D. Mosberger	implement thread_saved_pc() via kernel unwind API
+ */
+
+#include <linux/config.h>
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+#define IA64_NUM_DBG_REGS	8
+
+/*
+ * TASK_SIZE really is a mis-named.  It really is the maximum user
+ * space address (plus one).  On ia-64, there are five regions of 2TB
+ * each (assuming 8KB page size), for a total of 8TB of user virtual
+ * address space.
+ */
+#define TASK_SIZE		0xa000000000000000
+
+#ifdef CONFIG_IA32_SUPPORT
+# define TASK_UNMAPPED_BASE	0x40000000	/* XXX fix me! */
+#else
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	0x2000000000000000
+#endif
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/* Processor status register bits: */
+#define IA64_PSR_BE_BIT		1
+#define IA64_PSR_UP_BIT		2
+#define IA64_PSR_AC_BIT		3
+#define IA64_PSR_MFL_BIT	4
+#define IA64_PSR_MFH_BIT	5
+#define IA64_PSR_IC_BIT		13
+#define IA64_PSR_I_BIT		14
+#define IA64_PSR_PK_BIT		15
+#define IA64_PSR_DT_BIT		17
+#define IA64_PSR_DFL_BIT	18
+#define IA64_PSR_DFH_BIT	19
+#define IA64_PSR_SP_BIT		20
+#define IA64_PSR_PP_BIT		21
+#define IA64_PSR_DI_BIT		22
+#define IA64_PSR_SI_BIT		23
+#define IA64_PSR_DB_BIT		24
+#define IA64_PSR_LP_BIT		25
+#define IA64_PSR_TB_BIT		26
+#define IA64_PSR_RT_BIT		27
+/* The following are not affected by save_flags()/restore_flags(): */
+#define IA64_PSR_IS_BIT		34
+#define IA64_PSR_MC_BIT		35
+#define IA64_PSR_IT_BIT		36
+#define IA64_PSR_ID_BIT		37
+#define IA64_PSR_DA_BIT		38
+#define IA64_PSR_DD_BIT		39
+#define IA64_PSR_SS_BIT		40
+#define IA64_PSR_RI_BIT		41
+#define IA64_PSR_ED_BIT		43
+#define IA64_PSR_BN_BIT		44
+
+#define IA64_PSR_BE	(__IA64_UL(1) << IA64_PSR_BE_BIT)
+#define IA64_PSR_UP	(__IA64_UL(1) << IA64_PSR_UP_BIT)
+#define IA64_PSR_AC	(__IA64_UL(1) << IA64_PSR_AC_BIT)
+#define IA64_PSR_MFL	(__IA64_UL(1) << IA64_PSR_MFL_BIT)
+#define IA64_PSR_MFH	(__IA64_UL(1) << IA64_PSR_MFH_BIT)
+#define IA64_PSR_IC	(__IA64_UL(1) << IA64_PSR_IC_BIT)
+#define IA64_PSR_I	(__IA64_UL(1) << IA64_PSR_I_BIT)
+#define IA64_PSR_PK	(__IA64_UL(1) << IA64_PSR_PK_BIT)
+#define IA64_PSR_DT	(__IA64_UL(1) << IA64_PSR_DT_BIT)
+#define IA64_PSR_DFL	(__IA64_UL(1) << IA64_PSR_DFL_BIT)
+#define IA64_PSR_DFH	(__IA64_UL(1) << IA64_PSR_DFH_BIT)
+#define IA64_PSR_SP	(__IA64_UL(1) << IA64_PSR_SP_BIT)
+#define IA64_PSR_PP	(__IA64_UL(1) << IA64_PSR_PP_BIT)
+#define IA64_PSR_DI	(__IA64_UL(1) << IA64_PSR_DI_BIT)
+#define IA64_PSR_SI	(__IA64_UL(1) << IA64_PSR_SI_BIT)
+#define IA64_PSR_DB	(__IA64_UL(1) << IA64_PSR_DB_BIT)
+#define IA64_PSR_LP	(__IA64_UL(1) << IA64_PSR_LP_BIT)
+#define IA64_PSR_TB	(__IA64_UL(1) << IA64_PSR_TB_BIT)
+#define IA64_PSR_RT	(__IA64_UL(1) << IA64_PSR_RT_BIT)
+/* The following are not affected by save_flags()/restore_flags(): */
+#define IA64_PSR_IS	(__IA64_UL(1) << IA64_PSR_IS_BIT)
+#define IA64_PSR_MC	(__IA64_UL(1) << IA64_PSR_MC_BIT)
+#define IA64_PSR_IT	(__IA64_UL(1) << IA64_PSR_IT_BIT)
+#define IA64_PSR_ID	(__IA64_UL(1) << IA64_PSR_ID_BIT)
+#define IA64_PSR_DA	(__IA64_UL(1) << IA64_PSR_DA_BIT)
+#define IA64_PSR_DD	(__IA64_UL(1) << IA64_PSR_DD_BIT)
+#define IA64_PSR_SS	(__IA64_UL(1) << IA64_PSR_SS_BIT)
+#define IA64_PSR_RI	(__IA64_UL(3) << IA64_PSR_RI_BIT)
+#define IA64_PSR_ED	(__IA64_UL(1) << IA64_PSR_ED_BIT)
+#define IA64_PSR_BN	(__IA64_UL(1) << IA64_PSR_BN_BIT)
+
+/* User mask bits: */
+#define IA64_PSR_UM	(IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL | IA64_PSR_MFH)
+
+/* Default Control Register */
+#define IA64_DCR_PP_BIT		 0	/* privileged performance monitor default */
+#define IA64_DCR_BE_BIT		 1	/* big-endian default */
+#define IA64_DCR_LC_BIT		 2	/* ia32 lock-check enable */
+#define IA64_DCR_DM_BIT		 8	/* defer TLB miss faults */
+#define IA64_DCR_DP_BIT		 9	/* defer page-not-present faults */
+#define IA64_DCR_DK_BIT		10	/* defer key miss faults */
+#define IA64_DCR_DX_BIT		11	/* defer key permission faults */
+#define IA64_DCR_DR_BIT		12	/* defer access right faults */
+#define IA64_DCR_DA_BIT		13	/* defer access bit faults */
+#define IA64_DCR_DD_BIT		14	/* defer debug faults */
+
+#define IA64_DCR_PP	(__IA64_UL(1) << IA64_DCR_PP_BIT)
+#define IA64_DCR_BE	(__IA64_UL(1) << IA64_DCR_BE_BIT)
+#define IA64_DCR_LC	(__IA64_UL(1) << IA64_DCR_LC_BIT)
+#define IA64_DCR_DM	(__IA64_UL(1) << IA64_DCR_DM_BIT)
+#define IA64_DCR_DP	(__IA64_UL(1) << IA64_DCR_DP_BIT)
+#define IA64_DCR_DK	(__IA64_UL(1) << IA64_DCR_DK_BIT)
+#define IA64_DCR_DX	(__IA64_UL(1) << IA64_DCR_DX_BIT)
+#define IA64_DCR_DR	(__IA64_UL(1) << IA64_DCR_DR_BIT)
+#define IA64_DCR_DA	(__IA64_UL(1) << IA64_DCR_DA_BIT)
+#define IA64_DCR_DD	(__IA64_UL(1) << IA64_DCR_DD_BIT)
+
+/* Interrupt Status Register */
+#define IA64_ISR_X_BIT		32	/* execute access */
+#define IA64_ISR_W_BIT		33	/* write access */
+#define IA64_ISR_R_BIT		34	/* read access */
+#define IA64_ISR_NA_BIT		35	/* non-access */
+#define IA64_ISR_SP_BIT		36	/* speculative load exception */
+#define IA64_ISR_RS_BIT		37	/* mandatory register-stack exception */
+#define IA64_ISR_IR_BIT		38	/* invalid register frame exception */
+
+#define IA64_ISR_X	(__IA64_UL(1) << IA64_ISR_X_BIT)
+#define IA64_ISR_W	(__IA64_UL(1) << IA64_ISR_W_BIT)
+#define IA64_ISR_R	(__IA64_UL(1) << IA64_ISR_R_BIT)
+#define IA64_ISR_NA	(__IA64_UL(1) << IA64_ISR_NA_BIT)
+#define IA64_ISR_SP	(__IA64_UL(1) << IA64_ISR_SP_BIT)
+#define IA64_ISR_RS	(__IA64_UL(1) << IA64_ISR_RS_BIT)
+#define IA64_ISR_IR	(__IA64_UL(1) << IA64_ISR_IR_BIT)
+
+#define IA64_THREAD_FPH_VALID	(__IA64_UL(1) << 0)	/* floating-point high state valid? */
+#define IA64_THREAD_DBG_VALID	(__IA64_UL(1) << 1)	/* debug registers valid? */
+#define IA64_KERNEL_DEATH	(__IA64_UL(1) << 63)	/* used for die_if_kernel() recursion detection */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/smp.h>
+#include <linux/threads.h>
+
+#include <asm/fpu.h>
+#include <asm/offsets.h>
+#include <asm/page.h>
+#include <asm/rse.h>
+#include <asm/unwind.h>
+
+/* like above but expressed as bitfields for more efficient access: */
+struct ia64_psr {
+	__u64 reserved0 : 1;
+	__u64 be : 1;
+	__u64 up : 1;
+	__u64 ac : 1;
+	__u64 mfl : 1;
+	__u64 mfh : 1;
+	__u64 reserved1 : 7;
+	__u64 ic : 1;
+	__u64 i : 1;
+	__u64 pk : 1;
+	__u64 reserved2 : 1;
+	__u64 dt : 1;
+	__u64 dfl : 1;
+	__u64 dfh : 1;
+	__u64 sp : 1;
+	__u64 pp : 1;
+	__u64 di : 1;
+	__u64 si : 1;
+	__u64 db : 1;
+	__u64 lp : 1;
+	__u64 tb : 1;
+	__u64 rt : 1;
+	__u64 reserved3 : 4;
+	__u64 cpl : 2;
+	__u64 is : 1;
+	__u64 mc : 1;
+	__u64 it : 1;
+	__u64 id : 1;
+	__u64 da : 1;
+	__u64 dd : 1;
+	__u64 ss : 1;
+	__u64 ri : 2;
+	__u64 ed : 1;
+	__u64 bn : 1;
+	__u64 reserved4 : 19;
+};
+
+/*
+ * This shift should be large enough to be able to represent
+ * 1000000/itc_freq with good accuracy while being small enough to fit
+ * 1000000<<IA64_USEC_PER_CYC_SHIFT in 64 bits.
+ */
+#define IA64_USEC_PER_CYC_SHIFT	41
+
+/*
+ * CPU type, hardware bug flags, and per-CPU state.
+ */
+struct cpuinfo_ia64 {
+	__u64 *pgd_quick;
+	__u64 *pmd_quick;
+	__u64 *pte_quick;
+	__u64 pgtable_cache_sz;
+	/* CPUID-derived information: */
+	__u64 ppn;
+	__u64 features;
+	__u8 number;
+	__u8 revision;
+	__u8 model;
+	__u8 family;
+	__u8 archrev;
+	char vendor[16];
+	__u64 itc_freq;		/* frequency of ITC counter */
+	__u64 proc_freq;	/* frequency of processor */
+	__u64 cyc_per_usec;	/* itc_freq/1000000 */
+	__u64 usec_per_cyc;	/* 2^IA64_USEC_PER_CYC_SHIFT*1000000/itc_freq */
+#ifdef CONFIG_SMP
+	__u64 loops_per_sec;
+	__u64 ipi_count;
+	__u64 prof_counter;
+	__u64 prof_multiplier;
+#endif
+};
+
+#define my_cpu_data		cpu_data[smp_processor_id()]
+
+#ifdef CONFIG_SMP
+# define loops_per_sec()	my_cpu_data.loops_per_sec
+#else
+# define loops_per_sec()	loops_per_sec
+#endif
+
+extern struct cpuinfo_ia64 cpu_data[NR_CPUS];
+
+extern void identify_cpu (struct cpuinfo_ia64 *);
+extern void print_cpu_info (struct cpuinfo_ia64 *);
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+struct thread_struct {
+	__u64 ksp;			/* kernel stack pointer */
+	unsigned long flags;		/* various flags */
+	struct ia64_fpreg fph[96];	/* saved/loaded on demand */
+	__u64 dbr[IA64_NUM_DBG_REGS];
+	__u64 ibr[IA64_NUM_DBG_REGS];
+#ifdef CONFIG_IA32_SUPPORT
+	__u64 fsr;			/* IA32 floating pt status reg */
+	__u64 fcr;			/* IA32 floating pt control reg */
+	__u64 fir;			/* IA32 fp except. instr. reg */
+	__u64 fdr;			/* IA32 fp except. data reg */
+# define INIT_THREAD_IA32	, 0, 0, 0, 0
+#else
+# define INIT_THREAD_IA32
+#endif /* CONFIG_IA32_SUPPORT */
+};
+
+#define INIT_MMAP {								\
+	&init_mm, PAGE_OFFSET, PAGE_OFFSET + 0x10000000, NULL, PAGE_SHARED,	\
+        VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL				\
+}
+
+#define INIT_THREAD {					\
+	0,				/* ksp */	\
+	0,				/* flags */	\
+	{{{{0}}}, },			/* fph */	\
+	{0, },				/* dbr */	\
+	{0, }				/* ibr */	\
+	INIT_THREAD_IA32				\
+}
+
+#define start_thread(regs,new_ip,new_sp) do {					\
+	set_fs(USER_DS);							\
+	ia64_psr(regs)->cpl = 3;	/* set user mode */			\
+	ia64_psr(regs)->ri = 0;		/* clear return slot number */		\
+	regs->cr_iip = new_ip;							\
+	regs->ar_rsc = 0xf;		/* eager mode, privilege level 3 */	\
+	regs->r12 = new_sp - 16;	/* allocate 16 byte scratch area */	\
+	regs->ar_bspstore = IA64_RBS_BOT;					\
+	regs->ar_rnat = 0;							\
+	regs->loadrs = 0;							\
+} while (0)
+
+/* Forward declarations, a strange C thing... */
+struct mm_struct;
+struct task_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread (struct task_struct *);
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE 1: Only a kernel-only process (ie the swapper or direct
+ * descendants who haven't done an "execve()") should use this: it
+ * will work within a system call from a "real" process, but the
+ * process memory space will not be free'd until both the parent and
+ * the child have exited.
+ *
+ * NOTE 2: This MUST NOT be an inlined function.  Otherwise, we get
+ * into trouble in init/main.c when the child thread returns to
+ * do_basic_setup() and the timing is such that free_initmem() has
+ * been called already.
+ */
+extern int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags);
+
+/* Copy and release all segment info associated with a VM */
+#define copy_segments(tsk, mm)			do { } while (0)
+#define release_segments(mm)			do { } while (0)
+#define forget_segments()			do { } while (0)
+
+/* Get wait channel for task P.  */
+extern unsigned long get_wchan (struct task_struct *p);
+
+/* Return instruction pointer of blocked task TSK.  */
+#define KSTK_EIP(tsk)					\
+  ({							\
+	struct pt_regs *_regs = ia64_task_regs(tsk);	\
+	_regs->cr_iip + ia64_psr(_regs)->ri;		\
+  })
+
+/* Return stack pointer of blocked task TSK.  */
+#define KSTK_ESP(tsk)  ((tsk)->thread.ksp)
+
+static inline struct task_struct *
+ia64_get_fpu_owner (void)
+{
+	struct task_struct *t;
+	__asm__ ("mov %0=ar.k5" : "=r"(t));
+	return t;
+}
+
+static inline void
+ia64_set_fpu_owner (struct task_struct *t)
+{
+	__asm__ __volatile__ ("mov ar.k5=%0" :: "r"(t));
+}
+
+extern void __ia64_init_fpu (void);
+extern void __ia64_save_fpu (struct ia64_fpreg *fph);
+extern void __ia64_load_fpu (struct ia64_fpreg *fph);
+
+#define ia64_fph_enable()	__asm__ __volatile__ (";; rsm psr.dfh;; srlz.d;;" ::: "memory");
+#define ia64_fph_disable()	__asm__ __volatile__ (";; ssm psr.dfh;; srlz.d;;" ::: "memory");
+
+/* load fp 0.0 into fph */
+static inline void
+ia64_init_fpu (void) {
+	ia64_fph_enable();
+	__ia64_init_fpu();
+	ia64_fph_disable();
+}
+
+/* save f32-f127 at FPH */
+static inline void
+ia64_save_fpu (struct ia64_fpreg *fph) {
+	ia64_fph_enable();
+	__ia64_save_fpu(fph);
+	ia64_fph_disable();
+}
+
+/* load f32-f127 from FPH */
+static inline void
+ia64_load_fpu (struct ia64_fpreg *fph) {
+	ia64_fph_enable();
+	__ia64_load_fpu(fph);
+	ia64_fph_disable();
+}
+
+extern inline void
+ia64_fc (void *addr)
+{
+	__asm__ __volatile__ ("fc %0" :: "r"(addr) : "memory");
+}
+
+extern inline void
+ia64_sync_i (void)
+{
+	__asm__ __volatile__ (";; sync.i" ::: "memory");
+}
+
+extern inline void
+ia64_srlz_i (void)
+{
+	__asm__ __volatile__ (";; srlz.i ;;" ::: "memory");
+}
+
+extern inline void
+ia64_srlz_d (void)
+{
+	__asm__ __volatile__ (";; srlz.d" ::: "memory");
+}
+
+extern inline void
+ia64_set_rr (__u64 reg_bits, __u64 rr_val)
+{
+	__asm__ __volatile__ ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory");
+}
+
+extern inline __u64
+ia64_get_dcr (void)
+{
+	__u64 r;
+	__asm__ ("mov %0=cr.dcr" : "=r"(r));
+	return r;
+}
+
+extern inline void
+ia64_set_dcr (__u64 val)
+{
+	__asm__ __volatile__ ("mov cr.dcr=%0;;" :: "r"(val) : "memory");
+	ia64_srlz_d();
+}
+
+extern inline __u64
+ia64_get_lid (void)
+{
+	__u64 r;
+	__asm__ ("mov %0=cr.lid" : "=r"(r));
+	return r;
+}
+
+extern inline void
+ia64_invala (void)
+{
+	__asm__ __volatile__ ("invala" ::: "memory");
+}
+
+/*
+ * Save the processor status flags in FLAGS and then clear the
+ * interrupt collection and interrupt enable bits.
+ */
+#define ia64_clear_ic(flags)							\
+	__asm__ __volatile__ ("mov %0=psr;; rsm psr.i | psr.ic;; srlz.i;;"	\
+			      : "=r"(flags) :: "memory");
+
+/*
+ * Insert a translation into an instruction and/or data translation
+ * register.
+ */
+extern inline void
+ia64_itr (__u64 target_mask, __u64 tr_num,
+	  __u64 vmaddr, __u64 pte,
+	  __u64 log_page_size)
+{
+	__asm__ __volatile__ ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory");
+	__asm__ __volatile__ ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory");
+	if (target_mask & 0x1)
+		__asm__ __volatile__ ("itr.i itr[%0]=%1"
+				      :: "r"(tr_num), "r"(pte) : "memory");
+	if (target_mask & 0x2)
+		__asm__ __volatile__ (";;itr.d dtr[%0]=%1"
+				      :: "r"(tr_num), "r"(pte) : "memory");
+}
+
+/*
+ * Insert a translation into the instruction and/or data translation
+ * cache.
+ */
+extern inline void
+ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte,
+	  __u64 log_page_size)
+{
+	__asm__ __volatile__ ("mov cr.itir=%0" :: "r"(log_page_size << 2) : "memory");
+	__asm__ __volatile__ ("mov cr.ifa=%0;;" :: "r"(vmaddr) : "memory");
+	/* as per EAS2.6, itc must be the last instruction in an instruction group */
+	if (target_mask & 0x1)
+		__asm__ __volatile__ ("itc.i %0;;" :: "r"(pte) : "memory");
+	if (target_mask & 0x2)
+		__asm__ __volatile__ (";;itc.d %0;;" :: "r"(pte) : "memory");
+}
+
+/*
+ * Purge a range of addresses from instruction and/or data translation
+ * register(s).
+ */
+extern inline void
+ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size)
+{
+	if (target_mask & 0x1)
+		__asm__ __volatile__ ("ptr.i %0,%1" :: "r"(vmaddr), "r"(log_size << 2));
+	if (target_mask & 0x2)
+		__asm__ __volatile__ ("ptr.d %0,%1" :: "r"(vmaddr), "r"(log_size << 2));
+}
+
+/* Set the interrupt vector address.  The address must be suitably aligned (32KB).  */
+extern inline void
+ia64_set_iva (void *ivt_addr)
+{
+	__asm__ __volatile__ ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory");
+}
+
+/* Set the page table address and control bits.  */
+extern inline void
+ia64_set_pta (__u64 pta)
+{
+	/* Note: srlz.i implies srlz.d */
+	__asm__ __volatile__ ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory");
+}
+
+extern inline __u64
+ia64_get_cpuid (__u64 regnum)
+{
+	__u64 r;
+
+	__asm__ ("mov %0=cpuid[%r1]" : "=r"(r) : "rO"(regnum));
+	return r;
+}
+
+extern inline void
+ia64_eoi (void)
+{
+	__asm__ ("mov cr.eoi=r0;; srlz.d;;" ::: "memory");
+}
+
+extern __inline__ void
+ia64_set_lrr0 (__u8 vector, __u8 masked)
+{
+	if (masked > 1)
+		masked = 1;
+
+	__asm__ __volatile__ ("mov cr.lrr0=%0;; srlz.d"
+			      :: "r"((masked << 16) | vector) : "memory");
+}
+
+
+extern __inline__ void
+ia64_set_lrr1 (__u8 vector, __u8 masked)
+{
+	if (masked > 1)
+		masked = 1;
+
+	__asm__ __volatile__ ("mov cr.lrr1=%0;; srlz.d"
+			      :: "r"((masked << 16) | vector) : "memory");
+}
+
+extern __inline__ void
+ia64_set_pmv (__u64 val)
+{
+	__asm__ __volatile__ ("mov cr.pmv=%0" :: "r"(val) : "memory");
+}
+
+extern __inline__ __u64
+ia64_get_pmc (__u64 regnum)
+{
+	__u64 retval;
+
+	__asm__ __volatile__ ("mov %0=pmc[%1]" : "=r"(retval) : "r"(regnum));
+	return retval;
+}
+
+extern __inline__ void
+ia64_set_pmc (__u64 regnum, __u64 value)
+{
+	__asm__ __volatile__ ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value));
+}
+
+extern __inline__ __u64
+ia64_get_pmd (__u64 regnum)
+{
+	__u64 retval;
+
+	__asm__ __volatile__ ("mov %0=pmd[%1]" : "=r"(retval) : "r"(regnum));
+	return retval;
+}
+
+extern __inline__ void
+ia64_set_pmd (__u64 regnum, __u64 value)
+{
+	__asm__ __volatile__ ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value));
+}
+
+/*
+ * Given the address to which a spill occurred, return the unat bit
+ * number that corresponds to this address.
+ */
+extern inline __u64
+ia64_unat_pos (void *spill_addr)
+{
+	return ((__u64) spill_addr >> 3) & 0x3f;
+}
+
+/*
+ * Set the NaT bit of an integer register which was spilled at address
+ * SPILL_ADDR.  UNAT is the mask to be updated.
+ */
+extern inline void
+ia64_set_unat (__u64 *unat, void *spill_addr, unsigned long nat)
+{
+	__u64 bit = ia64_unat_pos(spill_addr);
+	__u64 mask = 1UL << bit;
+
+	*unat = (*unat & ~mask) | (nat << bit);
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ * Note that the only way T can block is through a call to schedule() -> switch_to().
+ */
+extern inline unsigned long
+thread_saved_pc (struct thread_struct *t)
+{
+	struct ia64_frame_info info;
+	/* XXX ouch: Linus, please pass the task pointer to thread_saved_pc() instead! */
+	struct task_struct *p = (void *) ((unsigned long) t - IA64_TASK_THREAD_OFFSET);
+
+	ia64_unwind_init_from_blocked_task(&info, p);
+	if (ia64_unwind_to_previous_frame(&info) < 0)
+		return 0;
+	return ia64_unwind_get_ip(&info);
+}
+
+/*
+ * Get the current instruction/program counter value.
+ */
+#define current_text_addr() \
+	({ void *_pc; __asm__ ("mov %0=ip" : "=r" (_pc)); _pc; })
+
+#define THREAD_SIZE	IA64_STK_OFFSET
+/* NOTE: The task struct and the stacks are allocated together.  */
+#define alloc_task_struct() \
+        ((struct task_struct *) __get_free_pages(GFP_KERNEL, IA64_TASK_STRUCT_LOG_NUM_PAGES))
+#define free_task_struct(p)     free_pages((unsigned long)(p), IA64_TASK_STRUCT_LOG_NUM_PAGES)
+#define get_task_struct(tsk)	atomic_inc(&mem_map[MAP_NR(tsk)].count)
+
+#define init_task	(init_task_union.task)
+#define init_stack	(init_task_union.stack)
+
+/*
+ * Set the correctable machine check vector register
+ */
+extern __inline__ void
+ia64_set_cmcv (__u64 val)
+{
+	__asm__ __volatile__ ("mov cr.cmcv=%0" :: "r"(val) : "memory");
+}
+
+/*
+ * Read the correctable machine check vector register
+ */
+extern __inline__ __u64
+ia64_get_cmcv (void)
+{
+	__u64 val;
+
+	__asm__ ("mov %0=cr.cmcv" : "=r"(val) :: "memory");
+	return val;
+}
+
+extern inline __u64
+ia64_get_ivr (void)
+{
+	__u64 r;
+	__asm__ __volatile__ ("srlz.d;; mov %0=cr.ivr;; srlz.d;;" : "=r"(r));
+	return r;
+}
+
+extern inline void
+ia64_set_tpr (__u64 val)
+{
+	__asm__ __volatile__ ("mov cr.tpr=%0" :: "r"(val));
+}
+
+extern inline __u64
+ia64_get_tpr (void)
+{
+	__u64 r;
+	__asm__ ("mov %0=cr.tpr" : "=r"(r));
+	return r;
+}
+
+extern __inline__ void
+ia64_set_irr0 (__u64 val)
+{
+	__asm__ __volatile__("mov cr.irr0=%0;;" :: "r"(val) : "memory");
+	ia64_srlz_d();
+}
+
+extern __inline__ __u64
+ia64_get_irr0 (void)
+{
+	__u64 val;
+
+	__asm__ ("mov %0=cr.irr0" : "=r"(val));
+	return val;
+}
+
+extern __inline__ void
+ia64_set_irr1 (__u64 val)
+{
+	__asm__ __volatile__("mov cr.irr1=%0;;" :: "r"(val) : "memory");
+	ia64_srlz_d();
+}
+
+extern __inline__ __u64
+ia64_get_irr1 (void)
+{
+	__u64 val;
+
+	__asm__ ("mov %0=cr.irr1" : "=r"(val));
+	return val;
+}
+
+extern __inline__ void
+ia64_set_irr2 (__u64 val)
+{
+	__asm__ __volatile__("mov cr.irr2=%0;;" :: "r"(val) : "memory");
+	ia64_srlz_d();
+}
+
+extern __inline__ __u64
+ia64_get_irr2 (void)
+{
+	__u64 val;
+
+	__asm__ ("mov %0=cr.irr2" : "=r"(val));
+	return val;
+}
+
+extern __inline__ void
+ia64_set_irr3 (__u64 val)
+{
+	__asm__ __volatile__("mov cr.irr3=%0;;" :: "r"(val) : "memory");
+	ia64_srlz_d();
+}
+
+extern __inline__ __u64
+ia64_get_irr3 (void)
+{
+	__u64 val;
+
+	__asm__ ("mov %0=cr.irr3" : "=r"(val));
+	return val;
+}
+
+extern __inline__ __u64
+ia64_get_gp(void)
+{
+	__u64 val;
+
+	__asm__ ("mov %0=gp" : "=r"(val));
+	return val;
+}
+
+/* XXX remove the handcoded version once we have a sufficiently clever compiler... */
+#ifdef SMART_COMPILER
+# define ia64_rotr(w,n)				\
+  ({						\
+	__u64 _w = (w), _n = (n);		\
+						\
+	(_w >> _n) | (_w << (64 - _n));		\
+  })
+#else
+# define ia64_rotr(w,n)							\
+  ({									\
+	__u64 result;							\
+	asm ("shrp %0=%1,%1,%2" : "=r"(result) : "r"(w), "i"(n));	\
+	result;								\
+  })
+#endif
+
+#define ia64_rotl(w,n)	ia64_rotr((w),(64)-(n))
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_IA64_PROCESSOR_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ptrace.h linux/include/asm-ia64/ptrace.h
--- v2.3.42/linux/include/asm-ia64/ptrace.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ptrace.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,240 @@
+#ifndef _ASM_IA64_PTRACE_H
+#define _ASM_IA64_PTRACE_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * 12/07/98	S. Eranian	added pt_regs & switch_stack
+ * 12/21/98	D. Mosberger	updated to match latest code
+ *  6/17/99	D. Mosberger	added second unat member to "struct switch_stack"
+ *
+ */
+/*
+ * When a user process is blocked, its state looks as follows:
+ *
+ *            +----------------------+	-------	IA64_STK_OFFSET
+ *     	      |			     |	 ^
+ *            | struct pt_regs       |	 |
+ *	      |			     |	 |
+ *            +----------------------+	 |
+ *	      |			     |	 |
+ *     	      |	   memory stack	     |	 |
+ *	      |	(growing downwards)  |	 |
+ *	      //.....................//	 |
+ *					 |
+ *	      //.....................//	 |
+ *	      |			     |	 |
+ *            +----------------------+	 |
+ *            | struct switch_stack  |	 |
+ *	      |			     |	 |
+ *	      +----------------------+	 |
+ *	      |			     |	 |
+ *	      //.....................//	 |
+ *					 |
+ *	      //.....................//	 |
+ *	      |			     |	 |
+ *	      |	 register stack	     |	 |
+ *	      |	(growing upwards)    |	 |
+ *            |			     |	 |
+ *	      +----------------------+	 |  ---	IA64_RBS_OFFSET
+ *	      |			     |	 |  ^
+ *            |  struct task_struct  |	 |  |
+ * current -> |			     |   |  |
+ *	      +----------------------+ -------
+ *
+ * Note that ar.ec is not saved explicitly in pt_reg or switch_stack.
+ * This is because ar.ec is saved as part of ar.pfs.
+ */
+
+#include <linux/config.h>
+
+#include <asm/fpu.h>
+#include <asm/offsets.h>
+
+/*
+ * Base-2 logarithm of number of pages to allocate per task structure
+ * (including register backing store and memory stack):
+ */
+#if defined(CONFIG_IA64_PAGE_SIZE_4KB)
+# define IA64_TASK_STRUCT_LOG_NUM_PAGES		3
+#elif defined(CONFIG_IA64_PAGE_SIZE_8KB)
+# define IA64_TASK_STRUCT_LOG_NUM_PAGES		2
+#elif defined(CONFIG_IA64_PAGE_SIZE_16KB)
+# define IA64_TASK_STRUCT_LOG_NUM_PAGES		1
+#else
+# define IA64_TASK_STRUCT_LOG_NUM_PAGES		0
+#endif
+
+#define IA64_RBS_OFFSET			((IA64_TASK_SIZE + 15) & ~15) 
+#define IA64_STK_OFFSET			((1 << IA64_TASK_STRUCT_LOG_NUM_PAGES)*PAGE_SIZE)
+
+#define INIT_TASK_SIZE			IA64_STK_OFFSET
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are saved on system
+ * calls.
+ *
+ * We don't save all floating point register because the kernel
+ * is compiled to use only a very small subset, so the other are
+ * untouched.
+ *
+ * THIS STRUCTURE MUST BE A MULTIPLE 16-BYTE IN SIZE
+ * (because the memory stack pointer MUST ALWAYS be aligned this way)
+ *
+ */
+struct pt_regs {
+	/* The following registers are saved by SAVE_MIN: */
+
+	unsigned long cr_ipsr;		/* interrupted task's psr */
+	unsigned long cr_iip;		/* interrupted task's instruction pointer */
+	unsigned long cr_ifs;		/* interrupted task's function state */
+
+	unsigned long ar_unat;		/* interrupted task's NaT register (preserved) */ 
+	unsigned long ar_pfs;		/* prev function state  */
+	unsigned long ar_rsc;		/* RSE configuration */
+	/* The following two are valid only if cr_ipsr.cpl > 0: */
+	unsigned long ar_rnat;		/* RSE NaT */ 
+	unsigned long ar_bspstore;	/* RSE bspstore */
+
+	unsigned long pr;		/* 64 predicate registers (1 bit each) */
+	unsigned long b6;		/* scratch */
+	unsigned long loadrs;		/* size of dirty partition << 16 */
+
+	unsigned long r1;		/* the gp pointer */
+	unsigned long r2;		/* scratch */
+	unsigned long r3;		/* scratch */
+	unsigned long r12;		/* interrupted task's memory stack pointer */
+	unsigned long r13;		/* thread pointer */
+	unsigned long r14;		/* scratch */
+	unsigned long r15;		/* scratch */
+
+	unsigned long r8;		/* scratch (return value register 0) */
+	unsigned long r9;		/* scratch (return value register 1) */
+	unsigned long r10;		/* scratch (return value register 2) */
+	unsigned long r11;		/* scratch (return value register 3) */
+
+	/* The following registers are saved by SAVE_REST: */
+
+	unsigned long r16;		/* scratch */
+	unsigned long r17;		/* scratch */
+	unsigned long r18;		/* scratch */
+	unsigned long r19;		/* scratch */
+	unsigned long r20;		/* scratch */
+	unsigned long r21;		/* scratch */
+	unsigned long r22;		/* scratch */
+	unsigned long r23;		/* scratch */
+	unsigned long r24;		/* scratch */
+	unsigned long r25;		/* scratch */
+	unsigned long r26;		/* scratch */
+	unsigned long r27;		/* scratch */
+	unsigned long r28;		/* scratch */
+	unsigned long r29;		/* scratch */
+	unsigned long r30;		/* scratch */
+	unsigned long r31;		/* scratch */
+
+	unsigned long ar_ccv;		/* compare/exchange value  */
+	unsigned long ar_fpsr;		/* floating point status*/
+
+	unsigned long b0;		/* return pointer (bp) */
+	unsigned long b7;		/* scratch */
+	/*
+	 * Floating point registers that the kernel considers
+	 * scratch:
+	 */
+	struct ia64_fpreg f6;		/* scratch*/
+	struct ia64_fpreg f7;		/* scratch*/
+	struct ia64_fpreg f8;		/* scratch*/
+	struct ia64_fpreg f9;		/* scratch*/
+};
+
+/*
+ * This structure contains the addition registers that need to
+ * preserved across a context switch.  This generally consists of
+ * "preserved" registers.
+ */
+struct switch_stack {
+	unsigned long caller_unat;	/* user NaT collection register (preserved) */ 
+	unsigned long ar_fpsr;		/* floating-point status register */
+
+	struct ia64_fpreg f2;		/* preserved */
+	struct ia64_fpreg f3;		/* preserved */
+	struct ia64_fpreg f4;		/* preserved */
+	struct ia64_fpreg f5;		/* preserved */
+
+	struct ia64_fpreg f10;		/* scratch, but untouched by kernel */
+	struct ia64_fpreg f11;		/* scratch, but untouched by kernel */
+	struct ia64_fpreg f12;		/* scratch, but untouched by kernel */
+	struct ia64_fpreg f13;		/* scratch, but untouched by kernel */
+	struct ia64_fpreg f14;		/* scratch, but untouched by kernel */
+	struct ia64_fpreg f15;		/* scratch, but untouched by kernel */
+	struct ia64_fpreg f16;		/* preserved */
+	struct ia64_fpreg f17;		/* preserved */
+	struct ia64_fpreg f18;		/* preserved */
+	struct ia64_fpreg f19;		/* preserved */
+	struct ia64_fpreg f20;		/* preserved */
+	struct ia64_fpreg f21;		/* preserved */
+	struct ia64_fpreg f22;		/* preserved */
+	struct ia64_fpreg f23;		/* preserved */
+	struct ia64_fpreg f24;		/* preserved */
+	struct ia64_fpreg f25;		/* preserved */
+	struct ia64_fpreg f26;		/* preserved */
+	struct ia64_fpreg f27;		/* preserved */
+	struct ia64_fpreg f28;		/* preserved */
+	struct ia64_fpreg f29;		/* preserved */
+	struct ia64_fpreg f30;		/* preserved */
+	struct ia64_fpreg f31;		/* preserved */
+
+	unsigned long r4;		/* preserved */
+	unsigned long r5;		/* preserved */
+	unsigned long r6;		/* preserved */
+	unsigned long r7;		/* preserved */
+
+	unsigned long b0;		/* so we can force a direct return in copy_thread */
+	unsigned long b1;
+	unsigned long b2;
+	unsigned long b3;
+	unsigned long b4;
+	unsigned long b5;
+
+	unsigned long ar_pfs;		/* previous function state */
+	unsigned long ar_lc;		/* loop counter (preserved) */
+	unsigned long ar_unat;		/* NaT bits for r4-r7 */
+	unsigned long ar_rnat;		/* RSE NaT collection register */ 
+	unsigned long ar_bspstore;	/* RSE dirty base (preserved) */
+	unsigned long pr;		/* 64 predicate registers (1 bit each) */
+};
+
+#ifdef __KERNEL__
+  /* given a pointer to a task_struct, return the user's pt_regs */
+# define ia64_task_regs(t)		(((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
+# define ia64_psr(regs)			((struct ia64_psr *) &(regs)->cr_ipsr)
+# define user_mode(regs)		(((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0)
+
+  struct task_struct;			/* forward decl */
+
+  extern void show_regs (struct pt_regs *);
+  extern long ia64_peek (struct pt_regs *, struct task_struct *, unsigned long addr, long *val);
+  extern long ia64_poke (struct pt_regs *, struct task_struct *, unsigned long addr, long val);
+
+  /* get nat bits for r1-r31 such that bit N==1 iff rN is a NaT */
+  extern long ia64_get_nat_bits (struct pt_regs *pt, struct switch_stack *sw);
+  /* put nat bits for r1-r31 such that rN is a NaT iff bit N==1 */
+  extern void ia64_put_nat_bits (struct pt_regs *pt, struct switch_stack *sw, unsigned long nat);
+
+  extern void ia64_increment_ip (struct pt_regs *pt);
+  extern void ia64_decrement_ip (struct pt_regs *pt);
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * The number chosen here is somewhat arbitrary but absolutely MUST
+ * not overlap with any of the number assigned in <linux/ptrace.h>.
+ */
+#define PTRACE_SINGLEBLOCK	12	/* resume execution until next branch */
+
+#endif /* _ASM_IA64_PTRACE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/ptrace_offsets.h linux/include/asm-ia64/ptrace_offsets.h
--- v2.3.42/linux/include/asm-ia64/ptrace_offsets.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/ptrace_offsets.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,216 @@
+#ifndef _ASM_IA64_PTRACE_OFFSETS_H
+#define _ASM_IA64_PTRACE_OFFSETS_H
+
+/*
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+/*
+ * The "uarea" that can be accessed via PEEKUSER and POKEUSER is a
+ * virtual structure that would have the following definition:
+ *
+ *	struct uarea {
+ *		struct ia64_fpreg fph[96];		// f32-f127
+ *		struct switch_stack sw;
+ *		struct pt_regs pt;
+ *		unsigned long rsvd1[358];
+ *		unsigned long dbr[8];
+ *		unsigned long rsvd2[252];
+ *		unsigned long ibr[8];
+ *	}
+ */
+
+/* fph: */
+#define PT_F32			0x0000
+#define PT_F33			0x0010
+#define PT_F34			0x0020
+#define PT_F35			0x0030
+#define PT_F36			0x0040
+#define PT_F37			0x0050
+#define PT_F38			0x0060
+#define PT_F39			0x0070
+#define PT_F40			0x0080
+#define PT_F41			0x0090
+#define PT_F42			0x00a0
+#define PT_F43			0x00b0
+#define PT_F44			0x00c0
+#define PT_F45			0x00d0
+#define PT_F46			0x00e0
+#define PT_F47			0x00f0
+#define PT_F48			0x0100
+#define PT_F49			0x0110
+#define PT_F50			0x0120
+#define PT_F51			0x0130
+#define PT_F52			0x0140
+#define PT_F53			0x0150
+#define PT_F54			0x0160
+#define PT_F55			0x0170
+#define PT_F56			0x0180
+#define PT_F57			0x0190
+#define PT_F58			0x01a0
+#define PT_F59			0x01b0
+#define PT_F60			0x01c0
+#define PT_F61			0x01d0
+#define PT_F62			0x01e0
+#define PT_F63			0x01f0
+#define PT_F64			0x0200
+#define PT_F65			0x0210
+#define PT_F66			0x0220
+#define PT_F67			0x0230
+#define PT_F68			0x0240
+#define PT_F69			0x0250
+#define PT_F70			0x0260
+#define PT_F71			0x0270
+#define PT_F72			0x0280
+#define PT_F73			0x0290
+#define PT_F74			0x02a0
+#define PT_F75			0x02b0
+#define PT_F76			0x02c0
+#define PT_F77			0x02d0
+#define PT_F78			0x02e0
+#define PT_F79			0x02f0
+#define PT_F80			0x0300
+#define PT_F81			0x0310
+#define PT_F82			0x0320
+#define PT_F83			0x0330
+#define PT_F84			0x0340
+#define PT_F85			0x0350
+#define PT_F86			0x0360
+#define PT_F87			0x0370
+#define PT_F88			0x0380
+#define PT_F89			0x0390
+#define PT_F90			0x03a0
+#define PT_F91			0x03b0
+#define PT_F92			0x03c0
+#define PT_F93			0x03d0
+#define PT_F94			0x03e0
+#define PT_F95			0x03f0
+#define PT_F96			0x0400
+#define PT_F97			0x0410
+#define PT_F98			0x0420
+#define PT_F99			0x0430
+#define PT_F100			0x0440
+#define PT_F101			0x0450
+#define PT_F102			0x0460
+#define PT_F103			0x0470
+#define PT_F104			0x0480
+#define PT_F105			0x0490
+#define PT_F106			0x04a0
+#define PT_F107			0x04b0
+#define PT_F108			0x04c0
+#define PT_F109			0x04d0
+#define PT_F110			0x04e0
+#define PT_F111			0x04f0
+#define PT_F112			0x0500
+#define PT_F113			0x0510
+#define PT_F114			0x0520
+#define PT_F115			0x0530
+#define PT_F116			0x0540
+#define PT_F117			0x0550
+#define PT_F118			0x0560
+#define PT_F119			0x0570
+#define PT_F120			0x0580
+#define PT_F121			0x0590
+#define PT_F122			0x05a0
+#define PT_F123			0x05b0
+#define PT_F124			0x05c0
+#define PT_F125			0x05d0
+#define PT_F126			0x05e0
+#define PT_F127			0x05f0
+/* switch stack: */
+#define PT_CALLER_UNAT		0x0600
+#define PT_KERNEL_FPSR		0x0608
+#define PT_F2			0x0610
+#define PT_F3			0x0620
+#define PT_F4			0x0630
+#define PT_F5			0x0640
+#define PT_F10			0x0650
+#define PT_F11			0x0660
+#define PT_F12			0x0670
+#define PT_F13			0x0680
+#define PT_F14			0x0690
+#define PT_F15			0x06a0
+#define PT_F16			0x06b0
+#define PT_F17			0x06c0
+#define PT_F18			0x06d0
+#define PT_F19			0x06e0
+#define PT_F20			0x06f0
+#define PT_F21			0x0700
+#define PT_F22			0x0710
+#define PT_F23			0x0720
+#define PT_F24			0x0730
+#define PT_F25			0x0740
+#define PT_F26			0x0750
+#define PT_F27			0x0760
+#define PT_F28			0x0770
+#define PT_F29			0x0780
+#define PT_F30			0x0790
+#define PT_F31			0x07a0
+#define PT_R4			0x07b0
+#define PT_R5			0x07b8
+#define PT_R6			0x07c0
+#define PT_R7			0x07c8
+#define PT_K_B0			0x07d0
+#define PT_B1			0x07d8
+#define PT_B2			0x07e0
+#define PT_B3			0x07e8
+#define PT_B4			0x07f0
+#define PT_B5			0x07f8
+#define PT_K_AR_PFS		0x0800
+#define PT_AR_LC		0x0808
+#define PT_K_AR_UNAT		0x0810
+#define PT_K_AR_RNAT		0x0818
+#define PT_K_AR_BSPSTORE	0x0820
+#define PT_K_PR			0x0828
+/* pt_regs */
+#define PT_CR_IPSR		0x0830
+#define PT_CR_IIP		0x0838
+#define PT_CR_IFS		0x0840
+#define PT_AR_UNAT		0x0848
+#define PT_AR_PFS		0x0858
+#define PT_AR_RSC		0x0858
+#define PT_AR_RNAT		0x0868
+#define PT_AR_BSPSTORE		0x0868
+#define PT_PR			0x0870
+#define PT_B6			0x0878
+#define PT_AR_BSP		0x0880
+#define PT_R1			0x0888
+#define PT_R2			0x0890
+#define PT_R3			0x0898
+#define PT_R12			0x08a0
+#define PT_R13			0x08a8
+#define PT_R14			0x08b0
+#define PT_R15			0x08b8
+#define PT_R8 			0x08c0
+#define PT_R9			0x08c8
+#define PT_R10			0x08d0
+#define PT_R11			0x08d8
+#define PT_R16			0x08e0
+#define PT_R17			0x08e8
+#define PT_R18			0x08f0
+#define PT_R19			0x08f8
+#define PT_R20			0x0900
+#define PT_R21			0x0908
+#define PT_R22			0x0910
+#define PT_R23			0x0918
+#define PT_R24			0x0920
+#define PT_R25			0x0928
+#define PT_R26			0x0930
+#define PT_R27			0x0938
+#define PT_R28			0x0940
+#define PT_R29			0x0948
+#define PT_R30			0x0950
+#define PT_R31			0x0958
+#define PT_AR_CCV		0x0960
+#define PT_AR_FPSR		0x0968
+#define PT_B0			0x0970
+#define PT_B7			0x0978
+#define PT_F6			0x0980
+#define PT_F7			0x0990
+#define PT_F8			0x09a0
+#define PT_F9			0x09b0
+
+#define PT_DBR			0x2000	/* data breakpoint registers */
+#define PT_IBR			0x3000	/* instruction breakpoint registers */
+
+#endif /* _ASM_IA64_PTRACE_OFFSETS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/resource.h linux/include/asm-ia64/resource.h
--- v2.3.42/linux/include/asm-ia64/resource.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/resource.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,48 @@
+#ifndef _ASM_IA64_RESOURCE_H
+#define _ASM_IA64_RESOURCE_H
+
+/*
+ * Resource limits
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_RSS	5		/* max resident set size */
+#define RLIMIT_NPROC	6		/* max number of processes */
+#define RLIMIT_NOFILE	7		/* max number of open files */
+#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
+#define RLIMIT_AS	9		/* address space limit */
+
+#define RLIM_NLIMITS	10
+
+/*
+ * SuS says limits have to be unsigned.
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY  (~0UL)
+
+# ifdef __KERNEL__
+
+#define INIT_RLIMITS					\
+{							\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{      _STK_LIM, RLIM_INFINITY },		\
+	{             0, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{             0,             0 },		\
+	{      INR_OPEN,     INR_OPEN  },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+}
+
+# endif /* __KERNEL__ */
+
+#endif /* _ASM_IA64_RESOURCE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/rse.h linux/include/asm-ia64/rse.h
--- v2.3.42/linux/include/asm-ia64/rse.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/rse.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,66 @@
+#ifndef _ASM_IA64_RSE_H
+#define _ASM_IA64_RSE_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Register stack engine related helper functions.  This file may be
+ * used in applications, so be careful about the name-space and give
+ * some consideration to non-GNU C compilers (though __inline__ is
+ * fine).
+ */
+
+static __inline__ unsigned long
+ia64_rse_slot_num (unsigned long *addr)
+{
+	return (((unsigned long) addr) >> 3) & 0x3f;
+}
+
+/*
+ * Return TRUE if ADDR is the address of an RNAT slot.
+ */
+static __inline__ unsigned long
+ia64_rse_is_rnat_slot (unsigned long *addr)
+{
+	return ia64_rse_slot_num(addr) == 0x3f;
+}
+
+/*
+ * Returns the address of the RNAT slot that covers the slot at
+ * address SLOT_ADDR.
+ */
+static __inline__ unsigned long *
+ia64_rse_rnat_addr (unsigned long *slot_addr)
+{
+	return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));
+}
+
+/*
+ * Calcuate the number of registers in the dirty partition starting at
+ * BSPSTORE with a size of DIRTY bytes.  This isn't simply DIRTY
+ * divided by eight because the 64th slot is used to store ar.rnat.
+ */
+static __inline__ unsigned long
+ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)
+{
+	unsigned long slots = (bsp - bspstore);
+
+	return slots - (ia64_rse_slot_num(bspstore) + slots)/0x40;
+}
+
+/*
+ * The inverse of the above: given bspstore and the number of
+ * registers, calculate ar.bsp.
+ */
+static __inline__ unsigned long *
+ia64_rse_skip_regs (unsigned long *addr, long num_regs)
+{
+	long delta = ia64_rse_slot_num(addr) + num_regs;
+
+	if (num_regs < 0)
+		delta -= 0x3e;
+	return addr + num_regs + delta/0x3f;
+}
+
+#endif /* _ASM_IA64_RSE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/sal.h linux/include/asm-ia64/sal.h
--- v2.3.42/linux/include/asm-ia64/sal.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/sal.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,486 @@
+#ifndef _ASM_IA64_SAL_H
+#define _ASM_IA64_SAL_H
+
+/*
+ * System Abstraction Layer definitions.
+ *
+ * This is based on version 2.5 of the manual "IA-64 System
+ * Abstraction Layer".
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
+ *
+ * 99/09/29 davidm	Updated for SAL 2.6.
+ */
+
+#include <linux/config.h>
+
+#include <asm/pal.h>
+#include <asm/system.h>
+
+extern spinlock_t sal_lock;
+
+#ifdef __GCC_MULTIREG_RETVALS__
+  /* If multi-register return values are returned according to the
+     ia-64 calling convention, we can call ia64_sal directly.  */
+# define __SAL_CALL(result,args...)	result = (*ia64_sal)(args)
+#else
+  /* If multi-register return values are returned through an aggregate
+     allocated in the caller, we need to use the stub implemented in
+     sal-stub.S.  */
+  extern struct ia64_sal_retval ia64_sal_stub (u64 index, ...);
+# define __SAL_CALL(result,args...)	result = ia64_sal_stub(args)
+#endif
+
+#ifdef CONFIG_SMP
+# define SAL_CALL(result,args...) do {		\
+	  spin_lock(&sal_lock);			\
+	  __SAL_CALL(result,args);		\
+	  spin_unlock(&sal_lock);		\
+} while (0)
+#else
+# define SAL_CALL(result,args...)	__SAL_CALL(result,args)
+#endif
+
+#define SAL_SET_VECTORS			0x01000000
+#define SAL_GET_STATE_INFO		0x01000001
+#define SAL_GET_STATE_INFO_SIZE		0x01000002
+#define SAL_CLEAR_STATE_INFO		0x01000003
+#define SAL_MC_RENDEZ			0x01000004
+#define SAL_MC_SET_PARAMS		0x01000005
+#define SAL_REGISTER_PHYSICAL_ADDR	0x01000006
+
+#define SAL_CACHE_FLUSH			0x01000008
+#define SAL_CACHE_INIT			0x01000009
+#define SAL_PCI_CONFIG_READ		0x01000010
+#define SAL_PCI_CONFIG_WRITE		0x01000011
+#define SAL_FREQ_BASE			0x01000012
+
+#define SAL_UPDATE_PAL			0x01000020
+
+struct ia64_sal_retval {
+	/*
+	 * A zero status value indicates call completed without error.
+	 * A negative status value indicates reason of call failure.
+	 * A positive status value indicates success but an
+	 * informational value should be printed (e.g., "reboot for
+	 * change to take effect").
+	 */
+	s64 	status;
+	u64 	v0;
+	u64 	v1;
+	u64 	v2;
+};
+
+typedef struct ia64_sal_retval (*ia64_sal_handler) (u64, ...);
+
+enum {
+	SAL_FREQ_BASE_PLATFORM = 0,
+	SAL_FREQ_BASE_INTERVAL_TIMER = 1,
+	SAL_FREQ_BASE_REALTIME_CLOCK = 2
+};
+
+/*
+ * The SAL system table is followed by a variable number of variable
+ * length descriptors.  The structure of these descriptors follows
+ * below.
+ */
+struct ia64_sal_systab {
+	char signature[4];	/* should be "SST_" */
+	int size;		/* size of this table in bytes */
+	unsigned char sal_rev_minor;
+	unsigned char sal_rev_major;
+	unsigned short entry_count;	/* # of entries in variable portion */
+	unsigned char checksum;
+	char ia32_bios_present;
+	unsigned short reserved1;
+	char oem_id[32];	/* ASCII NUL terminated OEM id
+				   (terminating NUL is missing if
+				   string is exactly 32 bytes long). */
+	char product_id[32];	/* ASCII product id  */
+	char reserved2[16];
+};
+
+enum SAL_Systab_Entry_Type {
+	SAL_DESC_ENTRY_POINT = 0,
+	SAL_DESC_MEMORY = 1,
+	SAL_DESC_PLATFORM_FEATURE = 2,
+	SAL_DESC_TR = 3,
+	SAL_DESC_PTC = 4,
+	SAL_DESC_AP_WAKEUP = 5
+};
+
+/*
+ * Entry type:	Size:
+ *	0	48
+ *	1	32
+ *	2	16
+ *	3	32
+ *	4	16
+ *	5	16
+ */
+#define SAL_DESC_SIZE(type)	"\060\040\020\040\020\020"[(unsigned) type]
+
+struct ia64_sal_desc_entry_point {
+	char type;
+	char reserved1[7];
+	s64 pal_proc;
+	s64 sal_proc;
+	s64 gp;
+	char reserved2[16];
+};
+
+struct ia64_sal_desc_memory {
+	char type;
+	char used_by_sal;	/* needs to be mapped for SAL? */
+	char mem_attr;		/* current memory attribute setting */
+	char access_rights;	/* access rights set up by SAL */
+	char mem_attr_mask;	/* mask of supported memory attributes */
+	char reserved1;
+	char mem_type;		/* memory type */
+	char mem_usage;		/* memory usage */
+	s64 addr;		/* physical address of memory */
+	unsigned int length;	/* length (multiple of 4KB pages) */
+	unsigned int reserved2;
+	char oem_reserved[8];
+};
+
+#define IA64_SAL_PLATFORM_FEATURE_BUS_LOCK		(1 << 0)
+#define IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT	(1 << 1)
+#define IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT	(1 << 2)
+
+struct ia64_sal_desc_platform_feature {
+	char type;
+	unsigned char feature_mask;
+	char reserved1[14];
+};
+
+struct ia64_sal_desc_tr {
+	char type;
+	char tr_type;		/* 0 == instruction, 1 == data */
+	char regnum;		/* translation register number */
+	char reserved1[5];
+	s64 addr;		/* virtual address of area covered */
+	s64 page_size;		/* encoded page size */
+	char reserved2[8];
+};
+
+struct ia64_sal_desc_ptc {
+	char type;
+	char reserved1[3];
+	unsigned int num_domains;	/* # of coherence domains */
+	long domain_info;	/* physical address of domain info table */
+};
+
+#define IA64_SAL_AP_EXTERNAL_INT 0
+
+struct ia64_sal_desc_ap_wakeup {
+	char type;
+	char mechanism;		/* 0 == external interrupt */
+	char reserved1[6];
+	long vector;		/* interrupt vector in range 0x10-0xff */
+};
+
+extern ia64_sal_handler ia64_sal;
+
+extern const char *ia64_sal_strerror (long status);
+extern void ia64_sal_init (struct ia64_sal_systab *sal_systab);
+
+/* SAL information type encodings */
+enum {
+	SAL_INFO_TYPE_MCA	=		0,	/* Machine check abort information */
+        SAL_INFO_TYPE_INIT	=		1,	/* Init information */
+        SAL_INFO_TYPE_CMC	=		2 	/* Corrected machine check information */
+};
+
+/* Sub information type encodings */
+enum {
+        SAL_SUB_INFO_TYPE_PROCESSOR	=	0,	/* Processor information */
+        SAL_SUB_INFO_TYPE_PLATFORM	=	1	/* Platform information */
+};
+
+/* Encodings for machine check parameter types */
+enum {
+        SAL_MC_PARAM_RENDEZ_INT		=	1,	/* Rendezevous interrupt */
+        SAL_MC_PARAM_RENDEZ_WAKEUP	=	2	/* Wakeup */
+};
+
+/* Encodings for rendezvous mechanisms */
+enum {
+        SAL_MC_PARAM_MECHANISM_INT	=	1,	/* Use interrupt */
+        SAL_MC_PARAM_MECHANISM_MEM	=	2	/* Use memory synchronization variable*/
+};
+
+/* Encodings for vectors which can be registered by the OS with SAL */
+enum {
+	SAL_VECTOR_OS_MCA		=	0,
+	SAL_VECTOR_OS_INIT		=	1,
+	SAL_VECTOR_OS_BOOT_RENDEZ	=	2
+};
+
+/* Definition of the SAL Error Log from the SAL spec */
+
+/* Definition of timestamp according to SAL spec for logging purposes */
+
+typedef struct sal_log_timestamp_s {
+	u8	slh_century;				/* Century (19, 20, 21, ...) */
+	u8	slh_year;				/* Year (00..99) */
+	u8	slh_month;				/* Month (1..12) */
+	u8	slh_day;				/* Day (1..31) */
+	u8	slh_reserved;					
+	u8	slh_hour;				/* Hour (0..23)	*/
+	u8	slh_minute;				/* Minute (0..59) */
+	u8	slh_second;				/* Second (0..59) */
+} sal_log_timestamp_t;
+
+
+#define MAX_CACHE_ERRORS			6
+#define MAX_TLB_ERRORS				6
+#define MAX_BUS_ERRORS				1
+
+typedef struct sal_log_processor_info_s {
+	struct	{
+		u64		slpi_psi	: 1,
+				slpi_cache_check: MAX_CACHE_ERRORS,
+				slpi_tlb_check	: MAX_TLB_ERRORS,
+				slpi_bus_check	: MAX_BUS_ERRORS,
+				slpi_reserved2	: (31 - (MAX_TLB_ERRORS + MAX_CACHE_ERRORS
+							 + MAX_BUS_ERRORS)),
+				slpi_minstate	: 1,
+				slpi_bank1_gr	: 1,
+				slpi_br		: 1,
+				slpi_cr		: 1,
+				slpi_ar		: 1,
+				slpi_rr		: 1,
+				slpi_fr		: 1,
+				slpi_reserved1	: 25;
+	} slpi_valid;
+
+	pal_processor_state_info_t	slpi_processor_state_info;
+
+	struct {
+		pal_cache_check_info_t	slpi_cache_check;
+		u64			slpi_target_address;
+	} slpi_cache_check_info[MAX_CACHE_ERRORS];
+		
+	pal_tlb_check_info_t		slpi_tlb_check_info[MAX_TLB_ERRORS];
+
+	struct {
+		pal_bus_check_info_t	slpi_bus_check;
+		u64			slpi_requestor_addr;	
+		u64			slpi_responder_addr;	
+		u64			slpi_target_addr;
+	} slpi_bus_check_info[MAX_BUS_ERRORS];
+
+	pal_min_state_area_t		slpi_min_state_area;
+	u64				slpi_bank1_gr[16];
+	u64				slpi_bank1_nat_bits;
+	u64				slpi_br[8];
+	u64				slpi_cr[128];
+	u64				slpi_ar[128];
+	u64				slpi_rr[8];
+	u64				slpi_fr[128];
+} sal_log_processor_info_t;
+
+#define sal_log_processor_info_psi_valid		slpi_valid.spli_psi
+#define sal_log_processor_info_cache_check_valid	slpi_valid.spli_cache_check
+#define sal_log_processor_info_tlb_check_valid		slpi_valid.spli_tlb_check
+#define sal_log_processor_info_bus_check_valid		slpi_valid.spli_bus_check
+#define sal_log_processor_info_minstate_valid		slpi_valid.spli_minstate
+#define sal_log_processor_info_bank1_gr_valid		slpi_valid.slpi_bank1_gr
+#define sal_log_processor_info_br_valid			slpi_valid.slpi_br
+#define sal_log_processor_info_cr_valid			slpi_valid.slpi_cr
+#define sal_log_processor_info_ar_valid			slpi_valid.slpi_ar
+#define sal_log_processor_info_rr_valid			slpi_valid.slpi_rr
+#define sal_log_processor_info_fr_valid			slpi_valid.slpi_fr
+
+typedef struct sal_log_header_s {
+	u64			slh_next_log;		/* Offset of the next log from the 
+							 * beginning of  this structure.
+							 */
+	uint			slh_log_len;		/* Length of this error log in bytes */
+	ushort			slh_log_type;		/* Type of log (0 - cpu ,1 - platform) */
+	ushort			slh_log_sub_type;	/* SGI specific sub type */
+	sal_log_timestamp_t	slh_log_timestamp;	/* Timestamp */
+	u64			slh_log_dev_spec_info;	/* For processor log this field will
+							 * contain an area architected for all
+							 * IA-64 processors. For platform log
+							 * this field will contain information
+							 * specific to the hardware 
+							 * implementation.
+							 */
+} sal_log_header_t;
+
+
+/*
+ * Now define a couple of inline functions for improved type checking
+ * and convenience.
+ */
+extern inline long
+ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
+		    unsigned long *drift_info)
+{
+	struct ia64_sal_retval isrv;
+
+	SAL_CALL(isrv, SAL_FREQ_BASE, which);
+	*ticks_per_second = isrv.v0;
+	*drift_info = isrv.v1;
+	return isrv.status;
+}
+
+/* Flush all the processor and platform level instruction and/or data caches */
+extern inline s64
+ia64_sal_cache_flush (u64 cache_type)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type);
+	return isrv.status;
+}
+
+
+	
+/* Initialize all the processor and platform level instruction and data caches */
+extern inline s64
+ia64_sal_cache_init (void)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_CACHE_INIT);
+	return isrv.status;
+}
+
+/* Clear the processor and platform information logged by SAL with respect to the 
+ * machine state at the time of MCA's, INITs or CMCs 
+ */
+extern inline s64
+ia64_sal_clear_state_info (u64 sal_info_type, u64 sal_info_sub_type)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_CLEAR_STATE_INFO, sal_info_type, sal_info_sub_type);
+	return isrv.status;
+}
+
+
+/* Get the processor and platform information logged by SAL with respect to the machine
+ * state at the time of the MCAs, INITs or CMCs.
+ */
+extern inline u64
+ia64_sal_get_state_info (u64 sal_info_type, u64 sal_info_sub_type, u64 *sal_info)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_GET_STATE_INFO, sal_info_type, sal_info_sub_type, sal_info);
+	if (isrv.status)
+		return 0;
+	return isrv.v0;
+}	
+/* Get the maximum size of the information logged by SAL with respect to the machine 
+ * state at the time of MCAs, INITs or CMCs
+ */
+extern inline u64
+ia64_sal_get_state_info_size (u64 sal_info_type, u64 sal_info_sub_type)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_GET_STATE_INFO_SIZE, sal_info_type, sal_info_sub_type);
+	if (isrv.status)
+		return 0;
+	return isrv.v0;
+}
+
+/* Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup
+ * from the monarch processor.
+ */
+extern inline s64
+ia64_sal_mc_rendez (void)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_MC_RENDEZ);
+	return isrv.status;
+}
+
+/* Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during
+ * the machine check rendezvous sequence as well as the mechanism to wake up the 
+ * non-monarch processor at the end of machine check processing.
+ */
+extern inline s64
+ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, timeout);
+	return isrv.status;
+}
+
+/* Read from PCI configuration space */
+extern inline s64
+ia64_sal_pci_config_read (u64 pci_config_addr, u64 size, u64 *value)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size);
+	if (value)
+		*value = isrv.v0;
+	return isrv.status;
+}
+
+/* Write to PCI configuration space */
+extern inline s64
+ia64_sal_pci_config_write (u64 pci_config_addr, u64 size, u64 value)
+{
+	struct ia64_sal_retval isrv;
+#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) && !defined(SAPIC_FIXED)
+	extern spinlock_t ivr_read_lock;
+	unsigned long flags;
+
+	/*
+	 * Avoid PCI configuration read/write overwrite -- A0 Interrupt loss workaround
+	 */
+	spin_lock_irqsave(&ivr_read_lock, flags);
+#endif
+	SAL_CALL(isrv, SAL_PCI_CONFIG_WRITE, pci_config_addr, size, value);
+#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) && !defined(SAPIC_FIXED)
+	spin_unlock_irqrestore(&ivr_read_lock, flags);
+#endif
+	return isrv.status;
+}
+
+/*
+ * Register physical addresses of locations needed by SAL when SAL
+ * procedures are invoked in virtual mode.
+ */
+extern inline s64
+ia64_sal_register_physical_addr (u64 phys_entry, u64 phys_addr)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_REGISTER_PHYSICAL_ADDR, phys_entry, phys_addr);
+	return isrv.status;
+}
+
+/* Register software dependent code locations within SAL. These locations are handlers
+ * or entry points where SAL will pass control for the specified event. These event
+ * handlers are for the bott rendezvous, MCAs and INIT scenarios.
+ */
+extern inline s64
+ia64_sal_set_vectors (u64 vector_type,
+		      u64 handler_addr1, u64 gp1, u64 handler_len1,
+		      u64 handler_addr2, u64 gp2, u64 handler_len2)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_SET_VECTORS, vector_type,
+			handler_addr1, gp1, handler_len1,
+			handler_addr2, gp2, handler_len2);			
+
+	return isrv.status;
+}		
+/* Update the contents of PAL block in the non-volatile storage device */
+extern inline s64
+ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size,
+		     u64 *error_code, u64 *scratch_buf_size_needed)
+{
+	struct ia64_sal_retval isrv;
+	SAL_CALL(isrv, SAL_UPDATE_PAL, param_buf, scratch_buf, scratch_buf_size);
+	if (error_code)
+		*error_code = isrv.v0;
+	if (scratch_buf_size_needed)
+		*scratch_buf_size_needed = isrv.v1;
+	return isrv.status;
+}
+
+#endif /* _ASM_IA64_PAL_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/scatterlist.h linux/include/asm-ia64/scatterlist.h
--- v2.3.42/linux/include/asm-ia64/scatterlist.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/scatterlist.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,21 @@
+#ifndef _ASM_IA64_SCATTERLIST_H
+#define _ASM_IA64_SCATTERLIST_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+struct scatterlist {
+	char *address;		/* location data is to be transferred to */
+	/*
+	 * Location of actual buffer if ADDRESS points to a DMA
+	 * indirection buffer, NULL otherwise:
+	 */
+	char *alt_address;
+	unsigned int length;	/* buffer length */
+};
+
+#define ISA_DMA_THRESHOLD	(~0UL)
+
+#endif /* _ASM_IA64_SCATTERLIST_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/segment.h linux/include/asm-ia64/segment.h
--- v2.3.42/linux/include/asm-ia64/segment.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/segment.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,6 @@
+#ifndef _ASM_IA64_SEGMENT_H
+#define _ASM_IA64_SEGMENT_H
+
+/* Only here because we have some old header files that expect it.. */
+
+#endif /* __ALPHA_SEGMENT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/semaphore.h linux/include/asm-ia64/semaphore.h
--- v2.3.42/linux/include/asm-ia64/semaphore.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/semaphore.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,330 @@
+#ifndef _ASM_IA64_SEMAPHORE_H
+#define _ASM_IA64_SEMAPHORE_H
+
+/*
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/wait.h>
+
+#include <asm/atomic.h>
+
+struct semaphore {
+	atomic_t count;
+	int sleepers;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;		/* initialized by __SEM_DEBUG_INIT() */
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name)		, (long) &(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count)					\
+{										\
+	ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+	__SEM_DEBUG_INIT(name)							\
+}
+
+#define __MUTEX_INITIALIZER(name)	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count)					\
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name, count)
+
+#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+#define DECLARE_MUTEX_LOCKED(name)	__DECLARE_SEMAPHORE_GENERIC(name, 0)
+
+extern inline void
+sema_init (struct semaphore *sem, int val)
+{
+	*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
+}
+
+static inline void
+init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void
+init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
+
+extern void __down (struct semaphore * sem);
+extern int  __down_interruptible (struct semaphore * sem);
+extern int  __down_trylock (struct semaphore * sem);
+extern void __up (struct semaphore * sem);
+
+extern spinlock_t semaphore_wake_lock;
+
+/*
+ * Atomically decrement the semaphore's count.  If it goes negative,
+ * block the calling thread in the TASK_UNINTERRUPTIBLE state.
+ */
+extern inline void
+down (struct semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	if (atomic_dec_return(&sem->count) < 0)
+		__down(sem);
+}
+
+/*
+ * Atomically decrement the semaphore's count.  If it goes negative,
+ * block the calling thread in the TASK_INTERRUPTIBLE state.
+ */
+extern inline int
+down_interruptible (struct semaphore * sem)
+{
+	int ret = 0;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_interruptible(sem);
+	return ret;
+}
+
+extern inline int
+down_trylock (struct semaphore *sem)
+{
+	int ret = 0;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_trylock(sem);
+	return ret;
+}
+
+extern inline void
+up (struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	if (atomic_inc_return(&sem->count) <= 0)
+		__up(sem);
+}	
+
+/*
+ * rw mutexes (should that be mutices? =) -- throw rw spinlocks and
+ * semaphores together, and this is what we end up with...
+ *
+ * The lock is initialized to BIAS.  This way, a writer subtracts BIAS
+ * ands gets 0 for the case of an uncontended lock.  Readers decrement
+ * by 1 and see a positive value when uncontended, negative if there
+ * are writers waiting (in which case it goes to sleep).  BIAS must be
+ * chosen such that subtracting BIAS once per CPU will result either
+ * in zero (uncontended case) or in a negative value (contention
+ * case).  On the other hand, BIAS must be at least as big as the
+ * number of processes in the system.
+ *
+ * On IA-64, we use a BIAS value of 0x100000000, which supports up to
+ * 2 billion (2^31) processors and 4 billion processes.
+ *
+ * In terms of fairness, when there is heavy use of the lock, we want
+ * to see the lock being passed back and forth between readers and
+ * writers (like in a producer/consumer style of communication).
+ * 
+
+  For
+ * liveness, it would be necessary to process the blocked readers and
+ * writers in FIFO order.  However, we don't do this (yet).  I suppose
+ * if you have a lock that is _that_ heavily contested, you're in big
+ * trouble anyhow.
+ *
+ *	      -ben (with clarifications & IA-64 comments by davidm)
+ */
+#define RW_LOCK_BIAS		0x100000000ul
+
+struct rw_semaphore {
+	volatile long		count;
+	volatile __u8		write_bias_granted;
+	volatile __u8		read_bias_granted;
+	__u16			pad1;
+	__u32			pad2;
+	wait_queue_head_t	wait;
+	wait_queue_head_t	write_bias_wait;
+#if WAITQUEUE_DEBUG
+	long			__magic;
+	atomic_t		readers;
+	atomic_t		writers;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+# define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
+#else
+# define __RWSEM_DEBUG_INIT
+#endif
+
+#define __RWSEM_INITIALIZER(name,count)						\
+{										\
+	(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)			\
+	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT				\
+}
+
+#define __DECLARE_RWSEM_GENERIC(name,count)					\
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
+
+#define DECLARE_RWSEM(name)			__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
+#define DECLARE_RWSEM_READ_LOCKED(name)		__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS - 1)
+#define DECLARE_RWSEM_WRITE_LOCKED(name)	__DECLARE_RWSEM_GENERIC(name, 0)
+
+extern void __down_read_failed (struct rw_semaphore *sem, long count);
+extern void __down_write_failed (struct rw_semaphore *sem, long count);
+extern void __rwsem_wake (struct rw_semaphore *sem, long count);
+
+extern inline void
+init_rwsem (struct rw_semaphore *sem)
+{
+	sem->count = RW_LOCK_BIAS;
+	sem->read_bias_granted = 0;
+	sem->write_bias_granted = 0;
+	init_waitqueue_head(&sem->wait);
+	init_waitqueue_head(&sem->write_bias_wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+	atomic_set(&sem->readers, 0);
+	atomic_set(&sem->writers, 0);
+#endif
+}
+
+extern inline void
+down_read (struct rw_semaphore *sem)
+{
+	long count;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	count = ia64_fetch_and_add(-1, &sem->count);
+	if (count < 0)
+		__down_read_failed(sem, count);
+
+#if WAITQUEUE_DEBUG
+	if (sem->write_bias_granted)
+		BUG();
+	if (atomic_read(&sem->writers))
+		BUG();
+	atomic_inc(&sem->readers);
+#endif
+}
+
+extern inline void
+down_write (struct rw_semaphore *sem)
+{
+	long old_count, new_count;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	do {
+		old_count = sem->count;
+		new_count = old_count - RW_LOCK_BIAS;
+	} while (cmpxchg(&sem->count, old_count, new_count) != old_count);
+
+	if (new_count != 0)
+		__down_write_failed(sem, new_count);
+#if WAITQUEUE_DEBUG
+	if (atomic_read(&sem->writers))
+		BUG();
+	if (atomic_read(&sem->readers))
+		BUG();
+	if (sem->read_bias_granted)
+		BUG();
+	if (sem->write_bias_granted)
+		BUG();
+	atomic_inc(&sem->writers);
+#endif
+}
+
+/*
+ * When a reader does a release, the only significant
+ * case is when there was a writer waiting, and we've
+ * bumped the count to 0: we must wake the writer up.
+ */
+extern inline void
+__up_read (struct rw_semaphore *sem)
+{
+	long count;
+
+	count = ia64_fetch_and_add(1, &sem->count);
+	if (count == 0)
+		/*
+		 * Other processes are blocked already; resolve
+		 * contention by letting either a writer or a reader
+		 * proceed...
+		 */
+		__rwsem_wake(sem, count);
+}
+
+/*
+ * Releasing the writer is easy -- just release it and
+ * wake up any sleepers.
+ */
+extern inline void
+__up_write (struct rw_semaphore *sem)
+{
+	long old_count, new_count;
+
+	do {
+		old_count = sem->count;
+		new_count = old_count + RW_LOCK_BIAS;
+	} while (cmpxchg(&sem->count, old_count, new_count) != old_count);
+
+	/*
+	 * Note: new_count <u RW_LOCK_BIAS <=> old_count < 0 && new_count >= 0.
+	 *	 (where <u is "unsigned less-than").
+	 */
+	if ((unsigned long) new_count < RW_LOCK_BIAS)
+		/* someone is blocked already, resolve contention... */
+		__rwsem_wake(sem, new_count);
+}
+
+extern inline void
+up_read (struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+	if (sem->write_bias_granted)
+		BUG();
+	if (atomic_read(&sem->writers))
+		BUG();
+	atomic_dec(&sem->readers);
+#endif
+	__up_read(sem);
+}
+
+extern inline void
+up_write (struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+	if (sem->read_bias_granted)
+		BUG();
+	if (sem->write_bias_granted)
+		BUG();
+	if (atomic_read(&sem->readers))
+		BUG();
+	if (atomic_read(&sem->writers) != 1)
+		BUG();
+	atomic_dec(&sem->writers);
+#endif
+	__up_write(sem);
+}
+
+#endif /* _ASM_IA64_SEMAPHORE_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/sembuf.h linux/include/asm-ia64/sembuf.h
--- v2.3.42/linux/include/asm-ia64/sembuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/sembuf.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,22 @@
+#ifndef _ASM_IA64_SEMBUF_H
+#define _ASM_IA64_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for IA-64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	__kernel_time_t	sem_otime;		/* last semop time */
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif /* _ASM_IA64_SEMBUF_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/serial.h linux/include/asm-ia64/serial.h
--- v2.3.42/linux/include/asm-ia64/serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/serial.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,135 @@
+/*
+ * include/asm-ia64/serial.h
+ * 
+ * Derived from the i386 version.
+ */
+
+#include <linux/config.h>
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+#define CONFIG_SERIAL_DETECT_IRQ	/* on IA-64, we always want to autodetect irqs */
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+#endif
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
+#define HUB6_FLAGS 0
+#define RS_TABLE_SIZE	64
+#else
+#define RS_TABLE_SIZE
+#endif
+	
+/*
+ * The following define the access methods for the HUB6 card. All
+ * access is through two ports for all 24 possible chips. The card is
+ * selected through the high 2 bits, the port on that card with the
+ * "middle" 3 bits, and the register on that port with the bottom
+ * 3 bits.
+ *
+ * While the access port and interrupt is configurable, the default
+ * port locations are 0x302 for the port control register, and 0x303
+ * for the data read/write register. Normally, the interrupt is at irq3
+ * but can be anything from 3 to 7 inclusive. Note that using 3 will
+ * require disabling com2.
+ */
+
+#define C_P(card,port) (((card)<<6|(port)<<3) + 1)
+
+#define STD_SERIAL_PORT_DEFNS			\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
+
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define EXTRA_SERIAL_PORT_DEFNS			\
+	{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS },	/* ttyS13 */	\
+	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS14 (spare) */		\
+	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS15 (spare) */		\
+	{ 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS },	/* ttyS16 */	\
+	{ 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS },	/* ttyS17 */	\
+	{ 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS },	/* ttyS18 */	\
+	{ 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS },	/* ttyS19 */	\
+	{ 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS },	/* ttyS20 */	\
+	{ 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS },	/* ttyS21 */	\
+	{ 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS },	/* ttyS22 */	\
+	{ 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS },	/* ttyS23 */	\
+	{ 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS },	/* ttyS24 */	\
+	{ 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS },	/* ttyS25 */	\
+	{ 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS },	/* ttyS26 */	\
+	{ 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS },	/* ttyS27 */	\
+	{ 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS },	/* ttyS28 */	\
+	{ 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS },	/* ttyS29 */	\
+	{ 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS },	/* ttyS30 */	\
+	{ 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS },	/* ttyS31 */
+#else
+#define EXTRA_SERIAL_PORT_DEFNS
+#endif
+
+/* You can have up to four HUB6's in the system, but I've only
+ * included two cards here for a total of twelve ports.
+ */
+#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS))
+#define HUB6_SERIAL_PORT_DFNS		\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) },  /* ttyS32 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) },  /* ttyS33 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) },  /* ttyS34 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) },  /* ttyS35 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) },  /* ttyS36 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) },  /* ttyS37 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) },  /* ttyS38 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) },  /* ttyS39 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) },  /* ttyS40 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) },  /* ttyS41 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) },  /* ttyS42 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) },  /* ttyS43 */
+#else
+#define HUB6_SERIAL_PORT_DFNS
+#endif
+
+#ifdef CONFIG_MCA
+#define MCA_SERIAL_PORT_DFNS			\
+	{ 0, BASE_BAUD, 0x3220, 3, STD_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x3228, 3, STD_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x4220, 3, STD_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x4228, 3, STD_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x5220, 3, STD_COM_FLAGS },	\
+	{ 0, BASE_BAUD, 0x5228, 3, STD_COM_FLAGS },
+#else
+#define MCA_SERIAL_PORT_DFNS
+#endif
+
+#define SERIAL_PORT_DFNS		\
+	STD_SERIAL_PORT_DEFNS		\
+	EXTRA_SERIAL_PORT_DEFNS		\
+	HUB6_SERIAL_PORT_DFNS		\
+	MCA_SERIAL_PORT_DFNS
+
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/shmbuf.h linux/include/asm-ia64/shmbuf.h
--- v2.3.42/linux/include/asm-ia64/shmbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/shmbuf.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,38 @@
+#ifndef _ASM_IA64_SHMBUF_H
+#define _ASM_IA64_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for IA-64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	__kernel_time_t		shm_ctime;	/* last change time */
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _ASM_IA64_SHMBUF_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/shmparam.h linux/include/asm-ia64/shmparam.h
--- v2.3.42/linux/include/asm-ia64/shmparam.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/shmparam.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,6 @@
+#ifndef _ASM_IA64_SHMPARAM_H
+#define _ASM_IA64_SHMPARAM_H
+
+#define	SHMLBA	PAGE_SIZE		/* attach addr a multiple of this */
+
+#endif /* _ASM_IA64_SHMPARAM_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/sigcontext.h linux/include/asm-ia64/sigcontext.h
--- v2.3.42/linux/include/asm-ia64/sigcontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/sigcontext.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,50 @@
+#ifndef _ASM_IA64_SIGCONTEXT_H
+#define _ASM_IA64_SIGCONTEXT_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/fpu.h>
+
+#define IA64_SC_FLAG_ONSTACK_BIT		1	/* is handler running on signal stack? */
+#define IA64_SC_FLAG_IN_SYSCALL_BIT		1	/* did signal interrupt a syscall? */
+#define IA64_SC_FLAG_FPH_VALID_BIT		2	/* is state in f[32]-f[127] valid? */
+
+#define IA64_SC_FLAG_ONSTACK		(1 << IA64_SC_FLAG_ONSTACK_BIT)
+#define IA64_SC_FLAG_IN_SYSCALL		(1 << IA64_SC_FLAG_IN_SYSCALL_BIT)
+#define IA64_SC_FLAG_FPH_VALID		(1 << IA64_SC_FLAG_FPH_VALID_BIT)
+
+# ifndef __ASSEMBLY__
+
+struct sigcontext {
+	unsigned long		sc_flags;	/* see manifest constants above */
+	unsigned long		sc_nat;		/* bit i == 1 iff scratch reg gr[i] is a NaT */
+	stack_t			sc_stack;	/* previously active stack */
+
+	unsigned long		sc_ip;		/* instruction pointer */
+	unsigned long		sc_cfm;		/* current frame marker */
+	unsigned long		sc_um;		/* user mask bits */
+	unsigned long		sc_ar_rsc;	/* register stack configuration register */
+	unsigned long		sc_ar_bsp;	/* backing store pointer */
+	unsigned long		sc_ar_rnat;	/* RSE NaT collection register */
+	unsigned long		sc_ar_ccv;	/* compare and exchange compare value register */
+	unsigned long		sc_ar_unat;	/* ar.unat of interrupted context */
+	unsigned long		sc_ar_fpsr;	/* floating-point status register */
+	unsigned long		sc_ar_pfs;	/* previous function state */
+	unsigned long		sc_ar_lc;	/* loop count register */
+	unsigned long		sc_pr;		/* predicate registers */
+	unsigned long		sc_br[8];	/* branch registers */
+	unsigned long		sc_gr[32];	/* general registers (static partition) */
+	struct ia64_fpreg	sc_fr[128];	/* floating-point registers */
+
+	/*
+	 * The mask must come last so we can increase _NSIG_WORDS
+	 * without breaking binary compatibility.
+	 */
+	sigset_t		sc_mask;	/* signal mask to restore after handler returns */
+};
+
+# endif /* __ASSEMBLY__ */
+#endif /* _ASM_IA64_SIGCONTEXT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/siginfo.h linux/include/asm-ia64/siginfo.h
--- v2.3.42/linux/include/asm-ia64/siginfo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/siginfo.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,202 @@
+#ifndef _ASM_IA64_SIGINFO_H
+#define _ASM_IA64_SIGINFO_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/types.h>
+
+typedef union sigval {
+	int sival_int;
+	void *sival_ptr;
+} sigval_t;
+
+#define SI_MAX_SIZE	128
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			unsigned int _timer1;
+			unsigned int _timer2;
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+			sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			pid_t _pid;		/* which child */
+			uid_t _uid;		/* sender's uid */
+			int _status;		/* exit code */
+			clock_t _utime;
+			clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			void *_addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} siginfo_t;
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid		_sifields._kill._pid
+#define si_uid		_sifields._kill._uid
+#define si_status	_sifields._sigchld._status
+#define si_utime	_sifields._sigchld._utime
+#define si_stime	_sifields._sigchld._stime
+#define si_value	_sifields._rt._sigval
+#define si_int		_sifields._rt._sigval.sival_int
+#define si_ptr		_sifields._rt._sigval.sival_ptr
+#define si_addr		_sifields._sigfault._addr
+#define si_band		_sifields._sigpoll._band
+#define si_fd		_sifields._sigpoll._fd
+
+/*
+ * si_code values
+ * Positive values for kernel-generated signals.
+ */
+#define SI_USER		0	/* sent by kill, sigsend, raise */
+#define SI_KERNEL	0x80	/* sent by the kernel from somewhere */
+#define SI_QUEUE	-1	/* sent by sigqueue */
+#define SI_TIMER	-2	/* sent by timer expiration */
+#define SI_MESGQ	-3	/* sent by real time mesq state change */
+#define SI_ASYNCIO	-4	/* sent by AIO completion */
+#define SI_SIGIO	-5	/* sent by queued SIGIO */
+
+#define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
+#define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
+
+/*
+ * SIGILL si_codes
+ */
+#define ILL_ILLOPC	1	/* illegal opcode */
+#define ILL_ILLOPN	2	/* illegal operand */
+#define ILL_ILLADR	3	/* illegal addressing mode */
+#define ILL_ILLTRP	4	/* illegal trap */
+#define ILL_PRVOPC	5	/* privileged opcode */
+#define ILL_PRVREG	6	/* privileged register */
+#define ILL_COPROC	7	/* coprocessor error */
+#define ILL_BADSTK	8	/* internal stack error */
+#define ILL_BADIADDR    9	/* Unimplemented instruction address */
+#define NSIGILL		9
+
+/*
+ * SIGFPE si_codes
+ */
+#define FPE_INTDIV	1	/* integer divide by zero */
+#define FPE_INTOVF	2	/* integer overflow */
+#define FPE_FLTDIV	3	/* floating point divide by zero */
+#define FPE_FLTOVF	4	/* floating point overflow */
+#define FPE_FLTUND	5	/* floating point underflow */
+#define FPE_FLTRES	6	/* floating point inexact result */
+#define FPE_FLTINV	7	/* floating point invalid operation */
+#define FPE_FLTSUB	8	/* subscript out of range */
+#define NSIGFPE		8
+
+/*
+ * SIGSEGV si_codes
+ */
+#define SEGV_MAPERR	1	/* address not mapped to object */
+#define SEGV_ACCERR	2	/* invalid permissions for mapped object */
+#define NSIGSEGV	2
+
+/*
+ * SIGBUS si_codes
+ */
+#define BUS_ADRALN	1	/* invalid address alignment */
+#define BUS_ADRERR	2	/* non-existant physical address */
+#define BUS_OBJERR	3	/* object specific hardware error */
+#define NSIGBUS		3
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRKPT	1	/* process breakpoint */
+#define TRAP_TRACE	2	/* process trace trap */
+#define TRAP_BRANCH	3	/* process taken branch trap */
+#define NSIGTRAP	3
+
+/*
+ * SIGCHLD si_codes
+ */
+#define CLD_EXITED	1	/* child has exited */
+#define CLD_KILLED	2	/* child was killed */
+#define CLD_DUMPED	3	/* child terminated abnormally */
+#define CLD_TRAPPED	4	/* traced child has trapped */
+#define CLD_STOPPED	5	/* child has stopped */
+#define CLD_CONTINUED	6	/* stopped child has continued */
+#define NSIGCHLD	6
+
+/*
+ * SIGPOLL si_codes
+ */
+#define POLL_IN		1	/* data input available */
+#define POLL_OUT	2	/* output buffers available */
+#define POLL_MSG	3	/* input message available */
+#define POLL_ERR	4	/* i/o error */
+#define POLL_PRI	5	/* high priority input available */
+#define POLL_HUP	6	/* device disconnected */
+#define NSIGPOLL	6
+
+/*
+ * sigevent definitions
+ * 
+ * It seems likely that SIGEV_THREAD will have to be handled from 
+ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
+ * thread manager then catches and does the appropriate nonsense.
+ * However, everything is written out here so as to not get lost.
+ */
+#define SIGEV_SIGNAL	0	/* notify via signal */
+#define SIGEV_NONE	1	/* other notification: meaningless */
+#define SIGEV_THREAD	2	/* deliver via thread creation */
+
+#define SIGEV_MAX_SIZE	64
+#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct sigevent {
+	sigval_t sigev_value;
+	int sigev_signo;
+	int sigev_notify;
+	union {
+		int _pad[SIGEV_PAD_SIZE];
+
+		struct {
+			void (*_function)(sigval_t);
+			void *_attribute;	/* really pthread_attr_t */
+		} _sigev_thread;
+	} _sigev_un;
+} sigevent_t;
+
+#define sigev_notify_function	_sigev_un._sigev_thread._function
+#define sigev_notify_attributes	_sigev_un._sigev_thread._attribute
+
+#endif /* _ASM_IA64_SIGINFO_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/signal.h linux/include/asm-ia64/signal.h
--- v2.3.42/linux/include/asm-ia64/signal.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/signal.h	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,162 @@
+#ifndef _ASM_IA64_SIGNAL_H
+#define _ASM_IA64_SIGNAL_H
+
+/*
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * Unfortunately, this file is being included by bits/signal.h in
+ * glibc-2.x.  Hence the #ifdef __KERNEL__ ugliness.
+ */
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define SIGSYS		31
+/* signal 31 is no longer "unused", but the SIGUNUSED macro remains for backwards compatibility */
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	(_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP	0x00000001
+#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
+#define SA_SIGINFO	0x00000004
+#define SA_ONSTACK	0x08000000
+#define SA_RESTART	0x10000000
+#define SA_NODEFER	0x40000000
+#define SA_RESETHAND	0x80000000
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+#define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER	0x04000000
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#ifdef __KERNEL__
+
+#define _NSIG		64
+#define _NSIG_BPW	64
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+#define SA_LEGACY		0x02000000	/* installed via a legacy irq? */
+
+#endif /* __KERNEL__ */
+
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+# ifndef __ASSEMBLY__
+
+#  include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+typedef struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+typedef unsigned long old_sigset_t;
+
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+
+#  include <asm/sigcontext.h>
+
+#endif /* __KERNEL__ */
+
+# endif /* !__ASSEMBLY__ */
+#endif /* _ASM_IA64_SIGNAL_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/smp.h linux/include/asm-ia64/smp.h
--- v2.3.42/linux/include/asm-ia64/smp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/smp.h	Tue Feb  8 12:01:59 2000
@@ -0,0 +1,100 @@
+/*
+ * SMP Support
+ *
+ * Copyright (C) 1999 VA Linux Systems 
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ */
+#ifndef _ASM_IA64_SMP_H
+#define _ASM_IA64_SMP_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/threads.h>
+#include <linux/kernel.h>
+
+#include <asm/ptrace.h>
+#include <asm/spinlock.h>
+#include <asm/io.h>
+
+#define IPI_DEFAULT_BASE_ADDR	0xfee00000
+#define XTP_OFFSET		0x1e0008
+
+#define smp_processor_id() (current->processor)
+
+extern unsigned long cpu_present_map;
+extern unsigned long cpu_online_map;
+extern unsigned long ipi_base_addr;
+extern int bootstrap_processor;
+extern volatile int cpu_number_map[NR_CPUS];
+extern volatile int __cpu_logical_map[NR_CPUS];
+
+#define cpu_logical_map(i)	__cpu_logical_map[i]
+
+#if defined(CONFIG_KDB)
+extern volatile unsigned long smp_kdb_wait;
+#endif  /* CONFIG_KDB */
+
+extern unsigned long ap_wakeup_vector;
+
+/*
+ * XTP control functions:
+ *    min_xtp   :  route all interrupts to this CPU
+ *    normal_xtp:  nominal XTP value
+ *    raise_xtp :  Route all interrupts away from this CPU
+ *    max_xtp   :  never deliver interrupts to this CPU.
+ */
+
+/* 
+ * This turns off XTP based interrupt routing.  There is a bug in the handling of 
+ * IRQ_INPROGRESS when the same vector appears on more than one CPU. 
+ */
+extern int use_xtp;
+
+extern __inline void 
+min_xtp(void)
+{
+	if (use_xtp)
+		writeb(0x80, ipi_base_addr | XTP_OFFSET); /* XTP to min */
+}
+
+extern __inline void
+normal_xtp(void)
+{
+	if (use_xtp)
+		writeb(0x8e, ipi_base_addr | XTP_OFFSET); /* XTP normal */
+}
+
+extern __inline void
+max_xtp(void) 
+{
+	if (use_xtp)
+		writeb(0x8f, ipi_base_addr | XTP_OFFSET); /* Set XTP to max... */
+}
+
+extern __inline unsigned int 
+hard_smp_processor_id(void)
+{
+	struct {
+		unsigned long reserved : 16;
+		unsigned long eid : 8;
+		unsigned long id  : 8;
+		unsigned long ignored : 32;
+	} lid;
+
+	__asm__ __volatile__ ("mov %0=cr.lid" : "=r" (lid));
+
+	/*
+	 * Damn.  IA64 CPU ID's are 16 bits long, Linux expect the hard id to be 
+	 * in the range 0..31.  So, return the low-order bits of the bus-local ID 
+	 * only and hope it's less than 32. This needs to be fixed...
+	 */
+	return (lid.id & 0x0f);
+}
+
+#define NO_PROC_ID 0xffffffff
+#define PROC_CHANGE_PENALTY 20
+
+extern void __init init_smp_config (void);
+extern void smp_do_timer (struct pt_regs *regs);
+
+#endif /* _ASM_IA64_SMP_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/smplock.h linux/include/asm-ia64/smplock.h
--- v2.3.42/linux/include/asm-ia64/smplock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/smplock.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,54 @@
+/*
+ * <asm/smplock.h>
+ *
+ * Default SMP lock implementation
+ */
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/spinlock.h>
+
+extern spinlock_t kernel_flag;
+
+/*
+ * Release global kernel lock and global interrupt lock
+ */
+static __inline__ void 
+release_kernel_lock(struct task_struct *task, int cpu)
+{
+	if (task->lock_depth >= 0)
+		spin_unlock(&kernel_flag);
+	release_irqlock(cpu);
+	__sti();
+}
+
+/*
+ * Re-acquire the kernel lock
+ */
+static __inline__ void 
+reacquire_kernel_lock(struct task_struct *task)
+{
+	if (task->lock_depth >= 0)
+		spin_lock(&kernel_flag);
+}
+
+/*
+ * Getting the big kernel lock.
+ *
+ * This cannot happen asynchronously,
+ * so we only need to worry about other
+ * CPU's.
+ */
+static __inline__ void 
+lock_kernel(void)
+{
+	if (!++current->lock_depth)
+		spin_lock(&kernel_flag);
+}
+
+static __inline__ void 
+unlock_kernel(void)
+{
+	if (--current->lock_depth < 0)
+		spin_unlock(&kernel_flag);
+}
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/socket.h linux/include/asm-ia64/socket.h
--- v2.3.42/linux/include/asm-ia64/socket.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/socket.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,49 @@
+#ifndef _ASM_IA64_SOCKET_H
+#define _ASM_IA64_SOCKET_H
+
+/*
+ * Socket related defines.  This mostly mirrors the Linux/x86 version.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+#define SO_BINDTODEVICE	25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#endif /* _ASM_IA64_SOCKET_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/sockios.h linux/include/asm-ia64/sockios.h
--- v2.3.42/linux/include/asm-ia64/sockios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/sockios.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,18 @@
+#ifndef _ASM_IA64_SOCKIOS_H
+#define _ASM_IA64_SOCKIOS_H
+
+/*
+ * Socket-level I/O control calls.  This mostly mirrors the Linux/x86
+ * version.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#define FIOSETOWN 	0x8901
+#define SIOCSPGRP	0x8902
+#define FIOGETOWN	0x8903
+#define SIOCGPGRP	0x8904
+#define SIOCATMARK	0x8905
+#define SIOCGSTAMP	0x8906		/* Get stamp */
+
+#endif /* _ASM_IA64_SOCKIOS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/softirq.h linux/include/asm-ia64/softirq.h
--- v2.3.42/linux/include/asm-ia64/softirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/softirq.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,152 @@
+#ifndef _ASM_IA64_SOFTIRQ_H
+#define _ASM_IA64_SOFTIRQ_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#include <linux/config.h>
+#include <linux/stddef.h>
+
+#include <asm/system.h>
+#include <asm/hardirq.h>
+
+extern unsigned int local_bh_count[NR_CPUS];
+
+#define cpu_bh_disable(cpu)	do { local_bh_count[(cpu)]++; barrier(); } while (0)
+#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count[(cpu)]--; } while (0)
+
+#define cpu_bh_trylock(cpu)	(local_bh_count[(cpu)] ? 0 : (local_bh_count[(cpu)] = 1))
+#define cpu_bh_endlock(cpu)	(local_bh_count[(cpu)] = 0)
+
+#define local_bh_disable()	cpu_bh_disable(smp_processor_id())
+#define local_bh_enable()	cpu_bh_enable(smp_processor_id())
+
+#define get_active_bhs()	(bh_mask & bh_active)
+
+static inline void
+clear_active_bhs (unsigned long x)
+{
+	unsigned long old, new;
+	volatile unsigned long *bh_activep = (void *) &bh_active;
+	CMPXCHG_BUGCHECK_DECL
+
+	do {
+		CMPXCHG_BUGCHECK(bh_activep);
+		old = *bh_activep;
+		new = old & ~x;
+	} while (ia64_cmpxchg(bh_activep, old, new, 8) != old);
+}
+
+extern inline void
+init_bh (int nr, void (*routine)(void))
+{
+	bh_base[nr] = routine;
+	atomic_set(&bh_mask_count[nr], 0);
+	bh_mask |= 1 << nr;
+}
+
+extern inline void
+remove_bh (int nr)
+{
+	bh_mask &= ~(1 << nr);
+	mb();
+	bh_base[nr] = NULL;
+}
+
+extern inline void
+mark_bh (int nr)
+{
+	set_bit(nr, &bh_active);
+}
+
+#ifdef CONFIG_SMP
+
+/*
+ * The locking mechanism for base handlers, to prevent re-entrancy,
+ * is entirely private to an implementation, it should not be
+ * referenced at all outside of this file.
+ */
+extern atomic_t global_bh_lock;
+extern atomic_t global_bh_count;
+
+extern void synchronize_bh(void);
+
+static inline void
+start_bh_atomic (void)
+{
+	atomic_inc(&global_bh_lock);
+	synchronize_bh();
+}
+
+static inline void
+end_bh_atomic (void)
+{
+	atomic_dec(&global_bh_lock);
+}
+
+/* These are for the irq's testing the lock */
+static inline int
+softirq_trylock (int cpu)
+{
+	if (cpu_bh_trylock(cpu)) {
+		if (!test_and_set_bit(0, &global_bh_count)) {
+			if (atomic_read(&global_bh_lock) == 0)
+				return 1;
+			clear_bit(0,&global_bh_count);
+		}
+		cpu_bh_endlock(cpu);
+	}
+	return 0;
+}
+
+static inline void
+softirq_endlock (int cpu)
+{
+	cpu_bh_enable(cpu);
+	clear_bit(0,&global_bh_count);
+}
+
+#else /* !CONFIG_SMP */
+
+extern inline void
+start_bh_atomic (void)
+{
+	local_bh_disable();
+	barrier();
+}
+
+extern inline void
+end_bh_atomic (void)
+{
+	barrier();
+	local_bh_enable();
+}
+
+/* These are for the irq's testing the lock */
+#define softirq_trylock(cpu)	(cpu_bh_trylock(cpu))
+#define softirq_endlock(cpu)	(cpu_bh_endlock(cpu))
+#define synchronize_bh()	barrier()
+
+#endif /* !CONFIG_SMP */
+
+/*
+ * These use a mask count to correctly handle
+ * nested disable/enable calls
+ */
+extern inline void
+disable_bh (int nr)
+{
+	bh_mask &= ~(1 << nr);
+	atomic_inc(&bh_mask_count[nr]);
+	synchronize_bh();
+}
+
+extern inline void
+enable_bh (int nr)
+{
+	if (atomic_dec_and_test(&bh_mask_count[nr]))
+		bh_mask |= 1 << nr;
+}
+
+#endif /* _ASM_IA64_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/spinlock.h linux/include/asm-ia64/spinlock.h
--- v2.3.42/linux/include/asm-ia64/spinlock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/spinlock.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,97 @@
+#ifndef _ASM_IA64_SPINLOCK_H
+#define _ASM_IA64_SPINLOCK_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ *
+ * This file is used for SMP configurations only.
+ */
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/atomic.h>
+
+typedef struct { 
+	volatile unsigned int lock;
+} spinlock_t;
+#define SPIN_LOCK_UNLOCKED			(spinlock_t) { 0 }
+#define spin_lock_init(x)			((x)->lock = 0) 
+
+/* Streamlined test_and_set_bit(0, (x)) */
+#define spin_lock(x) __asm__ __volatile__ ( \
+	"mov ar.ccv = r0\n" \
+	"mov r29 = 1\n" \
+	";;\n" \
+	"1:\n" \
+	"ld4 r2 = [%0]\n" \
+	";;\n" \
+	"cmp4.eq p0,p7 = r0,r2\n" \
+	"(p7) br.cond.dptk.few 1b \n" \
+	"cmpxchg4.acq r2 = [%0], r29, ar.ccv\n" \
+	";;\n" \
+	"cmp4.eq p0,p7 = r0, r2\n" \
+	"(p7) br.cond.dptk.few 1b\n" \
+	";;\n" \
+	:: "m" __atomic_fool_gcc((x)) : "r2", "r29")
+
+#define spin_unlock(x) __asm__ __volatile__ ("st4.rel [%0] = r0;;" : "=m" (__atomic_fool_gcc((x))))
+
+#define spin_trylock(x) (!test_and_set_bit(0, (x)))
+
+#define spin_unlock_wait(x) \
+	({ do { barrier(); } while(((volatile spinlock_t *)x)->lock); })
+
+typedef struct {
+	volatile int read_counter:31;
+	volatile int write_lock:1;
+} rwlock_t;
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+
+#define read_lock(rw) \
+do { \
+	int tmp = 0; \
+	__asm__ __volatile__ ("1:\tfetchadd4.acq %0 = %1, 1\n" \
+			      ";;\n" \
+			      "tbit.nz p6,p0 = %0, 31\n" \
+			      "(p6) br.cond.sptk.few 2f\n" \
+			      ".section .text.lock,\"ax\"\n" \
+			      "2:\tfetchadd4.rel %0 = %1, -1\n" \
+			      ";;\n" \
+			      "3:\tld4.acq %0 = %1\n" \
+			      ";;\n" \
+			      "tbit.nz p6,p0 = %0, 31\n" \
+			      "(p6) br.cond.sptk.few 3b\n" \
+			      "br.cond.sptk.few 1b\n" \
+			      ";;\n" \
+			      ".previous\n": "=r" (tmp), "=m" (__atomic_fool_gcc(rw))); \
+} while(0)
+
+#define read_unlock(rw) \
+do { \
+	int tmp = 0; \
+	__asm__ __volatile__ ("fetchadd4.rel %0 = %1, -1\n" \
+			      : "=r" (tmp) : "m" (__atomic_fool_gcc(rw))); \
+} while(0)
+
+/*
+ * These may need to be rewhacked in asm().
+ * XXX FIXME SDV - This may have a race on real hardware but is sufficient for SoftSDV
+ */
+#define write_lock(rw) \
+while(1) {\
+	do { \
+	} while (!test_and_set_bit(31, (rw))); \
+	if ((rw)->read_counter) { \
+		clear_bit(31, (rw)); \
+		while ((rw)->read_counter) \
+			; \
+	} else { \
+		break; \
+	} \
+}
+
+#define write_unlock(x)				(clear_bit(31, (x)))
+
+#endif /*  _ASM_IA64_SPINLOCK_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/stat.h linux/include/asm-ia64/stat.h
--- v2.3.42/linux/include/asm-ia64/stat.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/stat.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,28 @@
+#ifndef _ASM_IA64_STAT_H
+#define _ASM_IA64_STAT_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+struct stat {
+	unsigned int	st_dev;
+	unsigned int	st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	unsigned int	st_rdev;
+	unsigned int	__pad1;
+	unsigned long	st_size;
+	unsigned long	st_atime;
+	unsigned long	st_mtime;
+	unsigned long	st_ctime;
+	unsigned int	st_blksize;
+	int		st_blocks;
+	unsigned int	__unused1;
+	unsigned int	__unused2;
+};
+
+#endif /* _ASM_IA64_STAT_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/statfs.h linux/include/asm-ia64/statfs.h
--- v2.3.42/linux/include/asm-ia64/statfs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/statfs.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,27 @@
+#ifndef _ASM_IA64_STATFS_H
+#define _ASM_IA64_STATFS_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+# ifndef __KERNEL_STRICT_NAMES
+#  include <linux/types.h>
+   typedef __kernel_fsid_t	fsid_t;
+# endif
+
+struct statfs {
+	long f_type;
+	long f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	__kernel_fsid_t f_fsid;
+	long f_namelen;
+	long f_spare[6];
+};
+
+#endif /* _ASM_IA64_STATFS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/string.h linux/include/asm-ia64/string.h
--- v2.3.42/linux/include/asm-ia64/string.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/string.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,15 @@
+#ifndef _ASM_IA64_STRING_H
+#define _ASM_IA64_STRING_H
+
+/*
+ * Here is where we want to put optimized versions of the string
+ * routines.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define __HAVE_ARCH_STRLEN	1 /* see arch/ia64/lib/strlen.S */
+#define __HAVE_ARCH_MEMSET	1 /* see arch/ia64/lib/memset.S */
+
+#endif /* _ASM_IA64_STRING_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/system.h linux/include/asm-ia64/system.h
--- v2.3.42/linux/include/asm-ia64/system.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/system.h	Wed Feb  9 19:45:43 2000
@@ -0,0 +1,471 @@
+#ifndef _ASM_IA64_SYSTEM_H
+#define _ASM_IA64_SYSTEM_H
+
+/*
+ * System defines. Note that this is included both from .c and .S
+ * files, so it does only defines, not any C code.  This is based
+ * on information published in the Processor Abstraction Layer
+ * and the System Abstraction Layer manual.
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
+ */
+#include <linux/config.h>
+
+#include <asm/page.h>
+
+#define KERNEL_START		(PAGE_OFFSET + 0x500000)
+
+/*
+ * The following #defines must match with vmlinux.lds.S:
+ */
+#define IVT_END_ADDR		(KERNEL_START + 0x8000)
+#define ZERO_PAGE_ADDR		(IVT_END_ADDR + 0*PAGE_SIZE)
+#define SWAPPER_PGD_ADDR	(IVT_END_ADDR + 1*PAGE_SIZE)
+
+#define GATE_ADDR		(0xa000000000000000 + PAGE_SIZE)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pci_vector_struct {
+	__u16 bus;	/* PCI Bus number */
+        __u32 pci_id;	/* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */
+        __u8 pin;	/* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
+        __u8 irq;	/* IRQ assigned */
+};
+
+extern struct ia64_boot_param {
+	__u64 command_line;		/* physical address of command line arguments */
+	__u64 efi_systab;		/* physical address of EFI system table */
+	__u64 efi_memmap;		/* physical address of EFI memory map */
+	__u64 efi_memmap_size;		/* size of EFI memory map */
+	__u64 efi_memdesc_size;		/* size of an EFI memory map descriptor */
+	__u32 efi_memdesc_version;	/* memory descriptor version */
+	struct {
+		__u16 num_cols;	/* number of columns on console output device */
+		__u16 num_rows;	/* number of rows on console output device */
+		__u16 orig_x;	/* cursor's x position */
+		__u16 orig_y;	/* cursor's y position */
+	} console_info;
+	__u16 num_pci_vectors;	/* number of ACPI derived PCI IRQ's*/
+	__u64 pci_vectors;	/* physical address of PCI data (pci_vector_struct)*/
+	__u64 fpswa;		/* physical address of the the fpswa interface */
+} ia64_boot_param;
+
+extern inline void
+ia64_insn_group_barrier (void)
+{
+	__asm__ __volatile__ (";;" ::: "memory");
+}
+
+/*
+ * Macros to force memory ordering.  In these descriptions, "previous"
+ * and "subsequent" refer to program order; "visible" means that all
+ * architecturally visible effects of a memory access have occurred
+ * (at a minimum, this means the memory has been read or written).
+ *
+ *   wmb():	Guarantees that all preceding stores to memory-
+ *		like regions are visible before any subsequent
+ *		stores and that all following stores will be
+ *		visible only after all previous stores.
+ *   rmb():	Like wmb(), but for reads.
+ *   mb():	wmb()/rmb() combo, i.e., all previous memory
+ *		accesses are visible before all subsequent
+ *		accesses and vice versa.  This is also known as
+ *		a "fence."
+ *
+ * Note: "mb()" and its variants cannot be used as a fence to order
+ * accesses to memory mapped I/O registers.  For that, mf.a needs to
+ * be used.  However, we don't want to always use mf.a because (a)
+ * it's (presumably) much slower than mf and (b) mf.a is supported for
+ * sequential memory pages only.
+ */
+#define mb()	__asm__ __volatile__ ("mf" ::: "memory")
+#define rmb()	mb()
+#define wmb()	mb()
+
+/*
+ * XXX check on these---I suspect what Linus really wants here is
+ * acquire vs release semantics but we can't discuss this stuff with
+ * Linus just yet.  Grrr...
+ */
+#define set_mb(var, value)	do { (var) = (value); mb(); } while (0)
+#define set_rmb(var, value)	do { (var) = (value); mb(); } while (0)
+#define set_wmb(var, value)	do { (var) = (value); mb(); } while (0)
+
+/*
+ * The group barrier in front of the rsm & ssm are necessary to ensure
+ * that none of the previous instructions in the same group are
+ * affected by the rsm/ssm.
+ */
+/* For spinlocks etc */
+
+#ifdef CONFIG_IA64_DEBUG_IRQ
+
+  extern unsigned long last_cli_ip;
+
+# define local_irq_save(x)								\
+do {											\
+	unsigned long ip, psr;								\
+											\
+	__asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory");	\
+	if (psr & (1UL << 14)) {							\
+		__asm__ ("mov %0=ip" : "=r"(ip));					\
+		last_cli_ip = ip;							\
+	}										\
+	(x) = psr;									\
+} while (0)
+
+# define local_irq_disable()								\
+do {											\
+	unsigned long ip, psr;								\
+											\
+	__asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;" : "=r" (psr) :: "memory");	\
+	if (psr & (1UL << 14)) {							\
+		__asm__ ("mov %0=ip" : "=r"(ip));					\
+		last_cli_ip = ip;							\
+	}										\
+} while (0)
+
+# define local_irq_restore(x)						 \
+do {									 \
+	unsigned long ip, old_psr, psr = (x);				 \
+									 \
+	__asm__ __volatile__ ("mov %0=psr; mov psr.l=%1;; srlz.d"	 \
+			      : "=&r" (old_psr) : "r" (psr) : "memory"); \
+	if ((old_psr & (1UL << 14)) && !(psr & (1UL << 14))) {		 \
+		__asm__ ("mov %0=ip" : "=r"(ip));			 \
+		last_cli_ip = ip;					 \
+	}								 \
+} while (0)
+
+#else /* !CONFIG_IA64_DEBUG_IRQ */
+  /* clearing of psr.i is implicitly serialized (visible by next insn) */
+# define local_irq_save(x)	__asm__ __volatile__ ("mov %0=psr;; rsm psr.i;;"	\
+						      : "=r" (x) :: "memory")
+# define local_irq_disable()	__asm__ __volatile__ (";; rsm psr.i;;" ::: "memory")
+/* (potentially) setting psr.i requires data serialization: */
+# define local_irq_restore(x)	__asm__ __volatile__ ("mov psr.l=%0;; srlz.d"		\
+						      :: "r" (x) : "memory")
+#endif /* !CONFIG_IA64_DEBUG_IRQ */
+
+#define local_irq_enable()	__asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory")
+
+#define __cli()			local_irq_disable ()
+#define __save_flags(flags)	__asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory")
+#define __save_and_cli(flags)	local_irq_save(flags)
+#define save_and_cli(flags)	__save_and_cli(flags)
+
+
+#ifdef CONFIG_IA64_SOFTSDV_HACKS
+/*
+ * Yech.  SoftSDV has a slight probem with psr.i and itc/itm.  If
+ * PSR.i = 0 and ITC == ITM, you don't get the timer tick posted.  So,
+ * I'll check if ITC is larger than ITM here and reset if neccessary.
+ * I may miss a tick to two.
+ * 
+ * Don't include asm/delay.h; it causes include loops that are
+ * mind-numbingly hard to follow.
+ */
+
+#define get_itc(x) __asm__ __volatile__("mov %0=ar.itc" : "=r"((x)) :: "memory")
+#define get_itm(x) __asm__ __volatile__("mov %0=cr.itm" : "=r"((x)) :: "memory")
+#define set_itm(x) __asm__ __volatile__("mov cr.itm=%0" :: "r"((x)) : "memory")
+
+#define __restore_flags(x)			\
+do {						\
+        unsigned long itc, itm;			\
+	local_irq_restore(x);			\
+        get_itc(itc);				\
+        get_itm(itm);				\
+        if (itc > itm)				\
+		set_itm(itc + 10);		\
+} while (0)
+
+#define __sti()					\
+do {						\
+	unsigned long itc, itm;			\
+	local_irq_enable();			\
+	get_itc(itc);				\
+	get_itm(itm);				\
+	if (itc > itm)				\
+		set_itm(itc + 10);		\
+} while (0)
+
+#else /* !CONFIG_IA64_SOFTSDV_HACKS */
+
+#define __sti()			local_irq_enable ()
+#define __restore_flags(flags)	local_irq_restore(flags)
+
+#endif /* !CONFIG_IA64_SOFTSDV_HACKS */
+
+#ifdef CONFIG_SMP
+  extern void __global_cli (void);
+  extern void __global_sti (void);
+  extern unsigned long __global_save_flags (void);
+  extern void __global_restore_flags (unsigned long);
+# define cli()			__global_cli()
+# define sti()			__global_sti()
+# define save_flags(flags)	((flags) = __global_save_flags())
+# define restore_flags(flags)	__global_restore_flags(flags)
+#else /* !CONFIG_SMP */
+# define cli()			__cli()
+# define sti()			__sti()
+# define save_flags(flags)	__save_flags(flags)
+# define restore_flags(flags)	__restore_flags(flags)
+#endif /* !CONFIG_SMP */
+
+/*
+ * Force an unresolved reference if someone tries to use
+ * ia64_fetch_and_add() with a bad value.
+ */
+extern unsigned long __bad_size_for_ia64_fetch_and_add (void);
+extern unsigned long __bad_increment_for_ia64_fetch_and_add (void);
+
+#define IA64_FETCHADD(tmp,v,n,sz)						\
+({										\
+	switch (sz) {								\
+	      case 4:								\
+		__asm__ __volatile__ ("fetchadd4.rel %0=%1,%3"			\
+				      : "=r"(tmp), "=m"(__atomic_fool_gcc(v))	\
+				      : "m" (__atomic_fool_gcc(v)), "i"(n));	\
+		break;								\
+										\
+	      case 8:								\
+		__asm__ __volatile__ ("fetchadd8.rel %0=%1,%3"			\
+				      : "=r"(tmp), "=m"(__atomic_fool_gcc(v))	\
+				      : "m" (__atomic_fool_gcc(v)), "i"(n));	\
+		break;								\
+										\
+	      default:								\
+		__bad_size_for_ia64_fetch_and_add();				\
+	}									\
+})
+
+#define ia64_fetch_and_add(i,v)							\
+({										\
+	__u64 _tmp;								\
+	volatile __typeof__(*(v)) *_v = (v);					\
+	switch (i) {								\
+	      case -16:	IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); break;	\
+	      case  -8:	IA64_FETCHADD(_tmp, _v,  -8, sizeof(*(v))); break;	\
+	      case  -4:	IA64_FETCHADD(_tmp, _v,  -4, sizeof(*(v))); break;	\
+	      case  -1:	IA64_FETCHADD(_tmp, _v,  -1, sizeof(*(v))); break;	\
+	      case   1:	IA64_FETCHADD(_tmp, _v,   1, sizeof(*(v))); break;	\
+	      case   4:	IA64_FETCHADD(_tmp, _v,   4, sizeof(*(v))); break;	\
+	      case   8:	IA64_FETCHADD(_tmp, _v,   8, sizeof(*(v))); break;	\
+	      case  16:	IA64_FETCHADD(_tmp, _v,  16, sizeof(*(v))); break;	\
+	      default:								\
+		_tmp = __bad_increment_for_ia64_fetch_and_add();		\
+		break;								\
+	}									\
+	(__typeof__(*v)) (_tmp + (i));	/* return new value */			\
+})
+
+/*
+ * This function doesn't exist, so you'll get a linker error if
+ * something tries to do an invalid xchg().
+ */
+extern void __xchg_called_with_bad_pointer (void);
+
+static __inline__ unsigned long
+__xchg (unsigned long x, volatile void *ptr, int size)
+{
+	unsigned long result;
+
+	switch (size) {
+	      case 1:
+		__asm__ __volatile ("xchg1 %0=%1,%2" : "=r" (result)
+				    : "m" (*(char *) ptr), "r" (x) : "memory");
+		return result;
+
+	      case 2:
+		__asm__ __volatile ("xchg2 %0=%1,%2" : "=r" (result)
+				    : "m" (*(short *) ptr), "r" (x) : "memory");
+		return result;
+
+	      case 4:
+		__asm__ __volatile ("xchg4 %0=%1,%2" : "=r" (result)
+				    : "m" (*(int *) ptr), "r" (x) : "memory");
+		return result;
+
+	      case 8:
+		__asm__ __volatile ("xchg8 %0=%1,%2" : "=r" (result)
+				    : "m" (*(long *) ptr), "r" (x) : "memory");
+		return result;
+	}
+	__xchg_called_with_bad_pointer();
+	return x;
+}
+
+#define xchg(ptr,x)							     \
+  ((__typeof__(*(ptr))) __xchg ((unsigned long) (x), (ptr), sizeof(*(ptr))))
+#define tas(ptr)	(xchg ((ptr), 1))
+
+/* 
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg().
+ */
+extern long __cmpxchg_called_with_bad_pointer(void);
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) (*(struct __xchg_dummy *)(x))
+
+#define ia64_cmpxchg(ptr,old,new,size)					\
+({									\
+	__typeof__(ptr) _p_ = (ptr);					\
+	__typeof__(new) _n_ = (new);					\
+	__u64 _o_, _r_;							\
+									\
+	switch (size) {							\
+	      case 1: _o_ = (__u8 ) (old); break;			\
+	      case 2: _o_ = (__u16) (old); break;			\
+	      case 4: _o_ = (__u32) (old); break;			\
+	      case 8: _o_ = (__u64) (old); break;			\
+	      default:							\
+	}								\
+	 __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "r"(_o_));		\
+	switch (size) {							\
+	      case 1:							\
+		__asm__ __volatile__ ("cmpxchg1.rel %0=%2,%3,ar.ccv"	\
+				      : "=r"(_r_), "=m"(__xg(_p_))	\
+				      : "m"(__xg(_p_)), "r"(_n_));	\
+		break;							\
+									\
+	      case 2:							\
+		__asm__ __volatile__ ("cmpxchg2.rel %0=%2,%3,ar.ccv"	\
+				      : "=r"(_r_), "=m"(__xg(_p_))	\
+				      : "m"(__xg(_p_)), "r"(_n_));	\
+		break;							\
+									\
+	      case 4:							\
+		__asm__ __volatile__ ("cmpxchg4.rel %0=%2,%3,ar.ccv"	\
+				      : "=r"(_r_), "=m"(__xg(_p_))	\
+				      : "m"(__xg(_p_)), "r"(_n_));	\
+		break;							\
+									\
+	      case 8:							\
+		__asm__ __volatile__ ("cmpxchg8.rel %0=%2,%3,ar.ccv"	\
+				      : "=r"(_r_), "=m"(__xg(_p_))	\
+				      : "m"(__xg(_p_)), "r"(_n_));	\
+		break;							\
+									\
+	      default:							\
+		_r_ = __cmpxchg_called_with_bad_pointer();		\
+		break;							\
+	}								\
+	(__typeof__(old)) _r_;						\
+})
+
+#define cmpxchg(ptr,o,n)     ia64_cmpxchg((ptr), (o), (n), sizeof(*(ptr)))
+
+#ifdef CONFIG_IA64_DEBUG_CMPXCHG
+# define CMPXCHG_BUGCHECK_DECL	int _cmpxchg_bugcheck_count = 128;
+# define CMPXCHG_BUGCHECK(v)							\
+  do {										\
+	if (_cmpxchg_bugcheck_count-- <= 0) {					\
+		void *ip;							\
+		extern int printk(const char *fmt, ...);			\
+		asm ("mov %0=ip" : "=r"(ip));					\
+		printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));	\
+		break;								\
+	}									\
+  } while (0)
+#else /* !CONFIG_IA64_DEBUG_CMPXCHG */
+# define CMPXCHG_BUGCHECK_DECL
+# define CMPXCHG_BUGCHECK(v)
+#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
+
+#ifdef __KERNEL__
+
+extern void ia64_save_debug_regs (unsigned long *save_area);
+extern void ia64_load_debug_regs (unsigned long *save_area);
+
+#define prepare_to_switch()    do { } while(0)
+
+#ifdef CONFIG_IA32_SUPPORT
+# define TASK_TO_PTREGS(t)									\
+	((struct pt_regs *)(((unsigned long)(t) + IA64_STK_OFFSET - IA64_PT_REGS_SIZE)))
+# define IS_IA32_PROCESS(regs)	(ia64_psr(regs)->is != 0)
+# define IA32_FP_STATE(prev,next)						\
+	if (IS_IA32_PROCESS(TASK_TO_PTREGS(prev))) {				\
+	    __asm__ __volatile__("mov %0=ar.fsr":"=r"((prev)->thread.fsr));	\
+	    __asm__ __volatile__("mov %0=ar.fcr":"=r"((prev)->thread.fcr));	\
+	    __asm__ __volatile__("mov %0=ar.fir":"=r"((prev)->thread.fir));	\
+	    __asm__ __volatile__("mov %0=ar.fdr":"=r"((prev)->thread.fdr));	\
+	}									\
+	if (IS_IA32_PROCESS(TASK_TO_PTREGS(next))) {				\
+	    __asm__ __volatile__("mov ar.fsr=%0"::"r"((next)->thread.fsr));	\
+	    __asm__ __volatile__("mov ar.fcr=%0"::"r"((next)->thread.fcr));	\
+	    __asm__ __volatile__("mov ar.fir=%0"::"r"((next)->thread.fir));	\
+	    __asm__ __volatile__("mov ar.fdr=%0"::"r"((next)->thread.fdr));	\
+	}
+#else /* !CONFIG_IA32_SUPPORT */
+# define IA32_FP_STATE(prev,next)
+# define IS_IA32_PROCESS(regs)		0
+#endif /* CONFIG_IA32_SUPPORT */
+
+/*
+ * Context switch from one thread to another.  If the two threads have
+ * different address spaces, schedule() has already taken care of
+ * switching to the new address space by calling switch_mm().
+ *
+ * Disabling access to the fph partition and the debug-register
+ * context switch MUST be done before calling ia64_switch_to() since a
+ * newly created thread returns directly to
+ * ia64_ret_from_syscall_clear_r8.
+ */
+extern struct task_struct *ia64_switch_to (void *next_task);
+#define __switch_to(prev,next,last) do {					\
+	ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next));	\
+	if ((prev)->thread.flags & IA64_THREAD_DBG_VALID) {			\
+		ia64_save_debug_regs(&(prev)->thread.dbr[0]);			\
+	}									\
+	if ((next)->thread.flags & IA64_THREAD_DBG_VALID) {			\
+		ia64_load_debug_regs(&(next)->thread.dbr[0]);			\
+	}									\
+	IA32_FP_STATE(prev,next);						\
+	(last) = ia64_switch_to((next));					\
+} while (0)
+
+#ifdef CONFIG_SMP 
+  /*
+   * In the SMP case, we save the fph state when context-switching
+   * away from a thread that owned and modified fph.  This way, when
+   * the thread gets scheduled on another CPU, the CPU can pick up the
+   * state frm task->thread.fph, avoiding the complication of having
+   * to fetch the latest fph state from another CPU.  If the thread
+   * happens to be rescheduled on the same CPU later on and nobody
+   * else has touched the FPU in the meantime, the thread will fault
+   * upon the first access to fph but since the state in fph is still
+   * valid, no other overheads are incurred.  In other words, CPU
+   * affinity is a Good Thing.
+   */
+# define switch_to(prev,next,last) do {							\
+	if (ia64_get_fpu_owner() == (prev) && ia64_psr(ia64_task_regs(prev))->mfh) {	\
+		(prev)->thread.flags |= IA64_THREAD_FPH_VALID;				\
+		__ia64_save_fpu((prev)->thread.fph);					\
+	}										\
+	__switch_to(prev,next,last);							\
+  } while (0)
+#else
+# define switch_to(prev,next,last) 	__switch_to(prev,next,last)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_IA64_SYSTEM_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/termbits.h linux/include/asm-ia64/termbits.h
--- v2.3.42/linux/include/asm-ia64/termbits.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/termbits.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,179 @@
+#ifndef _ASM_IA64_TERMBITS_H
+#define _ASM_IA64_TERMBITS_H
+
+/*
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 99/01/28	Added new baudrates
+ */
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+
+/* c_oflag bits */
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif /* _ASM_IA64_TERMBITS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/termios.h linux/include/asm-ia64/termios.h
--- v2.3.42/linux/include/asm-ia64/termios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/termios.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,112 @@
+#ifndef _ASM_IA64_TERMIOS_H
+#define _ASM_IA64_TERMIOS_H
+
+/*
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 99/01/28	Added N_IRDA and N_SMSBLOCK
+ */
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+#define TIOCM_LOOP	0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS msgs */
+#define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14	/* synchronous PPP */
+
+# ifdef __KERNEL__
+
+/*	intr=^C		quit=^\		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) {	\
+	unsigned short __tmp;				\
+	get_user(__tmp,&(termio)->x);			\
+	*(unsigned short *) &(termios)->x = __tmp;	\
+}
+
+#define user_termio_to_kernel_termios(termios, termio)		\
+({								\
+	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag);		\
+	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag);		\
+	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag);		\
+	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag);		\
+	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC);	\
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios)		\
+({								\
+	put_user((termios)->c_iflag, &(termio)->c_iflag);	\
+	put_user((termios)->c_oflag, &(termio)->c_oflag);	\
+	put_user((termios)->c_cflag, &(termio)->c_cflag);	\
+	put_user((termios)->c_lflag, &(termio)->c_lflag);	\
+	put_user((termios)->c_line,  &(termio)->c_line);	\
+	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC);	\
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+# endif /* __KERNEL__ */
+
+#endif /* _ASM_IA64_TERMIOS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/timex.h linux/include/asm-ia64/timex.h
--- v2.3.42/linux/include/asm-ia64/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/timex.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,23 @@
+#ifndef _ASM_IA64_TIMEX_H
+#define _ASM_IA64_TIMEX_H
+
+/*
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#define CLOCK_TICK_RATE		1193180	/* Underlying HZ XXX fix me! */
+
+typedef unsigned long cycles_t;
+extern cycles_t cacheflush_time;
+
+static inline cycles_t
+get_cycles (void)
+{
+	cycles_t ret;
+
+	__asm__ __volatile__ ("mov %0=ar.itc" : "=r"(ret));
+	return ret;
+}
+
+#endif /* _ASM_IA64_TIMEX_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/types.h linux/include/asm-ia64/types.h
--- v2.3.42/linux/include/asm-ia64/types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/types.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,94 @@
+#ifndef _ASM_IA64_TYPES_H
+#define _ASM_IA64_TYPES_H
+
+/*
+ * This file is never included by application software unless
+ * explicitly requested (e.g., via linux/types.h) in which case the
+ * application is Linux specific so (user-) name space pollution is
+ * not a major issue.  However, for interoperability, libraries still
+ * need to be careful to avoid a name clashes.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#ifdef __ASSEMBLY__
+# define __IA64_UL(x)		x
+# define __IA64_UL_CONST(x)	x
+#else
+# define __IA64_UL(x)		((unsigned long)x)
+# define __IA64_UL_CONST(x)	x##UL
+#endif
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned int umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+/*
+ * There are 32-bit compilers for the ia-64 out there..
+ */
+# if ((~0UL) == 0xffffffff)
+#  if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#  endif
+# else
+typedef __signed__ long __s64;
+typedef unsigned long __u64;
+# endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+# ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+/*
+ * There are 32-bit compilers for the ia-64 out there...  (don't rely
+ * on cpp because that may cause su problem in a 32->64 bit
+ * cross-compilation environment).
+ */
+#  ifdef __LP64__
+
+typedef signed long s64;
+typedef unsigned long u64;
+#define BITS_PER_LONG 64
+
+#  else
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+#define BITS_PER_LONG 32
+
+#  endif
+
+/* DMA addresses are 64-bits wide, in general.  */
+
+typedef u64 dma_addr_t;
+
+# endif /* __KERNEL__ */
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_IA64_TYPES_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/uaccess.h linux/include/asm-ia64/uaccess.h
--- v2.3.42/linux/include/asm-ia64/uaccess.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/uaccess.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,366 @@
+#ifndef _ASM_IA64_UACCESS_H
+#define _ASM_IA64_UACCESS_H
+
+/*
+ * This file defines various macros to transfer memory areas across
+ * the user/kernel boundary.  This needs to be done carefully because
+ * this code is executed in kernel mode and uses user-specified
+ * addresses.  Thus, we need to be careful not to let the user to
+ * trick us into accessing kernel memory that would normally be
+ * inaccessible.  This code is also fairly performance sensitive,
+ * so we want to spend as little time doing saftey checks as
+ * possible.
+ *
+ * To make matters a bit more interesting, these macros sometimes also
+ * called from within the kernel itself, in which case the address
+ * validity check must be skipped.  The get_fs() macro tells us what
+ * to do: if get_fs()==USER_DS, checking is performed, if
+ * get_fs()==KERNEL_DS, checking is bypassed.
+ *
+ * Note that even if the memory area specified by the user is in a
+ * valid address range, it is still possible that we'll get a page
+ * fault while accessing it.  This is handled by filling out an
+ * exception handler fixup entry for each instruction that has the
+ * potential to fault.  When such a fault occurs, the page fault
+ * handler checks to see whether the faulting instruction has a fixup
+ * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
+ * then resumes execution at the continuation point.
+ * 
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+/*
+ * For historical reasons, the following macros are grossly misnamed:
+ */
+#define KERNEL_DS	((mm_segment_t) { ~0UL })		/* cf. access_ok() */
+#define USER_DS		((mm_segment_t) { TASK_SIZE-1 })	/* cf. access_ok() */
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+#define get_ds()  (KERNEL_DS)
+#define get_fs()  (current->addr_limit)
+#define set_fs(x) (current->addr_limit = (x))
+
+#define segment_eq(a,b)	((a).seg == (b).seg)
+
+/*
+ * When accessing user memory, we need to make sure the entire area
+ * really is in user-level space.  In order to do this efficiently, we
+ * make sure that the page at address TASK_SIZE is never valid (we do
+ * this by selecting VMALLOC_START as TASK_SIZE+PAGE_SIZE).  This way,
+ * we can simply check whether the starting address is < TASK_SIZE
+ * and, if so, start accessing the memory.  If the user specified bad
+ * length, we will fault on the NaT page and then return the
+ * appropriate error.
+ */
+#define __access_ok(addr,size,segment)	(((unsigned long) (addr)) <= (segment).seg)
+#define access_ok(type,addr,size)	__access_ok((addr),(size),get_fs())
+
+extern inline int
+verify_area (int type, const void *addr, unsigned long size)
+{
+	return access_ok(type,addr,size) ? 0 : -EFAULT;
+}
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * As the alpha uses the same address space for kernel and user
+ * data, we can just do these as direct assignments.  (Of course, the
+ * exception handling means that it's no longer "just"...)
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof/typeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)	__put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)),get_fs())
+#define get_user(x,ptr)	__get_user_check((x),(ptr),sizeof(*(ptr)),get_fs())
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the programmer has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr)	__put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr)	__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+  
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+#define put_user_ret(x,ptr,ret)		({ if (put_user(x,ptr)) return ret; })
+#define get_user_ret(x,ptr,ret)		({ if (get_user(x,ptr)) return ret; })
+#define __put_user_ret(x,ptr,ret)	({ if (__put_user(x,ptr)) return ret; })
+#define __get_user_ret(x,ptr,ret)	({ if (__get_user(x,ptr)) return ret; })
+
+extern void __get_user_unknown (void);
+
+#define __get_user_nocheck(x,ptr,size)				\
+({								\
+	register long __gu_err __asm__ ("r8") = 0;		\
+	register long __gu_val __asm__ ("r9") = 0;		\
+	switch (size) {						\
+	  case 1: __get_user_8(ptr); break;			\
+	  case 2: __get_user_16(ptr); break;			\
+	  case 4: __get_user_32(ptr); break;			\
+	  case 8: __get_user_64(ptr); break;			\
+	  default: __get_user_unknown(); break;			\
+	}							\
+	(x) = (__typeof__(*(ptr))) __gu_val;			\
+	__gu_err;						\
+})
+
+#define __get_user_check(x,ptr,size,segment)			\
+({								\
+	register long __gu_err __asm__ ("r8") = -EFAULT;	\
+	register long __gu_val __asm__ ("r9") = 0;		\
+	const __typeof__(*(ptr)) *__gu_addr = (ptr);		\
+	if (__access_ok((long)__gu_addr,size,segment)) {	\
+		__gu_err = 0;					\
+		switch (size) {					\
+		  case 1: __get_user_8(__gu_addr); break;	\
+		  case 2: __get_user_16(__gu_addr); break;	\
+		  case 4: __get_user_32(__gu_addr); break;	\
+		  case 8: __get_user_64(__gu_addr); break;	\
+		  default: __get_user_unknown(); break;		\
+		}						\
+	}							\
+	(x) = (__typeof__(*(ptr))) __gu_val;			\
+	__gu_err;						\
+})
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __get_user_64(addr)								\
+	__asm__ ("\n1:\tld8 %0=%2\t// %0 and %1 get overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 (2b-1b)|1\n"						\
+		 "\t.previous"								\
+		: "=r"(__gu_val), "=r"(__gu_err)					\
+		: "m"(__m(addr)), "1"(__gu_err));
+
+#define __get_user_32(addr)								\
+	__asm__ ("\n1:\tld4 %0=%2\t// %0 and %1 get overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 (2b-1b)|1\n"						\
+		 "\t.previous"								\
+		: "=r"(__gu_val), "=r"(__gu_err)					\
+		: "m"(__m(addr)), "1"(__gu_err));
+
+#define __get_user_16(addr)								\
+	__asm__ ("\n1:\tld2 %0=%2\t// %0 and %1 get overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 (2b-1b)|1\n"						\
+		 "\t.previous"								\
+		: "=r"(__gu_val), "=r"(__gu_err)					\
+		: "m"(__m(addr)), "1"(__gu_err));
+
+#define __get_user_8(addr)								\
+	__asm__ ("\n1:\tld1 %0=%2\t// %0 and %1 get overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 (2b-1b)|1\n"						\
+		 "\t.previous"								\
+		: "=r"(__gu_val), "=r"(__gu_err)					\
+		: "m"(__m(addr)), "1"(__gu_err));
+
+
+extern void __put_user_unknown (void);
+
+#define __put_user_nocheck(x,ptr,size)				\
+({								\
+	register long __pu_err __asm__ ("r8") = 0;		\
+	switch (size) {						\
+	  case 1: __put_user_8(x,ptr); break;			\
+	  case 2: __put_user_16(x,ptr); break;			\
+	  case 4: __put_user_32(x,ptr); break;			\
+	  case 8: __put_user_64(x,ptr); break;			\
+	  default: __put_user_unknown(); break;			\
+	}							\
+	__pu_err;						\
+})
+
+#define __put_user_check(x,ptr,size,segment)			\
+({								\
+	register long __pu_err __asm__ ("r8") = -EFAULT;	\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
+	if (__access_ok((long)__pu_addr,size,segment)) {	\
+		__pu_err = 0;					\
+		switch (size) {					\
+		  case 1: __put_user_8(x,__pu_addr); break;	\
+		  case 2: __put_user_16(x,__pu_addr); break;	\
+		  case 4: __put_user_32(x,__pu_addr); break;	\
+		  case 8: __put_user_64(x,__pu_addr); break;	\
+		  default: __put_user_unknown(); break;		\
+		}						\
+	}							\
+	__pu_err;						\
+})
+
+/*
+ * The "__put_user_xx()" macros tell gcc they read from memory
+ * instead of writing: this is because they do not write to
+ * any memory gcc knows about, so there are no aliasing issues
+ */
+#define __put_user_64(x,addr)								\
+	__asm__ __volatile__ (								\
+		 "\n1:\tst8 %1=%r2\t// %0 gets overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 2b-1b\n"							\
+		 "\t.previous"								\
+		: "=r"(__pu_err)							\
+		: "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+
+#define __put_user_32(x,addr)								\
+	__asm__ __volatile__ (								\
+		 "\n1:\tst4 %1=%r2\t// %0 gets overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 2b-1b\n"							\
+		 "\t.previous"								\
+		: "=r"(__pu_err)							\
+		: "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+
+#define __put_user_16(x,addr)								\
+	__asm__ __volatile__ (								\
+		 "\n1:\tst2 %1=%r2\t// %0 gets overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 2b-1b\n"							\
+		 "\t.previous"								\
+		: "=r"(__pu_err)							\
+		: "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+
+#define __put_user_8(x,addr)								\
+	__asm__ __volatile__ (								\
+		 "\n1:\tst1 %1=%r2\t// %0 gets overwritten by exception handler\n"	\
+		 "2:\n"									\
+		 "\t.section __ex_table,\"a\"\n"					\
+		 "\t\tdata4 @gprel(1b)\n"						\
+		 "\t\tdata4 2b-1b\n"							\
+		 "\t.previous"								\
+		: "=r"(__pu_err)							\
+		: "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+
+/*
+ * Complex access routines
+ */
+extern unsigned long __copy_user (void *to, const void *from, unsigned long count);
+
+#define __copy_to_user(to,from,n)	__copy_user((to), (from), (n))
+#define __copy_from_user(to,from,n) 	__copy_user((to), (from), (n))
+
+#define copy_to_user(to,from,n)   __copy_tofrom_user((to), (from), (n), 1)
+#define copy_from_user(to,from,n) __copy_tofrom_user((to), (from), (n), 0)
+
+#define __copy_tofrom_user(to,from,n,check_to)							\
+({												\
+	void *__cu_to = (to);									\
+	const void *__cu_from = (from);								\
+	long __cu_len = (n);									\
+												\
+	if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs())) {	\
+		__cu_len = __copy_user(__cu_to, __cu_from, __cu_len);				\
+	}											\
+	__cu_len;										\
+})
+
+#define copy_to_user_ret(to,from,n,retval)	\
+({						\
+	if (copy_to_user(to,from,n))		\
+		return retval;			\
+})
+
+#define copy_from_user_ret(to,from,n,retval)	\
+({						\
+	if (copy_from_user(to,from,n))		\
+		return retval;			\
+})
+
+extern unsigned long __do_clear_user (void *, unsigned long);
+
+#define __clear_user(to,n)			\
+({						\
+	__do_clear_user(to,n);			\
+})
+
+#define clear_user(to,n)					\
+({								\
+	unsigned long __cu_len = (n);				\
+	if (__access_ok((long) to, __cu_len, get_fs())) {	\
+		__cu_len = __do_clear_user(to, __cu_len);	\
+	}							\
+	__cu_len;						\
+})
+
+
+/* Returns: -EFAULT if exception before terminator, N if the entire
+   buffer filled, else strlen.  */
+
+extern long __strncpy_from_user (char *to, const char *from, long to_len);
+
+#define strncpy_from_user(to,from,n)					\
+({									\
+	const char * __sfu_from = (from);				\
+	long __sfu_ret = -EFAULT;					\
+	if (__access_ok((long) __sfu_from, 0, get_fs()))		\
+		__sfu_ret = __strncpy_from_user((to), __sfu_from, (n));	\
+	__sfu_ret;							\
+})
+
+/* Returns: 0 if bad, string length+1 (memory size) of string if ok */
+extern unsigned long __strlen_user (const char *);
+
+#define strlen_user(str)				\
+({							\
+	const char *__su_str = (str);			\
+	unsigned long __su_ret = 0;			\
+	if (__access_ok((long) __su_str, 0, get_fs()))	\
+		__su_ret = __strlen_user(__su_str);	\
+	__su_ret;					\
+})
+
+/*
+ * Returns: 0 if exception before NUL or reaching the supplied limit
+ * (N), a value greater than N if the limit would be exceeded, else
+ * strlen.
+ */
+extern unsigned long __strnlen_user (const char *, long);
+
+#define strnlen_user(str, len)					\
+({								\
+	const char *__su_str = (str);				\
+	unsigned long __su_ret = 0;				\
+	if (__access_ok((long) __su_str, 0, get_fs()))		\
+		__su_ret = __strnlen_user(__su_str, len);	\
+	__su_ret;						\
+})
+
+struct exception_table_entry {
+	int addr;	/* gp-relative address of insn this fixup is for */
+	int skip;	/* number of bytes to skip to get to the continuation point.
+			   Bit 0 tells us if r9 should be cleared to 0*/
+};
+
+extern const struct exception_table_entry *search_exception_table (unsigned long addr);
+
+#endif /* _ASM_IA64_UACCESS_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/unaligned.h linux/include/asm-ia64/unaligned.h
--- v2.3.42/linux/include/asm-ia64/unaligned.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/unaligned.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,123 @@
+#ifndef _ASM_IA64_UNALIGNED_H
+#define _ASM_IA64_UNALIGNED_H
+
+/*
+ * The main single-value unaligned transfer routines.  Derived from
+ * the Linux/Alpha version.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+#define get_unaligned(ptr) \
+	((__typeof__(*(ptr)))ia64_get_unaligned((ptr), sizeof(*(ptr))))
+
+#define put_unaligned(x,ptr) \
+	ia64_put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
+
+/*
+ * EGCS 1.1 knows about arbitrary unaligned loads.  Define some
+ * packed structures to talk about such things with.
+ */
+struct __una_u64 { __u64 x __attribute__((packed)); };
+struct __una_u32 { __u32 x __attribute__((packed)); };
+struct __una_u16 { __u16 x __attribute__((packed)); };
+
+extern inline unsigned long
+__uldq (const unsigned long * r11)
+{
+	const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
+	return ptr->x;
+}
+
+extern inline unsigned long
+__uldl (const unsigned int * r11)
+{
+	const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
+	return ptr->x;
+}
+
+extern inline unsigned long
+__uldw (const unsigned short * r11)
+{
+	const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
+	return ptr->x;
+}
+
+extern inline void
+__ustq (unsigned long r5, unsigned long * r11)
+{
+	struct __una_u64 *ptr = (struct __una_u64 *) r11;
+	ptr->x = r5;
+}
+
+extern inline void
+__ustl (unsigned long r5, unsigned int * r11)
+{
+	struct __una_u32 *ptr = (struct __una_u32 *) r11;
+	ptr->x = r5;
+}
+
+extern inline void
+__ustw (unsigned long r5, unsigned short * r11)
+{
+	struct __una_u16 *ptr = (struct __una_u16 *) r11;
+	ptr->x = r5;
+}
+
+
+/*
+ * This function doesn't actually exist.  The idea is that when
+ * someone uses the macros below with an unsupported size (datatype),
+ * the linker will alert us to the problem via an unresolved reference
+ * error.
+ */
+extern unsigned long ia64_bad_unaligned_access_length (void);
+
+#define ia64_get_unaligned(_ptr,size)				\
+({								\
+	const void *ptr = (_ptr);				\
+	unsigned long val;					\
+								\
+	switch (size) {						\
+	      case 1:						\
+		val = *(const unsigned char *) ptr;		\
+		break;						\
+	      case 2:						\
+		val = __uldw((const unsigned short *)ptr);	\
+		break;						\
+	      case 4:						\
+		val = __uldl((const unsigned int *)ptr);	\
+		break;						\
+	      case 8:						\
+		val = __uldq((const unsigned long *)ptr);	\
+		break;						\
+	      default:						\
+		val = ia64_bad_unaligned_access_length();	\
+	}							\
+	val;							\
+})
+
+#define ia64_put_unaligned(_val,_ptr,size)		\
+do {							\
+	const void *ptr = (_ptr);			\
+	unsigned long val = (_val);			\
+							\
+	switch (size) {					\
+	      case 1:					\
+		*(unsigned char *)ptr = (val);		\
+	        break;					\
+	      case 2:					\
+		__ustw(val, (unsigned short *)ptr);	\
+		break;					\
+	      case 4:					\
+		__ustl(val, (unsigned int *)ptr);	\
+		break;					\
+	      case 8:					\
+		__ustq(val, (unsigned long *)ptr);	\
+		break;					\
+	      default:					\
+	    	ia64_bad_unaligned_access_length();	\
+	}						\
+} while (0)
+
+#endif /* _ASM_IA64_UNALIGNED_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/unistd.h linux/include/asm-ia64/unistd.h
--- v2.3.42/linux/include/asm-ia64/unistd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/unistd.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,305 @@
+#ifndef _ASM_IA64_UNISTD_H
+#define _ASM_IA64_UNISTD_H
+
+/*
+ * IA-64 Linux syscall numbers and inline-functions.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <asm/break.h>
+
+#define __BREAK_SYSCALL			__IA64_BREAK_SYSCALL
+
+#define __NR_ni_syscall			1024
+#define __NR_exit			1025
+#define __NR_read			1026
+#define __NR_write			1027
+#define __NR_open			1028
+#define __NR_close			1029
+#define __NR_creat			1030
+#define __NR_link			1031
+#define __NR_unlink			1032
+#define __NR_execve			1033
+#define __NR_chdir			1034
+#define __NR_fchdir			1035
+#define __NR_utimes			1036
+#define __NR_mknod			1037
+#define __NR_chmod			1038
+#define __NR_chown			1039
+#define __NR_lseek			1040
+#define __NR_getpid			1041
+#define __NR_getppid			1042
+#define __NR_mount			1043
+#define __NR_umount			1044
+#define __NR_setuid			1045
+#define __NR_getuid			1046
+#define __NR_geteuid			1047
+#define __NR_ptrace			1048
+#define __NR_access			1049
+#define __NR_sync			1050
+#define __NR_fsync			1051
+#define __NR_fdatasync			1052
+#define __NR_kill			1053
+#define __NR_rename			1054
+#define __NR_mkdir			1055
+#define __NR_rmdir			1056
+#define __NR_dup			1057
+#define __NR_pipe			1058
+#define __NR_times			1059
+#define __NR_brk			1060
+#define __NR_setgid			1061
+#define __NR_getgid			1062
+#define __NR_getegid			1063
+#define __NR_acct			1064
+#define __NR_ioctl			1065
+#define __NR_fcntl			1066
+#define __NR_umask			1067
+#define __NR_chroot			1068
+#define __NR_ustat			1069
+#define __NR_dup2			1070
+#define __NR_setreuid			1071
+#define __NR_setregid			1072
+#define __NR_getresuid			1073
+#define __NR_setresuid			1074
+#define __NR_getresgid			1075
+#define __NR_setresgid			1076
+#define __NR_getgroups			1077
+#define __NR_setgroups			1078
+#define __NR_getpgid			1079
+#define __NR_setpgid			1080
+#define __NR_setsid			1081
+#define __NR_getsid			1082
+#define __NR_sethostname		1083
+#define __NR_setrlimit			1084
+#define __NR_getrlimit			1085
+#define __NR_getrusage			1086
+#define __NR_gettimeofday		1087
+#define __NR_settimeofday		1088
+#define __NR_select			1089
+#define __NR_poll			1090
+#define __NR_symlink			1091
+#define __NR_readlink			1092
+#define __NR_uselib			1093
+#define __NR_swapon			1094
+#define __NR_swapoff			1095
+#define __NR_reboot			1096
+#define __NR_truncate			1097
+#define __NR_ftruncate			1098
+#define __NR_fchmod			1099
+#define __NR_fchown			1100
+#define __NR_getpriority		1101
+#define __NR_setpriority		1102
+#define __NR_statfs			1103
+#define __NR_fstatfs			1104
+#define __NR_ioperm			1105
+#define __NR_semget			1106
+#define __NR_semop			1107
+#define __NR_semctl			1108
+#define __NR_msgget			1109
+#define __NR_msgsnd			1110
+#define __NR_msgrcv			1111
+#define __NR_msgctl			1112
+#define __NR_shmget			1113
+#define __NR_shmat			1114
+#define __NR_shmdt			1115
+#define __NR_shmctl			1116
+/* also known as klogctl() in GNU libc: */
+#define __NR_syslog			1117
+#define __NR_setitimer			1118
+#define __NR_getitimer			1119
+#define __NR_stat			1120
+#define __NR_lstat			1121
+#define __NR_fstat			1122
+#define __NR_vhangup			1123
+#define __NR_lchown			1124
+#define __NR_vm86			1125
+#define __NR_wait4			1126
+#define __NR_sysinfo			1127
+#define __NR_clone			1128
+#define __NR_setdomainname		1129
+#define __NR_uname			1130
+#define __NR_adjtimex			1131
+#define __NR_create_module		1132
+#define __NR_init_module		1133
+#define __NR_delete_module		1134
+#define __NR_get_kernel_syms		1135
+#define __NR_query_module		1136
+#define __NR_quotactl			1137
+#define __NR_bdflush			1138
+#define __NR_sysfs			1139
+#define __NR_personality		1140
+#define __NR_afs_syscall		1141
+#define __NR_setfsuid			1142
+#define __NR_setfsgid			1143
+#define __NR_getdents			1144
+#define __NR_flock			1145
+#define __NR_readv			1146
+#define __NR_writev			1147
+#define __NR_pread			1148
+#define __NR_pwrite			1149
+#define __NR__sysctl			1150
+#define __NR_mmap			1151
+#define __NR_munmap			1152
+#define __NR_mlock			1153
+#define __NR_mlockall			1154
+#define __NR_mprotect			1155
+#define __NR_mremap			1156
+#define __NR_msync			1157
+#define __NR_munlock			1158
+#define __NR_munlockall			1159
+#define __NR_sched_getparam		1160
+#define __NR_sched_setparam		1161
+#define __NR_sched_getscheduler		1162
+#define __NR_sched_setscheduler		1163
+#define __NR_sched_yield		1164
+#define __NR_sched_get_priority_max	1165
+#define __NR_sched_get_priority_min	1166
+#define __NR_sched_rr_get_interval	1167
+#define __NR_nanosleep			1168
+#define __NR_nfsservctl			1169
+#define __NR_prctl			1170
+#define __NR_getpagesize		1171
+#define __NR_mmap2			1172
+#define __NR_pciconfig_read		1173
+#define __NR_pciconfig_write		1174
+#define __NR_perfmonctl			1175
+#define __NR_sigaltstack		1176
+#define __NR_rt_sigaction		1177
+#define __NR_rt_sigpending		1178
+#define __NR_rt_sigprocmask		1179
+#define __NR_rt_sigqueueinfo		1180
+#define __NR_rt_sigreturn		1181
+#define __NR_rt_sigsuspend		1182
+#define __NR_rt_sigtimedwait		1183
+#define __NR_getcwd			1184
+#define __NR_capget			1185
+#define __NR_capset			1186
+#define __NR_sendfile			1187
+#define __NR_getpmsg			1188
+#define __NR_putpmsg			1189
+#define __NR_socket			1190
+#define __NR_bind			1191
+#define __NR_connect			1192
+#define __NR_listen			1193
+#define __NR_accept			1194
+#define __NR_getsockname		1195
+#define __NR_getpeername		1196
+#define __NR_socketpair			1197
+#define __NR_send			1198
+#define __NR_sendto			1199
+#define __NR_recv			1200
+#define __NR_recvfrom			1201
+#define __NR_shutdown			1202
+#define __NR_setsockopt			1203
+#define __NR_getsockopt			1204
+#define __NR_sendmsg			1205
+#define __NR_recvmsg			1206
+#define __NR_sys_pivot_root		1207
+
+#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
+
+extern long __ia64_syscall (long a0, long a1, long a2, long a3, long a4, long nr);
+
+#define _syscall0(type,name)						\
+type									\
+name (void)								\
+{									\
+	register long dummy1 __asm__ ("out0");				\
+	register long dummy2 __asm__ ("out1");				\
+	register long dummy3 __asm__ ("out2");				\
+	register long dummy4 __asm__ ("out3");				\
+	register long dummy5 __asm__ ("out4");				\
+									\
+	return __ia64_syscall(dummy1, dummy2, dummy3, dummy4, dummy5,	\
+			      __NR_##name);				\
+}
+
+#define _syscall1(type,name,type1,arg1)					\
+type									\
+name (type1 arg1)							\
+{									\
+	register long dummy2 __asm__ ("out1");				\
+	register long dummy3 __asm__ ("out2");				\
+	register long dummy4 __asm__ ("out3");				\
+	register long dummy5 __asm__ ("out4");				\
+									\
+	return __ia64_syscall((long) arg1, dummy2, dummy3, dummy4,	\
+			      dummy5, __NR_##name);			\
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2)			\
+type									\
+name (type1 arg1, type2 arg2)						\
+{									\
+	register long dummy3 __asm__ ("out2");				\
+	register long dummy4 __asm__ ("out3");				\
+	register long dummy5 __asm__ ("out4");				\
+									\
+	return __ia64_syscall((long) arg1, (long) arg2, dummy3, dummy4,	\
+			      dummy5, __NR_##name);			\
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)		\
+type									\
+name (type1 arg1, type2 arg2, type3 arg3)				\
+{									\
+	register long dummy4 __asm__ ("out3");				\
+	register long dummy5 __asm__ ("out4");				\
+									\
+	return __ia64_syscall((long) arg1, (long) arg2, (long) arg3,	\
+			      dummy4, dummy5, __NR_##name);		\
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)	\
+type										\
+name (type1 arg1, type2 arg2, type3 arg3, type4 arg4)				\
+{										\
+	register long dummy5 __asm__ ("out4");					\
+										\
+	return __ia64_syscall((long) arg1, (long) arg2, (long) arg3,		\
+			      (long) arg4, dummy5, __NR_##name);		\
+}
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5)	\
+type											\
+name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)			\
+{											\
+	return __ia64_syscall((long) arg1, (long) arg2, (long) arg3,			\
+			      (long) arg4, (long), __NR_##name);			\
+}
+
+#ifdef __KERNEL_SYSCALLS__
+
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
+static inline _syscall4(pid_t,wait4,pid_t,pid,int *,wait_stat,int,options,struct rusage*, rusage)
+static inline _syscall1(int,delete_module,const char *,name)
+static inline _syscall2(pid_t,clone,unsigned long,flags,void*,sp);
+
+#define __NR__exit __NR_exit
+static inline _syscall1(int,_exit,int,exitcode)
+
+static inline pid_t
+waitpid (int pid, int *wait_stat, int flags)
+{
+	return wait4(pid, wait_stat, flags, NULL);
+}
+
+static inline pid_t
+wait (int * wait_stat)
+{
+	return wait4(-1, wait_stat, 0, 0);
+}
+
+#endif /* __KERNEL_SYSCALLS__ */
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_IA64_UNISTD_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/unwind.h linux/include/asm-ia64/unwind.h
--- v2.3.42/linux/include/asm-ia64/unwind.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/unwind.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,77 @@
+#ifndef _ASM_IA64_UNWIND_H
+#define _ASM_IA64_UNWIND_H
+
+/*
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * A simple API for unwinding kernel stacks.  This is used for
+ * debugging and error reporting purposes.  The kernel doesn't need
+ * full-blown stack unwinding with all the bells and whitles, so there
+ * is not much point in implementing the full IA-64 unwind API (though
+ * it would of course be possible to implement the kernel API on top
+ * of it).
+ */
+
+struct task_struct;	/* forward declaration */
+struct switch_stack;	/* forward declaration */
+
+/*
+ * The following declarations are private to the unwind
+ * implementation:
+ */
+
+struct ia64_stack {
+	unsigned long *limit;
+	unsigned long *top;
+};
+
+/*
+ * No user of this module should every access this structure directly
+ * as it is subject to change.  It is declared here solely so we can
+ * use automatic variables.
+ */
+struct ia64_frame_info {
+	struct ia64_stack regstk;
+	unsigned long *bsp;
+	unsigned long top_rnat;		/* RSE NaT collection at top of backing store */
+	unsigned long cfm;
+	unsigned long ip;		/* instruction pointer */
+};
+
+/*
+ * The official API follows below:
+ */
+
+/*
+ * Prepare to unwind blocked task t.
+ */
+extern void ia64_unwind_init_from_blocked_task (struct ia64_frame_info *info,
+						struct task_struct *t);
+
+/*
+ * Prepare to unwind the current task.  For this to work, the kernel
+ * stack identified by REGS must look like this:
+ *
+ *	//		      //
+ *	|		      |
+ *	|   kernel stack      |
+ *	|		      |
+ *	+=====================+
+ *	|   struct pt_regs    |
+ *	+---------------------+ <--- REGS
+ *	| struct switch_stack |
+ *	+---------------------+
+ */
+extern void ia64_unwind_init_from_current (struct ia64_frame_info *info, struct pt_regs *regs);
+
+/*
+ * Unwind to previous to frame.  Returns 0 if successful, negative
+ * number in case of an error.
+ */
+extern int ia64_unwind_to_previous_frame (struct ia64_frame_info *info);
+
+#define ia64_unwind_get_ip(info)	((info)->ip)
+#define ia64_unwind_get_bsp(info)	((unsigned long) (info)->bsp)
+
+#endif /* _ASM_IA64_UNWIND_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/user.h linux/include/asm-ia64/user.h
--- v2.3.42/linux/include/asm-ia64/user.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/user.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,57 @@
+#ifndef _ASM_IA64_USER_H
+#define _ASM_IA64_USER_H
+
+/*
+ * Core file format: The core file is written in such a way that gdb
+ * can understand it and provide useful information to the user (under
+ * linux we use the `trad-core' bfd).  The file contents are as
+ * follows:
+ *
+ *  upage: 1 page consisting of a user struct that tells gdb
+ *	what is present in the file.  Directly after this is a
+ *	copy of the task_struct, which is currently not used by gdb,
+ *	but it may come in handy at some point.  All of the registers
+ *	are stored as part of the upage.  The upage should always be
+ *	only one page long.
+ *  data: The data segment follows next.  We use current->end_text to
+ *	current->brk to pick up all of the user variables, plus any memory
+ *	that may have been sbrk'ed.  No attempt is made to determine if a
+ *	page is demand-zero or if a page is totally unused, we just cover
+ *	the entire range.  All of the addresses are rounded in such a way
+ *	that an integral number of pages is written.
+ *  stack: We need the stack information in order to get a meaningful
+ *	backtrace.  We need to write the data from usp to
+ *	current->start_stack, so we round each of these in order to be able
+ *	to write an integer number of pages.
+ *
+ * Copyright (C) 1998, 1999 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/ptrace.h>
+
+#include <asm/page.h>
+
+#define EF_SIZE		3072	/* XXX fix me */
+
+struct user {
+	unsigned long	regs[EF_SIZE/8+32];	/* integer and fp regs */
+	size_t		u_tsize;		/* text size (pages) */
+	size_t		u_dsize;		/* data size (pages) */
+	size_t		u_ssize;		/* stack size (pages) */
+	unsigned long	start_code;		/* text starting address */
+	unsigned long	start_data;		/* data starting address */
+	unsigned long	start_stack;		/* stack starting address */
+	long int	signal;			/* signal causing core dump */
+	struct regs *	u_ar0;			/* help gdb find registers */
+	unsigned long	magic;			/* identifies a core file */
+	char		u_comm[32];		/* user command name */
+};
+
+#define NBPG			PAGE_SIZE
+#define UPAGES			1
+#define HOST_TEXT_START_ADDR	(u.start_code)
+#define HOST_DATA_START_ADDR	(u.start_data)
+#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
+
+#endif /* _ASM_IA64_USER_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ia64/vga.h linux/include/asm-ia64/vga.h
--- v2.3.42/linux/include/asm-ia64/vga.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/vga.h	Sun Feb  6 18:42:40 2000
@@ -0,0 +1,22 @@
+/*
+ *	Access to VGA videoram
+ *
+ *	(c) 1998 Martin Mares <mj@ucw.cz>
+ *	(c) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ *	(c) 1999 Don Dugger <don.dugger@intel.com>
+ */
+
+#ifndef __ASM_IA64_VGA_H_
+#define __ASM_IA64_VGA_H_
+
+/*
+ * On the PC, we can just recalculate addresses and then access the
+ * videoram directly without any black magic.
+ */
+
+#define VGA_MAP_MEM(x)	((unsigned long) ioremap((x), 0))
+
+#define vga_readb(x)	(*(x))
+#define vga_writeb(x,y)	(*(y) = (x))
+
+#endif /* __ASM_IA64_VGA_H_ */
diff -u --recursive --new-file v2.3.42/linux/include/asm-m68k/mmu_context.h linux/include/asm-m68k/mmu_context.h
--- v2.3.42/linux/include/asm-m68k/mmu_context.h	Fri Jan 28 15:09:09 2000
+++ linux/include/asm-m68k/mmu_context.h	Mon Feb  7 20:01:14 2000
@@ -9,6 +9,9 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
 extern inline void
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
diff -u --recursive --new-file v2.3.42/linux/include/asm-m68k/pgalloc.h linux/include/asm-m68k/pgalloc.h
--- v2.3.42/linux/include/asm-m68k/pgalloc.h	Fri Jan 28 15:09:09 2000
+++ linux/include/asm-m68k/pgalloc.h	Tue Feb  8 18:23:13 2000
@@ -396,4 +396,9 @@
 		__asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr));
 }
 
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+}
+
 #endif /* _M68K_PGALLOC_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-mips/mmu_context.h linux/include/asm-mips/mmu_context.h
--- v2.3.42/linux/include/asm-mips/mmu_context.h	Sun Jul 25 13:45:25 1999
+++ linux/include/asm-mips/mmu_context.h	Mon Feb  7 20:01:15 2000
@@ -11,6 +11,10 @@
 #ifndef __ASM_MIPS_MMU_CONTEXT_H
 #define __ASM_MIPS_MMU_CONTEXT_H
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
+
 /* Fuck.  The f-word is here so you can grep for it :-)  */
 extern unsigned long asid_cache;
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h
--- v2.3.42/linux/include/asm-mips/pgtable.h	Sun Jul 25 13:45:25 1999
+++ linux/include/asm-mips/pgtable.h	Tue Feb  8 18:23:13 2000
@@ -47,6 +47,10 @@
 			       unsigned long end);
 extern void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page);
 
+extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+}
+
 /*
  * - add_wired_entry() add a fixed TLB entry, and move wired register
  */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
--- v2.3.42/linux/include/asm-ppc/bitops.h	Thu Jan  7 12:06:54 1999
+++ linux/include/asm-ppc/bitops.h	Wed Feb  9 19:47:20 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: bitops.h,v 1.11 1999/01/03 20:16:48 cort Exp $
+ * $Id: bitops.h,v 1.12 2000/02/09 03:28:31 davem Exp $
  * bitops.h: Bit string operations on the ppc
  */
 
@@ -88,11 +88,11 @@
 }
 #endif
 
-extern __inline__ unsigned long test_bit(int nr, __const__ volatile void *addr)
+extern __inline__ int test_bit(int nr, __const__ volatile void *addr)
 {
 	__const__ unsigned int *p = (__const__ unsigned int *) addr;
 
-	return (p[nr >> 5] >> (nr & 0x1f)) & 1UL;
+	return ((p[nr >> 5] >> (nr & 0x1f)) & 1) != 0;
 }
 
 extern __inline__ int ffz(unsigned int x)
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/bootinfo.h linux/include/asm-ppc/bootinfo.h
--- v2.3.42/linux/include/asm-ppc/bootinfo.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-ppc/bootinfo.h	Wed Feb  9 19:43:47 2000
@@ -9,6 +9,12 @@
 #ifndef _PPC_BOOTINFO_H
 #define _PPC_BOOTINFO_H
 
+#include <linux/config.h>
+
+#if defined(CONFIG_APUS) && !defined(__BOOTER__)
+#include <asm-m68k/bootinfo.h>
+#else
+
 struct bi_record {
     unsigned long tag;			/* tag ID */
     unsigned long size;			/* size of record (in bytes) */
@@ -22,6 +28,8 @@
 #define BI_INITRD		0x1014
 #define BI_SYSMAP		0x1015
 #define BI_MACHTYPE		0x1016
+
+#endif /* CONFIG_APUS */
 
 #endif /* _PPC_BOOTINFO_H */
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/feature.h linux/include/asm-ppc/feature.h
--- v2.3.42/linux/include/asm-ppc/feature.h	Sat Oct  9 11:47:50 1999
+++ linux/include/asm-ppc/feature.h	Wed Feb  9 19:43:47 2000
@@ -8,12 +8,13 @@
  * for more details.
  *
  * Copyright (C) 1998 Paul Mackerras.
+ * 
  */
 #ifndef __ASM_PPC_FEATURE_H
 #define __ASM_PPC_FEATURE_H
 
 /*
- * The FCR bits for particular features vary somewhat between
+ * The FCR selector for particular features vary somewhat between
  * different machines.  So we abstract a list of features here
  * and let the feature_* routines map them to the actual bits.
  */
@@ -25,19 +26,23 @@
 	FEATURE_Serial_IO_B,
 	FEATURE_SWIM3_enable,
 	FEATURE_MESH_enable,
-	FEATURE_IDE_enable,
-	FEATURE_VIA_enable,
-	FEATURE_CD_power,
+	FEATURE_IDE0_enable,		/* Internal IDE */
+	FEATURE_IDE0_reset,		/* Internal IDE */
+	FEATURE_IOBUS_enable,		/* Internal IDE */
 	FEATURE_Mediabay_reset,
-	FEATURE_Mediabay_enable,
+	FEATURE_Mediabay_power,
 	FEATURE_Mediabay_PCI_enable,
-	FEATURE_Mediabay_IDE_enable,
+	FEATURE_Mediabay_IDE_enable,	/* Also IDE 1 */
+	FEATURE_Mediabay_IDE_reset,	/* Also IDE 1 */
 	FEATURE_Mediabay_floppy_enable,
 	FEATURE_BMac_reset,
 	FEATURE_BMac_IO_enable,
-	FEATURE_Modem_Reset,
-	FEATURE_IDE_DiskPower,
-	FEATURE_IDE_Reset,
+	FEATURE_Modem_power,
+	FEATURE_Slow_SCC_PCLK,
+	FEATURE_Sound_power,
+	FEATURE_Sound_CLK_enable,
+	FEATURE_IDE2_enable,
+	FEATURE_IDE2_reset,
 	FEATURE_last,
 };
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/heathrow.h linux/include/asm-ppc/heathrow.h
--- v2.3.42/linux/include/asm-ppc/heathrow.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/heathrow.h	Wed Feb  9 19:43:47 2000
@@ -0,0 +1,45 @@
+/*
+ * heathrow.h: definitions for using the "Heathrow" I/O controller chip.
+ *
+ * Grabbed from Open Firmware definitions on a PowerBook G3 Series
+ *
+ * Copyright (C) 1997 Paul Mackerras.
+ */
+
+/* offset from ohare base for feature control register */
+#define HEATHROW_FEATURE_REG	0x38
+
+/*
+ * Bits in feature control register.
+ * Bits postfixed with a _N are in inverse logic
+ */
+#define HRW_RESET_SCC		1		/* Named in_use_led in OF ??? */
+#define HRW_BAY_POWER_N		2
+#define HRW_BAY_PCI_ENABLE	4
+#define HRW_BAY_IDE_ENABLE	8
+#define HRW_BAY_FLOPPY_ENABLE	0x10
+#define HRW_IDE0_ENABLE		0x20
+#define HRW_IDE0_RESET_N	0x40
+#define HRW_BAY_RESET_N		0x80
+#define HRW_IOBUS_ENABLE	0x100		/* Internal IDE ? */
+#define HRW_SCC_ENABLE		0x200
+#define HRW_MESH_ENABLE		0x400
+#define HRW_SWIM_ENABLE		0x800
+#define HRW_SOUND_POWER_N	0x1000
+#define HRW_SOUND_CLK_ENABLE	0x2000
+#define HRW_SCCA_IO		0x4000
+#define HRW_SCCB_IO		0x8000
+#define HRW_PORT_OR_DESK_VIA_N	0x10000		/* This one is 0 on PowerBook */
+#define HRW_PWM_MON_ID_N	0x20000		/* ??? (0) */
+#define HRW_HOOK_MB_CNT_N	0x40000		/* ??? (0) */
+#define HRW_SWIM_CLONE_FLOPPY	0x80000		/* ??? (0) */
+#define HRW_AUD_RUN22		0x100000	/* ??? (1) */
+#define HRW_SCSI_LINK_MODE	0x200000	/* Read ??? (1) */
+#define HRW_ARB_BYPASS		0x400000	/* ??? (0 on main, 1 on gatwick) */
+#define HRW_IDE1_RESET_N	0x800000	/* Media bay */
+#define HRW_SLOW_SCC_PCLK	0x1000000	/* ??? (0) */
+#define HRW_MODEM_POWER_N	0x2000000	/* Used by internal modem on wallstreet */
+#define HRW_MFDC_CELL_ENABLE	0x4000000	/* ??? (0) */
+#define HRW_USE_MFDC		0x8000000	/* ??? (0) */
+#define HRW_BMAC_IO_ENABLE	0x60000000	/* two bits, not documented in OF */
+#define HRW_BMAC_RESET		0x80000000	/* not documented in OF */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h
--- v2.3.42/linux/include/asm-ppc/irq.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-ppc/irq.h	Wed Feb  9 19:43:47 2000
@@ -129,10 +129,9 @@
 
 /*
  * this is the # irq's for all ppc arch's (pmac/chrp/prep)
- * so it is the max of them all - which happens to be powermac
- * at present (G3 powermacs have 64).
+ * so it is the max of them all
  */
-#define NR_IRQS			128
+#define NR_IRQS			256
 
 #endif /* CONFIG_APUS */
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h
--- v2.3.42/linux/include/asm-ppc/machdep.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-ppc/machdep.h	Wed Feb  9 19:43:47 2000
@@ -21,7 +21,7 @@
 	unsigned int	(*irq_cannonicalize)(unsigned int irq);
 	void		(*init_IRQ)(void);
 	int		(*get_irq)(struct pt_regs *);
-	void		(*post_irq)( int );
+	void		(*post_irq)( struct pt_regs *, int );
 	
 	/* A general init function, called by ppc_init in init/main.c.
 	   May be NULL. */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/mediabay.h linux/include/asm-ppc/mediabay.h
--- v2.3.42/linux/include/asm-ppc/mediabay.h	Sun Nov 15 10:51:50 1998
+++ linux/include/asm-ppc/mediabay.h	Wed Feb  9 19:43:47 2000
@@ -8,6 +8,7 @@
 #define _PPC_MEDIABAY_H
 
 #define MB_FD	0		/* media bay contains floppy drive */
+#define MB_FD1	1		/* media bay contains floppy drive */
 #define MB_CD	3		/* media bay contains ATA drive such as CD */
 #define MB_NO	7		/* media bay contains nothing */
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/mmu.h linux/include/asm-ppc/mmu.h
--- v2.3.42/linux/include/asm-ppc/mmu.h	Wed Jun 30 11:24:55 1999
+++ linux/include/asm-ppc/mmu.h	Wed Feb  9 19:43:47 2000
@@ -310,4 +310,61 @@
  * a processor working register during a tablewalk.
  */
 #define M_TW		799
+
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified,
+ * 64-entry, fully-associative TLB which is maintained totally under
+ * software control. In addition, the instruction side has a
+ * hardware-managed, 4-entry, fully- associative TLB which serves as a
+ * first level to the shared TLB. These two TLBs are known as the UTLB
+ * and ITLB, respectively.
+ */
+
+#define        PPC4XX_TLB_SIZE 64
+
+/*
+ * TLB entries are defined by a "high" tag portion and a "low" data
+ * portion.  On all architectures, the data portion is 32-bits.
+ *
+ * TLB entries are managed entirely under software control by reading,
+ * writing, and searchoing using the 4xx-specific tlbre, tlbwr, and tlbsx
+ * instructions.
+ */
+
+#define	TLB_LO          1
+#define	TLB_HI          0
+       
+#define	TLB_DATA        TLB_LO
+#define	TLB_TAG         TLB_HI
+
+/* Tag portion */
+
+#define TLB_EPN_MASK    0xFFFFFC00      /* Effective Page Number */
+#define TLB_PAGESZ_MASK 0x00000380
+#define TLB_PAGESZ(x)   (((x) & 0x7) << 7)
+#define   PAGESZ_1K		0
+#define   PAGESZ_4K             1
+#define   PAGESZ_16K            2
+#define   PAGESZ_64K            3
+#define   PAGESZ_256K           4
+#define   PAGESZ_1M             5
+#define   PAGESZ_4M             6
+#define   PAGESZ_16M            7
+#define TLB_VALID       0x00000040      /* Entry is valid */
+
+/* Data portion */
+                 
+#define TLB_RPN_MASK    0xFFFFFC00      /* Real Page Number */
+#define TLB_PERM_MASK   0x00000300
+#define TLB_EX          0x00000200      /* Instruction execution allowed */
+#define TLB_WR          0x00000100      /* Writes permitted */
+#define TLB_ZSEL_MASK   0x000000F0
+#define TLB_ZSEL(x)     (((x) & 0xF) << 4)
+#define TLB_ATTR_MASK   0x0000000F
+#define TLB_W           0x00000008      /* Caching is write-through */
+#define TLB_I           0x00000004      /* Caching is inhibited */
+#define TLB_M           0x00000002      /* Memory is coherent */
+#define TLB_G           0x00000001      /* Memory is guarded from prefetch */
+
 #endif /* _PPC_MMU_H_ */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- v2.3.42/linux/include/asm-ppc/mmu_context.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-ppc/mmu_context.h	Mon Feb  7 20:01:15 2000
@@ -19,6 +19,9 @@
         -- Dan
  */
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
 #ifdef CONFIG_8xx
 #define NO_CONTEXT      	16
 #define LAST_CONTEXT    	15
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/ohare.h linux/include/asm-ppc/ohare.h
--- v2.3.42/linux/include/asm-ppc/ohare.h	Sat Oct  9 11:47:50 1999
+++ linux/include/asm-ppc/ohare.h	Wed Feb  9 19:43:47 2000
@@ -2,6 +2,9 @@
  * ohare.h: definitions for using the "O'Hare" I/O controller chip.
  *
  * Copyright (C) 1997 Paul Mackerras.
+ * 
+ * BenH: Changed to match those of heathrow (but not all of them). Please
+ *       check if I didn't break anything (especially the media bay).
  */
 
 /* offset from ohare base for feature control register */
@@ -13,21 +16,21 @@
  * and may differ for other machines.
  */
 #define OH_SCC_RESET		1
-#define OH_BAY_RESET		2	/* a guess */
+#define OH_BAY_POWER_N		2	/* a guess */
 #define OH_BAY_PCI_ENABLE	4	/* a guess */
 #define OH_BAY_IDE_ENABLE	8
 #define OH_BAY_FLOPPY_ENABLE	0x10
-#define OH_IDE_ENABLE		0x20
-#define OH_IDE_POWER		0x40	/* a guess */
-#define OH_BAY_ENABLE		0x80
-#define OH_IDE_RESET		0x100	/* 0-based, a guess */
+#define OH_IDE0_ENABLE		0x20
+#define OH_IDE0_RESET_N		0x40	/* a guess */
+#define OH_BAY_RESET_N		0x80
+#define OH_IOBUS_ENABLE		0x100	/* IOBUS seems to be IDE */
 #define OH_SCC_ENABLE		0x200
 #define OH_MESH_ENABLE		0x400
 #define OH_FLOPPY_ENABLE	0x800
 #define OH_SCCA_IO		0x4000
 #define OH_SCCB_IO		0x8000
-#define OH_VIA_ENABLE		0x10000
-#define OH_IDECD_POWER		0x800000
+#define OH_VIA_ENABLE		0x10000	/* Is apparently wrong, to be verified */
+#define OH_IDE1_RESET_N		0x800000
 
 /*
  * Bits to set in the feature control register on PowerBooks.
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- v2.3.42/linux/include/asm-ppc/pci.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-ppc/pci.h	Wed Feb  9 19:43:47 2000
@@ -10,4 +10,56 @@
 #define PCIBIOS_MIN_IO		0x1000
 #define PCIBIOS_MIN_MEM		0x10000000
 
+/* Dynamic DMA Mapping stuff
+ * 	++ajoshi
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/scatterlist.h>
+#include <asm/io.h>
+
+struct pci_dev;
+
+extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+				  dma_addr_t *dma_handle);
+extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+				void *vaddr, dma_addr_t dma_handle);
+extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
+					size_t size)
+{
+	return virt_to_bus(ptr);
+}
+extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+				    size_t size)
+{
+	/* nothing to do */
+}
+extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+			     int nents)
+{
+	return nents;
+}
+extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+				int nents)
+{
+	/* nothing to do */
+}
+extern inline void pci_dma_sync_single(struct pci_dev *hwdev,
+				       dma_addr_t dma_handle,
+				       size_t size)
+{
+	/* nothing to do */
+}
+extern inline void pci_dma_syng_sg(struct pci_dev *hwdev,
+				   struct scatterlist *sg,
+				   int nelems)
+{
+	/* nothing to do */
+}
+
+#define sg_dma_address(sg)	(virt_to_bus((sg)->address))
+#define sg_dma_len(sg)		((sg)->length)
+
 #endif /* __PPC_PCI_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.3.42/linux/include/asm-ppc/pgtable.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-ppc/pgtable.h	Wed Feb  9 19:43:47 2000
@@ -15,7 +15,7 @@
 extern void local_flush_tlb_mm(struct mm_struct *mm);
 extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
-                           unsigned long end);
+				  unsigned long end);
 extern inline void flush_hash_page(unsigned context, unsigned long va)
 	{ }
 #elif defined(CONFIG_8xx)
@@ -48,6 +48,12 @@
 #define flush_tlb_page local_flush_tlb_page
 #define flush_tlb_range local_flush_tlb_range
 
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+				unsigned long start, unsigned long end)
+{
+	/* PPC has hw page tables. */
+}
+
 /*
  * No cache flushing is required when address mappings are
  * changed, because the caches on PowerPCs are physically
@@ -102,6 +108,16 @@
  * copied to the MD_TWC before it gets loaded.
  */
 
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified,
+ * 64-entry, fully-associative TLB which is maintained totally under
+ * software control. In addition, the instruction side has a
+ * hardware-managed, 4-entry, fully-associative TLB which serves as a
+ * first level to the shared TLB. These two TLBs are known as the UTLB
+ * and ITLB, respectively (see "mmu.h" for definitions).
+ */
+
 /* PMD_SHIFT determines the size of the area mapped by the second-level page tables */
 #define PMD_SHIFT	22
 #define PMD_SIZE	(1UL << PMD_SHIFT)
@@ -159,68 +175,19 @@
  */
 
 #if defined(CONFIG_4xx)
-/*
- * At present, all PowerPC 400-class processors share a similar TLB
- * architecture. The instruction and data sides share a unified, 64-entry,
- * fully-associative TLB which is maintained under software control. In
- * addition, the instruction side has a hardware-managed, 4-entry, fully-
- * associative TLB which serves as a first level to the shared TLB. These
- * two TLBs are known as the UTLB and ITLB, respectively.
- */
-
-#define        PPC4XX_TLB_SIZE 64
-
-/*
- * TLB entries are defined by a "high" tag portion and a "low" data portion.
- * On all architectures, the data portion is 32-bits.
- */
-
-#define	TLB_LO          1
-#define	TLB_HI          0
-       
-#define	TLB_DATA        TLB_LO
-#define	TLB_TAG         TLB_HI
-
-/* Tag portion */
-
-#define TLB_EPN_MASK    0xFFFFFC00      /* Effective Page Number */
-#define TLB_PAGESZ_MASK 0x00000380
-#define TLB_PAGESZ(x)   (((x) & 0x7) << 7)
-#define   PAGESZ_1K		0
-#define   PAGESZ_4K             1
-#define   PAGESZ_16K            2
-#define   PAGESZ_64K            3
-#define   PAGESZ_256K           4
-#define   PAGESZ_1M             5
-#define   PAGESZ_4M             6
-#define   PAGESZ_16M            7
-#define TLB_VALID       0x00000040      /* Entry is valid */
-
-/* Data portion */
-                 
-#define TLB_RPN_MASK    0xFFFFFC00      /* Real Page Number */
-#define TLB_PERM_MASK   0x00000300
-#define TLB_EX          0x00000200      /* Instruction execution allowed */
-#define TLB_WR          0x00000100      /* Writes permitted */
-#define TLB_ZSEL_MASK   0x000000F0
-#define TLB_ZSEL(x)     (((x) & 0xF) << 4)
-#define TLB_ATTR_MASK   0x0000000F
-#define TLB_W           0x00000008      /* Caching is write-through */
-#define TLB_I           0x00000004      /* Caching is inhibited */
-#define TLB_M           0x00000002      /* Memory is coherent */
-#define TLB_G           0x00000001      /* Memory is guarded from prefetch */
-
-#define _PAGE_PRESENT	0x001	/* software: pte contains a translation */
-#define _PAGE_USER	0x002	/* matches one of the PP bits */
-#define _PAGE_RW	0x004	/* software: user write access allowed */
-#define _PAGE_GUARDED	0x008
-#define _PAGE_COHERENT	0x010	/* M: enforce memory coherence (SMP systems) */
-#define _PAGE_NO_CACHE	0x020	/* I: cache inhibit */
-#define _PAGE_WRITETHRU	0x040	/* W: cache write-through */
-#define _PAGE_DIRTY	0x080	/* C: page changed */
-#define _PAGE_ACCESSED	0x100	/* R: page referenced */
-#define _PAGE_HWWRITE	0x200	/* software: _PAGE_RW & _PAGE_DIRTY */
+/* Definitions for 4xx embedded chips. */
+#define	_PAGE_GUARDED	0x001	/* G: page is guarded from prefetch */
+#define	_PAGE_COHERENT	0x002	/* M: enforece memory coherence */
+#define	_PAGE_NO_CACHE	0x004	/* I: caching is inhibited */
+#define	_PAGE_WRITETHRU	0x008	/* W: caching is write-through */
+#define	_PAGE_USER	0x010	/* matches one of the zone permission bits */
+#define	_PAGE_PRESENT	0x040	/* software: PTE contains a translation */
+#define _PAGE_DIRTY	0x100	/* C: page changed */
+#define	_PAGE_RW	0x200	/* Writes permitted */
+#define _PAGE_ACCESSED	0x400	/* R: page referenced */
+#define _PAGE_HWWRITE	0x800	/* software: _PAGE_RW & _PAGE_DIRTY */
 #define	_PAGE_SHARED	0
+
 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT	0x0001	/* Page is valid */
@@ -242,7 +209,8 @@
  * protection.
  */
 #define _PAGE_HWWRITE	_PAGE_DIRTY
-#else
+
+#else /* CONFIG_6xx */
 /* Definitions for 60x, 740/750, etc. */
 #define _PAGE_PRESENT	0x001	/* software: pte contains a translation */
 #define _PAGE_USER	0x002	/* matches one of the PP bits */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.3.42/linux/include/asm-ppc/processor.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-ppc/processor.h	Wed Feb  9 19:43:47 2000
@@ -174,7 +174,11 @@
 #define	  HID0_DLOCK	(1<<12)		/* Data Cache Lock */
 #define	  HID0_ICFI	(1<<11)		/* Instr. Cache Flash Invalidate */
 #define	  HID0_DCI	(1<<10)		/* Data Cache Invalidate */
+#define   HID0_SPD	(1<<9)		/* Speculative disable */
+#define   HID0_SGE	(1<<7)		/* Store Gathering Enable */
 #define	  HID0_SIED	(1<<7)		/* Serial Instr. Execution [Disable] */
+#define   HID0_BTIC	(1<<5)		/* Branch Target Instruction Cache Enable */
+#define   HID0_ABE	(1<<3)		/* Address Broadcast Enable */
 #define	  HID0_BHTE	(1<<2)		/* Branch History Table Enable */
 #define	  HID0_BTCD	(1<<1)		/* Branch target cache disable */
 #define	SPRN_HID1	0x3F1	/* Hardware Implementation Register 1 */
@@ -339,6 +343,7 @@
 #define	TBRU	SPRN_TBRU	/* Time Base Read Upper Register */
 #define	TBWL	SPRN_TBWL	/* Time Base Write Lower Register */
 #define	TBWU	SPRN_TBWU	/* Time Base Write Upper Register */
+#define ICTC	1019
 #define	THRM1	SPRN_THRM1	/* Thermal Management Register 1 */
 #define	THRM2	SPRN_THRM2	/* Thermal Management Register 2 */
 #define	THRM3	SPRN_THRM3	/* Thermal Management Register 3 */
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h
--- v2.3.42/linux/include/asm-ppc/prom.h	Sat Oct  9 11:47:50 1999
+++ linux/include/asm-ppc/prom.h	Wed Feb  9 19:43:47 2000
@@ -63,7 +63,7 @@
 
 /* Prototypes */
 extern void abort(void);
-extern void prom_init(int, int, prom_entry);
+extern unsigned long prom_init(int, int, prom_entry);
 extern void prom_print(const char *msg);
 extern void relocate_nodes(void);
 extern void finish_device_tree(void);
@@ -72,7 +72,10 @@
 extern struct device_node *find_path_device(const char *path);
 extern struct device_node *find_compatible_devices(const char *type,
 						   const char *compat);
+extern struct device_node *find_pci_device_OFnode(unsigned char bus,
+	unsigned char dev_fn);
 extern struct device_node *find_phandle(phandle);
+extern struct device_node *find_all_nodes(void);
 extern int device_is_compatible(struct device_node *device, const char *);
 extern int machine_is_compatible(const char *compat);
 extern unsigned char *get_property(struct device_node *node, const char *name,
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- v2.3.42/linux/include/asm-ppc/semaphore.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-ppc/semaphore.h	Wed Feb  9 19:43:47 2000
@@ -4,6 +4,9 @@
 /*
  * Swiped from asm-sparc/semaphore.h and modified
  * -- Cort (cort@cs.nmt.edu)
+ *
+ * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h
+ * -- Ani Joshi (ajoshi@unixbox.com)
  */
 
 #ifdef __KERNEL__
@@ -101,6 +104,99 @@
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }	
+
+
+/* RW spinlock-based semaphores */
+
+struct rw_semaphore
+{
+	spinlock_t lock;
+	int rd, wr;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
+};
+
+#define __RWSEM_INITIALIZER(name, rd, wr)		\
+{							\
+	SPIN_LOCK_UNLOCKED,				\
+	(rd), (wr),					\
+	__WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+	__SEM_DEBUG_INIT(name)				\
+}
+
+#define __DECLARE_RWSEM_GENERIC(name, rd, wr)		\
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name, rd, wr)
+
+#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name, 0, 0)
+#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, 1, 0)
+#define DECLAER_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, 0, 1)
+
+extern inline void init_rwsem(struct rw_semaphore *sem)
+{
+	spin_lock_init(&sem->lock);
+	sem->rd = sem->wr = 0;
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+#endif
+}
+
+#ifndef CHECK_MAGIC
+#define CHECK_MAGIC(x)
+#endif
+
+extern void down_read_failed(struct rw_semaphore *);
+extern void down_write_failed(struct rw_semaphore *);
+
+extern inline void down_read(struct rw_semaphore *sem)
+{
+	CHECK_MAGIC(sem->__magic);
+
+	spin_lock_irq(&sem->lock);
+	if (sem->wr)
+		down_read_failed(sem);
+	sem->rd++;
+	spin_unlock_irq(&sem->lock);
+}
+
+extern inline void down_write(struct rw_semaphore *sem)
+{
+	CHECK_MAGIC(sem->__magic);
+
+	spin_lock(&sem->lock);
+	if(sem->rd || sem->wr)
+		down_write_failed(sem);
+	sem->wr = 1;
+	spin_unlock(&sem->lock);
+}
+
+#define up_read(sem)							\
+	do {								\
+		unsigned long flags;					\
+									\
+		CHECK_MAGIC((sem)->__magic);				\
+									\
+		spin_lock_irqsave(&(sem)->lock, flags);			\
+		if (!--(sem)->rd && waitqueue_active(&(sem)->wait))	\
+			wake_up(&(sem)->wait);				\
+		spin_unlock_irqrestore(&(sem)->lock, flags);		\
+	} while (0)
+
+#define up_write(sem)							\
+	do {								\
+		unsigned long flags;					\
+									\
+		CHECK_MAGIC((sem)->__magic);				\
+									\
+		spin_lock_irqsave(&(sem)->lock, flags);			\
+		(sem)->wr = 0;						\
+		if (waitqueue_active(&(sem)->wait))			\
+			wake_up(&(sem)->wait);				\
+		spin_unlock_irqrestore(&(sem)->lock, flags);		\
+	} while (0)
+
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/types.h linux/include/asm-ppc/types.h
--- v2.3.42/linux/include/asm-ppc/types.h	Wed Mar 10 21:30:32 1999
+++ linux/include/asm-ppc/types.h	Wed Feb  9 19:43:47 2000
@@ -41,6 +41,10 @@
 
 #define BITS_PER_LONG 32
 
+/* DMA addresses are 32-bits wide */
+
+typedef u32 dma_addr_t;
+
 #endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/asm-ppc/vga.h linux/include/asm-ppc/vga.h
--- v2.3.42/linux/include/asm-ppc/vga.h	Thu Apr 29 12:39:07 1999
+++ linux/include/asm-ppc/vga.h	Wed Feb  9 19:43:47 2000
@@ -8,43 +8,33 @@
 #define _LINUX_ASM_VGA_H_
 
 #include <asm/io.h>
-#include <asm/processor.h>
 
 #include <linux/config.h>
-#include <linux/console.h>
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
 
 #define VT_BUF_HAVE_RW
+/*
+ *  These are only needed for supporting VGA or MDA text mode, which use little
+ *  endian byte ordering.
+ *  In other cases, we can optimize by using native byte ordering and
+ *  <linux/vt_buffer.h> has already done the right job for us.
+ */
 
 extern inline void scr_writew(u16 val, u16 *addr)
 {
-	/* If using vgacon (not fbcon) byteswap the writes.
-	 * If non-vgacon assume fbcon and don't byteswap
-	 * just like include/linux/vt_buffer.h.
-	 * XXX: this is a performance loss so get rid of it
-	 *      as soon as fbcon works on prep.
-	 * -- Cort
-	 */
-#ifdef CONFIG_FB
-	if ( conswitchp != &vga_con )
-		(*(addr) = (val));
-	else
-#endif /* CONFIG_FB */
-		st_le16(addr, val);
+    writew(val, (unsigned long)addr);
 }
 
 extern inline u16 scr_readw(const u16 *addr)
 {
-#ifdef CONFIG_FB
-	if ( conswitchp != &vga_con )
-		return (*(addr));
-	else
-#endif /* CONFIG_FB */
-		return ld_le16((unsigned short *)addr);
+    return readw((unsigned long)addr);
 }
 
-#define VT_BUF_HAVE_MEMCPYF
-#define scr_memcpyw_from memcpy
-#define scr_memcpyw_to memcpy
+#define VT_BUF_HAVE_MEMCPYW
+#define scr_memcpyw	memcpy
+
+#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */
 
 extern unsigned long vgacon_remap_base;
 #define VGA_MAP_MEM(x) (x + vgacon_remap_base)
diff -u --recursive --new-file v2.3.42/linux/include/asm-sh/mmu_context.h linux/include/asm-sh/mmu_context.h
--- v2.3.42/linux/include/asm-sh/mmu_context.h	Sun Nov  7 16:37:34 1999
+++ linux/include/asm-sh/mmu_context.h	Mon Feb  7 20:01:15 2000
@@ -11,6 +11,9 @@
      (b) ASID (Address Space IDentifier)
  */
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
 /*
  * Cache of MMU context last used.
  */
diff -u --recursive --new-file v2.3.42/linux/include/asm-sh/pgtable.h linux/include/asm-sh/pgtable.h
--- v2.3.42/linux/include/asm-sh/pgtable.h	Sun Nov  7 16:37:34 1999
+++ linux/include/asm-sh/pgtable.h	Tue Feb  8 18:23:13 2000
@@ -57,6 +57,10 @@
 extern void flush_tlb_range(struct mm_struct *mm, unsigned long start,
 			    unsigned long end);
 extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+}
 
 /*
  * Basically we have the same two-level (which is the logical three level
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h
--- v2.3.42/linux/include/asm-sparc/bitops.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc/bitops.h	Wed Feb  9 19:47:20 2000
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.54 1998/09/21 05:07:34 jj Exp $
+/* $Id: bitops.h,v 1.55 2000/02/09 03:28:32 davem Exp $
  * bitops.h: Bit string operations on the Sparc.
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -94,7 +94,7 @@
  * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
  */
 
-extern __inline__ unsigned long test_and_set_bit(unsigned long nr, __SMPVOL void *addr)
+extern __inline__ int test_and_set_bit(unsigned long nr, __SMPVOL void *addr)
 {
 	register unsigned long mask asm("g2");
 	register unsigned long *ADDR asm("g1");
@@ -116,7 +116,7 @@
 	(void) test_and_set_bit(nr, addr);
 }
 
-extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, __SMPVOL void *addr)
+extern __inline__ int test_and_clear_bit(unsigned long nr, __SMPVOL void *addr)
 {
 	register unsigned long mask asm("g2");
 	register unsigned long *ADDR asm("g1");
@@ -139,7 +139,7 @@
 	(void) test_and_clear_bit(nr, addr);
 }
 
-extern __inline__ unsigned long test_and_change_bit(unsigned long nr, __SMPVOL void *addr)
+extern __inline__ int test_and_change_bit(unsigned long nr, __SMPVOL void *addr)
 {
 	register unsigned long mask asm("g2");
 	register unsigned long *ADDR asm("g1");
@@ -165,9 +165,9 @@
 #endif /* __KERNEL__ */
 
 /* The following routine need not be atomic. */
-extern __inline__ unsigned long test_bit(int nr, __const__ __SMPVOL void *addr)
+extern __inline__ int test_bit(int nr, __const__ __SMPVOL void *addr)
 {
-	return 1UL & (((__const__ unsigned int *) addr)[nr >> 5] >> (nr & 31));
+	return (1 & (((__const__ unsigned int *) addr)[nr >> 5] >> (nr & 31))) != 0;
 }
 
 /* The easy/cheese version for now. */
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc/hardirq.h linux/include/asm-sparc/hardirq.h
--- v2.3.42/linux/include/asm-sparc/hardirq.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc/hardirq.h	Wed Feb  9 20:08:09 2000
@@ -26,6 +26,8 @@
 
 #define synchronize_irq()	barrier()
 
+#define in_irq() (local_irq_count != 0)
+
 #else
 
 #include <asm/atomic.h>
@@ -44,6 +46,9 @@
  */
 #define in_interrupt() ({ int __cpu = smp_processor_id(); \
 	(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
+
+#define in_irq() ({ int __cpu = smp_processor_id(); \
+	(local_irq_count[__cpu] != 0); })
 
 static inline void release_irqlock(int cpu)
 {
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc/mmu_context.h linux/include/asm-sparc/mmu_context.h
--- v2.3.42/linux/include/asm-sparc/mmu_context.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc/mmu_context.h	Mon Feb  7 20:01:15 2000
@@ -5,6 +5,10 @@
 
 #ifndef __ASSEMBLY__
 
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
+
 /*
  * Initialize a new mmu context.  This is invoked when a new
  * address space instance (unique or shared) is instantiated.
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc/pci.h linux/include/asm-sparc/pci.h
--- v2.3.42/linux/include/asm-sparc/pci.h	Fri Jan 28 15:09:09 2000
+++ linux/include/asm-sparc/pci.h	Tue Feb  8 18:23:13 2000
@@ -10,4 +10,89 @@
 #define PCIBIOS_MIN_IO		0UL
 #define PCIBIOS_MIN_MEM		0UL
 
+#ifdef __KERNEL__
+
+/* Dynamic DMA mapping stuff.
+ */
+
+#include <asm/scatterlist.h>
+
+struct pci_dev;
+
+/* Allocate and map kernel buffer using consistent mode DMA for a device.
+ * hwdev should be valid struct pci_dev pointer for PCI devices.
+ */
+extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle);
+
+/* Free and unmap a consistent DMA buffer.
+ * cpu_addr is what was returned from pci_alloc_consistent,
+ * size must be the same as what as passed into pci_alloc_consistent,
+ * and likewise dma_addr must be the same as what *dma_addrp was set to.
+ *
+ * References to the memory and mappings assosciated with cpu_addr/dma_addr
+ * past this call are illegal.
+ */
+extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle);
+
+/* Map a single buffer of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory
+ * until either pci_unmap_single or pci_dma_sync_single is performed.
+ */
+extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size);
+
+/* Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guarenteed to see
+ * whatever the device wrote there.
+ */
+extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size);
+
+/* Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents);
+
+/* Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents);
+
+/* Make physical memory consistent for a single
+ * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, the
+ * device again owns the buffer.
+ */
+extern void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size);
+
+/* Make physical memory consistent for a set of streaming
+ * mode DMA translations after a transfer.
+ *
+ * The same as pci_dma_sync_single but for a scatter-gather list,
+ * same rules and usage.
+ */
+extern void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nelems);
+
+#endif /* __KERNEL__ */
+
 #endif /* __SPARC_PCI_H */
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc/pgalloc.h linux/include/asm-sparc/pgalloc.h
--- v2.3.42/linux/include/asm-sparc/pgalloc.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-sparc/pgalloc.h	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: pgalloc.h,v 1.2 2000/01/15 00:51:42 anton Exp $ */
+/* $Id: pgalloc.h,v 1.3 2000/02/03 10:13:31 jj Exp $ */
 #ifndef _SPARC_PGALLOC_H
 #define _SPARC_PGALLOC_H
 
@@ -68,6 +68,10 @@
 BTFIXUPDEF_CALL(void, flush_tlb_mm, struct mm_struct *)
 BTFIXUPDEF_CALL(void, flush_tlb_range, struct mm_struct *, unsigned long, unsigned long)
 BTFIXUPDEF_CALL(void, flush_tlb_page, struct vm_area_struct *, unsigned long)
+
+extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+}
 
 #define flush_tlb_all() BTFIXUP_CALL(flush_tlb_all)()
 #define flush_tlb_mm(mm) BTFIXUP_CALL(flush_tlb_mm)(mm)
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v2.3.42/linux/include/asm-sparc/pgtable.h	Tue Jan  4 13:57:19 2000
+++ linux/include/asm-sparc/pgtable.h	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.87 1999/12/27 06:37:14 anton Exp $ */
+/* $Id: pgtable.h,v 1.88 2000/02/06 22:56:09 zaitcev Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -50,16 +50,21 @@
 #define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus)
 #define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus)
 
-/* mmu_map/unmap is provided by iommu/iounit; mmu_flush/inval probably belongs to CPU... */
+/*
+ * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep.
+ * mmu_flush/inval belong to CPU. Valid on IIep.
+ */
 BTFIXUPDEF_CALL(void,  mmu_map_dma_area, unsigned long va, __u32 addr, int len)
-BTFIXUPDEF_CALL(void,  mmu_unmap_dma_area, unsigned long addr, int len)
-BTFIXUPDEF_CALL(void,  mmu_inval_dma_area, unsigned long addr, int len)
-BTFIXUPDEF_CALL(void,  mmu_flush_dma_area, unsigned long addr, int len)
+BTFIXUPDEF_CALL(unsigned long /*phys*/, mmu_translate_dvma, unsigned long busa)
+BTFIXUPDEF_CALL(void,  mmu_unmap_dma_area, unsigned long busa, int len)
+BTFIXUPDEF_CALL(void,  mmu_inval_dma_area, unsigned long virt, int len)
+BTFIXUPDEF_CALL(void,  mmu_flush_dma_area, unsigned long virt, int len)
 
 #define mmu_map_dma_area(va, ba,len) BTFIXUP_CALL(mmu_map_dma_area)(va,ba,len)
 #define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len)
-#define mmu_inval_dma_area(va,len) BTFIXUP_CALL(mmu_unmap_dma_area)(va,len)
-#define mmu_flush_dma_area(va,len) BTFIXUP_CALL(mmu_unmap_dma_area)(va,len)
+#define mmu_translate_dvma(ba)     BTFIXUP_CALL(mmu_translate_dvma)(ba)
+#define mmu_inval_dma_area(va,len) BTFIXUP_CALL(mmu_inval_dma_area)(va,len)
+#define mmu_flush_dma_area(va,len) BTFIXUP_CALL(mmu_flush_dma_area)(va,len)
 
 BTFIXUPDEF_SIMM13(pmd_shift)
 BTFIXUPDEF_SETHI(pmd_size)
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc/softirq.h linux/include/asm-sparc/softirq.h
--- v2.3.42/linux/include/asm-sparc/softirq.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc/softirq.h	Wed Feb  9 20:08:09 2000
@@ -14,170 +14,21 @@
 #include <asm/hardirq.h>
 
 
-#define get_active_bhs()	(bh_mask & bh_active)
-
 #ifdef __SMP__
 extern unsigned int local_bh_count[NR_CPUS];
 
-/*
- * The locking mechanism for base handlers, to prevent re-entrancy,
- * is entirely private to an implementation, it should not be
- * referenced at all outside of this file.
- */
-extern atomic_t global_bh_lock;
-extern spinlock_t global_bh_count;
-extern spinlock_t sparc_bh_lock;
-
-extern void synchronize_bh(void);
-
-static inline void clear_active_bhs(unsigned int mask)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&sparc_bh_lock, flags);
-	bh_active &= ~(mask);
-	spin_unlock_irqrestore(&sparc_bh_lock, flags);
-}
-
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-	unsigned long flags;
-	spin_lock_irqsave(&sparc_bh_lock, flags);
-	bh_base[nr] = routine;
-	atomic_set(&bh_mask_count[nr], 0);
-	bh_mask |= 1 << nr;
-	spin_unlock_irqrestore(&sparc_bh_lock, flags);
-}
-
-extern inline void remove_bh(int nr)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&sparc_bh_lock, flags);
-	bh_mask &= ~(1 << nr);
-	bh_base[nr] = NULL;
-	spin_unlock_irqrestore(&sparc_bh_lock, flags);
-}
-
-extern inline void mark_bh(int nr)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&sparc_bh_lock, flags);
-	bh_active |= (1 << nr);
-	spin_unlock_irqrestore(&sparc_bh_lock, flags);
-}
-
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&sparc_bh_lock, flags);
-	bh_mask &= ~(1 << nr);
-	atomic_inc(&bh_mask_count[nr]);
-	spin_unlock_irqrestore(&sparc_bh_lock, flags);
-	synchronize_bh();
-}
-
-extern inline void enable_bh(int nr)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&sparc_bh_lock, flags);
-	if (atomic_dec_and_test(&bh_mask_count[nr]))
-		bh_mask |= 1 << nr;
-	spin_unlock_irqrestore(&sparc_bh_lock, flags);
-}
-
-static inline void start_bh_atomic(void)
-{
-	atomic_inc(&global_bh_lock);
-	synchronize_bh();
-}
-
-static inline void end_bh_atomic(void)
-{
-	atomic_dec(&global_bh_lock);
-}
-
-/* These are for the IRQs testing the lock */
-static inline int softirq_trylock(int cpu)
-{
-	if (spin_trylock(&global_bh_count)) {
-		if (atomic_read(&global_bh_lock) == 0 &&
-		    local_bh_count[cpu] == 0) {
-			++local_bh_count[cpu];
-			return 1;
-		}
-		spin_unlock(&global_bh_count);
-	}
-	return 0;
-}
-
-static inline void softirq_endlock(int cpu)
-{
-	local_bh_count[cpu]--;
-	spin_unlock(&global_bh_count);
-}
-
 #define local_bh_disable()	(local_bh_count[smp_processor_id()]++)
 #define local_bh_enable()	(local_bh_count[smp_processor_id()]--)
 
+#define in_softirq() (local_bh_count[smp_processor_id()] != 0)
+
 #else
 extern unsigned int local_bh_count;
 
-#define clear_active_bhs(x)	(bh_active &= ~(x))
-#define mark_bh(nr)		(bh_active |= (1 << (nr)))
-
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)	(local_bh_count ? 0 : (local_bh_count=1))
-#define softirq_endlock(cpu)	(local_bh_count = 0)
-#define synchronize_bh()	barrier()
-
 #define local_bh_disable()	(local_bh_count++)
 #define local_bh_enable()	(local_bh_count--)
 
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-	bh_mask &= ~(1 << nr);
-	atomic_inc(&bh_mask_count[nr]);
-	synchronize_bh();
-}
-
-extern inline void enable_bh(int nr)
-{
-	if (atomic_dec_and_test(&bh_mask_count[nr]))
-		bh_mask |= 1 << nr;
-}
-
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-	bh_base[nr] = routine;
-	atomic_set(&bh_mask_count[nr], 0);
-	bh_mask |= 1 << nr;
-}
-
-extern inline void remove_bh(int nr)
-{
-	bh_mask &= ~(1 << nr);
-	mb();
-	bh_base[nr] = NULL;
-}
-
-extern inline void start_bh_atomic(void)
-{
-	local_bh_count++;
-	barrier();
-}
-
-extern inline void end_bh_atomic(void)
-{
-	barrier();
-	local_bh_count--;
-}
+#define in_softirq() (local_bh_count != 0)
 
 #endif	/* SMP */
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h
--- v2.3.42/linux/include/asm-sparc64/bitops.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/bitops.h	Wed Feb  9 19:47:20 2000
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.26 1999/01/07 14:14:15 jj Exp $
+/* $Id: bitops.h,v 1.27 2000/02/09 03:28:33 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -20,7 +20,7 @@
  * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
  */
 
-extern __inline__ unsigned long test_and_set_bit(unsigned long nr, void *addr)
+extern __inline__ int test_and_set_bit(unsigned long nr, void *addr)
 {
 	unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
 	unsigned long oldbit;
@@ -60,7 +60,7 @@
 	: "g5", "g7", "cc", "memory");
 }
 
-extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, void *addr)
+extern __inline__ int test_and_clear_bit(unsigned long nr, void *addr)
 {
 	unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
 	unsigned long oldbit;
@@ -100,7 +100,7 @@
 	: "g5", "g7", "cc", "memory");
 }
 
-extern __inline__ unsigned long test_and_change_bit(unsigned long nr, void *addr)
+extern __inline__ int test_and_change_bit(unsigned long nr, void *addr)
 {
 	unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
 	unsigned long oldbit;
@@ -135,9 +135,9 @@
 	: "g5", "g7", "cc", "memory");
 }
 
-extern __inline__ unsigned long test_bit(int nr, __const__ void *addr)
+extern __inline__ int test_bit(int nr, __const__ void *addr)
 {
-	return 1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63));
+	return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL;
 }
 
 /* The easy/cheese version for now. */
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc64/hardirq.h linux/include/asm-sparc64/hardirq.h
--- v2.3.42/linux/include/asm-sparc64/hardirq.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/hardirq.h	Wed Feb  9 20:08:09 2000
@@ -16,9 +16,12 @@
 
 /*
  * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
+ * or hardware interrupt processing?  On any cpu?
  */
 #define in_interrupt() ((local_irq_count + local_bh_count) != 0)
+
+/* This tests only the local processors hw IRQ context disposition.  */
+#define in_irq() (local_irq_count != 0)
 
 #ifndef __SMP__
 
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- v2.3.42/linux/include/asm-sparc64/io.h	Tue Feb  1 01:35:44 2000
+++ linux/include/asm-sparc64/io.h	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.30 2000/01/28 13:43:14 jj Exp $ */
+/* $Id: io.h,v 1.31 2000/02/08 05:11:38 jj Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -13,43 +13,10 @@
 #define __SLOW_DOWN_IO	do { } while (0)
 #define SLOW_DOWN_IO	do { } while (0)
 
-#define NEW_PCI_DMA_MAP
-
-#ifndef NEW_PCI_DMA_MAP
-#define PCI_DVMA_HASHSZ	256
-
-extern unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
-extern unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
-
-#define pci_dvma_ahashfn(addr)	(((addr) >> 24) & 0xff)
-
-extern __inline__ unsigned long virt_to_bus(volatile void *addr)
-{
-	unsigned long vaddr = (unsigned long)addr;
-	unsigned long off;
-
-	/* Handle kernel variable pointers... */
-	if (vaddr < PAGE_OFFSET)
-		vaddr += PAGE_OFFSET - (unsigned long)&empty_zero_page;
-
-	off = pci_dvma_v2p_hash[pci_dvma_ahashfn(vaddr - PAGE_OFFSET)];
-	return vaddr + off;
-}
-
-extern __inline__ void *bus_to_virt(unsigned long addr)
-{
-	unsigned long paddr = addr & 0xffffffffUL;
-	unsigned long off;
-
-	off = pci_dvma_p2v_hash[pci_dvma_ahashfn(paddr)];
-	return (void *)(paddr + off);
-}
-#else
 extern unsigned long virt_to_bus_not_defined_use_pci_map(volatile void *addr);
 #define virt_to_bus virt_to_bus_not_defined_use_pci_map
 extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
 #define bus_to_virt bus_to_virt_not_defined_use_pci_map
-#endif
 
 /* Different PCI controllers we support have their PCI MEM space
  * mapped to an either 2GB (Psycho) or 4GB (Sabre) aligned area,
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h
--- v2.3.42/linux/include/asm-sparc64/mmu_context.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/mmu_context.h	Tue Feb  8 18:23:13 2000
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.41 1999/09/10 15:39:03 jj Exp $ */
+/* $Id: mmu_context.h,v 1.42 2000/02/08 07:47:03 davem Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
@@ -9,6 +9,10 @@
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/spitfire.h>
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
 
 extern spinlock_t ctx_alloc_lock;
 extern unsigned long tlb_context_cache;
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc64/pgalloc.h linux/include/asm-sparc64/pgalloc.h
--- v2.3.42/linux/include/asm-sparc64/pgalloc.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/pgalloc.h	Tue Feb  8 18:23:13 2000
@@ -94,6 +94,28 @@
 
 #endif /* ! __SMP__ */
 
+/* This will change for Cheetah and later chips. */
+#define VPTE_BASE	0xfffffffe00000000
+
+extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start,
+					  unsigned long end)
+{
+	/* Note the signed type.  */
+	long s = start, e = end;
+	if (s > e)
+		/* Nobody should call us with start below VM hole and end above.
+		   See if it is really true.  */
+		BUG();
+#if 0
+	/* Currently free_pgtables guarantees this.  */
+	s &= PMD_MASK;
+	e = (e + PMD_SIZE - 1) & PMD_MASK;
+#endif
+	flush_tlb_range(mm,
+			VPTE_BASE + (s >> (PAGE_SHIFT - 3)),
+			VPTE_BASE + (e >> (PAGE_SHIFT - 3)));
+}
+
 /* Page table allocation/freeing. */
 #ifdef __SMP__
 /* Sliiiicck */
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc64/posix_types.h linux/include/asm-sparc64/posix_types.h
--- v2.3.42/linux/include/asm-sparc64/posix_types.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-sparc64/posix_types.h	Wed Feb  9 19:47:20 2000
@@ -9,11 +9,12 @@
 
 #if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8)
 typedef unsigned long int      __kernel_size_t;
+typedef long int               __kernel_ssize_t;
 #else
 typedef unsigned long long     __kernel_size_t;
+typedef long long              __kernel_ssize_t;
 #endif
 
-typedef long long              __kernel_ssize_t;
 typedef long                   __kernel_ptrdiff_t;
 typedef long                   __kernel_time_t;
 typedef long                   __kernel_clock_t;
diff -u --recursive --new-file v2.3.42/linux/include/asm-sparc64/softirq.h linux/include/asm-sparc64/softirq.h
--- v2.3.42/linux/include/asm-sparc64/softirq.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc64/softirq.h	Wed Feb  9 20:08:09 2000
@@ -19,117 +19,6 @@
 #define local_bh_disable()	(local_bh_count++)
 #define local_bh_enable()	(local_bh_count--)
 
-/* The locking mechanism for base handlers, to prevent re-entrancy,
- * is entirely private to an implementation, it should not be
- * referenced at all outside of this file.
- */
-
-#define get_active_bhs()	(bh_mask & bh_active)
-#define clear_active_bhs(mask)			\
-	__asm__ __volatile__(			\
-"1:	ldx	[%1], %%g7\n"			\
-"	andn	%%g7, %0, %%g5\n"		\
-"	casx	[%1], %%g7, %%g5\n"		\
-"	cmp	%%g7, %%g5\n"			\
-"	bne,pn	%%xcc, 1b\n"			\
-"	 nop"					\
-	: /* no outputs */			\
-	: "HIr" (mask), "r" (&bh_active)	\
-	: "g5", "g7", "cc", "memory")
-
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-	bh_base[nr] = routine;
-	atomic_set(&bh_mask_count[nr], 0);
-	bh_mask |= 1 << nr;
-}
-
-extern inline void remove_bh(int nr)
-{
-	bh_mask &= ~(1 << nr);
-	membar("#StoreStore");
-	bh_base[nr] = NULL;
-}
-
-extern inline void mark_bh(int nr)
-{
-	set_bit(nr, &bh_active);
-}
-
-#ifndef __SMP__
-
-extern inline void start_bh_atomic(void)
-{
-	local_bh_count++;
-	barrier();
-}
-
-extern inline void end_bh_atomic(void)
-{
-	barrier();
-	local_bh_count--;
-}
-
-/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)	(local_bh_count ? 0 : (local_bh_count=1))
-#define softirq_endlock(cpu)	(local_bh_count = 0)
-#define synchronize_bh()	barrier()
-
-#else /* (__SMP__) */
-
-extern atomic_t global_bh_lock;
-extern spinlock_t global_bh_count;
-
-extern void synchronize_bh(void);
-
-static inline void start_bh_atomic(void)
-{
-	atomic_inc(&global_bh_lock);
-	synchronize_bh();
-}
-
-static inline void end_bh_atomic(void)
-{
-	atomic_dec(&global_bh_lock);
-}
-
-/* These are for the IRQs testing the lock */
-static inline int softirq_trylock(int cpu)
-{
-	if (spin_trylock(&global_bh_count)) {
-		if (atomic_read(&global_bh_lock) == 0 &&
-		    cpu_data[cpu].bh_count == 0) {
-			++(cpu_data[cpu].bh_count);
-			return 1;
-		}
-		spin_unlock(&global_bh_count);
-	}
-	return 0;
-}
-
-static inline void softirq_endlock(int cpu)
-{
-	(cpu_data[cpu].bh_count)--;
-	spin_unlock(&global_bh_count);
-}
-
-#endif /* (__SMP__) */
-
-/*
- * These use a mask count to correctly handle
- * nested disable/enable calls
- */
-extern inline void disable_bh(int nr)
-{
-	bh_mask &= ~(1 << nr);
-	atomic_inc(&bh_mask_count[nr]);
-	synchronize_bh();
-}
-
-extern inline void enable_bh(int nr)
-{
-	if (atomic_dec_and_test(&bh_mask_count[nr]))
-		bh_mask |= 1 << nr;
-}
+#define in_softirq() (local_bh_count != 0)
 
 #endif /* !(__SPARC64_SOFTIRQ_H) */
diff -u --recursive --new-file v2.3.42/linux/include/linux/acpi.h linux/include/linux/acpi.h
--- v2.3.42/linux/include/linux/acpi.h	Fri Jan 28 15:09:09 2000
+++ linux/include/linux/acpi.h	Wed Feb  9 21:35:47 2000
@@ -56,15 +56,6 @@
 
 typedef int acpi_dstate_t;
 
-#ifdef __KERNEL__
-
-extern int acpi_active;
-
-extern void (*acpi_idle)(void);
-extern void (*acpi_power_off)(void);
-
-#endif /* __KERNEL__ */
-
 /* RSDP location */
 #define ACPI_BIOS_ROM_BASE (0x0e0000)
 #define ACPI_BIOS_ROM_END  (0x100000)
diff -u --recursive --new-file v2.3.42/linux/include/linux/adfs_fs.h linux/include/linux/adfs_fs.h
--- v2.3.42/linux/include/linux/adfs_fs.h	Fri Apr 23 21:20:38 1999
+++ linux/include/linux/adfs_fs.h	Wed Feb  9 21:32:58 2000
@@ -2,113 +2,43 @@
 #define _ADFS_FS_H
 
 #include <linux/types.h>
-/*
- * Structures of data on the disk
- */
 
 /*
  * Disc Record at disc address 0xc00
  */
 struct adfs_discrecord {
-    unsigned char  log2secsize;
-    unsigned char  secspertrack;
-    unsigned char  heads;
-    unsigned char  density;
-    unsigned char  idlen;
-    unsigned char  log2bpmb;
-    unsigned char  skew;
-    unsigned char  bootoption;
-    unsigned char  lowsector;
-    unsigned char  nzones;
-    unsigned short zone_spare;
-    unsigned long  root;
-    unsigned long  disc_size;
-    unsigned short disc_id;
-    unsigned char  disc_name[10];
-    unsigned long  disc_type;
-    unsigned long  disc_size_high;
-    unsigned char  log2sharesize:4;
-    unsigned char  unused:4;
-    unsigned char  big_flag:1;
+    __u8  log2secsize;
+    __u8  secspertrack;
+    __u8  heads;
+    __u8  density;
+    __u8  idlen;
+    __u8  log2bpmb;
+    __u8  skew;
+    __u8  bootoption;
+    __u8  lowsector;
+    __u8  nzones;
+    __u16 zone_spare;
+    __u32 root;
+    __u32 disc_size;
+    __u16 disc_id;
+    __u8  disc_name[10];
+    __u32 disc_type;
+    __u32 disc_size_high;
+    __u8  log2sharesize:4;
+    __u8  unused40:4;
+    __u8  big_flag:1;
+    __u8  unused41:1;
+    __u8  nzones_high;
+    __u32 format_version;
+    __u32 root_size;
+    __u8  unused52[60 - 52];
 };
 
 #define ADFS_DISCRECORD		(0xc00)
 #define ADFS_DR_OFFSET		(0x1c0)
 #define ADFS_DR_SIZE		 60
+#define ADFS_DR_SIZE_BITS	(ADFS_DR_SIZE << 3)
 #define ADFS_SUPER_MAGIC	 0xadf5
-#define ADFS_FREE_FRAG		 0
-#define ADFS_BAD_FRAG		 1
-#define ADFS_ROOT_FRAG		 2
-
-/*
- * Directory header
- */
-struct adfs_dirheader {
-	unsigned char startmasseq;
-	unsigned char startname[4];
-};
-
-#define ADFS_NEWDIR_SIZE	2048
-#define ADFS_OLDDIR_SIZE	1024
-#define ADFS_NUM_DIR_ENTRIES	77
-
-/*
- * Directory entries
- */
-struct adfs_direntry {
-	char dirobname[10];
-#define ADFS_NAME_LEN 10
-	__u8 dirload[4];
-	__u8 direxec[4];
-	__u8 dirlen[4];
-	__u8 dirinddiscadd[3];
-	__u8 newdiratts;
-#define ADFS_NDA_OWNER_READ	(1 << 0)
-#define ADFS_NDA_OWNER_WRITE	(1 << 1)
-#define ADFS_NDA_LOCKED		(1 << 2)
-#define ADFS_NDA_DIRECTORY	(1 << 3)
-#define ADFS_NDA_EXECUTE	(1 << 4)
-#define ADFS_NDA_PUBLIC_READ	(1 << 5)
-#define ADFS_NDA_PUBLIC_WRITE	(1 << 6)
-};
-
-#define ADFS_MAX_NAME_LEN	255
-struct adfs_idir_entry {
-	__u32		inode_no;			/* Address		*/
-	__u32		file_id;			/* file id		*/
-	__u32		name_len;			/* name length		*/
-	__u32		size;				/* size			*/
-	__u32		mtime;				/* modification time	*/
-	__u32		filetype;			/* RiscOS file type	*/
-	__u8		mode;				/* internal mode	*/
-	char		name[ADFS_MAX_NAME_LEN];	/* file name		*/
-};
-
-/*
- * Directory tail
- */
-union adfs_dirtail {
-	struct {
-		unsigned char dirlastmask;
-		char dirname[10];
-		unsigned char dirparent[3];
-		char dirtitle[19];
-		unsigned char reserved[14];
-		unsigned char endmasseq;
-		unsigned char endname[4];
-		unsigned char dircheckbyte;
-	} old;
-	struct {
-		unsigned char dirlastmask;
-		unsigned char reserved[2];
-		unsigned char dirparent[3];
-		char dirtitle[19];
-		char dirname[10];
-		unsigned char endmasseq;
-		unsigned char endname[4];
-		unsigned char dircheckbyte;
-	} new;
-};
 
 #ifdef __KERNEL__
 /*
@@ -129,47 +59,8 @@
 	return (result & 0xff) != ptr[511];
 }
 
-/* dir.c */
-extern unsigned int adfs_val (unsigned char *p, int len);
-extern int adfs_dir_read_parent (struct inode *inode, struct buffer_head **bhp);
-extern int adfs_dir_read (struct inode *inode, struct buffer_head **bhp);
-extern int adfs_dir_check (struct inode *inode, struct buffer_head **bhp,
-			   int buffers, union adfs_dirtail *dtp);
-extern void adfs_dir_free (struct buffer_head **bhp, int buffers);
-extern int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp,
-			 int buffers, int pos, unsigned long parent_object_id,
-			 struct adfs_idir_entry *ide);
-extern int adfs_dir_find_entry (struct super_block *sb, struct buffer_head **bhp,
-				int buffers, unsigned int index,
-				struct adfs_idir_entry *ide);
-
-/* inode.c */
-extern int adfs_inode_validate (struct inode *inode);
-extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx);
-extern unsigned long adfs_inode_objid (struct inode *inode);
-extern unsigned int adfs_parent_bmap (struct inode *inode, int block);
-extern int adfs_bmap (struct inode *inode, int block);
-extern void adfs_read_inode (struct inode *inode);
-
-/* map.c */
-extern int adfs_map_lookup (struct super_block *sb, int frag_id, int offset);
-
-/* namei.c */
-extern struct dentry *adfs_lookup (struct inode *dir, struct dentry *dentry);
+#endif
 
-/* super.c */
 extern int init_adfs_fs (void);
-extern void adfs_error (struct super_block *, const char *, const char *, ...);
-
-/*
- * Inodes and file operations
- */
-
-/* dir.c */
-extern struct inode_operations adfs_dir_inode_operations;
-
-/* file.c */
-extern struct inode_operations adfs_file_inode_operations;
-#endif
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/adfs_fs_i.h linux/include/linux/adfs_fs_i.h
--- v2.3.42/linux/include/linux/adfs_fs_i.h	Tue Jan 20 16:44:58 1998
+++ linux/include/linux/adfs_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -11,7 +11,13 @@
  * adfs file system inode data in memory
  */
 struct adfs_inode_info {
-	unsigned long	file_id;		/* id of fragments containing actual data */
+	unsigned long mmu_private;
+	unsigned long	parent_id;	/* object id of parent		*/
+	__u32		loadaddr;	/* RISC OS load address		*/
+	__u32		execaddr;	/* RISC OS exec address		*/
+	unsigned int	filetype;	/* RISC OS file type		*/
+	unsigned int	attr;		/* RISC OS permissions		*/
+	int		stamped:1;	/* RISC OS file has date/time	*/
 };
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/adfs_fs_sb.h linux/include/linux/adfs_fs_sb.h
--- v2.3.42/linux/include/linux/adfs_fs_sb.h	Fri Apr 23 21:26:07 1999
+++ linux/include/linux/adfs_fs_sb.h	Sun Feb  6 17:45:25 2000
@@ -1,33 +1,38 @@
 /*
  *  linux/include/linux/adfs_fs_sb.h
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1999 Russell King
  */
 
 #ifndef _ADFS_FS_SB
 #define _ADFS_FS_SB
 
-#include <linux/adfs_fs.h>
+/*
+ * Forward-declare this
+ */
+struct adfs_discmap;
+struct adfs_dir_ops;
 
 /*
- * adfs file system superblock data in memory
+ * ADFS file system superblock data in memory
  */
 struct adfs_sb_info {
-	struct buffer_head *s_sbh;	/* buffer head containing disc record	 */
-	struct adfs_discrecord *s_dr;	/* pointer to disc record in s_sbh	 */
-	uid_t	s_uid;			/* owner uid				 */
-	gid_t	s_gid;			/* owner gid				 */
-	int	s_owner_mask;		/* ADFS Owner perm -> unix perm		 */
-	int	s_other_mask;		/* ADFS Other perm -> unix perm		 */
-	__u16	s_zone_size;		/* size of a map zone in bits		 */
-	__u16	s_ids_per_zone;		/* max. no ids in one zone		 */
-	__u32	s_idlen;		/* length of ID in map			 */
-	__u32	s_map_size;		/* size of a map			 */
-	__u32	s_zonesize;		/* zone size (in map bits)		 */
-	__u32	s_map_block;		/* block address of map			 */
-	struct buffer_head **s_map;	/* bh list containing map		 */
-	__u32	s_root;			/* root disc address			 */
-	__s8	s_map2blk;		/* shift left by this for map->sector	 */
+	struct adfs_discmap *s_map;	/* bh list containing map		 */
+	struct adfs_dir_ops *s_dir;	/* directory operations			 */
+
+	uid_t		s_uid;		/* owner uid				 */
+	gid_t		s_gid;		/* owner gid				 */
+	umode_t		s_owner_mask;	/* ADFS owner perm -> unix perm		 */
+	umode_t		s_other_mask;	/* ADFS other perm -> unix perm		 */
+
+	__u32		s_ids_per_zone;	/* max. no ids in one zone		 */
+	__u32		s_idlen;	/* length of ID in map			 */
+	__u32		s_map_size;	/* sector size of a map			 */
+	unsigned long	s_size;		/* total size (in blocks) of this fs	 */
+	signed int	s_map2blk;	/* shift left by this for map->sector	 */
+	unsigned int	s_log2sharesize;/* log2 share size			 */
+	unsigned int	s_version;	/* disc format version			 */
+	unsigned int	s_namelen;	/* maximum number of characters in name	 */
 };
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/affs_fs.h linux/include/linux/affs_fs.h
--- v2.3.42/linux/include/linux/affs_fs.h	Fri Apr 23 21:20:38 1999
+++ linux/include/linux/affs_fs.h	Thu Feb 10 12:17:00 2000
@@ -105,11 +105,11 @@
 extern struct inode_operations	 affs_file_inode_operations;
 extern struct inode_operations	 affs_file_inode_operations_ofs;
 extern struct inode_operations	 affs_dir_inode_operations;
-extern struct inode_operations	 affs_symlink_inode_operations;
-extern struct inode_operations	 affs_chrdev_inode_operations;
-extern struct inode_operations	 affs_blkdev_inode_operations;
+extern struct address_space_operations	 affs_symlink_aops;
+extern struct address_space_operations	 affs_aops;
 
 extern struct dentry_operations	 affs_dentry_operations;
 extern struct dentry_operations	 affs_dentry_operations_intl;
 
+extern int affs_bmap(struct inode *, int);
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/affs_fs_i.h linux/include/linux/affs_fs_i.h
--- v2.3.42/linux/include/linux/affs_fs_i.h	Wed Aug 18 16:43:30 1999
+++ linux/include/linux/affs_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -29,6 +29,7 @@
  * affs fs inode data in memory
  */
 struct affs_inode_info {
+	unsigned long mmu_private;
 	u32	 i_protect;			/* unused attribute bits */
 	s32	 i_parent;			/* parent ino */
 	s32	 i_original;			/* if != 0, this is the key of the original */
diff -u --recursive --new-file v2.3.42/linux/include/linux/agp_backend.h linux/include/linux/agp_backend.h
--- v2.3.42/linux/include/linux/agp_backend.h	Tue Feb  1 01:35:44 2000
+++ linux/include/linux/agp_backend.h	Thu Feb 10 12:22:03 2000
@@ -48,6 +48,7 @@
 	VIA_GENERIC,
 	VIA_VP3,
 	VIA_MVP3,
+	VIA_MVP4,
 	VIA_APOLLO_PRO,
 	SIS_GENERIC,
 	AMD_GENERIC,
diff -u --recursive --new-file v2.3.42/linux/include/linux/atm.h linux/include/linux/atm.h
--- v2.3.42/linux/include/linux/atm.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/atm.h	Wed Feb  9 21:35:18 2000
@@ -1,6 +1,6 @@
 /* atm.h - general ATM declarations */
  
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  
 
 /*
@@ -20,6 +20,7 @@
 #include <linux/socket.h>
 #include <linux/types.h>
 #endif
+#include <linux/atmapi.h>
 #include <linux/atmsap.h>
 #include <linux/atmioc.h>
 
@@ -84,23 +85,6 @@
  * please speak up ...
  */
 
-/* socket layer */
-#define SO_BCTXOPT	__SO_ENCODE(SOL_SOCKET,16,struct atm_buffconst)
-			    /* not ATM specific - should go somewhere else */
-#define SO_BCRXOPT	__SO_ENCODE(SOL_SOCKET,17,struct atm_buffconst)
-
-
-/* for SO_BCTXOPT and SO_BCRXOPT */
-
-struct atm_buffconst {
-	unsigned long	buf_fac;	/* buffer alignment factor */
-	unsigned long	buf_off;	/* buffer alignment offset */
-	unsigned long	size_fac;	/* buffer size factor */
-	unsigned long	size_off;	/* buffer size offset */
-	unsigned long	min_size;	/* minimum size */
-	unsigned long	max_size;	/* maximum size, 0 = unlimited */
-};
-
 
 /* ATM cell header (for AAL0) */
 
@@ -154,12 +138,28 @@
 	int		min_pcr;	/* minimum PCR in cells per second */
 	int		max_cdv;	/* maximum CDV in microseconds */
 	int		max_sdu;	/* maximum SDU in bytes */
+        /* extra params for ABR */
+        unsigned int 	icr;         	/* Initial Cell Rate (24-bit) */
+        unsigned int	tbe;		/* Transient Buffer Exposure (24-bit) */ 
+        unsigned int 	frtt : 24;	/* Fixed Round Trip Time (24-bit) */
+        unsigned int 	rif  : 4;       /* Rate Increment Factor (4-bit) */
+        unsigned int 	rdf  : 4;       /* Rate Decrease Factor (4-bit) */
+        unsigned int nrm_pres  :1;      /* nrm present bit */
+        unsigned int trm_pres  :1;     	/* rm present bit */
+        unsigned int adtf_pres :1;     	/* adtf present bit */
+        unsigned int cdf_pres  :1;    	/* cdf present bit*/
+        unsigned int nrm       :3;     	/* Max # of Cells for each forward RM cell (3-bit) */
+        unsigned int trm       :3;    	/* Time between forward RM cells (3-bit) */    
+	unsigned int adtf      :10;     /* ACR Decrease Time Factor (10-bit) */
+	unsigned int cdf       :3;      /* Cutoff Decrease Factor (3-bit) */
+        unsigned int spare     :9;      /* spare bits */ 
 };
 
 struct atm_qos {
 	struct atm_trafprm txtp;	/* parameters in TX direction */
-	struct atm_trafprm rxtp;	/* parameters in RX direction */
-	unsigned char aal;
+	struct atm_trafprm rxtp __ATM_API_ALIGN;
+					/* parameters in RX direction */
+	unsigned char aal __ATM_API_ALIGN;
 };
 
 /* PVC addressing */
@@ -177,7 +177,7 @@
 		short	itf;		/* ATM interface */
 		short	vpi;		/* VPI (only 8 bits at UNI) */
 		int	vci;		/* VCI (only 16 bits at UNI) */
-	}		sap_addr;	/* PVC address */
+	} sap_addr __ATM_API_ALIGN;	/* PVC address */
 };
 
 /* SVC addressing */
@@ -209,7 +209,7 @@
     					/* unused addresses must be bzero'ed */
 	char		lij_type;	/* role in LIJ call; one of ATM_LIJ* */
 	uint32_t	lij_id;		/* LIJ call identifier */
-    }			sas_addr;	/* SVC address */
+    } sas_addr __ATM_API_ALIGN;		/* SVC address */
 };
 
 
@@ -234,10 +234,6 @@
     int length;
     void *arg;
 };
-
-
-#define ATM_CREATE_LEAF _IO('a',ATMIOC_SPECIAL+2)
-                                /* create a point-to-multipoint leaf socket */
 
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.3.42/linux/include/linux/atm_eni.h linux/include/linux/atm_eni.h
--- v2.3.42/linux/include/linux/atm_eni.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atm_eni.h	Tue Feb  8 18:23:13 2000
@@ -1,7 +1,7 @@
 /* atm_eni.h - Driver-specific declarations of the ENI driver (for use by
 	       driver-specific utilities) */
 
-/* Written 1995-1997 by Werner Almesberger, EPFL LRC */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #ifndef LINUX_ATM_ENI_H
@@ -9,7 +9,15 @@
 
 #include <linux/atmioc.h>
 
+
+struct eni_multipliers {
+	int tx,rx;	/* values are in percent and must be > 100 */
+};
+
+
 #define ENI_MEMDUMP     _IOW('a',ATMIOC_SARPRV,struct atmif_sioc)
                                                 /* printk memory map */
+#define ENI_SETMULT	_IOW('a',ATMIOC_SARPRV+7,struct atmif_sioc)
+						/* set buffer multipliers */
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/atm_idt77105.h linux/include/linux/atm_idt77105.h
--- v2.3.42/linux/include/linux/atm_idt77105.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/atm_idt77105.h	Tue Feb  8 18:23:13 2000
@@ -0,0 +1,40 @@
+/* atm_idt77105.h - Driver-specific declarations of the IDT77105 driver (for
+ * use by driver-specific utilities) */
+
+/* Written 1999 by Greg Banks <gnb@linuxfan.com>. Copied from atm_suni.h. */
+
+
+#ifndef LINUX_ATM_IDT77105_H
+#define LINUX_ATM_IDT77105_H
+
+#include <asm/types.h>
+#include <linux/atmioc.h>
+
+/*
+ * Structure for IDT77105_GETSTAT and IDT77105_GETSTATZ ioctls.
+ * Pointed to by `arg' in atmif_sioc.
+ */
+struct idt77105_stats {
+        __u32 symbol_errors;  /* wire symbol errors */
+        __u32 tx_cells;       /* cells transmitted */
+        __u32 rx_cells;       /* cells received */
+        __u32 rx_hec_errors;  /* Header Error Check errors on receive */
+};
+
+#define IDT77105_GETLOOP	_IOW('a',ATMIOC_PHYPRV,struct atmif_sioc)	/* get loopback mode */
+#define IDT77105_SETLOOP	_IOW('a',ATMIOC_PHYPRV+1,struct atmif_sioc)	/* set loopback mode */
+#define IDT77105_GETSTAT	_IOW('a',ATMIOC_PHYPRV+2,struct atmif_sioc)	/* get stats */
+#define IDT77105_GETSTATZ	_IOW('a',ATMIOC_PHYPRV+3,struct atmif_sioc)	/* get stats and zero */
+
+
+/*
+ * TODO: what we need is a global loopback mode get/set ioctl for
+ * all devices, not these device-specific hacks -- Greg Banks
+ */
+#define IDT77105_LM_NONE	0	/* no loopback */
+#define IDT77105_LM_DIAG	1	/* diagnostic (i.e. loop TX to RX)
+					 * (a.k.a. local loopback) */
+#define IDT77105_LM_LOOP	2	/* line (i.e. loop RX to TX)
+					 * (a.k.a. remote loopback) */
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/atm_nicstar.h linux/include/linux/atm_nicstar.h
--- v2.3.42/linux/include/linux/atm_nicstar.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atm_nicstar.h	Tue Feb  8 18:23:13 2000
@@ -18,6 +18,7 @@
  * sys/types.h for struct timeval
  */
 
+#include <linux/atmapi.h>
 #include <linux/atmioc.h>
 
 #define NS_GETPSTAT	_IOWR('a',ATMIOC_SARPRV+1,struct atmif_sioc)
@@ -32,7 +33,7 @@
    unsigned min;
    unsigned init;
    unsigned max;
-} buf_nr;
+}buf_nr;
 
 
 typedef struct pool_levels
diff -u --recursive --new-file v2.3.42/linux/include/linux/atm_tcp.h linux/include/linux/atm_tcp.h
--- v2.3.42/linux/include/linux/atm_tcp.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/atm_tcp.h	Tue Feb  8 18:23:13 2000
@@ -1,12 +1,14 @@
 /* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by
 	       driver-specific utilities) */
 
-/* Written 1997-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1997-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #ifndef LINUX_ATM_TCP_H
 #define LINUX_ATM_TCP_H
 
+#include <linux/atmapi.h>
+
 #ifdef __KERNEL__
 #include <linux/types.h>
 #endif
@@ -33,12 +35,12 @@
 
 struct atmtcp_control {
 	struct atmtcp_hdr hdr;	/* must be first */
-	int		type;	/* message type; both directions */
-	unsigned long	vcc;	/* both directions */
+	int type;		/* message type; both directions */
+	atm_kptr_t vcc;		/* both directions */
 	struct sockaddr_atmpvc addr; /* suggested value from kernel */
 	struct atm_qos	qos;	/* both directions */
 	int result;		/* to kernel only */
-};
+} __ATM_API_ALIGN;
 
 /*
  * Field usage:
diff -u --recursive --new-file v2.3.42/linux/include/linux/atm_zatm.h linux/include/linux/atm_zatm.h
--- v2.3.42/linux/include/linux/atm_zatm.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atm_zatm.h	Tue Feb  8 18:23:13 2000
@@ -1,7 +1,7 @@
 /* atm_zatm.h - Driver-specific declarations of the ZATM driver (for use by
 		driver-specific utilities) */
 
-/* Written 1995-1997 by Werner Almesberger, EPFL LRC */
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #ifndef LINUX_ATM_ZATM_H
@@ -12,6 +12,7 @@
  * sys/types.h for struct timeval
  */
 
+#include <linux/atmapi.h>
 #include <linux/atmioc.h>
 
 #define ZATM_GETPOOL	_IOW('a',ATMIOC_SARPRV+1,struct atmif_sioc)
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmapi.h linux/include/linux/atmapi.h
--- v2.3.42/linux/include/linux/atmapi.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/atmapi.h	Tue Feb  8 18:23:13 2000
@@ -0,0 +1,29 @@
+/* atmapi.h - ATM API user space/kernel compatibility */
+ 
+/* Written 1999,2000 by Werner Almesberger, EPFL ICA */
+ 
+
+#ifndef _LINUX_ATMAPI_H
+#define _LINUX_ATMAPI_H
+
+#ifdef __sparc__
+/* such alignment is not required on 32 bit sparcs, but we can't
+   figure that we are on a sparc64 while compiling user-space programs. */
+#define __ATM_API_ALIGN	__attribute__((aligned(8)))
+#else
+#define __ATM_API_ALIGN
+#endif
+
+
+/*
+ * Opaque type for kernel pointers. Note that _ is never accessed. We need
+ * the struct in order hide the array, so that we can make simple assignments
+ * instead of being forced to use memcpy. It also improves error reporting for
+ * code that still assumes that we're passing unsigned longs.
+ *
+ * Convention: NULL pointers are passed as a field of all zeroes.
+ */
+ 
+typedef struct { unsigned char _[8]; } atm_kptr_t;
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmarp.h linux/include/linux/atmarp.h
--- v2.3.42/linux/include/linux/atmarp.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atmarp.h	Wed Feb  9 21:35:18 2000
@@ -1,6 +1,6 @@
 /* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
  
 
 #ifndef _LINUX_ATMARP_H
@@ -9,6 +9,7 @@
 #ifdef __KERNEL__
 #include <linux/types.h>
 #endif
+#include <linux/atmapi.h>
 #include <linux/atmioc.h>
 
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmdev.h linux/include/linux/atmdev.h
--- v2.3.42/linux/include/linux/atmdev.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/atmdev.h	Wed Feb  9 21:35:57 2000
@@ -8,6 +8,8 @@
 
 
 #include <linux/config.h>
+#include <linux/atmapi.h>
+#include <linux/atm.h>
 #include <linux/atmioc.h>
 
 
@@ -26,9 +28,9 @@
 
 
 struct atm_aal_stats {
-	long		tx,tx_err;	/* TX okay and errors */
-	long		rx,rx_err;	/* RX okay and errors */
-	long		rx_drop;	/* RX out of memory */
+	int		tx,tx_err;	/* TX okay and errors */
+	int		rx,rx_err;	/* RX okay and errors */
+	int		rx_drop;	/* RX out of memory */
 };
 
 
@@ -36,7 +38,7 @@
 	struct atm_aal_stats aal0;
 	struct atm_aal_stats aal34;
 	struct atm_aal_stats aal5;
-};
+} __ATM_API_ALIGN;
 
 
 #define ATM_GETLINKRATE	_IOW('a',ATMIOC_ITF+1,struct atmif_sioc)
@@ -123,6 +125,12 @@
 #define ATM_VS2TXT_MAP \
     "IDLE", "CONNECTED", "CLOSING", "LISTEN", "INUSE", "BOUND"
 
+#define ATM_VF2TXT_MAP \
+    "ADDR",	"READY",	"PARTIAL",	"REGIS", \
+    "RELEASED", "HASQOS",	"LISTEN",	"META", \
+    "256",	"512",		"1024",		"2048", \
+    "SESSION",	"HASSAP",	"BOUND",	"CLOSE"
+
 
 #ifdef __KERNEL__
 
@@ -130,8 +138,8 @@
 #include <linux/time.h> /* struct timeval */
 #include <linux/net.h>
 #include <linux/skbuff.h> /* struct sk_buff */
-#include <linux/atm.h>
 #include <linux/uio.h>
+#include <net/sock.h>
 #include <asm/atomic.h>
 
 #ifdef CONFIG_PROC_FS
@@ -156,10 +164,10 @@
 #define ATM_VF_META	128	/* SVC socket isn't used for normal data
 				   traffic and doesn't depend on signaling
 				   to be available */
-#define ATM_VF_AQREL	256	/* Arequipa VC is being released */
-#define ATM_VF_AQDANG	512	/* VC is in Arequipa's dangling list */
-#define ATM_VF_SCRX	ATM_SC_RX /* 1024; allow single-copy in the RX dir. */
-#define ATM_VF_SCTX	ATM_SC_TX /* 2048; allow single-copy in the TX dir. */
+				/*  256; unused */
+				/*  512; unused */
+				/* 1024; unused */
+				/* 2048; unused */
 #define ATM_VF_SESSION	4096	/* VCC is p2mp session control descriptor */
 #define ATM_VF_HASSAP	8192	/* SAP has been set */
 #define ATM_VF_CLOSE	32768	/* asynchronous close - treat like VF_RELEASED*/
@@ -191,7 +199,6 @@
 	struct atm_dev	*dev;		/* device back pointer */
 	struct atm_qos	qos;		/* QOS */
 	struct atm_sap	sap;		/* SAP */
-	unsigned long	tx_quota,rx_quota; /* buffer quotas */
 	atomic_t	tx_inuse,rx_inuse; /* buffer space in use */
 	void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
 	void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
@@ -207,6 +214,7 @@
 	struct atm_aal_stats *stats;	/* pointer to AAL stats group */
 	wait_queue_head_t sleep;	/* if socket is busy */
 	wait_queue_head_t wsleep;	/* if waiting for write buffer space */
+	struct sock	*sk;		/* socket backpointer */
 	struct atm_vcc	*prev,*next;
 	/* SVC part --- may move later ------------------------------------- */
 	short		itf;		/* interface number */
@@ -220,7 +228,9 @@
 	/* Multipoint part ------------------------------------------------- */
 	struct atm_vcc	*session;	/* session VCC descriptor */
 	/* Other stuff ----------------------------------------------------- */
-	void		*user_back;	/* user backlink - not touched */
+	void		*user_back;	/* user backlink - not touched by */
+					/* native ATM stack. Currently used */
+					/* by CLIP and sch_atm. */
 };
 
 
@@ -335,6 +345,12 @@
 static __inline__ void atm_return(struct atm_vcc *vcc,int truesize)
 {
 	atomic_sub(truesize+ATM_PDU_OVHD,&vcc->rx_inuse);
+}
+
+
+static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size)
+{
+	return size+atomic_read(&vcc->tx_inuse)+ATM_PDU_OVHD < vcc->sk->sndbuf;
 }
 
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmioc.h linux/include/linux/atmioc.h
--- v2.3.42/linux/include/linux/atmioc.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atmioc.h	Tue Feb  8 18:23:13 2000
@@ -1,10 +1,10 @@
 /* atmioc.h - ranges for ATM-related ioctl numbers */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC */
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 
 
 /*
- * See http://lrcwww.epfl.ch/linux-atm/magic.html for the complete list of
+ * See http://icawww1.epfl.ch/linux-atm/magic.html for the complete list of
  * "magic" ioctl numbers.
  */
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmlec.h linux/include/linux/atmlec.h
--- v2.3.42/linux/include/linux/atmlec.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atmlec.h	Tue Feb  8 18:23:13 2000
@@ -9,6 +9,7 @@
 #ifndef _ATMLEC_H_
 #define _ATMLEC_H_
 
+#include <linux/atmapi.h>
 #include <linux/atmioc.h>
 #include <linux/atm.h>
 #include <linux/if_ether.h>
@@ -43,15 +44,16 @@
 
 struct atmlec_config_msg {
         unsigned int maximum_unknown_frame_count;
-        unsigned long max_unknown_frame_time;
+        unsigned int max_unknown_frame_time;
         unsigned short max_retry_count;
-        unsigned long aging_time;
-        unsigned long forward_delay_time;
-        unsigned long arp_response_time;
-        unsigned long flush_timeout;
-        unsigned long path_switching_delay;
+        unsigned int aging_time;
+        unsigned int forward_delay_time;
+        unsigned int arp_response_time;
+        unsigned int flush_timeout;
+        unsigned int path_switching_delay;
         unsigned int  lane_version; /* LANE2: 1 for LANEv1, 2 for LANEv2 */
         int mtu;
+        int is_proxy;
 };
  
 struct atmlec_msg {
@@ -61,7 +63,7 @@
                 struct {
                         unsigned char mac_addr[ETH_ALEN];
                         unsigned char atm_addr[ATM_ESA_LEN];
-                        unsigned long flag;/* Topology_change flag, 
+                        unsigned int flag;/* Topology_change flag, 
                                               remoteflag, permanent flag,
                                               lecid, transaction id */
                         unsigned int targetless_le_arp; /* LANE2 */
@@ -73,9 +75,10 @@
                         uint32_t tran_id;                    /* transaction id    */
                         unsigned char mac_addr[ETH_ALEN];    /* dst mac addr      */
                         unsigned char atm_addr[ATM_ESA_LEN]; /* reqestor ATM addr */
-                } proxy; /* For mapping LE_ARP requests to responses. Filled by   */
+                } proxy;
+		     /* For mapping LE_ARP requests to responses. Filled by */
         } content;       /* zeppelin, returned by kernel. Used only when proxying */ 
-};
+} __ATM_API_ALIGN;
 
 struct atmlec_ioc {
         int dev_num;
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmmpc.h linux/include/linux/atmmpc.h
--- v2.3.42/linux/include/linux/atmmpc.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atmmpc.h	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,7 @@
 #ifndef _ATMMPC_H_
 #define _ATMMPC_H_
 
+#include <linux/atmapi.h>
 #include <linux/atmioc.h>
 #include <linux/atm.h>
 
@@ -37,16 +38,16 @@
         uint16_t  holding_time;
 } eg_ctrl_info;
 
-struct mpc_parameters{
+struct mpc_parameters {
         uint16_t mpc_p1;   /* Shortcut-Setup Frame Count    */
         uint16_t mpc_p2;   /* Shortcut-Setup Frame Time     */
         uint8_t mpc_p3[8]; /* Flow-detection Protocols      */
         uint16_t mpc_p4;   /* MPC Initial Retry Time        */
         uint16_t mpc_p5;   /* MPC Retry Time Maximum        */
         uint16_t mpc_p6;   /* Hold Down Time                */      
-};
+} ;
 
-struct k_message{
+struct k_message {
         uint16_t type;
         uint32_t ip_mask;
         uint8_t  MPS_ctrl[ATM_ESA_LEN];
@@ -56,9 +57,10 @@
                 struct mpc_parameters params;
         } content;
         struct atm_qos qos;       
-};
+} __ATM_API_ALIGN;
 
-struct llc_snap_hdr { /* RFC 1483 LLC/SNAP encapsulation for routed IP PDUs */
+struct llc_snap_hdr {
+	/* RFC 1483 LLC/SNAP encapsulation for routed IP PDUs */
         uint8_t  dsap;    /* Destination Service Access Point (0xAA)     */
         uint8_t  ssap;    /* Source Service Access Point      (0xAA)     */
         uint8_t  ui;      /* Unnumbered Information           (0x03)     */
@@ -121,4 +123,3 @@
 #define RELOAD                301 /* kill -HUP the daemon for reload */
 
 #endif /* _ATMMPC_H_ */
-
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmsap.h linux/include/linux/atmsap.h
--- v2.3.42/linux/include/linux/atmsap.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atmsap.h	Tue Feb  8 18:23:13 2000
@@ -1,11 +1,13 @@
 /* atmsap.h - ATM Service Access Point addressing definitions */
 
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #ifndef _LINUX_ATMSAP_H
 #define _LINUX_ATMSAP_H
 
+#include <linux/atmapi.h>
+
 /*
  * BEGIN_xx and END_xx markers are used for automatic generation of
  * documentation. Do not change them.
@@ -116,24 +118,22 @@
 	    unsigned char def_size; /* default packet size (log2), 4-12 (0 to */
 				    /* omit) */
 	    unsigned char window;/* packet window size, 1-127 (0 to omit) */
-	} itu;			/* ITU-T ecoding */
+	} itu;			/* ITU-T encoding */
 	unsigned char user;	/* user specified l3 information */
-	struct {		/* if l3_proto = ATM_L3_H310 */
-	    unsigned char term_type; /* terminal type */
+	struct {		      /* if l3_proto = ATM_L3_H310 */
+	    unsigned char term_type;  /* terminal type */
 	    unsigned char fw_mpx_cap; /* forward multiplexing capability */
 				      /* only if term_type != ATM_TT_NONE */
 	    unsigned char bw_mpx_cap; /* backward multiplexing capability */
 				      /* only if term_type != ATM_TT_NONE */
 	} h310;
-	struct {		/* if l3_proto = ATM_L3_TR9577 */
-	    unsigned char ipi;	/* initial protocol id */
+	struct {		  /* if l3_proto = ATM_L3_TR9577 */
+	    unsigned char ipi;	  /* initial protocol id */
 	    unsigned char snap[5];/* IEEE 802.1 SNAP identifier */
 				  /* (only if ipi == NLPID_IEEE802_1_SNAP) */
 	} tr9577;
     } l3;
-    struct atm_blli *next;	/* next BLLI or NULL (undefined when used in */
-				/* atmsvc_msg) ONLY USED IN OLD-STYLE API */
-};
+} __ATM_API_ALIGN;
 
 
 struct atm_bhli {
@@ -149,7 +149,8 @@
 
 struct atm_sap {
 	struct atm_bhli bhli;		/* local SAP, high-layer information */
-	struct atm_blli blli[ATM_MAX_BLLI]; /* local SAP, low-layer info */
+	struct atm_blli blli[ATM_MAX_BLLI] __ATM_API_ALIGN;
+					/* local SAP, low-layer info */
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/atmsvc.h linux/include/linux/atmsvc.h
--- v2.3.42/linux/include/linux/atmsvc.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/atmsvc.h	Tue Feb  8 18:23:13 2000
@@ -1,11 +1,12 @@
 /* atmsvc.h - ATM signaling kernel-demon interface definitions */
  
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  
 
 #ifndef _LINUX_ATMSVC_H
 #define _LINUX_ATMSVC_H
 
+#include <linux/atmapi.h>
 #include <linux/atm.h>
 #include <linux/atmioc.h>
 
@@ -19,8 +20,8 @@
 
 struct atmsvc_msg {
 	enum atmsvc_msg_type type;
-	unsigned long vcc;
-	unsigned long listen_vcc;	/* indicate */
+	atm_kptr_t vcc;
+	atm_kptr_t listen_vcc;		/* indicate */
 	int reply;			/* for okay and close:		   */
 					/*   < 0: error before active	   */
 					/*        (sigd has discarded ctx) */
@@ -31,12 +32,12 @@
 	struct sockaddr_atmsvc local;	/* local SVC address */
 	struct atm_qos qos;		/* QOS parameters */
 	struct atm_sap sap;		/* SAP */
-	unsigned long session;		/* for p2pm */
+	unsigned int session;		/* for p2pm */
 	struct sockaddr_atmsvc svc;	/* SVC address */
-};
+} __ATM_API_ALIGN;
 
 /*
- * Message contents: see ftp://lrcftp.epfl.ch/pub/linux/atm/docs/isp-*.tar.gz
+ * Message contents: see ftp://icaftp.epfl.ch/pub/linux/atm/docs/isp-*.tar.gz
  */
 
 /*
diff -u --recursive --new-file v2.3.42/linux/include/linux/auto_fs.h linux/include/linux/auto_fs.h
--- v2.3.42/linux/include/linux/auto_fs.h	Tue Feb  1 01:35:44 2000
+++ linux/include/linux/auto_fs.h	Wed Feb  9 21:33:38 2000
@@ -14,20 +14,21 @@
 #ifndef _LINUX_AUTO_FS_H
 #define _LINUX_AUTO_FS_H
 
+#ifdef __KERNEL__
 #include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/limits.h>
-#include <linux/ioctl.h>
 #include <asm/types.h>
+#endif /* __KERNEL__ */
+
+#include <linux/ioctl.h>
 
-/* This header file describes a range of autofs interface versions;
-   the new implementation ("autofs4") supports them all, but the old
-   implementation only supports v3.  */
-#define AUTOFS_MIN_PROTO_VERSION 3	/* Min version we support */
-#define AUTOFS_MAX_PROTO_VERSION 4	/* Max (current) version */
+/* This file describes autofs v3 */
+#define AUTOFS_PROTO_VERSION	3
 
-/* Backwards compat for autofs v3; it just implements a version */
-#define AUTOFS_PROTO_VERSION 3		/* v3 version */
+/* Range of protocol versions defined */
+#define AUTOFS_MAX_PROTO_VERSION	AUTOFS_PROTO_VERSION
+#define AUTOFS_MIN_PROTO_VERSION	AUTOFS_PROTO_VERSION
 
 /*
  * Architectures where both 32- and 64-bit binaries can be executed
@@ -50,15 +51,13 @@
 typedef unsigned long autofs_wqt_t;
 #endif
 
-enum autofs_packet_type {
-	autofs_ptype_missing,	/* Missing entry (mount request) */
-	autofs_ptype_expire,	/* Expire entry (umount request) */
-	autofs_ptype_expire_multi,	/* Expire entry (umount request) */
-};
+/* Packet types */
+#define autofs_ptype_missing	0	/* Missing entry (mount request) */
+#define autofs_ptype_expire	1	/* Expire entry (umount request) */
 
 struct autofs_packet_hdr {
-	int proto_version;	      /* Protocol version */
-	enum autofs_packet_type type; /* Type of packet */
+	int proto_version;		/* Protocol version */
+	int type;			/* Type of packet */
 };
 
 struct autofs_packet_missing {
@@ -75,28 +74,12 @@
 	char name[NAME_MAX+1];
 };
 
-/* v4 multi expire (via pipe) */
-struct autofs_packet_expire_multi {
-	struct autofs_packet_hdr hdr;
-        autofs_wqt_t wait_queue_token;
-	int len;
-	char name[NAME_MAX+1];
-};
-
-union autofs_packet_union {
-	struct autofs_packet_hdr hdr;
-	struct autofs_packet_missing missing;
-	struct autofs_packet_expire expire;
-	struct autofs_packet_expire_multi expire_multi;
-};
-
 #define AUTOFS_IOC_READY      _IO(0x93,0x60)
 #define AUTOFS_IOC_FAIL       _IO(0x93,0x61)
 #define AUTOFS_IOC_CATATONIC  _IO(0x93,0x62)
 #define AUTOFS_IOC_PROTOVER   _IOR(0x93,0x63,int)
 #define AUTOFS_IOC_SETTIMEOUT _IOWR(0x93,0x64,unsigned long)
 #define AUTOFS_IOC_EXPIRE     _IOR(0x93,0x65,struct autofs_packet_expire)
-#define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int)
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/auto_fs4.h linux/include/linux/auto_fs4.h
--- v2.3.42/linux/include/linux/auto_fs4.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/auto_fs4.h	Wed Feb  9 21:33:38 2000
@@ -0,0 +1,47 @@
+/* -*- c-mode -*-
+ * linux/include/linux/auto_fs4.h
+ *
+ * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
+ *
+ * This file is part of the Linux kernel and is made available under
+ * the terms of the GNU General Public License, version 2, or at your
+ * option, any later version, incorporated herein by reference.
+ */
+
+#ifndef _LINUX_AUTO_FS4_H
+#define _LINUX_AUTO_FS4_H
+
+/* Include common v3 definitions */
+#include <linux/auto_fs.h>
+
+/* autofs v4 definitions */
+#undef AUTOFS_PROTO_VERSION
+#undef AUTOFS_MIN_PROTO_VERSION
+#undef AUTOFS_MAX_PROTO_VERSION
+
+#define AUTOFS_PROTO_VERSION		4
+#define AUTOFS_MIN_PROTO_VERSION	3
+#define AUTOFS_MAX_PROTO_VERSION	4
+
+/* New message type */
+#define autofs_ptype_expire_multi	2	/* Expire entry (umount request) */
+
+/* v4 multi expire (via pipe) */
+struct autofs_packet_expire_multi {
+	struct autofs_packet_hdr hdr;
+        autofs_wqt_t wait_queue_token;
+	int len;
+	char name[NAME_MAX+1];
+};
+
+union autofs_packet_union {
+	struct autofs_packet_hdr hdr;
+	struct autofs_packet_missing missing;
+	struct autofs_packet_expire expire;
+	struct autofs_packet_expire_multi expire_multi;
+};
+
+#define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int)
+
+
+#endif /* _LINUX_AUTO_FS4_H */
diff -u --recursive --new-file v2.3.42/linux/include/linux/bfs_fs.h linux/include/linux/bfs_fs.h
--- v2.3.42/linux/include/linux/bfs_fs.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/bfs_fs.h	Thu Feb 10 12:17:00 2000
@@ -83,6 +83,7 @@
 
 /* file.c */
 extern struct inode_operations bfs_file_inops;
+extern struct address_space_operations bfs_aops;
 
 /* dir.c */
 extern struct inode_operations bfs_dir_inops;
diff -u --recursive --new-file v2.3.42/linux/include/linux/bfs_fs_sb.h linux/include/linux/bfs_fs_sb.h
--- v2.3.42/linux/include/linux/bfs_fs_sb.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/bfs_fs_sb.h	Sun Feb  6 18:43:21 2000
@@ -7,13 +7,6 @@
 #define _LINUX_BFS_FS_SB
 
 /*
- * BFS block map entry, an array of these is kept in bfs_sb_info.
- */
- struct bfs_bmap {
- 	unsigned long start, end;
- };
-
-/*
  * BFS file system in-core superblock info
  */
 struct bfs_sb_info {
@@ -24,7 +17,6 @@
 	unsigned long si_lf_sblk;
 	unsigned long si_lf_eblk;
 	unsigned long si_lasti;
-	struct bfs_bmap * si_bmap;
 	char * si_imap;
 	struct buffer_head * si_sbh;		/* buffer header w/superblock */
 	struct bfs_super_block * si_bfs_sb;	/* superblock in si_sbh->b_data */
diff -u --recursive --new-file v2.3.42/linux/include/linux/blkdev.h linux/include/linux/blkdev.h
--- v2.3.42/linux/include/linux/blkdev.h	Fri Jan 28 15:09:09 2000
+++ linux/include/linux/blkdev.h	Wed Feb  9 21:33:19 2000
@@ -37,14 +37,17 @@
 };
 
 typedef struct request_queue request_queue_t;
-typedef int (merge_request_fn) (request_queue_t *, 
-				struct request  * req,
-				struct buffer_head *);
-typedef int (merge_requests_fn) (request_queue_t *, 
-				 struct request  * req,
-				 struct request  * req2);
-typedef void (request_fn_proc) (request_queue_t *);
+typedef int (merge_request_fn) (request_queue_t *q, 
+				struct request  *req,
+				struct buffer_head *bh);
+typedef int (merge_requests_fn) (request_queue_t *q, 
+				 struct request  *req,
+				 struct request  *req2);
+typedef void (request_fn_proc) (request_queue_t *q);
 typedef request_queue_t * (queue_proc) (kdev_t dev);
+typedef void (make_request_fn) (int rw, struct buffer_head *bh);
+typedef void (plug_device_fn) (request_queue_t *q, kdev_t device);
+typedef void (unplug_device_fn) (void *q);
 
 struct request_queue
 {
@@ -52,6 +55,8 @@
 	request_fn_proc		* request_fn;
 	merge_request_fn	* merge_fn;
 	merge_requests_fn	* merge_requests_fn;
+	make_request_fn		* make_request_fn;
+	plug_device_fn		* plug_device_fn;
 	/*
 	 * The queue owner gets to use this for whatever they like.
 	 * ll_rw_blk doesn't touch it.
@@ -72,12 +77,6 @@
 	 * not.
 	 */
 	char			  head_active;
-
-	/*
-	 * Boolean that indicates whether we should use plugging on
-	 * this queue or not.
-	 */
-	char			  use_plug; 
 };
 
 struct blk_dev_struct {
@@ -107,8 +106,10 @@
 extern wait_queue_head_t wait_for_request;
 extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size);
 extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
-extern void unplug_device(void * data);
-extern void make_request(int major,int rw, struct buffer_head * bh);
+extern void generic_unplug_device(void * data);
+extern void generic_plug_device (request_queue_t *q, kdev_t dev);
+extern void generic_make_request(int rw, struct buffer_head * bh);
+extern request_queue_t * blk_get_queue(kdev_t dev);
 
 /*
  * Access functions for manipulating queue properties
@@ -116,12 +117,8 @@
 extern void blk_init_queue(request_queue_t *, request_fn_proc *);
 extern void blk_cleanup_queue(request_queue_t *);
 extern void blk_queue_headactive(request_queue_t *, int);
-extern void blk_queue_pluggable(request_queue_t *, int);
-
-/* md needs this function to remap requests */
-extern int md_map (int minor, kdev_t *rdev, unsigned long *rsector, unsigned long size);
-extern int md_make_request (int minor, int rw, struct buffer_head * bh);
-extern int md_error (kdev_t mddev, kdev_t rdev);
+extern void blk_queue_pluggable(request_queue_t *, plug_device_fn *);
+extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
 
 extern int * blk_size[MAX_BLKDEV];
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/bootmem.h linux/include/linux/bootmem.h
--- v2.3.42/linux/include/linux/bootmem.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/bootmem.h	Wed Feb  9 21:34:35 2000
@@ -55,6 +55,3 @@
 	__alloc_bootmem_node((nid), (x), PAGE_SIZE, 0)
 
 #endif /* _LINUX_BOOTMEM_H */
-
-
-
diff -u --recursive --new-file v2.3.42/linux/include/linux/coda.h linux/include/linux/coda.h
--- v2.3.42/linux/include/linux/coda.h	Tue Jul  6 19:08:33 1999
+++ linux/include/linux/coda.h	Thu Feb 10 12:17:00 2000
@@ -305,33 +305,35 @@
 #define CODA_INACTIVE	21
 #define CODA_VGET	22
 #define CODA_SIGNAL	23
-#define CODA_REPLACE	24
-#define CODA_FLUSH       25
-#define CODA_PURGEUSER   26
-#define CODA_ZAPFILE     27
-#define CODA_ZAPDIR      28
-#define CODA_PURGEFID    30
+#define CODA_REPLACE	 24 /* DOWNCALL */
+#define CODA_FLUSH       25 /* DOWNCALL */
+#define CODA_PURGEUSER   26 /* DOWNCALL */
+#define CODA_ZAPFILE     27 /* DOWNCALL */
+#define CODA_ZAPDIR      28 /* DOWNCALL */
+#define CODA_PURGEFID    30 /* DOWNCALL */
 #define CODA_OPEN_BY_PATH 31
 #define CODA_RESOLVE     32
 #define CODA_REINTEGRATE 33
 #define CODA_STATFS	 34
-#define CODA_NCALLS 35
+#define CODA_MAKE_CINODE 35 /* DOWNCALL */
+#define CODA_NCALLS 36
 
-#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID)
+#define DOWNCALL(opcode) \
+	((opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID) || \
+	 opcode == CODA_MAKE_CINODE)
 
 #define VC_MAXDATASIZE	    8192
 #define VC_MAXMSGSIZE      sizeof(union inputArgs)+sizeof(union outputArgs) +\
                             VC_MAXDATASIZE  
 
 #define CIOC_KERNEL_VERSION _IOWR('c', 10, sizeof (int))
+
 #if	0
-	/* don't care about kernel version number */
-#define CODA_KERNEL_VERSION 0
-	/* The old venus 4.6 compatible interface */
-#define CODA_KERNEL_VERSION 1
+#define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
+#define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */
+#define CODA_KERNEL_VERSION 2 /* venus_lookup gets an extra parameter */
 #endif
-	/* venus_lookup gets an extra parameter to aid windows.*/
-#define CODA_KERNEL_VERSION 2
+#define CODA_KERNEL_VERSION 3 /* added CODA_MAKE_CINODE downcall */
 
 /*
  *        Venus <-> Coda  RPC arguments
@@ -650,6 +652,13 @@
     ViceFid CodaFid;
 };
 
+struct coda_make_cinode_out {
+    struct coda_out_hdr oh;
+    ViceFid CodaFid;
+    struct coda_vattr attr;
+    int fd;
+};
+
 /* coda_rdwr: */
 struct coda_rdwr_in {
     struct coda_in_hdr ih;
@@ -751,6 +760,7 @@
     struct coda_purgefid_out coda_purgefid;
     struct coda_rdwr_out coda_rdwr;
     struct coda_replace_out coda_replace;
+    struct coda_make_cinode_out coda_make_cinode;
     struct coda_open_by_path_out coda_open_by_path;
     struct coda_statfs_out coda_statfs;
 };    
diff -u --recursive --new-file v2.3.42/linux/include/linux/coda_fs_i.h linux/include/linux/coda_fs_i.h
--- v2.3.42/linux/include/linux/coda_fs_i.h	Sun Jul 11 23:14:00 1999
+++ linux/include/linux/coda_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -40,6 +40,8 @@
 #define C_INITED      0x20
 #define C_FLUSH       0x2   /* used after a flush */
 
+struct inode *coda_iget(struct super_block * sb, ViceFid * fid,
+                        struct coda_vattr * attr);
 int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *);
 int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
 struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb);
diff -u --recursive --new-file v2.3.42/linux/include/linux/coda_linux.h linux/include/linux/coda_linux.h
--- v2.3.42/linux/include/linux/coda_linux.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/coda_linux.h	Thu Feb 10 12:17:00 2000
@@ -26,7 +26,9 @@
 extern struct inode_operations coda_dir_inode_operations;
 extern struct inode_operations coda_file_inode_operations;
 extern struct inode_operations coda_ioctl_inode_operations;
-extern struct inode_operations coda_symlink_inode_operations;
+
+extern struct address_space_operations coda_file_aops;
+extern struct address_space_operations coda_symlink_aops;
 
 extern struct file_operations coda_dir_operations;
 extern struct file_operations coda_file_operations;
diff -u --recursive --new-file v2.3.42/linux/include/linux/coda_psdev.h linux/include/linux/coda_psdev.h
--- v2.3.42/linux/include/linux/coda_psdev.h	Tue Jul  6 19:08:33 1999
+++ linux/include/linux/coda_psdev.h	Thu Feb 10 12:17:00 2000
@@ -101,6 +101,7 @@
 #define REQ_ASYNC  0x1
 #define REQ_READ   0x2
 #define REQ_WRITE  0x4
+#define REQ_ABORT  0x8
 
 
 /*
diff -u --recursive --new-file v2.3.42/linux/include/linux/console.h linux/include/linux/console.h
--- v2.3.42/linux/include/linux/console.h	Fri Oct 15 15:25:14 1999
+++ linux/include/linux/console.h	Wed Feb  9 21:32:56 2000
@@ -14,6 +14,9 @@
 #ifndef _LINUX_CONSOLE_H_
 #define _LINUX_CONSOLE_H_ 1
 
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+
 struct vc_data;
 struct console_font_op;
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/efs_fs.h linux/include/linux/efs_fs.h
--- v2.3.42/linux/include/linux/efs_fs.h	Wed Aug 18 16:45:22 1999
+++ linux/include/linux/efs_fs.h	Thu Feb 10 12:17:00 2000
@@ -47,7 +47,7 @@
 
 extern struct inode_operations efs_dir_inode_operations;
 extern struct inode_operations efs_file_inode_operations;
-extern struct inode_operations efs_symlink_inode_operations;
+extern struct address_space_operations efs_symlink_aops;
 
 extern int init_module(void);
 extern void cleanup_module(void);
diff -u --recursive --new-file v2.3.42/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- v2.3.42/linux/include/linux/ext2_fs.h	Tue Jan 11 22:31:44 2000
+++ linux/include/linux/ext2_fs.h	Thu Feb 10 12:17:00 2000
@@ -560,14 +560,10 @@
 extern void ext2_check_inodes_bitmap (struct super_block *);
 
 /* inode.c */
-extern long ext2_bmap (struct inode *, long);
-extern int ext2_get_block (struct inode *, long, struct buffer_head *, int);
 
 extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
-extern int ext2_getblk_block (struct inode *, long, int, int *, int *);
 extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
 
-extern int ext2_getcluster (struct inode * inode, long block);
 extern void ext2_read_inode (struct inode *);
 extern void ext2_write_inode (struct inode *);
 extern void ext2_put_inode (struct inode *);
@@ -620,8 +616,9 @@
 extern struct inode_operations ext2_file_inode_operations;
 
 /* symlink.c */
-extern struct inode_operations ext2_symlink_inode_operations;
 extern struct inode_operations ext2_fast_symlink_inode_operations;
+
+extern struct address_space_operations ext2_aops;
 
 #endif	/* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.42/linux/include/linux/fs.h	Fri Jan 28 15:09:09 2000
+++ linux/include/linux/fs.h	Thu Feb 10 12:17:00 2000
@@ -251,6 +251,7 @@
 
 #define touch_buffer(bh)	set_bit(PG_referenced, &bh->b_page->flags)
 
+
 #include <linux/pipe_fs_i.h>
 #include <linux/minix_fs_i.h>
 #include <linux/ext2_fs_i.h>
@@ -332,10 +333,23 @@
  * oh the beauties of C type declarations.
  */
 struct page;
+struct address_space;
+
+struct address_space_operations {
+	int (*writepage) (struct dentry *, struct page *);
+	int (*readpage)(struct dentry *, struct page *);
+	int (*prepare_write)(struct page *, unsigned, unsigned);
+	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+	/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
+	int (*bmap)(struct address_space *, long);
+};
 
 struct address_space {
-	struct list_head	pages;
-	unsigned long		nrpages;
+	struct list_head	pages;		/* list of pages */
+	unsigned long		nrpages;	/* number of pages */
+	struct address_space_operations *a_ops;	/* methods */
+	void			*host;		/* owner: inode, block_device */
+	void			*private;	/* private data */
 };
 
 struct block_device {
@@ -374,6 +388,7 @@
 	wait_queue_head_t	i_wait;
 	struct file_lock	*i_flock;
 	struct vm_area_struct	*i_mmap;
+	struct address_space	*i_mapping;	
 	struct address_space	i_data;	
 	spinlock_t		i_shared_lock;
 	struct dquot		*i_dquot[MAXQUOTAS];
@@ -655,24 +670,6 @@
 			struct inode *, struct dentry *);
 	int (*readlink) (struct dentry *, char *,int);
 	struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int);
-	/*
-	 * the order of these functions within the VFS template has been
-	 * changed because SMP locking has changed: from now on all get_block,
-	 * readpage and writepage functions are supposed to do
-	 * whatever locking they need to get proper SMP operation - for
-	 * now in most cases this means a lock/unlock_kernel at entry/exit.
-	 * [The new order is also slightly more logical :)]
-	 */
-	/*
-	 * Generic block allocator exported by the lowlevel fs. All metadata
-	 * details are handled by the lowlevel fs, all 'logical data content'
-	 * details are handled by the highlevel block layer.
-	 */
-	int (*get_block) (struct inode *, long, struct buffer_head *, int);
-
-	int (*readpage) (struct dentry *, struct page *);
-	int (*writepage) (struct dentry *, struct page *);
-
 	void (*truncate) (struct inode *);
 	int (*permission) (struct inode *, int);
 	int (*revalidate) (struct dentry *);
@@ -779,7 +776,6 @@
 extern int register_chrdev(unsigned int, const char *, struct file_operations *);
 extern int unregister_chrdev(unsigned int, const char *);
 extern int chrdev_open(struct inode *, struct file *);
-extern struct file_operations def_chr_fops;
 extern const char * bdevname(kdev_t);
 extern const char * cdevname(kdev_t);
 extern const char * kdevname(kdev_t);
@@ -852,20 +848,17 @@
 }
 
 extern void FASTCALL(__mark_buffer_dirty(struct buffer_head *bh, int flag));
+extern void FASTCALL(mark_buffer_dirty(struct buffer_head *bh, int flag));
 
 #define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state)
 
-extern inline void mark_buffer_dirty(struct buffer_head * bh, int flag)
-{
-	if (!atomic_set_buffer_dirty(bh))
-		__mark_buffer_dirty(bh, flag);
-}
-
 extern void balance_dirty(kdev_t);
 extern int check_disk_change(kdev_t);
 extern int invalidate_inodes(struct super_block *);
 extern void invalidate_inode_pages(struct inode *);
-extern void invalidate_buffers(kdev_t);
+#define invalidate_buffers(dev)	__invalidate_buffers((dev), 0)
+#define destroy_buffers(dev)	__invalidate_buffers((dev), 1)
+extern void __invalidate_buffers(kdev_t dev, int);
 extern int floppy_is_wp(int);
 extern void sync_inodes(kdev_t);
 extern void write_inode_now(struct inode *);
@@ -978,30 +971,29 @@
 extern int brw_page(int, struct page *, kdev_t, int [], int);
 
 typedef int (*writepage_t)(struct file *, struct page *, unsigned long, unsigned long, const char *);
+typedef int (get_block_t)(struct inode*,long,struct buffer_head*,int);
 
 /* Generic buffer handling for block filesystems.. */
-extern int block_read_full_page(struct dentry *, struct page *);
-extern int block_write_full_page (struct dentry *, struct page *);
-extern int block_write_partial_page (struct file *, struct page *, unsigned long, unsigned long, const char *);
-extern int block_write_cont_page (struct file *, struct page *, unsigned long, unsigned long, const char *);
-extern int block_write_zero_range(struct inode *, struct page *, unsigned, unsigned, unsigned, const char *);
-extern inline int block_write_range(struct inode *inode, struct page *page,
-				unsigned from, unsigned len,const char *buf) 
-{
-	return block_write_zero_range(inode, page, from, from, from+len, buf);
-}
 extern int block_flushpage(struct page *, unsigned long);
 extern int block_symlink(struct inode *, const char *, int);
+extern int block_write_full_page(struct page*, get_block_t*);
+extern int block_read_full_page(struct page*, get_block_t*);
+extern int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
+extern int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
+				unsigned long *);
+int generic_block_bmap(struct address_space *, long, get_block_t *);
+int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
-extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *, writepage_t);
+extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
 extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
 
 extern int vfs_readlink(struct dentry *, char *, int, const char *);
 extern struct dentry *vfs_follow_link(struct dentry *, struct dentry *, unsigned, const char *);
 extern int page_readlink(struct dentry *, char *, int);
 extern struct dentry *page_follow_link(struct dentry *, struct dentry *, unsigned);
+struct inode_operations page_symlink_inode_operations;
 
 extern struct super_block *get_super(kdev_t);
 struct super_block *get_empty_super(void);
diff -u --recursive --new-file v2.3.42/linux/include/linux/genhd.h linux/include/linux/genhd.h
--- v2.3.42/linux/include/linux/genhd.h	Fri Jan 21 18:19:17 2000
+++ linux/include/linux/genhd.h	Wed Feb  9 21:32:56 2000
@@ -19,6 +19,7 @@
 #define WIN98_EXTENDED_PARTITION 0x0f
 
 #define LINUX_SWAP_PARTITION	0x82
+#define LINUX_RAID_PARTITION	0xfd	/* autodetect RAID partition */
 
 #ifdef CONFIG_SOLARIS_X86_PARTITION
 #define SOLARIS_X86_PARTITION	LINUX_SWAP_PARTITION
@@ -45,6 +46,7 @@
 struct hd_struct {
 	long start_sect;
 	long nr_sects;
+	int type;			/* currently RAID or normal */
 };
 
 struct gendisk {
diff -u --recursive --new-file v2.3.42/linux/include/linux/hfs_fs_i.h linux/include/linux/hfs_fs_i.h
--- v2.3.42/linux/include/linux/hfs_fs_i.h	Wed Dec 23 14:10:36 1998
+++ linux/include/linux/hfs_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -19,6 +19,7 @@
 struct hfs_inode_info {
 	int				magic;     /* A magic number */
 
+	unsigned long			mmu_private;
 	struct hfs_cat_entry		*entry;
 
 	/* For a regular or header file */
diff -u --recursive --new-file v2.3.42/linux/include/linux/hpfs_fs_i.h linux/include/linux/hpfs_fs_i.h
--- v2.3.42/linux/include/linux/hpfs_fs_i.h	Wed Jun 16 19:26:27 1999
+++ linux/include/linux/hpfs_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -2,6 +2,7 @@
 #define _HPFS_FS_I
 
 struct hpfs_inode_info {
+	unsigned long mmu_private;
 	ino_t i_parent_dir;	/* (directories) gives fnode of parent dir */
 	unsigned i_dno;		/* (directories) root dnode */
 	unsigned i_dpos;	/* (directories) temp for readdir */
diff -u --recursive --new-file v2.3.42/linux/include/linux/i2c-id.h linux/include/linux/i2c-id.h
--- v2.3.42/linux/include/linux/i2c-id.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/i2c-id.h	Wed Feb  9 18:48:03 2000
@@ -20,7 +20,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
 /* ------------------------------------------------------------------------- */
 
-/* $Id: i2c-id.h,v 1.6 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-id.h,v 1.10 2000/02/04 02:47:41 mds Exp $ */
 
 #ifndef I2C_ID_H
 #define I2C_ID_H
@@ -44,35 +44,36 @@
  *        never be used in official drivers 
  */
 
-#define I2C_DRIVERID_MSP3400     1
-#define I2C_DRIVERID_TUNER       2
-#define I2C_DRIVERID_VIDEOTEXT   3	/* please rename		*/
+#define I2C_DRIVERID_MSP3400	 1
+#define I2C_DRIVERID_TUNER	 2
+#define I2C_DRIVERID_VIDEOTEX	 3	/* please rename		*/
 #define I2C_DRIVERID_TDA8425	 4	/* stereo sound processor	*/
 #define I2C_DRIVERID_TEA6420	 5	/* audio matrix switch		*/
 #define I2C_DRIVERID_TEA6415C	 6	/* video matrix switch		*/
 #define I2C_DRIVERID_TDA9840	 7	/* stereo sound processor	*/
 #define I2C_DRIVERID_SAA7111A	 8	/* video input processor	*/
 #define I2C_DRIVERID_SAA5281	 9	/* videotext decoder		*/
-#define I2C_DRIVERID_SAA7112    10      /* video decoder, image scaler	*/
-#define I2C_DRIVERID_SAA7120    11      /* video encoder		*/
-#define I2C_DRIVERID_SAA7121    12      /* video encoder		*/
-#define I2C_DRIVERID_SAA7185B   13      /* video encoder		*/
-#define I2C_DRIVERID_CH7003     14      /* digital pc to tv encoder 	*/
-#define I2C_DRIVERID_PCF8574A   15      /* i2c expander - 8 bit in/out	*/
-#define I2C_DRIVERID_PCF8582C   16      /* eeprom   			*/
-#define I2C_DRIVERID_AT24Cxx    17      /* eeprom 1/2/4/8/16 K 		*/
+#define I2C_DRIVERID_SAA7112	10	/* video decoder, image scaler	*/
+#define I2C_DRIVERID_SAA7120	11	/* video encoder		*/
+#define I2C_DRIVERID_SAA7121	12	/* video encoder		*/
+#define I2C_DRIVERID_SAA7185B	13	/* video encoder		*/
+#define I2C_DRIVERID_CH7003	14	/* digital pc to tv encoder 	*/
+#define I2C_DRIVERID_PCF8574A	15	/* i2c expander - 8 bit in/out	*/
+#define I2C_DRIVERID_PCF8582C	16	/* eeprom			*/
+#define I2C_DRIVERID_AT24Cxx	17	/* eeprom 1/2/4/8/16 K 		*/
 #define I2C_DRIVERID_TEA6300	18	/* audio mixer			*/
-#define I2C_DRIVERID_BT829      19      /* pc to tv encoder		*/
+#define I2C_DRIVERID_BT829	19	/* pc to tv encoder		*/
 #define I2C_DRIVERID_TDA9850	20	/* audio mixer			*/
 #define I2C_DRIVERID_TDA9855	21	/* audio mixer			*/
+#define I2C_DRIVERID_SAA7110	22	/* 				*/
+#define I2C_DRIVERID_MGATVO	23	/* Matrox TVOut			*/
+#define I2C_DRIVERID_SAA5249	24	/* SAA5249 and compatibles	*/
 
 #define I2C_DRIVERID_EXP0	0xF0	/* experimental use id's	*/
 #define I2C_DRIVERID_EXP1	0xF1
 #define I2C_DRIVERID_EXP2	0xF2
 #define I2C_DRIVERID_EXP3	0xF3
 
-#define I2C_DRIVERID_MGATVO	0x0101	/* Matrox TVOut			*/
-
 #define I2C_DRIVERID_I2CDEV	900
 #define I2C_DRIVERID_I2CPROC	901
 
@@ -88,8 +89,8 @@
 #define I2C_ALGO_PCF	0x020000	/* PCF 8584 style adapters	*/
 #define I2C_ALGO_ATI	0x030000	/* ATI video card		*/
 #define I2C_ALGO_SMBUS	0x040000
-#define I2C_ALGO_ISA 	0x050000        /* lm_sensors ISA pseudo-adapter */
-#define I2C_ALGO_SAA7146  0x060000	/* SAA 7146 video decoder bus	*/
+#define I2C_ALGO_ISA 	0x050000	/* lm_sensors ISA pseudo-adapter */
+#define I2C_ALGO_SAA714	0x060000	/* SAA 7146 video decoder bus	*/
 #define I2C_ALGO_SAA7146A 0x060001	/* SAA 7146A - enhanced version	*/
 
 
@@ -113,9 +114,11 @@
 #define I2C_HW_B_VELLE	0x04	/* Vellemann K8000			*/
 #define I2C_HW_B_BT848	0x05	/* BT848 video boards			*/
 #define I2C_HW_B_WNV	0x06	/* Winnov Videums			*/
-#define I2C_HW_B_VIA    0x07    /* Via vt82c586b			*/
-#define I2C_HW_B_HYDRA  0x08    /* Apple Hydra Mac I/O                  */
+#define I2C_HW_B_VIA	0x07	/* Via vt82c586b			*/
+#define I2C_HW_B_HYDRA	0x08	/* Apple Hydra Mac I/O			*/
 #define I2C_HW_B_G400	0x09	/* Matrox G400				*/
+#define I2C_HW_B_I810	0x0a	/* Intel I810 				*/
+#define I2C_HW_B_RIVA	0x10	/* Riva based graphics cards		*/
 
 /* --- PCF 8584 based algorithms					*/
 #define I2C_HW_P_LP	0x00	/* Parallel port interface		*/
@@ -127,11 +130,11 @@
 #define I2C_HW_SMBUS_ALI15X3	0x01
 #define I2C_HW_SMBUS_VIA2	0x02
 #define I2C_HW_SMBUS_VOODOO3	0x03
-#define I2C_HW_SMBUS_I801   	0x04
+#define I2C_HW_SMBUS_I801	0x04
 #define I2C_HW_SMBUS_AMD756	0x05
 #define I2C_HW_SMBUS_SIS5595	0x06
 
-/* --- ISA pseudo-adapter                                               */
+/* --- ISA pseudo-adapter						*/
 #define I2C_HW_ISA 0x00
 
 #endif /* I2C_ID_H */
diff -u --recursive --new-file v2.3.42/linux/include/linux/i2c.h linux/include/linux/i2c.h
--- v2.3.42/linux/include/linux/i2c.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/i2c.h	Wed Feb  9 18:48:03 2000
@@ -3,7 +3,7 @@
 /* i2c.h - definitions for the i2c-bus interface			     */
 /* 									     */
 /* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-1999 Simon G. Vogl
+/*   Copyright (C) 1995-2000 Simon G. Vogl
 
     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
@@ -23,7 +23,7 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
    Frodo Looijaard <frodol@dds.nl> */
 
-/* $Id: i2c.h,v 1.32 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c.h,v 1.36 2000/01/18 23:54:07 frodo Exp $ */
 
 #ifndef I2C_H
 #define I2C_H
@@ -94,6 +94,8 @@
 	unsigned short flags;		
 #define I2C_M_TEN	0x10	/* we have a ten bit chip address	*/
 #define I2C_M_RD	0x01
+#define I2C_M_NOSTART	0x4000
+#define I2C_M_REV_DIR_ADDR	0x2000
 #if 0
 #define I2C_M_PROBE	0x20
 #endif
@@ -171,8 +173,8 @@
 	 * dec_use is the inverse operation.
 	 * NB: Make sure you have no circular dependencies, or else you get a 
 	 * deadlock when trying to unload the modules.
-         * You should use the i2c_{inc,dec}_use_client functions instead of
-         * calling this function directly.
+	* You should use the i2c_{inc,dec}_use_client functions instead of
+	* calling this function directly.
 	 */
 	void (*inc_use)(struct i2c_client *client);
 	void (*dec_use)(struct i2c_client *client);
@@ -190,9 +192,9 @@
 	unsigned int addr;		/* chip address - NOTE: 7bit 	*/
 					/* addresses are stored in the	*/
 					/* _LOWER_ 7 bits of this char	*/
-        /* addr: unsigned int to make lm_sensors i2c-isa adapter work
-           more cleanly. It does not take any more memory space, due to
-           alignment considerations */
+	/* addr: unsigned int to make lm_sensors i2c-isa adapter work
+	  more cleanly. It does not take any more memory space, due to
+	  alignment considerations */
 	struct i2c_adapter *adapter;	/* the adapter we sit on	*/
 	struct i2c_driver *driver;	/* and our access routines	*/
 	void *data;			/* for the clients		*/
@@ -207,17 +209,17 @@
  */
 struct i2c_algorithm {
 	char name[32];				/* textual description 	*/
-	unsigned int id;       
+	unsigned int id;
 
 	/* If a adapter algorithm can't to I2C-level access, set master_xfer
-           to NULL. If an adapter algorithm can do SMBus access, set 
-           smbus_xfer. If set to NULL, the SMBus protocol is simulated
-           using common I2C messages */
+	   to NULL. If an adapter algorithm can do SMBus access, set 
+	   smbus_xfer. If set to NULL, the SMBus protocol is simulated
+	   using common I2C messages */
 	int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[], 
-                           int num);
+	                   int num);
 	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, 
-                           unsigned short flags, char read_write,
-                           u8 command, int size, union i2c_smbus_data * data);
+	                   unsigned short flags, char read_write,
+	                   u8 command, int size, union i2c_smbus_data * data);
 
 	/* --- these optional/future use for some adapter types.*/
 	int (*slave_send)(struct i2c_adapter *,char*,int);
@@ -245,7 +247,7 @@
 	struct i2c_algorithm *algo;/* the algorithm to access the bus	*/
 	void *algo_data;
 
-        /* --- These may be NULL, but should increase the module use count */
+	/* --- These may be NULL, but should increase the module use count */
 	void (*inc_use)(struct i2c_adapter *);
 	void (*dec_use)(struct i2c_adapter *);
 
@@ -279,20 +281,20 @@
 
 /*flags for the driver struct: */
 #define I2C_DF_NOTIFY	0x01		/* notify on bus (de/a)ttaches 	*/
-#define I2C_DF_DUMMY    0x02    	/* do not connect any clients */
+#define I2C_DF_DUMMY	0x02		/* do not connect any clients */
 
 /* i2c_client_address_data is the struct for holding default client
  * addresses for a driver and for the parameters supplied on the
  * command line
  */
 struct i2c_client_address_data {
-  unsigned short *normal_i2c;
-  unsigned short *normal_i2c_range;
-  unsigned short *probe;
-  unsigned short *probe_range;
-  unsigned short *ignore;
-  unsigned short *ignore_range;
-  unsigned short *force;
+	unsigned short *normal_i2c;
+	unsigned short *normal_i2c_range;
+	unsigned short *probe;
+	unsigned short *probe_range;
+	unsigned short *ignore;
+	unsigned short *ignore_range;
+	unsigned short *force;
 };
 
 /* Internal numbers to terminate lists */
@@ -361,20 +363,21 @@
 
 /* To determine what functionality is present */
 
-#define I2C_FUNC_I2C                    0x00000001
-#define I2C_FUNC_10BIT_ADDR             0x00000002
-#define I2C_FUNC_SMBUS_QUICK            0x00010000 
-#define I2C_FUNC_SMBUS_READ_BYTE        0x00020000 
-#define I2C_FUNC_SMBUS_WRITE_BYTE       0x00040000 
-#define I2C_FUNC_SMBUS_READ_BYTE_DATA   0x00080000 
-#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA  0x00100000 
-#define I2C_FUNC_SMBUS_READ_WORD_DATA   0x00200000 
-#define I2C_FUNC_SMBUS_WRITE_WORD_DATA  0x00400000 
-#define I2C_FUNC_SMBUS_PROC_CALL        0x00800000 
-#define I2C_FUNC_SMBUS_READ_BLOCK_DATA  0x01000000 
+#define I2C_FUNC_I2C			0x00000001
+#define I2C_FUNC_10BIT_ADDR		0x00000002
+#define I2C_FUNC_PROTOCOL_MANGLING	0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART} */
+#define I2C_FUNC_SMBUS_QUICK		0x00010000 
+#define I2C_FUNC_SMBUS_READ_BYTE	0x00020000 
+#define I2C_FUNC_SMBUS_WRITE_BYTE	0x00040000 
+#define I2C_FUNC_SMBUS_READ_BYTE_DATA	0x00080000 
+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA	0x00100000 
+#define I2C_FUNC_SMBUS_READ_WORD_DATA	0x00200000 
+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA	0x00400000 
+#define I2C_FUNC_SMBUS_PROC_CALL	0x00800000 
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA	0x01000000 
 #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 
-#define I2C_FUNC_SMBUS_READ_I2C_BLOCK   0x04000000 /* New I2C-like block */
-#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK  0x08000000 /* transfers          */
+#define I2C_FUNC_SMBUS_READ_I2C_BLOCK	0x04000000 /* New I2C-like block */
+#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK	0x08000000 /* transfer */
 
 #define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \
                             I2C_FUNC_SMBUS_WRITE_BYTE
@@ -398,23 +401,23 @@
  * Data for SMBus Messages 
  */
 union i2c_smbus_data {
-        __u8 byte;
-        __u16 word;
-        __u8 block[33]; /* block[0] is used for length */
+	__u8 byte;
+	__u16 word;
+	__u8 block[33]; /* block[0] is used for length */
 };
 
 /* smbus_access read or write markers */
-#define I2C_SMBUS_READ      1
-#define I2C_SMBUS_WRITE     0
+#define I2C_SMBUS_READ	1
+#define I2C_SMBUS_WRITE	0
 
 /* SMBus transaction types (size parameter in the above functions) 
    Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
-#define I2C_SMBUS_QUICK      0
-#define I2C_SMBUS_BYTE       1
-#define I2C_SMBUS_BYTE_DATA  2 
-#define I2C_SMBUS_WORD_DATA  3
-#define I2C_SMBUS_PROC_CALL  4
-#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_QUICK		0
+#define I2C_SMBUS_BYTE		1
+#define I2C_SMBUS_BYTE_DATA	2 
+#define I2C_SMBUS_WORD_DATA	3
+#define I2C_SMBUS_PROC_CALL	4
+#define I2C_SMBUS_BLOCK_DATA	5
 
 
 /* ----- commands for the ioctl like i2c_command call:
@@ -423,7 +426,7 @@
  *	corresponding header files.
  */
 				/* -> bit-adapter specific ioctls	*/
-#define I2C_RETRIES	0x0701  /* number times a device adress should  */
+#define I2C_RETRIES	0x0701	/* number times a device adress should	*/
 				/* be polled when not acknowledging 	*/
 #define I2C_TIMEOUT	0x0702	/* set timeout - call with int 		*/
 
@@ -433,11 +436,11 @@
 				/* Attn.: Slave address is 7 or 10 bits */
 #define I2C_SLAVE_FORCE	0x0706	/* Change slave address			*/
 				/* Attn.: Slave address is 7 or 10 bits */
-                                /* This changes the address, even if it */
-                                /* is already taken!                    */
-#define I2C_TENBIT	0x0704	/* 0 for 7 bit addrs, != 0 for 10 bit   */
+				/* This changes the address, even if it */
+				/* is already taken!			*/
+#define I2C_TENBIT	0x0704	/* 0 for 7 bit addrs, != 0 for 10 bit	*/
 
-#define I2C_FUNCS       0x0705  /* Get the adapter functionality */
+#define I2C_FUNCS	0x0705	/* Get the adapter functionality */
 #if 0
 #define I2C_ACK_TEST	0x0710	/* See if a slave is at a specific adress */
 #endif
@@ -445,7 +448,7 @@
 #define I2C_SMBUS	0x0720	/* SMBus-level access */
 
 /* ... algo-bit.c recognizes */
-#define I2C_UDELAY	0x0705  /* set delay in microsecs between each  */
+#define I2C_UDELAY	0x0705	/* set delay in microsecs between each	*/
 				/* written byte (except address)	*/
 #define I2C_MDELAY	0x0706	/* millisec delay between written bytes */
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/input.h linux/include/linux/input.h
--- v2.3.42/linux/include/linux/input.h	Fri Jan 28 15:09:09 2000
+++ linux/include/linux/input.h	Mon Feb  7 19:14:45 2000
@@ -234,7 +234,7 @@
 #define KEY_RECORD		167		
 #define KEY_REWIND		168		
 
-#define KEY_UNKNOWN		192
+#define KEY_UNKNOWN		180
 
 #define BTN_MISC		0x100
 #define BTN_0			0x100
diff -u --recursive --new-file v2.3.42/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v2.3.42/linux/include/linux/interrupt.h	Wed Dec 29 13:13:21 1999
+++ linux/include/linux/interrupt.h	Wed Feb  9 21:33:04 2000
@@ -3,6 +3,7 @@
 #define _LINUX_INTERRUPT_H
 
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
@@ -15,17 +16,9 @@
 	struct irqaction *next;
 };
 
-extern volatile unsigned char bh_running;
-
-extern atomic_t bh_mask_count[32];
-extern unsigned long bh_active;
-extern unsigned long bh_mask;
-extern void (*bh_base[32])(void);
-
-asmlinkage void do_bottom_half(void);
 
 /* Who gets which entry in bh_base.  Things which will occur most often
-   should come first - in which case NET should be up the top with SERIAL/TQUEUE! */
+   should come first */
    
 enum {
 	TIMER_BH = 0,
@@ -37,10 +30,8 @@
 	SPECIALIX_BH,
 	AURORA_BH,
 	ESP_BH,
-	NET_BH,
 	SCSI_BH,
 	IMMEDIATE_BH,
-	KEYBOARD_BH,
 	CYCLADES_BH,
 	CM206_BH,
 	JS_BH,
@@ -50,6 +41,228 @@
 
 #include <asm/hardirq.h>
 #include <asm/softirq.h>
+
+
+
+/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
+   frequency threaded job scheduling. For almost all the purposes
+   tasklets are more than enough. F.e. KEYBOARD_BH, CONSOLE_BH, all serial
+   device BHs et al. are converted to tasklets, not to softirqs.
+ */
+
+enum
+{
+	HI_SOFTIRQ=0,
+	NET_TX_SOFTIRQ,
+	NET_RX_SOFTIRQ,
+	TASKLET_SOFTIRQ
+};
+
+#if SMP_CACHE_BYTES <= 32
+/* It is trick to make assembly easier. */
+#define SOFTIRQ_STATE_PAD 32
+#else
+#define SOFTIRQ_STATE_PAD SMP_CACHE_BYTES
+#endif
+
+struct softirq_state
+{
+	__u32	active;
+	__u32	mask;
+} __attribute__ ((__aligned__(SOFTIRQ_STATE_PAD)));
+
+extern struct softirq_state softirq_state[NR_CPUS];
+
+struct softirq_action
+{
+	void	(*action)(struct softirq_action *);
+	void	*data;
+};
+
+asmlinkage void do_softirq(void);
+extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
+
+extern __inline__ void __cpu_raise_softirq(int cpu, int nr)
+{
+	softirq_state[cpu].active |= (1<<nr);
+}
+
+
+/* I do not want to use atomic variables now, so that cli/sti */
+extern __inline__ void raise_softirq(int nr)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	__cpu_raise_softirq(smp_processor_id(), nr);
+	local_irq_restore(flags);
+}
+
+extern void softirq_init(void);
+
+
+
+/* Tasklets --- multithreaded analogue of BHs.
+
+   Main feature differing them of generic softirqs: tasklet
+   is running only on one CPU simultaneously.
+
+   Main feature differing them of BHs: different tasklets
+   may be run simultaneously on different CPUs.
+
+   Properties:
+   * If tasklet_schedule() is called, then tasklet is guaranteed
+     to be executed on some cpu at least once after this.
+   * If the tasklet is already scheduled, but its excecution is still not
+     started, it will be executed only once.
+   * If this tasklet is already running on another CPU (or schedule is called
+     from tasklet itself), it is rescheduled for later.
+   * Tasklet is strictly serialized wrt itself, but not
+     wrt another tasklets. If client needs some intertask synchronization,
+     he makes it with spinlocks.
+ */
+
+struct tasklet_struct
+{
+	struct tasklet_struct *next;
+	unsigned long state;
+	atomic_t count;
+	void (*func)(unsigned long);
+	unsigned long data;
+};
+
+#define DECLARE_TASKLET(name, func, data) \
+struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
+
+#define DECLARE_TASKLET_DISABLED(name, func, data) \
+struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }
+
+
+enum
+{
+	TASKLET_STATE_SCHED,	/* Tasklet is scheduled for execution */
+	TASKLET_STATE_RUN	/* Tasklet is running (SMP only) */
+};
+
+struct tasklet_head
+{
+	struct tasklet_struct *list;
+} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
+
+extern struct tasklet_head tasklet_vec[NR_CPUS];
+extern struct tasklet_head tasklet_hi_vec[NR_CPUS];
+
+#ifdef __SMP__
+#define tasklet_trylock(t) (!test_and_set_bit(TASKLET_STATE_RUN, &(t)->state))
+#define tasklet_unlock_wait(t) while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { /* NOTHING */ }
+#define tasklet_unlock(t) clear_bit(TASKLET_STATE_RUN, &(t)->state)
+#else
+#define tasklet_trylock(t) 1
+#define tasklet_unlock_wait(t) do { } while (0)
+#define tasklet_unlock(t) do { } while (0)
+#endif
+
+extern __inline__ void tasklet_schedule(struct tasklet_struct *t)
+{
+	if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
+		int cpu = smp_processor_id();
+		unsigned long flags;
+
+		local_irq_save(flags);
+		t->next = tasklet_vec[cpu].list;
+		tasklet_vec[cpu].list = t;
+		__cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
+		local_irq_restore(flags);
+	}
+}
+
+extern __inline__ void tasklet_hi_schedule(struct tasklet_struct *t)
+{
+	if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
+		int cpu = smp_processor_id();
+		unsigned long flags;
+
+		local_irq_save(flags);
+		t->next = tasklet_hi_vec[cpu].list;
+		tasklet_hi_vec[cpu].list = t;
+		__cpu_raise_softirq(cpu, HI_SOFTIRQ);
+		local_irq_restore(flags);
+	}
+}
+
+
+extern __inline__ void tasklet_disable_nosync(struct tasklet_struct *t)
+{
+	atomic_inc(&t->count);
+}
+
+extern __inline__ void tasklet_disable(struct tasklet_struct *t)
+{
+	tasklet_disable_nosync(t);
+	tasklet_unlock_wait(t);
+}
+
+extern __inline__ void tasklet_enable(struct tasklet_struct *t)
+{
+	atomic_dec(&t->count);
+}
+
+extern void tasklet_kill(struct tasklet_struct *t);
+extern void tasklet_init(struct tasklet_struct *t,
+			 void (*func)(unsigned long), unsigned long data);
+
+#ifdef __SMP__
+
+#define SMP_TIMER_NAME(name) name##__thr
+
+#define SMP_TIMER_DEFINE(name, task) \
+DECLARE_TASKLET(task, name##__thr, 0); \
+static void name (unsigned long dummy) \
+{ \
+	tasklet_schedule(&(task)); \
+}
+
+#else /* __SMP__ */
+
+#define SMP_TIMER_NAME(name) name
+#define SMP_TIMER_DEFINE(name, task)
+
+#endif /* __SMP__ */
+
+
+/* Old BH definitions */
+
+extern struct tasklet_struct bh_task_vec[];
+
+/* It is exported _ONLY_ for wait_on_irq(). */
+extern spinlock_t global_bh_lock;
+
+extern __inline__ void mark_bh(int nr)
+{
+	tasklet_hi_schedule(bh_task_vec+nr);
+}
+
+extern __inline__ void disable_bh_nosync(int nr)
+{
+	tasklet_disable_nosync(bh_task_vec+nr);
+}
+
+extern __inline__ void disable_bh(int nr)
+{
+	tasklet_disable_nosync(bh_task_vec+nr);
+	if (!in_interrupt())
+		tasklet_unlock_wait(bh_task_vec+nr);
+}
+
+extern __inline__ void enable_bh(int nr)
+{
+	tasklet_enable(bh_task_vec+nr);
+}
+
+
+extern void init_bh(int nr, void (*routine)(void));
+extern void remove_bh(int nr);
+
 
 /*
  * Autoprobing for irqs:
diff -u --recursive --new-file v2.3.42/linux/include/linux/iso_fs.h linux/include/linux/iso_fs.h
--- v2.3.42/linux/include/linux/iso_fs.h	Tue Dec 14 01:27:24 1999
+++ linux/include/linux/iso_fs.h	Thu Feb 10 12:17:00 2000
@@ -178,7 +178,6 @@
 extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
 extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
 
-extern int rock_ridge_symlink_readpage(struct dentry *, struct page *);
 extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *);
 
 int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *);
@@ -192,10 +191,7 @@
 
 extern struct inode_operations isofs_file_inode_operations;
 extern struct inode_operations isofs_dir_inode_operations;
-extern struct inode_operations isofs_symlink_inode_operations;
-extern struct inode_operations isofs_chrdev_inode_operations;
-extern struct inode_operations isofs_blkdev_inode_operations;
-extern struct inode_operations isofs_fifo_inode_operations;
+extern struct address_space_operations isofs_symlink_aops;
 
 /* The following macros are used to check for memory leaks. */
 #ifdef LEAK_CHECK
diff -u --recursive --new-file v2.3.42/linux/include/linux/kbd_kern.h linux/include/linux/kbd_kern.h
--- v2.3.42/linux/include/linux/kbd_kern.h	Fri Jan 21 18:19:17 2000
+++ linux/include/linux/kbd_kern.h	Wed Feb  9 21:34:06 2000
@@ -4,6 +4,8 @@
 #include <linux/interrupt.h>
 #include <linux/keyboard.h>
 
+extern struct tasklet_struct keyboard_tasklet;
+
 extern int shift_state;
 
 extern char *func_table[MAX_NR_FUNC];
@@ -85,7 +87,7 @@
 
 extern inline void set_leds(void)
 {
-	mark_bh(KEYBOARD_BH);
+	tasklet_schedule(&keyboard_tasklet);
 }
 
 extern inline int vc_kbd_mode(struct kbd_struct * kbd, int flag)
diff -u --recursive --new-file v2.3.42/linux/include/linux/linkage.h linux/include/linux/linkage.h
--- v2.3.42/linux/include/linux/linkage.h	Tue Aug 31 17:29:14 1999
+++ linux/include/linux/linkage.h	Mon Feb  7 19:45:28 2000
@@ -9,6 +9,8 @@
 
 #if defined __i386__ && (__GNUC__ > 2 || __GNUC_MINOR__ > 7)
 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
+#elif defined __ia64__
+#define asmlinkage CPP_ASMLINKAGE __attribute__((syscall_linkage))
 #else
 #define asmlinkage CPP_ASMLINKAGE
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/lp.h linux/include/linux/lp.h
--- v2.3.42/linux/include/linux/lp.h	Fri Oct 15 15:25:14 1999
+++ linux/include/linux/lp.h	Tue Feb  8 12:10:31 2000
@@ -89,6 +89,7 @@
 #define LPGETSTATS  0x060d  /* get statistics (struct lp_stats) */
 #endif
 #define LPGETFLAGS  0x060e  /* get status flags */
+#define LPSETTIMEOUT 0x060f /* set parport timeout */
 
 /* timeout for printk'ing a timeout, in jiffies (100ths of a second).
    This is also used for re-checking error conditions if LP_ABORT is
@@ -145,6 +146,7 @@
 	unsigned int last_error;
 	struct semaphore port_mutex;
 	wait_queue_head_t dataq;
+	long timeout;
 };
 
 /*
diff -u --recursive --new-file v2.3.42/linux/include/linux/mc146818rtc.h linux/include/linux/mc146818rtc.h
--- v2.3.42/linux/include/linux/mc146818rtc.h	Wed Aug 18 16:45:23 1999
+++ linux/include/linux/mc146818rtc.h	Wed Feb  9 21:35:43 2000
@@ -11,6 +11,7 @@
 #ifndef _MC146818RTC_H
 #define _MC146818RTC_H
 #include <asm/io.h>
+#include <linux/rtc.h> /* get the user-level API */
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)	(0x70 + (x))
@@ -105,45 +106,5 @@
 #ifndef BIN_TO_BCD
 #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
 #endif
-
-/*
- * The struct used to pass data via the following ioctl. Similar to the
- * struct tm in <time.h>, but it needs to be here so that the kernel 
- * source is self contained, allowing cross-compiles, etc. etc.
- */
-
-struct rtc_time {
-	int tm_sec;
-	int tm_min;
-	int tm_hour;
-	int tm_mday;
-	int tm_mon;
-	int tm_year;
-	int tm_wday;
-	int tm_yday;
-	int tm_isdst;
-};
-
-/*
- * ioctl calls that are permitted to the /dev/rtc interface, if 
- * CONFIG_RTC was enabled.
- */
-
-#define RTC_AIE_ON	_IO('p', 0x01)	/* Alarm int. enable on		*/
-#define RTC_AIE_OFF	_IO('p', 0x02)	/* ... off			*/
-#define RTC_UIE_ON	_IO('p', 0x03)	/* Update int. enable on	*/
-#define RTC_UIE_OFF	_IO('p', 0x04)	/* ... off			*/
-#define RTC_PIE_ON	_IO('p', 0x05)	/* Periodic int. enable on	*/
-#define RTC_PIE_OFF	_IO('p', 0x06)	/* ... off			*/
-
-#define RTC_ALM_SET	_IOW('p', 0x07, struct rtc_time) /* Set alarm time  */
-#define RTC_ALM_READ	_IOR('p', 0x08, struct rtc_time) /* Read alarm time */
-#define RTC_RD_TIME	_IOR('p', 0x09, struct rtc_time) /* Read RTC time   */
-#define RTC_SET_TIME	_IOW('p', 0x0a, struct rtc_time) /* Set RTC time    */
-#define RTC_IRQP_READ	_IOR('p', 0x0b, unsigned long)	 /* Read IRQ rate   */
-#define RTC_IRQP_SET	_IOW('p', 0x0c, unsigned long)	 /* Set IRQ rate    */
-#define RTC_EPOCH_READ	_IOR('p', 0x0d, unsigned long)	 /* Read epoch      */
-#define RTC_EPOCH_SET	_IOW('p', 0x0e, unsigned long)	 /* Set epoch       */
-
 
 #endif /* _MC146818RTC_H */
diff -u --recursive --new-file v2.3.42/linux/include/linux/md.h linux/include/linux/md.h
--- v2.3.42/linux/include/linux/md.h	Tue May 11 14:46:24 1999
+++ linux/include/linux/md.h	Wed Dec 31 16:00:00 1969
@@ -1,300 +0,0 @@
-/*
-   md.h : Multiple Devices driver for Linux
-          Copyright (C) 1994-96 Marc ZYNGIER
-	  <zyngier@ufr-info-p7.ibp.fr> or
-	  <maz@gloups.fdn.fr>
-	  
-   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, or (at your option)
-   any later version.
-   
-   You should have received a copy of the GNU General Public License
-   (for example /usr/src/linux/COPYING); if not, write to the Free
-   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
-*/
-
-#ifndef _MD_H
-#define _MD_H
-
-#include <linux/major.h>
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-/*
- * Different major versions are not compatible.
- * Different minor versions are only downward compatible.
- * Different patchlevel versions are downward and upward compatible.
- */
-#define MD_MAJOR_VERSION		0
-#define MD_MINOR_VERSION		36
-#define MD_PATCHLEVEL_VERSION		6
-
-#define MD_DEFAULT_DISK_READAHEAD	(256 * 1024)
-
-/* ioctls */
-#define REGISTER_DEV 		_IO (MD_MAJOR, 1)
-#define START_MD     		_IO (MD_MAJOR, 2)
-#define STOP_MD      		_IO (MD_MAJOR, 3)
-#define REGISTER_DEV_NEW	_IO (MD_MAJOR, 4)
-
-/*
-   personalities :
-   Byte 0 : Chunk size factor
-   Byte 1 : Fault tolerance count for each physical device
-            (   0 means no fault tolerance,
-             0xFF means always tolerate faults), not used by now.
-   Byte 2 : Personality
-   Byte 3 : Reserved.
- */
-
-#define FAULT_SHIFT       8
-#define PERSONALITY_SHIFT 16
-
-#define FACTOR_MASK       0x000000FFUL
-#define FAULT_MASK        0x0000FF00UL
-#define PERSONALITY_MASK  0x00FF0000UL
-
-#define MD_RESERVED       0	/* Not used by now */
-#define LINEAR            (1UL << PERSONALITY_SHIFT)
-#define STRIPED           (2UL << PERSONALITY_SHIFT)
-#define RAID0             STRIPED
-#define RAID1             (3UL << PERSONALITY_SHIFT)
-#define RAID5             (4UL << PERSONALITY_SHIFT)
-#define MAX_PERSONALITY   5
-
-/*
- * MD superblock.
- *
- * The MD superblock maintains some statistics on each MD configuration.
- * Each real device in the MD set contains it near the end of the device.
- * Some of the ideas are copied from the ext2fs implementation.
- *
- * We currently use 4096 bytes as follows:
- *
- *	word offset	function
- *
- *	   0  -    31	Constant generic MD device information.
- *        32  -    63   Generic state information.
- *	  64  -   127	Personality specific information.
- *	 128  -   511	12 32-words descriptors of the disks in the raid set.
- *	 512  -   911	Reserved.
- *	 912  -  1023	Disk specific descriptor.
- */
-
-/*
- * If x is the real device size in bytes, we return an apparent size of:
- *
- *	y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
- *
- * and place the 4kB superblock at offset y.
- */
-#define MD_RESERVED_BYTES		(64 * 1024)
-#define MD_RESERVED_SECTORS		(MD_RESERVED_BYTES / 512)
-#define MD_RESERVED_BLOCKS		(MD_RESERVED_BYTES / BLOCK_SIZE)
-
-#define MD_NEW_SIZE_SECTORS(x)		((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
-#define MD_NEW_SIZE_BLOCKS(x)		((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
-
-#define MD_SB_BYTES			4096
-#define MD_SB_WORDS			(MD_SB_BYTES / 4)
-#define MD_SB_BLOCKS			(MD_SB_BYTES / BLOCK_SIZE)
-#define MD_SB_SECTORS			(MD_SB_BYTES / 512)
-
-/*
- * The following are counted in 32-bit words
- */
-#define	MD_SB_GENERIC_OFFSET		0
-#define MD_SB_PERSONALITY_OFFSET	64
-#define MD_SB_DISKS_OFFSET		128
-#define MD_SB_DESCRIPTOR_OFFSET		992
-
-#define MD_SB_GENERIC_CONSTANT_WORDS	32
-#define MD_SB_GENERIC_STATE_WORDS	32
-#define MD_SB_GENERIC_WORDS		(MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
-#define MD_SB_PERSONALITY_WORDS		64
-#define MD_SB_DISKS_WORDS		384
-#define MD_SB_DESCRIPTOR_WORDS		32
-#define MD_SB_RESERVED_WORDS		(1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
-#define MD_SB_EQUAL_WORDS		(MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
-#define MD_SB_DISKS			(MD_SB_DISKS_WORDS / MD_SB_DESCRIPTOR_WORDS)
-
-/*
- * Device "operational" state bits
- */
-#define MD_FAULTY_DEVICE		0	/* Device is faulty / operational */
-#define MD_ACTIVE_DEVICE		1	/* Device is a part or the raid set / spare disk */
-#define MD_SYNC_DEVICE			2	/* Device is in sync with the raid set */
-
-typedef struct md_device_descriptor_s {
-	__u32 number;		/* 0 Device number in the entire set */
-	__u32 major;		/* 1 Device major number */
-	__u32 minor;		/* 2 Device minor number */
-	__u32 raid_disk;	/* 3 The role of the device in the raid set */
-	__u32 state;		/* 4 Operational state */
-	__u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
-} md_descriptor_t;
-
-#define MD_SB_MAGIC		0xa92b4efc
-
-/*
- * Superblock state bits
- */
-#define MD_SB_CLEAN		0
-#define MD_SB_ERRORS		1
-
-typedef struct md_superblock_s {
-
-	/*
-	 * Constant generic information
-	 */
-	__u32 md_magic;		/*  0 MD identifier */
-	__u32 major_version;	/*  1 major version to which the set conforms */
-	__u32 minor_version;	/*  2 minor version to which the set conforms */
-	__u32 patch_version;	/*  3 patchlevel version to which the set conforms */
-	__u32 gvalid_words;	/*  4 Number of non-reserved words in this section */
-	__u32 set_magic;	/*  5 Raid set identifier */
-	__u32 ctime;		/*  6 Creation time */
-	__u32 level;		/*  7 Raid personality (mirroring, raid5, ...) */
-	__u32 size;		/*  8 Apparent size of each individual disk, in kB */
-	__u32 nr_disks;		/*  9 Number of total disks in the raid set */
-	__u32 raid_disks;	/* 10 Number of disks in a fully functional raid set */
-	__u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 11];
-
-	/*
-	 * Generic state information
-	 */
-	__u32 utime;		/*  0 Superblock update time */
-	__u32 state;		/*  1 State bits (clean, ...) */
-	__u32 active_disks;	/*  2 Number of currently active disks (some non-faulty disks might not be in sync) */
-	__u32 working_disks;	/*  3 Number of working disks */
-	__u32 failed_disks;	/*  4 Number of failed disks */
-	__u32 spare_disks;	/*  5 Number of spare disks */
-	__u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 6];
-
-	/*
-	 * Personality information
-	 */
-	__u32 parity_algorithm;
-	__u32 chunk_size;
-	__u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 2];
-
-	/*
-	 * Disks information
-	 */
-	md_descriptor_t disks[MD_SB_DISKS];
-
-	/*
-	 * Reserved
-	 */
-	__u32 reserved[MD_SB_RESERVED_WORDS];
-
-	/*
-	 * Active descriptor
-	 */
-	md_descriptor_t descriptor;
-} md_superblock_t;
-
-#ifdef __KERNEL__
-
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/blkdev.h>
-#include <asm/semaphore.h>
-
-/*
- * Kernel-based reconstruction is mostly working, but still requires
- * some additional work.
- */
-#define SUPPORT_RECONSTRUCTION	0
-
-#define MAX_REAL     8		/* Max number of physical dev per md dev */
-#define MAX_MD_DEV   4		/* Max number of md dev */
-
-#define FACTOR(a)         ((a)->repartition & FACTOR_MASK)
-#define MAX_FAULT(a)      (((a)->repartition & FAULT_MASK)>>8)
-#define PERSONALITY(a)    ((a)->repartition & PERSONALITY_MASK)
-
-#define FACTOR_SHIFT(a) (PAGE_SHIFT + (a) - 10)
-
-struct real_dev
-{
-  kdev_t dev;			/* Device number */
-  int size;			/* Device size (in blocks) */
-  int offset;			/* Real device offset (in blocks) in md dev
-				   (only used in linear mode) */
-  struct inode *inode;		/* Lock inode */
-  md_superblock_t *sb;
-  u32 sb_offset;
-};
-
-struct md_dev;
-
-#define SPARE_INACTIVE	0
-#define SPARE_WRITE	1
-#define SPARE_ACTIVE	2
-
-struct md_personality
-{
-  char *name;
-  int (*map)(struct md_dev *mddev, kdev_t *rdev,
-	              unsigned long *rsector, unsigned long size);
-  int (*make_request)(struct md_dev *mddev, int rw, struct buffer_head * bh);
-  void (*end_request)(struct buffer_head * bh, int uptodate);
-  int (*run)(int minor, struct md_dev *mddev);
-  int (*stop)(int minor, struct md_dev *mddev);
-  int (*status)(char *page, int minor, struct md_dev *mddev);
-  int (*ioctl)(struct inode *inode, struct file *file,
-	       unsigned int cmd, unsigned long arg);
-  int max_invalid_dev;
-  int (*error_handler)(struct md_dev *mddev, kdev_t dev);
-
-/*
- * Some personalities (RAID-1, RAID-5) can get disks hot-added and
- * hot-removed. Hot removal is different from failure. (failure marks
- * a disk inactive, but the disk is still part of the array)
- */
-  int (*hot_add_disk) (struct md_dev *mddev, kdev_t dev);
-  int (*hot_remove_disk) (struct md_dev *mddev, kdev_t dev);
-  int (*mark_spare) (struct md_dev *mddev, md_descriptor_t *descriptor, int state);
-};
-
-struct md_dev
-{
-  struct real_dev	devices[MAX_REAL];
-  struct md_personality	*pers;
-  md_superblock_t	*sb;
-  int			sb_dirty;
-  int			repartition;
-  int			busy;
-  int			nb_dev;
-  void			*private;
-};
-
-struct md_thread {
-	void			(*run) (void *data);
-	void			*data;
-	wait_queue_head_t	wqueue;
-	unsigned long           flags;
-	struct semaphore	*sem;
-	struct task_struct	*tsk;
-};
-
-#define THREAD_WAKEUP  0
-
-extern struct md_dev md_dev[MAX_MD_DEV];
-extern int md_size[MAX_MD_DEV];
-extern int md_maxreadahead[MAX_MD_DEV];
-
-extern char *partition_name (kdev_t dev);
-
-extern int register_md_personality (int p_num, struct md_personality *p);
-extern int unregister_md_personality (int p_num);
-extern struct md_thread *md_register_thread (void (*run) (void *data), void *data);
-extern void md_unregister_thread (struct md_thread *thread);
-extern void md_wakeup_thread(struct md_thread *thread);
-extern int md_update_sb (int minor);
-extern int md_do_sync(struct md_dev *mddev);
-
-#endif __KERNEL__
-#endif _MD_H
diff -u --recursive --new-file v2.3.42/linux/include/linux/minix_fs.h linux/include/linux/minix_fs.h
--- v2.3.42/linux/include/linux/minix_fs.h	Mon Aug  9 12:29:00 1999
+++ linux/include/linux/minix_fs.h	Thu Feb 10 12:17:00 2000
@@ -107,10 +107,7 @@
 extern void minix_free_block(struct inode * inode, int block);
 extern unsigned long minix_count_free_blocks(struct super_block *sb);
 
-extern int minix_bmap(struct inode *,int);
-
 extern struct buffer_head * minix_getblk(struct inode *, int, int);
-extern int minix_get_block(struct inode *, long, struct buffer_head *, int);
 extern struct buffer_head * minix_bread(struct inode *, int, int);
 
 extern void minix_truncate(struct inode *);
@@ -118,9 +115,9 @@
 extern int minix_sync_inode(struct inode *);
 extern int minix_sync_file(struct file *, struct dentry *);
 
+extern struct address_space_operations minix_aops;
 extern struct inode_operations minix_file_inode_operations;
 extern struct inode_operations minix_dir_inode_operations;
-extern struct inode_operations minix_symlink_inode_operations;
 extern struct dentry_operations minix_dentry_operations;
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.42/linux/include/linux/miscdevice.h linux/include/linux/miscdevice.h
--- v2.3.42/linux/include/linux/miscdevice.h	Tue Aug 31 17:29:14 1999
+++ linux/include/linux/miscdevice.h	Wed Feb  9 19:45:43 2000
@@ -14,6 +14,7 @@
 #define WATCHDOG_MINOR		130	/* Watchdog timer     */
 #define TEMP_MINOR		131	/* Temperature Sensor */
 #define RTC_MINOR 135
+#define EFI_RTC_MINOR		136	/* EFI Time services */
 #define SUN_OPENPROM_MINOR 139
 #define NVRAM_MINOR 144
 #define I2O_MINOR 166
diff -u --recursive --new-file v2.3.42/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.42/linux/include/linux/mm.h	Fri Jan 28 15:09:09 2000
+++ linux/include/linux/mm.h	Wed Feb  9 21:33:16 2000
@@ -394,7 +394,7 @@
 extern int check_pgt_cache(void);
 
 extern void paging_init(void);
-extern void free_area_init(unsigned int * zones_size);
+extern void free_area_init(unsigned long * zones_size);
 extern void free_area_init_node(int nid, pg_data_t *pgdat, 
 		unsigned int * zones_size, unsigned long zone_start_paddr);
 extern void mem_init(void);
@@ -462,7 +462,7 @@
 
 #define __GFP_DMA	0x20
 
-#define GFP_BUFFER	(__GFP_WAIT)
+#define GFP_BUFFER	(__GFP_HIGH | __GFP_WAIT)
 #define GFP_ATOMIC	(__GFP_HIGH)
 #define GFP_USER	(__GFP_WAIT | __GFP_IO)
 #define GFP_HIGHUSER	(GFP_USER | __GFP_HIGHMEM)
@@ -501,6 +501,8 @@
 
 /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
 extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);
+extern struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
+					     struct vm_area_struct **pprev);
 
 /* Look up the first VMA which intersects the interval start_addr..end_addr-1,
    NULL if none.  Assume start_addr < end_addr. */
diff -u --recursive --new-file v2.3.42/linux/include/linux/mmzone.h linux/include/linux/mmzone.h
--- v2.3.42/linux/include/linux/mmzone.h	Tue Feb  1 01:35:44 2000
+++ linux/include/linux/mmzone.h	Wed Feb  9 21:33:00 2000
@@ -29,7 +29,7 @@
 	unsigned long offset;
 	unsigned long free_pages;
 	int low_on_memory;
-	unsigned long pages_low, pages_high;
+	unsigned long pages_min, pages_low, pages_high;
 	struct pglist_data *zone_pgdat;
 
 	/*
diff -u --recursive --new-file v2.3.42/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- v2.3.42/linux/include/linux/msdos_fs.h	Wed Aug 18 16:45:21 1999
+++ linux/include/linux/msdos_fs.h	Thu Feb 10 12:17:00 2000
@@ -271,11 +271,6 @@
 extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *);
 extern void fat_truncate(struct inode *inode);
 
-/* mmap.c */
-extern int fat_mmap(struct file *, struct vm_area_struct *);
-extern int fat_readpage(struct file *, struct page *);
-
-
 /* vfat.c */
 extern int init_vfat_fs(void);
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/msdos_fs_i.h linux/include/linux/msdos_fs_i.h
--- v2.3.42/linux/include/linux/msdos_fs_i.h	Mon Aug  9 11:43:49 1999
+++ linux/include/linux/msdos_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -6,6 +6,7 @@
  */
 
 struct msdos_inode_info {
+	unsigned long mmu_private;
 	int i_start;	/* first cluster or 0 */
 	int i_logstart;	/* logical first cluster */
 	int i_attrs;	/* unused attribute bits */
@@ -13,7 +14,6 @@
 	int i_location;	/* on-disk position of directory entry or 0 */
 	struct inode *i_fat_inode;	/* struct inode of this one */
 	struct list_head i_fat_hash;	/* hash by i_location */
-	int i_realsize;
 };
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.3.42/linux/include/linux/netdevice.h	Fri Jan  7 19:13:23 2000
+++ linux/include/linux/netdevice.h	Wed Feb  9 21:34:14 2000
@@ -29,6 +29,8 @@
 #include <linux/if_packet.h>
 
 #include <asm/atomic.h>
+#include <asm/cache.h>
+#include <asm/byteorder.h>
 
 #ifdef __KERNEL__
 #include <linux/config.h>
@@ -107,15 +109,6 @@
 	unsigned long	tx_compressed;
 };
 
-#ifdef CONFIG_NET_FASTROUTE
-struct net_fastroute_stats
-{
-	int		hits;
-	int		succeed;
-	int		deferred;
-	int		latency_reduction;
-};
-#endif
 
 /* Media selection options. */
 enum {
@@ -138,6 +131,23 @@
 struct neigh_parms;
 struct sk_buff;
 
+struct netif_rx_stats
+{
+	unsigned total;
+	unsigned dropped;
+	unsigned time_squeeze;
+	unsigned throttled;
+	unsigned fastroute_hit;
+	unsigned fastroute_success;
+	unsigned fastroute_defer;
+	unsigned fastroute_deferred_out;
+	unsigned fastroute_latency_reduction;
+	unsigned cpu_collision;
+} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
+
+extern struct netif_rx_stats netdev_rx_stat[];
+
+
 /*
  *	We tag multicasts with these structures.
  */
@@ -163,6 +173,16 @@
 	unsigned long	hh_data[16/sizeof(unsigned long)];
 };
 
+enum netdev_state_t
+{
+	LINK_STATE_XOFF=0,
+	LINK_STATE_DOWN,
+	LINK_STATE_START,
+	LINK_STATE_RXSEM,
+	LINK_STATE_TXSEM,
+	LINK_STATE_SCHED
+};
+
 
 /*
  *	The DEVICE structure.
@@ -194,34 +214,30 @@
 	unsigned long		mem_start;	/* shared mem start	*/
 	unsigned long		base_addr;	/* device I/O address	*/
 	unsigned int		irq;		/* device IRQ number	*/
-	
-	/* Low-level status flags. */
-	volatile unsigned char	start;		/* start an operation	*/
+
 	/*
-	 * These two are just single-bit flags, but due to atomicity
-	 * reasons they have to be inside a "unsigned long". However,
-	 * they should be inside the SAME unsigned long instead of
-	 * this wasteful use of memory..
+	 *	Some hardware also needs these fields, but they are not
+	 *	part of the usual set specified in Space.c.
 	 */
-	unsigned long		interrupt;	/* bitops.. */
-	unsigned long		tbusy;		/* transmitter busy */
-	
-	struct net_device		*next;
+
+	unsigned char		if_port;	/* Selectable AUI, TP,..*/
+	unsigned char		dma;		/* DMA channel		*/
+
+	unsigned long		state;
+
+	struct net_device	*next;
 	
 	/* The device initialization function. Called only once. */
 	int			(*init)(struct net_device *dev);
 
+	/* ------- Fields preinitialized in Space.c finish here ------- */
+
+	struct net_device	*next_sched;
+
 	/* Interface index. Unique device identifier	*/
 	int			ifindex;
 	int			iflink;
 
-	/*
-	 *	Some hardware also needs these fields, but they are not
-	 *	part of the usual set specified in Space.c.
-	 */
-
-	unsigned char		if_port;	/* Selectable AUI, TP,..*/
-	unsigned char		dma;		/* DMA channel		*/
 
 	struct net_device_stats* (*get_stats)(struct net_device *dev);
 	struct iw_statistics*	(*get_wireless_stats)(struct net_device *dev);
@@ -235,14 +251,18 @@
 	/* These may be needed for future network-power-down code. */
 	unsigned long		trans_start;	/* Time (in jiffies) of last Tx	*/
 	unsigned long		last_rx;	/* Time of last Rx	*/
-	
+
 	unsigned short		flags;	/* interface flags (a la BSD)	*/
 	unsigned short		gflags;
 	unsigned		mtu;	/* interface MTU value		*/
 	unsigned short		type;	/* interface hardware type	*/
 	unsigned short		hard_header_len;	/* hardware hdr length	*/
 	void			*priv;	/* pointer to private data	*/
-	
+
+	struct net_device	*master; /* Pointer to master device of a group,
+					  * which this device is member of.
+					  */
+
 	/* Interface address info. */
 	unsigned char		broadcast[MAX_ADDR_LEN];	/* hw bcast add	*/
 	unsigned char		pad;		/* make dev_addr aligned to 8 bytes */
@@ -253,11 +273,9 @@
 	int			mc_count;	/* Number of installed mcasts	*/
 	int			promiscuity;
 	int			allmulti;
-    
-	/* For load balancing driver pair support */
-  
-	unsigned long		pkt_queue;	/* Packets queued	*/
-	struct net_device		*slave;		/* Slave device		*/
+
+	int			watchdog_timeo;
+	struct timer_list	watchdog_timer;
 
 	/* Protocol specific pointers */
 	
@@ -329,13 +347,15 @@
 #define HAVE_CHANGE_MTU
 	int			(*change_mtu)(struct net_device *dev, int new_mtu);
 
+#define HAVE_TX_TIMOUT
+	void			(*tx_timeout) (struct net_device *dev);
+
 	int			(*hard_header_parse)(struct sk_buff *skb,
 						     unsigned char *haddr);
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
 	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
 
 #ifdef CONFIG_NET_FASTROUTE
-	unsigned long		tx_semaphore;
 #define NETDEV_FASTROUTE_HMASK 0xF
 	/* Semi-private data. Keep it at the end of device struct. */
 	rwlock_t		fastpath_lock;
@@ -361,8 +381,6 @@
 extern struct net_device		loopback_dev;		/* The loopback */
 extern struct net_device		*dev_base;		/* All devices */
 extern rwlock_t			dev_base_lock;		/* Device list lock */
-extern int			netdev_dropping;
-extern int			net_cpu_congestion;
 
 extern struct net_device    *dev_getbyhwaddr(unsigned short type, char *hwaddr);
 extern void		dev_add_pack(struct packet_type *pt);
@@ -392,9 +410,77 @@
 	return register_gifconf(family, 0);
 }
 
+/*
+ * Incoming packets are placed on per-cpu queues so that
+ * no locking is needed.
+ */
+
+struct softnet_data
+{
+	int			throttle;
+	struct sk_buff_head	input_pkt_queue;
+	struct net_device	*output_queue;
+	struct sk_buff		*completion_queue;
+} __attribute__((__aligned__(SMP_CACHE_BYTES)));
+
+
+extern struct softnet_data softnet_data[NR_CPUS];
+
+#define HAS_NETIF_QUEUE
+
+extern __inline__ void __netif_schedule(struct net_device *dev)
+{
+	if (!test_and_set_bit(LINK_STATE_SCHED, &dev->state)) {
+		unsigned long flags;
+		int cpu = smp_processor_id();
+
+		local_irq_save(flags);
+		dev->next_sched = softnet_data[cpu].output_queue;
+		softnet_data[cpu].output_queue = dev;
+		__cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
+		local_irq_restore(flags);
+	}
+}
+
+extern __inline__ void netif_schedule(struct net_device *dev)
+{
+	if (!test_bit(LINK_STATE_XOFF, &dev->state))
+		__netif_schedule(dev);
+}
+
+extern __inline__ void netif_start_queue(struct net_device *dev)
+{
+	clear_bit(LINK_STATE_XOFF, &dev->state);
+}
+
+extern __inline__ void netif_wake_queue(struct net_device *dev)
+{
+	if (test_and_clear_bit(LINK_STATE_XOFF, &dev->state))
+		__netif_schedule(dev);
+}
+
+extern __inline__ void netif_stop_queue(struct net_device *dev)
+{
+	set_bit(LINK_STATE_XOFF, &dev->state);
+}
+
+extern __inline__ void dev_kfree_skb_irq(struct sk_buff *skb)
+{
+	if (atomic_dec_and_test(&skb->users)) {
+		int cpu =smp_processor_id();
+		unsigned long flags;
+
+		local_irq_save(flags);
+		skb->next = softnet_data[cpu].completion_queue;
+		softnet_data[cpu].completion_queue = skb;
+		__cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
+		local_irq_restore(flags);
+	}
+}
+
+
 #define HAVE_NETIF_RX 1
 extern void		netif_rx(struct sk_buff *skb);
-extern void		net_bh(void);
 extern int		dev_ioctl(unsigned int cmd, void *);
 extern int		dev_change_flags(struct net_device *, unsigned);
 extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
@@ -448,15 +534,13 @@
 extern void		dev_mcast_init(void);
 extern int		netdev_register_fc(struct net_device *dev, void (*stimul)(struct net_device *dev));
 extern void		netdev_unregister_fc(int bit);
-extern int		netdev_dropping;
 extern int		netdev_max_backlog;
-extern atomic_t		netdev_rx_dropped;
 extern unsigned long	netdev_fc_xoff;
+extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
 #ifdef CONFIG_NET_FASTROUTE
 extern int		netdev_fastroute;
 extern int		netdev_fastroute_obstacles;
 extern void		dev_clear_fastroute(struct net_device *dev);
-extern struct net_fastroute_stats dev_fastroute_stat;
 #endif
 
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.3.42/linux/include/linux/nfs_fs.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/nfs_fs.h	Thu Feb 10 12:17:00 2000
@@ -190,6 +190,7 @@
  * linux/fs/nfs/file.c
  */
 extern struct inode_operations nfs_file_inode_operations;
+extern struct address_space_operations nfs_file_aops;
 
 /*
  * linux/fs/nfs/dir.c
diff -u --recursive --new-file v2.3.42/linux/include/linux/ntfs_fs_i.h linux/include/linux/ntfs_fs_i.h
--- v2.3.42/linux/include/linux/ntfs_fs_i.h	Tue Jan 11 22:31:44 2000
+++ linux/include/linux/ntfs_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -62,6 +62,7 @@
 
 /* Definition of NTFS in-memory inode structure */
 struct ntfs_inode_info{
+	unsigned long mmu_private;
 	struct ntfs_sb_info *vol;
 	int i_number;                /* should be really 48 bits */
 	unsigned sequence_number;
diff -u --recursive --new-file v2.3.42/linux/include/linux/openpic.h linux/include/linux/openpic.h
--- v2.3.42/linux/include/linux/openpic.h	Mon Dec 20 18:48:22 1999
+++ linux/include/linux/openpic.h	Wed Feb  9 19:43:47 2000
@@ -263,8 +263,12 @@
      *  Interrupt Source Registers
      */
 
-#define OPENPIC_SENSE_POLARITY			0x00800000	/* Undoc'd */
+#define OPENPIC_POLARITY_POSITIVE		0x00800000
+#define OPENPIC_POLARITY_NEGATIVE		0x00000000
+#define OPENPIC_POLARITY_MASK			0x00800000
 #define OPENPIC_SENSE_LEVEL			0x00400000
+#define OPENPIC_SENSE_EDGE			0x00000000
+#define OPENPIC_SENSE_MASK			0x00400000
 
 
     /*
diff -u --recursive --new-file v2.3.42/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.3.42/linux/include/linux/pagemap.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/pagemap.h	Thu Feb 10 12:17:00 2000
@@ -83,7 +83,7 @@
 
 extern inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long index)
 {
-	__add_page_to_hash_queue(page, page_hash(&inode->i_data,index));
+	__add_page_to_hash_queue(page, page_hash(inode->i_mapping,index));
 }
 
 extern inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
diff -u --recursive --new-file v2.3.42/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.42/linux/include/linux/pci.h	Tue Feb  1 01:35:44 2000
+++ linux/include/linux/pci.h	Thu Feb 10 12:24:54 2000
@@ -149,7 +149,8 @@
 #define  PCI_BRIDGE_CTL_FAST_BACK 0x80	/* Fast Back2Back enabled on secondary interface */
 
 /* Header type 2 (CardBus bridges) */
-/* 0x14-0x15 reserved */
+#define PCI_CB_CAPABILITY_LIST	0x14
+/* 0x15 reserved */
 #define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
 #define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
 #define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
@@ -570,6 +571,19 @@
 extern inline int pci_enable_device(struct pci_dev *dev) { return 0; }
 
 #endif /* !CONFIG_PCI */
+
+/* these helpers provide future and backwards compatibility
+ * for accessing popular PCI BAR info */
+#define pci_resource_start(dev,bar)   ((dev)->resource[(bar)].start)
+#define pci_resource_end(dev,bar)     ((dev)->resource[(bar)].end)
+#define pci_resource_flags(dev,bar)   ((dev)->resource[(bar)].flags)
+#define pci_resource_len(dev,bar) \
+	((pci_resource_start((dev),(bar)) == 0 &&	\
+	  pci_resource_end((dev),(bar)) ==		\
+	  pci_resource_start((dev),(bar))) ? 0 :	\
+	  						\
+	 (pci_resource_end((dev),(bar)) -		\
+	  pci_resource_start((dev),(bar)) + 1))
 
 /*
  *  The world is not perfect and supplies us with broken PCI devices.
diff -u --recursive --new-file v2.3.42/linux/include/linux/pm.h linux/include/linux/pm.h
--- v2.3.42/linux/include/linux/pm.h	Fri Jan 28 15:09:09 2000
+++ linux/include/linux/pm.h	Wed Feb  9 21:33:47 2000
@@ -21,6 +21,8 @@
 #ifndef _LINUX_PM_H
 #define _LINUX_PM_H
 
+#ifdef __KERNEL__
+
 #include <linux/config.h>
 #include <linux/list.h>
 
@@ -69,8 +71,10 @@
 	PM_SYS_UNKNOWN = 0x00000000, /* generic */
 	PM_SYS_KBC =	 0x41d00303, /* keyboard controller */
 	PM_SYS_COM =	 0x41d00500, /* serial port */
+	PM_SYS_IRDA =	 0x41d00510, /* IRDA controller */
 	PM_SYS_FDC =	 0x41d00700, /* floppy controller */
 	PM_SYS_VGA =	 0x41d00900, /* VGA controller */
+	PM_SYS_PCMCIA =	 0x41d00e00, /* PCMCIA controller */
 };
 
 /*
@@ -96,13 +100,17 @@
 	void		*data;
 
 	unsigned long	 flags;
-	unsigned long	 status;
+	int		 state;
 
 	struct list_head entry;
 };
 
 #if defined(CONFIG_ACPI) || defined(CONFIG_APM)
 
+extern int pm_active;
+
+#define PM_IS_ACTIVE() (pm_active != 0)
+
 /*
  * Register a device with power management
  */
@@ -116,6 +124,11 @@
 void pm_unregister(struct pm_dev *dev);
 
 /*
+ * Unregister all devices with matching callback
+ */
+void pm_unregister_all(pm_callback callback);
+
+/*
  * Send a request to all devices
  */
 int pm_send_request(pm_request_t rqst, void *data);
@@ -130,6 +143,8 @@
 
 #else // CONFIG_ACPI || CONFIG_APM
 
+#define PM_IS_ACTIVE() 0
+
 extern inline struct pm_dev *pm_register(pm_dev_t type,
 					 unsigned long id,
 					 pm_callback callback)
@@ -139,6 +154,8 @@
 
 extern inline void pm_unregister(struct pm_dev *dev) {}
 
+extern inline void pm_unregister_all(pm_callback callback) {}
+
 extern inline int pm_send_request(pm_request_t rqst, void *data)
 {
 	return 0;
@@ -153,5 +170,10 @@
 extern inline void pm_dev_idle(struct pm_dev *dev) {}
 
 #endif // CONFIG_ACPI || CONFIG_APM
+
+extern void (*pm_idle)(void);
+extern void (*pm_power_off)(void);
+
+#endif // __KERNEL__
 
 #endif /* _LINUX_PM_H */
diff -u --recursive --new-file v2.3.42/linux/include/linux/pmu.h linux/include/linux/pmu.h
--- v2.3.42/linux/include/linux/pmu.h	Fri Oct 15 15:25:14 1999
+++ linux/include/linux/pmu.h	Wed Feb  9 19:43:47 2000
@@ -51,6 +51,7 @@
 	PMU_OHARE_BASED,	/* 2400, 3400, 3500 (old G3 powerbook) */
 	PMU_HEATHROW_BASED,	/* PowerBook G3 series */
 	PMU_PADDINGTON_BASED,	/* 1999 PowerBook G3 */
+	PMU_KEYLARGO_BASED,	/* Core99 motherboard (PMU99) */
 };
 
 /*
@@ -66,6 +67,8 @@
 #define PMU_IOC_SET_BACKLIGHT	_IOW('B', 2, sizeof(__u32))
 /* out param: u32*	backlight value: 0 to 31 */
 #define PMU_IOC_GET_MODEL	_IOR('B', 3, sizeof(__u32*))
+/* out param: u32*	has_adb: 0 or 1 */
+#define PMU_IOC_HAS_ADB		_IOR('B', 4, sizeof(__u32*)) 
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/ppp_channel.h linux/include/linux/ppp_channel.h
--- v2.3.42/linux/include/linux/ppp_channel.h	Fri Oct 15 15:25:14 1999
+++ linux/include/linux/ppp_channel.h	Tue Feb  8 18:35:27 2000
@@ -1,3 +1,5 @@
+#ifndef _PPP_CHANNEL_H_
+#define _PPP_CHANNEL_H_
 /*
  * Definitions for the interface between the generic PPP code
  * and a PPP channel.
@@ -17,7 +19,7 @@
  * ==FILEVERSION 990909==
  */
 
-/* $Id: ppp_channel.h,v 1.2 1999/09/15 11:21:53 paulus Exp $ */
+/* $Id: ppp_channel.h,v 1.3 2000/01/31 01:42:48 davem Exp $ */
 
 #include <linux/list.h>
 #include <linux/skbuff.h>
@@ -61,3 +63,4 @@
 extern void ppp_unregister_channel(struct ppp_channel *);
 
 #endif /* __KERNEL__ */
+#endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.42/linux/include/linux/proc_fs.h	Tue Feb  1 01:35:44 2000
+++ linux/include/linux/proc_fs.h	Wed Feb  9 21:33:21 2000
@@ -115,7 +115,6 @@
 extern struct inode_operations proc_sys_inode_operations;
 extern struct inode_operations proc_kcore_inode_operations;
 extern struct inode_operations proc_kmsg_inode_operations;
-extern struct inode_operations proc_omirr_inode_operations;
 extern struct inode_operations proc_ppc_htab_inode_operations;
 
 /*
diff -u --recursive --new-file v2.3.42/linux/include/linux/qnx4_fs.h linux/include/linux/qnx4_fs.h
--- v2.3.42/linux/include/linux/qnx4_fs.h	Tue Feb  1 01:35:44 2000
+++ linux/include/linux/qnx4_fs.h	Thu Feb 10 12:17:00 2000
@@ -108,7 +108,6 @@
 extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode);
 extern struct inode_operations qnx4_file_inode_operations;
 extern struct inode_operations qnx4_dir_inode_operations;
-extern struct inode_operations qnx4_symlink_inode_operations;
 extern int qnx4_is_free(struct super_block *sb, long block);
 extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
 extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
diff -u --recursive --new-file v2.3.42/linux/include/linux/qnx4_fs_i.h linux/include/linux/qnx4_fs_i.h
--- v2.3.42/linux/include/linux/qnx4_fs_i.h	Tue Jan 11 22:31:45 2000
+++ linux/include/linux/qnx4_fs_i.h	Thu Feb 10 12:17:00 2000
@@ -33,6 +33,7 @@
 	__u8		i_zero[4];	/*  4 */
 	qnx4_ftype_t	i_type;		/*  1 */
 	__u8		i_status;	/*  1 */
+	unsigned long	mmu_private;
 };
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid/linear.h linux/include/linux/raid/linear.h
--- v2.3.42/linux/include/linux/raid/linear.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/raid/linear.h	Tue Feb  8 11:39:00 2000
@@ -0,0 +1,32 @@
+#ifndef _LINEAR_H
+#define _LINEAR_H
+
+#include <linux/raid/md.h>
+
+struct dev_info {
+	kdev_t		dev;
+	int		size;
+	unsigned int	offset;
+};
+
+typedef struct dev_info dev_info_t;
+
+struct linear_hash
+{
+	dev_info_t *dev0, *dev1;
+};
+
+struct linear_private_data
+{
+	struct linear_hash	*hash_table;
+	dev_info_t		disks[MD_SB_DISKS];
+	dev_info_t		*smallest;
+	int			nr_zones;
+};
+
+
+typedef struct linear_private_data linear_conf_t;
+
+#define mddev_to_conf(mddev) ((linear_conf_t *) mddev->private)
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid/md.h linux/include/linux/raid/md.h
--- v2.3.42/linux/include/linux/raid/md.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/raid/md.h	Wed Feb  9 21:34:03 2000
@@ -0,0 +1,94 @@
+/*
+   md.h : Multiple Devices driver for Linux
+          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
+          Copyright (C) 1994-96 Marc ZYNGIER
+	  <zyngier@ufr-info-p7.ibp.fr> or
+	  <maz@gloups.fdn.fr>
+	  
+   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, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _MD_H
+#define _MD_H
+
+#include <linux/mm.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <asm/semaphore.h>
+#include <linux/major.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <asm/bitops.h>
+#include <linux/module.h>
+#include <linux/hdreg.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <net/checksum.h>
+#include <linux/random.h>
+#include <linux/locks.h>
+#include <asm/io.h>
+
+#include <linux/raid/md_compatible.h>
+/*
+ * 'md_p.h' holds the 'physical' layout of RAID devices
+ * 'md_u.h' holds the user <=> kernel API
+ *
+ * 'md_k.h' holds kernel internal definitions
+ */
+
+#include <linux/raid/md_p.h>
+#include <linux/raid/md_u.h>
+#include <linux/raid/md_k.h>
+
+/*
+ * Different major versions are not compatible.
+ * Different minor versions are only downward compatible.
+ * Different patchlevel versions are downward and upward compatible.
+ */
+#define MD_MAJOR_VERSION                0
+#define MD_MINOR_VERSION                90
+#define MD_PATCHLEVEL_VERSION           0
+
+extern int md_size[MAX_MD_DEVS];
+extern struct hd_struct md_hd_struct[MAX_MD_DEVS];
+
+extern void add_mddev_mapping (mddev_t *mddev, kdev_t dev, void *data);
+extern void del_mddev_mapping (mddev_t *mddev, kdev_t dev);
+extern char * partition_name (kdev_t dev);
+extern int register_md_personality (int p_num, mdk_personality_t *p);
+extern int unregister_md_personality (int p_num);
+extern mdk_thread_t * md_register_thread (void (*run) (void *data),
+				void *data, const char *name);
+extern void md_unregister_thread (mdk_thread_t *thread);
+extern void md_wakeup_thread(mdk_thread_t *thread);
+extern void md_interrupt_thread (mdk_thread_t *thread);
+extern int md_update_sb (mddev_t *mddev);
+extern int md_do_sync(mddev_t *mddev, mdp_disk_t *spare);
+extern void md_recover_arrays (void);
+extern int md_check_ordering (mddev_t *mddev);
+extern void autodetect_raid(void);
+extern struct gendisk * find_gendisk (kdev_t dev);
+extern int md_notify_reboot(struct notifier_block *this,
+					unsigned long code, void *x);
+extern int md_error (kdev_t mddev, kdev_t rdev);
+
+#if CONFIG_BLK_DEV_MD
+extern void raid_setup(char *str,int *ints) md__init;
+#endif
+
+extern void md_print_devices (void);
+
+#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
+
+#endif _MD_H
+
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid/md_compatible.h linux/include/linux/raid/md_compatible.h
--- v2.3.42/linux/include/linux/raid/md_compatible.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/raid/md_compatible.h	Wed Feb  9 21:33:09 2000
@@ -0,0 +1,160 @@
+
+/*
+   md.h : Multiple Devices driver compatibility layer for Linux 2.0/2.2
+          Copyright (C) 1998 Ingo Molnar
+	  
+   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, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#include <linux/version.h>
+
+#ifndef _MD_COMPATIBLE_H
+#define _MD_COMPATIBLE_H
+
+/** 2.3/2.4 stuff: **/
+
+#include <linux/reboot.h>
+#include <linux/vmalloc.h>
+#include <linux/blkpg.h>
+
+/* 000 */
+#define md__get_free_pages(x,y) __get_free_pages(x,y)
+
+#ifdef __i386__
+/* 001 */
+extern __inline__ int md_cpu_has_mmx(void)
+{
+	return boot_cpu_data.x86_capability & X86_FEATURE_MMX;
+}
+#endif
+
+/* 002 */
+#define md_clear_page(page)        clear_page(page)
+
+/* 003 */
+#define MD_EXPORT_SYMBOL(x) EXPORT_SYMBOL(x)
+
+/* 004 */
+#define md_copy_to_user(x,y,z) copy_to_user(x,y,z)
+
+/* 005 */
+#define md_copy_from_user(x,y,z) copy_from_user(x,y,z)
+
+/* 006 */
+#define md_put_user put_user
+
+/* 007 */
+extern inline int md_capable_admin(void)
+{
+	return capable(CAP_SYS_ADMIN);
+}
+
+/* 008 */
+#define MD_FILE_TO_INODE(file) ((file)->f_dentry->d_inode)
+
+/* 009 */
+extern inline void md_flush_signals (void)
+{
+	spin_lock(&current->sigmask_lock);
+	flush_signals(current);
+	spin_unlock(&current->sigmask_lock);
+}
+ 
+/* 010 */
+extern inline void md_init_signals (void)
+{
+        current->exit_signal = SIGCHLD;
+        siginitsetinv(&current->blocked, sigmask(SIGKILL));
+}
+
+/* 011 */
+#define md_signal_pending signal_pending
+
+/* 012 */
+extern inline void md_set_global_readahead(int * table)
+{
+	max_readahead[MD_MAJOR] = table;
+}
+
+/* 013 */
+#define md_mdelay(x) mdelay(x)
+
+/* 014 */
+#define MD_SYS_DOWN SYS_DOWN
+#define MD_SYS_HALT SYS_HALT
+#define MD_SYS_POWER_OFF SYS_POWER_OFF
+
+/* 015 */
+#define md_register_reboot_notifier register_reboot_notifier
+
+/* 016 */
+#define md_test_and_set_bit test_and_set_bit
+
+/* 017 */
+#define md_test_and_clear_bit test_and_clear_bit
+
+/* 018 */
+#define md_atomic_read atomic_read
+#define md_atomic_set atomic_set
+
+/* 019 */
+#define md_lock_kernel lock_kernel
+#define md_unlock_kernel unlock_kernel
+
+/* 020 */
+
+#include <linux/init.h>
+
+#define md__init __init
+#define md__initdata __initdata
+#define md__initfunc(__arginit) __initfunc(__arginit)
+
+/* 021 */
+
+
+/* 022 */
+
+#define md_list_head list_head
+#define MD_LIST_HEAD(name) LIST_HEAD(name)
+#define MD_INIT_LIST_HEAD(ptr) INIT_LIST_HEAD(ptr)
+#define md_list_add list_add
+#define md_list_del list_del
+#define md_list_empty list_empty
+
+#define md_list_entry(ptr, type, member) list_entry(ptr, type, member)
+
+/* 023 */
+
+#define md_schedule_timeout schedule_timeout
+
+/* 024 */
+#define md_need_resched(tsk) ((tsk)->need_resched)
+
+/* 025 */
+#define md_spinlock_t spinlock_t
+#define MD_SPIN_LOCK_UNLOCKED SPIN_LOCK_UNLOCKED
+
+#define md_spin_lock spin_lock
+#define md_spin_unlock spin_unlock
+#define md_spin_lock_irq spin_lock_irq
+#define md_spin_unlock_irq spin_unlock_irq
+#define md_spin_unlock_irqrestore spin_unlock_irqrestore
+#define md_spin_lock_irqsave spin_lock_irqsave
+
+/* 026 */
+typedef wait_queue_head_t md_wait_queue_head_t;
+#define MD_DECLARE_WAITQUEUE(w,t) DECLARE_WAITQUEUE((w),(t))
+#define MD_DECLARE_WAIT_QUEUE_HEAD(x) DECLARE_WAIT_QUEUE_HEAD(x)
+#define md_init_waitqueue_head init_waitqueue_head
+
+/* END */
+
+#endif _MD_COMPATIBLE_H
+
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid/md_k.h linux/include/linux/raid/md_k.h
--- v2.3.42/linux/include/linux/raid/md_k.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/raid/md_k.h	Tue Feb  8 11:39:00 2000
@@ -0,0 +1,341 @@
+/*
+   md_k.h : kernel internal structure of the Linux MD driver
+          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
+	  
+   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, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _MD_K_H
+#define _MD_K_H
+
+#define MD_RESERVED       0UL
+#define LINEAR            1UL
+#define STRIPED           2UL
+#define RAID0             STRIPED
+#define RAID1             3UL
+#define RAID5             4UL
+#define TRANSLUCENT       5UL
+#define HSM               6UL
+#define MAX_PERSONALITY   7UL
+
+extern inline int pers_to_level (int pers)
+{
+	switch (pers) {
+		case HSM:		return -3;
+		case TRANSLUCENT:	return -2;
+		case LINEAR:		return -1;
+		case RAID0:		return 0;
+		case RAID1:		return 1;
+		case RAID5:		return 5;
+	}
+	panic("pers_to_level()");
+}
+
+extern inline int level_to_pers (int level)
+{
+	switch (level) {
+		case -3: return HSM;
+		case -2: return TRANSLUCENT;
+		case -1: return LINEAR;
+		case 0: return RAID0;
+		case 1: return RAID1;
+		case 4:
+		case 5: return RAID5;
+	}
+	return MD_RESERVED;
+}
+
+typedef struct mddev_s mddev_t;
+typedef struct mdk_rdev_s mdk_rdev_t;
+
+#if (MINORBITS != 8)
+#error MD doesnt handle bigger kdev yet
+#endif
+
+#define MAX_REAL     12			/* Max number of disks per md dev */
+#define MAX_MD_DEVS  (1<<MINORBITS)	/* Max number of md dev */
+
+/*
+ * Maps a kdev to an mddev/subdev. How 'data' is handled is up to
+ * the personality. (eg. HSM uses this to identify individual LVs)
+ */
+typedef struct dev_mapping_s {
+	mddev_t *mddev;
+	void *data;
+} dev_mapping_t;
+
+extern dev_mapping_t mddev_map [MAX_MD_DEVS];
+
+extern inline mddev_t * kdev_to_mddev (kdev_t dev)
+{
+        return mddev_map[MINOR(dev)].mddev;
+}
+
+/*
+ * options passed in raidrun:
+ */
+
+#define MAX_CHUNK_SIZE (4096*1024)
+
+/*
+ * default readahead
+ */
+#define MD_READAHEAD	(256 * 512)
+
+extern inline int disk_faulty(mdp_disk_t * d)
+{
+	return d->state & (1 << MD_DISK_FAULTY);
+}
+
+extern inline int disk_active(mdp_disk_t * d)
+{
+	return d->state & (1 << MD_DISK_ACTIVE);
+}
+
+extern inline int disk_sync(mdp_disk_t * d)
+{
+	return d->state & (1 << MD_DISK_SYNC);
+}
+
+extern inline int disk_spare(mdp_disk_t * d)
+{
+	return !disk_sync(d) && !disk_active(d) && !disk_faulty(d);
+}
+
+extern inline int disk_removed(mdp_disk_t * d)
+{
+	return d->state & (1 << MD_DISK_REMOVED);
+}
+
+extern inline void mark_disk_faulty(mdp_disk_t * d)
+{
+	d->state |= (1 << MD_DISK_FAULTY);
+}
+
+extern inline void mark_disk_active(mdp_disk_t * d)
+{
+	d->state |= (1 << MD_DISK_ACTIVE);
+}
+
+extern inline void mark_disk_sync(mdp_disk_t * d)
+{
+	d->state |= (1 << MD_DISK_SYNC);
+}
+
+extern inline void mark_disk_spare(mdp_disk_t * d)
+{
+	d->state = 0;
+}
+
+extern inline void mark_disk_removed(mdp_disk_t * d)
+{
+	d->state = (1 << MD_DISK_FAULTY) | (1 << MD_DISK_REMOVED);
+}
+
+extern inline void mark_disk_inactive(mdp_disk_t * d)
+{
+	d->state &= ~(1 << MD_DISK_ACTIVE);
+}
+
+extern inline void mark_disk_nonsync(mdp_disk_t * d)
+{
+	d->state &= ~(1 << MD_DISK_SYNC);
+}
+
+/*
+ * MD's 'extended' device
+ */
+struct mdk_rdev_s
+{
+	struct md_list_head same_set;	/* RAID devices within the same set */
+	struct md_list_head all;	/* all RAID devices */
+	struct md_list_head pending;	/* undetected RAID devices */
+
+	kdev_t dev;			/* Device number */
+	kdev_t old_dev;			/*  "" when it was last imported */
+	int size;			/* Device size (in blocks) */
+	mddev_t *mddev;			/* RAID array if running */
+	unsigned long last_events;	/* IO event timestamp */
+
+	struct inode *inode;		/* Lock inode */
+	struct file filp;		/* Lock file */
+
+	mdp_super_t *sb;
+	int sb_offset;
+
+	int faulty;			/* if faulty do not issue IO requests */
+	int desc_nr;			/* descriptor index in the superblock */
+};
+
+
+/*
+ * disk operations in a working array:
+ */
+#define DISKOP_SPARE_INACTIVE	0
+#define DISKOP_SPARE_WRITE	1
+#define DISKOP_SPARE_ACTIVE	2
+#define DISKOP_HOT_REMOVE_DISK	3
+#define DISKOP_HOT_ADD_DISK	4
+
+typedef struct mdk_personality_s mdk_personality_t;
+
+struct mddev_s
+{
+	void				*private;
+	mdk_personality_t		*pers;
+	int				__minor;
+	mdp_super_t			*sb;
+	int				nb_dev;
+	struct md_list_head 		disks;
+	int				sb_dirty;
+	mdu_param_t			param;
+	int				ro;
+	unsigned int			curr_resync;
+	unsigned long			resync_start;
+	char				*name;
+	int				recovery_running;
+	struct semaphore		reconfig_sem;
+	struct semaphore		recovery_sem;
+	struct semaphore		resync_sem;
+	struct md_list_head		all_mddevs;
+	request_queue_t			queue;
+};
+
+struct mdk_personality_s
+{
+	char *name;
+	int (*map)(mddev_t *mddev, kdev_t dev, kdev_t *rdev,
+		unsigned long *rsector, unsigned long size);
+	int (*make_request)(mddev_t *mddev, int rw, struct buffer_head * bh);
+	void (*end_request)(struct buffer_head * bh, int uptodate);
+	int (*run)(mddev_t *mddev);
+	int (*stop)(mddev_t *mddev);
+	int (*status)(char *page, mddev_t *mddev);
+	int (*ioctl)(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg);
+	int max_invalid_dev;
+	int (*error_handler)(mddev_t *mddev, kdev_t dev);
+
+/*
+ * Some personalities (RAID-1, RAID-5) can have disks hot-added and
+ * hot-removed. Hot removal is different from failure. (failure marks
+ * a disk inactive, but the disk is still part of the array) The interface
+ * to such operations is the 'pers->diskop()' function, can be NULL.
+ *
+ * the diskop function can change the pointer pointing to the incoming
+ * descriptor, but must do so very carefully. (currently only
+ * SPARE_ACTIVE expects such a change)
+ */
+	int (*diskop) (mddev_t *mddev, mdp_disk_t **descriptor, int state);
+
+	int (*stop_resync)(mddev_t *mddev);
+	int (*restart_resync)(mddev_t *mddev);
+};
+
+
+/*
+ * Currently we index md_array directly, based on the minor
+ * number. This will have to change to dynamic allocation
+ * once we start supporting partitioning of md devices.
+ */
+extern inline int mdidx (mddev_t * mddev)
+{
+	return mddev->__minor;
+}
+
+extern inline kdev_t mddev_to_kdev(mddev_t * mddev)
+{
+	return MKDEV(MD_MAJOR, mdidx(mddev));
+}
+
+extern mdk_rdev_t * find_rdev(mddev_t * mddev, kdev_t dev);
+extern mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr);
+
+/*
+ * iterates through some rdev ringlist. It's safe to remove the
+ * current 'rdev'. Dont touch 'tmp' though.
+ */
+#define ITERATE_RDEV_GENERIC(head,field,rdev,tmp)			\
+									\
+	for (tmp = head.next;						\
+		rdev = md_list_entry(tmp, mdk_rdev_t, field),		\
+			tmp = tmp->next, tmp->prev != &head		\
+		; )
+/*
+ * iterates through the 'same array disks' ringlist
+ */
+#define ITERATE_RDEV(mddev,rdev,tmp)					\
+	ITERATE_RDEV_GENERIC((mddev)->disks,same_set,rdev,tmp)
+
+/*
+ * Same as above, but assumes that the device has rdev->desc_nr numbered
+ * from 0 to mddev->nb_dev, and iterates through rdevs in ascending order.
+ */
+#define ITERATE_RDEV_ORDERED(mddev,rdev,i)				\
+	for (i = 0; rdev = find_rdev_nr(mddev, i), i < mddev->nb_dev; i++)
+
+
+/*
+ * Iterates through all 'RAID managed disks'
+ */
+#define ITERATE_RDEV_ALL(rdev,tmp)					\
+	ITERATE_RDEV_GENERIC(all_raid_disks,all,rdev,tmp)
+
+/*
+ * Iterates through 'pending RAID disks'
+ */
+#define ITERATE_RDEV_PENDING(rdev,tmp)					\
+	ITERATE_RDEV_GENERIC(pending_raid_disks,pending,rdev,tmp)
+
+/*
+ * iterates through all used mddevs in the system.
+ */
+#define ITERATE_MDDEV(mddev,tmp)					\
+									\
+	for (tmp = all_mddevs.next;					\
+		mddev = md_list_entry(tmp, mddev_t, all_mddevs),	\
+			tmp = tmp->next, tmp->prev != &all_mddevs	\
+		; )
+
+extern inline int lock_mddev (mddev_t * mddev)
+{
+	return down_interruptible(&mddev->reconfig_sem);
+}
+
+extern inline void unlock_mddev (mddev_t * mddev)
+{
+	up(&mddev->reconfig_sem);
+}
+
+#define xchg_values(x,y) do { __typeof__(x) __tmp = x; \
+				x = y; y = __tmp; } while (0)
+
+typedef struct mdk_thread_s {
+	void			(*run) (void *data);
+	void			*data;
+	md_wait_queue_head_t	wqueue;
+	unsigned long           flags;
+	struct semaphore	*sem;
+	struct task_struct	*tsk;
+	const char		*name;
+} mdk_thread_t;
+
+#define THREAD_WAKEUP  0
+
+#define MAX_DISKNAME_LEN 32
+
+typedef struct dev_name_s {
+	struct md_list_head list;
+	kdev_t dev;
+	char name [MAX_DISKNAME_LEN];
+} dev_name_t;
+
+#endif _MD_K_H
+
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid/md_p.h linux/include/linux/raid/md_p.h
--- v2.3.42/linux/include/linux/raid/md_p.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/raid/md_p.h	Tue Feb  8 11:39:00 2000
@@ -0,0 +1,161 @@
+/*
+   md_p.h : physical layout of Linux RAID devices
+          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
+	  
+   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, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _MD_P_H
+#define _MD_P_H
+
+/*
+ * RAID superblock.
+ *
+ * The RAID superblock maintains some statistics on each RAID configuration.
+ * Each real device in the RAID set contains it near the end of the device.
+ * Some of the ideas are copied from the ext2fs implementation.
+ *
+ * We currently use 4096 bytes as follows:
+ *
+ *	word offset	function
+ *
+ *	   0  -    31	Constant generic RAID device information.
+ *        32  -    63   Generic state information.
+ *	  64  -   127	Personality specific information.
+ *	 128  -   511	12 32-words descriptors of the disks in the raid set.
+ *	 512  -   911	Reserved.
+ *	 912  -  1023	Disk specific descriptor.
+ */
+
+/*
+ * If x is the real device size in bytes, we return an apparent size of:
+ *
+ *	y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
+ *
+ * and place the 4kB superblock at offset y.
+ */
+#define MD_RESERVED_BYTES		(64 * 1024)
+#define MD_RESERVED_SECTORS		(MD_RESERVED_BYTES / 512)
+#define MD_RESERVED_BLOCKS		(MD_RESERVED_BYTES / BLOCK_SIZE)
+
+#define MD_NEW_SIZE_SECTORS(x)		((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
+#define MD_NEW_SIZE_BLOCKS(x)		((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
+
+#define MD_SB_BYTES			4096
+#define MD_SB_WORDS			(MD_SB_BYTES / 4)
+#define MD_SB_BLOCKS			(MD_SB_BYTES / BLOCK_SIZE)
+#define MD_SB_SECTORS			(MD_SB_BYTES / 512)
+
+/*
+ * The following are counted in 32-bit words
+ */
+#define	MD_SB_GENERIC_OFFSET		0
+#define MD_SB_PERSONALITY_OFFSET	64
+#define MD_SB_DISKS_OFFSET		128
+#define MD_SB_DESCRIPTOR_OFFSET		992
+
+#define MD_SB_GENERIC_CONSTANT_WORDS	32
+#define MD_SB_GENERIC_STATE_WORDS	32
+#define MD_SB_GENERIC_WORDS		(MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
+#define MD_SB_PERSONALITY_WORDS		64
+#define MD_SB_DESCRIPTOR_WORDS		32
+#define MD_SB_DISKS			27
+#define MD_SB_DISKS_WORDS		(MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_RESERVED_WORDS		(1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_EQUAL_WORDS		(MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
+
+/*
+ * Device "operational" state bits
+ */
+#define MD_DISK_FAULTY		0 /* disk is faulty / operational */
+#define MD_DISK_ACTIVE		1 /* disk is running or spare disk */
+#define MD_DISK_SYNC		2 /* disk is in sync with the raid set */
+#define MD_DISK_REMOVED		3 /* disk is in sync with the raid set */
+
+typedef struct mdp_device_descriptor_s {
+	__u32 number;		/* 0 Device number in the entire set	      */
+	__u32 major;		/* 1 Device major number		      */
+	__u32 minor;		/* 2 Device minor number		      */
+	__u32 raid_disk;	/* 3 The role of the device in the raid set   */
+	__u32 state;		/* 4 Operational state			      */
+	__u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
+} mdp_disk_t;
+
+#define MD_SB_MAGIC		0xa92b4efc
+
+/*
+ * Superblock state bits
+ */
+#define MD_SB_CLEAN		0
+#define MD_SB_ERRORS		1
+
+typedef struct mdp_superblock_s {
+	/*
+	 * Constant generic information
+	 */
+	__u32 md_magic;		/*  0 MD identifier 			      */
+	__u32 major_version;	/*  1 major version to which the set conforms */
+	__u32 minor_version;	/*  2 minor version ...			      */
+	__u32 patch_version;	/*  3 patchlevel version ...		      */
+	__u32 gvalid_words;	/*  4 Number of used words in this section    */
+	__u32 set_uuid0;	/*  5 Raid set identifier		      */
+	__u32 ctime;		/*  6 Creation time			      */
+	__u32 level;		/*  7 Raid personality			      */
+	__u32 size;		/*  8 Apparent size of each individual disk   */
+	__u32 nr_disks;		/*  9 total disks in the raid set	      */
+	__u32 raid_disks;	/* 10 disks in a fully functional raid set    */
+	__u32 md_minor;		/* 11 preferred MD minor device number	      */
+	__u32 not_persistent;	/* 12 does it have a persistent superblock    */
+	__u32 set_uuid1;	/* 13 Raid set identifier #2		      */
+	__u32 set_uuid2;	/* 14 Raid set identifier #3		      */
+	__u32 set_uuid3;	/* 14 Raid set identifier #4		      */
+	__u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
+
+	/*
+	 * Generic state information
+	 */
+	__u32 utime;		/*  0 Superblock update time		      */
+	__u32 state;		/*  1 State bits (clean, ...)		      */
+	__u32 active_disks;	/*  2 Number of currently active disks	      */
+	__u32 working_disks;	/*  3 Number of working disks		      */
+	__u32 failed_disks;	/*  4 Number of failed disks		      */
+	__u32 spare_disks;	/*  5 Number of spare disks		      */
+	__u32 sb_csum;		/*  6 checksum of the whole superblock        */
+	__u64 events;		/*  7 number of superblock updates (64-bit!)  */
+	__u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 9];
+
+	/*
+	 * Personality information
+	 */
+	__u32 layout;		/*  0 the array's physical layout	      */
+	__u32 chunk_size;	/*  1 chunk size in bytes		      */
+	__u32 root_pv;		/*  2 LV root PV */
+	__u32 root_block;	/*  3 LV root block */
+	__u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
+
+	/*
+	 * Disks information
+	 */
+	mdp_disk_t disks[MD_SB_DISKS];
+
+	/*
+	 * Reserved
+	 */
+	__u32 reserved[MD_SB_RESERVED_WORDS];
+
+	/*
+	 * Active descriptor
+	 */
+	mdp_disk_t this_disk;
+
+} mdp_super_t;
+
+#endif _MD_P_H
+
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid/md_u.h linux/include/linux/raid/md_u.h
--- v2.3.42/linux/include/linux/raid/md_u.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/raid/md_u.h	Tue Feb  8 11:39:00 2000
@@ -0,0 +1,115 @@
+/*
+   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
+          Copyright (C) 1998 Ingo Molnar
+	  
+   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, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _MD_U_H
+#define _MD_U_H
+
+/* ioctls */
+
+/* status */
+#define RAID_VERSION		_IOR (MD_MAJOR, 0x10, mdu_version_t)
+#define GET_ARRAY_INFO		_IOR (MD_MAJOR, 0x11, mdu_array_info_t)
+#define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
+#define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13)
+
+/* configuration */
+#define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20)
+#define ADD_NEW_DISK		_IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
+#define HOT_REMOVE_DISK		_IO (MD_MAJOR, 0x22)
+#define SET_ARRAY_INFO		_IOW (MD_MAJOR, 0x23, mdu_array_info_t)
+#define SET_DISK_INFO		_IO (MD_MAJOR, 0x24)
+#define WRITE_RAID_INFO		_IO (MD_MAJOR, 0x25)
+#define UNPROTECT_ARRAY		_IO (MD_MAJOR, 0x26)
+#define PROTECT_ARRAY		_IO (MD_MAJOR, 0x27)
+#define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28)
+#define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29)
+
+/* usage */
+#define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t)
+#define START_ARRAY		_IO (MD_MAJOR, 0x31)
+#define STOP_ARRAY		_IO (MD_MAJOR, 0x32)
+#define STOP_ARRAY_RO		_IO (MD_MAJOR, 0x33)
+#define RESTART_ARRAY_RW	_IO (MD_MAJOR, 0x34)
+
+typedef struct mdu_version_s {
+	int major;
+	int minor;
+	int patchlevel;
+} mdu_version_t;
+
+typedef struct mdu_array_info_s {
+	/*
+	 * Generic constant information
+	 */
+	int major_version;
+	int minor_version;
+	int patch_version;
+	int ctime;
+	int level;
+	int size;
+	int nr_disks;
+	int raid_disks;
+	int md_minor;
+	int not_persistent;
+
+	/*
+	 * Generic state information
+	 */
+	int utime;		/*  0 Superblock update time		      */
+	int state;		/*  1 State bits (clean, ...)		      */
+	int active_disks;	/*  2 Number of currently active disks	      */
+	int working_disks;	/*  3 Number of working disks		      */
+	int failed_disks;	/*  4 Number of failed disks		      */
+	int spare_disks;	/*  5 Number of spare disks		      */
+
+	/*
+	 * Personality information
+	 */
+	int layout;		/*  0 the array's physical layout	      */
+	int chunk_size;	/*  1 chunk size in bytes		      */
+
+} mdu_array_info_t;
+
+typedef struct mdu_disk_info_s {
+	/*
+	 * configuration/status of one particular disk
+	 */
+	int number;
+	int major;
+	int minor;
+	int raid_disk;
+	int state;
+
+} mdu_disk_info_t;
+
+typedef struct mdu_start_info_s {
+	/*
+	 * configuration/status of one particular disk
+	 */
+	int major;
+	int minor;
+	int raid_disk;
+	int state;
+
+} mdu_start_info_t;
+
+typedef struct mdu_param_s
+{
+	int			personality;	/* 1,2,3,4 */
+	int			chunk_size;	/* in bytes */
+	int			max_fault;	/* unused for now */
+} mdu_param_t;
+
+#endif _MD_U_H
+
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid/raid0.h linux/include/linux/raid/raid0.h
--- v2.3.42/linux/include/linux/raid/raid0.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/raid/raid0.h	Tue Feb  8 11:39:00 2000
@@ -0,0 +1,33 @@
+#ifndef _RAID0_H
+#define _RAID0_H
+
+#include <linux/raid/md.h>
+
+struct strip_zone
+{
+	int zone_offset;		/* Zone offset in md_dev */
+	int dev_offset;			/* Zone offset in real dev */
+	int size;			/* Zone size */
+	int nb_dev;			/* # of devices attached to the zone */
+	mdk_rdev_t *dev[MAX_REAL]; /* Devices attached to the zone */
+};
+
+struct raid0_hash
+{
+	struct strip_zone *zone0, *zone1;
+};
+
+struct raid0_private_data
+{
+	struct raid0_hash *hash_table; /* Dynamically allocated */
+	struct strip_zone *strip_zone; /* This one too */
+	int nr_strip_zones;
+	struct strip_zone *smallest;
+	int nr_zones;
+};
+
+typedef struct raid0_private_data raid0_conf_t;
+
+#define mddev_to_conf(mddev) ((raid0_conf_t *) mddev->private)
+
+#endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/raid0.h linux/include/linux/raid0.h
--- v2.3.42/linux/include/linux/raid0.h	Tue Oct 29 05:20:24 1996
+++ linux/include/linux/raid0.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-#ifndef _RAID0_H
-#define _RAID0_H
-
-struct strip_zone
-{
-  int zone_offset;		/* Zone offset in md_dev */
-  int dev_offset;		/* Zone offset in real dev */
-  int size;			/* Zone size */
-  int nb_dev;			/* Number of devices attached to the zone */
-  struct real_dev *dev[MAX_REAL]; /* Devices attached to the zone */
-};
-
-struct raid0_hash
-{
-  struct strip_zone *zone0, *zone1;
-};
-
-struct raid0_data
-{
-  struct raid0_hash *hash_table; /* Dynamically allocated */
-  struct strip_zone *strip_zone; /* This one too */
-  int nr_strip_zones;
-  struct strip_zone *smallest;
-  int nr_zones;
-};
-
-#endif
diff -u --recursive --new-file v2.3.42/linux/include/linux/rtc.h linux/include/linux/rtc.h
--- v2.3.42/linux/include/linux/rtc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/rtc.h	Mon Feb  7 19:45:28 2000
@@ -0,0 +1,51 @@
+/*
+ * Generic RTC interface.
+ * This version contains the part of the user interface to the Real Time Clock
+ * service. It is used with both the legacy mc146818 and also  EFI
+ * 
+ * Copyright (C) 1999 Hewlett-Packard Co.
+ * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ */
+#ifndef _LINUX_RTC_H
+#define _LINUX_RTC_H_
+
+/*
+ * The struct used to pass data via the following ioctl. Similar to the
+ * struct tm in <time.h>, but it needs to be here so that the kernel 
+ * source is self contained, allowing cross-compiles, etc. etc.
+ */
+
+struct rtc_time {
+	int tm_sec;
+	int tm_min;
+	int tm_hour;
+	int tm_mday;
+	int tm_mon;
+	int tm_year;
+	int tm_wday;
+	int tm_yday;
+	int tm_isdst;
+};
+
+/*
+ * ioctl calls that are permitted to the /dev/rtc interface, if 
+ * CONFIG_RTC/CONFIG_EFI_RTC was enabled.
+ */
+
+#define RTC_AIE_ON	_IO('p', 0x01)	/* Alarm int. enable on		*/
+#define RTC_AIE_OFF	_IO('p', 0x02)	/* ... off			*/
+#define RTC_UIE_ON	_IO('p', 0x03)	/* Update int. enable on	*/
+#define RTC_UIE_OFF	_IO('p', 0x04)	/* ... off			*/
+#define RTC_PIE_ON	_IO('p', 0x05)	/* Periodic int. enable on	*/
+#define RTC_PIE_OFF	_IO('p', 0x06)	/* ... off			*/
+
+#define RTC_ALM_SET	_IOW('p', 0x07, struct rtc_time) /* Set alarm time  */
+#define RTC_ALM_READ	_IOR('p', 0x08, struct rtc_time) /* Read alarm time */
+#define RTC_RD_TIME	_IOR('p', 0x09, struct rtc_time) /* Read RTC time   */
+#define RTC_SET_TIME	_IOW('p', 0x0a, struct rtc_time) /* Set RTC time    */
+#define RTC_IRQP_READ	_IOR('p', 0x0b, unsigned long)	 /* Read IRQ rate   */
+#define RTC_IRQP_SET	_IOW('p', 0x0c, unsigned long)	 /* Set IRQ rate    */
+#define RTC_EPOCH_READ	_IOR('p', 0x0d, unsigned long)	 /* Read epoch      */
+#define RTC_EPOCH_SET	_IOW('p', 0x0e, unsigned long)	 /* Set epoch       */
+
+#endif /* _LINUX_RTC_H_ */
diff -u --recursive --new-file v2.3.42/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
--- v2.3.42/linux/include/linux/rtnetlink.h	Fri Jan  7 19:13:23 2000
+++ linux/include/linux/rtnetlink.h	Wed Feb  9 20:08:09 2000
@@ -434,11 +434,15 @@
 	IFLA_QDISC,
 	IFLA_STATS,
 	IFLA_COST,
-	IFLA_PRIORITY
+#define IFLA_COST IFLA_COST
+	IFLA_PRIORITY,
+#define IFLA_PRIORITY IFLA_PRIORITY
+	IFLA_MASTER
+#define IFLA_MASTER IFLA_MASTER
 };
 
 
-#define IFLA_MAX IFLA_STATS
+#define IFLA_MAX IFLA_MASTER
 
 #define IFLA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
 #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
@@ -464,7 +468,7 @@
    IFF_BROADCAST devices are able to use multicasts too.
  */
 
-/* ifi_link.
+/* IFLA_LINK.
    For usual devices it is equal ifi_index.
    If it is a "virtual interface" (f.e. tunnel), ifi_link
    can point to real physical interface (f.e. for bandwidth calculations),
@@ -558,6 +562,13 @@
 #define RTA_PUT(skb, attrtype, attrlen, data) \
 ({ if (skb_tailroom(skb) < (int)RTA_SPACE(attrlen)) goto rtattr_failure; \
    __rta_fill(skb, attrtype, attrlen, data); })
+
+extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
+
+#else
+
+#define rtmsg_ifinfo(a,b,c) do { } while (0)
+
 #endif
 
 extern struct semaphore rtnl_sem;
diff -u --recursive --new-file v2.3.42/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.42/linux/include/linux/sched.h	Fri Jan 21 18:19:17 2000
+++ linux/include/linux/sched.h	Thu Feb 10 12:41:10 2000
@@ -80,7 +80,6 @@
 #define TASK_UNINTERRUPTIBLE	2
 #define TASK_ZOMBIE		4
 #define TASK_STOPPED		8
-#define TASK_SWAPPING		16
 #define TASK_EXCLUSIVE		32
 
 #define __set_task_state(tsk, state_value)		\
diff -u --recursive --new-file v2.3.42/linux/include/linux/shm.h linux/include/linux/shm.h
--- v2.3.42/linux/include/linux/shm.h	Tue Jan 11 22:31:45 2000
+++ linux/include/linux/shm.h	Wed Feb  9 21:34:39 2000
@@ -2,6 +2,7 @@
 #define _LINUX_SHM_H_
 
 #include <linux/ipc.h>
+#include <linux/mm.h>
 
 /*
  * SHMMAX, SHMMNI and SHMALL are upper limits are defaults which can
diff -u --recursive --new-file v2.3.42/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v2.3.42/linux/include/linux/smb_fs.h	Fri Jan 21 18:19:17 2000
+++ linux/include/linux/smb_fs.h	Thu Feb 10 12:17:00 2000
@@ -101,6 +101,7 @@
 
 /* linux/fs/smbfs/file.c */
 extern struct inode_operations smb_file_inode_operations;
+extern struct address_space_operations smb_file_aops;
 
 /* linux/fs/smbfs/dir.c */
 extern struct inode_operations smb_dir_inode_operations;
diff -u --recursive --new-file v2.3.42/linux/include/linux/sonet.h linux/include/linux/sonet.h
--- v2.3.42/linux/include/linux/sonet.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/sonet.h	Tue Feb  8 18:23:13 2000
@@ -1,22 +1,22 @@
 /* sonet.h - SONET/SHD physical layer control */
  
-/* Written 1995 by Werner Almesberger, EPFL LRC */
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
  
 
 #ifndef LINUX_SONET_H
 #define LINUX_SONET_H
 
 struct sonet_stats {
-	long section_bip;		/* section parity errors (B1) */
-	long line_bip;			/* line parity errors (B2) */
-	long path_bip;			/* path parity errors (B3) */
-	long line_febe;			/* line parity errors at remote */
-	long path_febe;			/* path parity errors at remote */
-	long corr_hcs;			/* correctable header errors */
-	long uncorr_hcs;		/* uncorrectable header errors */
-	long tx_cells;			/* cells sent */
-	long rx_cells;			/* cells received */
-};
+	int section_bip;		/* section parity errors (B1) */
+	int line_bip;			/* line parity errors (B2) */
+	int path_bip;			/* path parity errors (B3) */
+	int line_febe;			/* line parity errors at remote */
+	int path_febe;			/* path parity errors at remote */
+	int corr_hcs;			/* correctable header errors */
+	int uncorr_hcs;			/* uncorrectable header errors */
+	int tx_cells;			/* cells sent */
+	int rx_cells;			/* cells received */
+} __attribute__ ((packed));
 
 #define SONET_GETSTAT	_IOR('a',ATMIOC_PHYTYP,struct sonet_stats)
 					/* get statistics */
diff -u --recursive --new-file v2.3.42/linux/include/linux/spinlock.h linux/include/linux/spinlock.h
--- v2.3.42/linux/include/linux/spinlock.h	Fri Jan 21 18:19:17 2000
+++ linux/include/linux/spinlock.h	Wed Feb  9 21:32:58 2000
@@ -53,6 +53,7 @@
 
 #define spin_lock_init(lock)	do { } while(0)
 #define spin_lock(lock)		(void)(lock) /* Not "unused variable". */
+#define spin_is_locked(lock)	(0)
 #define spin_trylock(lock)	({1; })
 #define spin_unlock_wait(lock)	do { } while(0)
 #define spin_unlock(lock)	do { } while(0)
@@ -65,6 +66,7 @@
 #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
 
 #define spin_lock_init(x)	do { (x)->lock = 0; } while (0)
+#define spin_is_locked(lock)	(test_bit(0,(lock)))
 #define spin_trylock(lock)	(!test_and_set_bit(0,(lock)))
 
 #define spin_lock(x)		do { (x)->lock = 1; } while (0)
@@ -83,6 +85,7 @@
 #include <linux/kernel.h>
 
 #define spin_lock_init(x)	do { (x)->lock = 0; } while (0)
+#define spin_is_locked(lock)	(test_bit(0,(lock)))
 #define spin_trylock(lock)	(!test_and_set_bit(0,(lock)))
 
 #define spin_lock(x)		do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
diff -u --recursive --new-file v2.3.42/linux/include/linux/sunrpc/svc.h linux/include/linux/sunrpc/svc.h
--- v2.3.42/linux/include/linux/sunrpc/svc.h	Wed Aug 18 16:45:08 1999
+++ linux/include/linux/sunrpc/svc.h	Wed Feb  9 21:33:30 2000
@@ -29,6 +29,7 @@
 	struct svc_sock *	sv_sockets;	/* pending sockets */
 	struct svc_program *	sv_program;	/* RPC program */
 	struct svc_stat *	sv_stats;	/* RPC statistics */
+	spinlock_t		sv_lock;
 	unsigned int		sv_nrthreads;	/* # of server threads */
 	unsigned int		sv_bufsz;	/* datagram buffer size */
 	unsigned int		sv_xdrsize;	/* XDR buffer size */
diff -u --recursive --new-file v2.3.42/linux/include/linux/sunrpc/svcsock.h linux/include/linux/sunrpc/svcsock.h
--- v2.3.42/linux/include/linux/sunrpc/svcsock.h	Wed Aug 18 16:45:08 1999
+++ linux/include/linux/sunrpc/svcsock.h	Wed Feb  9 21:33:33 2000
@@ -21,6 +21,7 @@
 	struct svc_sock *	sk_list;	/* list of all sockets */
 	struct socket *		sk_sock;	/* berkeley socket layer */
 	struct sock *		sk_sk;		/* INET layer */
+	spinlock_t		sk_lock;
 
 	struct svc_serv *	sk_server;	/* service for this socket */
 	unsigned char		sk_inuse;	/* use count */
diff -u --recursive --new-file v2.3.42/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.42/linux/include/linux/sysctl.h	Fri Jan 28 15:09:09 2000
+++ linux/include/linux/sysctl.h	Wed Feb  9 20:08:09 2000
@@ -183,7 +183,8 @@
 	NET_CORE_FASTROUTE=7,
 	NET_CORE_MSG_COST=8,
 	NET_CORE_MSG_BURST=9,
-	NET_CORE_OPTMEM_MAX=10
+	NET_CORE_OPTMEM_MAX=10,
+	NET_CORE_HOT_LIST_LENGTH=11
 };
 
 /* /proc/sys/net/ethernet */
diff -u --recursive --new-file v2.3.42/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h
--- v2.3.42/linux/include/linux/sysv_fs.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/sysv_fs.h	Thu Feb 10 12:17:00 2000
@@ -384,7 +384,6 @@
 extern void sysv_free_block(struct super_block * sb, unsigned int block);
 extern unsigned long sysv_count_free_blocks(struct super_block *sb);
 
-extern int sysv_get_block(struct inode *, long, struct buffer_head *, int);
 extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
 
 extern void sysv_truncate(struct inode *);
@@ -394,9 +393,8 @@
 extern int sysv_sync_file(struct file *, struct dentry *);
 
 extern struct inode_operations sysv_file_inode_operations;
-extern struct inode_operations sysv_file_inode_operations_with_bmap;
 extern struct inode_operations sysv_dir_inode_operations;
-extern struct inode_operations sysv_symlink_inode_operations;
+extern struct address_space_operations sysv_aops;
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.42/linux/include/linux/timer.h linux/include/linux/timer.h
--- v2.3.42/linux/include/linux/timer.h	Mon Jun 28 13:41:34 1999
+++ linux/include/linux/timer.h	Wed Feb  9 21:32:56 2000
@@ -51,6 +51,7 @@
 	unsigned long expires;
 	unsigned long data;
 	void (*function)(unsigned long);
+	volatile int running;
 };
 
 extern void add_timer(struct timer_list * timer);
@@ -61,7 +62,7 @@
  * active timer (if the timer is inactive it will be activated)
  * mod_timer(a,b) is equivalent to del_timer(a); a->expires = b; add_timer(a)
  */
-void mod_timer(struct timer_list *timer, unsigned long expires);
+int mod_timer(struct timer_list *timer, unsigned long expires);
 
 extern void it_real_fn(unsigned long);
 
@@ -69,12 +70,29 @@
 {
 	timer->next = NULL;
 	timer->prev = NULL;
+#ifdef __SMP__
+	timer->running = 0;
+#endif
 }
 
 extern inline int timer_pending(const struct timer_list * timer)
 {
 	return timer->prev != NULL;
 }
+
+#ifdef __SMP__
+#define timer_exit(t) do { (t)->running = 0; mb(); } while (0)
+#define timer_set_running(t) do { (t)->running = 1; mb(); } while (0)
+#define timer_is_running(t) ((t)->running != 0)
+#define timer_synchronize(t) while (timer_is_running(t)) barrier()
+extern int del_timer_sync(struct timer_list * timer);
+#else
+#define timer_exit(t) do { } while (0)
+#define timer_set_running(t) do { } while (0)
+#define timer_is_running(t) (0)
+#define timer_synchronize(t) barrier()
+#define del_timer_sync(t) del_timer(t)
+#endif
 
 /*
  *	These inlines deal with timer wrapping correctly. You are 
diff -u --recursive --new-file v2.3.42/linux/include/linux/tqueue.h linux/include/linux/tqueue.h
--- v2.3.42/linux/include/linux/tqueue.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/tqueue.h	Wed Feb  9 21:33:00 2000
@@ -116,7 +116,8 @@
 			p      = p -> next;
 			mb();
 			save_p -> sync = 0;
-			(*f)(arg);
+			if (f)
+				(*f)(arg);
 		}
 	}
 }
diff -u --recursive --new-file v2.3.42/linux/include/linux/udf_167.h linux/include/linux/udf_167.h
--- v2.3.42/linux/include/linux/udf_167.h	Mon Nov  1 13:56:27 1999
+++ linux/include/linux/udf_167.h	Wed Feb  9 18:48:03 2000
@@ -390,10 +390,13 @@
 #define INTEGRITY_TYPE_CLOSE	1
 
 /* Recorded Address (ECMA 167 4/7.1) */
+#ifndef _LINUX_UDF_FS_I_H
+/* Declared in udf_fs_i.h */
 typedef struct {
 	Uint32 logicalBlockNum;
 	Uint16 partitionReferenceNum;
 } lb_addr;
+#endif
 
 /* Extent interpretation (ECMA 167 4/14.14.1.1) */
 #define EXTENT_RECORDED_ALLOCATED               0x00
diff -u --recursive --new-file v2.3.42/linux/include/linux/ufs_fs.h linux/include/linux/ufs_fs.h
--- v2.3.42/linux/include/linux/ufs_fs.h	Tue Dec 14 01:27:24 1999
+++ linux/include/linux/ufs_fs.h	Thu Feb 10 12:17:00 2000
@@ -525,6 +525,8 @@
 extern struct inode_operations ufs_file_inode_operations;
 extern struct file_operations ufs_file_operations;
 
+extern struct address_space_operations ufs_aops;
+
 /* ialloc.c */
 extern void ufs_free_inode (struct inode *inode);
 extern struct inode * ufs_new_inode (const struct inode *, int, int *);
@@ -538,7 +540,6 @@
 extern void ufs_write_inode (struct inode *);
 extern void ufs_delete_inode (struct inode *);
 extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
-extern int ufs_getfrag_block (struct inode *, long, struct buffer_head *, int);
 extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
 
 /* namei.c */
@@ -562,7 +563,6 @@
 extern void ufs_write_super (struct super_block *);
 
 /* symlink.c */
-extern struct inode_operations ufs_symlink_inode_operations;
 extern struct inode_operations ufs_fast_symlink_inode_operations;
 
 /* truncate.c */
diff -u --recursive --new-file v2.3.42/linux/include/linux/umsdos_fs.h linux/include/linux/umsdos_fs.h
--- v2.3.42/linux/include/linux/umsdos_fs.h	Tue Jan 11 22:31:45 2000
+++ linux/include/linux/umsdos_fs.h	Thu Feb 10 12:17:00 2000
@@ -174,7 +174,6 @@
 #endif
 
 extern struct inode_operations umsdos_dir_inode_operations;
-extern struct inode_operations umsdos_symlink_inode_operations;
 extern int init_umsdos_fs (void);
 
 #include <linux/umsdos_fs.p>
diff -u --recursive --new-file v2.3.42/linux/include/linux/vt_buffer.h linux/include/linux/vt_buffer.h
--- v2.3.42/linux/include/linux/vt_buffer.h	Wed Aug 18 16:43:31 1999
+++ linux/include/linux/vt_buffer.h	Wed Feb  9 21:33:55 2000
@@ -15,7 +15,7 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_VGA_CONSOLE
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
 #include <asm/vga.h>
 #endif
 
diff -u --recursive --new-file v2.3.42/linux/include/net/atmclip.h linux/include/net/atmclip.h
--- v2.3.42/linux/include/net/atmclip.h	Fri Sep 10 23:57:37 1999
+++ linux/include/net/atmclip.h	Wed Feb  9 21:35:57 2000
@@ -1,6 +1,6 @@
 /* net/atm/atmarp.h - RFC1577 ATM ARP */
  
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
  
  
 #ifndef _ATMCLIP_H
@@ -26,7 +26,9 @@
 	unsigned long	last_use;	/* last send or receive operation */
 	unsigned long	idle_timeout;	/* keep open idle for so many jiffies*/
 	void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
-					/* keep old push fn for detaching */
+					/* keep old push fn for chaining */
+	void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb);
+					/* keep old pop fn for chaining */
 	struct clip_vcc	*next;		/* next VCC */
 };
 
diff -u --recursive --new-file v2.3.42/linux/include/net/dsfield.h linux/include/net/dsfield.h
--- v2.3.42/linux/include/net/dsfield.h	Fri Jan  7 19:13:23 2000
+++ linux/include/net/dsfield.h	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* include/net/dsfield.h - Manipulation of the Differentiated Services field */
 
-/* Written 1998 by Werner Almesberger, EPFL ICA */
+/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
 
 
 #ifndef __NET_DSFIELD_H
@@ -46,7 +46,7 @@
         __u16 tmp;
 
 	tmp = ntohs(*(__u16 *) ipv6h);
-	tmp = (tmp & (mask << 4)) | (value << 4);
+	tmp = (tmp & ((mask << 4) | 0xf00f)) | (value << 4);
 	*(__u16 *) ipv6h = htons(tmp);
 }
 
diff -u --recursive --new-file v2.3.42/linux/include/net/irda/nsc-ircc.h linux/include/net/irda/nsc-ircc.h
--- v2.3.42/linux/include/net/irda/nsc-ircc.h	Tue Feb  1 01:35:44 2000
+++ linux/include/net/irda/nsc-ircc.h	Tue Feb  8 11:32:19 2000
@@ -31,6 +31,7 @@
 #include <linux/time.h>
 
 #include <linux/spinlock.h>
+#include <linux/pm.h>
 #include <asm/io.h>
 
 /* DMA modes needed */
@@ -253,6 +254,8 @@
 	__u32 flags;               /* Interface flags */
 	__u32 new_speed;
 	int index;                 /* Instance index */
+
+        struct pm_dev *dev;
 };
 
 static inline void switch_bank(int iobase, int bank)
diff -u --recursive --new-file v2.3.42/linux/include/net/irda/smc-ircc.h linux/include/net/irda/smc-ircc.h
--- v2.3.42/linux/include/net/irda/smc-ircc.h	Tue Feb  1 01:35:44 2000
+++ linux/include/net/irda/smc-ircc.h	Tue Feb  8 11:32:19 2000
@@ -31,6 +31,7 @@
 #define SMC_IRCC_H
 
 #include <linux/spinlock.h>
+#include <linux/pm.h>
 
 #include <net/irda/irport.h>
 
@@ -181,6 +182,8 @@
 
 	int tx_buff_offsets[10];   /* Offsets between frames in tx_buff */
 	int tx_len;                /* Number of frames in tx_buff */
+
+	struct pm_dev *pmdev;
 };
 
 #endif /* SMC_IRCC_H */
diff -u --recursive --new-file v2.3.42/linux/include/net/neighbour.h linux/include/net/neighbour.h
--- v2.3.42/linux/include/net/neighbour.h	Thu Aug 26 13:05:41 1999
+++ linux/include/net/neighbour.h	Wed Feb  9 21:34:16 2000
@@ -163,6 +163,7 @@
 	unsigned long		last_rand;
 	struct neigh_parms	*parms_list;
 	kmem_cache_t		*kmem_cachep;
+	struct tasklet_struct	gc_task;
 	struct neigh_statistics	stats;
 	struct neighbour	*hash_buckets[NEIGH_HASHMASK+1];
 	struct pneigh_entry	*phash_buckets[PNEIGH_HASHMASK+1];
diff -u --recursive --new-file v2.3.42/linux/include/net/pkt_sched.h linux/include/net/pkt_sched.h
--- v2.3.42/linux/include/net/pkt_sched.h	Tue Jan 11 22:31:45 2000
+++ linux/include/net/pkt_sched.h	Wed Feb  9 20:08:09 2000
@@ -63,19 +63,10 @@
 	int			(*dump)(struct Qdisc *, struct sk_buff *);
 };
 
-struct Qdisc_head
-{
-	struct Qdisc_head *forw;
-	struct Qdisc_head *back;
-};
-
-extern struct Qdisc_head qdisc_head;
-extern spinlock_t qdisc_runqueue_lock;
 extern rwlock_t qdisc_tree_lock;
 
 struct Qdisc
 {
-	struct Qdisc_head	h;
 	int 			(*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
 	struct sk_buff *	(*dequeue)(struct Qdisc *dev);
 	unsigned		flags;
@@ -87,11 +78,9 @@
 	u32			handle;
 	atomic_t		refcnt;
 	struct sk_buff_head	q;
-	struct net_device 		*dev;
+	struct net_device	*dev;
 
 	struct tc_stats		stats;
-	unsigned long		tx_timeo;
-	unsigned long		tx_last;
 	int			(*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
 
 	/* This field is deprecated, but it is still used by CBQ
@@ -437,60 +426,13 @@
 int tc_filter_init(void);
 int pktsched_init(void);
 
-extern void qdisc_run_queues(void);
 extern int qdisc_restart(struct net_device *dev);
 
-extern spinlock_t qdisc_runqueue_lock;
-
-/* Is it on run list? Reliable only under qdisc_runqueue_lock. */
-
-extern __inline__ int qdisc_on_runqueue(struct Qdisc *q)
-{
-	return q->h.forw != NULL;
-}
-
-/* Is run list not empty? Reliable only under qdisc_runqueue_lock. */
-
-extern __inline__ int qdisc_pending(void)
-{
-	return qdisc_head.forw != &qdisc_head;
-}
-
-/* Add qdisc to tail of run list. Called with BH, disabled on this CPU */
-
-extern __inline__ void qdisc_run(struct Qdisc *q)
-{
-	spin_lock(&qdisc_runqueue_lock);
-	if (!qdisc_on_runqueue(q) && q->dev) {
-		q->h.forw = &qdisc_head;
-		q->h.back = qdisc_head.back;
-		qdisc_head.back->forw = &q->h;
-		qdisc_head.back = &q->h;
-	}
-	spin_unlock(&qdisc_runqueue_lock);
-}
-
-extern __inline__ int __qdisc_wakeup(struct net_device *dev)
+extern __inline__ void qdisc_run(struct net_device *dev)
 {
-	int res;
-
-	while ((res = qdisc_restart(dev))<0 && !dev->tbusy)
+	while (!test_bit(LINK_STATE_XOFF, &dev->state) &&
+	       qdisc_restart(dev)<0)
 		/* NOTHING */;
-
-	return res;
-}
-
-
-/* If the device is not throttled, restart it and add to run list.
- * BH must be disabled on this CPU. Usually, it is called by timers.
- */
-
-extern __inline__ void qdisc_wakeup(struct net_device *dev)
-{
-	spin_lock(&dev->queue_lock);
-	if (dev->tbusy || __qdisc_wakeup(dev))
-		qdisc_run(dev->qdisc);
-	spin_unlock(&dev->queue_lock);
 }
 
 /* Calculate maximal size of packet seen by hard_start_xmit
diff -u --recursive --new-file v2.3.42/linux/include/net/snmp.h linux/include/net/snmp.h
--- v2.3.42/linux/include/net/snmp.h	Fri Jan 28 15:09:09 2000
+++ linux/include/net/snmp.h	Wed Feb  9 20:08:09 2000
@@ -202,7 +202,7 @@
 	unsigned long	__pad[32-26];
 };
 
-#define SNMP_INC_STATS(mib, field) ((mib)[2*smp_processor_id()+!in_interrupt()].field++)
+#define SNMP_INC_STATS(mib, field) ((mib)[2*smp_processor_id()+!in_softirq()].field++)
 #define SNMP_INC_STATS_BH(mib, field) ((mib)[2*smp_processor_id()].field++)
 #define SNMP_INC_STATS_USER(mib, field) ((mib)[2*smp_processor_id()+1].field++)
  	
diff -u --recursive --new-file v2.3.42/linux/include/net/sock.h linux/include/net/sock.h
--- v2.3.42/linux/include/net/sock.h	Fri Jan 28 15:09:09 2000
+++ linux/include/net/sock.h	Wed Feb  9 21:34:22 2000
@@ -242,6 +242,7 @@
 		__u32	lrcvtime;	/* timestamp of last received data packet*/
 		__u16	last_seg_size;	/* Size of last incoming segment */
 		__u16	rcv_mss;	/* MSS used for delayed ACK decisions */ 
+		__u32	rcv_segs;	/* Number of received segments since last ack */
 	} ack;
 
 	/* Data for direct copy to user */
@@ -325,7 +326,6 @@
         __u32	rcv_tsecr;	/* Time stamp echo reply        	*/
         __u32	ts_recent;	/* Time stamp to echo next		*/
         long	ts_recent_stamp;/* Time we stored ts_recent (for aging) */
-	__u32	last_ack_sent;	/* last ack we sent (RTTM/PAWS)		*/
 
 /*	SACKs data	*/
 	struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
@@ -934,20 +934,20 @@
  */
 extern __inline__ void sock_orphan(struct sock *sk)
 {
-	write_lock_irq(&sk->callback_lock);
+	write_lock_bh(&sk->callback_lock);
 	sk->dead = 1;
 	sk->socket = NULL;
 	sk->sleep = NULL;
-	write_unlock_irq(&sk->callback_lock);
+	write_unlock_bh(&sk->callback_lock);
 }
 
 extern __inline__ void sock_graft(struct sock *sk, struct socket *parent)
 {
-	write_lock_irq(&sk->callback_lock);
+	write_lock_bh(&sk->callback_lock);
 	sk->sleep = &parent->wait;
 	parent->sk = sk;
 	sk->socket = parent;
-	write_unlock_irq(&sk->callback_lock);
+	write_unlock_bh(&sk->callback_lock);
 }
 
 
@@ -1150,7 +1150,7 @@
 
 extern __inline__ int gfp_any(void)
 {
-	return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+	return in_softirq() ? GFP_ATOMIC : GFP_KERNEL;
 }
 
 extern __inline__ long sock_rcvtimeo(struct sock *sk, int noblock)
diff -u --recursive --new-file v2.3.42/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.3.42/linux/include/net/tcp.h	Fri Jan 28 15:09:09 2000
+++ linux/include/net/tcp.h	Wed Feb  9 21:34:31 2000
@@ -20,6 +20,8 @@
 
 #define TCP_DEBUG 1
 #undef  TCP_FORMAL_WINDOW
+#define TCP_MORE_COARSE_ACKS
+#undef  TCP_LESS_COARSE_ACKS
 
 #include <linux/config.h>
 #include <linux/tcp.h>
@@ -287,10 +289,10 @@
 				  * TIME-WAIT timer.
 				  */
 
-#define TCP_DELACK_MAX	(HZ/2)	/* maximal time to delay before sending an ACK */
+#define TCP_DELACK_MAX	(HZ/5)	/* maximal time to delay before sending an ACK */
 #define TCP_DELACK_MIN	(2)	/* minimal time to delay before sending an ACK,
-				 * 2 scheduler ticks, not depending on HZ */
-#define TCP_ATO_MAX	((TCP_DELACK_MAX*4)/5) /* ATO producing TCP_DELACK_MAX */
+				 * 2 scheduler ticks, not depending on HZ. */
+#define TCP_ATO_MAX	(HZ/2)	/* Clamp ATO estimator at his value. */
 #define TCP_ATO_MIN	2
 #define TCP_RTO_MAX	(120*HZ)
 #define TCP_RTO_MIN	(HZ/5)
@@ -335,12 +337,14 @@
    so that we select tick to get range about 4 seconds.
  */
 
-#if HZ == 100
-#define TCP_TW_RECYCLE_TICK (7+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#if HZ == 20
+# define TCP_TW_RECYCLE_TICK (5+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ == 100
+# define TCP_TW_RECYCLE_TICK (7+2-TCP_TW_RECYCLE_SLOTS_LOG)
 #elif HZ == 1024
-#define TCP_TW_RECYCLE_TICK (10+2-TCP_TW_RECYCLE_SLOTS_LOG)
+# define TCP_TW_RECYCLE_TICK (10+2-TCP_TW_RECYCLE_SLOTS_LOG)
 #else
-#error HZ != 100 && HZ != 1024.
+# error HZ != 20 &&  HZ != 100 && HZ != 1024.
 #endif
 
 /*
@@ -594,11 +598,8 @@
 
 static __inline__ void tcp_dec_quickack_mode(struct tcp_opt *tp)
 {
-	if (tp->ack.quick && --tp->ack.quick == 0 && !tp->ack.pingpong) {
-		/* Leaving quickack mode we deflate ATO to give peer
-		 * a time to adapt to new worse(!) RTO. It is not required
-		 * in pingpong mode, when ACKs were delayed in any case.
-		 */
+	if (tp->ack.quick && --tp->ack.quick == 0) {
+		/* Leaving quickack mode we deflate ATO. */
 		tp->ack.ato = TCP_ATO_MIN;
 	}
 }
@@ -825,12 +826,13 @@
 		 * Don't update rcv_wup/rcv_wnd here or else
 		 * we will not be able to advertise a zero
 		 * window in time.  --DaveM
+		 *
+		 * Relax Will Robinson.
 		 */
 		new_win = cur_win;
-	} else {
-		tp->rcv_wnd = new_win;
-		tp->rcv_wup = tp->rcv_nxt;
 	}
+	tp->rcv_wnd = new_win;
+	tp->rcv_wup = tp->rcv_nxt;
 
 	/* RFC1323 scaling applied */
 	new_win >>= tp->rcv_wscale;
@@ -1186,7 +1188,7 @@
 		/* fall through */
 	default:
 		if (oldstate==TCP_ESTABLISHED)
-			tcp_statistics[smp_processor_id()*2+!in_interrupt()].TcpCurrEstab--;
+			tcp_statistics[smp_processor_id()*2+!in_softirq()].TcpCurrEstab--;
 	}
 
 	/* Change state AFTER socket is unhashed to avoid closed
diff -u --recursive --new-file v2.3.42/linux/include/scsi/sg.h linux/include/scsi/sg.h
--- v2.3.42/linux/include/scsi/sg.h	Sat Oct  9 11:47:50 1999
+++ linux/include/scsi/sg.h	Wed Feb  9 18:40:24 2000
@@ -3,25 +3,25 @@
 
 /*
    History:
-    Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user 
-     process control of SCSI devices. 
+    Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user
+     process control of SCSI devices.
     Development Sponsored by Killy Corp. NY NY
 Original driver (sg.h):
 *       Copyright (C) 1992 Lawrence Foard
-2.x extensions to driver:
+Version 2 and 3 extensions to driver:
 *       Copyright (C) 1998, 1999 Douglas Gilbert
 
+    Version: 3.1.10 (20000123)
+    This version is for 2.3/2.4 series kernels.
 
-    Version: 2.3.35 (990708)
-    This version for 2.3 series kernels. It only differs from sg version
-    2.1.35 used in the 2.2 series kernels by changes to wait_queue. This
-    in an internal kernel interface and should not effect users.
-        D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au)
-
-    Changes since 2.1.34 (990603)
+    Changes since 2.1.34 (990603) and 2.3.35 (990708)
+	- add new interface structure: sg_io_hdr_t
+	  - supports larger sense buffer, DMA residual count + direct IO
+	- add SG_IO ioctl (combines function of write() + read() )
+	- remove SG_SET_MERGE_FD, UNDERRUN_FLAG + _GET_ ioctls + logic
+	- add proc_fs support in /proc/scsi/sg/ directory
         - add queuing info into struct sg_scsi_id
-        - block negative timeout values
-        - add back write() wait on previous read() when no cmd queuing
+	- def_reserved_size can be given at driver or module load time
     Changes since 2.1.33 (990521)
         - implement SG_SET_RESERVED_SIZE and associated memory re-org.
         - add SG_NEXT_CMD_LEN to override SCSI command lengths
@@ -34,117 +34,135 @@
         - clean up logging of pointers to use %p (for 64 bit architectures)
         - rework usage of get_user/copy_to_user family of kernel calls
         - "disown" scsi_command blocks before releasing them
-    Changes since 2.1.30 (990320)
-        - memory tweaks: change flags on kmalloc (GFP_KERNEL to GFP_ATOMIC)
-        -                increase max allowable mid-level pool usage
-
-
-    New features and changes:
-        - per file descriptor (fd) write-read sequencing and command queues.
-        - command queuing supported (SG_MAX_QUEUE is maximum per fd).
-        - scatter-gather supported (allowing potentially megabyte transfers).
-        - the SCSI target, host and driver status are returned
-          in unused fields of sg_header (maintaining its original size).
-        - asynchronous notification support added (SIGPOLL, SIGIO) for
-          read()s (write()s should never block).
-        - pack_id logic added so read() can wait for a specific pack_id. 
-        - uses memory > ISA_DMA_THRESHOLD if adapter allows it (e.g. a
-          pci scsi adapter).
-        - this driver no longer uses a single SG_BIG_BUFF sized buffer
-          obtained at driver/module init time. Rather it tries to obtain a 
-          SG_DEF_RESERVED_SIZE buffer when a fd is open()ed and frees it
-          at the corresponding release() (ie per fd). Actually the "buffer"
-          may be a collection of buffers if scatter-gather is being used.
-        - add SG_SET_RESERVED_SIZE ioctl allowing the user to request a
-          large buffer for duration of current file descriptor's lifetime.
-        - SG_GET_RESERVED_SIZE ioctl can be used to find out how much
-          actually has been reserved.
-        - add SG_NEXT_CMD_LEN ioctl to override SCSI command length on
-          the next write() to this file descriptor.
-        - SG_GET_RESERVED_SIZE's presence as a symbol can be used for
-          compile time identification of the version 2 sg driver.
-          However, it is recommended that run time identification based on
-          calling the ioctl of the same name is a more flexible and
-          safer approach.
-        - adds several ioctl calls, see ioctl section below.
- 
- Good documentation on the original "sg" device interface and usage can be
- found in the Linux HOWTO document: "SCSI Programming HOWTO" (version 0.5)
- by Heiko Eissfeldt; last updated 7 May 1996. Here is a quick summary of
- sg basics:
- An SG device is accessed by writing SCSI commands plus any associated 
- outgoing data to it; the resulting status codes and any incoming data
- are then obtained by a read call. The device can be opened O_NONBLOCK
- (non-blocking) and poll() used to monitor its progress. The device may be
- opened O_EXCL which excludes other "sg" users from this device (but not 
- "sd", "st" or "sr" users). The buffer given to the write() call is made
- up as follows:
-        - struct sg_header image (see below)
-        - scsi command (6, 10 or 12 bytes long)
-        - data to be written to the device (if any)
-
- The buffer received from the corresponding read() call contains:
-        - struct sg_header image (check results + sense_buffer)
-        - data read back from device (if any)
-
- The given SCSI command has its LUN field overwritten internally by the
- value associated with the device that has been opened.
-
- This device currently uses "indirect IO" in the sense that data is
- DMAed into kernel buffers from the hardware and afterwards is
- transferred into the user space (or vice versa if you are writing).
- Transfer speeds or up to 20 to 30MBytes/sec have been measured using
- indirect IO. For faster throughputs "direct IO" which cuts out the
- double handling of data is required. This will also need a new interface.
-
- Grabbing memory for those kernel buffers used in this driver for DMA may
- cause the dreaded ENOMEM error. This error seems to be more prevalent 
- under early 2.2.x kernels than under the 2.0.x kernel series. For a given 
- (large) transfer the memory obtained by this driver must be contiguous or
- scatter-gather must be used (if supported by the adapter). [Furthermore, 
- ISA SCSI adapters can only use memory below the 16MB level on a i386.]
-
- When a "sg" device is open()ed O_RDWR then this driver will attempt to
- reserve a buffer of SG_DEF_RESERVED_SIZE that will be used by subsequent
- write()s on this file descriptor as long as:
-    -  it is not already in use (eg when command queuing is in use)
-    -  the write() does not call for a buffer size larger than the
-       reserved size.
- In these cases the write() will attempt to find the memory it needs for
- DMA buffers dynamically and in the worst case will fail with ENOMEM.
- The amount of memory actually reserved depends on various dynamic factors
- and can be checked with the SG_GET_RESERVED_SIZE ioctl(). [In a very
- tight memory situation it may yield 0!] The size of the reserved buffer
- can be changed with the SG_SET_RESERVED_SIZE ioctl(). It should be
- followed with a call to the SG_GET_RESERVED_SIZE ioctl() to find out how
- much was actually reserved.
 
- More documentation plus test and utility programs can be found at 
- http://www.torque.net/sg
+Map of SG verions to the Linux kernels in which they appear:
+       ----------        ----------------------------------
+       original          all kernels < 2.2.6
+       2.1.31            2.2.6 and 2.2.7
+       2.1.32            2.2.8 and 2.2.9
+       2.1.34            2.2.10 to 2.2.13
+       2.1.36            2.2.14 
+       2.3.35            2.3.x development series kernels (starting 2.3.20)
+       3.0.x             optional version 3 sg driver for 2.2 series
+       3.1.x             candidate version 3 sg driver for 2.3 series
+
+Major new features in SG 3.x driver (cf SG 2.x drivers)
+	- SG_IO ioctl() combines function if write() and read()
+	- new interface (sg_io_hdr_t) but still supports old interface
+	- scatter/gather in user space and direct IO supported
+
+Major features in SG 2.x driver (cf original SG driver)
+	- per file descriptor (fd) write-read sequencing
+	- command queuing supported
+	- scatter-gather supported at kernel level allowing potentially
+	  large transfers
+	- more SCSI status information returned
+	- asynchronous notification support added (SIGPOLL, SIGIO)
+	- read() can fetch by given pack_id
+	- uses kernel memory as appropriate for SCSI adapter being used
+	- single SG_BIG_BUFF replaced by per file descriptor "reserve
+	  buffer" whose size can be manipulated by ioctls()
+
+ The term "indirect IO" refers a method by which data is DMAed into kernel
+ buffers from the hardware and afterwards is transferred into the user
+ space (or vice versa if you are writing). Transfer speeds of up to 20 to
+ 30MBytes/sec have been measured using indirect IO. For faster throughputs
+ "direct IO" which cuts out the double handling of data is required.
+ Direct IO is supported by the SG 3.x drivers on 2.3 series Linux kernels
+ (or later) and requires the use of the new interface.
+
+ Requests for direct IO with the new interface will automatically fall back
+ to indirect IO mode if they cannot be fulfilled. An example of such a case
+ is an ISA SCSI adapter which is only capable of DMAing to the lower 16MB of
+ memory due to the architecture of ISA. The 'info' field in the new
+ interface indicates whether a direct or indirect data transfer took place.
+
+ Obtaining memory for the kernel buffers used in indirect IO is done by
+ first checking if the "reserved buffer" for the current file descriptor
+ is available and large enough. If these conditions are _not_ met then
+ kernel memory is obtained on a per SCSI command basis. This corresponds
+ to a write(), read() sequence or a SG_IO ioctl() call. Further, the
+ kernel memory that is suitable for DMA may be constrained by the
+ architecture of the SCSI adapter (e.g. ISA adapters).
+
+ Documentation
+ =============
+ A web site for SG device drivers can be found at:
+	http://www.torque.net/sg  [alternatively check the MAINTAINERS file]
+ The main documents are still based on 2.x versions:
+	http://www.torque.net/sg/p/scsi-generic.txt
+	http://www.torque.net/sg/p/scsi-generic_long.txt
+ The first document can also be found in the kernel source tree, probably at:
+	/usr/src/linux/Documentation/scsi-generic.txt .
+ Documentation on the changes and additions in 3.x version of the sg driver
+ can be found at: http://www.torque.net/sg/p/scsi-generic_v3.txt
+ Utility and test programs are also available at that web site.
 */
 
-#define SG_MAX_SENSE 16   /* too little, unlikely to change in 2.2.x */
+/* New interface introduced in the 3.x SG drivers follows */
 
-struct sg_header
+typedef struct sg_iovec /* same structure as used by readv() Linux system */
+{                       /* call. It defines one scatter-gather element. */
+    void * iov_base;            /* Starting address  */
+    size_t iov_len;             /* Length in bytes  */
+} sg_iovec_t;
+
+
+typedef struct sg_io_hdr
 {
-    int pack_len;    /* [o] reply_len (ie useless), ignored as input */
-    int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
-    int pack_id;     /* [io] id number of packet (use ints >= 0) */
-    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
-    unsigned int twelve_byte:1; 
-        /* [i] Force 12 byte command length for group 6 & 7 commands  */
-    unsigned int target_status:5;   /* [o] scsi status from target */
-    unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
-    unsigned int driver_status:8;   /* [o] driver status+suggestion */
-    unsigned int other_flags:10;    /* unused */
-    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
-           when target_status is CHECK_CONDITION or 
-           when target_status is COMMAND_TERMINATED or
-           when (driver_status & DRIVER_SENSE) is true. */
-};      /* This structure is 36 bytes long on i386 */
+    char interface_id;          /* [i] 'S' for SCSI generic (required) */
+    unsigned char cmd_len;      /* [i] SCSI command length ( <= 16 bytes) */
+    unsigned char iovec_count;  /* [i] 0 implies no scatter gather */
+    unsigned char mx_sb_len;    /* [i] max length to write to sbp */
+    int dxfer_direction;        /* [i] data transfer direction  */
+    unsigned int dxfer_len;     /* [i] byte count of data transfer */
+    void * dxferp;              /* [i], [*io] points to data transfer memory
+					      or scatter gather list */
+    unsigned char * cmdp;       /* [i], [*i] points to command to perform */
+    unsigned char * sbp;        /* [i], [*o] points to sense_buffer memory */
+    unsigned int timeout;       /* [i] MAX_UINT->no timeout (unit: millisec) */
+    unsigned int flags;         /* [i] 0 -> default, see SG_FLAG... */
+    int pack_id;                /* [i->o] unused internally (normally) */
+    void * usr_ptr;             /* [i->o] unused internally */
+    unsigned char status;       /* [o] scsi status */
+    unsigned char masked_status;/* [o] shifted, masked scsi status */
+    unsigned char msg_status;   /* [o] messaging level data (optional) */
+    unsigned char sb_len_wr;    /* [o] byte count actually written to sbp */
+    unsigned short host_status; /* [o] errors from host adapter */
+    unsigned short driver_status;/* [o] errors from software driver */
+    int resid;                  /* [o] dxfer_len - actual_transferred */
+    unsigned int duration;      /* [o] time taken by cmd (unit: millisec) */
+    unsigned int info;          /* [o] auxiliary information */
+} sg_io_hdr_t;  /* 60 bytes long (on i386) */
+
+/* Use negative values to flag difference from original sg_header structure */
+#define SG_DXFER_NONE -1        /* e.g. a SCSI Test Unit Ready command */
+#define SG_DXFER_TO_DEV -2      /* e.g. a SCSI WRITE command */
+#define SG_DXFER_FROM_DEV -3    /* e.g. a SCSI READ command */
+#define SG_DXFER_TO_FROM_DEV -4 /* treated like SG_DXFER_FROM_DEV with the
+				   additional property than during indirect
+				   IO the user buffer is copied into the
+				   kernel buffers before the transfer */
+
+/* following flag values can be "or"-ed together */
+#define SG_FLAG_DIRECT_IO 1     /* default is indirect IO */
+#define SG_FLAG_LUN_INHIBIT 2   /* default is to put device's lun into */
+				/* the 2nd byte of SCSI command */
+#define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */
+				/* user space (debug indirect IO) */
+
+/* following 'info' values are "or"-ed together */
+#define SG_INFO_OK_MASK 0x1
+#define SG_INFO_OK 0x0          /* no sense, host nor driver "noise" */
+#define SG_INFO_CHECK 0x1       /* something abnormal happened */
+
+#define SG_INFO_DIRECT_IO_MASK 0x6
+#define SG_INFO_INDIRECT_IO 0x0 /* data xfer via kernel buffers (or no xfer) */
+#define SG_INFO_DIRECT_IO 0x2   /* direct IO requested and performed */
+#define SG_INFO_MIXED_IO 0x4    /* part direct, part indirect IO */
 
 
-typedef struct sg_scsi_id {
+typedef struct sg_scsi_id { /* used by SG_GET_SCSI_ID ioctl() */
     int host_no;        /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */
     int channel;
     int scsi_id;        /* scsi id of target device */
@@ -152,25 +170,38 @@
     int scsi_type;      /* TYPE_... defined in scsi/scsi.h */
     short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
     short d_queue_depth;/* device (or adapter) maximum queue length */
-    int unused1;        /* probably find a good use, set 0 for now */
-    int unused2;        /* ditto */
-} Sg_scsi_id;
+    int unused[2];      /* probably find a good use, set 0 for now */
+} sg_scsi_id_t; /* 32 bytes long on i386 */
 
-/* IOCTLs: ( _GET_s yield result via 'int *' 3rd argument unless 
-             otherwise indicated) */
-#define SG_SET_TIMEOUT 0x2201  /* unit: jiffies (10ms on i386) */
-#define SG_GET_TIMEOUT 0x2202  /* yield timeout as _return_ value */
+typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
+    char req_state;     /* 0 -> not used, 1 -> written, 2 -> ready to read */
+    char orphan;        /* 0 -> normal request, 1 -> from interruped SG_IO */
+    char sg_io_owned;   /* 0 -> complete with read(), 1 -> owned by SG_IO */
+    char problem;       /* 0 -> no problem detected, 1 -> error to report */
+    int pack_id;        /* pack_id associated with request */
+    void * usr_ptr;     /* user provided pointer (in new interface) */
+    unsigned int duration; /* millisecs elapsed since written (req_state==1)
+			      or request duration (req_state==2) */
+    int unused;
+} sg_req_info_t; /* 20 bytes long on i386 */
+
+
+/* IOCTLs: Those ioctls that are relevant to the SG 3.x drivers follow.
+ [Those that only apply to the SG 2.x drivers are at the end of the file.]
+ (_GET_s yield result via 'int *' 3rd argument unless otherwise indicated) */
 
 #define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */
 
 /* Used to configure SCSI command transformation layer for ATAPI devices */
-#define SG_SET_TRANSFORM 0x2204
+/* Only supported by the ide-scsi driver */
+#define SG_SET_TRANSFORM 0x2204 /* N.B. 3rd arg is not pointer but value: */
+		      /* 3rd arg = 0 to disable transform, 1 to enable it */
 #define SG_GET_TRANSFORM 0x2205
 
 #define SG_SET_RESERVED_SIZE 0x2275  /* request a new reserved buffer size */
 #define SG_GET_RESERVED_SIZE 0x2272  /* actual size of reserved buffer */
 
-/* The following ioctl takes a 'Sg_scsi_id *' object as its 3rd argument. */
+/* The following ioctl has a 'sg_scsi_id_t *' object as its 3rd argument. */
 #define SG_GET_SCSI_ID 0x2276   /* Yields fd's bus, chan, dev, lun + type */
 /* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */
 
@@ -179,66 +210,111 @@
 #define SG_GET_LOW_DMA 0x227a   /* 0-> use all ram for dma; 1-> low dma ram */
 
 /* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which
-   will attempt to read that pack_id or block (or return EAGAIN). If 
-   pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0
-   then pack_id ignored by read() and oldest readable fetched. */ 
+   tries to fetch a packet with a matching pack_id, waits, or returns EAGAIN.
+   If pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0
+   then pack_id ignored by read() and oldest readable fetched. */
 #define SG_SET_FORCE_PACK_ID 0x227b
 #define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */
 
 #define SG_GET_NUM_WAITING 0x227d /* Number of commands awaiting read() */
 
-/* Turn on error sense trace (1..8), dump this device to log/console (9)
-   or dump all sg device states ( >9 ) to log/console */
-#define SG_SET_DEBUG 0x227e    /* 0 -> turn off debug */
-
 /* Yields max scatter gather tablesize allowed by current host adapter */
 #define SG_GET_SG_TABLESIZE 0x227F  /* 0 implies can't do scatter gather */
 
-/* Control whether sequencing per file descriptor or per device */
-#define SG_GET_MERGE_FD 0x2274   /* 0-> per fd, 1-> per device */
-#define SG_SET_MERGE_FD 0x2273   /* Attempt to change sequencing state,
-  if more than current fd open on device, will fail with EBUSY */
-
-/* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q) */
-#define SG_GET_COMMAND_Q 0x2270   /* Yields 0 (queuing off) or 1 (on) */
-#define SG_SET_COMMAND_Q 0x2271   /* Change queuing state with 0 or 1 */
-
-/* Get/set whether DMA underrun will cause an error (DID_ERROR). This only
-   currently applies to the [much-used] aic7xxx driver. */
-#define SG_GET_UNDERRUN_FLAG 0x2280 /* Yields 0 (don't flag) or 1 (flag) */
-#define SG_SET_UNDERRUN_FLAG 0x2281 /* Change flag underrun state */
-
 #define SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */
-#define SG_NEXT_CMD_LEN 0x2283  /* override SCSI command length with given
-                   number on the next write() on this file descriptor */
 
 /* Returns -EBUSY if occupied else takes as input: 0 -> do nothing,
    1 -> device reset or  2 -> bus reset (may not be activated yet) */
 #define SG_SCSI_RESET 0x2284
 
+/* synchronous SCSI command ioctl, (only in version 3 interface) */
+#define SG_IO 0x2285   /* similar effect as write() followed by read() */
+
+#define SG_GET_REQUEST_TABLE 0x2286   /* yields table of active requests */
+
+/* How to treat EINTR during SG_IO ioctl(), only in SG 3.x series */
+#define SG_SET_KEEP_ORPHAN 0x2287 /* 1 -> hold for read(), 0 -> drop (def) */
+#define SG_GET_KEEP_ORPHAN 0x2288
+
 
 #define SG_SCATTER_SZ (8 * 4096)  /* PAGE_SIZE not available to user */
 /* Largest size (in bytes) a single scatter-gather list element can have.
-   The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on 
+   The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on
    i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
    by adapter then this value is the largest data block that can be
    read/written by a single scsi command. The user can find the value of
    PAGE_SIZE by calling getpagesize() defined in unistd.h . */
 
-#define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */
 #define SG_DEFAULT_RETRIES 1
 
 /* Defaults, commented if they differ from original sg driver */
-#define SG_DEF_COMMAND_Q 0
-#define SG_DEF_MERGE_FD 0       /* was 1 -> per device sequencing */
 #define SG_DEF_FORCE_LOW_DMA 0  /* was 1 -> memory below 16MB on i386 */
 #define SG_DEF_FORCE_PACK_ID 0
-#define SG_DEF_UNDERRUN_FLAG 0
-#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ
+#define SG_DEF_KEEP_ORPHAN 0
+#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */
 
 /* maximum outstanding requests, write() yields EDOM if exceeded */
 #define SG_MAX_QUEUE 16
 
 #define SG_BIG_BUFF SG_DEF_RESERVED_SIZE    /* for backward compatibility */
+
+/* Alternate style type names, "..._t" variants preferred */
+typedef struct sg_io_hdr Sg_io_hdr;
+typedef struct sg_io_vec Sg_io_vec;
+typedef struct sg_scsi_id Sg_scsi_id;
+typedef struct sg_req_info Sg_req_info;
+
+
+/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
+/*   The older SG interface based on the 'sg_header' structure follows.   */
+/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
+
+#define SG_MAX_SENSE 16   /* this only applies to the sg_header interface */
+
+struct sg_header
+{
+    int pack_len;    /* [o] reply_len (ie useless), ignored as input */
+    int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
+    int pack_id;     /* [io] id number of packet (use ints >= 0) */
+    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
+    unsigned int twelve_byte:1;
+	/* [i] Force 12 byte command length for group 6 & 7 commands  */
+    unsigned int target_status:5;   /* [o] scsi status from target */
+    unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
+    unsigned int driver_status:8;   /* [o] driver status+suggestion */
+    unsigned int other_flags:10;    /* unused */
+    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
+	   when target_status is CHECK_CONDITION or
+	   when target_status is COMMAND_TERMINATED or
+	   when (driver_status & DRIVER_SENSE) is true. */
+};      /* This structure is 36 bytes long on i386 */
+
+
+/* IOCTLs: The following are not required (or ignored) when the sg_io_hdr_t
+	   interface is used. That are kept for backward compatibility with
+	   the original and version 2 drivers. */
+
+#define SG_SET_TIMEOUT 0x2201  /* unit: jiffies (10ms on i386) */
+#define SG_GET_TIMEOUT 0x2202  /* yield timeout as _return_ value */
+
+/* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q.
+   Each time a sg_io_hdr_t object is seen on this file descriptor, this
+   command queuing flag is set on (overriding the previous setting). */
+#define SG_GET_COMMAND_Q 0x2270   /* Yields 0 (queuing off) or 1 (on) */
+#define SG_SET_COMMAND_Q 0x2271   /* Change queuing state with 0 or 1 */
+
+/* Turn on/off error sense trace (1 and 0 respectively, default is off).
+   Try using: "# cat /proc/scsi/sg/debug" instead in the v3 driver */
+#define SG_SET_DEBUG 0x227e    /* 0 -> turn off debug */
+
+#define SG_NEXT_CMD_LEN 0x2283  /* override SCSI command length with given
+		   number on the next write() on this file descriptor */
+
+
+/* Defaults, commented if they differ from original sg driver */
+#define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */
+#define SG_DEF_COMMAND_Q 0     /* command queuing is always on when
+				  the new interface is used */
+#define SG_DEF_UNDERRUN_FLAG 0
 
 #endif
diff -u --recursive --new-file v2.3.42/linux/include/video/macmodes.h linux/include/video/macmodes.h
--- v2.3.42/linux/include/video/macmodes.h	Mon Oct 11 15:38:15 1999
+++ linux/include/video/macmodes.h	Wed Feb  9 19:43:57 2000
@@ -42,6 +42,7 @@
 #define VMODE_CHOOSE		99
 
 #define CMODE_NVRAM		-1
+#define CMODE_CHOOSE		-2
 #define CMODE_8			0	/* 8 bits/pixel */
 #define CMODE_16		1	/* 16 (actually 15) bits/pixel */
 #define CMODE_32		2	/* 32 (actually 24) bits/pixel */
diff -u --recursive --new-file v2.3.42/linux/init/main.c linux/init/main.c
--- v2.3.42/linux/init/main.c	Fri Jan 21 18:19:17 2000
+++ linux/init/main.c	Wed Feb  9 20:08:09 2000
@@ -20,6 +20,7 @@
 #include <linux/utsname.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/raid/md.h>
 #include <linux/smp_lock.h>
 #include <linux/blk.h>
 #include <linux/hdreg.h>
@@ -45,10 +46,6 @@
 #  include <asm/mtrr.h>
 #endif
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
-
 #ifdef CONFIG_MAC
 extern void nubus_init(void);
 #endif
@@ -114,6 +111,7 @@
 #define MAX_INIT_ENVS 8
 
 extern void time_init(void);
+extern void softirq_init(void);
 
 int rows, cols;
 
@@ -472,6 +470,7 @@
 	init_IRQ();
 	sched_init();
 	time_init();
+	softirq_init();
 	parse_options(command_line);
 
 	/*
@@ -685,6 +684,9 @@
 			while (pid != wait(&i));
 		if (MAJOR(real_root_dev) != RAMDISK_MAJOR
 		     || MINOR(real_root_dev) != 0) {
+#ifdef CONFIG_BLK_DEV_MD
+			autodetect_raid();
+#endif
 			error = change_root(real_root_dev,"/initrd");
 			if (error)
 				printk(KERN_ERR "Change root to /initrd: "
diff -u --recursive --new-file v2.3.42/linux/ipc/util.h linux/ipc/util.h
--- v2.3.42/linux/ipc/util.h	Tue Jan 11 22:31:45 2000
+++ linux/ipc/util.h	Tue Feb  8 18:23:13 2000
@@ -98,4 +98,5 @@
 
 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
+
 int ipc_parse_version (int *cmd);
diff -u --recursive --new-file v2.3.42/linux/kernel/Makefile linux/kernel/Makefile
--- v2.3.42/linux/kernel/Makefile	Fri Jan 21 18:19:17 2000
+++ linux/kernel/Makefile	Thu Feb 10 12:35:19 2000
@@ -29,6 +29,14 @@
 OX_OBJS  += ksyms.o
 endif
 
+ifdef CONFIG_ACPI
+OX_OBJS += pm.o
+else
+  ifdef CONFIG_APM
+  OX_OBJS += pm.o
+  endif
+endif
+
 CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.42/linux/kernel/exec_domain.c linux/kernel/exec_domain.c
--- v2.3.42/linux/kernel/exec_domain.c	Mon Nov  1 13:56:27 1999
+++ linux/kernel/exec_domain.c	Thu Feb 10 12:41:10 2000
@@ -103,12 +103,11 @@
 	unsigned long old_personality;
 	int ret;
 
-	lock_kernel();
-	ret = current->personality;
 	if (personality == 0xffffffff)
-		goto out;
+		return current->personality;
 
 	ret = -EINVAL;
+	lock_kernel();
 	it = lookup_exec_domain(personality);
 	if (!it)
 		goto out;
diff -u --recursive --new-file v2.3.42/linux/kernel/exit.c linux/kernel/exit.c
--- v2.3.42/linux/kernel/exit.c	Tue Feb  1 01:35:44 2000
+++ linux/kernel/exit.c	Wed Feb  9 20:08:09 2000
@@ -247,6 +247,7 @@
 	current->mm = NULL;
 	/* active_mm is still 'mm' */
 	atomic_inc(&mm->mm_count);
+	enter_lazy_tlb(mm, current, smp_processor_id());
 	return mm;
 }
 
@@ -275,6 +276,7 @@
 		mm_release();
 		if (mm != tsk->active_mm) BUG();
 		tsk->mm = NULL;
+		enter_lazy_tlb(mm, current, smp_processor_id());
 		mmput(mm);
 	}
 }
@@ -393,9 +395,7 @@
 	if (!tsk->pid)
 		panic("Attempted to kill the idle task!");
 	tsk->flags |= PF_EXITING;
-	start_bh_atomic();
-	del_timer(&tsk->real_timer);
-	end_bh_atomic();
+	del_timer_sync(&tsk->real_timer);
 
 	lock_kernel();
 fake_volatile:
diff -u --recursive --new-file v2.3.42/linux/kernel/itimer.c linux/kernel/itimer.c
--- v2.3.42/linux/kernel/itimer.c	Tue Aug 31 17:29:15 1999
+++ linux/kernel/itimer.c	Wed Feb  9 20:08:09 2000
@@ -48,7 +48,9 @@
 	case ITIMER_REAL:
 		interval = current->it_real_incr;
 		val = 0;
-		start_bh_atomic();
+		/* 
+		 * FIXME! This needs to be atomic, in case the kernel timer happens!
+		 */
 		if (timer_pending(&current->real_timer)) {
 			val = current->real_timer.expires - jiffies;
 
@@ -56,7 +58,6 @@
 			if ((long) val <= 0)
 				val = 1;
 		}
-		end_bh_atomic();
 		break;
 	case ITIMER_VIRTUAL:
 		val = current->it_virt_value;
@@ -102,6 +103,7 @@
 		p->real_timer.expires = jiffies + interval;
 		add_timer(&p->real_timer);
 	}
+	timer_exit(&p->real_timer);
 }
 
 int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
@@ -115,9 +117,7 @@
 		return k;
 	switch (which) {
 		case ITIMER_REAL:
-			start_bh_atomic();
-			del_timer(&current->real_timer);
-			end_bh_atomic();
+			del_timer_sync(&current->real_timer);
 			current->it_real_value = j;
 			current->it_real_incr = i;
 			if (!j)
diff -u --recursive --new-file v2.3.42/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.42/linux/kernel/ksyms.c	Fri Jan 28 15:09:09 2000
+++ linux/kernel/ksyms.c	Thu Feb 10 12:17:00 2000
@@ -151,6 +151,7 @@
 EXPORT_SYMBOL(d_alloc);
 EXPORT_SYMBOL(d_lookup);
 EXPORT_SYMBOL(d_path);
+EXPORT_SYMBOL(mark_buffer_dirty);
 EXPORT_SYMBOL(__mark_buffer_dirty);
 EXPORT_SYMBOL(__mark_inode_dirty);
 EXPORT_SYMBOL(free_kiovec);
@@ -163,7 +164,7 @@
 EXPORT_SYMBOL(put_filp);
 EXPORT_SYMBOL(files_lock);
 EXPORT_SYMBOL(check_disk_change);
-EXPORT_SYMBOL(invalidate_buffers);
+EXPORT_SYMBOL(__invalidate_buffers);
 EXPORT_SYMBOL(invalidate_inodes);
 EXPORT_SYMBOL(invalidate_inode_pages);
 EXPORT_SYMBOL(truncate_inode_pages);
@@ -183,11 +184,12 @@
 EXPORT_SYMBOL(ll_rw_block);
 EXPORT_SYMBOL(__wait_on_buffer);
 EXPORT_SYMBOL(___wait_on_page);
-EXPORT_SYMBOL(block_read_full_page);
 EXPORT_SYMBOL(block_write_full_page);
-EXPORT_SYMBOL(block_write_partial_page);
-EXPORT_SYMBOL(block_write_cont_page);
-EXPORT_SYMBOL(block_write_zero_range);
+EXPORT_SYMBOL(block_read_full_page);
+EXPORT_SYMBOL(block_prepare_write);
+EXPORT_SYMBOL(cont_prepare_write);
+EXPORT_SYMBOL(generic_commit_write);
+EXPORT_SYMBOL(generic_block_bmap);
 EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(do_generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
@@ -222,6 +224,7 @@
 EXPORT_SYMBOL(vfs_follow_link);
 EXPORT_SYMBOL(page_readlink);
 EXPORT_SYMBOL(page_follow_link);
+EXPORT_SYMBOL(page_symlink_inode_operations);
 EXPORT_SYMBOL(block_symlink);
 
 /* for stackable file systems (lofs, wrapfs, etc.) */
@@ -263,8 +266,6 @@
 EXPORT_SYMBOL(gendisk_head);
 EXPORT_SYMBOL(grok_partitions);
 EXPORT_SYMBOL(register_disk);
-EXPORT_SYMBOL(unplug_device);
-EXPORT_SYMBOL(make_request);
 EXPORT_SYMBOL(tq_disk);
 EXPORT_SYMBOL(init_buffer);
 EXPORT_SYMBOL(refile_buffer);
@@ -317,12 +318,11 @@
 EXPORT_SYMBOL(free_irq);
 EXPORT_SYMBOL(probe_irq_on);
 EXPORT_SYMBOL(probe_irq_off);
-EXPORT_SYMBOL(bh_active);
-EXPORT_SYMBOL(bh_mask);
-EXPORT_SYMBOL(bh_mask_count);
-EXPORT_SYMBOL(bh_base);
 EXPORT_SYMBOL(add_timer);
 EXPORT_SYMBOL(del_timer);
+#ifdef __SMP__
+EXPORT_SYMBOL(del_timer_sync);
+#endif
 EXPORT_SYMBOL(mod_timer);
 EXPORT_SYMBOL(tq_timer);
 EXPORT_SYMBOL(tq_immediate);
@@ -369,7 +369,9 @@
 EXPORT_SYMBOL(jiffies);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
+#ifndef __ia64__
 EXPORT_SYMBOL(loops_per_sec);
+#endif
 EXPORT_SYMBOL(kstat);
 
 /* misc */
@@ -380,7 +382,6 @@
 EXPORT_SYMBOL(kdevname);
 EXPORT_SYMBOL(bdevname);
 EXPORT_SYMBOL(cdevname);
-EXPORT_SYMBOL(partition_name);		/* md.c only */
 EXPORT_SYMBOL(simple_strtoul);
 EXPORT_SYMBOL(system_utsname);	/* UTS data */
 EXPORT_SYMBOL(uts_sem);		/* UTS semaphore */
@@ -458,5 +459,12 @@
 /* library functions */
 EXPORT_SYMBOL(strnicmp);
 
+/* software interrupts */
+EXPORT_SYMBOL(tasklet_hi_vec);
+EXPORT_SYMBOL(bh_task_vec);
+EXPORT_SYMBOL(init_bh);
+EXPORT_SYMBOL(remove_bh);
+
 /* init task, for moving kthread roots - ought to export a function ?? */
+
 EXPORT_SYMBOL(init_task_union);
diff -u --recursive --new-file v2.3.42/linux/kernel/panic.c linux/kernel/panic.c
--- v2.3.42/linux/kernel/panic.c	Wed Dec 29 13:13:21 1999
+++ linux/kernel/panic.c	Wed Feb  9 12:29:01 2000
@@ -41,10 +41,10 @@
 	vsprintf(buf, fmt, args);
 	va_end(args);
 	printk(KERN_EMERG "Kernel panic: %s\n",buf);
-	if (current == init_tasks[0])
-		printk(KERN_EMERG "In swapper task - not syncing\n");
-	else if (in_interrupt())
+	if (in_interrupt())
 		printk(KERN_EMERG "In interrupt handler - not syncing\n");
+	else if (!current->pid)
+		printk(KERN_EMERG "In idle task - not syncing\n");
 	else
 		sys_sync();
 
diff -u --recursive --new-file v2.3.42/linux/kernel/pm.c linux/kernel/pm.c
--- v2.3.42/linux/kernel/pm.c	Wed Dec 31 16:00:00 1969
+++ linux/kernel/pm.c	Thu Feb 10 12:35:19 2000
@@ -0,0 +1,170 @@
+/*
+ *  pm.c - Power management interface
+ *
+ *  Copyright (C) 2000 Andrew Henroid
+ *
+ *  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
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+
+int pm_active = 0;
+
+static spinlock_t pm_devs_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(pm_devs);
+
+/*
+ * Register a device with power management
+ */
+struct pm_dev *pm_register(pm_dev_t type,
+			   unsigned long id,
+			   pm_callback callback)
+{
+	struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
+	if (dev) {
+		unsigned long flags;
+
+		memset(dev, 0, sizeof(*dev));
+		dev->type = type;
+		dev->id = id;
+		dev->callback = callback;
+
+		spin_lock_irqsave(&pm_devs_lock, flags);
+		list_add(&dev->entry, &pm_devs);
+		spin_unlock_irqrestore(&pm_devs_lock, flags);
+	}
+	return dev;
+}
+
+/*
+ * Unregister a device with power management
+ */
+void pm_unregister(struct pm_dev *dev)
+{
+	if (dev) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&pm_devs_lock, flags);
+		list_del(&dev->entry);
+		spin_unlock_irqrestore(&pm_devs_lock, flags);
+
+		kfree(dev);
+	}
+}
+
+/*
+ * Unregister all devices with matching callback
+ */
+void pm_unregister_all(pm_callback callback)
+{
+	struct list_head *entry;
+
+	if (!callback)
+		return;
+
+	entry = pm_devs.next;
+	while (entry != &pm_devs) {
+		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+		entry = entry->next;
+		if (dev->callback == callback)
+			pm_unregister(dev);
+	}
+}
+
+/*
+ * Send request to an individual device
+ */
+static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+	int status = 0;
+	int next_state;
+	switch (rqst) {
+	case PM_SUSPEND:
+	case PM_RESUME:
+		next_state = (int) data;
+		if (dev->state != next_state) {
+			if (dev->callback)
+				status = (*dev->callback)(dev, rqst, data);
+			if (!status)
+				dev->state = next_state;
+		}
+		break;
+	default:
+		if (dev->callback)
+			status = (*dev->callback)(dev, rqst, data);
+		break;
+	}
+	return status;
+}
+
+/*
+ * Undo incomplete request
+ */
+static void pm_undo_request(struct pm_dev *last, pm_request_t undo, void *data)
+{
+	struct list_head *entry = last->entry.prev;
+	while (entry != &pm_devs) {
+		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+		if (dev->callback)
+			pm_send(dev, undo, data);
+		entry = entry->prev;
+	}
+}
+
+/*
+ * Send a request to all devices
+ */
+int pm_send_request(pm_request_t rqst, void *data)
+{
+	struct list_head *entry = pm_devs.next;
+	while (entry != &pm_devs) {
+		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+		if (dev->callback) {
+			int status = pm_send(dev, rqst, data);
+			if (status) {
+				/* resume devices on failed suspend request */
+				if (rqst == PM_SUSPEND)
+					pm_undo_request(dev, PM_RESUME, 0);
+				return status;
+			}
+		}
+		entry = entry->next;
+	}
+	return 0;
+}
+
+/*
+ * Find a device
+ */
+struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
+{
+	struct list_head *entry = from ? from->entry.next:pm_devs.next;
+	while (entry != &pm_devs) {
+		struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+		if (type == PM_UNKNOWN_DEV || dev->type == type)
+			return dev;
+		entry = entry->next;
+	}
+	return 0;
+}
+
+EXPORT_SYMBOL(pm_register);
+EXPORT_SYMBOL(pm_unregister);
+EXPORT_SYMBOL(pm_unregister_all);
+EXPORT_SYMBOL(pm_send_request);
+EXPORT_SYMBOL(pm_find);
diff -u --recursive --new-file v2.3.42/linux/kernel/sched.c linux/kernel/sched.c
--- v2.3.42/linux/kernel/sched.c	Fri Jan 28 15:09:09 2000
+++ linux/kernel/sched.c	Thu Feb 10 12:38:53 2000
@@ -199,30 +199,17 @@
 		goto send_now;
 
 	/*
-	 * The only heuristics - we use the tsk->avg_slice value
-	 * to detect 'frequent reschedulers'.
-	 *
-	 * If both the woken-up process and the preferred CPU is
-	 * is a frequent rescheduler, then skip the asynchronous
-	 * wakeup, the frequent rescheduler will likely chose this
-	 * task during it's next schedule():
-	 */
-	if (p->policy == SCHED_OTHER) {
-		tsk = cpu_curr(best_cpu);
-		if (p->avg_slice + tsk->avg_slice < cacheflush_time)
-			goto out_no_target;
-	}
-
-	/*
 	 * We know that the preferred CPU has a cache-affine current
 	 * process, lets try to find a new idle CPU for the woken-up
 	 * process:
 	 */
-	for (i = 0; i < smp_num_cpus; i++) {
+	for (i = smp_num_cpus - 1; i >= 0; i--) {
 		cpu = cpu_logical_map(i);
+		if (cpu == best_cpu)
+			continue;
 		tsk = cpu_curr(cpu);
 		/*
-		 * We use the first available idle CPU. This creates
+		 * We use the last available idle CPU. This creates
 		 * a priority list between idle CPUs, but this is not
 		 * a problem.
 		 */
@@ -232,26 +219,32 @@
 
 	/*
 	 * No CPU is idle, but maybe this process has enough priority
-	 * to preempt it's preferred CPU. (this is a shortcut):
+	 * to preempt it's preferred CPU.
 	 */
 	tsk = cpu_curr(best_cpu);
 	if (preemption_goodness(tsk, p, best_cpu) > 0)
 		goto send_now;
 
 	/*
-	 * We should get here rarely - or in the high CPU contention
+	 * We will get here often - or in the high CPU contention
 	 * case. No CPU is idle and this process is either lowprio or
-	 * the preferred CPU is highprio. Maybe some other CPU can/must
-	 * be preempted:
+	 * the preferred CPU is highprio. Try to preemt some other CPU
+	 * only if it's RT or if it's iteractive and the preferred
+	 * cpu won't reschedule shortly.
 	 */
-	for (i = 0; i < smp_num_cpus; i++) {
-		cpu = cpu_logical_map(i);
-		tsk = cpu_curr(cpu);
-		if (preemption_goodness(tsk, p, cpu) > 0)
-			goto send_now;
+	if ((p->avg_slice < cacheflush_time && cpu_curr(best_cpu)->avg_slice > cacheflush_time) ||
+	    p->policy != SCHED_OTHER)
+	{
+		for (i = smp_num_cpus - 1; i >= 0; i--) {
+			cpu = cpu_logical_map(i);
+			if (cpu == best_cpu)
+				continue;
+			tsk = cpu_curr(cpu);
+			if (preemption_goodness(tsk, p, cpu) > 0)
+				goto send_now;
+		}
 	}
 
-out_no_target:
 	spin_unlock_irqrestore(&runqueue_lock, flags);
 	return;
 		
@@ -397,6 +390,9 @@
 	add_timer(&timer);
 	schedule();
 	del_timer(&timer);
+	/* RED-PEN. Timer may be running now on another cpu.
+	 * Pray that process will not exit enough fastly.
+	 */
 
 	timeout = expire - jiffies;
 
@@ -460,9 +456,9 @@
 	release_kernel_lock(prev, this_cpu);
 
 	/* Do "administrative" work here while we don't hold any locks */
-	if (bh_mask & bh_active)
-		goto handle_bh;
-handle_bh_back:
+	if (softirq_state[this_cpu].active & softirq_state[this_cpu].mask)
+		goto handle_softirq;
+handle_softirq_back:
 
 	/*
 	 * 'sched_data' is protected by the fact that we can run
@@ -581,6 +577,7 @@
 			if (next->active_mm) BUG();
 			next->active_mm = oldmm;
 			atomic_inc(&oldmm->mm_count);
+			enter_lazy_tlb(oldmm, next, this_cpu);
 		} else {
 			if (next->active_mm != mm) BUG();
 			switch_mm(oldmm, mm, next, this_cpu);
@@ -620,9 +617,9 @@
 	next = prev;
 	goto still_running_back;
 
-handle_bh:
-	do_bottom_half();
-	goto handle_bh_back;
+handle_softirq:
+	do_softirq();
+	goto handle_softirq_back;
 
 handle_tq_scheduler:
 	run_task_queue(&tq_scheduler);
@@ -1148,7 +1145,6 @@
 
 void __init init_idle(void)
 {
-	cycles_t t;
 	struct schedule_data * sched_data;
 	sched_data = &aligned_data[smp_processor_id()].schedule_data;
 
@@ -1157,9 +1153,8 @@
 			smp_processor_id(), current->pid);
 		del_from_runqueue(current);
 	}
-	t = get_cycles();
 	sched_data->curr = current;
-	sched_data->last_schedule = t;
+	sched_data->last_schedule = get_cycles();
 }
 
 void __init sched_init(void)
@@ -1184,5 +1179,5 @@
 	 * The boot idle thread does lazy MMU switching as well:
 	 */
 	atomic_inc(&init_mm.mm_count);
+	enter_lazy_tlb(&init_mm, current, cpu);
 }
-
diff -u --recursive --new-file v2.3.42/linux/kernel/softirq.c linux/kernel/softirq.c
--- v2.3.42/linux/kernel/softirq.c	Sun Mar 21 07:22:00 1999
+++ linux/kernel/softirq.c	Wed Feb  9 20:08:09 2000
@@ -3,68 +3,271 @@
  *
  *	Copyright (C) 1992 Linus Torvalds
  *
- * do_bottom_half() runs at normal kernel priority: all interrupts
- * enabled.  do_bottom_half() is atomic with respect to itself: a
- * bottom_half handler need not be re-entrant.
- *
  * Fixed a disable_bh()/enable_bh() race (was causing a console lockup)
  * due bh_mask_count not atomic handling. Copyright (C) 1998  Andrea Arcangeli
+ *
+ * Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903)
  */
 
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <linux/init.h>
 
-#include <asm/io.h>
+/*
+   - No shared variables, all the data are CPU local.
+   - If a softirq needs serialization, let it serialize itself
+     by its own spinlocks.
+   - Even if softirq is serialized, only local cpu is marked for
+     execution. Hence, we get something sort of weak cpu binding.
+     Though it is still not clear, will it result in better locality
+     or will not.
+   - These softirqs are not masked by global cli() and start_bh_atomic()
+     (by clear reasons). Hence, old parts of code still using global locks
+     MUST NOT use softirqs, but insert interfacing routines acquiring
+     global locks. F.e. look at BHs implementation.
 
-/* intr_count died a painless death... -DaveM */
+   Examples:
+   - NET RX softirq. It is multithreaded and does not require
+     any global serialization.
+   - NET TX softirq. It kicks software netdevice queues, hence
+     it is logically serialized per device, but this serialization
+     is invisible to common code.
+   - Tasklets: serialized wrt itself.
+   - Bottom halves: globally serialized, grr...
+ */
 
-atomic_t bh_mask_count[32];
-unsigned long bh_active = 0;
-unsigned long bh_mask = 0;
-void (*bh_base[32])(void);
 
-/*
- * This needs to make sure that only one bottom half handler
- * is ever active at a time. We do this without locking by
- * doing an atomic increment on the intr_count, and checking
- * (nonatomically) against 1. Only if it's 1 do we schedule
- * the bottom half.
- *
- * Note that the non-atomicity of the test (as opposed to the
- * actual update) means that the test may fail, and _nobody_
- * runs the handlers if there is a race that makes multiple
- * CPU's get here at the same time. That's ok, we'll run them
- * next time around.
- */
-static inline void run_bottom_halves(void)
+struct softirq_state softirq_state[NR_CPUS];
+static struct softirq_action softirq_vec[32];
+
+asmlinkage void do_softirq()
+{
+	int cpu = smp_processor_id();
+	__u32 active, mask;
+
+	if (in_interrupt())
+		return;
+
+	local_bh_disable();
+
+	local_irq_disable();
+	mask = softirq_state[cpu].mask;
+	active = softirq_state[cpu].active & mask;
+
+	if (active) {
+		struct softirq_action *h;
+
+restart:
+		/* Reset active bitmask before enabling irqs */
+		softirq_state[cpu].active &= ~active;
+
+		local_irq_enable();
+
+		h = softirq_vec;
+		mask &= ~active;
+
+		do {
+			if (active & 1)
+				h->action(h);
+			h++;
+			active >>= 1;
+		} while (active);
+
+		local_irq_disable();
+
+		active = softirq_state[cpu].active;
+		if ((active &= mask) != 0)
+			goto retry;
+	}
+
+	local_bh_enable();
+
+	/* Leave with locally disabled hard irqs. It is critical to close
+	 * window for infinite recursion, while we help local bh count,
+	 * it protected us. Now we are defenceless.
+	 */
+	return;
+
+retry:
+	goto restart;
+}
+
+
+static spinlock_t softirq_mask_lock = SPIN_LOCK_UNLOCKED;
+
+void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&softirq_mask_lock, flags);
+	softirq_vec[nr].data = data;
+	softirq_vec[nr].action = action;
+
+	for (i=0; i<NR_CPUS; i++)
+		softirq_state[i].mask |= (1<<nr);
+	spin_unlock_irqrestore(&softirq_mask_lock, flags);
+}
+
+
+/* Tasklets */
+
+struct tasklet_head tasklet_vec[NR_CPUS] __cacheline_aligned;
+
+static void tasklet_action(struct softirq_action *a)
 {
-	unsigned long active;
-	void (**bh)(void);
+	int cpu = smp_processor_id();
+	struct tasklet_struct *list;
+
+	local_irq_disable();
+	list = tasklet_vec[cpu].list;
+	tasklet_vec[cpu].list = NULL;
+	local_irq_enable();
+
+	while (list != NULL) {
+		struct tasklet_struct *t = list;
 
-	active = get_active_bhs();
-	clear_active_bhs(active);
-	bh = bh_base;
-	do {
-		if (active & 1)
-			(*bh)();
-		bh++;
-		active >>= 1;
-	} while (active);
+		list = list->next;
+
+		if (tasklet_trylock(t)) {
+			if (atomic_read(&t->count) == 0) {
+				clear_bit(TASKLET_STATE_SCHED, &t->state);
+
+				t->func(t->data);
+				tasklet_unlock(t);
+				continue;
+			}
+			tasklet_unlock(t);
+		}
+		local_irq_disable();
+		t->next = tasklet_vec[cpu].list;
+		tasklet_vec[cpu].list = t;
+		__cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
+		local_irq_enable();
+	}
 }
 
-asmlinkage void do_bottom_half(void)
+
+
+struct tasklet_head tasklet_hi_vec[NR_CPUS] __cacheline_aligned;
+
+static void tasklet_hi_action(struct softirq_action *a)
 {
 	int cpu = smp_processor_id();
+	struct tasklet_struct *list;
+
+	local_irq_disable();
+	list = tasklet_hi_vec[cpu].list;
+	tasklet_hi_vec[cpu].list = NULL;
+	local_irq_enable();
+
+	while (list != NULL) {
+		struct tasklet_struct *t = list;
+
+		list = list->next;
+
+		if (tasklet_trylock(t)) {
+			if (atomic_read(&t->count) == 0) {
+				clear_bit(TASKLET_STATE_SCHED, &t->state);
 
-	if (softirq_trylock(cpu)) {
-		if (hardirq_trylock(cpu)) {
-			__sti();
-			run_bottom_halves();
-			__cli();
-			hardirq_endlock(cpu);
+				t->func(t->data);
+				tasklet_unlock(t);
+				continue;
+			}
+			tasklet_unlock(t);
 		}
-		softirq_endlock(cpu);
+		local_irq_disable();
+		t->next = tasklet_hi_vec[cpu].list;
+		tasklet_hi_vec[cpu].list = t;
+		__cpu_raise_softirq(cpu, HI_SOFTIRQ);
+		local_irq_enable();
+	}
+}
+
+
+void tasklet_init(struct tasklet_struct *t,
+		  void (*func)(unsigned long), unsigned long data)
+{
+	t->func = func;
+	t->data = data;
+	t->state = 0;
+	atomic_set(&t->count, 0);
+}
+
+void tasklet_kill(struct tasklet_struct *t)
+{
+	while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
+		if (in_interrupt())
+			panic("Attempt to kill tasklet from interrupt\n");
+		schedule();
 	}
+	tasklet_unlock_wait(t);
+}
+
+
+
+/* Old style BHs */
+
+static void (*bh_base[32])(void);
+struct tasklet_struct bh_task_vec[32];
+
+/* BHs are serialized by spinlock global_bh_lock.
+
+   It is still possible to make synchronize_bh() as
+   spin_unlock_wait(&global_bh_lock). This operation is not used
+   by kernel now, so that this lock is not made private only
+   due to wait_on_irq().
+
+   It can be removed only after auditing all the BHs.
+ */
+spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
+
+static void bh_action(unsigned long nr)
+{
+	int cpu = smp_processor_id();
+
+	if (!spin_trylock(&global_bh_lock))
+		goto resched;
+
+	if (!hardirq_trylock(cpu))
+		goto resched_unlock;
+
+	if (bh_base[nr])
+		bh_base[nr]();
+
+	hardirq_endlock(cpu);
+	spin_unlock(&global_bh_lock);
+	return;
+
+resched_unlock:
+	spin_unlock(&global_bh_lock);
+resched:
+	mark_bh(nr);
+}
+
+void init_bh(int nr, void (*routine)(void))
+{
+	bh_base[nr] = routine;
+	mb();
+}
+
+void remove_bh(int nr)
+{
+	tasklet_kill(bh_task_vec+nr);
+	bh_base[nr] = NULL;
 }
+
+void __init softirq_init()
+{
+	int i;
+
+	for (i=0; i<32; i++)
+		tasklet_init(bh_task_vec+i, bh_action, i);
+
+	open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL);
+	open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);
+}
+
+
diff -u --recursive --new-file v2.3.42/linux/kernel/sys.c linux/kernel/sys.c
--- v2.3.42/linux/kernel/sys.c	Fri Jan 28 15:09:09 2000
+++ linux/kernel/sys.c	Mon Feb  7 19:45:28 2000
@@ -901,6 +901,8 @@
 			? -EFAULT : 0;
 }
 
+#if !defined(__ia64__)
+
 /*
  *	Back compatibility for getrlimit. Needed for some apps.
  */
@@ -919,6 +921,7 @@
 	return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
 }
 
+#endif
 
 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
diff -u --recursive --new-file v2.3.42/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.3.42/linux/kernel/sysctl.c	Fri Jan 28 15:09:09 2000
+++ linux/kernel/sysctl.c	Thu Feb 10 12:17:00 2000
@@ -111,17 +111,8 @@
 
 struct file_operations proc_sys_file_operations =
 {
-	NULL,		/* lseek   */
-	proc_readsys,	/* read	   */
-	proc_writesys,	/* write   */
-	NULL,		/* readdir */
-	NULL,		/* poll    */
-	NULL,		/* ioctl   */
-	NULL,		/* mmap	   */
-	NULL,		/* no special open code	   */
-	NULL,		/* no special flush code */
-	NULL,		/* no special release code */
-	NULL		/* can't fsync */
+	read:		proc_readsys,
+	write:		proc_writesys,
 };
 
 struct inode_operations proc_sys_inode_operations =
@@ -138,9 +129,6 @@
 	NULL,		/* rename */
 	NULL,		/* readlink */
 	NULL,		/* follow_link */
-	NULL,		/* get_block */
-	NULL,		/* readpage */
-	NULL,		/* writepage */
 	NULL,		/* truncate */
 	proc_sys_permission, /* permission */
 	NULL		/* revalidate */
diff -u --recursive --new-file v2.3.42/linux/kernel/timer.c linux/kernel/timer.c
--- v2.3.42/linux/kernel/timer.c	Tue Dec 14 01:27:24 1999
+++ linux/kernel/timer.c	Thu Feb 10 12:41:10 2000
@@ -105,13 +105,15 @@
 
 static unsigned long timer_jiffies = 0;
 
-static inline void insert_timer(struct timer_list *timer,
-				struct timer_list **vec, int idx)
+static inline void insert_timer(struct timer_list *timer, struct timer_list **vec)
 {
-	if ((timer->next = vec[idx]))
-		vec[idx]->prev = timer;
-	vec[idx] = timer;
-	timer->prev = (struct timer_list *)&vec[idx];
+	struct timer_list *next = *vec;
+
+	timer->next = next;
+	if (next)
+		next->prev = timer;
+	*vec = timer;
+	timer->prev = (struct timer_list *)vec;
 }
 
 static inline void internal_add_timer(struct timer_list *timer)
@@ -121,31 +123,34 @@
 	 */
 	unsigned long expires = timer->expires;
 	unsigned long idx = expires - timer_jiffies;
+	struct timer_list ** vec;
 
 	if (idx < TVR_SIZE) {
 		int i = expires & TVR_MASK;
-		insert_timer(timer, tv1.vec, i);
+		vec = tv1.vec + i;
 	} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
 		int i = (expires >> TVR_BITS) & TVN_MASK;
-		insert_timer(timer, tv2.vec, i);
+		vec = tv2.vec + i;
 	} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
 		int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
-		insert_timer(timer, tv3.vec, i);
+		vec =  tv3.vec + i;
 	} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
 		int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
-		insert_timer(timer, tv4.vec, i);
+		vec = tv4.vec + i;
 	} else if ((signed long) idx < 0) {
 		/* can happen if you add a timer with expires == jiffies,
 		 * or you set a timer to go off in the past
 		 */
-		insert_timer(timer, tv1.vec, tv1.index);
+		vec = tv1.vec + tv1.index;
 	} else if (idx <= 0xffffffffUL) {
 		int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
-		insert_timer(timer, tv5.vec, i);
+		vec = tv5.vec + i;
 	} else {
 		/* Can only get here on architectures with 64-bit jiffies */
 		timer->next = timer->prev = timer;
+		return;
 	}
+	insert_timer(timer, vec);
 }
 
 spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
@@ -181,15 +186,17 @@
 	return 0;
 }
 
-void mod_timer(struct timer_list *timer, unsigned long expires)
+int mod_timer(struct timer_list *timer, unsigned long expires)
 {
+	int ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&timerlist_lock, flags);
 	timer->expires = expires;
-	detach_timer(timer);
+	ret = detach_timer(timer);
 	internal_add_timer(timer);
 	spin_unlock_irqrestore(&timerlist_lock, flags);
+	return ret;
 }
 
 int del_timer(struct timer_list * timer)
@@ -204,6 +211,39 @@
 	return ret;
 }
 
+#ifdef __SMP__
+/*
+ * SMP specific function to delete periodic timer.
+ * Caller must disable by some means restarting the timer
+ * for new. Upon exit the timer is not queued and handler is not running
+ * on any CPU. It returns number of times, which timer was deleted
+ * (for reference counting).
+ */
+
+int del_timer_sync(struct timer_list * timer)
+{
+	int ret = 0;
+
+	for (;;) {
+		unsigned long flags;
+		int running;
+
+		spin_lock_irqsave(&timerlist_lock, flags);
+		ret += detach_timer(timer);
+		timer->next = timer->prev = 0;
+		running = timer->running;
+		spin_unlock_irqrestore(&timerlist_lock, flags);
+
+		if (!running)
+			return ret;
+		timer_synchronize(timer);
+	}
+
+	return ret;
+}
+#endif
+
+
 static inline void cascade_timers(struct timer_vec *tv)
 {
         /* cascade all the timers from tv up one level */
@@ -238,6 +278,7 @@
 			unsigned long data = timer->data;
 			detach_timer(timer);
 			timer->next = timer->prev = NULL;
+			timer_set_running(timer);
 			spin_unlock_irq(&timerlist_lock);
 			fn(data);
 			spin_lock_irq(&timerlist_lock);
@@ -553,8 +594,7 @@
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if ((p->state == TASK_RUNNING ||
-		     (p->state & TASK_UNINTERRUPTIBLE) ||
-		     (p->state & TASK_SWAPPING)))
+		     (p->state & TASK_UNINTERRUPTIBLE)))
 			nr += FIXED_1;
 	}
 	read_unlock(&tasklist_lock);
diff -u --recursive --new-file v2.3.42/linux/mm/bootmem.c linux/mm/bootmem.c
--- v2.3.42/linux/mm/bootmem.c	Wed Dec 29 13:13:21 1999
+++ linux/mm/bootmem.c	Mon Feb  7 20:09:05 2000
@@ -129,11 +129,10 @@
 static void * __init __alloc_bootmem_core (bootmem_data_t *bdata, 
 	unsigned long size, unsigned long align, unsigned long goal)
 {
-	int area = 0;
-	unsigned long i, start = 0, reserved;
+	unsigned long i, start = 0;
 	void *ret;
 	unsigned long offset, remaining_size;
-	unsigned long areasize, preferred;
+	unsigned long areasize, preferred, incr;
 	unsigned long eidx = bdata->node_low_pfn - (bdata->node_boot_start >>
 							PAGE_SHIFT);
 
@@ -145,26 +144,28 @@
 	 */
 	if (goal && (goal >= bdata->node_boot_start) && 
 			((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) {
-		preferred = (goal - bdata->node_boot_start) >> PAGE_SHIFT;
+		preferred = goal - bdata->node_boot_start;
 	} else
 		preferred = 0;
 
+	preferred = ((preferred + align - 1) & ~(align - 1)) >> PAGE_SHIFT;
 	areasize = (size+PAGE_SIZE-1)/PAGE_SIZE;
+	incr = align >> PAGE_SHIFT ? : 1;
 
 restart_scan:
-	for (i = preferred; i < eidx; i++) {
-		reserved = test_bit(i, bdata->node_bootmem_map);
-		if (!reserved) {
-			if (!area) {
-				area = 1;
-				start = i;
-			}
-			if (i - start + 1 == areasize)
-				goto found;
-		} else {
-			area = 0;
-			start = -1;
+	for (i = preferred; i < eidx; i += incr) {
+		unsigned long j;
+		if (test_bit(i, bdata->node_bootmem_map))
+			continue;
+		for (j = i + 1; j < i + areasize; ++j) {
+			if (j >= eidx)
+				goto fail_block;
+			if (test_bit (j, bdata->node_bootmem_map))
+				goto fail_block;
 		}
+		start = i;
+		goto found;
+	fail_block:;
 	}
 	if (preferred) {
 		preferred = 0;
@@ -183,13 +184,12 @@
 	 * of this allocation's buffer? If yes then we can 'merge'
 	 * the previous partial page with this allocation.
 	 */
-	if (bdata->last_offset && (bdata->last_pos+1 == start)) {
+	if (align <= PAGE_SIZE
+	    && bdata->last_offset && bdata->last_pos+1 == start) {
 		offset = (bdata->last_offset+align-1) & ~(align-1);
 		if (offset > PAGE_SIZE)
 			BUG();
 		remaining_size = PAGE_SIZE-offset;
-		if (remaining_size > PAGE_SIZE)
-			BUG();
 		if (size < remaining_size) {
 			areasize = 0;
 			// last_pos unchanged
diff -u --recursive --new-file v2.3.42/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.42/linux/mm/filemap.c	Fri Jan 28 15:09:09 2000
+++ linux/mm/filemap.c	Thu Feb 10 12:17:00 2000
@@ -98,7 +98,7 @@
 	struct list_head *head, *curr;
 	struct page * page;
 
-	head = &inode->i_data.pages;
+	head = &inode->i_mapping->pages;
 	spin_lock(&pagecache_lock);
 	curr = head->next;
 
@@ -134,7 +134,7 @@
 	start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 repeat:
-	head = &inode->i_data.pages;
+	head = &inode->i_mapping->pages;
 	spin_lock(&pagecache_lock);
 	curr = head->next;
 	while (curr != head) {
@@ -289,6 +289,12 @@
 			goto cache_unlock_continue;
 
 		/*
+		 * We did the page aging part.
+		 */
+		if (nr_lru_pages < freepages.min * priority)
+			goto cache_unlock_continue;
+
+		/*
 		 * Is it a page swap page? If so, we want to
 		 * drop it if it is no longer used, even if it
 		 * were to be marked referenced..
@@ -417,7 +423,7 @@
 	struct page *page;
 	int retval = 0;
 
-	head = &inode->i_data.pages;
+	head = &inode->i_mapping->pages;
 
 	spin_lock(&pagecache_lock);
 	curr = head->next;
@@ -519,11 +525,12 @@
 static inline int page_cache_read(struct file * file, unsigned long offset) 
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct page **hash = page_hash(&inode->i_data, offset);
+	struct address_space *mapping = inode->i_mapping;
+	struct page **hash = page_hash(mapping, offset);
 	struct page *page; 
 
 	spin_lock(&pagecache_lock);
-	page = __find_page_nolock(&inode->i_data, offset, *hash); 
+	page = __find_page_nolock(mapping, offset, *hash); 
 	spin_unlock(&pagecache_lock);
 	if (page)
 		return 0;
@@ -532,8 +539,8 @@
 	if (!page)
 		return -ENOMEM;
 
-	if (!add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
-		int error = inode->i_op->readpage(file->f_dentry, page);
+	if (!add_to_page_cache_unique(page, mapping, offset, hash)) {
+		int error = mapping->a_ops->readpage(file->f_dentry, page);
 		page_cache_release(page);
 		return error;
 	}
@@ -949,6 +956,7 @@
 {
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
+	struct address_space *mapping = inode->i_mapping;
 	unsigned long index, offset;
 	struct page *cached_page;
 	int reada_ok;
@@ -1017,10 +1025,10 @@
 		/*
 		 * Try to find the data in the page cache..
 		 */
-		hash = page_hash(&inode->i_data, index);
+		hash = page_hash(mapping, index);
 
 		spin_lock(&pagecache_lock);
-		page = __find_page_nolock(&inode->i_data, index, *hash);
+		page = __find_page_nolock(mapping, index, *hash);
 		if (!page)
 			goto no_cached_page;
 found_page:
@@ -1068,7 +1076,7 @@
 
 readpage:
 		/* ... and start the actual read. The read will unlock the page. */
-		error = inode->i_op->readpage(filp->f_dentry, page);
+		error = mapping->a_ops->readpage(filp->f_dentry, page);
 
 		if (!error) {
 			if (Page_Uptodate(page))
@@ -1107,7 +1115,7 @@
 			 * dropped the page cache lock. Check for that.
 			 */
 			spin_lock(&pagecache_lock);
-			page = __find_page_nolock(&inode->i_data, index, *hash);
+			page = __find_page_nolock(mapping, index, *hash);
 			if (page)
 				goto found_page;
 		}
@@ -1116,7 +1124,7 @@
 		 * Ok, add the new page to the hash-queues...
 		 */
 		page = cached_page;
-		__add_to_page_cache(page, &inode->i_data, index, hash);
+		__add_to_page_cache(page, mapping, index, hash);
 		spin_unlock(&pagecache_lock);
 		cached_page = NULL;
 
@@ -1227,7 +1235,7 @@
 	in_inode = in_file->f_dentry->d_inode;
 	if (!in_inode)
 		goto fput_in;
-	if (!in_inode->i_op || !in_inode->i_op->readpage)
+	if (!in_inode->i_mapping->a_ops->readpage)
 		goto fput_in;
 	retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count);
 	if (retval)
@@ -1301,6 +1309,7 @@
 	struct file *file = area->vm_file;
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
+	struct address_space *mapping = inode->i_mapping;
 	struct page *page, **hash, *old_page;
 	unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
@@ -1319,9 +1328,9 @@
 	/*
 	 * Do we have something in the page cache already?
 	 */
-	hash = page_hash(&inode->i_data, pgoff);
+	hash = page_hash(mapping, pgoff);
 retry_find:
-	page = __find_get_page(&inode->i_data, pgoff, hash);
+	page = __find_get_page(mapping, pgoff, hash);
 	if (!page)
 		goto no_cached_page;
 
@@ -1390,7 +1399,7 @@
 		goto success;
 	}
 
-	if (!inode->i_op->readpage(file->f_dentry, page)) {
+	if (!mapping->a_ops->readpage(file->f_dentry, page)) {
 		wait_on_page(page);
 		if (Page_Uptodate(page))
 			goto success;
@@ -1408,7 +1417,7 @@
 		goto success;
 	}
 	ClearPageError(page);
-	if (!inode->i_op->readpage(file->f_dentry, page)) {
+	if (!mapping->a_ops->readpage(file->f_dentry, page)) {
 		wait_on_page(page);
 		if (Page_Uptodate(page))
 			goto success;
@@ -1440,7 +1449,7 @@
 		if (size_idx <= index)
 			return -EIO;
 	}
-	writepage = inode->i_op->writepage;
+	writepage = inode->i_mapping->a_ops->writepage;
 	lock_page(page);
 
 	retval = writepage(file->f_dentry, page);
@@ -1652,13 +1661,13 @@
 
 	ops = &file_private_mmap;
 	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
-		if (!inode->i_op || !inode->i_op->writepage)
+		if (!inode->i_mapping->a_ops->writepage)
 			return -EINVAL;
 		ops = &file_shared_mmap;
 	}
 	if (!inode->i_sb || !S_ISREG(inode->i_mode))
 		return -EACCES;
-	if (!inode->i_op || !inode->i_op->readpage)
+	if (!inode->i_mapping->a_ops->readpage)
 		return -ENOEXEC;
 	UPDATE_ATIME(inode);
 	vma->vm_ops = ops;
@@ -1810,6 +1819,21 @@
 	return page;
 }
 
+static inline void remove_suid(struct inode *inode)
+{
+	unsigned int mode;
+
+	/* set S_IGID if S_IXGRP is set, and always set S_ISUID */
+	mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
+
+	/* was any of the uid bits set? */
+	mode &= inode->i_mode;
+	if (mode && !capable(CAP_FSETID)) {
+		inode->i_mode &= ~mode;
+		mark_inode_dirty(inode);
+	}
+}
+
 /*
  * Write to a file through the page cache. This is mainly for the
  * benefit of NFS and possibly other network-based file systems.
@@ -1827,12 +1851,11 @@
  *							okir@monad.swb.de
  */
 ssize_t
-generic_file_write(struct file *file, const char *buf,
-		   size_t count, loff_t *ppos,
-		   writepage_t write_one_page)
+generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
 {
 	struct dentry	*dentry = file->f_dentry; 
 	struct inode	*inode = dentry->d_inode; 
+	struct address_space *mapping = inode->i_mapping;
 	unsigned long	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
 	loff_t		pos;
 	struct page	*page, *cached_page;
@@ -1876,9 +1899,15 @@
 	}
 
 	status  = 0;
+	if (count) {
+		remove_suid(inode);
+		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+		mark_inode_dirty(inode);
+	}
 
 	while (count) {
 		unsigned long bytes, index, offset;
+		char *kaddr;
 
 		/*
 		 * Try to find the page in the cache. If it isn't there,
@@ -1891,7 +1920,7 @@
 			bytes = count;
 
 		status = -ENOMEM;	/* we'll assign it later anyway */
-		page = __grab_cache_page(&inode->i_data, index, &cached_page);
+		page = __grab_cache_page(mapping, index, &cached_page);
 		if (!page)
 			break;
 
@@ -1900,7 +1929,16 @@
 			PAGE_BUG(page);
 		}
 
-		status = write_one_page(file, page, offset, bytes, buf);
+		status = mapping->a_ops->prepare_write(page, offset, offset+bytes);
+		if (status)
+			goto unlock;
+		kaddr = (char*)page_address(page);
+		status = copy_from_user(kaddr+offset, buf, bytes);
+		if (status)
+			goto fail_write;
+		status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
+		if (!status)
+			status = bytes;
 
 		if (status >= 0) {
 			written += status;
@@ -1910,6 +1948,7 @@
 			if (pos > inode->i_size)
 				inode->i_size = pos;
 		}
+unlock:
 		/* Mark it unlocked again and drop the page.. */
 		UnlockPage(page);
 		page_cache_release(page);
@@ -1926,6 +1965,11 @@
 out:
 	up(&inode->i_sem);
 	return err;
+fail_write:
+	status = -EFAULT;
+	ClearPageUptodate(page);
+	kunmap(page);
+	goto unlock;
 }
 
 void __init page_cache_init(unsigned long mempages)
diff -u --recursive --new-file v2.3.42/linux/mm/mlock.c linux/mm/mlock.c
--- v2.3.42/linux/mm/mlock.c	Mon Nov  1 13:56:27 1999
+++ linux/mm/mlock.c	Mon Feb  7 19:45:28 2000
@@ -142,7 +142,7 @@
 
 	if (on && !capable(CAP_IPC_LOCK))
 		return -EPERM;
-	len = (len + ~PAGE_MASK) & PAGE_MASK;
+	len = PAGE_ALIGN(len);
 	end = start + len;
 	if (end < start)
 		return -EINVAL;
@@ -191,7 +191,7 @@
 	int error = -ENOMEM;
 
 	down(&current->mm->mmap_sem);
-	len = (len + (start & ~PAGE_MASK) + ~PAGE_MASK) & PAGE_MASK;
+	len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
 	start &= PAGE_MASK;
 
 	locked = len >> PAGE_SHIFT;
@@ -220,7 +220,7 @@
 	int ret;
 
 	down(&current->mm->mmap_sem);
-	len = (len + (start & ~PAGE_MASK) + ~PAGE_MASK) & PAGE_MASK;
+	len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
 	start &= PAGE_MASK;
 	ret = do_mlock(start, len, 0);
 	up(&current->mm->mmap_sem);
diff -u --recursive --new-file v2.3.42/linux/mm/mmap.c linux/mm/mmap.c
--- v2.3.42/linux/mm/mmap.c	Mon Dec 20 18:48:22 1999
+++ linux/mm/mmap.c	Tue Feb  8 18:23:13 2000
@@ -114,9 +114,9 @@
 		goto out;
 	}
 
-	/* Check against rlimit and stack.. */
+	/* Check against rlimit.. */
 	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
-	if (rlim < RLIM_INFINITY && brk - mm->end_code > rlim)
+	if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
 		goto out;
 
 	/* Check against existing mmap mappings. */
@@ -609,8 +609,10 @@
 no_mmaps:
 	first = first >> PGDIR_SHIFT;
 	last = last >> PGDIR_SHIFT;
-	if (last > first)
+	if (last > first) {
 		clear_page_tables(mm, first, last-first);
+		flush_tlb_pgtables(mm, first << PGDIR_SHIFT, last << PGDIR_SHIFT);
+	}
 }
 
 /* Munmap is split into 2 main parts -- this part which finds
diff -u --recursive --new-file v2.3.42/linux/mm/mprotect.c linux/mm/mprotect.c
--- v2.3.42/linux/mm/mprotect.c	Tue Nov 23 22:42:21 1999
+++ linux/mm/mprotect.c	Mon Feb  7 19:45:28 2000
@@ -214,7 +214,7 @@
 
 	if (start & ~PAGE_MASK)
 		return -EINVAL;
-	len = (len + ~PAGE_MASK) & PAGE_MASK;
+	len = PAGE_ALIGN(len);
 	end = start + len;
 	if (end < start)
 		return -EINVAL;
diff -u --recursive --new-file v2.3.42/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.3.42/linux/mm/page_alloc.c	Fri Jan 28 15:09:09 2000
+++ linux/mm/page_alloc.c	Wed Feb  9 19:33:13 2000
@@ -29,7 +29,9 @@
 LIST_HEAD(lru_cache);
 
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
-static int zone_balance_ratio[MAX_NR_ZONES] = { 128, 128, 128 };
+static int zone_balance_ratio[MAX_NR_ZONES] = { 128, 128, 128, };
+static int zone_balance_min[MAX_NR_ZONES] = { 10 , 10, 10, };
+static int zone_balance_max[MAX_NR_ZONES] = { 255 , 255, 255, };
 
 /*
  * Free_page() adds the page to the free lists. This is optimized for
@@ -196,9 +198,6 @@
 	return NULL;
 }
 
-#define ZONE_BALANCED(zone) \
-	(((zone)->free_pages > (zone)->pages_low) && (!(zone)->low_on_memory))
-
 static inline unsigned long classfree(zone_t *zone)
 {
 	unsigned long free = 0;
@@ -215,21 +214,6 @@
 static inline int zone_balance_memory (zone_t *zone, int gfp_mask)
 {
 	int freed;
-	unsigned long free = classfree(zone);
-
-	if (free >= zone->pages_low) {
-		if (!zone->low_on_memory)
-			return 1;
-		/*
-		 * Simple hysteresis: exit 'low memory mode' if
-		 * the upper limit has been reached:
-		 */
-		if (free >= zone->pages_high) {
-			zone->low_on_memory = 0;
-			return 1;
-		}
-	} else
-		zone->low_on_memory = 1;
 
 	/*
 	 * In the atomic allocation case we only 'kick' the
@@ -243,43 +227,6 @@
 	return 1;
 }
 
-#if 0
-/*
- * We are still balancing memory in a global way:
- */
-static inline int balance_memory (zone_t *zone, int gfp_mask)
-{
-	unsigned long free = nr_free_pages();
-	static int low_on_memory = 0;
-	int freed;
-
-	if (free >= freepages.low) {
-		if (!low_on_memory)
-			return 1;
-		/*
-		 * Simple hysteresis: exit 'low memory mode' if
-		 * the upper limit has been reached:
-		 */
-		if (free >= freepages.high) {
-			low_on_memory = 0;
-			return 1;
-		}
-	} else
-		low_on_memory = 1;
-
-	/*
-	 * In the atomic allocation case we only 'kick' the
-	 * state machine, but do not try to free pages
-	 * ourselves.
-	 */
-	freed = try_to_free_pages(gfp_mask, zone);
-
-	if (!freed && !(gfp_mask & __GFP_HIGH))
-		return 0;
-	return 1;
-}
-#endif
-
 /*
  * This is the 'heart' of the zoned buddy allocator:
  */
@@ -310,11 +257,31 @@
 		 * further thought.
 		 */
 		if (!(current->flags & PF_MEMALLOC))
-			/*
-			 * fastpath
-			 */
-			if (!ZONE_BALANCED(z))
-				goto balance;
+		{
+			if (classfree(z) > z->pages_high)
+			{
+				if (z->low_on_memory)
+					z->low_on_memory = 0;
+			}
+			else
+			{
+				extern wait_queue_head_t kswapd_wait;
+
+				if (z->low_on_memory)
+					goto balance;
+
+				if (classfree(z) <= z->pages_low)
+				{
+					wake_up_interruptible(&kswapd_wait);
+
+					if (classfree(z) <= z->pages_min)
+					{
+						z->low_on_memory = 1;
+						goto balance;
+					}
+				}
+			}
+		}
 		/*
 		 * This is an optimization for the 'higher order zone
 		 * is empty' case - it can happen even in well-behaved
@@ -378,7 +345,7 @@
 	zone_t *zone;
 	int i;
 
-	sum = nr_lru_pages;
+	sum = nr_lru_pages - atomic_read(&page_cache_size);
 	for (i = 0; i < NUMNODES; i++)
 		for (zone = NODE_DATA(i)->node_zones; zone <= NODE_DATA(i)->node_zones+ZONE_NORMAL; zone++)
 			sum += zone->free_pages;
@@ -515,12 +482,12 @@
  *   - clear the memory bitmaps
  */
 void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
-	unsigned int *zones_size, unsigned long zone_start_paddr)
+	unsigned long *zones_size, unsigned long zone_start_paddr)
 {
 	struct page *p, *lmem_map;
 	unsigned long i, j;
 	unsigned long map_size;
-	unsigned int totalpages, offset;
+	unsigned long totalpages, offset;
 	unsigned int cumulative = 0;
 
 	totalpages = 0;
@@ -528,7 +495,7 @@
 		unsigned long size = zones_size[i];
 		totalpages += size;
 	}
-	printk("On node %d totalpages: %08x\n", nid, totalpages);
+	printk("On node %d totalpages: %lu\n", nid, totalpages);
 
 	/*
 	 * Select nr of pages we try to keep free for important stuff
@@ -579,7 +546,7 @@
 
 		size = zones_size[j];
 
-		printk("zone(%ld): %ld pages.\n", j, size);
+		printk("zone(%lu): %lu pages.\n", j, size);
 		zone->size = size;
 		zone->name = zone_names[j];
 		zone->lock = SPIN_LOCK_UNLOCKED;
@@ -590,7 +557,11 @@
 		zone->offset = offset;
 		cumulative += size;
 		mask = (cumulative / zone_balance_ratio[j]);
-		if (mask < 1) mask = 1;
+		if (mask < zone_balance_min[j])
+			mask = zone_balance_min[j];
+		else if (mask > zone_balance_max[j])
+			mask = zone_balance_max[j];
+		zone->pages_min = mask;
 		zone->pages_low = mask*2;
 		zone->pages_high = mask*3;
 		zone->low_on_memory = 0;
@@ -622,7 +593,7 @@
 	build_zonelists(pgdat);
 }
 
-void __init free_area_init(unsigned int *zones_size)
+void __init free_area_init(unsigned long *zones_size)
 {
 	free_area_init_core(0, NODE_DATA(0), &mem_map, zones_size, 0);
 }
diff -u --recursive --new-file v2.3.42/linux/mm/slab.c linux/mm/slab.c
--- v2.3.42/linux/mm/slab.c	Fri Jan 21 18:19:17 2000
+++ linux/mm/slab.c	Wed Feb  9 20:08:09 2000
@@ -110,7 +110,7 @@
 /* If there is a different PAGE_SIZE around, and it works with this allocator,
  * then change the following.
  */
-#if	(PAGE_SIZE != 8192 && PAGE_SIZE != 4096 && PAGE_SIZE != 32768)
+#if	(PAGE_SIZE != 8192 && PAGE_SIZE != 4096 && PAGE_SIZE != 16384 && PAGE_SIZE != 32768)
 #error	Your page size is probably not correctly supported - please check
 #endif
 
@@ -1864,11 +1864,10 @@
 	} while (--scan && searchp != clock_searchp);
 
 	clock_searchp = searchp;
-	up(&cache_chain_sem);
 
 	if (!best_cachep) {
 		/* couldn't find anything to reap */
-		return;
+		goto out;
 	}
 
 	spin_lock_irq(&best_cachep->c_spinlock);
@@ -1902,6 +1901,8 @@
 	}
 dma_fail:
 	spin_unlock_irq(&best_cachep->c_spinlock);
+out:
+	up(&cache_chain_sem);
 	return;
 }
 
@@ -1990,14 +1991,14 @@
 		unsigned long allocs = cachep->c_num_allocations;
 		errors = (unsigned long) atomic_read(&cachep->c_errors);
 		spin_unlock_irqrestore(&cachep->c_spinlock, save_flags);
-		len += sprintf(buf+len, "%-16s %6lu %6lu %4lu %4lu %4lu %6lu %7lu %5lu %4lu %4lu\n",
-				cachep->c_name, active_objs, num_objs, active_slabs, num_slabs,
+		len += sprintf(buf+len, "%-16s %6lu %6lu %6lu %4lu %4lu %4lu %6lu %7lu %5lu %4lu %4lu\n",
+				cachep->c_name, active_objs, num_objs, cachep->c_offset, active_slabs, num_slabs,
 				(1<<cachep->c_gfporder)*num_slabs,
 				high, allocs, grown, reaped, errors);
 		}
 #else
 		spin_unlock_irqrestore(&cachep->c_spinlock, save_flags);
-		len += sprintf(buf+len, "%-17s %6lu %6lu\n", cachep->c_name, active_objs, num_objs);
+		len += sprintf(buf+len, "%-17s %6lu %6lu %6lu\n", cachep->c_name, active_objs, num_objs, cachep->c_offset);
 #endif	/* SLAB_STATS */
 	} while ((cachep = cachep->c_nextp) != &cache_cache);
 	up(&cache_chain_sem);
diff -u --recursive --new-file v2.3.42/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.42/linux/mm/swapfile.c	Thu Jan  6 12:57:48 2000
+++ linux/mm/swapfile.c	Mon Feb  7 17:48:03 2000
@@ -445,12 +445,12 @@
 	struct swap_info_struct * p = NULL;
 	struct dentry * dentry;
 	int i, type, prev;
-	int err = -EPERM;
+	int err;
 	
-	lock_kernel();
 	if (!capable(CAP_SYS_ADMIN))
-		goto out;
+		return -EPERM;
 
+	lock_kernel();
 	dentry = namei(specialfile);
 	err = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
@@ -587,7 +587,7 @@
 	struct dentry * swap_dentry;
 	unsigned int type;
 	int i, j, prev;
-	int error = -EPERM;
+	int error;
 	static int least_priority = 0;
 	union swap_header *swap_header = 0;
 	int swap_header_version;
@@ -596,13 +596,14 @@
 	int swapfilesize;
 	struct block_device *bdev = NULL;
 	
-	lock_kernel();
 	if (!capable(CAP_SYS_ADMIN))
-		goto out;
+		return -EPERM;
+	lock_kernel();
 	p = swap_info;
 	for (type = 0 ; type < nr_swapfiles ; type++,p++)
 		if (!(p->flags & SWP_USED))
 			break;
+	error = -EPERM;
 	if (type >= MAX_SWAPFILES)
 		goto out;
 	if (type >= nr_swapfiles)
diff -u --recursive --new-file v2.3.42/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.42/linux/mm/vmscan.c	Fri Jan 28 15:09:09 2000
+++ linux/mm/vmscan.c	Wed Feb  9 18:58:20 2000
@@ -451,7 +451,7 @@
 	return priority >= 0;
 }
 
-static struct task_struct *kswapd_process;
+DECLARE_WAIT_QUEUE_HEAD(kswapd_wait);
 
 /*
  * The background pageout daemon, started as a kernel thread
@@ -471,7 +471,6 @@
 {
 	struct task_struct *tsk = current;
 
-	kswapd_process = tsk;
 	tsk->session = 1;
 	tsk->pgrp = 1;
 	strcpy(tsk->comm, "kswapd");
@@ -510,7 +509,7 @@
 			run_task_queue(&tq_disk);
 		} while (!tsk->need_resched);
 		tsk->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ);
+		interruptible_sleep_on(&kswapd_wait);
 	}
 }
 
@@ -533,7 +532,6 @@
 {
 	int retval = 1;
 
-	wake_up_process(kswapd_process);
 	if (gfp_mask & __GFP_WAIT) {
 		current->flags |= PF_MEMALLOC;
 		retval = do_try_to_free_pages(gfp_mask, zone);
diff -u --recursive --new-file v2.3.42/linux/net/atm/atm_misc.c linux/net/atm/atm_misc.c
--- v2.3.42/linux/net/atm/atm_misc.c	Fri Sep 10 23:57:37 1999
+++ linux/net/atm/atm_misc.c	Tue Feb  8 18:23:13 2000
@@ -10,13 +10,11 @@
 #include <asm/atomic.h>
 #include <asm/errno.h>
 
-#include "tunable.h"
-
 
 int atm_charge(struct atm_vcc *vcc,int truesize)
 {
 	atm_force_charge(vcc,truesize);
-	if (atomic_read(&vcc->rx_inuse) <= vcc->rx_quota) return 1;
+	if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) return 1;
 	atm_return(vcc,truesize);
 	vcc->stats->rx_drop++;
 	return 0;
@@ -29,7 +27,7 @@
 	int guess = atm_guess_pdu2truesize(pdu_size);
 
 	atm_force_charge(vcc,guess);
-	if (atomic_read(&vcc->rx_inuse) <= vcc->rx_quota) {
+	if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) {
 		struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
 
 		if (skb) {
diff -u --recursive --new-file v2.3.42/linux/net/atm/clip.c linux/net/atm/clip.c
--- v2.3.42/linux/net/atm/clip.c	Fri Sep 10 23:57:37 1999
+++ linux/net/atm/clip.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* net/atm/clip.c - RFC1577 Classical IP over ATM */
 
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/config.h>
@@ -30,7 +30,6 @@
 #include <asm/atomic.h>
 
 #include "common.h"
-#include "tunable.h"
 #include "resources.h"
 #include "ipcommon.h"
 #include <net/atmclip.h>
@@ -219,6 +218,18 @@
 }
 
 
+static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+{
+	DPRINTK("clip_pop(vcc %p)\n",vcc);
+	CLIP_VCC(vcc)->old_pop(vcc,skb);
+	/* skb->dev == NULL in outbound ARP packets */
+	if (atm_may_send(vcc,0) && skb->dev) {
+		skb->dev->tbusy = 0;
+		mark_bh(NET_BH);
+	}
+}
+
+
 static void clip_neigh_destroy(struct neighbour *neigh)
 {
 	DPRINTK("clip_neigh_destroy (neigh %p)\n",neigh);
@@ -346,6 +357,7 @@
 static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
 {
 	struct atmarp_entry *entry;
+	struct atm_vcc *vcc;
 
 	DPRINTK("clip_start_xmit (skb %p)\n",skb);
 	if (!skb->dst) {
@@ -381,9 +393,8 @@
 		return 0;
 	}
 	DPRINTK("neigh %p, vccs %p\n",entry,entry->vccs);
-	ATM_SKB(skb)->vcc = entry->vccs->vcc;
-	DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,
-	    ATM_SKB(skb)->vcc);
+	ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
+	DPRINTK("using neighbour %p, vcc %p\n",skb->dst->neighbour,vcc);
 	if (entry->vccs->encap) {
 		void *here;
 
@@ -391,15 +402,15 @@
 		memcpy(here,llc_oui,sizeof(llc_oui));
 		((u16 *) here)[3] = skb->protocol;
 	}
-	atomic_add(skb->truesize,&ATM_SKB(skb)->vcc->tx_inuse);
+	atomic_add(skb->truesize,&vcc->tx_inuse);
+	dev->tbusy = !atm_may_send(vcc,0);
 	ATM_SKB(skb)->iovcnt = 0;
-	ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
+	ATM_SKB(skb)->atm_options = vcc->atm_options;
 	entry->vccs->last_use = jiffies;
-	DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,ATM_SKB(skb)->vcc,
-	    ATM_SKB(skb)->vcc->dev);
+	DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
 	PRIV(dev)->stats.tx_packets++;
 	PRIV(dev)->stats.tx_bytes += skb->len;
-	(void) ATM_SKB(skb)->vcc->dev->ops->send(ATM_SKB(skb)->vcc,skb);
+	(void) vcc->dev->ops->send(vcc,skb);
 	return 0;
 }
 
@@ -428,9 +439,11 @@
 	clip_vcc->last_use = jiffies;
 	clip_vcc->idle_timeout = timeout*HZ;
 	clip_vcc->old_push = vcc->push;
+	clip_vcc->old_pop = vcc->pop;
 	save_flags(flags);
 	cli();
 	vcc->push = clip_push;
+	vcc->pop = clip_pop;
 	skb_migrate(&vcc->recvq,&copy);
 	restore_flags(flags);
 	/* re-process everything received between connection setup and MKIP */
@@ -511,7 +524,12 @@
 	dev->hard_header_len = RFC1483LLC_LEN;
 	dev->mtu = RFC1626_MTU;
 	dev->addr_len = 0;
-	dev->tx_queue_len = 0;
+	dev->tx_queue_len = 100; /* "normal" queue */
+	    /* When using a "real" qdisc, the qdisc determines the queue */
+	    /* length. tx_queue_len is only used for the default case, */
+	    /* without any more elaborate queuing. 100 is a reasonable */
+	    /* compromise between decent burst-tolerance and protection */
+	    /* against memory hogs. */
 	dev->flags = 0;
 	dev_init_buffers(dev); /* is this ever supposed to be used ? */
 	return 0;
@@ -641,20 +659,7 @@
 
 
 static struct atmdev_ops atmarpd_dev_ops = {
-	NULL,		/* no dev_close */
-	NULL,		/* no open */
-	atmarpd_close,	/* close */
-	NULL,		/* no ioctl */
-	NULL,		/* no getsockopt */
-	NULL,		/* no setsockopt */
-	NULL,		/* send */
-	NULL,		/* no sg_send */
-	NULL,		/* no send_oam */
-	NULL,		/* no phy_put */
-	NULL,		/* no phy_get */
-	NULL,		/* no feedback */
-	NULL,		/* no change_qos */
-	NULL		/* no free_rx_skb */
+	close:	atmarpd_close,
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/net/atm/common.c linux/net/atm/common.c
--- v2.3.42/linux/net/atm/common.c	Fri Sep 10 23:57:37 1999
+++ linux/net/atm/common.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
 
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/config.h>
@@ -24,11 +24,6 @@
 #include <asm/uaccess.h>
 #include <asm/poll.h>
 
-#ifdef CONFIG_MMU_HACKS
-#include <linux/mmuio.h>
-#include <linux/uio.h>
-#endif
-
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 #include <linux/atmlec.h>
 #include "lec.h"
@@ -62,7 +57,6 @@
 #include "resources.h"		/* atm_find_dev */
 #include "common.h"		/* prototypes */
 #include "protocols.h"		/* atm_init_<transport> */
-#include "tunable.h"		/* tunable parameters */
 #include "addr.h"		/* address registry */
 #ifdef CONFIG_ATM_CLIP
 #include <net/atmclip.h>	/* for clip_create */
@@ -81,10 +75,9 @@
 {
 	struct sk_buff *skb;
 
-	if (atomic_read(&vcc->tx_inuse) && size+atomic_read(&vcc->tx_inuse)+
-	    ATM_PDU_OVHD > vcc->tx_quota) {
-		DPRINTK("Sorry: tx_inuse = %d, size = %d, tx_quota = %ld\n",
-		    atomic_read(&vcc->tx_inuse),size,vcc->tx_quota);
+	if (atomic_read(&vcc->tx_inuse) && !atm_may_send(vcc,size)) {
+		DPRINTK("Sorry: tx_inuse = %d, size = %d, sndbuf = %d\n",
+		    atomic_read(&vcc->tx_inuse),size,vcc->sk->sndbuf);
 		return NULL;
 	}
 	while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
@@ -103,15 +96,13 @@
 	if (sock->type == SOCK_STREAM) return -EINVAL;
 	if (!(sk = alloc_atm_vcc_sk(family))) return -ENOMEM;
 	vcc = sk->protinfo.af_atm;
-	vcc->flags = ATM_VF_SCRX | ATM_VF_SCTX;
+	vcc->flags = 0;
 	vcc->dev = NULL;
 	vcc->family = sock->ops->family;
 	vcc->alloc_tx = alloc_tx;
 	vcc->callback = NULL;
 	memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
 	memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
-	vcc->tx_quota = ATM_TXBQ_DEF;
-	vcc->rx_quota = ATM_RXBQ_DEF;
 	atomic_set(&vcc->tx_inuse,0);
 	atomic_set(&vcc->rx_inuse,0);
 	vcc->push = NULL;
@@ -382,19 +373,9 @@
 		else vcc->dev->ops->free_rx_skb(vcc, skb);
 		return error ? error : eff_len;
 	}
-#ifdef CONFIG_MMU_HACKS
-	if (vcc->flags & ATM_VF_SCRX) {
-		mmucp_tofs((unsigned long) buff,eff_len,skb,
-		    (unsigned long) skb->data);
-		return eff_len;
-	}
-	else
-#endif
-	{
-		error = copy_to_user(buff,skb->data,eff_len) ? -EFAULT : 0;
-		if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
-		else vcc->dev->ops->free_rx_skb(vcc, skb);
-	}
+	error = copy_to_user(buff,skb->data,eff_len) ? -EFAULT : 0;
+	if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb);
+	else vcc->dev->ops->free_rx_skb(vcc, skb);
 	return error ? error : eff_len;
 }
 
@@ -419,39 +400,6 @@
 	if (!(vcc->flags & ATM_VF_READY)) return -EPIPE;
 	if (!size) return 0;
 	/* verify_area is done by net/socket.c */
-#ifdef CONFIG_MMU_HACKS
-	if ((vcc->flags & ATM_VF_SCTX) && vcc->dev->ops->sg_send &&
-	    vcc->dev->ops->sg_send(vcc,(unsigned long) buff,size)) {
-		int res,max_iov;
-
-		max_iov = 2+size/PAGE_SIZE;
-		/*
-		 * Doesn't use alloc_tx yet - this will change later. @@@
-		 */
-		while (!(skb = alloc_skb(sizeof(struct iovec)*max_iov,
-		    GFP_KERNEL))) {
-			if (m->msg_flags & MSG_DONTWAIT) return -EAGAIN;
-			interruptible_sleep_on(&vcc->wsleep);
-			if (signal_pending(current)) return -ERESTARTSYS;
-		}
-		skb_put(skb,size);
-		res = lock_user((unsigned long) buff,size,max_iov,
-		    (struct iovec *) skb->data);
-		if (res < 0) {
-			kfree_skb(skb);
-			if (res != -EAGAIN) return res;
-		}
-		else {
-			DPRINTK("res is %d\n",res);
-			DPRINTK("Asnd %d += %d\n",vcc->tx_inuse,skb->truesize);
-			atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
-			ATM_SKB(skb)->iovcnt = res;
-			error = vcc->dev->ops->send(vcc,skb);
-			/* FIXME: security: may send up to 3 "garbage" bytes */
-			return error ? error : size;
-		}
-	}
-#endif
 	eff = (size+3) & ~3; /* align to word boundary */
 	while (!(skb = vcc->alloc_tx(vcc,eff))) {
 		if (m->msg_flags & MSG_DONTWAIT) return -EAGAIN;
@@ -461,6 +409,7 @@
 			return vcc->reply;
 		if (!(vcc->flags & ATM_VF_READY)) return -EPIPE;
 	}
+	skb->dev = NULL; /* for paths shared with net_device interfaces */
 	ATM_SKB(skb)->iovcnt = 0;
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 	if (copy_from_user(skb_put(skb,size),buff,size)) {
@@ -488,7 +437,7 @@
 	if (sock->state != SS_CONNECTING) {
 		if (vcc->qos.txtp.traffic_class != ATM_NONE &&
 		    vcc->qos.txtp.max_sdu+atomic_read(&vcc->tx_inuse)+
-		    ATM_PDU_OVHD <= vcc->tx_quota)
+		    ATM_PDU_OVHD <= vcc->sk->sndbuf)
 			mask |= POLLOUT | POLLWRNORM;
 	}
 	else if (vcc->reply != WAITING) {
@@ -527,13 +476,13 @@
 
 	vcc = ATM_SD(sock);
 	switch (cmd) {
-		case TIOCOUTQ:
+		case SIOCOUTQ:
 			if (sock->state != SS_CONNECTED ||
 			    !(vcc->flags & ATM_VF_READY)) return -EINVAL;
-			return put_user(vcc->tx_quota-
+			return put_user(vcc->sk->sndbuf-
 			    atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
 			    (int *) arg) ? -EFAULT : 0;
-		case TIOCINQ:
+		case SIOCINQ:
 			{
 				struct sk_buff *skb;
 
@@ -569,30 +518,13 @@
 			return copy_to_user((void *) arg,&vcc->timestamp,
 			    sizeof(struct timeval)) ? -EFAULT : 0;
 		case ATM_SETSC:
-			if (arg & ~(ATM_VF_SCRX | ATM_VF_SCTX)) return -EINVAL;
-			/* @@@ race condition - should split flags into
-			       "volatile" and non-volatile part */
-			vcc->flags = (vcc->flags & ~(ATM_VF_SCRX |
-			    ATM_VF_SCTX)) | arg;
+			printk(KERN_WARNING "ATM_SETSC is obsolete\n");
 			return 0;
 		case ATMSIGD_CTRL:
 			if (!capable(CAP_NET_ADMIN)) return -EPERM;
 			error = sigd_attach(vcc);
 			if (!error) sock->state = SS_CONNECTED;
 			return error;
-#ifdef WE_DONT_SUPPORT_P2MP_YET
-		case ATM_CREATE_LEAF:
-			{
-				struct socket *session;
-
-				if (!(session = sockfd_lookup(arg,&error)))
-					return error;
-				if (sock->ops->family != PF_ATMSVC ||
-				    session->ops->family != PF_ATMSVC)
-					return -EPROTOTYPE;
-				return create_leaf(sock,session);
-			}
-#endif
 #ifdef CONFIG_ATM_CLIP
 		case SIOCMKCLIP:
 			if (!capable(CAP_NET_ADMIN)) return -EPERM;
@@ -746,7 +678,8 @@
 		default:
 			if (!dev->ops->ioctl) return -EINVAL;
 			size = dev->ops->ioctl(dev,cmd,buf);
-			if (size < 0) return size;
+			if (size < 0)
+				return size == -ENOIOCTLCMD ? -EINVAL : size;
 	}
 	if (!size) return 0;
 	return put_user(size,&((struct atmif_sioc *) arg)->length) ?
@@ -805,22 +738,6 @@
 
 	vcc = ATM_SD(sock);
 	switch (optname) {
-		case SO_SNDBUF:
-			if (get_user(value,(unsigned long *) optval))
-				return -EFAULT;
-			if (!value) value = ATM_TXBQ_DEF;
-			if (value < ATM_TXBQ_MIN) value = ATM_TXBQ_MIN;
-			if (value > ATM_TXBQ_MAX) value = ATM_TXBQ_MAX;
-			vcc->tx_quota = value;
-			return 0;
-		case SO_RCVBUF:
-			if (get_user(value,(unsigned long *) optval))
-				return -EFAULT;
-			if (!value) value = ATM_RXBQ_DEF;
-			if (value < ATM_RXBQ_MIN) value = ATM_RXBQ_MIN;
-			if (value > ATM_RXBQ_MAX) value = ATM_RXBQ_MAX;
-			vcc->rx_quota = value;
-			return 0;
 		case SO_ATMQOS:
 			{
 				struct atm_qos qos;
@@ -859,18 +776,6 @@
 
 	vcc = ATM_SD(sock);
 	switch (optname) {
-		case SO_SNDBUF:
-			return put_user(vcc->tx_quota,(unsigned long *) optval)
-			    ? -EFAULT : 0;
-		case SO_RCVBUF:
-			return put_user(vcc->rx_quota,(unsigned long *) optval)
-			    ? -EFAULT : 0;
-		case SO_BCTXOPT:
-			/* fall through */
-		case SO_BCRXOPT:
-			printk(KERN_WARNING "Warning: SO_BCTXOPT/SO_BCRXOPT "
-			   "are obsolete\n");
-			break;
 		case SO_ATMQOS:
 			if (!(vcc->flags & ATM_VF_HASQOS)) return -EINVAL;
 			return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ?
diff -u --recursive --new-file v2.3.42/linux/net/atm/lec.c linux/net/atm/lec.c
--- v2.3.42/linux/net/atm/lec.c	Fri Sep 10 23:57:38 1999
+++ linux/net/atm/lec.c	Tue Feb  8 18:23:13 2000
@@ -39,7 +39,6 @@
 
 #include "lec.h"
 #include "lec_arpc.h"
-#include "tunable.h"
 #include "resources.h"  /* for bind_vcc() */
 
 #if 0
@@ -60,7 +59,7 @@
 static int lec_send_packet(struct sk_buff *skb, struct net_device *dev);
 static int lec_close(struct net_device *dev);
 static struct net_device_stats *lec_get_stats(struct net_device *dev);
-static int lec_init(struct net_device *dev);
+static void lec_init(struct net_device *dev);
 static __inline__ struct lec_arp_table* lec_arp_find(struct lec_priv *priv,
                                                      unsigned char *mac_addr);
 static __inline__ int lec_arp_remove(struct lec_arp_table **lec_arp_tables,
@@ -79,9 +78,6 @@
 	NULL                  /* associate indicator, spec 3.1.5 */
 };
 
-/* will be lec0, lec1, lec2 etc. */
-static char myname[] = "lecxx";
-
 static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
 
 /* Device structures */
@@ -262,6 +258,17 @@
                 lec_h = (struct lecdatahdr_8023*)skb->data;
                 lec_h->le_header = htons(priv->lecid); 
 
+#ifdef CONFIG_TR
+                /* Ugly. Use this to realign Token Ring packets for
+                 * e.g. PCA-200E driver. */
+                if (priv->is_trdev) {
+                        skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN);
+                        kfree_skb(skb);
+                        if (skb2 == NULL) return 0;
+                        skb = skb2;
+                }
+#endif
+
 #if DUMP_PACKETS > 0
                 printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name,
                         skb->len, priv->lecid);
@@ -466,6 +473,7 @@
 		if (dev->change_mtu(dev, mesg->content.config.mtu))
 			printk("%s: change_mtu to %d failed\n", dev->name,
 			    mesg->content.config.mtu);
+		priv->is_proxy = mesg->content.config.is_proxy;
                 break;
         case l_flush_tran_id:
                 lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr,
@@ -540,24 +548,8 @@
 }
 
 static struct atmdev_ops lecdev_ops = {
-        NULL, /*dev_close*/
-        NULL, /*open*/
-        lec_atm_close, /*close*/
-        NULL, /*ioctl*/
-        NULL, /*getsockopt */
-        NULL, /*setsockopt */
-        lec_atm_send, /*send */
-        NULL, /*sg_send */
-#if 0   /* these are disabled in <linux/atmdev.h> too */
-        NULL, /*poll */
-        NULL, /*send_iovec*/
-#endif 
-        NULL, /*send_oam*/
-        NULL, /*phy_put*/
-        NULL, /*phy_get*/
-        NULL, /*feedback*/
-        NULL, /* change_qos*/
-        NULL  /* free_rx_skb*/
+        close:	lec_atm_close,
+        send:	lec_atm_send
 };
 
 static struct atm_dev lecatm_dev = {
@@ -626,17 +618,9 @@
         return 0;
 }
 
-static int 
+static void 
 lec_init(struct net_device *dev)
 {
-        struct lec_priv *priv;
-
-        priv = (struct lec_priv *)dev->priv;
-        if (priv->is_trdev) {
-#ifdef CONFIG_TR
-                init_trdev(dev, 0);
-#endif
-        } else ether_setup(dev);
         dev->change_mtu = lec_change_mtu;
         dev->open = lec_open;
         dev->stop = lec_close;
@@ -646,7 +630,7 @@
         dev->set_multicast_list = NULL;
         dev->do_ioctl  = NULL;
         printk("%s: Initialized!\n",dev->name);
-        return 0;
+        return;
 }
 
 static unsigned char lec_ctrl_magic[] = {
@@ -660,7 +644,6 @@
 {
         struct net_device *dev = (struct net_device *)vcc->proto_data;
         struct lec_priv *priv = (struct lec_priv *)dev->priv; 
-        struct lecdatahdr_8023 *hdr;
 
 #if DUMP_PACKETS >0
         int i=0;
@@ -696,9 +679,10 @@
                 skb_queue_tail(&vcc->recvq, skb);
                 wake_up(&vcc->sleep);
         } else { /* Data frame, queue to protocol handlers */
+                unsigned char *dst;
+
                 atm_return(vcc,skb->truesize);
-                hdr = (struct lecdatahdr_8023 *)skb->data;
-                if (hdr->le_header == htons(priv->lecid) ||
+                if (*(uint16_t *)skb->data == htons(priv->lecid) ||
                     !priv->lecd) { 
                         /* Probably looping back, or if lecd is missing,
                            lecd has gone down */
@@ -706,7 +690,19 @@
                         dev_kfree_skb(skb);
                         return;
                 }
-                if (priv->lec_arp_empty_ones) { /* FILTER DATA!!!! */
+#ifdef CONFIG_TR
+                if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
+                else
+#endif
+                dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
+
+                if (!(dst[0]&0x01) &&   /* Never filter Multi/Broadcast */
+                    !priv->is_proxy &&  /* Proxy wants all the packets */
+                    memcmp(dst, dev->dev_addr, sizeof(dev->dev_addr))) {
+                        dev_kfree_skb(skb);
+                        return;
+                }
+                if (priv->lec_arp_empty_ones) {
                         lec_arp_check_empties(priv, vcc, skb);
                 }
                 skb->dev = dev;
@@ -757,7 +753,7 @@
 int 
 lecd_attach(struct atm_vcc *vcc, int arg)
 {  
-        int i, result;
+        int i;
         struct lec_priv *priv;
 
         if (arg<0)
@@ -772,30 +768,28 @@
                 return -EINVAL;
 #endif
         if (!dev_lec[i]) {
-                dev_lec[i] = (struct net_device*)
-		    kmalloc(sizeof(struct net_device)+sizeof(myname)+1, 
-		    GFP_KERNEL);
-                if (!dev_lec[i])
-                        return -ENOMEM;
-                memset(dev_lec[i],0,sizeof(struct net_device)+sizeof(myname)+1);
-
-                dev_lec[i]->priv = kmalloc(sizeof(struct lec_priv), GFP_KERNEL);
-                if (!dev_lec[i]->priv)
-                        return -ENOMEM;
-                memset(dev_lec[i]->priv,0,sizeof(struct lec_priv));
-                priv = (struct lec_priv *)dev_lec[i]->priv;
+                int is_trdev, size;
 
+                is_trdev = 0;
                 if (i >= (MAX_LEC_ITF - NUM_TR_DEVS))
-                        priv->is_trdev = 1;
+                        is_trdev = 1;
 
-                dev_lec[i]->name = (char*)(dev_lec[i]+1);
-                sprintf(dev_lec[i]->name, "lec%d",i);
-                dev_lec[i]->init = lec_init;
-                if ((result = register_netdev(dev_lec[i])) !=0)
-                        return result;
-                sprintf(dev_lec[i]->name, "lec%d", i); /* init_trdev globbers device name */
+                size = sizeof(struct lec_priv);
+#ifdef CONFIG_TR
+                if (is_trdev)
+                        dev_lec[i] = init_trdev(NULL, size);
+                else
+#endif
+                dev_lec[i] = init_etherdev(NULL, size);
+                if (!dev_lec[i])
+                        return -ENOMEM;
+
+                priv = dev_lec[i]->priv;
+                priv->is_trdev = is_trdev;
+                sprintf(dev_lec[i]->name, "lec%d", i);
+                lec_init(dev_lec[i]);
         } else {
-                priv = (struct lec_priv *)dev_lec[i]->priv;
+                priv = dev_lec[i]->priv;
                 if (priv->lecd)
                         return -EADDRINUSE;
         }
@@ -874,7 +868,6 @@
 #endif
                         } else
                                 unregister_netdev(dev_lec[i]);
-                        kfree(dev_lec[i]->priv);
                         kfree(dev_lec[i]);
                         dev_lec[i] = NULL;
                 }
@@ -1535,7 +1528,7 @@
                 if (entry)
                         entry->next = to_remove->next;
         }
-        if (!entry)
+        if (!entry) {
                 if (to_remove == priv->lec_no_forward) {
                         priv->lec_no_forward = to_remove->next;
                 } else {
@@ -1545,6 +1538,7 @@
                         if (entry)
                                 entry->next = to_remove->next;
                 }
+	}
         lec_arp_clear_vccs(to_remove);
         kfree(to_remove);
 }
diff -u --recursive --new-file v2.3.42/linux/net/atm/mpc.c linux/net/atm/mpc.c
--- v2.3.42/linux/net/atm/mpc.c	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/mpc.c	Tue Feb  8 18:23:13 2000
@@ -27,7 +27,6 @@
 
 #include "lec.h"
 #include "mpc.h"
-#include "tunable.h"
 #include "resources.h"  /* for bind_vcc() */
 
 /*
@@ -326,7 +325,7 @@
         return;
 }
 
-static const char *mpoa_device_type_string (char type)
+static const char * __attribute__ ((unused)) mpoa_device_type_string(char type)
 {
         switch(type) {
         case NON_MPOA:
@@ -623,7 +622,8 @@
         dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
         in_entry = mpc->in_ops->search_by_vcc(vcc, mpc);
         if (in_entry) {
-                unsigned char *ip = (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
+                unsigned char *ip __attribute__ ((unused)) =
+		    (unsigned char *)&in_entry->ctrl_info.in_dst_ip;
 	        dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
                        mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
                 in_entry->shortcut = NULL;
@@ -726,21 +726,8 @@
 }
 
 static struct atmdev_ops mpc_ops = { /* only send is required */
-        NULL,           /* dev_close   */
-        NULL,           /* open        */
-        mpoad_close,    /* close       */
-        NULL,           /* ioctl       */
-        NULL,           /* getsockopt  */
-        NULL,           /* setsockopt  */
-        msg_from_mpoad, /* send        */
-        NULL,           /* sg_send     */
-        NULL,           /* send_oam    */
-        NULL,           /* phy_put     */
-        NULL,           /* phy_get     */
-        NULL,           /* feedback    */
-        NULL,           /* change_qos  */
-        NULL,           /* free_rx_skb */
-        NULL            /* proc_read   */
+        close:	mpoad_close,
+        send:	msg_from_mpoad
 };
 
 static struct atm_dev mpc_dev = {
@@ -1074,7 +1061,7 @@
  */
 static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry){
         uint32_t dst_ip = msg->content.in_info.in_dst_ip;
-        unsigned char *ip = (unsigned char *)&dst_ip;
+        unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
 	struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
 	eg_cache_entry *eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client);
 	if(eg_entry && eg_entry->shortcut){
diff -u --recursive --new-file v2.3.42/linux/net/atm/mpoa_caches.c linux/net/atm/mpoa_caches.c
--- v2.3.42/linux/net/atm/mpoa_caches.c	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/mpoa_caches.c	Tue Feb  8 18:23:13 2000
@@ -87,7 +87,7 @@
 					  struct mpoa_client *client)
 {
         unsigned long flags;
-        unsigned char *ip = (unsigned char *)&dst_ip;
+        unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
         in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
 
         if (entry == NULL) {
@@ -149,7 +149,8 @@
 
         if( entry->count > mpc->parameters.mpc_p1 &&
             entry->entry_state == INGRESS_INVALID){
-                unsigned char *ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
+                unsigned char *ip __attribute__ ((unused)) =
+		    (unsigned char *)&entry->ctrl_info.in_dst_ip;
 
 		dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
                 entry->entry_state = INGRESS_RESOLVING;
diff -u --recursive --new-file v2.3.42/linux/net/atm/mpoa_proc.c linux/net/atm/mpoa_proc.c
--- v2.3.42/linux/net/atm/mpoa_proc.c	Tue Nov 23 22:42:21 1999
+++ linux/net/atm/mpoa_proc.c	Wed Feb  9 11:42:36 2000
@@ -41,9 +41,8 @@
  *   Define allowed FILE OPERATIONS
  */
 static struct file_operations mpc_file_operations = {
-        NULL,                   /* lseek */
-        proc_mpc_read,          /* read */
-        proc_mpc_write,         /* write */
+	read:		proc_mpc_read,
+	write:		proc_mpc_write,
 };
 
 /*
@@ -143,7 +142,7 @@
 		while(eg_entry != NULL){
 		  for(i=0;i<ATM_ESA_LEN;i++){
 		          length += sprintf((char *)page + length,"%02x",eg_entry->ctrl_info.in_MPC_data_ATM_addr[i]);}  
-		        length += sprintf((char *)page + length,"\n%-16lu%s%-14lu%-15u",ntohl(eg_entry->ctrl_info.cache_id), egress_state_string(eg_entry->entry_state), (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), eg_entry->packets_rcvd);
+		        length += sprintf((char *)page + length,"\n%-16lu%s%-14lu%-15u",(unsigned long) ntohl(eg_entry->ctrl_info.cache_id), egress_state_string(eg_entry->entry_state), (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), eg_entry->packets_rcvd);
 			
 			/* latest IP address */
 			temp = (unsigned char *)&eg_entry->latest_ip_addr;
diff -u --recursive --new-file v2.3.42/linux/net/atm/proc.c linux/net/atm/proc.c
--- v2.3.42/linux/net/atm/proc.c	Tue Dec  7 09:32:52 1999
+++ linux/net/atm/proc.c	Wed Feb  9 11:42:36 2000
@@ -1,6 +1,6 @@
 /* net/atm/proc.c - ATM /proc interface */
 
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 /*
  * The mechanism used here isn't designed for speed but rather for convenience
@@ -56,13 +56,11 @@
     loff_t *pos);
 
 static struct file_operations proc_dev_atm_operations = {
-	NULL,			/* lseek */
-	proc_dev_atm_read,	/* read */
+	read:		proc_dev_atm_read,
 };
 
 static struct file_operations proc_spec_atm_operations = {
-	NULL,			/* lseek */
-	proc_spec_atm_read,	/* read */
+	read:		proc_spec_atm_read,
 };
 
 static struct inode_operations proc_dev_atm_inode_operations = {
@@ -73,10 +71,11 @@
 	&proc_spec_atm_operations,	/* default ATM directory file-ops */
 };
 
+
 static void add_stats(char *buf,const char *aal,
   const struct atm_aal_stats *stats)
 {
-	sprintf(strchr(buf,0),"%s ( %ld %ld %ld %ld %ld )",aal,stats->tx,
+	sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal,stats->tx,
 	    stats->tx_err,stats->rx,stats->rx_err,stats->rx_drop);
 }
 
@@ -112,7 +111,7 @@
 		len = strlen(addr->sas_addr.pub);
 		buf += len;
 		if (*addr->sas_addr.pub) {
-			*buf += '+';
+			*buf++ = '+';
 			len++;
 		}
 	}
@@ -209,12 +208,39 @@
 }
 
 
+static void vc_info(struct atm_vcc *vcc,char *buf)
+{
+	char *here;
+
+	here = buf+sprintf(buf,"%p ",vcc);
+	if (!vcc->dev) here += sprintf(here,"Unassigned    ");
+	else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,
+		    vcc->vci);
+	switch (vcc->family) {
+		case AF_ATMPVC:
+			here += sprintf(here,"PVC");
+			break;
+		case AF_ATMSVC:
+			here += sprintf(here,"SVC");
+			break;
+		default:
+			here += sprintf(here,"%3d",vcc->family);
+	}
+	here += sprintf(here," %04x  %5d %7d/%7d %7d/%7d\n",vcc->flags,
+	    vcc->reply,
+	    atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf,
+	    atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf);
+}
+
+
 static void svc_info(struct atm_vcc *vcc,char *buf)
 {
 	char *here;
 	int i;
 
-	if (!vcc->dev) sprintf(buf,"Unassigned    ");
+	if (!vcc->dev)
+		sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%6s" : "N/A@%p%2s",
+		    vcc,"");
 	else sprintf(buf,"%3d %3d %5d ",vcc->dev->number,vcc->vpi,vcc->vci);
 	here = strchr(buf,0);
 	here += sprintf(here,"%-10s ",vcc_state(vcc));
@@ -253,7 +279,6 @@
 lec_info(struct lec_arp_table *entry, char *buf)
 {
         int j, offset=0;
-        
 
         for(j=0;j<ETH_ALEN;j++) {
                 offset+=sprintf(buf+offset,"%2.2x",0xff&entry->mac_addr[j]);
@@ -322,6 +347,34 @@
 	return 0;
 }
 
+
+static int atm_vc_info(loff_t pos,char *buf)
+{
+	struct atm_dev *dev;
+	struct atm_vcc *vcc;
+	int left;
+
+	if (!pos)
+		return sprintf(buf,sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s",
+		    "Address"," Itf VPI VCI   Fam Flags Reply Send buffer"
+		    "     Recv buffer\n");
+	left = pos-1;
+	for (dev = atm_devs; dev; dev = dev->next)
+		for (vcc = dev->vccs; vcc; vcc = vcc->next)
+			if (!left--) {
+				vc_info(vcc,buf);
+				return strlen(buf);
+			}
+	for (vcc = nodev_vccs; vcc; vcc = vcc->next)
+		if (!left--) {
+			vc_info(vcc,buf);
+			return strlen(buf);
+		}
+
+	return 0;
+}
+
+
 static int atm_svc_info(loff_t pos,char *buf)
 {
 	struct atm_dev *dev;
@@ -388,6 +441,7 @@
 	struct lec_arp_table *entry;
 	int i, count, d, e;
 	struct net_device **dev_lec;
+
 	if (!pos) {
 		return sprintf(buf,"Itf  MAC          ATM destination"
 		    "                          Status            Flags "
@@ -449,7 +503,8 @@
 	if (count < 0) return -EINVAL;
 	page = get_free_page(GFP_KERNEL);
 	if (!page) return -ENOMEM;
-	dev = ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
+	dev = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
+	    ->data;
 	if (!dev->ops->proc_read)
 		length = -EINVAL;
 	else {
@@ -464,13 +519,15 @@
 	return length;
 }
 
+
 static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count,
     loff_t *pos)
 {
 	unsigned long page;
 	int length;
 	int (*info)(loff_t,char *);
-	info = ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
+	info = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip)
+	    ->data;
 
 	if (count < 0) return -EINVAL;
 	page = get_free_page(GFP_KERNEL);
@@ -485,9 +542,11 @@
 	return length;
 }
 
+
 struct proc_dir_entry *atm_proc_root;
 EXPORT_SYMBOL(atm_proc_root);
 
+
 int atm_proc_dev_register(struct atm_dev *dev)
 {
 	int digits,num;
@@ -520,48 +579,41 @@
 	kfree(dev->proc_name);
 }
 
+
+#define CREATE_ENTRY(name) \
+    name = create_proc_entry(#name,0,atm_proc_root); \
+    if (!name) goto cleanup; \
+    name->data = atm_##name##_info; \
+    name->ops = &proc_spec_atm_inode_operations
+
+
 int __init atm_proc_init(void)
 {
-	struct proc_dir_entry *dev=NULL,*pvc=NULL,*svc=NULL,*arp=NULL,*lec=NULL;
+	struct proc_dir_entry *devices = NULL,*pvc = NULL,*svc = NULL;
+	struct proc_dir_entry *arp = NULL,*lec = NULL,*vc = NULL;
+
 	atm_proc_root = proc_mkdir("atm", &proc_root);
 	if (!atm_proc_root)
 		return -ENOMEM;
-	dev = create_proc_entry("devices",0,atm_proc_root);
-	if (!dev)
-		goto cleanup;
-	dev->data = atm_devices_info;
-	dev->ops = &proc_spec_atm_inode_operations;
-	pvc = create_proc_entry("pvc",0,atm_proc_root);
-	if (!pvc)
-		goto cleanup;
-	pvc->data = atm_pvc_info;
-	pvc->ops = &proc_spec_atm_inode_operations;
-	svc = create_proc_entry("svc",0,atm_proc_root);
-	if (!svc)
-		goto cleanup;
-	svc->data = atm_svc_info;
-	svc->ops = &proc_spec_atm_inode_operations;
+	CREATE_ENTRY(devices);
+	CREATE_ENTRY(pvc);
+	CREATE_ENTRY(svc);
+	CREATE_ENTRY(vc);
 #ifdef CONFIG_ATM_CLIP
-	arp = create_proc_entry("arp",0,atm_proc_root);
-	if (!arp)
-		goto cleanup;
-	arp->data = atm_arp_info;
-	arp->ops = &proc_spec_atm_inode_operations;
+	CREATE_ENTRY(arp);
 #endif
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
-	lec = create_proc_entry("lec",0,atm_proc_root);
-	if (!lec)
-		goto cleanup;
-	lec->data = atm_lec_info;
-	lec->ops = &proc_spec_atm_inode_operations;
+	CREATE_ENTRY(lec);
 #endif
 	return 0;
+
 cleanup:
-	if (dev) remove_proc_entry("devices",atm_proc_root);
+	if (devices) remove_proc_entry("devices",atm_proc_root);
 	if (pvc) remove_proc_entry("pvc",atm_proc_root);
 	if (svc) remove_proc_entry("svc",atm_proc_root);
 	if (arp) remove_proc_entry("arp",atm_proc_root);
 	if (lec) remove_proc_entry("lec",atm_proc_root);
+	if (vc) remove_proc_entry("vc",atm_proc_root);
 	remove_proc_entry("atm",&proc_root);
 	return -ENOMEM;
 }
diff -u --recursive --new-file v2.3.42/linux/net/atm/raw.c linux/net/atm/raw.c
--- v2.3.42/linux/net/atm/raw.c	Fri Sep 10 23:57:38 1999
+++ linux/net/atm/raw.c	Tue Feb  8 18:50:03 2000
@@ -3,7 +3,6 @@
 /* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/atmdev.h>
@@ -11,14 +10,8 @@
 #include <linux/skbuff.h>
 #include <linux/mm.h>
 
-#ifdef CONFIG_MMU_HACKS
-#include <linux/mmuio.h>
-#include <linux/uio.h>
-#endif
-
 #include "common.h"
 #include "protocols.h"
-#include "tunable.h"		/* tunable parameters */
 
 
 #if 0
@@ -43,10 +36,6 @@
 
 static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
 {
-#ifdef CONFIG_MMU_HACKS
-	if (ATM_SKB(skb)->iovcnt)
-		unlock_user(ATM_SKB(skb)->iovcnt,(struct iovec *) skb->data);
-#endif
 	DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize);
 	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
 	dev_kfree_skb(skb);
diff -u --recursive --new-file v2.3.42/linux/net/atm/resources.c linux/net/atm/resources.c
--- v2.3.42/linux/net/atm/resources.c	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/resources.c	Tue Feb  8 18:23:13 2000
@@ -145,8 +145,10 @@
 		sk_free(sk);
 		return NULL;
 	}
+	sock_init_data(NULL,sk);
 	sk->destruct = atm_free_sock;
 	memset(vcc,0,sizeof(*vcc));
+	vcc->sk = sk;
 	if (nodev_vccs) nodev_vccs->prev = vcc;
 	vcc->prev = NULL;
 	vcc->next = nodev_vccs;
diff -u --recursive --new-file v2.3.42/linux/net/atm/signaling.c linux/net/atm/signaling.c
--- v2.3.42/linux/net/atm/signaling.c	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/signaling.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* net/atm/signaling.c - ATM signaling */
 
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/errno.h>	/* error codes */
@@ -13,7 +13,6 @@
 #include <linux/atmsvc.h>
 #include <linux/atmdev.h>
 
-#include "tunable.h"
 #include "resources.h"
 #include "signaling.h"
 
@@ -92,8 +91,9 @@
 
 	msg = (struct atmsvc_msg *) skb->data;
 	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
-	DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,msg->vcc);
-	vcc = (struct atm_vcc *) msg->vcc;
+	DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
+	  (unsigned long) msg->vcc);
+	vcc = *(struct atm_vcc **) &msg->vcc;
 	switch (msg->type) {
 		case as_okay:
 			vcc->reply = msg->reply;
@@ -118,7 +118,7 @@
 			vcc->reply = msg->reply;
 			break;
 		case as_indicate:
-			vcc = (struct atm_vcc *) msg->listen_vcc;
+			vcc = *(struct atm_vcc **) &msg->listen_vcc;
 			DPRINTK("as_indicate!!!\n");
 			if (!vcc->backlog_quota) {
 				sigd_enq(0,as_reject,vcc,NULL,NULL);
@@ -152,7 +152,7 @@
 
 
 void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
-    const struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
+    struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
     const struct sockaddr_atmsvc *svc)
 {
 	struct sk_buff *skb;
@@ -162,9 +162,10 @@
 	while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
 		schedule();
 	msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg));
+	memset(msg,0,sizeof(*msg));
 	msg->type = type;
-	msg->vcc = (unsigned long) vcc;
-	msg->listen_vcc = (unsigned long) listen_vcc;
+	*(struct atm_vcc **) &msg->vcc = vcc;
+	*(struct atm_vcc **) &msg->listen_vcc = listen_vcc;
 	msg->reply = 0; /* other ISP applications may use this field */
 	if (vcc) {
 		msg->qos = vcc->qos;
@@ -210,20 +211,8 @@
 
 
 static struct atmdev_ops sigd_dev_ops = {
-	NULL,		/* no dev_close */
-	NULL,		/* no open */
-	sigd_close,	/* close */
-	NULL,		/* no ioctl */
-	NULL,		/* no getsockopt */
-	NULL,		/* no setsockopt */
-	sigd_send,	/* send */
-	NULL,		/* no sg_send */
-	NULL,		/* no send_oam */
-	NULL,		/* no phy_put */
-	NULL,		/* no phy_get */
-	NULL,		/* no feedback */
-	NULL,		/* no change_qos */
-	NULL		/* no free_rx_skb */
+	close:	sigd_close,
+	send:	sigd_send
 };
 
 
diff -u --recursive --new-file v2.3.42/linux/net/atm/signaling.h linux/net/atm/signaling.h
--- v2.3.42/linux/net/atm/signaling.h	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/signaling.h	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* net/atm/signaling.h - ATM signaling */
  
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  
 
 #ifndef NET_ATM_SIGNALING_H
@@ -18,7 +18,7 @@
 
 
 void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
-    const struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
+    struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc,
     const struct sockaddr_atmsvc *svc);
 int sigd_attach(struct atm_vcc *vcc);
 void signaling_init(void);
diff -u --recursive --new-file v2.3.42/linux/net/atm/svc.c linux/net/atm/svc.c
--- v2.3.42/linux/net/atm/svc.c	Fri Sep 10 23:57:38 1999
+++ linux/net/atm/svc.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* net/atm/svc.c - ATM SVC sockets */
 
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/string.h>
@@ -253,6 +253,7 @@
 		new_vcc->qos = msg->qos;
 		new_vcc->flags |= ATM_VF_HASQOS;
 		new_vcc->remote = msg->svc;
+		new_vcc->local = msg->local;
 		new_vcc->sap = msg->sap;
 		error = atm_connect(newsock,msg->pvc.sap_addr.itf,
 		    msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci);
diff -u --recursive --new-file v2.3.42/linux/net/atm/tunable.h linux/net/atm/tunable.h
--- v2.3.42/linux/net/atm/tunable.h	Fri Sep 10 23:57:38 1999
+++ linux/net/atm/tunable.h	Wed Dec 31 16:00:00 1969
@@ -1,16 +0,0 @@
-/* net/atm/tunable.h - Tunable parameters of ATM support */
-
-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
-
-
-#ifndef NET_ATM_TUNABLE_H
-#define NET_ATM_TUNABLE_H
-
-#define ATM_RXBQ_DEF	(  64*1024)  /* default RX buffer quota, in bytes */
-#define ATM_TXBQ_DEF	(  64*1024)  /* default TX buffer quota, in bytes */
-#define ATM_RXBQ_MIN	(   1*1024)  /* RX buffer minimum, in bytes */
-#define ATM_TXBQ_MIN	(   1*1024)  /* TX buffer minimum, in bytes */
-#define ATM_RXBQ_MAX	(1024*1024)  /* RX buffer quota limit, in bytes */
-#define ATM_TXBQ_MAX	(1024*1024)  /* TX buffer quota limit, in bytes */
-
-#endif
diff -u --recursive --new-file v2.3.42/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.42/linux/net/core/dev.c	Wed Dec 29 13:13:21 1999
+++ linux/net/core/dev.c	Wed Feb  9 20:08:09 2000
@@ -95,9 +95,7 @@
 #endif
 
 NET_PROFILE_DEFINE(dev_queue_xmit)
-NET_PROFILE_DEFINE(net_bh)
-NET_PROFILE_DEFINE(net_bh_skb)
-
+NET_PROFILE_DEFINE(softnet_process)
 
 const char *if_port_text[] = {
   "unknown",
@@ -141,19 +139,15 @@
 
 /*
  *	Device drivers call our routines to queue packets here. We empty the
- *	queue in the bottom half handler.
+ *	queue in the local softnet handler.
  */
-
-static struct sk_buff_head backlog;
+struct softnet_data softnet_data[NR_CPUS] __cacheline_aligned;
 
 #ifdef CONFIG_NET_FASTROUTE
 int netdev_fastroute;
 int netdev_fastroute_obstacles;
-struct net_fastroute_stats dev_fastroute_stat;
 #endif
 
-static void dev_clear_backlog(struct net_device *dev);
-
 
 /******************************************************************************************
 
@@ -186,6 +180,9 @@
 void dev_add_pack(struct packet_type *pt)
 {
 	int hash;
+
+	write_lock_bh(&ptype_lock);
+
 #ifdef CONFIG_NET_FASTROUTE
 	/* Hack to detect packet socket */
 	if (pt->data) {
@@ -193,7 +190,6 @@
 		dev_clear_fastroute(pt->dev);
 	}
 #endif
-	write_lock_bh(&ptype_lock);
 	if(pt->type==htons(ETH_P_ALL))
 	{
 		netdev_nit++;
@@ -217,6 +213,9 @@
 void dev_remove_pack(struct packet_type *pt)
 {
 	struct packet_type **pt1;
+
+	write_lock_bh(&ptype_lock);
+
 	if(pt->type==htons(ETH_P_ALL))
 	{
 		netdev_nit--;
@@ -224,7 +223,7 @@
 	}
 	else
 		pt1=&ptype_base[ntohs(pt->type)&15];
-	write_lock_bh(&ptype_lock);
+
 	for(; (*pt1)!=NULL; pt1=&((*pt1)->next))
 	{
 		if(pt==(*pt1))
@@ -284,6 +283,9 @@
 /* 
    Return value is changed to int to prevent illegal usage in future.
    It is still legal to use to check for device existance.
+
+   User should understand, that the result returned by this function
+   is meaningless, if it was not issued under rtnl semaphore.
  */
 
 int dev_get(const char *name)
@@ -391,8 +393,10 @@
 
 void netdev_state_change(struct net_device *dev)
 {
-	if (dev->flags&IFF_UP)
+	if (dev->flags&IFF_UP) {
 		notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
+		rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
+	}
 }
 
 
@@ -450,17 +454,11 @@
 	if (ret == 0) 
 	{
 		/*
-		 *	nil rebuild_header routine,
-		 *	that should be never called and used as just bug trap.
-		 */
-
-		if (dev->rebuild_header == NULL)
-			dev->rebuild_header = default_rebuild_header;
-
-		/*
 		 *	Set the flags.
 		 */
-		dev->flags |= (IFF_UP | IFF_RUNNING);
+		dev->flags |= IFF_UP;
+
+		set_bit(LINK_STATE_START, &dev->state);
 
 		/*
 		 *	Initialize multicasting status 
@@ -476,7 +474,6 @@
 		 *	... and announce new interface.
 		 */
 		notifier_call_chain(&netdev_chain, NETDEV_UP, dev);
-
 	}
 	return(ret);
 }
@@ -523,8 +520,16 @@
 	if (!(dev->flags&IFF_UP))
 		return 0;
 
+	/*
+	 *	Tell people we are going down, so that they can
+	 *	prepare to death, when device is still operating.
+	 */
+	notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev);
+
 	dev_deactivate(dev);
 
+	clear_bit(LINK_STATE_START, &dev->state);
+
 	/*
 	 *	Call the device specific close. This cannot fail.
 	 *	Only if device is UP
@@ -533,21 +538,17 @@
 	if (dev->stop)
 		dev->stop(dev);
 
-	if (dev->start)
-		printk("dev_close: bug %s still running\n", dev->name);
-
 	/*
 	 *	Device is now down.
 	 */
-	dev_clear_backlog(dev);
 
-	dev->flags&=~(IFF_UP|IFF_RUNNING);
+	dev->flags &= ~IFF_UP;
 #ifdef CONFIG_NET_FASTROUTE
 	dev_clear_fastroute(dev);
 #endif
 
 	/*
-	 *	Tell people we are going down
+	 *	Tell people we are down
 	 */
 	notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
 
@@ -647,12 +648,7 @@
 	if (q->enqueue) {
 		int ret = q->enqueue(skb, q);
 
-		/* If the device is not busy, kick it.
-		 * Otherwise or if queue is not empty after kick,
-		 * add it to run list.
-		 */
-		if (dev->tbusy || __qdisc_wakeup(dev))
-			qdisc_run(q);
+		qdisc_run(dev);
 
 		spin_unlock_bh(&dev->queue_lock);
 		return ret;
@@ -670,17 +666,22 @@
 	   Either shot noqueue qdisc, it is even simpler 8)
 	 */
 	if (dev->flags&IFF_UP) {
-		if (dev->xmit_lock_owner != smp_processor_id()) {
+		int cpu = smp_processor_id();
+
+		if (dev->xmit_lock_owner != cpu) {
 			spin_unlock(&dev->queue_lock);
 			spin_lock(&dev->xmit_lock);
-			dev->xmit_lock_owner = smp_processor_id();
+			dev->xmit_lock_owner = cpu;
 
-			if (netdev_nit)
-				dev_queue_xmit_nit(skb,dev);
-			if (dev->hard_start_xmit(skb, dev) == 0) {
-				dev->xmit_lock_owner = -1;
-				spin_unlock_bh(&dev->xmit_lock);
-				return 0;
+			if (!test_bit(LINK_STATE_XOFF, &dev->state)) {
+				if (netdev_nit)
+					dev_queue_xmit_nit(skb,dev);
+
+				if (dev->hard_start_xmit(skb, dev) == 0) {
+					dev->xmit_lock_owner = -1;
+					spin_unlock_bh(&dev->xmit_lock);
+					return 0;
+				}
 			}
 			dev->xmit_lock_owner = -1;
 			spin_unlock_bh(&dev->xmit_lock);
@@ -705,12 +706,13 @@
 			Receiver rotutines
   =======================================================================*/
 
-int netdev_dropping = 0;
 int netdev_max_backlog = 300;
-atomic_t netdev_rx_dropped;
+
+struct netif_rx_stats netdev_rx_stat[NR_CPUS];
+
 
 #ifdef CONFIG_NET_HW_FLOWCONTROL
-int netdev_throttle_events;
+static atomic_t netdev_dropping = ATOMIC_INIT(0);
 static unsigned long netdev_fc_mask = 1;
 unsigned long netdev_fc_xoff = 0;
 spinlock_t netdev_fc_lock = SPIN_LOCK_UNLOCKED;
@@ -756,59 +758,18 @@
 {
 	unsigned long xoff;
 
-	spin_lock_irq(&netdev_fc_lock);
+	spin_lock(&netdev_fc_lock);
 	xoff = netdev_fc_xoff;
 	netdev_fc_xoff = 0;
-	netdev_dropping = 0;
-	netdev_throttle_events++;
 	while (xoff) {
 		int i = ffz(~xoff);
 		xoff &= ~(1<<i);
 		netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);
 	}
-	spin_unlock_irq(&netdev_fc_lock);
+	spin_unlock(&netdev_fc_lock);
 }
 #endif
 
-static void dev_clear_backlog(struct net_device *dev)
-{
-	struct sk_buff_head garbage;
-
-	/*
-	 *
-	 *  Let now clear backlog queue. -AS
-	 *
-	 */
-
-	skb_queue_head_init(&garbage);
-
-	spin_lock_irq(&backlog.lock);
-	if (backlog.qlen) {
-		struct sk_buff *prev, *curr;
-		curr = backlog.next;
-
-		while (curr != (struct sk_buff *)(&backlog)) {
-			curr=curr->next;
-			if (curr->prev->dev == dev) {
-				prev = curr->prev;
-				__skb_unlink(prev, &backlog);
-				__skb_queue_tail(&garbage, prev);
-			}
-		}
-	}
-	spin_unlock_irq(&backlog.lock);
-
-	if (garbage.qlen) {
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-		if (netdev_dropping)
-			netdev_wakeup();
-#else
-		netdev_dropping = 0;
-#endif
-		skb_queue_purge(&garbage);
-	}
-}
-
 /*
  *	Receive a packet from a device driver and queue it for the upper
  *	(protocol) levels.  It always succeeds. 
@@ -816,44 +777,59 @@
 
 void netif_rx(struct sk_buff *skb)
 {
+	int this_cpu = smp_processor_id();
+	struct softnet_data *queue;
+	unsigned long flags;
+
 	if(skb->stamp.tv_sec==0)
 		get_fast_time(&skb->stamp);
 
 	/* The code is rearranged so that the path is the most
 	   short when CPU is congested, but is still operating.
 	 */
+	queue = &softnet_data[this_cpu];
 
-	if (backlog.qlen <= netdev_max_backlog) {
-		if (backlog.qlen) {
-			if (netdev_dropping == 0) {
-				if (skb->rx_dev)
-					dev_put(skb->rx_dev);
-				skb->rx_dev = skb->dev;
-				dev_hold(skb->rx_dev);
-				skb_queue_tail(&backlog,skb);
-				mark_bh(NET_BH);
-				return;
-			}
-			atomic_inc(&netdev_rx_dropped);
-			kfree_skb(skb);
+	local_irq_save(flags);
+
+	netdev_rx_stat[this_cpu].total++;
+	if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
+		if (queue->input_pkt_queue.qlen) {
+			if (queue->throttle)
+				goto drop;
+
+enqueue:
+			if (skb->rx_dev)
+				dev_put(skb->rx_dev);
+			skb->rx_dev = skb->dev;
+			dev_hold(skb->rx_dev);
+			__skb_queue_tail(&queue->input_pkt_queue,skb);
+			__cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ);
+			local_irq_restore(flags);
 			return;
 		}
+
+		if (queue->throttle) {
+			queue->throttle = 0;
 #ifdef CONFIG_NET_HW_FLOWCONTROL
-		if (netdev_dropping)
-			netdev_wakeup();
-#else
-		netdev_dropping = 0;
+			if (atomic_dec_and_test(&netdev_dropping))
+				netdev_wakeup();
 #endif
-		if (skb->rx_dev)
-			dev_put(skb->rx_dev);
-		skb->rx_dev = skb->dev;
-		dev_hold(skb->rx_dev);
-		skb_queue_tail(&backlog,skb);
-		mark_bh(NET_BH);
-		return;
+		}
+		goto enqueue;
 	}
-	netdev_dropping = 1;
-	atomic_inc(&netdev_rx_dropped);
+
+	if (queue->throttle == 0) {
+		queue->throttle = 1;
+		netdev_rx_stat[this_cpu].throttled++;
+#ifdef CONFIG_NET_HW_FLOWCONTROL
+		atomic_inc(&netdev_dropping);
+#endif
+	}
+
+drop:
+	netdev_rx_stat[this_cpu].dropped++;
+	local_irq_restore(flags);
+
 	kfree_skb(skb);
 }
 
@@ -888,195 +864,199 @@
 }
 #endif
 
-/*
- *	When we are called the queue is ready to grab, the interrupts are
- *	on and hardware can interrupt and queue to the receive queue as we
- *	run with no problems.
- *	This is run as a bottom half after an interrupt handler that does
- *	mark_bh(NET_BH);
+/* Deliver skb to an old protocol, which is not threaded well
+   or which do not understand shared skbs.
  */
- 
-void net_bh(void)
+static void deliver_to_old_ones(struct packet_type *pt, struct sk_buff *skb, int last)
 {
-	struct packet_type *ptype;
-	struct packet_type *pt_prev;
-	unsigned short type;
-	unsigned long start_time = jiffies;
+	static spinlock_t net_bh_lock = SPIN_LOCK_UNLOCKED;
 
-	NET_PROFILE_ENTER(net_bh);
-	/*
-	 *	Can we send anything now? We want to clear the
-	 *	decks for any more sends that get done as we
-	 *	process the input. This also minimises the
-	 *	latency on a transmit interrupt bh.
+	if (!last) {
+		skb = skb_clone(skb, GFP_ATOMIC);
+		if (skb == NULL)
+			return;
+	}
+
+	/* The assumption (correct one) is that old protocols
+	   did not depened on BHs different of NET_BH and TIMER_BH.
 	 */
 
-	if (qdisc_pending())
-		qdisc_run_queues();
+	/* Emulate NET_BH with special spinlock */
+	spin_lock(&net_bh_lock);
 
-	/*
-	 *	Any data left to process. This may occur because a
-	 *	mark_bh() is done after we empty the queue including
-	 *	that from the device which does a mark_bh() just after
-	 */
+	/* Disable timers and wait for all timers completion */
+	tasklet_disable(bh_task_vec+TIMER_BH);
 
-	/*
-	 *	While the queue is not empty..
-	 *
-	 *	Note that the queue never shrinks due to
-	 *	an interrupt, so we can do this test without
-	 *	disabling interrupts.
-	 */
+	pt->func(skb, skb->dev, pt);
 
-	while (!skb_queue_empty(&backlog)) 
-	{
-		struct sk_buff * skb;
+	tasklet_enable(bh_task_vec+TIMER_BH);
+	spin_unlock(&net_bh_lock);
+}
 
-		/* Give chance to other bottom halves to run */
-		if (jiffies - start_time > 1)
-			goto net_bh_break;
+/* Reparent skb to master device. This function is called
+ * only from net_rx_action under ptype_lock. It is misuse
+ * of ptype_lock, but it is OK for now.
+ */
+static __inline__ void skb_bond(struct sk_buff *skb)
+{
+	struct net_device *dev = skb->rx_dev;
+	
+	if (dev->master) {
+		dev_hold(dev->master);
+		skb->dev = skb->rx_dev = dev->master;
+		dev_put(dev);
+	}
+}
 
-		/*
-		 *	We have a packet. Therefore the queue has shrunk
-		 */
-		skb = skb_dequeue(&backlog);
+static void net_tx_action(struct softirq_action *h)
+{
+	int cpu = smp_processor_id();
+	unsigned long flags;
 
-#ifdef CONFIG_NET_FASTROUTE
-		if (skb->pkt_type == PACKET_FASTROUTE) {
-			dev_queue_xmit(skb);
-			continue;
-		}
-#endif
+	if (softnet_data[cpu].completion_queue) {
+		struct sk_buff *clist;
 
-		/*
-	 	 *	Bump the pointer to the next structure.
-		 * 
-		 *	On entry to the protocol layer. skb->data and
-		 *	skb->nh.raw point to the MAC and encapsulated data
-		 */
+		local_irq_save(flags);
+		clist = softnet_data[cpu].completion_queue;
+		softnet_data[cpu].completion_queue = NULL;
+		local_irq_restore(flags);
+
+		while (clist != NULL) {
+			struct sk_buff *skb = clist;
+			clist = clist->next;
 
-		/* XXX until we figure out every place to modify.. */
-		skb->h.raw = skb->nh.raw = skb->data;
+			BUG_TRAP(atomic_read(&skb->users) == 0);
+			__kfree_skb(skb);
+		}
+	}
 
-		if (skb->mac.raw < skb->head || skb->mac.raw > skb->data) {
-			printk(KERN_CRIT "%s: wrong mac.raw ptr, proto=%04x\n", skb->dev->name, skb->protocol);
-			kfree_skb(skb);
-			continue;
+	if (softnet_data[cpu].output_queue) {
+		struct net_device *head;
+
+		local_irq_save(flags);
+		head = softnet_data[cpu].output_queue;
+		softnet_data[cpu].output_queue = NULL;
+		local_irq_restore(flags);
+
+		while (head != NULL) {
+			struct net_device *dev = head;
+			head = head->next_sched;
+
+			clear_bit(LINK_STATE_SCHED, &dev->state);
+
+			if (spin_trylock(&dev->queue_lock)) {
+				qdisc_run(dev);
+				spin_unlock(&dev->queue_lock);
+			} else {
+				netif_schedule(dev);
+			}
 		}
+	}
+}
 
-		/*
-		 * 	Fetch the packet protocol ID. 
-		 */
+static void net_rx_action(struct softirq_action *h)
+{
+	int this_cpu = smp_processor_id();
+	struct softnet_data *queue = &softnet_data[this_cpu];
+	unsigned long start_time = jiffies;
+	int bugdet = netdev_max_backlog;
 
-		type = skb->protocol;
+	read_lock(&ptype_lock);
 
-#ifdef CONFIG_BRIDGE
-		/*
-		 *	If we are bridging then pass the frame up to the
-		 *	bridging code (if this protocol is to be bridged).
-		 *      If it is bridged then move on
-		 */
-		handle_bridge(skb, type); 
-#endif
+	for (;;) {
+		struct sk_buff *skb;
 
-		/*
-		 *	We got a packet ID.  Now loop over the "known protocols"
-		 * 	list. There are two lists. The ptype_all list of taps (normally empty)
-		 *	and the main protocol list which is hashed perfectly for normal protocols.
-		 */
+		local_irq_disable();
+		skb = __skb_dequeue(&queue->input_pkt_queue);
+		local_irq_enable();
+
+		if (skb == NULL)
+			break;
 
-		pt_prev = NULL;
-		read_lock(&ptype_lock);
-		for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
+		skb_bond(skb);
+
+#ifdef CONFIG_NET_FASTROUTE
+		if (skb->pkt_type == PACKET_FASTROUTE) {
+			netdev_rx_stat[this_cpu].fastroute_deferred_out++;
+			dev_queue_xmit(skb);
+			continue;
+		}
+#endif
+		skb->h.raw = skb->nh.raw = skb->data;
 		{
-			if (!ptype->dev || ptype->dev == skb->dev) {
-				if(pt_prev)
-				{
-					struct sk_buff *skb2;
-					if (pt_prev->data == NULL)
-						skb2 = skb_clone(skb, GFP_ATOMIC);
-					else {
-						skb2 = skb;
-						atomic_inc(&skb2->users);
+			struct packet_type *ptype, *pt_prev;
+			unsigned short type = skb->protocol;
+#ifdef CONFIG_BRIDGE
+			handle_bridge(skb, type);
+#endif
+			pt_prev = NULL;
+			for (ptype = ptype_all; ptype; ptype = ptype->next) {
+				if (!ptype->dev || ptype->dev == skb->dev) {
+					if (pt_prev) {
+						if (!pt_prev->data) {
+							deliver_to_old_ones(pt_prev, skb, 0);
+						} else {
+							atomic_inc(&skb->users);
+							pt_prev->func(skb,
+								      skb->dev,
+								      pt_prev);
+						}
 					}
-					if(skb2)
-						pt_prev->func(skb2, skb->dev, pt_prev);
+					pt_prev = ptype;
 				}
-				pt_prev=ptype;
 			}
-		}
-
-		for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next) 
-		{
-			if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
-			{
-				/*
-				 *	We already have a match queued. Deliver
-				 *	to it and then remember the new match
-				 */
-				if(pt_prev)
-				{
-					struct sk_buff *skb2;
-
-					if (pt_prev->data == NULL)
-						skb2 = skb_clone(skb, GFP_ATOMIC);
-					else {
-						skb2 = skb;
-						atomic_inc(&skb2->users);
+			for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) {
+				if (ptype->type == type &&
+				    (!ptype->dev || ptype->dev == skb->dev)) {
+					if (pt_prev) {
+						if (!pt_prev->data)
+							deliver_to_old_ones(pt_prev, skb, 0);
+						else {
+							atomic_inc(&skb->users);
+							pt_prev->func(skb,
+								      skb->dev,
+								      pt_prev);
+						}
 					}
-
-					/*
-					 *	Kick the protocol handler. This should be fast
-					 *	and efficient code.
-					 */
-
-					if(skb2)
-						pt_prev->func(skb2, skb->dev, pt_prev);
+					pt_prev = ptype;
 				}
-				/* Remember the current last to do */
-				pt_prev=ptype;
 			}
-		} /* End of protocol list loop */
-
-		/*
-		 *	Is there a last item to send to ?
-		 */
-
-		if(pt_prev)
-			pt_prev->func(skb, skb->dev, pt_prev);
-		/*
-		 * 	Has an unknown packet has been received ?
-		 */
-	 
-		else {
-			kfree_skb(skb);
+			if (pt_prev) {
+				if (!pt_prev->data)
+					deliver_to_old_ones(pt_prev, skb, 1);
+				else
+					pt_prev->func(skb, skb->dev, pt_prev);
+			} else
+				kfree_skb(skb);
 		}
-		read_unlock(&ptype_lock);
-  	}	/* End of queue loop */
-
-  	/*
-  	 *	We have emptied the queue
-  	 */
-	
-	/*
-	 *	One last output flush.
-	 */
 
-	if (qdisc_pending())
-		qdisc_run_queues();
+		if (bugdet-- < 0 || jiffies - start_time > 1)
+			goto softnet_break;
+	}
+	read_unlock(&ptype_lock);
 
+	local_irq_disable();
+	if (queue->throttle) {
+		queue->throttle = 0;
 #ifdef CONFIG_NET_HW_FLOWCONTROL
-	if (netdev_dropping)
-		netdev_wakeup();
-#else
-	netdev_dropping = 0;
+		if (atomic_dec_and_test(&netdev_dropping))
+			netdev_wakeup();
 #endif
-	NET_PROFILE_LEAVE(net_bh);
+	}
+	local_irq_enable();
+
+	NET_PROFILE_LEAVE(softnet_process);
 	return;
 
-net_bh_break:
-	mark_bh(NET_BH);
-	NET_PROFILE_LEAVE(net_bh);
+softnet_break:
+	read_unlock(&ptype_lock);
+
+	local_irq_disable();
+	netdev_rx_stat[this_cpu].time_squeeze++;
+	__cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ);
+	local_irq_enable();
+
+	NET_PROFILE_LEAVE(softnet_process);
 	return;
 }
 
@@ -1276,23 +1256,26 @@
 static int dev_proc_stats(char *buffer, char **start, off_t offset,
 			  int length, int *eof, void *data)
 {
-	int len;
+	int i;
+	int len=0;
 
-	len = sprintf(buffer, "%08x %08x %08x %08x %08x\n",
-		      atomic_read(&netdev_rx_dropped),
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-		      netdev_throttle_events,
-#else
-		      0,
-#endif
-#ifdef CONFIG_NET_FASTROUTE
-		      dev_fastroute_stat.hits,
-		      dev_fastroute_stat.succeed,
-		      dev_fastroute_stat.deferred
+	for (i=0; i<smp_num_cpus; i++) {
+		len += sprintf(buffer+len, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+			       netdev_rx_stat[i].total,
+			       netdev_rx_stat[i].dropped,
+			       netdev_rx_stat[i].time_squeeze,
+			       netdev_rx_stat[i].throttled,
+			       netdev_rx_stat[i].fastroute_hit,
+			       netdev_rx_stat[i].fastroute_success,
+			       netdev_rx_stat[i].fastroute_defer,
+			       netdev_rx_stat[i].fastroute_deferred_out,
+#if 0
+			       netdev_rx_stat[i].fastroute_latency_reduction
 #else
-		      0, 0, 0
+			       netdev_rx_stat[i].cpu_collision
 #endif
-		      );
+			       );
+	}
 
 	len -= offset;
 
@@ -1397,6 +1380,34 @@
 #endif	/* CONFIG_PROC_FS */
 #endif	/* WIRELESS_EXT */
 
+int netdev_set_master(struct net_device *slave, struct net_device *master)
+{
+	struct net_device *old = slave->master;
+
+	ASSERT_RTNL();
+
+	if (master) {
+		if (old)
+			return -EBUSY;
+		dev_hold(master);
+	}
+
+	write_lock_bh(&ptype_lock);
+	slave->master = master;
+	write_unlock_bh(&ptype_lock);
+
+	if (old)
+		dev_put(old);
+
+	if (master)
+		slave->flags |= IFF_SLAVE;
+	else
+		slave->flags &= ~IFF_SLAVE;
+
+	rtmsg_ifinfo(RTM_NEWLINK, slave, IFF_SLAVE);
+	return 0;
+}
+
 void dev_set_promiscuity(struct net_device *dev, int inc)
 {
 	unsigned short old_flags = dev->flags;
@@ -1438,8 +1449,7 @@
 	 *	Set the flags on our device.
 	 */
 
-	dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_RUNNING|IFF_NOARP|
-			       IFF_SLAVE|IFF_MASTER|IFF_DYNAMIC|
+	dev->flags = (flags & (IFF_DEBUG|IFF_NOTRAILERS|IFF_NOARP|IFF_DYNAMIC|
 			       IFF_MULTICAST|IFF_PORTSEL|IFF_AUTOMEDIA)) |
 				       (dev->flags & (IFF_UP|IFF_VOLATILE|IFF_PROMISC|IFF_ALLMULTI));
 
@@ -1465,7 +1475,7 @@
 	}
 
 	if (dev->flags&IFF_UP &&
-	    ((old_flags^dev->flags)&~(IFF_UP|IFF_RUNNING|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))
+	    ((old_flags^dev->flags)&~(IFF_UP|IFF_PROMISC|IFF_ALLMULTI|IFF_VOLATILE)))
 		notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev);
 
 	if ((flags^dev->gflags)&IFF_PROMISC) {
@@ -1484,6 +1494,9 @@
 		dev_set_allmulti(dev, inc);
 	}
 
+	if (old_flags^dev->flags)
+		rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags^dev->flags);
+
 	return ret;
 }
 
@@ -1502,8 +1515,10 @@
 	switch(cmd) 
 	{
 		case SIOCGIFFLAGS:	/* Get interface flags */
-			ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
+			ifr->ifr_flags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI|IFF_RUNNING))
 				|(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI));
+			if (!test_bit(LINK_STATE_DOWN, &dev->state))
+				ifr->ifr_flags |= IFF_RUNNING;
 			return 0;
 
 		case SIOCSIFFLAGS:	/* Set interface flags */
@@ -1936,6 +1951,9 @@
 	if (dev->uninit)
 		dev->uninit(dev);
 
+	/* Notifier chain MUST detach us from master device. */
+	BUG_TRAP(dev->master==NULL);
+
 	if (dev->new_style) {
 #ifdef NET_REFCNT_DEBUG
 		if (atomic_read(&dev->refcnt) != 1)
@@ -2012,16 +2030,24 @@
 int __init net_dev_init(void)
 {
 	struct net_device *dev, **dp;
+	int i;
 
 #ifdef CONFIG_NET_SCHED
 	pktsched_init();
 #endif
 
 	/*
-	 *	Initialise the packet receive queue.
+	 *	Initialise the packet receive queues.
 	 */
-	 
-	skb_queue_head_init(&backlog);
+
+	for (i = 0; i < NR_CPUS; i++) {
+		struct softnet_data *queue;
+
+		queue = &softnet_data[i];
+		skb_queue_head_init(&queue->input_pkt_queue);
+		queue->throttle = 0;
+		queue->completion_queue = NULL;
+	}
 	
 	/*
 	 *	The bridge has to be up before the devices
@@ -2035,10 +2061,7 @@
 #ifdef CONFIG_NET_PROFILE
 	net_profile_init();
 	NET_PROFILE_REGISTER(dev_queue_xmit);
-	NET_PROFILE_REGISTER(net_bh);
-#if 0
-	NET_PROFILE_REGISTER(net_bh_skb);
-#endif
+	NET_PROFILE_REGISTER(softnet_process);
 #endif
 	/*
 	 *	Add the devices.
@@ -2054,6 +2077,9 @@
 	while ((dev = *dp) != NULL) {
 		spin_lock_init(&dev->queue_lock);
 		spin_lock_init(&dev->xmit_lock);
+#ifdef CONFIG_NET_FASTROUTE
+		dev->fastpath_lock = RW_LOCK_UNLOCKED;
+#endif
 		dev->xmit_lock_owner = -1;
 		dev->iflink = -1;
 		dev_hold(dev);
@@ -2085,15 +2111,16 @@
 
 #ifdef CONFIG_PROC_FS
 	proc_net_create("dev", 0, dev_get_info);
-	create_proc_read_entry("net/dev_stat", 0, 0, dev_proc_stats, NULL);
+	create_proc_read_entry("net/softnet_stat", 0, 0, dev_proc_stats, NULL);
 #ifdef WIRELESS_EXT
 	proc_net_create("wireless", 0, dev_get_wireless_info);
 #endif	/* WIRELESS_EXT */
 #endif	/* CONFIG_PROC_FS */
 
-	init_bh(NET_BH, net_bh);
-
 	dev_boot_phase = 0;
+
+	open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
+	open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
 
 	dst_init();
 	dev_mcast_init();
diff -u --recursive --new-file v2.3.42/linux/net/core/neighbour.c linux/net/core/neighbour.c
--- v2.3.42/linux/net/core/neighbour.c	Tue Dec  7 09:32:52 1999
+++ linux/net/core/neighbour.c	Wed Feb  9 20:08:09 2000
@@ -209,10 +209,11 @@
 		}
 	}
 
-	del_timer(&tbl->proxy_timer);
 	skb_queue_purge(&tbl->proxy_queue);
 	pneigh_ifdown(tbl, dev);
 	write_unlock_bh(&tbl->lock);
+
+	del_timer_sync(&tbl->proxy_timer);
 	return 0;
 }
 
@@ -533,7 +534,7 @@
 	}
 }
 
-static void neigh_periodic_timer(unsigned long arg)
+static void SMP_TIMER_NAME(neigh_periodic_timer)(unsigned long arg)
 {
 	struct neigh_table *tbl = (struct neigh_table*)arg;
 	unsigned long now = jiffies;
@@ -592,11 +593,21 @@
 		}
 	}
 
-	tbl->gc_timer.expires = now + tbl->gc_interval;
-	add_timer(&tbl->gc_timer);
+	mod_timer(&tbl->gc_timer, now + tbl->gc_interval);
 	write_unlock(&tbl->lock);
 }
 
+#ifdef __SMP__
+static void neigh_periodic_timer(unsigned long arg)
+{
+	struct neigh_table *tbl = (struct neigh_table*)arg;
+	
+	tasklet_schedule(&tbl->gc_task);
+
+	timer_exit(&tbl->gc_timer);
+}
+#endif
+
 static __inline__ int neigh_max_probes(struct neighbour *n)
 {
 	struct neigh_parms *p = n->parms;
@@ -665,6 +676,7 @@
 
 	neigh->ops->solicit(neigh, skb_peek(&neigh->arp_queue));
 	atomic_inc(&neigh->probes);
+	timer_exit(&neigh->timer);
 	return;
 
 out:
@@ -673,6 +685,7 @@
 	if (notify && neigh->parms->app_probes)
 		neigh_app_notify(neigh);
 #endif
+	timer_exit(&neigh->timer);
 	neigh_release(neigh);
 }
 
@@ -1008,6 +1021,7 @@
 		tbl->proxy_timer.expires = jiffies + sched_next;
 		add_timer(&tbl->proxy_timer);
 	}
+	timer_exit(&tbl->proxy_timer);
 }
 
 void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
@@ -1092,6 +1106,9 @@
 						     0, SLAB_HWCACHE_ALIGN,
 						     NULL, NULL);
 
+#ifdef __SMP__
+	tasklet_init(&tbl->gc_task, SMP_TIMER_NAME(neigh_periodic_timer), (unsigned long)tbl);
+#endif
 	init_timer(&tbl->gc_timer);
 	tbl->lock = RW_LOCK_UNLOCKED;
 	tbl->gc_timer.data = (unsigned long)tbl;
@@ -1116,8 +1133,10 @@
 {
 	struct neigh_table **tp;
 
-	del_timer(&tbl->gc_timer);
-	del_timer(&tbl->proxy_timer);
+	/* It is not clean... Fix it to unload IPv6 module safely */
+	del_timer_sync(&tbl->gc_timer);
+	tasklet_kill(&tbl->gc_task);
+	del_timer_sync(&tbl->proxy_timer);
 	skb_queue_purge(&tbl->proxy_queue);
 	neigh_ifdown(tbl, NULL);
 	if (tbl->entries)
diff -u --recursive --new-file v2.3.42/linux/net/core/rtnetlink.c linux/net/core/rtnetlink.c
--- v2.3.42/linux/net/core/rtnetlink.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/rtnetlink.c	Wed Feb  9 20:08:09 2000
@@ -171,6 +171,11 @@
 	r->ifi_flags = dev->flags;
 	r->ifi_change = change;
 
+	if (test_bit(LINK_STATE_DOWN, &dev->state))
+		r->ifi_flags &= ~IFF_RUNNING;
+	else
+		r->ifi_flags |= IFF_RUNNING;
+
 	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
 	if (dev->addr_len) {
 		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
@@ -186,6 +191,8 @@
 		RTA_PUT(skb, IFLA_QDISC,
 			strlen(dev->qdisc_sleeping->ops->id) + 1,
 			dev->qdisc_sleeping->ops->id);
+	if (dev->master)
+		RTA_PUT(skb, IFLA_MASTER, sizeof(int), &dev->master->ifindex);
 	if (dev->get_stats) {
 		struct net_device_stats *stats = dev->get_stats(dev);
 		if (stats)
@@ -243,7 +250,7 @@
 	return skb->len;
 }
 
-void rtmsg_ifinfo(int type, struct net_device *dev)
+void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
 {
 	struct sk_buff *skb;
 	int size = NLMSG_GOODSIZE;
@@ -252,7 +259,7 @@
 	if (!skb)
 		return;
 
-	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, ~0U) < 0) {
+	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change) < 0) {
 		kfree_skb(skb);
 		return;
 	}
@@ -488,10 +495,20 @@
 	struct net_device *dev = ptr;
 	switch (event) {
 	case NETDEV_UNREGISTER:
-		rtmsg_ifinfo(RTM_DELLINK, dev);
+		rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
+		break;
+	case NETDEV_REGISTER:
+		rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
+		break;
+	case NETDEV_UP:
+	case NETDEV_DOWN:
+		rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
+		break;
+	case NETDEV_CHANGE:
+	case NETDEV_GOING_DOWN:
 		break;
 	default:
-		rtmsg_ifinfo(RTM_NEWLINK, dev);
+		rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
 		break;
 	}
 	return NOTIFY_DONE;
diff -u --recursive --new-file v2.3.42/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.3.42/linux/net/core/skbuff.c	Fri Jan 28 15:09:09 2000
+++ linux/net/core/skbuff.c	Wed Feb  9 20:08:09 2000
@@ -4,7 +4,7 @@
  *	Authors:	Alan Cox <iiitac@pyr.swan.ac.uk>
  *			Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *	Version:	$Id: skbuff.c,v 1.64 2000/01/16 05:11:03 davem Exp $
+ *	Version:	$Id: skbuff.c,v 1.66 2000/02/09 21:11:30 davem Exp $
  *
  *	Fixes:	
  *		Alan Cox	:	Fixed the worst of the load balancer bugs.
@@ -61,18 +61,15 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-/*
- *	Resource tracking variables
- */
-
-static atomic_t net_skbcount = ATOMIC_INIT(0);
-static atomic_t net_allocs = ATOMIC_INIT(0);
-static atomic_t net_fails  = ATOMIC_INIT(0);
-
-extern atomic_t ip_frag_mem;
+int sysctl_hot_list_len = 128;
 
 static kmem_cache_t *skbuff_head_cache;
 
+static union {
+	struct sk_buff_head	list;
+	char			pad[SMP_CACHE_BYTES];
+} skb_head_pool[NR_CPUS];
+
 /*
  *	Keep out-of-line to prevent kernel bloat.
  *	__builtin_return_address is not used because it is not always
@@ -93,20 +90,39 @@
 	*(int*)0 = 0;
 }
 
-void show_net_buffers(void)
+static __inline__ struct sk_buff *skb_head_from_pool(void)
 {
-	printk("Networking buffers in use          : %u\n",
-	       atomic_read(&net_skbcount));
-	printk("Total network buffer allocations   : %u\n",
-	       atomic_read(&net_allocs));
-	printk("Total failed network buffer allocs : %u\n",
-	       atomic_read(&net_fails));
-#ifdef CONFIG_INET
-	printk("IP fragment buffer size            : %u\n",
-	       atomic_read(&ip_frag_mem));
-#endif	
+	struct sk_buff_head *list = &skb_head_pool[smp_processor_id()].list;
+
+	if (skb_queue_len(list)) {
+		struct sk_buff *skb;
+		unsigned long flags;
+
+		local_irq_save(flags);
+		skb = __skb_dequeue(list);
+		local_irq_restore(flags);
+		return skb;
+	}
+	return NULL;
+}
+
+static __inline__ void skb_head_to_pool(struct sk_buff *skb)
+{
+	struct sk_buff_head *list = &skb_head_pool[smp_processor_id()].list;
+
+	if (skb_queue_len(list) < sysctl_hot_list_len) {
+		unsigned long flags;
+
+		local_irq_save(flags);
+		__skb_queue_head(list, skb);
+		local_irq_restore(flags);
+
+		return;
+	}
+	kmem_cache_free(skbuff_head_cache, skb);
 }
 
+
 /* 	Allocate a new skbuff. We do this ourselves so we can fill in a few
  *	'private' fields and also do memory statistics to find all the
  *	[BEEP] leaks.
@@ -129,9 +145,12 @@
 	}
 
 	/* Get the HEAD */
-	skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
-	if (skb == NULL) 
-		goto nohead;
+	skb = skb_head_from_pool();
+	if (skb == NULL) {
+		skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
+		if (skb == NULL)
+			goto nohead;
+	}
 
 	/* Get the DATA. Size must match skb_add_mtu(). */
 	size = ((size + 15) & ~15); 
@@ -139,17 +158,9 @@
 	if (data == NULL)
 		goto nodata;
 
-	/* Note that this counter is useless now - you can just look in the
-	 * skbuff_head entry in /proc/slabinfo. We keep it only for emergency
-	 * cases.
-	 */
-	atomic_inc(&net_allocs);
-
 	/* XXX: does not include slab overhead */ 
 	skb->truesize = size + sizeof(struct sk_buff);
 
-	atomic_inc(&net_skbcount);
-
 	/* Load the data pointers. */
 	skb->head = data;
 	skb->data = data;
@@ -166,9 +177,8 @@
 	return skb;
 
 nodata:
-	kmem_cache_free(skbuff_head_cache, skb);
+	skb_head_to_pool(skb);
 nohead:
-	atomic_inc(&net_fails);
 	return NULL;
 }
 
@@ -213,8 +223,7 @@
 	if (!skb->cloned || atomic_dec_and_test(skb_datarefp(skb)))  
 		kfree(skb->head);
 
-	kmem_cache_free(skbuff_head_cache, skb);
-	atomic_dec(&net_skbcount);
+	skb_head_to_pool(skb);
 }
 
 /*
@@ -230,8 +239,13 @@
 	}
 
 	dst_release(skb->dst);
-	if(skb->destructor)
+	if(skb->destructor) {
+		if (in_irq()) {
+			printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n",
+				NET_CALLER(skb));
+		}
 		skb->destructor(skb);
+	}
 #ifdef CONFIG_NET		
 	if(skb->rx_dev)
 		dev_put(skb->rx_dev);
@@ -247,17 +261,18 @@
 struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
 {
 	struct sk_buff *n;
-	
-	n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
-	if (!n)
-		return NULL;
+
+	n = skb_head_from_pool();
+	if (!n) {
+		n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
+		if (!n)
+			return NULL;
+	}
 
 	memcpy(n, skb, sizeof(*n));
 	atomic_inc(skb_datarefp(skb));
 	skb->cloned = 1;
        
-	atomic_inc(&net_allocs);
-	atomic_inc(&net_skbcount);
 	dst_clone(n->dst);
 	n->rx_dev = NULL;
 	n->cloned = 1;
@@ -379,6 +394,8 @@
 
 void __init skb_init(void)
 {
+	int i;
+
 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
 					      sizeof(struct sk_buff),
 					      0,
@@ -386,4 +403,7 @@
 					      skb_headerinit, NULL);
 	if (!skbuff_head_cache)
 		panic("cannot create skbuff cache");
+
+	for (i=0; i<NR_CPUS; i++)
+		skb_queue_head_init(&skb_head_pool[i].list);
 }
diff -u --recursive --new-file v2.3.42/linux/net/core/sysctl_net_core.c linux/net/core/sysctl_net_core.c
--- v2.3.42/linux/net/core/sysctl_net_core.c	Sat Nov  7 11:00:32 1998
+++ linux/net/core/sysctl_net_core.c	Wed Feb  9 20:08:09 2000
@@ -23,6 +23,7 @@
 
 extern int sysctl_core_destroy_delay;
 extern int sysctl_optmem_max;
+extern int sysctl_hot_list_len;
 
 ctl_table core_table[] = {
 #ifdef CONFIG_NET
@@ -54,6 +55,9 @@
 	 &proc_dointvec_jiffies},
 	{NET_CORE_OPTMEM_MAX, "optmem_max",
 	 &sysctl_optmem_max, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
+	{NET_CORE_HOT_LIST_LENGTH, "hot_list_length",
+	 &sysctl_hot_list_len, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
 #endif /* CONFIG_NET */
 	{ 0 }
diff -u --recursive --new-file v2.3.42/linux/net/decnet/TODO linux/net/decnet/TODO
--- v2.3.42/linux/net/decnet/TODO	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/TODO	Tue Feb  8 18:23:13 2000
@@ -61,3 +61,11 @@
  o Hello messages should be generated for each primary address on each
    interface.
 
+ o Add more information into /proc/net/decnet and finalise the format to
+   allow DECnet support in netstat.
+
+ o Make sure that returned connect messages are generated when they should
+   be, and that the correct error messages are sent too. Ensure that the
+   conninit receiving routine does not accept conninits with parameters
+   that we cannot handle.
+
diff -u --recursive --new-file v2.3.42/linux/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- v2.3.42/linux/net/decnet/dn_dev.c	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/dn_dev.c	Wed Feb  9 20:08:09 2000
@@ -911,6 +911,7 @@
 	}
 
 	dn_dev_set_timer(dev);
+	timer_exit(&dn_db->timer);
 }
 
 static void dn_dev_set_timer(struct net_device *dev)
@@ -1010,8 +1011,7 @@
 	if (dn_db == NULL)
 		return;
 
-	del_timer(&dn_db->timer);
-	synchronize_bh();
+	del_timer_sync(&dn_db->timer);
 
 	dn_dev_sysctl_unregister(&dn_db->parms);
 
diff -u --recursive --new-file v2.3.42/linux/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- v2.3.42/linux/net/decnet/dn_nsp_in.c	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/dn_nsp_in.c	Wed Feb  9 20:08:09 2000
@@ -21,6 +21,8 @@
  *    Steve Whitehouse:  Now handles returned conninit frames.
  *     David S. Miller:  New socket locking
  *    Steve Whitehouse:  Fixed lockup when socket filtering was enabled.
+ *         Paul Koning:  Fix to push CC sockets into RUN when acks are
+ *                       received.
  */
 
 /******************************************************************************
@@ -400,7 +402,7 @@
 }
 
 /*
- * Copy of sock_queue_rcv_skb (from sock.h) with out
+ * Copy of sock_queue_rcv_skb (from sock.h) without
  * bh_lock_sock() (its already held when this is called) which
  * also allows data and other data to be queued to a socket.
  */
@@ -409,7 +411,6 @@
 #ifdef CONFIG_FILTER
 	struct sk_filter *filter;
 #endif
-	unsigned long flags;
 
         /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
            number of warnings when compiling with -W --ANK
@@ -431,7 +432,10 @@
         skb_set_owner_r(skb, sk);
         skb_queue_tail(queue, skb);
 
-	read_lock_irqsave(&sk->callback_lock, flags);
+	/* This code only runs from BH or BH protected context.
+	 * Therefore the plain read_lock is ok here. -DaveM
+	 */
+	read_lock(&sk->callback_lock);
         if (!sk->dead) {
 		struct socket *sock = sk->socket;
 		wake_up_interruptible(sk->sleep);
@@ -439,7 +443,7 @@
 			kill_fasync(sock->fasync_list, sig, 
 				    (sig == SIGURG) ? POLL_PRI : POLL_IN);
 	}
-	read_unlock_irqrestore(&sk->callback_lock, flags);
+	read_unlock(&sk->callback_lock);
 
         return 0;
 }
@@ -616,7 +620,6 @@
 	if (sk != NULL) {
 		struct dn_scp *scp = &sk->protinfo.dn;
 		int ret;
-		/* printk(KERN_DEBUG "dn_nsp_rx: Found a socket\n"); */
 
 		/* Reset backoff */
 		scp->nsp_rxtshift = 0;
@@ -691,6 +694,13 @@
 	} else {
 		int other = 1;
 
+		/* both data and ack frames can kick a CC socket into RUN */
+		if ((scp->state == DN_CC) && !sk->dead) {
+			scp->state = DN_RUN;
+			sk->state = TCP_ESTABLISHED;
+			sk->state_change(sk);
+		}
+
 		if ((cb->nsp_flags & 0x1c) == 0)
 			other = 0;
 		if (cb->nsp_flags == 0x04)
@@ -706,16 +716,9 @@
 		/*
 		 * If we've some sort of data here then call a
 		 * suitable routine for dealing with it, otherwise
-		 * the packet is an ack and can be discarded. All
-		 * data frames can also kick a CC socket into RUN.
+		 * the packet is an ack and can be discarded.
 		 */
 		if ((cb->nsp_flags & 0x0c) == 0) {
-
-			if ((scp->state == DN_CC) && !sk->dead) {
-				scp->state = DN_RUN;
-				sk->state = TCP_ESTABLISHED;
-				sk->state_change(sk);
-			}
 
 			if (scp->state != DN_RUN)
 				goto free_out;
diff -u --recursive --new-file v2.3.42/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- v2.3.42/linux/net/decnet/dn_route.c	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/dn_route.c	Tue Feb  8 18:23:13 2000
@@ -1149,9 +1149,9 @@
                 panic("Failed to allocate DECnet route cache hash table\n");
 
 	printk(KERN_INFO 
-		"DECnet: Routing cache hash table of %u buckets, %dKbytes\n", 
+		"DECnet: Routing cache hash table of %u buckets, %ldKbytes\n", 
 		dn_rt_hash_mask, 
-		(dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
+		(long)(dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
 
 	dn_rt_hash_mask--;
         for(i = 0; i <= dn_rt_hash_mask; i++) {
diff -u --recursive --new-file v2.3.42/linux/net/decnet/dn_table.c linux/net/decnet/dn_table.c
--- v2.3.42/linux/net/decnet/dn_table.c	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/dn_table.c	Tue Feb  8 18:23:13 2000
@@ -437,7 +437,7 @@
 
 #else /* no CONFIG_RTNETLINK */
 
-#define dn_rt_msg_fib(event,f,z,tb_id,nlh,req)
+#define dn_rtmsg_fib(event,f,z,tb_id,nlh,req)
 
 #endif /* CONFIG_RTNETLINK */
 
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.3.42/linux/net/ipv4/af_inet.c	Fri Jan 28 15:09:09 2000
+++ linux/net/ipv4/af_inet.c	Tue Feb  8 18:35:27 2000
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.104 2000/01/18 08:24:14 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.106 2000/02/04 21:04:06 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -675,7 +675,9 @@
   
 	sin->sin_family = AF_INET;
 	if (peer) {
-		if (!sk->dport) 
+		if (!sk->dport)
+			return -ENOTCONN;
+		if (((1<<sk->state)&(TCPF_CLOSE|TCPF_SYN_SENT)) && peer == 1)
 			return -ENOTCONN;
 		sin->sin_port = sk->dport;
 		sin->sin_addr.s_addr = sk->daddr;
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.3.42/linux/net/ipv4/icmp.c	Tue Jan 11 22:31:46 2000
+++ linux/net/ipv4/icmp.c	Wed Feb  9 20:08:09 2000
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.63 2000/01/09 02:19:45 davem Exp $
+ *	Version: $Id: icmp.c,v 1.64 2000/02/09 11:16:40 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -468,7 +468,7 @@
 {
 	if (type>NR_ICMP_TYPES)
 		return;
-	(icmp_pointers[type].output)[(smp_processor_id()*2+!in_interrupt())*sizeof(struct icmp_mib)/sizeof(unsigned long)]++;
+	(icmp_pointers[type].output)[(smp_processor_id()*2+!in_softirq())*sizeof(struct icmp_mib)/sizeof(unsigned long)]++;
 	ICMP_INC_STATS(IcmpOutMsgs);
 }
  
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v2.3.42/linux/net/ipv4/igmp.c	Thu Jan  6 12:57:48 2000
+++ linux/net/ipv4/igmp.c	Wed Feb  9 20:08:09 2000
@@ -8,7 +8,7 @@
  *	the older version didn't come out right using gcc 2.5.8, the newer one
  *	seems to fall out with gcc 2.6.2.
  *
- *	Version: $Id: igmp.c,v 1.36 2000/01/06 00:41:54 davem Exp $
+ *	Version: $Id: igmp.c,v 1.37 2000/02/09 11:16:40 davem Exp $
  *
  *	Authors:
  *		Alan Cox <Alan.Cox@linux.org>
@@ -154,11 +154,9 @@
 	int tv=net_random() % max_delay;
 
 	spin_lock_bh(&im->lock);
-	if (!del_timer(&im->timer))
-		atomic_inc(&im->refcnt);
-	im->timer.expires=jiffies+tv+2;
 	im->tm_running=1;
-	add_timer(&im->timer);
+	if (!mod_timer(&im->timer, jiffies+tv+2))
+		atomic_inc(&im->refcnt);
 	spin_unlock_bh(&im->lock);
 }
 
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v2.3.42/linux/net/ipv4/ip_fragment.c	Tue Jan 11 22:31:46 2000
+++ linux/net/ipv4/ip_fragment.c	Wed Feb  9 20:08:09 2000
@@ -5,7 +5,7 @@
  *
  *		The IP fragmentation functionality.
  *		
- * Version:	$Id: ip_fragment.c,v 1.46 2000/01/09 02:19:36 davem Exp $
+ * Version:	$Id: ip_fragment.c,v 1.47 2000/02/09 21:11:33 davem Exp $
  *
  * Authors:	Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
  *		Alan Cox <Alan.Cox@linux.org>
@@ -77,7 +77,7 @@
 #define ipqhashfn(id, saddr, daddr, prot) \
 	((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
 
-atomic_t ip_frag_mem = ATOMIC_INIT(0);		/* Memory used for fragments */
+static atomic_t ip_frag_mem = ATOMIC_INIT(0);	/* Memory used for fragments */
 
 /* Memory Tracking Functions. */
 extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.3.42/linux/net/ipv4/ip_output.c	Fri Jan 28 15:09:09 2000
+++ linux/net/ipv4/ip_output.c	Wed Feb  9 20:08:09 2000
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) output module.
  *
- * Version:	$Id: ip_output.c,v 1.78 2000/01/16 05:11:22 davem Exp $
+ * Version:	$Id: ip_output.c,v 1.80 2000/02/09 11:16:41 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -645,14 +645,14 @@
 	} while (offset >= 0);
 
 	if (nfrags>1)
-		ip_statistics[smp_processor_id()*2 + !in_interrupt()].IpFragCreates += nfrags;
+		ip_statistics[smp_processor_id()*2 + !in_softirq()].IpFragCreates += nfrags;
 out:
 	return 0;
 
 error:
 	IP_INC_STATS(IpOutDiscards);
 	if (nfrags>1)
-		ip_statistics[smp_processor_id()*2 + !in_interrupt()].IpFragCreates += nfrags;
+		ip_statistics[smp_processor_id()*2 + !in_softirq()].IpFragCreates += nfrags;
 	return err; 
 }
 
@@ -972,10 +972,15 @@
 		return;
 
 	daddr = ipc.addr = rt->rt_src;
-	ipc.opt = &replyopts.opt;
+	ipc.opt = NULL;
+
+	if (replyopts.opt.optlen) {
+		ipc.opt = &replyopts.opt;
+
+		if (ipc.opt->srr)
+			daddr = replyopts.opt.faddr;
+	}
 
-	if (ipc.opt->srr)
-		daddr = replyopts.opt.faddr;
 	if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0))
 		return;
 
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.42/linux/net/ipv4/route.c	Fri Jan 28 15:09:09 2000
+++ linux/net/ipv4/route.c	Wed Feb  9 20:08:09 2000
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.80 2000/01/21 06:37:27 davem Exp $
+ * Version:	$Id: route.c,v 1.81 2000/02/09 11:16:42 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -313,7 +313,7 @@
 }
 
 /* This runs via a timer and thus is always in BH context. */
-static void rt_check_expire(unsigned long dummy)
+static void SMP_TIMER_NAME(rt_check_expire)(unsigned long dummy)
 {
 	int i, t;
 	static int rover;
@@ -359,10 +359,12 @@
 	mod_timer(&rt_periodic_timer, now + ip_rt_gc_interval);
 }
 
+SMP_TIMER_DEFINE(rt_check_expire, rt_gc_task);
+
 /* This can run from both BH and non-BH contexts, the latter
  * in the case of a forced flush event.
  */
-static void rt_run_flush(unsigned long dummy)
+static void SMP_TIMER_NAME(rt_run_flush)(unsigned long dummy)
 {
 	int i;
 	struct rtable * rth, * next;
@@ -382,13 +384,15 @@
 		}
 	}
 }
+
+SMP_TIMER_DEFINE(rt_run_flush, rt_cache_flush_task);
   
 static spinlock_t rt_flush_lock = SPIN_LOCK_UNLOCKED;
 
 void rt_cache_flush(int delay)
 {
 	unsigned long now = jiffies;
-	int user_mode = !in_interrupt();
+	int user_mode = !in_softirq();
 
 	if (delay < 0)
 		delay = ip_rt_min_delay;
@@ -414,7 +418,7 @@
 
 	if (delay <= 0) {
 		spin_unlock_bh(&rt_flush_lock);
-		rt_run_flush(0);
+		SMP_TIMER_NAME(rt_run_flush)(0);
 		return;
 	}
 
@@ -529,7 +533,7 @@
 
 		if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
 			return 0;
-	} while (!in_interrupt() && jiffies - now < 1);
+	} while (!in_softirq() && jiffies - now < 1);
 
 	if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
 		return 0;
@@ -552,7 +556,7 @@
 {
 	struct rtable	*rth, **rthp;
 	unsigned long	now = jiffies;
-	int attempts = !in_interrupt();
+	int attempts = !in_softirq();
 
 restart:
 	rthp = &rt_hash_table[hash].chain;
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.3.42/linux/net/ipv4/tcp.c	Tue Feb  1 01:35:44 2000
+++ linux/net/ipv4/tcp.c	Tue Feb  8 18:35:27 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.161 2000/01/31 01:21:16 davem Exp $
+ * Version:	$Id: tcp.c,v 1.163 2000/02/08 21:27:13 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1106,8 +1106,8 @@
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	struct sk_buff *skb;
-	int time_to_ack;
-	
+	int time_to_ack = 0;
+
 	/* NOTE! The socket must be locked, so that we don't get
 	 * a messed-up receive queue.
 	 */
@@ -1117,13 +1117,39 @@
 		tcp_eat_skb(sk, skb);
 	}
 
-	/* Delayed ACKs frequently hit locked sockets during bulk receive. */
-	time_to_ack = tp->ack.blocked && tp->ack.pending;
-#ifdef CONFIG_TCP_MORE_COARSE_ACKS
-	if (tp->ack.pending &&
-	    (tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss)
-		time_to_ack = 1;
+	if (tp->ack.pending) {
+		   /* Delayed ACKs frequently hit locked sockets during bulk receive. */
+		if (tp->ack.blocked
+#ifdef TCP_MORE_COARSE_ACKS
+		    /* Once-per-two-segments ACK was not sent by tcp_input.c */
+		    || tp->rcv_nxt - tp->rcv_wup > tp->ack.rcv_mss
 #endif
+		    /*
+		     * If this read emptied read buffer, we send ACK when:
+		     *
+		     * -- ATO estimator diverged. In this case it is useless
+		     * to delay ACK, it will miss in any case.
+		     *
+		     * -- The second condition is triggered when we did not
+		     * ACK 8 segments not depending of their size.
+		     * Linux senders allocate full-sized frame even for one byte
+		     * packets, so that default queue for MTU=8K can hold
+		     * only 8 packets. Note, that no other workarounds
+		     * but counting packets are possible. If sender selected
+		     * a small sndbuf or have larger mtu lockup will still
+		     * occur. Well, not lockup, but 10-20msec gap.
+		     * It is essentially dead lockup for 1Gib ethernet
+		     * and loopback :-). The value 8 covers all reasonable
+		     * cases and we may receive packet of any size
+		     * with maximal possible rate now.
+		     */
+		    || (copied > 0 &&
+			(tp->ack.ato >= TCP_DELACK_MAX || tp->ack.rcv_segs > 7) &&
+			!tp->ack.pingpong &&
+			atomic_read(&sk->rmem_alloc) == 0)) {
+			time_to_ack = 1;
+		}
+	}
 
   	/* We send an ACK if we can now advertise a non-zero window
 	 * which has been raised "significantly".
@@ -1135,14 +1161,12 @@
 		__u32 rcv_window_now = tcp_receive_window(tp);
 		__u32 new_window = __tcp_select_window(sk);
 
-		/* We won't be raising the window any further than
-		 * the window-clamp allows.  Our window selection
-		 * also keeps things a nice multiple of MSS.  These
-		 * checks are necessary to prevent spurious ACKs
-		 * which don't advertize a larger window.
+		/* Send ACK now, if this read freed lots of space
+		 * in our buffer. Certainly, new_window is new window.
+		 * We can advertise it now, if it is not less than current one.
+		 * "Lots" means "at least twice" here.
 		 */
-		if((new_window && (new_window >= rcv_window_now * 2)) &&
-		   ((rcv_window_now + tp->ack.rcv_mss) <= tp->window_clamp))
+		if(new_window && new_window >= 2*rcv_window_now)
 			time_to_ack = 1;
 	}
 	if (time_to_ack)
@@ -1408,11 +1432,6 @@
 					copied += chunk;
 				}
 			}
-#ifdef CONFIG_TCP_MORE_COARSE_ACKS
-			if (tp->ack.pending &&
-			    (tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss)
-				tcp_send_ack(sk);
-#endif
 		}
 		continue;
 
@@ -1472,7 +1491,7 @@
 		skb->used = 1;
 		tcp_eat_skb(sk, skb);
 
-#ifdef CONFIG_TCP_LESS_COARSE_ACKS
+#ifdef TCP_LESS_COARSE_ACKS
 		/* Possible improvement. When sender is faster than receiver,
 		 * traffic looks like: fill window ... wait for window open ...
 		 * fill window. We lose at least one rtt, because call
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.3.42/linux/net/ipv4/tcp_input.c	Tue Feb  1 01:35:44 2000
+++ linux/net/ipv4/tcp_input.c	Tue Feb  8 18:35:27 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.186 2000/01/31 20:26:13 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.188 2000/02/08 21:27:14 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -134,25 +134,6 @@
 				tp->ack.rcv_mss = len;
 			tp->ack.last_seg_size = len;
 		}
-
-#if 0
-		/* Tiny-grams with PSH set artifically deflate our
-		 * ato measurement.
-		 *
-		 * Mmm... I copied this test from tcp_remember_ack(), but
-		 * I did not understand this. Is it to speedup nagling sender?
-		 * It does not because classic (non-Minshall) sender nagles
-		 * guided by not-acked frames not depending on size.
-		 * And it does not help NODELAY sender, because latency
-		 * is too high in any case. The only result is timer trashing
-		 * and redundant ACKs. Grr... Seems, I missed something.  --ANK
-		 *
-		 * Let me to comment out this yet... TCP should work
-		 * perfectly without this. 				  --ANK
-		 */
-		if (len < (tp->ack.rcv_mss >> 1) && skb->h.th->psh)
-			tp->ack.ato = TCP_ATO_MIN;
-#endif
 	}
 }
 
@@ -199,6 +180,7 @@
 	tcp_measure_rcv_mss(tp, skb);
 
 	tp->ack.pending = 1;
+	tp->ack.rcv_segs++;
 
 	now = tcp_time_stamp;
 
@@ -232,7 +214,8 @@
 		} else {
 			if (m <= 0)
 				m = TCP_ATO_MIN/2;
-			tp->ack.ato = (tp->ack.ato >> 1) + m;
+			if (m <= tp->ack.ato)
+				tp->ack.ato = (tp->ack.ato >> 1) + m;
 		}
 	}
 	tp->ack.lrcvtime = now;
@@ -458,7 +441,7 @@
 extern __inline__ void
 tcp_replace_ts_recent(struct sock *sk, struct tcp_opt *tp, u32 seq)
 {
-	if (!after(seq, tp->last_ack_sent)) {
+	if (!after(seq, tp->rcv_wup)) {
 		/* PAWS bug workaround wrt. ACK frames, the PAWS discard
 		 * extra check below makes sure this can only happen
 		 * for pure ACK frames.  -DaveM
@@ -2303,6 +2286,8 @@
 	if(atomic_read(&sk->rmem_alloc) < (sk->rcvbuf << 1))
 		return 0;
 
+	NET_INC_STATS_BH(RcvPruned);
+
 	/* Massive buffer overcommit. */
 	return -1;
 }
@@ -2470,10 +2455,10 @@
 				goto slow_path;
 
 			/* Predicted packet is in window by definition.
-			 * seq == rcv_nxt and last_ack_sent <= rcv_nxt.
-			 * Hence, check seq<=last_ack_sent reduces to:
+			 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+			 * Hence, check seq<=rcv_wup reduces to:
 			 */
-			if (tp->rcv_nxt == tp->last_ack_sent) {
+			if (tp->rcv_nxt == tp->rcv_wup) {
 				tp->ts_recent = tp->rcv_tsval;
 				tp->ts_recent_stamp = xtime.tv_sec;
 			}
@@ -2544,7 +2529,7 @@
 
 			tcp_event_data_recv(tp, skb);
 
-#if 1/*def CONFIG_TCP_MORE_COARSE_ACKS*/
+#ifdef TCP_MORE_COARSE_ACKS
 			if (eaten) {
 				if (tcp_in_quickack_mode(tp)) {
 					tcp_send_ack(sk);
@@ -2747,7 +2732,6 @@
 		newtp->copied_seq = req->rcv_isn + 1;
 
 		newtp->saw_tstamp = 0;
-		newtp->last_ack_sent = req->rcv_isn + 1;
 
 		newtp->probes_out = 0;
 		newtp->syn_seq = req->rcv_isn;
@@ -3146,7 +3130,6 @@
 			tp->ack.pending = 1;
 			tp->ack.lrcvtime = tcp_time_stamp;
 			tcp_enter_quickack_mode(tp);
-			tp->ack.pingpong = 1;
 			tp->ack.ato = TCP_ATO_MIN;
 			tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MIN);
 			goto discard;
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.42/linux/net/ipv4/tcp_ipv4.c	Tue Feb  1 01:35:44 2000
+++ linux/net/ipv4/tcp_ipv4.c	Tue Feb  8 18:35:27 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.198 2000/01/31 01:21:20 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.199 2000/02/08 21:27:17 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -1339,6 +1339,16 @@
 	tp.user_mss = sk->tp_pinfo.af_tcp.user_mss;
 
 	tcp_parse_options(NULL, th, &tp, want_cookie);
+
+	if (tp.saw_tstamp && tp.rcv_tsval == 0) {
+		/* Some OSes (unknown ones, but I see them on web server, which
+		 * contains information interesting only for windows'
+		 * users) do not send their stamp in SYN. It is easy case.
+		 * We simply do not advertise TS support.
+		 */
+		tp.saw_tstamp = 0;
+		tp.tstamp_ok = 0;
+	}
 
 	tcp_openreq_init(req, &tp, skb);
 
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.3.42/linux/net/ipv4/tcp_output.c	Tue Feb  1 01:35:44 2000
+++ linux/net/ipv4/tcp_output.c	Tue Feb  8 18:35:27 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.120 2000/01/31 01:21:22 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.121 2000/02/08 21:27:19 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -94,9 +94,9 @@
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
-	tp->last_ack_sent = tp->rcv_nxt;
 	tcp_dec_quickack_mode(tp);
 	tp->ack.pending = 0;
+	tp->ack.rcv_segs = 0;
 	tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
 }
 
@@ -363,7 +363,7 @@
 
 	/* Bound mss with half of window */
 	if (tp->max_window && mss_now > (tp->max_window>>1))
-		mss_now = max((tp->max_window>>1), 1);
+		mss_now = max((tp->max_window>>1), 68 - tp->tcp_header_len);
 
 	/* And store cached results */
 	tp->pmtu_cookie = pmtu;
@@ -509,10 +509,7 @@
 	if (tp->window_clamp < mss)
 		mss = tp->window_clamp; 
 
-	if ((free_space < (min((int)tp->window_clamp, tcp_full_space(sk)) / 2)) && 
-		(free_space < ((int) (mss/2)))) {
-		window = 0;
-
+	if (free_space < min((int)tp->window_clamp, tcp_full_space(sk)) / 2) {
 		/* THIS IS _VERY_ GOOD PLACE to play window clamp.
 		 * if free_space becomes suspiciously low
 		 * verify ratio rmem_alloc/(rcv_nxt - copied_seq),
@@ -520,21 +517,28 @@
 		 * rmem_alloc will run out of rcvbuf*2, shrink window_clamp.
 		 * It will eliminate most of prune events! Very simple,
 		 * it is the next thing to do.			--ANK
+		 *
+		 * Provided we found a way to raise it back...  --ANK
 		 */
-	} else {
-		/* Get the largest window that is a nice multiple of mss.
-		 * Window clamp already applied above.
-		 * If our current window offering is within 1 mss of the
-		 * free space we just keep it. This prevents the divide
-		 * and multiply from happening most of the time.
-		 * We also don't do any window rounding when the free space
-		 * is too small.
-		 */
-		window = tp->rcv_wnd;
-		if ((((int) window) <= (free_space - ((int) mss))) ||
-				(((int) window) > free_space))
-			window = (((unsigned int) free_space)/mss)*mss;
+		tp->ack.quick = 0;
+
+		if (free_space < ((int) (mss/2)))
+			return 0;
 	}
+
+	/* Get the largest window that is a nice multiple of mss.
+	 * Window clamp already applied above.
+	 * If our current window offering is within 1 mss of the
+	 * free space we just keep it. This prevents the divide
+	 * and multiply from happening most of the time.
+	 * We also don't do any window rounding when the free space
+	 * is too small.
+	 */
+	window = tp->rcv_wnd;
+	if ((((int) window) <= (free_space - ((int) mss))) ||
+	    (((int) window) > free_space))
+		window = (((unsigned int) free_space)/mss)*mss;
+
 	return window;
 }
 
@@ -1092,8 +1096,7 @@
 	unsigned long timeout;
 
 	/* Stay within the limit we were given */
-	timeout = tp->ack.ato;
-	timeout += jiffies + (timeout>>2);
+	timeout = jiffies + tp->ack.ato;
 
 	/* Use new timeout only if there wasn't a older one earlier. */
 	spin_lock_bh(&sk->timer_lock);
@@ -1151,6 +1154,7 @@
 		buff = alloc_skb(MAX_TCP_HEADER + 15, GFP_ATOMIC);
 		if (buff == NULL) {
 			tp->ack.pending = 1;
+			tp->ack.ato = TCP_ATO_MAX;
 			tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
 			return;
 		}
diff -u --recursive --new-file v2.3.42/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.3.42/linux/net/ipv4/tcp_timer.c	Fri Jan 28 15:09:09 2000
+++ linux/net/ipv4/tcp_timer.c	Wed Feb  9 20:08:09 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.71 2000/01/18 08:24:19 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.73 2000/02/09 11:16:42 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -200,15 +200,23 @@
 	}
 
 	if (tp->ack.pending) {
-		/* Delayed ACK missed: inflate ATO, leave pingpong mode */
-		tp->ack.ato = min(tp->ack.ato<<1, TCP_ATO_MAX);
-		tp->ack.pingpong = 0;
+		if (!tp->ack.pingpong) {
+			/* Delayed ACK missed: inflate ATO. */
+			tp->ack.ato = min(tp->ack.ato<<1, TCP_ATO_MAX);
+		} else {
+			/* Delayed ACK missed: leave pingpong mode and
+			 * deflate ATO.
+			 */
+			tp->ack.pingpong = 0;
+			tp->ack.ato = TCP_ATO_MIN;
+		}
 		tcp_send_ack(sk);
 		NET_INC_STATS_BH(DelayedACKs);
 	}
 	TCP_CHECK_TIMER(sk);
 
 out_unlock:
+	timer_exit(&tp->delack_timer);
 	bh_unlock_sock(sk);
 	sock_put(sk);
 }
@@ -259,6 +267,7 @@
 		TCP_CHECK_TIMER(sk);
 	}
 out_unlock:
+	timer_exit(&tp->probe_timer);
 	bh_unlock_sock(sk);
 	sock_put(sk);
 }
@@ -272,7 +281,7 @@
 static spinlock_t tw_death_lock = SPIN_LOCK_UNLOCKED;
 static struct timer_list tcp_tw_timer = { function: tcp_twkill };
 
-static void tcp_twkill(unsigned long data)
+static void SMP_TIMER_NAME(tcp_twkill)(unsigned long dummy)
 {
 	struct tcp_tw_bucket *tw;
 	int killed = 0;
@@ -310,6 +319,8 @@
 	spin_unlock(&tw_death_lock);
 }
 
+SMP_TIMER_DEFINE(tcp_twkill, tcp_twkill_task);
+
 /* These are always called from BH context.  See callers in
  * tcp_input.c to verify this.
  */
@@ -419,7 +430,7 @@
 	spin_unlock(&tw_death_lock);
 }
 
-void tcp_twcal_tick(unsigned long dummy)
+void SMP_TIMER_NAME(tcp_twcal_tick)(unsigned long dummy)
 {
 	int n, slot;
 	unsigned long j;
@@ -470,6 +481,7 @@
 	spin_unlock(&tw_death_lock);
 }
 
+SMP_TIMER_DEFINE(tcp_twcal_tick, tcp_twcal_tasklet);
 
 /*
  *	The TCP retransmit timer.
@@ -565,6 +577,7 @@
 	TCP_CHECK_TIMER(sk);
 
 out_unlock:
+	timer_exit(&tp->retransmit_timer);
 	bh_unlock_sock(sk);
 	sock_put(sk);
 }
@@ -763,6 +776,7 @@
 	tcp_done(sk);
 
 out:
+	timer_exit(&sk->timer);
 	bh_unlock_sock(sk);
 	sock_put(sk);
 }
diff -u --recursive --new-file v2.3.42/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.3.42/linux/net/ipv6/af_inet6.c	Fri Jan 28 15:09:09 2000
+++ linux/net/ipv6/af_inet6.c	Tue Feb  8 18:35:27 2000
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.52 2000/01/18 08:24:21 davem Exp $
+ *	$Id: af_inet6.c,v 1.53 2000/02/04 21:04:08 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -340,6 +340,8 @@
 	sin->sin6_flowinfo = 0;
 	if (peer) {
 		if (!sk->dport)
+			return -ENOTCONN;
+		if (((1<<sk->state)&(TCPF_CLOSE|TCPF_SYN_SENT)) && peer == 1)
 			return -ENOTCONN;
 		sin->sin6_port = sk->dport;
 		memcpy(&sin->sin6_addr, &sk->net_pinfo.af_inet6.daddr,
diff -u --recursive --new-file v2.3.42/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c
--- v2.3.42/linux/net/ipv6/mcast.c	Fri Jan 28 15:09:09 2000
+++ linux/net/ipv6/mcast.c	Tue Feb  8 18:35:27 2000
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: mcast.c,v 1.29 2000/01/18 08:24:21 davem Exp $
+ *	$Id: mcast.c,v 1.30 2000/02/08 21:27:23 davem Exp $
  *
  *	Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c 
  *
@@ -346,8 +346,8 @@
 			}
 		}
 		read_unlock_bh(&idev->lock);
+		in6_dev_put(idev);
 	}
-	in6_dev_put(idev);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.42/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.42/linux/net/irda/irmod.c	Fri Jan  7 19:13:23 2000
+++ linux/net/irda/irmod.c	Wed Feb  9 11:42:36 2000
@@ -88,18 +88,12 @@
 static u_int irda_poll(struct file *file, poll_table *wait);
 
 static struct file_operations irda_fops = {
-	NULL,	       /* seek */
-	irda_read,     /* read */
-	irda_write,    /* write */
-	NULL,	       /* readdir */
-	irda_poll,     /* poll */
-	irda_ioctl,    /* ioctl */
-	NULL,	       /* mmap */
-	irda_open,
-	NULL,
-	irda_close,
-	NULL,
-	NULL,          /* fasync */
+	read:		irda_read,
+	write:		irda_write,
+	poll:		irda_poll,
+	ioctl:		irda_ioctl,
+	open:		irda_open,
+	release:	irda_close,
 };
 
 /* IrTTP */
diff -u --recursive --new-file v2.3.42/linux/net/khttpd/datasending.c linux/net/khttpd/datasending.c
--- v2.3.42/linux/net/khttpd/datasending.c	Fri Jan 28 15:09:09 2000
+++ linux/net/khttpd/datasending.c	Thu Feb 10 12:17:00 2000
@@ -114,8 +114,7 @@
 			
 			inode = CurrentRequest->filp->f_dentry->d_inode;
 			
-			if ( (inode!=NULL)&&(inode->i_op!=NULL)&&(inode->i_op->readpage!=NULL))
-			{
+			if (inode && inode->i_mapping->a_ops->readpage) {
 				/* This does the actual transfer using sendfile */		
 				read_descriptor_t desc;
 				loff_t *ppos;
diff -u --recursive --new-file v2.3.42/linux/net/khttpd/structure.h linux/net/khttpd/structure.h
--- v2.3.42/linux/net/khttpd/structure.h	Thu Aug 26 13:05:46 1999
+++ linux/net/khttpd/structure.h	Wed Feb  9 19:47:20 2000
@@ -42,7 +42,7 @@
 	char		LengthS[14];	/* File length, string representation */
 	char		*MimeType;	/* Pointer to a string with the mime-type 
 					   based on the filename */
-	int		MimeLength;	/* The length of this string */
+	__kernel_size_t	MimeLength;	/* The length of this string */
 	
 };
 
diff -u --recursive --new-file v2.3.42/linux/net/khttpd/userspace.c linux/net/khttpd/userspace.c
--- v2.3.42/linux/net/khttpd/userspace.c	Fri Jan 28 15:09:09 2000
+++ linux/net/khttpd/userspace.c	Wed Feb  9 20:08:09 2000
@@ -216,10 +216,10 @@
 	sock->state = SS_UNCONNECTED;
 
 	req->class	= &Dummy;
-	write_lock_irq(&nsk->callback_lock);
+	write_lock_bh(&nsk->callback_lock);
 	nsk->socket = NULL;
         nsk->sleep  = NULL;
-	write_unlock_irq(&nsk->callback_lock);
+	write_unlock_bh(&nsk->callback_lock);
 
 	tcp_acceptq_queue(sk, req, nsk);	
 
diff -u --recursive --new-file v2.3.42/linux/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c
--- v2.3.42/linux/net/netlink/netlink_dev.c	Tue Aug 31 17:29:15 1999
+++ linux/net/netlink/netlink_dev.c	Wed Feb  9 11:42:36 2000
@@ -166,16 +166,13 @@
 
 
 static struct file_operations netlink_fops = {
-	netlink_lseek,
-	netlink_read,
-	netlink_write,
-	NULL,		/* netlink_readdir */
-	netlink_poll,
-	netlink_ioctl,
-	NULL,		/* netlink_mmap */
-	netlink_open,
-	NULL,		/* flush */
-	netlink_release
+	llseek:		netlink_lseek,
+	read:		netlink_read,
+	write:		netlink_write,
+	poll:		netlink_poll,
+	ioctl:		netlink_ioctl,
+	open:		netlink_open,
+	release:	netlink_release,
 };
 
 int __init init_netlink(void)
diff -u --recursive --new-file v2.3.42/linux/net/netsyms.c linux/net/netsyms.c
--- v2.3.42/linux/net/netsyms.c	Fri Jan 28 15:09:09 2000
+++ linux/net/netsyms.c	Wed Feb  9 20:08:09 2000
@@ -487,6 +487,7 @@
 EXPORT_SYMBOL(dev_get_by_name);
 EXPORT_SYMBOL(__dev_get_by_name);
 EXPORT_SYMBOL(netdev_finish_unregister);
+EXPORT_SYMBOL(netdev_set_master);
 EXPORT_SYMBOL(eth_type_trans);
 #ifdef CONFIG_FDDI
 EXPORT_SYMBOL(fddi_type_trans);
@@ -510,7 +511,6 @@
 #endif
 EXPORT_SYMBOL(dev_ioctl);
 EXPORT_SYMBOL(dev_queue_xmit);
-EXPORT_SYMBOL(netdev_dropping);
 #ifdef CONFIG_NET_FASTROUTE
 EXPORT_SYMBOL(dev_fastroute_stat);
 #endif
@@ -552,11 +552,9 @@
 EXPORT_SYMBOL(qdisc_destroy);
 EXPORT_SYMBOL(qdisc_reset);
 EXPORT_SYMBOL(qdisc_restart);
-EXPORT_SYMBOL(qdisc_head);
 EXPORT_SYMBOL(qdisc_create_dflt);
 EXPORT_SYMBOL(noop_qdisc);
 EXPORT_SYMBOL(qdisc_tree_lock);
-EXPORT_SYMBOL(qdisc_runqueue_lock);
 #ifdef CONFIG_NET_SCHED
 PSCHED_EXPORTLIST;
 EXPORT_SYMBOL(pfifo_qdisc_ops);
@@ -597,5 +595,8 @@
 #endif
 
 EXPORT_SYMBOL(register_gifconf);
+
+EXPORT_SYMBOL(softirq_state);
+EXPORT_SYMBOL(softnet_data);
 
 #endif  /* CONFIG_NET */
diff -u --recursive --new-file v2.3.42/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.3.42/linux/net/packet/af_packet.c	Fri Jan 28 15:09:09 2000
+++ linux/net/packet/af_packet.c	Tue Feb  8 18:35:27 2000
@@ -5,7 +5,7 @@
  *
  *		PACKET - implements raw packet sockets.
  *
- * Version:	$Id: af_packet.c,v 1.28 2000/01/24 23:35:59 davem Exp $
+ * Version:	$Id: af_packet.c,v 1.30 2000/02/01 12:38:30 freitag Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1000,6 +1000,10 @@
 	struct sock *sk = sock->sk;
 	struct sk_buff *skb;
 	int copied, err;
+
+	err = -EINVAL;
+	if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC))
+		goto out;
 
 #if 0
 	/* What error should we return now? EUNATTACH? */
diff -u --recursive --new-file v2.3.42/linux/net/sched/sch_atm.c linux/net/sched/sch_atm.c
--- v2.3.42/linux/net/sched/sch_atm.c	Fri Sep 10 23:57:38 1999
+++ linux/net/sched/sch_atm.c	Tue Feb  8 18:23:13 2000
@@ -1,6 +1,6 @@
 /* net/sched/sch_atm.c - ATM VC selection "queueing discipline" */
 
-/* Written 1998,1999 by Werner Almesberger, EPFL ICA */
+/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
 
 
 #include <linux/config.h>
@@ -56,12 +56,14 @@
 
 
 #define PRIV(sch) ((struct atm_qdisc_data *) (sch)->data)
+#define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
 
 
 struct atm_flow_data {
 	struct Qdisc		*q;		/* FIFO, TBF, etc. */
 	struct tcf_proto	*filter_list;
 	struct atm_vcc		*vcc;		/* VCC; NULL if VCC is closed */
+	void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* chaining */
 	struct socket		*sock;		/* for closing */
 	u32			classid;	/* x:y type ID */
 	int			ref;		/* reference count */
@@ -133,7 +135,7 @@
 
 static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid)
 {
-	struct atm_qdisc_data *p = PRIV(sch);
+	struct atm_qdisc_data *p __attribute__((unused)) = PRIV(sch);
 	struct atm_flow_data *flow;
 
 	DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
@@ -184,6 +186,7 @@
 	}
 	if (flow->sock) {
 		DPRINTK("atm_tc_put: f_count %d\n",file_count(flow->sock->file));
+		flow->vcc->pop = flow->old_pop;
 		sockfd_put(flow->sock);
 	}
 	if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess);
@@ -195,6 +198,13 @@
 }
 
 
+static void sch_atm_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+{
+	VCC2FLOW(vcc)->old_pop(vcc,skb);
+	mark_bh(NET_BH); /* may allow to send more */
+}
+
+
 static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
     struct rtattr **tca, unsigned long *arg)
 {
@@ -289,7 +299,10 @@
 	DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
 	flow->sock = sock;
         flow->vcc = ATM_SD(sock); /* speedup */
+	flow->vcc->user_back = flow;
         DPRINTK("atm_tc_change: vcc %p\n",flow->vcc);
+	flow->old_pop = flow->vcc->pop;
+	flow->vcc->pop = sch_atm_pop;
 	flow->classid = classid;
 	flow->ref = 1;
 	flow->excess = excess;
@@ -440,6 +453,10 @@
 		 * little bursts. Otherwise, it may ... @@@
 		 */
 		while ((skb = flow->q->dequeue(flow->q))) {
+			if (!atm_may_send(flow->vcc,skb->truesize)) {
+				flow->q->ops->requeue(skb,flow->q);
+				break;
+			}
 			sch->q.qlen--;
 			D2PRINTK("atm_tc_deqeueue: sending on class %p\n",flow);
 			/* remove any LL header somebody else has attached */
@@ -468,6 +485,22 @@
 }
 
 
+static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch)
+{
+	struct atm_qdisc_data *p = PRIV(sch);
+	int ret;
+
+	D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
+	ret = p->link.q->ops->requeue(skb,p->link.q);
+	if (!ret) sch->q.qlen++;
+	else {
+		sch->stats.drops++;
+		p->link.stats.drops++;
+	}
+	return ret;
+}
+
+
 static int atm_tc_drop(struct Qdisc *sch)
 {
 	struct atm_qdisc_data *p = PRIV(sch);
@@ -616,7 +649,7 @@
 
 	atm_tc_enqueue,			/* enqueue */
 	atm_tc_dequeue,			/* dequeue */
-	atm_tc_enqueue,			/* requeue; we're cheating a little */
+	atm_tc_requeue,			/* requeue */
 	atm_tc_drop,			/* drop */
 
 	atm_tc_init,			/* init */
diff -u --recursive --new-file v2.3.42/linux/net/sched/sch_cbq.c linux/net/sched/sch_cbq.c
--- v2.3.42/linux/net/sched/sch_cbq.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/sch_cbq.c	Wed Feb  9 20:08:09 2000
@@ -597,8 +597,9 @@
 static void cbq_watchdog(unsigned long arg)
 {
 	struct Qdisc *sch = (struct Qdisc*)arg;
+
 	sch->flags &= ~TCQ_F_THROTTLED;
-	qdisc_wakeup(sch->dev);
+	netif_schedule(sch->dev);
 }
 
 static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio)
@@ -666,7 +667,7 @@
 	}
 
 	sch->flags &= ~TCQ_F_THROTTLED;
-	qdisc_wakeup(sch->dev);
+	netif_schedule(sch->dev);
 }
 
 
@@ -1052,7 +1053,7 @@
 
 	if (sch->q.qlen) {
 		sch->stats.overlimits++;
-		if (q->wd_expires && !sch->dev->tbusy) {
+		if (q->wd_expires && !test_bit(LINK_STATE_XOFF, &sch->dev->state)) {
 			long delay = PSCHED_US2JIFFIE(q->wd_expires);
 			del_timer(&q->wd_timer);
 			if (delay <= 0)
diff -u --recursive --new-file v2.3.42/linux/net/sched/sch_generic.c linux/net/sched/sch_generic.c
--- v2.3.42/linux/net/sched/sch_generic.c	Fri Jan  7 19:13:23 2000
+++ linux/net/sched/sch_generic.c	Wed Feb  9 20:08:09 2000
@@ -34,9 +34,6 @@
 
 /* Main transmission queue. */
 
-struct Qdisc_head qdisc_head = { &qdisc_head, &qdisc_head };
-spinlock_t qdisc_runqueue_lock = SPIN_LOCK_UNLOCKED;
-
 /* Main qdisc structure lock. 
 
    However, modifications
@@ -55,11 +52,7 @@
  */
 rwlock_t qdisc_tree_lock = RW_LOCK_UNLOCKED;
 
-/* Anti deadlock rules:
-
-   qdisc_runqueue_lock protects main transmission list qdisc_head.
-   Run list is accessed only under this spinlock.
-
+/* 
    dev->queue_lock serializes queue accesses for this device
    AND dev->qdisc pointer itself.
 
@@ -67,10 +60,6 @@
 
    dev->queue_lock and dev->xmit_lock are mutually exclusive,
    if one is grabbed, another must be free.
-
-   qdisc_runqueue_lock may be requested under dev->queue_lock,
-   but neither dev->queue_lock nor dev->xmit_lock may be requested
-   under qdisc_runqueue_lock.
  */
 
 
@@ -99,17 +88,19 @@
 			/* And release queue */
 			spin_unlock(&dev->queue_lock);
 
-			if (netdev_nit)
-				dev_queue_xmit_nit(skb, dev);
-
-			if (dev->hard_start_xmit(skb, dev) == 0) {
-				dev->xmit_lock_owner = -1;
-				spin_unlock(&dev->xmit_lock);
-
-				spin_lock(&dev->queue_lock);
-				dev->qdisc->tx_last = jiffies;
-				return -1;
+			if (!test_bit(LINK_STATE_XOFF, &dev->state)) {
+				if (netdev_nit)
+					dev_queue_xmit_nit(skb, dev);
+
+				if (dev->hard_start_xmit(skb, dev) == 0) {
+					dev->xmit_lock_owner = -1;
+					spin_unlock(&dev->xmit_lock);
+
+					spin_lock(&dev->queue_lock);
+					return -1;
+				}
 			}
+
 			/* Release the driver */
 			dev->xmit_lock_owner = -1;
 			spin_unlock(&dev->xmit_lock);
@@ -126,14 +117,10 @@
 			if (dev->xmit_lock_owner == smp_processor_id()) {
 				kfree_skb(skb);
 				if (net_ratelimit())
-					printk(KERN_DEBUG "Dead loop on virtual %s, fix it urgently!\n", dev->name);
+					printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
 				return -1;
 			}
-
-			/* Otherwise, packet is requeued
-			   and will be sent by the next net_bh run.
-			 */
-			mark_bh(NET_BH);
+			netdev_rx_stat[smp_processor_id()].cpu_collision++;
 		}
 
 		/* Device kicked us out :(
@@ -147,139 +134,68 @@
 		 */
 
 		q->ops->requeue(skb, q);
-		return -1;
+		netif_schedule(dev);
+		return 1;
 	}
 	return q->q.qlen;
 }
 
-static __inline__ void
-qdisc_stop_run(struct Qdisc *q)
+static void dev_watchdog(unsigned long arg)
 {
-	q->h.forw->back = q->h.back;
-	q->h.back->forw = q->h.forw;
-	q->h.forw = NULL;
-}
-
-extern __inline__ void
-qdisc_continue_run(struct Qdisc *q)
-{
-	if (!qdisc_on_runqueue(q) && q->dev) {
-		q->h.forw = &qdisc_head;
-		q->h.back = qdisc_head.back;
-		qdisc_head.back->forw = &q->h;
-		qdisc_head.back = &q->h;
+	struct net_device *dev = (struct net_device *)arg;
+
+	spin_lock(&dev->xmit_lock);
+	if (dev->qdisc != &noop_qdisc) {
+		if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+		    (jiffies - dev->trans_start) > dev->watchdog_timeo) {
+			printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n", dev->name);
+			dev->tx_timeout(dev);
+		}
+		if (!del_timer(&dev->watchdog_timer))
+			dev_hold(dev);
+
+		dev->watchdog_timer.expires = jiffies + dev->watchdog_timeo;
+		add_timer(&dev->watchdog_timer);
 	}
+	spin_unlock(&dev->xmit_lock);
+
+	dev_put(dev);
 }
 
-static __inline__ int
-qdisc_init_run(struct Qdisc_head *lh)
+static void dev_watchdog_init(struct net_device *dev)
 {
-	if (qdisc_head.forw != &qdisc_head) {
-		*lh = qdisc_head;
-		lh->forw->back = lh;
-		lh->back->forw = lh;
-		qdisc_head.forw = &qdisc_head;
-		qdisc_head.back = &qdisc_head;
-		return 1;
-	}
-	return 0;
+	init_timer(&dev->watchdog_timer);
+	dev->watchdog_timer.data = (unsigned long)dev;
+	dev->watchdog_timer.function = dev_watchdog;
 }
 
-/* Scan transmission queue and kick devices.
-
-   Deficiency: slow devices (ppp) and fast ones (100Mb ethernet)
-   share one queue. This means that if we have a lot of loaded ppp channels,
-   we will scan a long list on every 100Mb EOI.
-   I have no idea how to solve it using only "anonymous" Linux mark_bh().
-
-   To change queue from device interrupt? Ough... only not this...
-
-   This function is called only from net_bh.
- */
-
-void qdisc_run_queues(void)
+static void dev_watchdog_up(struct net_device *dev)
 {
-	struct Qdisc_head lh, *h;
-
-	spin_lock(&qdisc_runqueue_lock);
-	if (!qdisc_init_run(&lh))
-		goto out;
-
-	while ((h = lh.forw) != &lh) {
-		int res;
-		struct net_device *dev;
-		struct Qdisc *q = (struct Qdisc*)h;
-
-		qdisc_stop_run(q);
+	spin_lock_bh(&dev->xmit_lock);
 
-		dev = q->dev;
-
-		res = -1;
-		if (spin_trylock(&dev->queue_lock)) {
-			spin_unlock(&qdisc_runqueue_lock);
-			while (!dev->tbusy && (res = qdisc_restart(dev)) < 0)
-				/* NOTHING */;
-			spin_lock(&qdisc_runqueue_lock);
-			spin_unlock(&dev->queue_lock);
-		}
-
-		/* If qdisc is not empty add it to the tail of list */
-		if (res)
-			qdisc_continue_run(dev->qdisc);
+	if (dev->tx_timeout) {
+		if (dev->watchdog_timeo <= 0)
+			dev->watchdog_timeo = 5*HZ;
+		if (!del_timer(&dev->watchdog_timer))
+			dev_hold(dev);
+		dev->watchdog_timer.expires = jiffies + dev->watchdog_timeo;
+		add_timer(&dev->watchdog_timer);
 	}
-out:
-	spin_unlock(&qdisc_runqueue_lock);
+	spin_unlock_bh(&dev->xmit_lock);
 }
 
-/* Periodic watchdog timer to recover from hard/soft device bugs. */
-
-static void dev_do_watchdog(unsigned long dummy);
-
-static struct timer_list dev_watchdog =
-	{ NULL, NULL, 0L, 0L, &dev_do_watchdog };
-
-/*   This function is called only from timer */
-
-static void dev_do_watchdog(unsigned long dummy)
+static void dev_watchdog_down(struct net_device *dev)
 {
-	struct Qdisc_head lh, *h;
-
-	if (!spin_trylock(&qdisc_runqueue_lock)) {
-		/* No hurry with watchdog. */
-		mod_timer(&dev_watchdog, jiffies + HZ/10);
-		return;
-	}
-
-	if (!qdisc_init_run(&lh))
-		goto out;
-
-	while ((h = lh.forw) != &lh) {
-		struct net_device *dev;
-		struct Qdisc *q = (struct Qdisc*)h;
+	spin_lock_bh(&dev->xmit_lock);
 
-		qdisc_stop_run(q);
-
-		dev = q->dev;
-
-		if (spin_trylock(&dev->queue_lock)) {
-			spin_unlock(&qdisc_runqueue_lock);
-			q = dev->qdisc;
-			if (dev->tbusy && jiffies - q->tx_last > q->tx_timeo)
-				qdisc_restart(dev);
-			spin_lock(&qdisc_runqueue_lock);
-			spin_unlock(&dev->queue_lock);
-		}
-
-		qdisc_continue_run(dev->qdisc);
+	if (dev->tx_timeout) {
+		if (del_timer(&dev->watchdog_timer))
+			__dev_put(dev);
 	}
-
-out:
-	mod_timer(&dev_watchdog, jiffies + 5*HZ);
-	spin_unlock(&qdisc_runqueue_lock);
+	spin_unlock_bh(&dev->xmit_lock);
 }
 
 
-
 /* "NOOP" scheduler: the best scheduler, recommended for all interfaces
    under all circumstances. It is difficult to invent anything faster or
    cheaper.
@@ -321,7 +237,6 @@
 
 struct Qdisc noop_qdisc =
 {
-        { NULL }, 
 	noop_enqueue,
 	noop_dequeue,
 	TCQ_F_BUILTIN,
@@ -344,7 +259,6 @@
 
 struct Qdisc noqueue_qdisc =
 {
-        { NULL }, 
 	NULL,
 	noop_dequeue,
 	TCQ_F_BUILTIN,
@@ -476,6 +390,7 @@
 void qdisc_reset(struct Qdisc *qdisc)
 {
 	struct Qdisc_ops *ops = qdisc->ops;
+
 	if (ops->reset)
 		ops->reset(qdisc);
 }
@@ -540,15 +455,10 @@
 	}
 
 	spin_lock_bh(&dev->queue_lock);
-	spin_lock(&qdisc_runqueue_lock);
 	if ((dev->qdisc = dev->qdisc_sleeping) != &noqueue_qdisc) {
-		dev->qdisc->tx_timeo = 5*HZ;
-		dev->qdisc->tx_last = jiffies - dev->qdisc->tx_timeo;
-		if (!del_timer(&dev_watchdog))
-			dev_watchdog.expires = jiffies + 5*HZ;
-		add_timer(&dev_watchdog);
+		dev->trans_start = jiffies;
+		dev_watchdog_up(dev);
 	}
-	spin_unlock(&qdisc_runqueue_lock);
 	spin_unlock_bh(&dev->queue_lock);
 }
 
@@ -557,17 +467,20 @@
 	struct Qdisc *qdisc;
 
 	spin_lock_bh(&dev->queue_lock);
-	spin_lock(&qdisc_runqueue_lock);
 	qdisc = dev->qdisc;
 	dev->qdisc = &noop_qdisc;
 
 	qdisc_reset(qdisc);
 
-	if (qdisc_on_runqueue(qdisc))
-		qdisc_stop_run(qdisc);
-	spin_unlock(&qdisc_runqueue_lock);
 	spin_unlock_bh(&dev->queue_lock);
 
+	dev_watchdog_down(dev);
+
+	if (test_bit(LINK_STATE_SCHED, &dev->state)) {
+		current->policy |= SCHED_YIELD;
+		schedule();
+	}
+
 	spin_unlock_wait(&dev->xmit_lock);
 }
 
@@ -580,6 +493,8 @@
 	dev->qdisc_sleeping = &noop_qdisc;
 	dev->qdisc_list = NULL;
 	write_unlock(&qdisc_tree_lock);
+
+	dev_watchdog_init(dev);
 }
 
 void dev_shutdown(struct net_device *dev)
@@ -599,6 +514,7 @@
         }
 #endif
 	BUG_TRAP(dev->qdisc_list == NULL);
+	BUG_TRAP(dev->watchdog_timer.prev == NULL);
 	dev->qdisc_list = NULL;
 	spin_unlock_bh(&dev->queue_lock);
 	write_unlock(&qdisc_tree_lock);
diff -u --recursive --new-file v2.3.42/linux/net/sched/sch_tbf.c linux/net/sched/sch_tbf.c
--- v2.3.42/linux/net/sched/sch_tbf.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/sch_tbf.c	Wed Feb  9 20:08:09 2000
@@ -186,7 +186,7 @@
 	struct Qdisc *sch = (struct Qdisc*)arg;
 
 	sch->flags &= ~TCQ_F_THROTTLED;
-	qdisc_wakeup(sch->dev);
+	netif_schedule(sch->dev);
 }
 
 static struct sk_buff *
@@ -226,7 +226,7 @@
 			return skb;
 		}
 
-		if (!sch->dev->tbusy) {
+		if (!test_bit(LINK_STATE_XOFF, &sch->dev->state)) {
 			long delay = PSCHED_US2JIFFIE(max(-toks, -ptoks));
 
 			if (delay == 0)
diff -u --recursive --new-file v2.3.42/linux/net/sched/sch_teql.c linux/net/sched/sch_teql.c
--- v2.3.42/linux/net/sched/sch_teql.c	Fri Jan  7 19:13:23 2000
+++ linux/net/sched/sch_teql.c	Wed Feb  9 20:08:09 2000
@@ -126,10 +126,7 @@
 		struct net_device *m = dat->m->dev.qdisc->dev;
 		if (m) {
 			dat->m->slaves = sch;
-			spin_lock(&m->queue_lock);
-			m->tbusy = 0;
-			qdisc_restart(m);
-			spin_unlock(&m->queue_lock);
+			netif_wake_queue(m);
 		}
 	}
 	sch->q.qlen = dat->q.qlen + dat->m->dev.qdisc->q.qlen;
@@ -285,8 +282,6 @@
 	int len = skb->len;
 	struct sk_buff *skb_res = NULL;
 
-	dev->tbusy = 1;
-
 	start = master->slaves;
 
 restart:
@@ -301,23 +296,22 @@
 		
 		if (slave->qdisc_sleeping != q)
 			continue;
-		if (slave->tbusy) {
+		if (test_bit(LINK_STATE_XOFF, &slave->state) ||
+		    test_bit(LINK_STATE_DOWN, &slave->state)) {
 			busy = 1;
 			continue;
 		}
 
-		if (!qdisc_on_runqueue(q))
-			qdisc_run(q);
-
 		switch (teql_resolve(skb, skb_res, slave)) {
 		case 0:
 			if (spin_trylock(&slave->xmit_lock)) {
 				slave->xmit_lock_owner = smp_processor_id();
-				if (slave->hard_start_xmit(skb, slave) == 0) {
+				if (!test_bit(LINK_STATE_XOFF, &slave->state) &&
+				    slave->hard_start_xmit(skb, slave) == 0) {
 					slave->xmit_lock_owner = -1;
 					spin_unlock(&slave->xmit_lock);
 					master->slaves = NEXT_SLAVE(q);
-					dev->tbusy = 0;
+					netif_wake_queue(dev);
 					master->stats.tx_packets++;
 					master->stats.tx_bytes += len;
 					return 0;
@@ -325,12 +319,11 @@
 				slave->xmit_lock_owner = -1;
 				spin_unlock(&slave->xmit_lock);
 			}
-			if (dev->tbusy)
+			if (test_bit(LINK_STATE_XOFF, &dev->state))
 				busy = 1;
 			break;
 		case 1:
 			master->slaves = NEXT_SLAVE(q);
-			dev->tbusy = 0;
 			return 0;
 		default:
 			nores = 1;
@@ -344,9 +337,10 @@
 		goto restart;
 	}
 
-	dev->tbusy = busy;
-	if (busy)
+	if (busy) {
+		netif_stop_queue(dev);
 		return 1;
+	}
 	master->stats.tx_errors++;
 
 drop:
@@ -393,13 +387,14 @@
 
 	m->dev.mtu = mtu;
 	m->dev.flags = (m->dev.flags&~FMASK) | flags;
-	m->dev.tbusy = 0;
+	netif_start_queue(&m->dev);
 	MOD_INC_USE_COUNT;
 	return 0;
 }
 
 static int teql_master_close(struct net_device *dev)
 {
+	netif_stop_queue(dev);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
diff -u --recursive --new-file v2.3.42/linux/net/socket.c linux/net/socket.c
--- v2.3.42/linux/net/socket.c	Fri Jan 28 15:09:09 2000
+++ linux/net/socket.c	Wed Feb  9 20:08:09 2000
@@ -106,18 +106,15 @@
  */
 
 static struct file_operations socket_file_ops = {
-	sock_lseek,
-	sock_read,
-	sock_write,
-	NULL,			/* readdir */
-	sock_poll,
-	sock_ioctl,
-	sock_mmap,
-	sock_no_open,		/* special open code to disallow open via /proc */
-	NULL,			/* flush */
-	sock_close,
-	NULL,			/* no fsync */
-	sock_fasync
+	llseek:		sock_lseek,
+	read:		sock_read,
+	write:		sock_write,
+	poll:		sock_poll,
+	ioctl:		sock_ioctl,
+	mmap:		sock_mmap,
+	open:		sock_no_open,	/* special open code to disallow open via /proc */
+	release:	sock_close,
+	fasync:		sock_fasync
 };
 
 /*
@@ -272,12 +269,12 @@
 			goto out;
 		}
 
+		sock->file = file;
 		file->f_op = &socket_file_ops;
 		file->f_mode = 3;
 		file->f_flags = O_RDWR;
 		file->f_pos = 0;
 		fd_install(fd, file);
-		sock->file = file;
 	}
 
 out:
@@ -588,9 +585,9 @@
  *	   i.e. under semaphore.
  *	2. fasync_list is used under read_lock(&sk->callback_lock)
  *	   or under socket lock.
- *	3. fasync_list is used from any context including IRQ, so that
+ *	3. fasync_list can be used from softirq context, so that
  *	   modification under socket lock have to be enhanced with
- *	   write_lock_irq(&sk->callback_lock).
+ *	   write_lock_bh(&sk->callback_lock).
  *							--ANK (990710)
  */
 
@@ -625,9 +622,9 @@
 	{
 		if(fa!=NULL)
 		{
-			write_lock_irq(&sk->callback_lock);
+			write_lock_bh(&sk->callback_lock);
 			fa->fa_fd=fd;
-			write_unlock_irq(&sk->callback_lock);
+			write_unlock_bh(&sk->callback_lock);
 
 			kfree_s(fna,sizeof(struct fasync_struct));
 			goto out;
@@ -636,17 +633,17 @@
 		fna->fa_fd=fd;
 		fna->magic=FASYNC_MAGIC;
 		fna->fa_next=sock->fasync_list;
-		write_lock_irq(&sk->callback_lock);
+		write_lock_bh(&sk->callback_lock);
 		sock->fasync_list=fna;
-		write_unlock_irq(&sk->callback_lock);
+		write_unlock_bh(&sk->callback_lock);
 	}
 	else
 	{
 		if (fa!=NULL)
 		{
-			write_lock_irq(&sk->callback_lock);
+			write_lock_bh(&sk->callback_lock);
 			*prev=fa->fa_next;
-			write_unlock_irq(&sk->callback_lock);
+			write_unlock_bh(&sk->callback_lock);
 			kfree_s(fa,sizeof(struct fasync_struct));
 		}
 	}
@@ -929,7 +926,7 @@
 		goto out_release;
 
 	if (upeer_sockaddr) {
-		if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 1)<0) {
+		if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) {
 			err = -ECONNABORTED;
 			goto out_release;
 		}
@@ -938,9 +935,8 @@
 			goto out_release;
 	}
 
-	/* File flags are inherited via accept(). It looks silly, but we
-	 * have to be compatible with another OSes.
-	 */
+	/* File flags are not inherited via accept() unlike another OSes. */
+
 	if ((err = sock_map_fd(newsock)) < 0)
 		goto out_release;
 
diff -u --recursive --new-file v2.3.42/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.3.42/linux/net/sunrpc/sched.c	Fri Oct 22 13:21:56 1999
+++ linux/net/sunrpc/sched.c	Wed Feb  9 20:08:09 2000
@@ -130,12 +130,11 @@
 int
 rpc_add_wait_queue(struct rpc_wait_queue *q, struct rpc_task *task)
 {
-	unsigned long oldflags;
 	int result;
 
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	result = __rpc_add_wait_queue(q, task);
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 	return result;
 }
 
@@ -160,11 +159,9 @@
 void
 rpc_remove_wait_queue(struct rpc_task *task)
 {
-	unsigned long oldflags;
-
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	__rpc_remove_wait_queue(task);
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 }
 
 /*
@@ -286,13 +283,12 @@
 rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
 				rpc_action action, rpc_action timer)
 {
-	unsigned long	oldflags;
 	/*
 	 * Protect the queue operations.
 	 */
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	__rpc_sleep_on(q, task, action, timer);
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 }
 
 /*
@@ -342,11 +338,9 @@
 void
 rpc_wake_up_task(struct rpc_task *task)
 {
-	unsigned long	oldflags;
-
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	__rpc_wake_up(task);
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 }
 
 /*
@@ -355,14 +349,13 @@
 struct rpc_task *
 rpc_wake_up_next(struct rpc_wait_queue *queue)
 {
-	unsigned long	oldflags;
 	struct rpc_task	*task;
 
 	dprintk("RPC:      wake_up_next(%p \"%s\")\n", queue, rpc_qname(queue));
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	if ((task = queue->task) != 0)
 		__rpc_wake_up(task);
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 
 	return task;
 }
@@ -373,12 +366,10 @@
 void
 rpc_wake_up(struct rpc_wait_queue *queue)
 {
-	unsigned long	oldflags;
-
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	while (queue->task)
 		__rpc_wake_up(queue->task);
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 }
 
 /*
@@ -388,14 +379,13 @@
 rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
 {
 	struct rpc_task	*task;
-	unsigned long	oldflags;
 
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	while ((task = queue->task) != NULL) {
 		task->tk_status = status;
 		__rpc_wake_up(task);
 	}
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 }
 
 /*
@@ -422,7 +412,6 @@
 static int
 __rpc_execute(struct rpc_task *task)
 {
-	unsigned long	oldflags;
 	int		status = 0;
 
 	dprintk("RPC: %4d rpc_execute flgs %x\n",
@@ -476,13 +465,13 @@
 		 * and the RPC reply arrives before we get here, it will
 		 * have state RUNNING, but will still be on schedq.
 		 */
-		spin_lock_irqsave(&rpc_queue_lock, oldflags);
+		spin_lock_bh(&rpc_queue_lock);
 		if (RPC_IS_RUNNING(task)) {
 			if (task->tk_rpcwait == &schedq)
 				__rpc_remove_wait_queue(task);
 		} else while (!RPC_IS_RUNNING(task)) {
 			if (RPC_IS_ASYNC(task)) {
-				spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+				spin_unlock_bh(&rpc_queue_lock);
 				return 0;
 			}
 
@@ -492,9 +481,9 @@
 			if (current->pid == rpciod_pid)
 				printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
 
-			spin_unlock_irq(&rpc_queue_lock);
+			spin_unlock_bh(&rpc_queue_lock);
 			__wait_event(task->tk_wait, RPC_IS_RUNNING(task));
-			spin_lock_irq(&rpc_queue_lock);
+			spin_lock_bh(&rpc_queue_lock);
 
 			/*
 			 * When the task received a signal, remove from
@@ -506,7 +495,7 @@
 			dprintk("RPC: %4d sync task resuming\n",
 							task->tk_pid);
 		}
-		spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+		spin_unlock_bh(&rpc_queue_lock);
 
 		/*
 		 * When a sync task receives a signal, it exits with
@@ -562,20 +551,19 @@
 {
 	struct rpc_task	*task;
 	int		count = 0;
-	unsigned long	oldflags;
 	int need_resched = current->need_resched;
 
 	dprintk("RPC:      rpc_schedule enter\n");
 	while (1) {
-		spin_lock_irqsave(&rpc_queue_lock, oldflags);
+		spin_lock_bh(&rpc_queue_lock);
 		if (!(task = schedq.task)) {
-			spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+			spin_unlock_bh(&rpc_queue_lock);
 			break;
 		}
 		rpc_del_timer(task);
 		__rpc_remove_wait_queue(task);
 		task->tk_flags |= RPC_TASK_RUNNING;
-		spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+		spin_unlock_bh(&rpc_queue_lock);
 
 		__rpc_execute(task);
 
@@ -726,7 +714,6 @@
 rpc_release_task(struct rpc_task *task)
 {
 	struct rpc_task	*next, *prev;
-	unsigned long	oldflags;
 
 	dprintk("RPC: %4d release task\n", task->tk_pid);
 
@@ -744,7 +731,7 @@
 	spin_unlock(&rpc_sched_lock);
 
 	/* Protect the execution below. */
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 
 	/* Delete any running timer */
 	rpc_del_timer(task);
@@ -752,7 +739,7 @@
 	/* Remove from any wait queue we're still on */
 	__rpc_remove_wait_queue(task);
 
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 
 	/* Release resources */
 	if (task->tk_rqstp)
@@ -800,15 +787,14 @@
 static void
 rpc_child_exit(struct rpc_task *child)
 {
-	unsigned long	oldflags;
 	struct rpc_task	*parent;
 
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	if ((parent = rpc_find_parent(child)) != NULL) {
 		parent->tk_status = child->tk_status;
 		__rpc_wake_up(parent);
 	}
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 	rpc_release_task(child);
 }
 
@@ -835,13 +821,11 @@
 void
 rpc_run_child(struct rpc_task *task, struct rpc_task *child, rpc_action func)
 {
-	unsigned long oldflags;
-
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	/* N.B. Is it possible for the child to have already finished? */
 	__rpc_sleep_on(&childq, task, func, NULL);
 	rpc_make_runnable(child);
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 }
 
 /*
diff -u --recursive --new-file v2.3.42/linux/net/sunrpc/svc.c linux/net/sunrpc/svc.c
--- v2.3.42/linux/net/sunrpc/svc.c	Fri Jan 21 18:19:17 2000
+++ linux/net/sunrpc/svc.c	Wed Feb  9 20:08:09 2000
@@ -45,6 +45,7 @@
 	serv->sv_stats     = prog->pg_stats;
 	serv->sv_bufsz	   = bufsize? bufsize : 4096;
 	serv->sv_xdrsize   = xdrsize;
+	spin_lock_init(&serv->sv_lock);
 
 	serv->sv_name      = prog->pg_name;
 
diff -u --recursive --new-file v2.3.42/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.3.42/linux/net/sunrpc/svcsock.c	Fri Jan 21 18:19:17 2000
+++ linux/net/sunrpc/svcsock.c	Thu Feb 10 12:16:38 2000
@@ -33,15 +33,20 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/ip.h>
-#if LINUX_VERSION_CODE >= 0x020100
 #include <asm/uaccess.h>
-#endif
 
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/stats.h>
 
+/* SMP locking strategy:
+ *
+ * 	svc_sock->sk_lock and svc_serv->sv_lock protect their
+ *	respective structures.
+ *
+ *	Antideadlock ordering is sk_lock --> sv_lock.
+ */
 
 #define RPCDBG_FACILITY	RPCDBG_SVCSOCK
 
@@ -54,20 +59,22 @@
 
 
 /*
- * Queue up an idle server thread.
+ * Queue up an idle server thread.  Must have serv->sv_lock held.
  */
 static inline void
 svc_serv_enqueue(struct svc_serv *serv, struct svc_rqst *rqstp)
 {
+	BUG_TRAP(spin_is_locked(&serv->sv_lock));
 	rpc_append_list(&serv->sv_threads, rqstp);
 }
 
 /*
- * Dequeue an nfsd thread.
+ * Dequeue an nfsd thread.  Must have serv->sv_lock held.
  */
 static inline void
 svc_serv_dequeue(struct svc_serv *serv, struct svc_rqst *rqstp)
 {
+	BUG_TRAP(spin_is_locked(&serv->sv_lock));
 	rpc_remove_list(&serv->sv_threads, rqstp);
 }
 
@@ -90,8 +97,8 @@
 /*
  * Queue up a socket with data pending. If there are idle nfsd
  * processes, wake 'em up.
- * When calling this function, you should make sure it can't be interrupted
- * by the network bottom half.
+ *
+ * This must be called with svsk->sk_lock held.
  */
 static void
 svc_sock_enqueue(struct svc_sock *svsk)
@@ -99,6 +106,11 @@
 	struct svc_serv	*serv = svsk->sk_server;
 	struct svc_rqst	*rqstp;
 
+	BUG_TRAP(spin_is_locked(&svsk->sk_lock));
+
+	/* NOTE: Local BH is already disabled by our caller. */
+	spin_lock(&serv->sv_lock);
+
 	if (serv->sv_threads && serv->sv_sockets)
 		printk(KERN_ERR
 			"svc_sock_enqueue: threads and sockets both waiting??\n");
@@ -106,7 +118,7 @@
 	if (svsk->sk_busy) {
 		/* Don't enqueue socket while daemon is receiving */
 		dprintk("svc: socket %p busy, not enqueued\n", svsk->sk_sk);
-		return;
+		goto out_unlock;
 	}
 
 	/* Mark socket as busy. It will remain in this state until the
@@ -131,20 +143,23 @@
 		rpc_append_list(&serv->sv_sockets, svsk);
 		svsk->sk_qued = 1;
 	}
+
+out_unlock:
+	spin_unlock(&serv->sv_lock);
 }
 
 /*
- * Dequeue the first socket.
+ * Dequeue the first socket.  Must be called with the serv->sv_lock held.
  */
 static inline struct svc_sock *
 svc_sock_dequeue(struct svc_serv *serv)
 {
 	struct svc_sock	*svsk;
 
-	start_bh_atomic();
+	BUG_TRAP(spin_is_locked(&serv->sv_lock));
+
 	if ((svsk = serv->sv_sockets) != NULL)
 		rpc_remove_list(&serv->sv_sockets, svsk);
-	end_bh_atomic();
 
 	if (svsk) {
 		dprintk("svc: socket %p dequeued, inuse=%d\n",
@@ -162,7 +177,7 @@
 static inline void
 svc_sock_received(struct svc_sock *svsk, int count)
 {
-	start_bh_atomic();
+	spin_lock_bh(&svsk->sk_lock);
 	if ((svsk->sk_data -= count) < 0) {
 		printk(KERN_NOTICE "svc: sk_data negative!\n");
 		svsk->sk_data = 0;
@@ -174,7 +189,7 @@
 						svsk->sk_sk);
 		svc_sock_enqueue(svsk);
 	}
-	end_bh_atomic();
+	spin_unlock_bh(&svsk->sk_lock);
 }
 
 /*
@@ -183,7 +198,7 @@
 static inline void
 svc_sock_accepted(struct svc_sock *svsk)
 {
-	start_bh_atomic();
+	spin_lock_bh(&svsk->sk_lock);
         svsk->sk_busy = 0;
         svsk->sk_conn--;
         if (svsk->sk_conn || svsk->sk_data || svsk->sk_close) {
@@ -191,7 +206,7 @@
 						svsk->sk_sk);
                 svc_sock_enqueue(svsk);
         }
-	end_bh_atomic();
+	spin_unlock_bh(&svsk->sk_lock);
 }
 
 /*
@@ -221,6 +236,7 @@
 {
 	struct svc_rqst	*rqstp;
 
+	spin_lock_bh(&serv->sv_lock);
 	if ((rqstp = serv->sv_threads) != NULL) {
 		dprintk("svc: daemon %p woken up.\n", rqstp);
 		/*
@@ -229,6 +245,7 @@
 		 */
 		wake_up(&rqstp->rq_wait);
 	}
+	spin_unlock_bh(&serv->sv_lock);
 }
 
 /*
@@ -252,24 +269,14 @@
 	msg.msg_control = NULL;
 	msg.msg_controllen = 0;
 
-#if LINUX_VERSION_CODE >= 0x020100
 	msg.msg_flags	= MSG_DONTWAIT;
 
 	oldfs = get_fs(); set_fs(KERNEL_DS);
 	len = sock_sendmsg(sock, &msg, buflen);
 	set_fs(oldfs);
-#else
-	msg.msg_flags	= 0;
-
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	len = sock->ops->sendmsg(sock, &msg, buflen, 1, 0);
-	set_fs(oldfs);
-#endif
 
-	dprintk("svc: socket %p sendto([%p %lu... ], %d, %d) = %d\n",
-		rqstp->rq_sock, iov[0].iov_base,
-		(unsigned long) iov[0].iov_len, nr,
-		buflen, len);
+	dprintk("svc: socket %p sendto([%p %Zu... ], %d, %d) = %d\n",
+			rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, nr, buflen, len);
 
 	return len;
 }
@@ -312,22 +319,14 @@
 	msg.msg_control = NULL;
 	msg.msg_controllen = 0;
 
-#if LINUX_VERSION_CODE >= 0x020100
 	msg.msg_flags	= MSG_DONTWAIT;
 
 	oldfs = get_fs(); set_fs(KERNEL_DS);
 	len = sock_recvmsg(sock, &msg, buflen, MSG_DONTWAIT);
 	set_fs(oldfs);
-#else
-	msg.msg_flags	= 0;
 
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	len = sock->ops->recvmsg(sock, &msg, buflen, 0, 1, &rqstp->rq_addrlen);
-	set_fs(oldfs);
-#endif
-
-	dprintk("svc: socket %p recvfrom(%p, %lu) = %d\n", rqstp->rq_sock,
-		iov[0].iov_base, (unsigned long) iov[0].iov_len, len);
+	dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
+		rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
 
 	return len;
 }
@@ -344,8 +343,10 @@
 		return;
 	dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
 		svsk, sk, count, svsk->sk_busy);
+	spin_lock_bh(&svsk->sk_lock);
 	svsk->sk_data = 1;
 	svc_sock_enqueue(svsk);
+	spin_unlock_bh(&svsk->sk_lock);
 }
 
 /*
@@ -385,11 +386,7 @@
 	/* Get sender address */
 	rqstp->rq_addr.sin_family = AF_INET;
 	rqstp->rq_addr.sin_port = skb->h.uh->source;
-#if LINUX_VERSION_CODE >= 0x020100
 	rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
-#else
-	rqstp->rq_addr.sin_addr.s_addr = skb->saddr;
-#endif
 
 	if (serv->sv_stats)
 		serv->sv_stats->netudpcnt++;
@@ -456,8 +453,10 @@
 		printk("svc: socket %p: no user data\n", sk);
 		return;
 	}
+	spin_lock_bh(&svsk->sk_lock);
 	svsk->sk_conn++;
 	svc_sock_enqueue(svsk);
+	spin_unlock_bh(&svsk->sk_lock);
 }
 
 /*
@@ -475,8 +474,10 @@
 		printk("svc: socket %p: no user data\n", sk);
 		return;
 	}
+	spin_lock_bh(&svsk->sk_lock);
 	svsk->sk_close = 1;
 	svc_sock_enqueue(svsk);
+	spin_unlock_bh(&svsk->sk_lock);
 }
 
 static void
@@ -494,8 +495,10 @@
 			sk, sk->user_data);
 	if (!(svsk = (struct svc_sock *)(sk->user_data)))
 		return;
+	spin_lock_bh(&svsk->sk_lock);
 	svsk->sk_data++;
 	svc_sock_enqueue(svsk);
+	spin_unlock_bh(&svsk->sk_lock);
 }
 
 /*
@@ -562,9 +565,11 @@
 	/* Precharge. Data may have arrived on the socket before we
 	 * installed the data_ready callback. 
 	 */
+	spin_lock_bh(&newsvsk->sk_lock);
 	newsvsk->sk_data = 1;
 	newsvsk->sk_temp = 1;
 	svc_sock_enqueue(newsvsk);
+	spin_unlock_bh(&newsvsk->sk_lock);
 
 	if (serv->sv_stats)
 		serv->sv_stats->nettcpconn++;
@@ -758,7 +763,7 @@
 	if (signalled())
 		return -EINTR;
 
-	start_bh_atomic();
+	spin_lock_bh(&serv->sv_lock);
 	if ((svsk = svc_sock_dequeue(serv)) != NULL) {
 		rqstp->rq_sock = svsk;
 		svsk->sk_inuse++;
@@ -772,20 +777,21 @@
 		 */
 		current->state = TASK_INTERRUPTIBLE;
 		add_wait_queue(&rqstp->rq_wait, &wait);
-		end_bh_atomic();
+		spin_unlock_bh(&serv->sv_lock);
+
 		schedule_timeout(timeout);
 
+		spin_lock_bh(&serv->sv_lock);
 		remove_wait_queue(&rqstp->rq_wait, &wait);
 
-		start_bh_atomic();
 		if (!(svsk = rqstp->rq_sock)) {
 			svc_serv_dequeue(serv, rqstp);
-			end_bh_atomic();
+			spin_unlock_bh(&serv->sv_lock);
 			dprintk("svc: server %p, no data yet\n", rqstp);
 			return signalled()? -EINTR : -EAGAIN;
 		}
 	}
-	end_bh_atomic();
+	spin_unlock_bh(&serv->sv_lock);
 
 	dprintk("svc: server %p, socket %p, inuse=%d\n",
 		 rqstp, svsk, svsk->sk_inuse);
@@ -867,17 +873,14 @@
 	}
 	memset(svsk, 0, sizeof(*svsk));
 
-#if LINUX_VERSION_CODE >= 0x020100
 	inet = sock->sk;
-#else
-	inet = (struct sock *) sock->data;
-#endif
 	inet->user_data = svsk;
 	svsk->sk_sock = sock;
 	svsk->sk_sk = inet;
 	svsk->sk_ostate = inet->state_change;
 	svsk->sk_odata = inet->data_ready;
 	svsk->sk_server = serv;
+	spin_lock_init(&svsk->sk_lock);
 
 	/* Initialize the socket */
 	if (sock->type == SOCK_DGRAM)
@@ -897,8 +900,10 @@
 		return NULL;
 	}
 
+	spin_lock_bh(&serv->sv_lock);
 	svsk->sk_list = serv->sv_allsocks;
 	serv->sv_allsocks = svsk;
+	spin_unlock_bh(&serv->sv_lock);
 
 	dprintk("svc: svc_setup_socket created %p (inet %p)\n",
 				svsk, svsk->sk_sk);
@@ -971,16 +976,22 @@
 	sk->state_change = svsk->sk_ostate;
 	sk->data_ready = svsk->sk_odata;
 
+	spin_lock_bh(&serv->sv_lock);
+
 	for (rsk = &serv->sv_allsocks; *rsk; rsk = &(*rsk)->sk_list) {
 		if (*rsk == svsk)
 			break;
 	}
-	if (!*rsk)
+	if (!*rsk) {
+		spin_unlock_bh(&serv->sv_lock);
 		return;
+	}
 	*rsk = svsk->sk_list;
-
 	if (svsk->sk_qued)
 		rpc_remove_list(&serv->sv_sockets, svsk);
+
+	spin_unlock_bh(&serv->sv_lock);
+
 	svsk->sk_dead = 1;
 
 	if (!svsk->sk_inuse) {
diff -u --recursive --new-file v2.3.42/linux/net/sunrpc/sysctl.c linux/net/sunrpc/sysctl.c
--- v2.3.42/linux/net/sunrpc/sysctl.c	Thu Nov 18 20:25:38 1999
+++ linux/net/sunrpc/sysctl.c	Thu Feb 10 12:16:38 2000
@@ -76,13 +76,8 @@
 		if (!access_ok(VERIFY_READ, buffer, left))
 			return -EFAULT;
 		p = (char *) buffer;
-#if LINUX_VERSION_CODE >= 0x020100
 		while (left && __get_user(c, p) >= 0 && isspace(c))
 			left--, p++;
-#else
-		while (left && (c = get_fs_byte(p)) >= 0 && isspace(c))
-			left--, p++;
-#endif
 		if (!left)
 			goto done;
 
diff -u --recursive --new-file v2.3.42/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.3.42/linux/net/sunrpc/xprt.c	Fri Jan 28 15:09:09 2000
+++ linux/net/sunrpc/xprt.c	Thu Feb 10 12:16:38 2000
@@ -65,17 +65,9 @@
 
 #include <asm/uaccess.h>
 
-#define SOCK_HAS_USER_DATA
 /* Following value should be > 32k + RPC overhead */
 #define XPRT_MIN_WRITE_SPACE 35000
 
-/*
- * Local variables
- */
-#ifndef SOCK_HAS_USER_DATA
-static struct rpc_xprt *	sock_list = NULL;
-#endif
-
 /* Spinlock for critical sections in the code. */
 spinlock_t xprt_lock = SPIN_LOCK_UNLOCKED;
 
@@ -140,15 +132,7 @@
 static inline struct rpc_xprt *
 xprt_from_sock(struct sock *sk)
 {
-#ifndef SOCK_HAS_USER_DATA
-	struct rpc_xprt		*xprt;
-
-	for (xprt = sock_list; xprt && sk != xprt->inet; xprt = xprt->link)
-		;
-	return xprt;
-#else
 	return (struct rpc_xprt *) sk->user_data;
-#endif
 }
 
 /*
@@ -352,9 +336,7 @@
 
 	xprt_disconnect(xprt);
 
-#ifdef SOCK_HAS_USER_DATA
 	sk->user_data    = NULL;
-#endif
 	sk->data_ready   = xprt->old_data_ready;
 	sk->state_change = xprt->old_state_change;
 	sk->write_space  = xprt->old_write_space;
@@ -409,19 +391,19 @@
 	if (!xprt->stream)
 		return;
 
-	start_bh_atomic();
+	spin_lock_bh(&xprt_lock);
 	if (xprt->connected) {
-		end_bh_atomic();
+		spin_unlock_bh(&xprt_lock);
 		return;
 	}
 	if (xprt->connecting) {
 		task->tk_timeout = xprt->timeout.to_maxval;
 		rpc_sleep_on(&xprt->reconn, task, NULL, NULL);
-		end_bh_atomic();
+		spin_unlock_bh(&xprt_lock);
 		return;
 	}
 	xprt->connecting = 1;
-	end_bh_atomic();
+	spin_unlock_bh(&xprt_lock);
 
 	/* Create an unconnected socket */
 	if (!(sock = xprt_create_socket(xprt->prot, NULL, &xprt->timeout))) {
@@ -433,9 +415,7 @@
 	inet->data_ready   = xprt->inet->data_ready;
 	inet->state_change = xprt->inet->state_change;
 	inet->write_space  = xprt->inet->write_space;
-#ifdef SOCK_HAS_USER_DATA
 	inet->user_data    = xprt;
-#endif
 
 	dprintk("RPC: %4d closing old socket\n", task->tk_pid);
 	xprt_close(xprt);
@@ -460,22 +440,22 @@
 				task->tk_pid, status, xprt->connected);
 		task->tk_timeout = 60 * HZ;
 
-		start_bh_atomic();
+		spin_lock_bh(&xprt_lock);
 		if (!xprt->connected) {
 			rpc_sleep_on(&xprt->reconn, task,
 				NULL, xprt_reconn_timeout);
-			end_bh_atomic();
+			spin_unlock_bh(&xprt_lock);
 			return;
 		}
-		end_bh_atomic();
+		spin_unlock_bh(&xprt_lock);
 	}
 
 
 defer:
-	start_bh_atomic();
+	spin_lock_bh(&xprt_lock);
 	if (!xprt->connected)
 		rpc_wake_up_next(&xprt->reconn);
-	end_bh_atomic();
+	spin_unlock_bh(&xprt_lock);
 }
 
 /*
@@ -485,34 +465,36 @@
 static void
 xprt_reconn_timeout(struct rpc_task *task)
 {
+	spin_lock_bh(&xprt_lock);
 	dprintk("RPC: %4d xprt_reconn_timeout %d\n",
 				task->tk_pid, task->tk_status);
 	task->tk_status = -ENOTCONN;
-	start_bh_atomic();
 	if (task->tk_xprt->connecting)
 		task->tk_xprt->connecting = 0;
 	if (!task->tk_xprt->connected)
 		task->tk_status = -ENOTCONN;
 	else
 		task->tk_status = -ETIMEDOUT;
-	end_bh_atomic();
 	task->tk_timeout = 0;
 	rpc_wake_up_task(task);
+	spin_unlock_bh(&xprt_lock);
 }
 
 extern spinlock_t rpc_queue_lock;
 /*
  * Look up the RPC request corresponding to a reply.
+ *
+ * RED-PEN: Niiice... Guys, when will we learn finally that locking
+ * in this manner is NOOP? --ANK
  */
 static inline struct rpc_rqst *
 xprt_lookup_rqst(struct rpc_xprt *xprt, u32 xid)
 {
 	struct rpc_task	*head, *task;
 	struct rpc_rqst	*req;
-	unsigned long	oldflags;
 	int		safe = 0;
 
-	spin_lock_irqsave(&rpc_queue_lock, oldflags);
+	spin_lock_bh(&rpc_queue_lock);
 	if ((head = xprt->pending.task) != NULL) {
 		task = head;
 		do {
@@ -529,7 +511,7 @@
  out_bad:
 	req = NULL;
  out:
-	spin_unlock_irqrestore(&rpc_queue_lock, oldflags);
+	spin_unlock_bh(&rpc_queue_lock);
 	return req;
 }
 
@@ -858,9 +840,10 @@
 
 void rpciod_tcp_dispatcher(void)
 {
-	start_bh_atomic();
+	/* mama... start_bh_atomic was here...
+	   Calls to sock->ops _are_ _impossible_ with disabled bh. Period. --ANK
+	 */
 	do_rpciod_tcp_dispatcher();
-	end_bh_atomic();
 }
 
 int xprt_tcp_pending(void)
@@ -1027,8 +1010,7 @@
 	struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
 	struct rpc_rqst	*req = task->tk_rqstp;
 
-	start_bh_atomic();
-	spin_lock(&xprt_lock);
+	spin_lock_bh(&xprt_lock);
 	if (xprt->snd_task && xprt->snd_task != task) {
 		dprintk("RPC: %4d TCP write queue full (task %d)\n",
 			task->tk_pid, xprt->snd_task->tk_pid);
@@ -1041,8 +1023,7 @@
 #endif
 		req->rq_bytes_sent = 0;
 	}
-	spin_unlock(&xprt_lock);
-	end_bh_atomic();
+	spin_unlock_bh(&xprt_lock);
 	return xprt->snd_task == task;
 }
 
@@ -1055,10 +1036,10 @@
 	struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
 
 	if (xprt->snd_task && xprt->snd_task == task) {
-		start_bh_atomic();
+		spin_lock_bh(&xprt_lock);
 		xprt->snd_task = NULL;
 		rpc_wake_up_next(&xprt->sending);
-		end_bh_atomic();
+		spin_unlock_bh(&xprt_lock);
 	}
 }
 
@@ -1175,16 +1156,16 @@
 		rpc_remove_wait_queue(task);
 
 	/* Protect against (udp|tcp)_write_space */
-	start_bh_atomic();
+	spin_lock_bh(&xprt_lock);
 	if (status == -ENOMEM || status == -EAGAIN) {
 		task->tk_timeout = req->rq_timeout.to_current;
 		if (!xprt->write_space)
 			rpc_sleep_on(&xprt->sending, task, xprt_transmit_status,
 				     xprt_transmit_timeout);
-		end_bh_atomic();
+		spin_unlock_bh(&xprt_lock);
 		return;
 	}
-	end_bh_atomic();
+	spin_unlock_bh(&xprt_lock);
 
 out_release:
 	xprt_up_transmit(task);
@@ -1238,22 +1219,22 @@
 	 */
 	task->tk_timeout = req->rq_timeout.to_current;
 
-	start_bh_atomic();
+	spin_lock_bh(&xprt_lock);
 	if (task->tk_rpcwait)
 		rpc_remove_wait_queue(task);
 
 	if (task->tk_status < 0 || xprt->shutdown) {
-		end_bh_atomic();
+		spin_unlock_bh(&xprt_lock);
 		goto out;
 	}
 
 	if (!req->rq_gotit) {
 		rpc_sleep_on(&xprt->pending, task,
 				xprt_receive_status, xprt_timer);
-		end_bh_atomic();
+		spin_unlock_bh(&xprt_lock);
 		return;
 	}
-	end_bh_atomic();
+	spin_unlock_bh(&xprt_lock);
 
 	dprintk("RPC: %4d xprt_receive returns %d\n",
 				task->tk_pid, task->tk_status);
@@ -1385,13 +1366,13 @@
 	spin_unlock(&xprt_lock);
 
 	/* remove slot from queue of pending */
-	start_bh_atomic();
+	spin_lock_bh(&xprt_lock);
 	if (task->tk_rpcwait) {
 		printk("RPC: task of released request still queued!\n");
 		rpc_del_timer(task);
 		rpc_remove_wait_queue(task);
 	}
-	end_bh_atomic();
+	spin_unlock_bh(&xprt_lock);
 
 	/* Decrease congestion value. */
 	xprt->cong -= RPC_CWNDSCALE;
@@ -1455,12 +1436,7 @@
 	xprt->stream = (proto == IPPROTO_TCP)? 1 : 0;
 	xprt->congtime = jiffies;
 	init_waitqueue_head(&xprt->cong_wait);
-#ifdef SOCK_HAS_USER_DATA
 	inet->user_data = xprt;
-#else
-	xprt->link = sock_list;
-	sock_list = xprt;
-#endif
 	xprt->old_data_ready = inet->data_ready;
 	xprt->old_state_change = inet->state_change;
 	xprt->old_write_space = inet->write_space;
@@ -1626,18 +1602,6 @@
 int
 xprt_destroy(struct rpc_xprt *xprt)
 {
-#ifndef SOCK_HAS_USER_DATA
-	struct rpc_xprt	**q;
-
-	for (q = &sock_list; *q && *q != xprt; q = &((*q)->link))
-		;
-	if (!*q) {
-		printk(KERN_WARNING "xprt_destroy: unknown socket!\n");
-		return -EIO;	/* why is there no EBUGGYSOFTWARE */
-	}
-	*q = xprt->link;
-#endif
-
 	dprintk("RPC:      destroying transport %p\n", xprt);
 	xprt_close(xprt);
 	kfree(xprt);
diff -u --recursive --new-file v2.3.42/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
--- v2.3.42/linux/net/wanrouter/wanproc.c	Fri Jan 28 15:09:09 2000
+++ linux/net/wanrouter/wanproc.c	Thu Feb 10 12:17:00 2000
@@ -90,17 +90,7 @@
  */
 static struct file_operations router_fops =
 {
-	NULL,			/* lseek   */
-	router_proc_read,	/* read	   */
-	NULL,			/* write   */
-	NULL,			/* readdir */
-	NULL,			/* select  */
-	NULL,			/* ioctl   */
-	NULL,			/* mmap	   */
-	NULL,			/* no special open code	   */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
+	read:		router_proc_read,
 };
 
 static struct inode_operations router_inode =
@@ -117,9 +107,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	router_proc_perms,	/* permission */
 	NULL			/* revalidate */
@@ -131,17 +118,8 @@
 
 static struct file_operations wandev_fops =
 {
-	NULL,			/* lseek   */
-	router_proc_read,	/* read	   */
-	NULL,			/* write   */
-	NULL,			/* readdir */
-	NULL,			/* select  */
-	wanrouter_ioctl,	/* ioctl   */
-	NULL,			/* mmap	   */
-	NULL,			/* no special open code	   */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
+	read:		router_proc_read,
+	ioctl:		wanrouter_ioctl,
 };
 
 static struct inode_operations wandev_inode =
@@ -158,9 +136,6 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
 	NULL,			/* truncate */
 	router_proc_perms,	/* permission */
 	NULL			/* revalidate */
