diff -u --recursive --new-file v2.3.23/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.23/linux/Documentation/Configure.help	Fri Oct 22 13:21:43 1999
+++ linux/Documentation/Configure.help	Wed Oct 27 14:21:52 1999
@@ -2200,7 +2200,7 @@
   If you have a S3 Trio say Y. Say N for S3 Virge. 
 
 ATI Mach64 display support
-CONFIG_FB_ATY
+CONFIG_FB_ATY (EXPERIMENTAL)
   This driver supports graphics boards with the ATI Mach64 chips.
   Say Y if you have such a graphics board.
 
@@ -2268,7 +2268,7 @@
   includes a server that supports the frame buffer device directly
   (XF68_FBDev).
 
-Matrox unified accelerated driver
+Matrox unified accelerated driver (EXPERIMENTAL)
 CONFIG_FB_MATROX
   Say Y here if you have Matrox Millennium, Matrox Millennium II,
   Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
@@ -3107,7 +3107,7 @@
   The module will be called af_spx.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-DECnet networking
+DECnet networking (EXPERIMENTAL)
 CONFIG_DECNET
   The DECnet networking protocol was used in many products made by
   Digital (now Compaq). It provides reliable stream and sequenced
@@ -3138,7 +3138,7 @@
    
    If unsure, say N.
 
-DECnet Router Support
+DECnet Router Support (EXPERIMENTAL)
 CONFIG_DECNET_ROUTER
    Add support for turning your DECnet Endnode into a level 1 or 2
    router. This is an unfinished option for developers only. If you do
@@ -3613,7 +3613,7 @@
   can only use one protocol at a time, depending on what the other end
   can understand).
 
-CCITT X.25 Packet Layer
+CCITT X.25 Packet Layer (EXPERIMENTAL)
 CONFIG_X25
   X.25 is a set of standardized network protocols, similar in scope to
   frame relay; the one physical line from your box to the X.25 network
@@ -3663,7 +3663,7 @@
   want), say M here and read Documentation/modules.txt. The module
   will be called lapb.o. If unsure, say N.
 
-802.2 LLC (VERY EXPERIMENTAL)
+802.2 LLC (EXPERIMENTAL)
 CONFIG_LLC
   This is a Logical Link Layer protocol used for X.25 connections over
   Ethernet, using ordinary Ethernet cards. 
@@ -4603,7 +4603,7 @@
 
   There is no safe option and the default answer is recommended.
 
-assume boards are SYMBIOS compatible
+assume boards are SYMBIOS compatible (EXPERIMENTAL)
 CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
   This option allows you to enable some features depending on GPIO
   wiring. These General Purpose Input/Output pins can be used for
@@ -5132,7 +5132,7 @@
 
   Generally, saying N is fine.
 
-SCSI Debug host simulator.
+SCSI Debug host simulator. (EXPERIMENTAL)
 CONFIG_SCSI_DEBUG
   This is a host adapter simulator that can be programmed to simulate
   a large number of conditions that could occur on a real bus. The
@@ -5194,7 +5194,7 @@
   This enables support for the Cumana SCSI I card. If you have an
   Acorn system with one of these, say Y. If unsure, say N.
 
-Cumana SCSI II support
+Cumana SCSI II support (EXPERIMENTAL)
 CONFIG_SCSI_CUMANA_2
   This enables support for the Cumana SCSI II card. If you have an
   Acorn system with one of these, say Y. If unsure, say N.
@@ -5205,12 +5205,12 @@
   in the Econet socket. If you have an Acorn system with one of these,
   say Y. If unsure, say N.
 
-EESOX SCSI support
+EESOX SCSI support (EXPERIMENTAL)
 CONFIG_SCSI_EESOXSCSI
   This enables support for the EESOX SCSI card. If you have an Acorn
   system with one of these, say Y, otherwise say N.
 
-Powertec SCSI support
+Powertec SCSI support (EXPERIMENTAL)
 CONFIG_SCSI_POWERTECSCSI
   This enables support for the Powertec SCSI card on Acorn systems. If
   you have one of these, say Y. If unsure, say N.
@@ -5368,6 +5368,15 @@
   into and removed from the running kernel).  If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
 
+CONFIG_PPP_SYNC_TTY
+  Say Y (or M) here if you want to be able to use PPP over synchronous
+  (HDLC) tty devices, such as the SyncLink adapter. These devices
+  are often used for high-speed leased lines like T1/E1.
+
+  This code is also available as a module (code which can be inserted
+  into and removed from the running kernel).  If you want to compile
+  it as a module, say M here and read Documentation/modules.txt.
+
 PPP Deflate compression
 CONFIG_PPP_DEFLATE
   Support for the Deflate compression method for PPP, which uses the
@@ -5670,7 +5679,7 @@
   module, say M here and read Documentation/modules.txt. If unsure,
   say N.
 
-Ethertap network tap
+Ethertap network tap (EXPERIMENTAL)
 CONFIG_ETHERTAP
   If you say Y here (and have said Y to "Kernel/User network link
   driver", above) and create a character special file /dev/tap0 with
@@ -6185,7 +6194,7 @@
   you say N, the PPP support will not be included in the driver (saves
   about 16 KB of kernel memory).
 
-Cyclom 2X(tm) multiprotocol cards
+Cyclom 2X(tm) multiprotocol cards (EXPERIMENTAL)
 CONFIG_CYCLADES_SYNC
   Cyclom 2X from Cyclades Corporation (http://www.cyclades.com and
   http://www.cyclades.com.br ) is an intelligent multiprotocol WAN
@@ -6378,7 +6387,7 @@
   the questions about NI cards. If you say Y, you will be asked for
   your specific card in the following questions.
 
-NI5010 support
+NI5010 support (EXPERIMENTAL)
 CONFIG_NI5010
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -6983,7 +6992,7 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-Mylex EISA LNE390A/LNE390B support
+Mylex EISA LNE390A/LNE390B support (EXPERIMENTAL)
 CONFIG_LNE390
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -6995,7 +7004,7 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-Novell/Eagle/Microdyne NE3210 EISA support
+Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)
 CONFIG_NE3210
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -7080,7 +7089,7 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-ICL EtherTeam 16i/32 support
+ICL EtherTeam 16i/32 support (EXPERIMENTAL)
 CONFIG_ETH16I
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -7122,7 +7131,7 @@
   a module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
-Racal-Interlan EISA ES3210 support
+Racal-Interlan EISA ES3210 support (EXPERIMENTAL)
 CONFIG_ES3210
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
@@ -7151,7 +7160,7 @@
   Say Y here if you have an Seeq based Ethernet network card. This is
   used in many Silicon Graphics machines.
 
-Zenith Z-Note support
+Zenith Z-Note support (EXPERIMENTAL)
 CONFIG_ZNET
   The Zenith Z-Note notebook computer has a built-in network
   (Ethernet) card, and this is the Linux driver for it. Note that the
@@ -7650,7 +7659,7 @@
   http://metalab.unc.edu/mdw/linux.html#howto . Probably the quota
   support is only useful for multi user systems. If unsure, say N.
 
-Support for USB (EXPERIMENTAL!)
+Support for USB (EXPERIMENTAL)
 CONFIG_USB
   Universal Serial Bus (USB) is a specification for a serial bus
   system which offers higher speeds and more features than the
@@ -7802,6 +7811,16 @@
   The module will be called acm.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+USB Belkin and Peracom serial support
+CONFIG_USB_SERIAL
+  Say Y here if you want to connect a Belkin, Peracom, or eTek
+  single port USB to serial converter.
+  
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-serial.o. If you want to compile it 
+  as a module, say M here and read Documentation/modules.txt.
+
 USB Printer support
 CONFIG_USB_PRINTER
   Say Y here if you want to connect a printer to your computer's USB
@@ -8203,7 +8222,7 @@
   directories that are mount points on the local filesystem (this is
   how nfsd behaves on Sun systems), say Y here. If unsure, say N.
 
-OS/2 HPFS filesystem support (read only)
+OS/2 HPFS filesystem support
 CONFIG_HPFS_FS
   OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
   is the filesystem used for organizing files on OS/2 hard disk
@@ -8230,7 +8249,7 @@
   The module will be called ntfs.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-NTFS read-write support (EXPERIMENTAL)
+NTFS write support (DANGEROUS)
 CONFIG_NTFS_RW
   If you say Y here, you will (hopefully) be able to write to NTFS
   file systems as well as read from them. The read-write support
@@ -8265,7 +8284,7 @@
   tar" or preferably "info tar"). Note also that this option has
   nothing whatsoever to do with the option "System V IPC". Read about
   the System V filesystem in Documentation/filesystems/sysv-fs.txt.
-  Saying Y here will enlarge your kernel by about 34 KB.
+  Saying Y here will enlarge your kernel by about 27 kB.
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -8322,7 +8341,7 @@
   If you don't know whether you need it, then you don't need it:
   answer N.
 
-QNX filesystem support (EXPERIMENTAL)
+QNX filesystem support (read only) (EXPERIMENTAL)
 CONFIG_QNX4FS_FS  
   This is the filesystem used by the operating system QNX 4. Say Y if
   you intend to mount QNX hard disks or floppies. Unless you say Y to
@@ -8336,7 +8355,7 @@
 
   If unsure, say N.
 
-QNXFS read-write support (FOR TESTING ONLY)
+QNXFS write support (DANGEROUS)
 CONFIG_QNX4FS_RW
   Say Y if you want to test write support for QNX filesystems.
 
@@ -9289,7 +9308,7 @@
   and read Documentation/modules.txt. The module will be called esp.o.
   If unsure, say N.
 
-Multi-Tech multiport card support
+Multi-Tech multiport card support (EXPERIMENTAL)
 CONFIG_ISI
   This is a driver for the Multi-Tech cards which provide several
   serial ports. The driver is experimental and can currently only be
@@ -9459,9 +9478,9 @@
 
 PC110 digitizer pad support
 CONFIG_PC110_PAD
-  This drives the digitizer pad on the IBM PC110 palmtop (see
-  http://toy.cabi.net ). It can turn the digitizer pad into a PS/2
-  mouse emulation with tap gestures or into an absolute pad.
+  This drives the digitizer pad on the IBM PC110 palmtop. It can turn 
+  the digitizer pad into a PS/2 mouse emulation with tap gestures or
+  into an absolute pad.
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -10377,7 +10396,7 @@
   I'm told that even without a sound card, you can make your computer
   say more than an occasional beep, by programming the PC speaker.
   Kernel patches and supporting utilities to do that are in the pcsp
-  package, available at http://www.imladris.demon.co.uk/pcsp/ .
+  package, available at ftp://ftp.infradead.org/pub/pcsp/.
 
 OSS sound modules
 CONFIG_SOUND_OSS
@@ -10912,6 +10931,23 @@
   Say Y here to include support for the Rockwell WaveArtist sound
   system.  This driver is mainly for the NetWinder.
 
+VIA 82Cxxx Audio Codec
+CONFIG_SOUND_VIA82CXXX
+  Say Y here to include support for the audio codec found on
+  VIA 82Cxxx-based chips.  Typically these are built into a motherboard.
+  DO NOT select SoundBlaster or Adlib with this driver, unless you have
+  a SoundBlaster or Adlib card in addition to your VIA audio chip.
+
+NeoMagic 256AV/256ZX sound chipsets
+CONFIG_SOUND_NM256
+  Say M here to include audio support for the NeoMagic 256AV/256ZX
+  chipsets.  These are the audio chipsets found in the Sony Z505S/SX/DX,
+  some Sony F-series, and the Dell Latitude CPi and CPt laptops. It includes 
+  support for an AC97-compatible mixer and an apparently proprietary sound 
+  engine.
+
+  See Documentation/sound/NM256 for further information.
+
 Are you using a crosscompiler
 CONFIG_CROSSCOMPILE
   Say Y here if you are compiling the kernel on a different
@@ -11319,7 +11355,7 @@
   This is the driver for the Sun ESP SCSI host adapter. The ESP
   chipset is present in most SPARC-based computers.
 
-SPARC /dev/openprom compatibility driver
+SPARC /dev/openprom compatibility driver (EXPERIMENTAL)
 CONFIG_SUN_OPENPROMIO
   This driver provides user programs with an interface to the SPARC
   PROM device tree. The driver implements a SunOS-compatible
@@ -11417,7 +11453,7 @@
   If you anticipate running this kernel on a computer with a MC68060
   processor, say Y. Otherwise, say N.
 
-Math emulation support
+Math emulation support (EXPERIMENTAL)
 CONFIG_M68KFPU_EMU
   At some point in the future, this will cause floating-point math
   instructions to be emulated by the kernel on machines that lack a
@@ -11476,7 +11512,7 @@
   Note that even if you say N here, you can still use your expansion
   cards. If in doubt, say Y.
 
-Amiga 1200/600 PCMCIA support
+Amiga 1200/600 PCMCIA support (EXPERIMENTAL)
 CONFIG_AMIGA_PCMCIA
   Include support in the kernel for pcmcia on Amiga 1200 and Amiga
   600. If you intend to use pcmcia cards say Y; otherwise say N.
@@ -11608,7 +11644,7 @@
   1260 accelerator, and the optional SCSI module, say Y. Otherwise,
   say N.
 
-Blizzard PowerUP 603e+ SCSI support
+Blizzard PowerUP 603e+ SCSI support (EXPERIMENTAL)
 CONFIG_BLZ603EPLUS_SCSI
   If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+
   accelerator, say Y. Otherwise, say N.
@@ -11792,7 +11828,7 @@
   want). If you want to compile it as a module, say M here and read
   Documentation/modules.txt.
 
-Atari DSP56k Digital Signal Processor support
+Atari DSP56k Digital Signal Processor support (EXPERIMENTAL)
 CONFIG_ATARI_DSP56K
   If you want to be able to use the DSP56001 in Falcons, say Y. This
   driver is still experimental, and if you don't know what it is, or
@@ -12404,7 +12440,7 @@
   enabled. Say Y unless you experience problems that you suspect may
   be caused by this.
 
-Disable pgtable cache
+Disable pgtable cache (EXPERIMENTAL)
 CONFIG_NO_PGT_CACHE
   Normally the kernel maintains a `quicklist' of preallocated
   pagetable structures in order to increase performance. On machines
@@ -12427,7 +12463,7 @@
   time by entering them here. As a minimum, you should specify the
   memory size and the root device (e.g., mem=64M root=/dev/nfs)
 
-Hardware alignment trap
+Hardware alignment trap (EXPERIMENTAL)
 CONFIG_ALIGNMENT_TRAP
   ARM processors can not fetch/store information which is not
   naturally aligned on the bus, i.e., a 4 byte fetch must start at an
@@ -12533,7 +12569,7 @@
   If you say Y here, you also need to say Y or M to a compression
   protocol below.
 
-IrLAP Deflate Compression Protocol
+IrLAP Deflate Compression Protocol (EXPERIMENTAL)
 CONFIG_IRDA_DEFLATE
   Say Y here if you want to build support for the Deflate compression
   protocol. The deflate compression (GZIP) is exactly
@@ -12736,6 +12772,13 @@
   The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
   SCSI controller chip.  Almost everyone using one of these boards
   will want to say Y to this question.
+
+Simple 53c710 SCSI support (Compaq, NCR machines)
+CONFIG_SCSI_SIM710
+  This is a driver for the NCR53C710 chip commonly found in Compaq and
+  NCR machines.  If you are looking for 53C710 support for an Amiga or
+  some 680x0 based VME card then you probably want the other NCR53C710
+  driver.
 
 MVME16x Ethernet support
 CONFIG_MVME16x_NET
diff -u --recursive --new-file v2.3.23/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- v2.3.23/linux/Documentation/ioctl-number.txt	Mon Oct 11 15:38:14 1999
+++ linux/Documentation/ioctl-number.txt	Mon Oct 25 11:07:43 1999
@@ -1,5 +1,5 @@
 Ioctl Numbers
-10 October 1999
+19 October 1999
 Michael Elizabeth Chastain
 <mec@shout.net>
 
@@ -162,6 +162,8 @@
 					<mailto:buk@buks.ipn.de>
 0xA0	all	linux/sdp/sdp.h		Industrial Device Project
 					<mailto:kenji@bitgate.com>
+0xA2    00-0F   DVD decoder driver      in development:
+                                        <http://linuxtv.org/dvd/api/>
 0xA3	00-1F	Philips SAA7146 dirver	in development:
 					<mailto:Andreas.Beckmann@hamburg.sc.philips.com>
 0xA3	80-8F	Port ACL		in development:
@@ -173,3 +175,5 @@
 					<mailto:rusty@rustcorp.com.au>	
 0xB0	all	RATIO devices		in development:
 					<mailto:vgo@ratio.de>
+0xCB	00-1F	CBM serial IEC bus	in development:
+					<mailto:michael.klein@puffin.lb.shuttle.de>
diff -u --recursive --new-file v2.3.23/linux/Documentation/kbuild/config-language.txt linux/Documentation/kbuild/config-language.txt
--- v2.3.23/linux/Documentation/kbuild/config-language.txt	Sat Oct  9 11:47:49 1999
+++ linux/Documentation/kbuild/config-language.txt	Mon Oct 25 10:51:31 1999
@@ -1,5 +1,5 @@
 Config Language Specification
-28 September 1999
+18 October 1999
 Michael Elizabeth Chastain, <mailto:mec@shout.net>
 
 
@@ -568,15 +568,31 @@
 /expr/ may contain the following atoms and operators.  Note that, unlike
 shell, you must use double quotes around every atom.
 
-    "..."		a literal
-    "$..."		a variable
-
-    /atom/  = /atom/	true if atoms have identical value
-    /atom/ != /atom/	true if atoms have different value
+    /atom/:
+	"..."			a literal
+	"$..."			a variable
+
+    /expr/:
+	/atom/  = /atom/	true if atoms have identical value
+	/atom/ != /atom/	true if atoms have different value
+
+    /expr/:
+	/expr/ -o /expr/	true if either expression is true
+	/expr/ -a /expr/	true if both expressions are true
+	! /expr/		true if expression is not true
+
+Note that a naked /atom/ is not a valid /expr/.  If you try to use it
+as such:
+
+    # Do not do this.
+    if [ "$CONFIG_EXPERIMENTAL" ]; then
+	bool 'Bogus experimental feature' CONFIG_BOGUS
+    fi
 
-    /expr/ -o /expr/	true if either expression is true
-    /expr/ -a /expr/	true if both expressions are true
-    ! /expr/		true if expression is not true
+... then you will be surprised, because CONFIG_EXPERIMENTAL never has a
+value of the empty string!  It is always "y" or "n", and both of these
+are treated as true (non-empty) by the bash-based interpreters Configure
+and Menuconfig.
 
 Configure:  implemented
 Menuconfig: implemented
diff -u --recursive --new-file v2.3.23/linux/Documentation/sound/NM256 linux/Documentation/sound/NM256
--- v2.3.23/linux/Documentation/sound/NM256	Mon Oct  4 15:49:29 1999
+++ linux/Documentation/sound/NM256	Mon Oct 25 08:26:52 1999
@@ -2,10 +2,10 @@
 Documentation for the NeoMagic 256AV/256ZX sound driver
 =======================================================
 
-You're looking at version 1.0 of the driver.  (Woohoo!) It has been
+You're looking at version 1.1 of the driver.  (Woohoo!) It has been
 successfully tested against the following laptop models:
 
-	Sony Z505S/Z505SX/Z505DX
+	Sony Z505S/Z505SX/Z505DX/Z505RX
 	Sony F150, F160, F180, F250, F270, F280, PCG-F26
 	Dell Latitude CPi, CPt (various submodels)
 
@@ -16,9 +16,14 @@
 NeoMagic.  There is no warranty, expressed, implied, or otherwise.  It
 is free software in the public domain; feel free to use it, sell it,
 give it to your best friends, even claim that you wrote it (but why?!)
-but don't come whining to me, NeoMagic, Sony, Dell, or anyone else
+but don't go whining to me, NeoMagic, Sony, Dell, or anyone else
 when it blows up your computer.
 
+Version 1.1 contains a change to try and detect non-AC97 versions of
+the hardware, and not install itself appropriately.  It should also
+reinitialize the hardware on an APM resume event, assuming that APM
+was configured into your kernel.
+
 ============
 Installation
 ============
@@ -42,16 +47,19 @@
 another device (it normally shares IRQ 9 with the builtin eepro100
 ethernet on the Sony Z505 laptops). 
 
-It does not run the card in any sort of compatibility mode. Thus it
-almost certainly will not work on laptops that have the
-SB16-compatible codec/mixer; you will want to use the standard SB16
-OSS driver with these chipsets.  I cannot provide any assistance with
-machines using the SB-16 compatible version.
+It does not run the card in any sort of compatibility mode. It will
+not work on laptops that have the SB16-compatible, AD1848-compatible
+or CS4232-compatible codec/mixer; you will want to use the appropriate
+compatible OSS driver with these chipsets.  I cannot provide any
+assistance with machines using the SB16, AD1848 or CS4232 compatible
+versions.  (The driver now attempts to detect the mixer version, and
+will refuse to load if it believes the hardware is not not
+AC97-compatible.)
 
 The sound support is very basic, but it does include simultaneous
 playback and record capability.  The mixer support is also quite
 simple, although this is in keeping with the rather limited
-functionality of the chipset.  
+functionality of the chipset.
 
 There is no hardware synthesizer available, as the Losedows OPL-3 and
 MIDI support is done via hardware emulation.
@@ -63,8 +71,6 @@
 so of course the CD-ROM input doesn't work.  It does work on laptops
 with a builtin CD-ROM drive.
 
-Recording is mono 8-bit only.
-
 The mixer device does not appear to have any tone controls, at least
 on the Z505 series.  The mixer module checks for tone controls in the
 AC97 mixer, and will enable them if they are available.
@@ -93,10 +99,11 @@
     limitation.  It may be possible to support other speeds in the future.
 
   * There is no support for the telephone mixer/codec.  There is support
-    for a phonein/phoneout device if your mixer program supports it;
-    whether or not it does anything is anyone's guess.  (Reports on this
-    would be appreciated.)
-  
+    for a phonein/phoneout device in the mixer driver;  whether or not 
+    it does anything is anyone's guess.  (Reports on this would be
+    appreciated.  You'll have to figure out how to get the phone to
+    go off-hook before it'll work, tho.)
+
   * This driver was not written with any cooperation or support from
     NeoMagic.  If you have any questions about this, see their website
     for their official stance on supporting open source drivers.
@@ -118,8 +125,8 @@
 
   * Sometimes the NM256 driver has to guess at where the buffer 
     should be placed, especially if the module is loaded after the
-    X server is started.  It's usually correct, but it will fail on
-    the Sony F250.
+    X server is started.  It's usually correct, but it will consistently
+    fail on the Sony F250.
 
   * Virtual screens greater than 1024x768x16 under XFree86 are
     problematic on laptops with only 2.5MB of screen RAM. This
@@ -139,10 +146,16 @@
 On the F250, it is possible to force the driver to load properly even
 after the XFree86 server is started by doing:
 
-	insmod nm256.o buffertop=0x25a800
+	insmod nm256 buffertop=0x25a800
 
 This forces the audio buffers to the correct offset in screen RAM.
 
+One user has reported a similar problem on the Sony F270, although
+others apparently aren't seeing any problems.  His suggested command
+is
+
+	insmod nm256 buffertop=0x272800
+
 =================
 Official WWW site
 =================
@@ -154,6 +167,17 @@
 You should always be able to get the latest version of the driver there,
 and the driver will be supported for the foreseeable future.
 
+==============
+Z505RX and IDE
+==============
+
+There appears to be a problem with the IDE chipset on the Z505RX; one
+of the symptoms is that sound playback periodically hangs (when the
+disk is accessed).  The user reporting the problem also reported that
+enabling all of the IDE chipset workarounds in the kernel solved the
+problem, tho obviously only one of them should be needed--if someone
+can give me more details I would appreciate it.
+
 ==============================
 Z505S/Z505SX on-board Ethernet
 ==============================
@@ -176,11 +200,30 @@
 ==================================
 
 There is also a known problem with the Sony Z505S and Z505SX hanging
-if a PCMCIA card is inserted while the ethernet driver is loaded.
-This is caused by tons of spurious IRQ 9s, probably generated from the
-PCMCIA or ACPI bridges.  There is currently no fix for the problem,
-and the only known workaround is to disable the ethernet interface
-before inserting or removing a PCMCIA card.
+if a PCMCIA card is inserted while the ethernet driver is loaded, or
+in some cases if the laptop is suspended.  This is caused by tons of
+spurious IRQ 9s, probably generated from the PCMCIA or ACPI bridges.
+
+There is currently no fix for the problem that works in every case.
+The only known workarounds are to disable the ethernet interface
+before inserting or removing a PCMCIA card, or with some cards
+disabling the PCMCIA card before ejecting it will also help the
+problem with the laptop hanging when the card is ejected.
+
+One user has reported that setting the tcic's cs_irq to some value
+other than 9 (like 11) fixed the problem.  This doesn't work on my
+Z505S, however--changing the value causes the cardmgr to stop seeing
+card insertions and removals, cards don't seem to work correctly, and
+I still get hangs if a card is inserted when the kernel is booted.
+
+Using the latest ethernet driver and pcmcia package allows me to
+insert an Adaptec 1480A SlimScsi card without the laptop hanging,
+although I still have to shut down the card before ejecting or
+powering down the laptop.  However, similar experiments with a DE-660
+ethernet card still result in hangs when the card is inserted.  I am
+beginning to think that the interrupts are CardBus-related, since the
+Adaptec card is a CardBus card, and the DE-660 is not; however, I
+don't have any other CardBus cards to test with.
 
 ======
 Thanks
@@ -208,6 +251,11 @@
 	Jeff Garzik, for various helpful suggestions on the AC97
 	interface
 
+	"Mr. Bumpy" for feedback on the Z505RX
+
+	Bill Nottingham, for generous assistance in getting the mixer ID
+	code working
+
 =================
 Previous versions
 =================
@@ -227,3 +275,6 @@
 
 Version 0.75 renamed all the functions and files with slightly more
 generic names.
+
+Note that previous versions of this document claimed that recording was
+8-bit only; it actually has been working for 16-bits all along.
diff -u --recursive --new-file v2.3.23/linux/Documentation/video4linux/bttv/CARDS linux/Documentation/video4linux/bttv/CARDS
--- v2.3.23/linux/Documentation/video4linux/bttv/CARDS	Fri Oct 15 15:25:13 1999
+++ linux/Documentation/video4linux/bttv/CARDS	Mon Oct 25 08:26:52 1999
@@ -106,7 +106,7 @@
 Image World ConferenceTV
 ------------------------
 Doesn't work:
-	- autodetect. Use card=3D20
+	- autodetect. Use card=21
 	- sound mute. Use the line-in volume of your soundcard
 	- radio tuner.  Since the card doesn't have an antenna, it is quite
           understandable ;)  However, you can hear some stations if you
diff -u --recursive --new-file v2.3.23/linux/Documentation/vm/locking linux/Documentation/vm/locking
--- v2.3.23/linux/Documentation/vm/locking	Fri Oct 22 13:21:43 1999
+++ linux/Documentation/vm/locking	Mon Oct 25 11:14:33 1999
@@ -14,13 +14,12 @@
 The vma list of the victim mm is also scanned by the stealer, 
 and the vmlist_lock is used to preserve list sanity against the
 process adding/deleting to the list. This also gurantees existance
-of the vma. Vma existance gurantee while invoking the driver
-swapout() method in try_to_swap_out() also relies on the fact
-that do_munmap() temporarily gets lock_kernel before decimating
-the vma, thus the swapout() method must snapshot all the vma 
-fields it needs before going to sleep (which will release the
-lock_kernel held by the page stealer). Currently, filemap_swapout
-is the only method that depends on this shaky interlocking.
+of the vma. Vma existance is not guranteed once try_to_swap_out() 
+drops the vmlist lock. To gurantee the existance of the underlying 
+file structure, a get_file is done before the swapout() method is 
+invoked. The page passed into swapout() is guaranteed not to be reused
+for a different purpose because the page reference count due to being
+present in the user's pte is not released till after swapout() returns.
 
 Any code that modifies the vmlist, or the vm_start/vm_end/
 vm_flags:VM_LOCKED/vm_next of any vma *in the list* must prevent 
diff -u --recursive --new-file v2.3.23/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.23/linux/MAINTAINERS	Fri Oct 22 13:21:43 1999
+++ linux/MAINTAINERS	Mon Oct 25 10:26:38 1999
@@ -93,6 +93,13 @@
 L:	linux-net@vger.rutgers.edu
 S:	Maintained
 
+ACPI
+P:	Andrew Henroid
+M:	andy_henroid@yahoo.com
+L:	acpi@phobos.fs.tum.de
+W:	http://phobos.fs.tum.de/acpi/index.html
+S:	Maintained
+
 AD1816 SOUND DRIVER
 P:	Thorsten Knabe
 M:	Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
diff -u --recursive --new-file v2.3.23/linux/Makefile linux/Makefile
--- v2.3.23/linux/Makefile	Fri Oct 22 13:21:43 1999
+++ linux/Makefile	Wed Oct 27 14:21:52 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 23
+SUBLEVEL = 24
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -331,7 +331,7 @@
 
 modules: $(patsubst %, _mod_%, $(SUBDIRS))
 
-$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h
+$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER
 	$(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules
 
 modules_install:
diff -u --recursive --new-file v2.3.23/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.3.23/linux/arch/arm/config.in	Fri Oct 22 13:21:43 1999
+++ linux/arch/arm/config.in	Mon Oct 25 10:51:31 1999
@@ -123,7 +123,7 @@
 
 endmenu
 
-if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_EXPERIMENTAL" ]; then
+if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP
 fi
 #bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS
diff -u --recursive --new-file v2.3.23/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.23/linux/arch/i386/config.in	Fri Oct 22 13:21:45 1999
+++ linux/arch/i386/config.in	Mon Oct 25 08:26:52 1999
@@ -125,7 +125,6 @@
 
 endmenu
 
-source drivers/i2o/Config.in
 
 source drivers/pnp/Config.in
 
@@ -144,6 +143,8 @@
    source drivers/scsi/Config.in
 fi
 endmenu
+
+source drivers/i2o/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
    mainmenu_option next_comment
diff -u --recursive --new-file v2.3.23/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.23/linux/arch/i386/defconfig	Fri Oct 22 13:21:45 1999
+++ linux/arch/i386/defconfig	Wed Oct 27 16:16:32 1999
@@ -70,16 +70,6 @@
 # CONFIG_APM is not set
 
 #
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
 # Plug and Play configuration
 #
 CONFIG_PNP=y
@@ -125,6 +115,7 @@
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # 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
@@ -228,6 +219,16 @@
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
 
 #
 # Network device support
diff -u --recursive --new-file v2.3.23/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.3.23/linux/arch/i386/kernel/i386_ksyms.c	Mon Oct 11 15:38:14 1999
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Oct 25 10:26:38 1999
@@ -37,6 +37,7 @@
 EXPORT_SYMBOL(dump_fpu);
 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);
diff -u --recursive --new-file v2.3.23/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.3.23/linux/arch/i386/kernel/process.c	Wed Aug 18 11:11:15 1999
+++ linux/arch/i386/kernel/process.c	Wed Oct 27 15:12:38 1999
@@ -47,8 +47,6 @@
 
 #include <linux/irq.h>
 
-spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
-
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int hlt_counter=0;
@@ -341,70 +339,6 @@
 }
 
 /*
- * Allocation and freeing of basic task resources.
- *
- * NOTE! The task struct and the stack go together
- *
- * The task structure is a two-page thing, and as such
- * not reliable to allocate using the basic page alloc
- * functions. We have a small cache of structures for
- * when the allocations fail..
- *
- * This extra buffer essentially acts to make for less
- * "jitter" in the allocations..
- *
- * On SMP we don't do this right now because:
- *  - we aren't holding any locks when called, and we might
- *    as well just depend on the generic memory management
- *    to do proper locking for us instead of complicating it
- *    here.
- *  - if you use SMP you have a beefy enough machine that
- *    this shouldn't matter..
- */
-#ifndef __SMP__
-#define EXTRA_TASK_STRUCT	16
-static struct task_struct * task_struct_stack[EXTRA_TASK_STRUCT];
-static int task_struct_stack_ptr = -1;
-#endif
-
-struct task_struct * alloc_task_struct(void)
-{
-#ifndef EXTRA_TASK_STRUCT
-	return (struct task_struct *) __get_free_pages(GFP_KERNEL,1);
-#else
-	int index;
-	struct task_struct *ret;
-
-	index = task_struct_stack_ptr;
-	if (index >= EXTRA_TASK_STRUCT/2)
-		goto use_cache;
-	ret = (struct task_struct *) __get_free_pages(GFP_KERNEL,1);
-	if (!ret) {
-		index = task_struct_stack_ptr;
-		if (index >= 0) {
-use_cache:
-			ret = task_struct_stack[index];
-			task_struct_stack_ptr = index-1;
-		}
-	}
-	return ret;
-#endif
-}
-
-void free_task_struct(struct task_struct *p)
-{
-#ifdef EXTRA_TASK_STRUCT
-	int index = task_struct_stack_ptr+1;
-
-	if (index < EXTRA_TASK_STRUCT) {
-		task_struct_stack[index] = p;
-		task_struct_stack_ptr = index;
-	} else
-#endif
-		free_pages((unsigned long) p, 1);
-}
-
-/*
  * No need to lock the MM as we are the last user
  */
 void release_segments(struct mm_struct *mm)
@@ -419,19 +353,6 @@
 		clear_LDT();
 		vfree(ldt);
 	}
-}
-
-void forget_segments(void)
-{
-	/* forget local segments */
-	__asm__ __volatile__("movl %w0,%%fs ; movl %w0,%%gs"
-		: /* no outputs */
-		: "r" (0));
-
-	/*
-	 * Load the LDT entry of init_task.
-	 */
-	load_LDT(&init_mm);
 }
 
 /*
diff -u --recursive --new-file v2.3.23/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.23/linux/arch/i386/kernel/setup.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/i386/kernel/setup.c	Mon Oct 25 20:51:13 1999
@@ -29,6 +29,8 @@
  *  Cleaned up cache-detection code
  *	Dave Jones <dave@powertweak.com>, October 1999
  *
+ *	Added proper L2 cache detection for Coppermine
+ *	Dragan Stancevic <visitor@valinux.com>, October 1999
  */
 
 /*
@@ -695,14 +697,18 @@
 #endif
 
 #ifdef CONFIG_BLK_DEV_INITRD
-// FIXME needs to do the new bootmem alloc stuff
 	if (LOADER_TYPE) {
-		initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
-		initrd_end = initrd_start+INITRD_SIZE;
-		if (initrd_end > (max_low_pfn << PAGE_SHIFT)) {
+		if (INITRD_START + INITRD_SIZE < (max_low_pfn << PAGE_SHIFT)) {
+			reserve_bootmem(INITRD_START, INITRD_SIZE);
+			initrd_start =
+				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+			initrd_end = initrd_start+INITRD_SIZE;
+		}
+		else {
 			printk("initrd extends beyond end of memory "
 			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-			    initrd_end,memory_end);
+			    INITRD_START + INITRD_SIZE,
+			    max_low_pfn << PAGE_SHIFT);
 			initrd_start = 0;
 		}
 	}
@@ -1233,6 +1239,7 @@
 				break;
 
 			case 0x42:
+			case 0x82: /*Detect 256-Kbyte cache on Coppermine*/
 				c->x86_cache_size = 256;
 				break;
 
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.3.23/linux/arch/ppc/boot/misc.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/ppc/boot/misc.c	Mon Oct 25 10:53:37 1999
@@ -1,7 +1,7 @@
 /*
  * misc.c
  *
- * $Id: misc.c,v 1.67 1999/08/10 22:53:57 cort Exp $
+ * $Id: misc.c,v 1.68 1999/10/20 22:08:08 cort Exp $
  * 
  * Adapted for PowerPC by Gary Thomas
  *
@@ -462,6 +462,7 @@
 		puts(" ");
 		puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
 		puts("\n");
+		avail_ram += zimage_size;
 	}
 
 	/* relocate initrd */
@@ -469,15 +470,19 @@
 	{
 		puts("initrd at:     "); puthex(initrd_start);
 		puts(" "); puthex(initrd_end); puts("\n");
-#ifdef OMIT
-		avail_ram = (char *)PAGE_ALIGN(
-			(unsigned long)zimage_size+(unsigned long)zimage_start);
-		memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE );
-		initrd_start = (unsigned long)avail_ram;
-		initrd_end = initrd_start + INITRD_SIZE;
-		puts("relocated to:  "); puthex(initrd_start);
-		puts(" "); puthex(initrd_end); puts("\n");
-#endif
+		if ( (unsigned long)initrd_start <= 0x00800000 )
+		{
+			memcpy( (void *)avail_ram,
+				(void *)initrd_start, initrd_end-initrd_start );
+			puts("relocated to:  ");
+			initrd_end = (unsigned long) avail_ram + (initrd_end-initrd_start);
+			initrd_start = (unsigned long)avail_ram;
+			puthex((unsigned long)initrd_start);
+			puts(" ");
+			puthex((unsigned long)initrd_end);
+			puts("\n");
+		}
+		avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end);
 	}
 
 	avail_ram = (char *)0x00400000;
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.23/linux/arch/ppc/defconfig	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/defconfig	Mon Oct 25 10:53:37 1999
@@ -1,5 +1,5 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 
 #
@@ -8,15 +8,27 @@
 CONFIG_PPC=y
 CONFIG_6xx=y
 # CONFIG_PPC64 is not set
+# CONFIG_82xx is not set
 # CONFIG_8xx is not set
+# CONFIG_MPC821 is not set
+# CONFIG_MPC823 is not set
+# CONFIG_MPC850 is not set
+# CONFIG_MPC855 is not set
+# CONFIG_MPC860 is not set
+# CONFIG_MPC860T is not set
+# CONFIG_RPXLITE is not set
+# CONFIG_RPXCLASSIC is not set
+# CONFIG_BSEIP is not set
+# CONFIG_MBX is not set
+# CONFIG_WINCEPT is not set
 # CONFIG_PMAC is not set
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
-CONFIG_ALL_PPC=y
-# CONFIG_GEMINI is not set
+# CONFIG_ALL_PPC is not set
+CONFIG_GEMINI=y
 # CONFIG_APUS is not set
-# CONFIG_MBX is not set
 # CONFIG_SMP is not set
+CONFIG_MACH_SPECIFIC=y
 CONFIG_6xx=y
 
 #
@@ -35,63 +47,45 @@
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_PARPORT is not set
-CONFIG_VGA_CONSOLE=y
-CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
-CONFIG_PMAC_PBOOK=y
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_MACIO=y
-CONFIG_ADB_PMU=y
-CONFIG_ADB_KEYBOARD=y
-CONFIG_PROC_DEVICETREE=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB is not set
+# CONFIG_PMAC_PBOOK is not set
+# CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
+# CONFIG_ADB is not set
+# CONFIG_PROC_DEVICETREE is not set
 # CONFIG_TOTALMP is not set
-CONFIG_BOOTX_TEXT=y
+# CONFIG_BOOTX_TEXT is not set
 # CONFIG_MOTOROLA_HOTSWAP is not set
-# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Plug and Play configuration
 #
 # CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
 
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_IDECD_SLOTS is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_IDEPCI is not set
-CONFIG_BLK_DEV_SL82C105=y
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_IDEDMA_PMAC_AUTO=y
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDE_CHIPSETS is not set
+# 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
 # CONFIG_BLK_CPQ_DA is not set
-CONFIG_BLK_DEV_LOOP=y
+
+#
+# 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=y
-CONFIG_BLK_DEV_INITRD=y
+# 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_IDE_MODES=y
+# CONFIG_BLK_DEV_IDE_MODES is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -115,12 +109,20 @@
 # CONFIG_IP_MROUTE is not set
 CONFIG_IP_ALIAS=y
 CONFIG_SYN_COOKIES=y
+
+#
+# (it is safe to leave these untouched)
+#
 CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
-CONFIG_ATALK=m
+# CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
@@ -140,11 +142,19 @@
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_ST is not set
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 # CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -157,11 +167,7 @@
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-CONFIG_AIC7XXX_PROC_STATS=y
-CONFIG_AIC7XXX_RESET_DELAY=15
+# CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
@@ -175,6 +181,8 @@
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
@@ -202,9 +210,8 @@
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
 # CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MAC53C94=y
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
 
 #
 # Network device support
@@ -224,8 +231,9 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-CONFIG_MACE=y
-CONFIG_BMAC=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+CONFIG_NCR885E=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -235,38 +243,11 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
 # CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
-CONFIG_PCNET32=y
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_DE4X5=y
-# CONFIG_DEC_ELCP is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_ZNET is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_LTPC is not set
-# CONFIG_COPS is not set
-# CONFIG_IPDDP is not set
-CONFIG_PPP=y
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
 
@@ -287,13 +268,6 @@
 # CONFIG_DLCI is not set
 
 #
-# PCMCIA network devices
-#
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_3C589 is not set
-# CONFIG_PCMCIA_RAYCS is not set
-
-#
 # Amateur Radio support
 #
 # CONFIG_HAMRADIO is not set
@@ -311,45 +285,14 @@
 #
 # Console drivers
 #
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_OF=y
-CONFIG_FB_CONTROL=y
-CONFIG_FB_PLATINUM=y
-CONFIG_FB_VALKYRIE=y
-CONFIG_FB_IMSTT=y
-CONFIG_FB_CT65550=y
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-CONFIG_FB_MATROX=y
-# CONFIG_FB_MATROX_MILLENIUM is not set
-CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G100=y
-# CONFIG_FB_MATROX_MULTIHEAD is not set
-CONFIG_FB_ATY=y
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-CONFIG_FONT_SUN8x16=y
-CONFIG_FONT_SUN12x22=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
 
 #
 # Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
@@ -362,14 +305,13 @@
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
-# CONFIG_ADB_MOUSE is not set
 CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
+# CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 
 #
@@ -389,6 +331,14 @@
 # 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
 # CONFIG_DRM is not set
 
 #
@@ -400,14 +350,11 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -427,11 +374,10 @@
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_SUN is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 
@@ -451,49 +397,11 @@
 #
 # Sound
 #
-CONFIG_SOUND=y
-CONFIG_DMASOUND=y
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_OSS=y
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-CONFIG_SOUND_CS4232=m
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_SOFTOSS is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_UART6850 is not set
-
-#
-# Additional low level sound drivers
-#
-# CONFIG_LOWLEVEL_SOUND is not set
+# CONFIG_SOUND is not set
 
 #
 # Kernel hacking
 #
-CONFIG_MAGIC_SYSRQ=y
+# 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.23/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.3.23/linux/arch/ppc/kernel/chrp_pci.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/chrp_pci.c	Tue Oct 26 15:02:14 1999
@@ -286,9 +286,6 @@
 	{
 		if ( dev->irq )
 			dev->irq = openpic_to_irq( dev->irq );
-		/* adjust the io_port for the NCR cards for busses other than 0 -- Cort */
-		if ( (dev->bus->number > 0) && (dev->vendor == PCI_VENDOR_ID_NCR) )
-			dev->resource[0].start += (dev->bus->number*0x08000000);
 		/* these need to be absolute addrs for OF and Matrox FB -- Cort */
 		if ( dev->vendor == PCI_VENDOR_ID_MATROX )
 		{
@@ -305,6 +302,10 @@
 			pcibios_write_config_word(dev->bus->number,
 			  dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
 		}
+		if ( (dev->bus->number > 0) &&
+		     ((dev->vendor == PCI_VENDOR_ID_NCR) ||
+		      (dev->vendor == PCI_VENDOR_ID_AMD)))
+			dev->resource[0].start += (dev->bus->number*0x08000000);
 	}
 }
 
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.23/linux/arch/ppc/kernel/chrp_setup.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Tue Oct 26 15:02:14 1999
@@ -28,7 +28,6 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/blk.h>
-#include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/console.h>
 #include <linux/pci.h>
@@ -37,6 +36,7 @@
 #include <linux/adb.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -127,7 +127,7 @@
 	len = sprintf(buffer,"machine\t\t: CHRP %s\n", model);
 
 	/* longtrail (goldengate) stuff */
-	if ( !strncmp( model, "IBM,LongTrail", 9 ) )
+	if ( !strncmp( model, "IBM,LongTrail", 13 ) )
 	{
 		/* VLSI VAS96011/12 `Golden Gate 2' */
 		/* Memory banks */
@@ -198,21 +198,27 @@
 				     u8 type)
 {
 	u8 level0, type0, active;
-
-	/* select logical device */
-	sio_write(device, 0x07);
-	active = sio_read(0x30);
-	level0 = sio_read(0x70);
-	type0 = sio_read(0x71);
-	printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
-	       !active ? "in" : "");
-	if (level0 == level && type0 == type && active)
-		printk("OK\n");
-	else {
-		printk("remapping to level %d, type %d, active\n", level, type);
-		sio_write(0x01, 0x30);
-		sio_write(level, 0x70);
-		sio_write(type, 0x71);
+	struct device_node *root;
+	
+	root = find_path_device("/");
+	if (root &&
+	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13 ) )
+	{
+		/* select logical device */
+		sio_write(device, 0x07);
+		active = sio_read(0x30);
+		level0 = sio_read(0x70);
+		type0 = sio_read(0x71);
+		printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
+		       !active ? "in" : "");
+		if (level0 == level && type0 == type && active)
+			printk("OK\n");
+		else {
+			printk("remapping to level %d, type %d, active\n", level, type);
+			sio_write(0x01, 0x30);
+			sio_write(level, 0x70);
+			sio_write(type, 0x71);
+		}
 	}
 
 }
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- v2.3.23/linux/arch/ppc/kernel/gemini_setup.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/gemini_setup.c	Tue Oct 26 15:02:14 1999
@@ -332,9 +332,12 @@
 
 	/* gemini has no 8259 */
 	open_pic.irq_offset = 0;
-	for( i=0; i < 16; i++ ) 
+	for( i=0; i < OPENPIC_VEC_SPURIOUS; i++ ) 
 		irq_desc[i].ctl = &open_pic;
 	openpic_init(1);
+#ifdef __SMP__
+	request_irq(OPENPIC_VEC_IPI, openpic_ipi_action, 0, "IPI0", 0);
+#endif	/* __SMP__ */
 }
 
 #define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.3.23/linux/arch/ppc/kernel/idle.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/idle.c	Tue Oct 26 15:02:14 1999
@@ -40,10 +40,10 @@
 unsigned long powersave_nap = 0;
 
 unsigned long *zero_cache;    /* head linked list of pre-zero'd pages */
-unsigned long zero_sz;	      /* # currently pre-zero'd pages */
-unsigned long zeropage_hits;  /* # zero'd pages request that we've done */
-unsigned long zeropage_calls; /* # zero'd pages request that've been made */
-unsigned long zerototal;      /* # pages zero'd over time */
+atomic_t zerototal;      /* # pages zero'd over time */
+atomic_t zeropage_hits;  /* # zero'd pages request that we've done */
+atomic_t zero_sz;	      /* # currently pre-zero'd pages */
+atomic_t zeropage_calls; /* # zero'd pages request that've been made */
 
 int idled(void)
 {
@@ -57,7 +57,7 @@
 		
 		check_pgt_cache();
 
-		if ( !current->need_resched && zero_paged_on ) zero_paged();
+		/*if ( !current->need_resched && zero_paged_on ) zero_paged();*/
 		if ( !current->need_resched && htab_reclaim_on ) htab_reclaim();
 		if ( !current->need_resched ) power_save();
 
@@ -141,6 +141,7 @@
 #endif /* CONFIG_8xx */
 }
 
+#if 0
 /*
  * Returns a pre-zero'd page from the list otherwise returns
  * NULL.
@@ -149,7 +150,7 @@
 {
 	unsigned long page = 0;
 
-	atomic_inc((atomic_t *)&zero_cache_calls);
+	atomic_inc(&zero_cache_calls);
 	if ( zero_quicklist )
 	{
 		/* atomically remove this page from the list */
@@ -194,9 +195,9 @@
 	unsigned long bytecount = 0;  
 	pte_t *pte;
 
-	if ( zero_cache_sz >= zero_cache_water[0] )
+	if ( atomic_read(&zero_cache_sz) >= zero_cache_water[0] )
 		return;
-	while ( (zero_cache_sz < zero_cache_water[1]) && (!current->need_resched) )
+	while ( (atomic_read(&zero_cache_sz) < zero_cache_water[1]) && (!current->need_resched) )
 	{
 		/*
 		 * Mark a page as reserved so we can mess with it
@@ -272,6 +273,7 @@
 		atomic_inc((atomic_t *)&zero_cache_total);
 	}
 }
+#endif
 
 void power_save(void)
 {
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.3.23/linux/arch/ppc/kernel/irq.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/irq.c	Mon Oct 25 10:53:37 1999
@@ -241,6 +241,8 @@
 #endif /* __SMP__ */
 		if ( irq_desc[i].ctl )		
 			len += sprintf(buf+len, " %s ", irq_desc[i].ctl->typename );
+		else
+			len += sprintf(buf+len, "  None      ");
 		len += sprintf(buf+len, "    %s",action->name);
 		for (action=action->next; action; action = action->next) {
 			len += sprintf(buf+len, ", %s", action->name);
@@ -297,7 +299,8 @@
 	if ( irq < 0 )
 	{
 		/* -2 means ignore, already handled */
-		if (irq != -2) {
+		if (irq != -2)
+		{
 			printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
 			       irq, regs->nip);
 			ppc_spurious_interrupts++;
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.3.23/linux/arch/ppc/kernel/open_pic.c	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/kernel/open_pic.c	Tue Oct 26 15:02:14 1999
@@ -85,6 +85,7 @@
 #ifdef __SMP__
 void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
 {
+printk("openpic_ipi_action\n");	
 	smp_message_recv();
 }
 #endif /* __SMP__ */
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.23/linux/arch/ppc/kernel/setup.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/setup.c	Tue Oct 26 15:02:14 1999
@@ -311,18 +311,16 @@
 	/*
 	 * Ooh's and aah's info about zero'd pages in idle task
 	 */ 
-	{
-		len += sprintf(buffer+len,"zero pages\t: total %lu (%luKb) "
-			       "current: %lu (%luKb) hits: %lu/%lu (%lu%%)\n",
-			       zero_cache_total,
-			       (zero_cache_total*PAGE_SIZE)>>10,
-			       zero_cache_sz,
-			       (zero_cache_sz*PAGE_SIZE)>>10,
-			       zero_cache_hits,zero_cache_calls,
-			       /* : 1 below is so we don't div by zero */
-			       (zero_cache_hits*100) /
-			       ((zero_cache_calls)?zero_cache_calls:1));
-	}
+	len += sprintf(buffer+len,"zero pages\t: total: %u (%luKb) "
+		       "current: %u (%luKb) hits: %u/%u (%u%%)\n",
+		       atomic_read(&zero_cache_total),
+		       (atomic_read(&zero_cache_total)*PAGE_SIZE)>>10,
+		       atomic_read(&zero_cache_sz),
+		       (atomic_read(&zero_cache_sz)*PAGE_SIZE)>>10,
+		       atomic_read(&zero_cache_hits),atomic_read(&zero_cache_calls),
+		       /* : 1 below is so we don't div by zero */
+		       (atomic_read(&zero_cache_hits)*100) /
+		       ((atomic_read(&zero_cache_calls))?atomic_read(&zero_cache_calls):1));
 
 	if (ppc_md.get_cpuinfo != NULL)
 	{
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.3.23/linux/arch/ppc/kernel/smp.c	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/kernel/smp.c	Tue Oct 26 15:02:14 1999
@@ -159,6 +159,12 @@
 
 void smp_send_reschedule(int cpu)
 {
+	/*
+	 * This isn't the case anymore since the other CPU could be
+	 * sleeping and won't reschedule until the next interrupt (such
+	 * as the timer).
+	 *  -- Cort
+	 */
 	/* This is only used if `cpu' is running an idle task,
 	   so it will reschedule itself anyway... */
 	/*smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);*/
@@ -173,7 +179,7 @@
 void smp_message_pass(int target, int msg, unsigned long data, int wait)
 {
 	int i;
-	if ( !(_machine & (_MACH_Pmac|_MACH_chrp)) )
+	if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_gemini)) )
 		return;
 
 	spin_lock(&mesg_pass_lock);
@@ -216,24 +222,29 @@
 	{
 		/*
 		 * There has to be some way of doing this better -
-		 * perhaps a sent-to-all or send-to-all-but-self
+		 * perhaps a send-to-all or send-to-all-but-self
 		 * in the openpic.  This gets us going for now, though.
 		 * -- Cort
 		 */
 		switch ( target )
 		{
 		case MSG_ALL:
-			for ( i = 0 ; i < smp_num_cpus ; i++ )
-				openpic_cause_IPI(i, 0, 0xffffffff );
+			openpic_cause_IPI(smp_processor_id(), 0, 0x0 );
+			openpic_cause_IPI(smp_processor_id(), 0, 0xffffffff );
 			break;
 		case MSG_ALL_BUT_SELF:
 			for ( i = 0 ; i < smp_num_cpus ; i++ )
 				if ( i != smp_processor_id () )
-					openpic_cause_IPI(i, 0,
-			  0xffffffff & ~(1 << smp_processor_id()));
+				{
+					openpic_cause_IPI(smp_processor_id(), 0,
+							  0x0 );
+					openpic_cause_IPI(smp_processor_id(), 0,
+					  0xffffffff & ~(1 << smp_processor_id()));
+				}
 			break;
 		default:
-			openpic_cause_IPI(target, 0, 1U << target);
+			openpic_cause_IPI(smp_processor_id(), 0, 0x0 );
+			openpic_cause_IPI(target, 0, 1U << target );
 			break;
 		}
 	}
@@ -251,8 +262,7 @@
 	struct task_struct *p;
 	unsigned long a;
 
-        printk("Entering SMP Mode...\n");
-	/* let other processors know to not do certain initialization */
+	printk("Entering SMP Mode...\n");
 	smp_num_cpus = 1;
         smp_store_cpu_info(0);
 
@@ -290,15 +300,13 @@
 		cpu_nr = 2; 
 		break;
 	case _MACH_chrp:
-		/* openpic doesn't report # of cpus, just # possible -- Cort */
-#if 0		
-		cpu_nr = ((openpic_read(&OpenPIC->Global.Feature_Reporting0)
-				 & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
-				OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT)+1;
-#endif
+		for ( i = 0; i < 4 ; i++ )
+			openpic_enable_IPI(i);
 		cpu_nr = smp_chrp_cpu_nr;
 		break;
 	case _MACH_gemini:
+		for ( i = 0; i < 4 ; i++ )
+			openpic_enable_IPI(i);
                 cpu_nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK)>>2;
                 cpu_nr = (cpu_nr == 0) ? 4 : cpu_nr;
 		break;
@@ -350,19 +358,6 @@
 		case _MACH_chrp:
 			*(unsigned long *)KERNELBASE = i;
 			asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-#if 0
-			device = find_type_devices("cpu");
-			/* assume cpu device list is in order, find the ith cpu */
-			for ( a = i; device && a; device = device->next, a-- )
-				;
-			if ( !device )
-				break;
-			printk( "Starting %s (%lu): ", device->full_name,
-				*(ulong *)get_property(device, "reg", NULL) );
-			call_rtas( "start-cpu", 3, 1, NULL,
-				   *(ulong *)get_property(device, "reg", NULL),
-				   __pa(__secondary_start_chrp), i);
-#endif			
 			break;
 		case _MACH_gemini:
 			openpic_init_processor( 1<<i );
@@ -428,6 +423,7 @@
         smp_store_cpu_info(current->processor);
 	set_dec(decrementer_count);
 	
+	init_idle();
 #if 0
 	current->mm->mmap->vm_page_prot = PAGE_SHARED;
 	current->mm->mmap->vm_start = PAGE_OFFSET;
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.3.23/linux/arch/ppc/kernel/time.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/ppc/kernel/time.c	Mon Oct 25 10:53:37 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: time.c,v 1.55 1999/08/31 06:54:09 davem Exp $
+ * $Id: time.c,v 1.57 1999/10/21 03:08:16 cort Exp $
  * Common time routines among all ppc machines.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -95,37 +95,48 @@
 	}
 #endif /* __SMP__ */			
 	
-	while ((dval = get_dec()) < 0) {
+	dval = get_dec();
+	/*
+	 * Wait for the decrementer to change, then jump
+	 * in and add decrementer_count to its value
+	 * (quickly, before it changes again!)
+	 */
+	while ((d = get_dec()) == dval)
+		;
+	/*
+	 * Don't play catchup between the call to time_init()
+	 * and sti() in init/main.c.
+	 *
+	 * This also means if we're delayed for > HZ
+	 * we lose those ticks.  If we're delayed for > HZ
+	 * then we have something wrong anyway, though.
+	 *
+	 * -- Cort
+	 */
+	if ( d < (-1*decrementer_count) )
+		d = 0;
+	set_dec(d + decrementer_count);
+	if ( !smp_processor_id() )
+	{
+		do_timer(regs);
 		/*
-		 * Wait for the decrementer to change, then jump
-		 * in and add decrementer_count to its value
-		 * (quickly, before it changes again!)
+		 * update the rtc when needed
 		 */
-		while ((d = get_dec()) == dval)
-			;
-		set_dec(d + decrementer_count);
-		if ( !smp_processor_id() )
+		if ( (time_status & STA_UNSYNC) &&
+		     ((xtime.tv_sec > last_rtc_update + 60) ||
+		      (xtime.tv_sec < last_rtc_update)) )
 		{
-			do_timer(regs);
-			/*
-			 * update the rtc when needed
-			 */
-			if ( (time_status & STA_UNSYNC) &&
-			     ((xtime.tv_sec > last_rtc_update + 60) ||
-			      (xtime.tv_sec < last_rtc_update)) )
-			{
-				if (ppc_md.set_rtc_time(xtime.tv_sec) == 0)
-					last_rtc_update = xtime.tv_sec;
-				else
-					/* do it again in 60 s */
-					last_rtc_update = xtime.tv_sec;
-			}
+			if (ppc_md.set_rtc_time(xtime.tv_sec) == 0)
+				last_rtc_update = xtime.tv_sec;
+			else
+				/* do it again in 60 s */
+				last_rtc_update = xtime.tv_sec;
 		}
 	}
 #ifdef __SMP__
 	smp_local_timer_interrupt(regs);
 #endif		
-
+	
 	if ( ppc_md.heartbeat && !ppc_md.heartbeat_count--)
 		ppc_md.heartbeat();
 	
diff -u --recursive --new-file v2.3.23/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.3.23/linux/arch/ppc/mm/init.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/mm/init.c	Tue Oct 26 15:02:14 1999
@@ -204,9 +204,8 @@
         if (pmd_none(*pmd)) {
 		if (!mem_init_done)
 			pte = (pte_t *) MMU_get_page();
-		else if ((pte = (pte_t *) get_zero_page_fast()) == NULL)
-			if ((pte = (pte_t *) __get_free_page(GFP_KERNEL)))
-				clear_page(pte);
+		else if ((pte = (pte_t *) __get_free_page(GFP_KERNEL)))
+			clear_page(pte);
                 if (pte) {
                         pmd_val(*pmd) = (unsigned long)pte;
                         return pte + offset;
@@ -1156,8 +1155,7 @@
 				    __pa(end_of_DRAM) >> PAGE_SHIFT);
 
 	/* remove the bootmem bitmap from the available memory */
-	remove_mem_piece(&phys_avail, start, start + boot_mapsize, 1);
-
+	remove_mem_piece(&phys_avail, start, boot_mapsize, 1);
 	/* add everything in phys_avail into the bootmem map */
 	for (i = 0; i < phys_avail.n_regions; ++i)
 		free_bootmem(phys_avail.regions[i].address,
@@ -1509,10 +1507,10 @@
 	       ramsize >> 20, Hash_size >> 10, Hash);
 	if ( Hash_size )
 	{
+		if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
 		Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
 		__clear_user(Hash, Hash_size);
-		
-		if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
+
 		/*
 		 * Patch up the instructions in head.S:hash_page
 		 */
diff -u --recursive --new-file v2.3.23/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S
--- v2.3.23/linux/arch/sh/kernel/entry.S	Fri Oct 22 13:21:46 1999
+++ linux/arch/sh/kernel/entry.S	Mon Oct 25 10:59:18 1999
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.15 1999/10/17 01:32:52 gniibe Exp $
+/* $Id: entry.S,v 1.16 1999/10/21 14:00:27 gniibe Exp $
  *
  *  linux/arch/sh/entry.S
  *
@@ -149,7 +149,7 @@
 	/* Unwind the stack and jmp to the debug entry */
 debug:
 	add	#4,r15		! skip syscall number
-	ldc.l	@r15+,ssr
+	mov.l	@r15+,r11	! SSR
 	mov.l	@r15+,r10	! original stack
 	mov.l	@r15+,r0
 	mov.l	@r15+,r1
@@ -164,6 +164,7 @@
 	or	r9,r14
 	ldc	r14,sr			! here, change the register bank
 	mov	r10,k0
+	mov	r11,k1
 	mov.l	@r15+,r8
 	mov.l	@r15+,r9
 	mov.l	@r15+,r10
@@ -180,7 +181,7 @@
 	!
 	mov.l	9f,k0
 	jmp	@k0
-	 nop
+	 ldc	k1,ssr
 	.balign	4
 8:	.long	0x300000f0
 9:	.long	0xa0000100
@@ -371,7 +372,7 @@
 	!
 restore_all:
 	add	#4,r15		! skip syscall number
-	ldc.l	@r15+,ssr
+	mov.l	@r15+,r11	! SSR
 	mov.l	@r15+,r10	! original stack
 	mov.l	@r15+,r0
 	mov.l	@r15+,r1
@@ -386,6 +387,7 @@
 	or	r9,r14
 	ldc	r14,sr			! here, change the register bank
 	mov	r10,k0
+	mov	r11,k1
 	mov.l	@r15+,r8
 	mov.l	@r15+,r9
 	mov.l	@r15+,r10
@@ -399,6 +401,7 @@
 	lds.l	@r15+,pr
 	ldc.l	@r15+,spc
 	mov	k0,r15
+	ldc	k1,ssr
 	rte
 	 nop
 
@@ -515,7 +518,7 @@
 
 .data
 ENTRY(exception_handling_table)
-	.long	none /* XXX: Avoid spurious interrupt */
+	.long	error
 	.long	error
 	.long	tlb_miss_load
 	.long	tlb_miss_store
diff -u --recursive --new-file v2.3.23/linux/arch/sh/kernel/irq_onchip.c linux/arch/sh/kernel/irq_onchip.c
--- v2.3.23/linux/arch/sh/kernel/irq_onchip.c	Fri Oct 22 13:21:46 1999
+++ linux/arch/sh/kernel/irq_onchip.c	Mon Oct 25 10:59:18 1999
@@ -1,4 +1,4 @@
-/* $Id: irq_onchip.c,v 1.3 1999/10/11 13:12:19 gniibe Exp $
+/* $Id: irq_onchip.c,v 1.4 1999/10/19 12:22:05 gniibe Exp $
  *
  * linux/arch/sh/kernel/irq_onchip.c
  *
@@ -89,29 +89,33 @@
 
 void disable_onChip_irq(unsigned int irq)
 {
+	unsigned long val, flags;
 	/* Set priority in IPR to 0 */
 	int offset = ipr_data[irq-TIMER_IRQ].offset;
 	unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE);
 	unsigned short mask = 0xffff ^ (0xf << (offset%16));
-	unsigned long val;
 
+	save_and_cli(flags);
 	val = ctrl_inw(intc_ipr_address);
 	val &= mask;
 	ctrl_outw(val, intc_ipr_address);
+	restore_flags(flags);
 }
 
 static void enable_onChip_irq(unsigned int irq)
 {
+	unsigned long val, flags;
 	/* Set priority in IPR back to original value */
 	int offset = ipr_data[irq-TIMER_IRQ].offset;
 	int priority = ipr_data[irq-TIMER_IRQ].priority;
 	unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE);
 	unsigned short value = (priority << (offset%16));
-	unsigned long val;
 
+	save_and_cli(flags);
 	val = ctrl_inw(intc_ipr_address);
 	val |= value;
 	ctrl_outw(val, intc_ipr_address);
+	restore_flags(flags);
 }
 
 void make_onChip_irq(unsigned int irq)
diff -u --recursive --new-file v2.3.23/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c
--- v2.3.23/linux/arch/sh/kernel/setup.c	Fri Oct 22 13:21:46 1999
+++ linux/arch/sh/kernel/setup.c	Mon Oct 25 10:59:18 1999
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.4 1999/10/17 02:49:24 gniibe Exp $
+/* $Id: setup.c,v 1.7 1999/10/23 01:34:50 gniibe Exp $
  *
  *  linux/arch/sh/kernel/setup.c
  *
@@ -28,14 +28,17 @@
 #ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
 #endif
-#include <asm/processor.h>
+#include <linux/bootmem.h>
 #include <linux/console.h>
+#include <asm/processor.h>
+#include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 
+
 /*
  * Machine setup..
  */
@@ -62,7 +65,6 @@
 #define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c))
 #define INITRD_START (*(unsigned long *) (PARAM+0x010))
 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x014))
-#define MEMORY_END (*(unsigned long *) (PARAM+0x018))
 /* ... */
 #define COMMAND_LINE ((char *) (PARAM+0x100))
 #define COMMAND_LINE_SIZE 256
@@ -105,11 +107,67 @@
 	{ "Video ROM", 0xc0000, 0xc7fff }
 };
 
-void __init setup_arch(char **cmdline_p,
-		       unsigned long * memory_start_p,
-		       unsigned long * memory_end_p)
+static unsigned long memory_start, memory_end;
+
+unsigned long __init memparse(char *ptr, char **retptr)
+{
+	unsigned long ret;
+
+	ret = simple_strtoul(ptr, retptr, 0);
+
+	if (**retptr == 'K' || **retptr == 'k') {
+		ret <<= 10;
+		(*retptr)++;
+	}
+	else if (**retptr == 'M' || **retptr == 'm') {
+		ret <<= 20;
+		(*retptr)++;
+	}
+	return ret;
+} /* memparse */
+
+static inline void parse_mem_cmdline (char ** cmdline_p)
+{
+	char c = ' ', *to = command_line, *from = COMMAND_LINE;
+	int len = 0;
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+
+	memory_start = (unsigned long)__va(0)+__MEMORY_START;
+	/* Default is 4Mbyte. */
+	memory_end = (unsigned long)__va(0x00400000)+__MEMORY_START;
+
+	for (;;) {
+		/*
+		 * "mem=XXX[kKmM]" defines a size of memory.
+		 */
+		if (c == ' ' && !memcmp(from, "mem=", 4)) {
+			if (to != command_line)
+				to--;
+			{
+				unsigned long mem_size;
+
+				mem_size = memparse(from+4, &from);
+				memory_end = memory_start + mem_size;
+			}
+		}
+		c = *(from++);
+		if (!c)
+			break;
+		if (COMMAND_LINE_SIZE <= ++len)
+			break;
+		*(to++) = c;
+	}
+	*to = '\0';
+	*cmdline_p = command_line;
+}
+
+void __init setup_arch(char **cmdline_p)
 {
-	unsigned long memory_start, memory_end;
+	unsigned long bootmap_size;
+	unsigned long start_pfn, max_pfn, max_low_pfn;
 
 	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
 
@@ -118,12 +176,9 @@
 	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
+
 	if (!MOUNT_ROOT_RDONLY)
 		root_mountflags &= ~MS_RDONLY;
-
-	memory_start = (unsigned long) &_end;
-	memory_end = MEMORY_END;
-
 	init_mm.start_code = (unsigned long)&_text;
 	init_mm.end_code = (unsigned long) &_etext;
 	init_mm.end_data = (unsigned long) &_edata;
@@ -134,21 +189,73 @@
 	data_resource.start = virt_to_bus(&_etext);
 	data_resource.end = virt_to_bus(&_edata)-1;
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
-	memcpy(command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	command_line[COMMAND_LINE_SIZE-1] = '\0';
+	parse_mem_cmdline(cmdline_p);
 
-	/* Not support "mem=XXX[kKmM]" command line option. */
-	*cmdline_p = command_line;
-
-	memory_end &= PAGE_MASK;
-	ram_resources[1].end = memory_end-1;
-
-	*memory_start_p = memory_start;
-	*memory_end_p = memory_end;
+#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)	((x) << PAGE_SHIFT)
+
+	/*
+	 * partially used pages are not usable - thus
+	 * we are rounding upwards:
+	 */
+	start_pfn = PFN_UP(__pa(&_end)-__MEMORY_START);
+
+	/*
+	 * Find the highest page frame number we have available
+	 */
+	max_pfn = PFN_DOWN(__pa(memory_end)-__MEMORY_START);
+
+	/*
+	 * Determine low and high memory ranges:
+	 */
+	max_low_pfn = max_pfn;
+
+	/*
+	 * Initialize the boot-time allocator (with low memory only):
+	 */
+	bootmap_size = init_bootmem(start_pfn, max_low_pfn);
+
+	/*
+	 * FIXME: what about high memory?
+	 */
+	ram_resources[1].end = PFN_PHYS(max_low_pfn) + __MEMORY_START;
+
+	/*
+	 * Register fully available low RAM pages with the bootmem allocator.
+	 */
+	{
+		unsigned long curr_pfn, last_pfn, size;
+
+		/*
+		 * We are rounding up the start address of usable memory:
+		 */
+		curr_pfn = PFN_UP(0);
+		/*
+		 * ... and at the end of the usable range downwards:
+		 */
+		last_pfn = PFN_DOWN(memory_end-__MEMORY_START);
+
+		if (last_pfn > max_low_pfn)
+			last_pfn = max_low_pfn;
+
+		size = last_pfn - curr_pfn;
+		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+	}
+	/*
+	 * Reserve the kernel text and
+	 * Reserve the bootmem bitmap itself as well. We do this in two
+	 * steps (first step was init_bootmem()) because this catches
+	 * the (very unlikely) case of us accidentally initializing the
+	 * bootmem allocator with an invalid RAM area.
+	 */
+	reserve_bootmem(PAGE_SIZE, PFN_PHYS(start_pfn) + bootmap_size);
+
+	/*
+	 * reserve physical page 0 - it's a special BIOS page on many boxes,
+	 * enabling clean reboots, SMP operation, laptop functions.
+	 */
+	reserve_bootmem(0, PAGE_SIZE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (LOADER_TYPE) {
@@ -156,10 +263,12 @@
 		initrd_end = initrd_start+INITRD_SIZE;
 		if (initrd_end > memory_end) {
 			printk("initrd extends beyond end of memory "
-			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-			    initrd_end,memory_end);
+			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+			       initrd_end,memory_end);
 			initrd_start = 0;
-		}
+		} else
+			reserve_bootmem(__pa(initrd_start)-__MEMORY_START,
+					INITRD_SIZE);
 	}
 #endif
 
diff -u --recursive --new-file v2.3.23/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c
--- v2.3.23/linux/arch/sh/kernel/time.c	Fri Oct 22 13:21:46 1999
+++ linux/arch/sh/kernel/time.c	Mon Oct 25 10:59:18 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.2 1999/10/11 13:12:02 gniibe Exp $
+/* $Id: time.c,v 1.3 1999/10/17 10:30:15 gniibe Exp $
  *
  *  linux/arch/sh/kernel/time.c
  *
diff -u --recursive --new-file v2.3.23/linux/arch/sh/lib/Makefile linux/arch/sh/lib/Makefile
--- v2.3.23/linux/arch/sh/lib/Makefile	Fri Oct 22 13:21:46 1999
+++ linux/arch/sh/lib/Makefile	Mon Oct 25 10:59:18 1999
@@ -6,7 +6,7 @@
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
 
 L_TARGET = lib.a
-L_OBJS  = delay.o memcpy.o memset.o memmove.o old-checksum.o \
+L_OBJS  = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \
 	  checksum.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.23/linux/arch/sh/lib/memchr.S linux/arch/sh/lib/memchr.S
--- v2.3.23/linux/arch/sh/lib/memchr.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/memchr.S	Mon Oct 25 10:59:18 1999
@@ -0,0 +1,26 @@
+/* $Id: memchr.S,v 1.1 1999/10/17 11:32:38 gniibe Exp $
+ *
+ * "memchr" implementation of SuperH
+ *
+ * Copyright (C) 1999  Niibe Yutaka
+ *
+ */
+
+/*
+ * void *memchr(const void *s, int c, size_t n);
+ */
+
+#include <linux/linkage.h>
+ENTRY(memchr)
+	tst	r6,r6
+	bt/s	2f
+	 exts.b	r5,r5
+1:	mov.b	@r4,r1
+	cmp/eq	r1,r5
+	bt/s	3f
+	 dt	r6
+	bf/s	1b
+	 add	#1,r4
+2:	mov	#0,r4
+3:	rts
+	 mov	r4,r0
diff -u --recursive --new-file v2.3.23/linux/arch/sh/mm/init.c linux/arch/sh/mm/init.c
--- v2.3.23/linux/arch/sh/mm/init.c	Fri Oct 22 13:21:46 1999
+++ linux/arch/sh/mm/init.c	Mon Oct 25 10:59:18 1999
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.3 1999/10/11 10:41:30 gniibe Exp $
+/* $Id: init.c,v 1.4 1999/10/23 01:37:02 gniibe Exp $
  *
  *  linux/arch/sh/mm/init.c
  *
@@ -24,6 +24,7 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
 #endif
+#include <linux/bootmem.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -37,21 +38,53 @@
  */
 unsigned long mmu_context_cache;
 
-static unsigned long totalram = 0;
+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);
 
-void __bad_pte_kernel(pmd_t *pmd)
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving an inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+
+unsigned long empty_bad_page[1024];
+pte_t empty_bad_pte_table[PTRS_PER_PTE];
+extern unsigned long empty_zero_page[1024];
+
+static pte_t * get_bad_pte_table(void)
+{
+	pte_t v;
+	int i;
+
+	v = pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED));
+
+	for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
+		empty_bad_pte_table[i] = v;
+
+	return empty_bad_pte_table;
+}
+
+void __handle_bad_pmd(pmd_t *pmd)
 {
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-	pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
+	pmd_ERROR(*pmd);
+	pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table());
 }
 
-void __bad_pte(pmd_t *pmd)
+void __handle_bad_pmd_kernel(pmd_t *pmd)
 {
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-	pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+	pmd_ERROR(*pmd);
+	pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table());
 }
 
 pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
@@ -61,16 +94,16 @@
 	pte = (pte_t *) __get_free_page(GFP_KERNEL);
 	if (pmd_none(*pmd)) {
 		if (pte) {
-			clear_page((unsigned long)pte);
+			clear_page(pte);
 			pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
 			return pte + offset;
 		}
-		pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
+		pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table());
 		return NULL;
 	}
 	free_page((unsigned long)pte);
 	if (pmd_bad(*pmd)) {
-		__bad_pte_kernel(pmd);
+		__handle_bad_pmd_kernel(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + offset;
@@ -83,19 +116,19 @@
 	pte = (unsigned long) __get_free_page(GFP_KERNEL);
 	if (pmd_none(*pmd)) {
 		if (pte) {
-			clear_page(pte);
+			clear_page((void *)pte);
 			pmd_val(*pmd) = _PAGE_TABLE + __pa(pte);
-			return (pte_t *)(pte + offset);
+			return (pte_t *)pte + offset;
 		}
-		pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+		pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table());
 		return NULL;
 	}
 	free_page(pte);
 	if (pmd_bad(*pmd)) {
-		__bad_pte(pmd);
+		__handle_bad_pmd(pmd);
 		return NULL;
 	}
-	return (pte_t *) (pmd_page(*pmd) + offset);
+	return (pte_t *) pmd_page(*pmd) + offset;
 }
 
 int do_check_pgt_cache(int low, int high)
@@ -114,37 +147,6 @@
 	return freed;
 }
 
-/*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving an inode
- * unused etc..
- *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
- *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-pte_t * __bad_pagetable(void)
-{
-	extern unsigned long empty_bad_page_table[PAGE_SIZE];
-	unsigned long page = (unsigned long)empty_bad_page_table;
-
-	clear_page(page);
-	return (pte_t *)empty_bad_page_table;
-}
-
-pte_t __bad_page(void)
-{
-	extern char empty_bad_page[PAGE_SIZE];
-	unsigned long page = (unsigned long)empty_bad_page;
-
-	clear_page(page);
-	return pte_mkdirty(mk_pte(page, PAGE_SHARED));
-}
-
 void show_mem(void)
 {
 	int i,free = 0,total = 0,reserved = 0;
@@ -170,13 +172,12 @@
 	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();
 #ifdef CONFIG_NET
 	show_net_buffers();
 #endif
 }
 
-extern unsigned long free_area_init(unsigned long, unsigned long);
-
 /* References to section boundaries */
 
 extern char _text, _etext, _edata, __bss_start, _end;
@@ -190,13 +191,10 @@
  * This routines also unmaps the page at virtual kernel address 0, so
  * that we can trap those pesky NULL-reference errors in the kernel.
  */
-unsigned long __init
-paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init paging_init(void)
 {
 	pgd_t * pg_dir;
 
-	start_mem = PAGE_ALIGN(start_mem);
-
 	/* We don't need kernel mapping as hardware support that. */
 	pg_dir = swapper_pg_dir;
 
@@ -209,61 +207,25 @@
 	mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
 	set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);
 
-	return free_area_init(start_mem, end_mem);
+	free_area_init(max_low_pfn);
 }
 
-unsigned long empty_bad_page[1024];
-unsigned long empty_bad_page_table[1024];
-extern unsigned long empty_zero_page[1024];
-
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init mem_init(void)
 {
 	int codepages = 0;
 	int reservedpages = 0;
 	int datapages = 0;
 	int initpages = 0;
-	unsigned long tmp;
 
-	end_mem &= PAGE_MASK;
-	high_memory = (void *) end_mem;
-	max_mapnr = num_physpages = MAP_NR(end_mem);
+	max_mapnr = num_physpages = max_low_pfn;
+	high_memory = (void *) ((unsigned long)__va(max_low_pfn * PAGE_SIZE)+__MEMORY_START);
 
 	/* clear the zero-page */
 	memset(empty_zero_page, 0, PAGE_SIZE);
 
-	/* Mark (clear "reserved" bit) usable pages in the mem_map[] */
-	/*    Note that all are marked reserved already. */
-	tmp = start_mem = PAGE_ALIGN(start_mem);
-	while (tmp < end_mem) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
-		clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
-		tmp += PAGE_SIZE;
-	}
+	/* this will put all low memory onto the freelists */
+	totalram_pages += free_all_bootmem();
 
-	for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) {
-		if (PageReserved(mem_map+MAP_NR(tmp))) {
-			if (tmp >= (unsigned long) &_text && tmp < (unsigned long) &_edata) {
-				if (tmp < (unsigned long) &_etext)
-					codepages++;
-				else
-					datapages++;
-			} else if (tmp >= (unsigned long) &__init_begin
-				   && tmp < (unsigned long) &__init_end)
-				initpages++;
-			else if (tmp >= (unsigned long) &__bss_start
-				 && tmp < (unsigned long) start_mem)
-				datapages++;
-			else
-				reservedpages++;
-			continue;
-		}
-		set_page_count(mem_map+MAP_NR(tmp), 1);
-		totalram += PAGE_SIZE;
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end))
-#endif
-			free_page(tmp);
-	}
 	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
 		(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
 		max_mapnr << (PAGE_SHIFT-10),
@@ -279,19 +241,22 @@
 	
 	addr = (unsigned long)(&__init_begin);
 	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
-		mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
+		ClearPageReserved(mem_map + MAP_NR(addr));
 		set_page_count(mem_map+MAP_NR(addr), 1);
 		free_page(addr);
-		totalram += PAGE_SIZE;
+		totalram_pages++;
 	}
 	printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
 }
 
 void si_meminfo(struct sysinfo *val)
 {
-	val->totalram = totalram;
+	val->totalram = totalram_pages;
 	val->sharedram = 0;
-	val->freeram = nr_free_pages << PAGE_SHIFT;
-	val->bufferram = atomic_read(&buffermem);
+	val->freeram = nr_free_pages;
+	val->bufferram = atomic_read(&buffermem_pages);
+	val->totalhigh = totalhigh_pages;
+	val->freehigh = nr_free_highpages;
+	val->mem_unit = PAGE_SIZE;
 	return;
 }
diff -u --recursive --new-file v2.3.23/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.3.23/linux/drivers/block/Config.in	Fri Oct 22 13:21:47 1999
+++ linux/drivers/block/Config.in	Wed Oct 27 16:07:40 1999
@@ -200,6 +200,9 @@
    bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
 fi
 tristate 'XT hard disk support' CONFIG_BLK_DEV_XD
+if [ "$CONFIG_PCI" = "y" ]; then
+  tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960
+fi
 
 # PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
 # PARIDE must also be a module.  The bogus CONFIG_PARIDE_PARPORT option
diff -u --recursive --new-file v2.3.23/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.3.23/linux/drivers/block/DAC960.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/block/DAC960.c	Wed Oct 27 16:07:40 1999
@@ -19,8 +19,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.2.4"
-#define DAC960_DriverDate			"23 August 1999"
+#define DAC960_DriverVersion			"2.3.4"
+#define DAC960_DriverDate			"23 September 1999"
 
 
 #include <linux/version.h>
@@ -256,7 +256,7 @@
 static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  Semaphore_T Semaphore = MUTEX_LOCKED;
+  DECLARE_MUTEX_LOCKED(Semaphore);
   unsigned long ProcessorFlags;
   Command->Semaphore = &Semaphore;
   DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
@@ -475,8 +475,8 @@
       unsigned char Device = DeviceFunction >> 3;
       unsigned char Function = DeviceFunction & 0x7;
       unsigned int IRQ_Channel = PCI_Device->irq;
-      unsigned long BaseAddress0 = PCI_Device->base_address[0];
-      unsigned long BaseAddress1 = PCI_Device->base_address[1];
+      unsigned long BaseAddress0 = PCI_Device->resource[0].start;
+      unsigned long BaseAddress1 = PCI_Device->resource[1].start;
       unsigned short SubsystemVendorID, SubsystemDeviceID;
       int CommandIdentifier;
       pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID,
@@ -825,7 +825,7 @@
 	    &Controller->InquiryStandardData[Channel][TargetID];
 	  InquiryStandardData->PeripheralDeviceType = 0x1F;
 	  Semaphore = &Semaphores[Channel];
-	  *Semaphore = MUTEX_LOCKED;
+	  init_MUTEX_LOCKED(Semaphore);
 	  DCDB = &DCDBs[Channel];
 	  DAC960_ClearCommand(Command);
 	  Command->CommandType = DAC960_ImmediateCommand;
diff -u --recursive --new-file v2.3.23/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.3.23/linux/drivers/block/cpqarray.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/block/cpqarray.c	Mon Oct 25 20:49:42 1999
@@ -34,6 +34,7 @@
 #include <linux/blkpg.h>
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
@@ -703,6 +704,26 @@
         return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);
 }
 
+#ifndef MODULE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
+/*
+ * Config string is a comma seperated set of i/o addresses of EISA cards.
+ */
+static int cpqarray_setup(char *str)
+{
+	int i, ints[9];
+
+	(void)get_options(str, ARRAY_SIZE(ints), ints);
+
+	for(i=0; i<ints[0] && i<8; i++)
+		eisa[i] = ints[i+1];
+	return 1;
+}
+
+__setup("smart2=", cpqarray_setup);
+
+#else
+
 /*
  * Copy the contents of the ints[] array passed to us by init.
  */
@@ -712,6 +733,8 @@
 	for(i=0; i<ints[0] && i<8; i++)
 		eisa[i] = ints[i+1];
 }
+#endif
+#endif
 
 /*
  * Find an EISA controller's signature.  Set up an hba if we find it.
diff -u --recursive --new-file v2.3.23/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.23/linux/drivers/block/ll_rw_blk.c	Fri Oct 22 13:21:47 1999
+++ linux/drivers/block/ll_rw_blk.c	Tue Oct 26 10:28:17 1999
@@ -286,15 +286,39 @@
 	else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
 }
 
-static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
-                                   short disk_index)
+static inline void drive_stat_acct(struct request *req,
+                                   unsigned long nr_sectors, int new_io)
 {
-	kstat.dk_drive[disk_index]++;
-	if (cmd == READ) {
-		kstat.dk_drive_rio[disk_index]++;
+	int major = MAJOR(req->rq_dev);
+	int minor = MINOR(req->rq_dev);
+	unsigned int disk_index;
+
+	switch (major) {
+		case DAC960_MAJOR+0:
+			disk_index = (minor & 0x00f8) >> 3;
+			break;
+		case SCSI_DISK0_MAJOR:
+			disk_index = (minor & 0x00f0) >> 4;
+			break;
+		case IDE0_MAJOR:	/* same as HD_MAJOR */
+		case XT_DISK_MAJOR:
+			disk_index = (minor & 0x0040) >> 6;
+			break;
+		case IDE1_MAJOR:
+			disk_index = ((minor & 0x0040) >> 6) + 2;
+			break;
+		default:
+			return;
+	}
+	if (disk_index >= DK_NDRIVE)
+		return;
+
+	kstat.dk_drive[disk_index] += new_io;
+	if (req->cmd == READ) {
+		kstat.dk_drive_rio[disk_index] += new_io;
 		kstat.dk_drive_rblk[disk_index] += nr_sectors;
-	} else if (cmd == WRITE) {
-		kstat.dk_drive_wio[disk_index]++;
+	} else if (req->cmd == WRITE) {
+		kstat.dk_drive_wio[disk_index] += new_io;
 		kstat.dk_drive_wblk[disk_index] += nr_sectors;
 	} else
 		printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
@@ -313,35 +337,11 @@
 void add_request(struct blk_dev_struct * dev, struct request * req)
 {
 	int major = MAJOR(req->rq_dev);
-	int minor = MINOR(req->rq_dev);
 	struct request * tmp, **current_request;
-	short		 disk_index;
 	unsigned long flags;
 	int queue_new_request = 0;
 
-	switch (major) {
-		case DAC960_MAJOR+0:
-			disk_index = (minor & 0x00f8) >> 3;
-			if (disk_index < 4)
-				drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
-			break;
-		case SCSI_DISK0_MAJOR:
-			disk_index = (minor & 0x00f0) >> 4;
-			if (disk_index < 4)
-				drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
-			break;
-		case IDE0_MAJOR:	/* same as HD_MAJOR */
-		case XT_DISK_MAJOR:
-			disk_index = (minor & 0x0040) >> 6;
-			drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
-			break;
-		case IDE1_MAJOR:
-			disk_index = ((minor & 0x0040) >> 6) + 2;
-			drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
-		default:
-			break;
-	}
-
+	drive_stat_acct(req, req->nr_sectors, 1);
 	req->next = NULL;
 
 	/*
@@ -575,6 +575,7 @@
 				req->bhtail->b_reqnext = bh;
 				req->bhtail = bh;
 			    	req->nr_sectors += count;
+				drive_stat_acct(req, count, 0);
 				/* Can we now merge this req with the next? */
 				attempt_merge(req, max_sectors);
 			/* or to the beginning? */
@@ -585,6 +586,7 @@
 			    	req->current_nr_sectors = count;
 			    	req->sector = sector;
 			    	req->nr_sectors += count;
+				drive_stat_acct(req, count, 0);
 			} else
 				continue;
 
diff -u --recursive --new-file v2.3.23/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.23/linux/drivers/block/rd.c	Fri Oct 22 13:21:47 1999
+++ linux/drivers/block/rd.c	Mon Oct 25 08:59:32 1999
@@ -276,12 +276,9 @@
 
 static int initrd_release(struct inode *inode,struct file *file)
 {
-	unsigned long i;
-
-	if (--initrd_users) return 0;
-	for (i = initrd_start; i < initrd_end; i += PAGE_SIZE)
-		free_page(i);
 	initrd_start = 0;
+	/* No need to actually release the pages, because that is
+	   done later by free_all_bootmem. */
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.23/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.23/linux/drivers/char/bttv.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/char/bttv.c	Mon Oct 25 08:26:53 1999
@@ -121,8 +121,9 @@
                 if (!pmd_none(*pmd)) {
                         ptep = pte_offset(pmd, adr);
                         pte = *ptep;
+                        /* Note; page_address will panic for us if the page is high */
                         if(pte_present(pte))
-                                ret = (pte_page(pte)|(adr&(PAGE_SIZE-1)));
+                                ret = page_address(pte_page(pte))|(adr&(PAGE_SIZE-1));
                 }
         }
         MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
diff -u --recursive --new-file v2.3.23/linux/drivers/char/drm/proc.c linux/drivers/char/drm/proc.c
--- v2.3.23/linux/drivers/char/drm/proc.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/char/drm/proc.c	Mon Oct 25 08:26:52 1999
@@ -393,7 +393,7 @@
 			       pgprot & _PAGE_PCD      ? 'u' : 'c',
 			       pgprot & _PAGE_ACCESSED ? 'a' : '-',
 			       pgprot & _PAGE_DIRTY    ? 'd' : '-',
-			       pgprot & _PAGE_4M       ? 'm' : 'k',
+			       pgprot & _PAGE_PSE      ? 'm' : 'k',
 			       pgprot & _PAGE_GLOBAL   ? 'g' : 'l' );
 #endif		
 		DRM_PROC_PRINT("\n");
diff -u --recursive --new-file v2.3.23/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.3.23/linux/drivers/char/serial.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/serial.c	Wed Oct 27 16:06:52 1999
@@ -156,6 +156,7 @@
 #ifdef LOCAL_HEADERS
 #include "serial_local.h"
 #else
+#include <linux/serialP.h>
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 #include <asm/serial.h>
diff -u --recursive --new-file v2.3.23/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- v2.3.23/linux/drivers/i2o/i2o_block.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/i2o/i2o_block.c	Mon Oct 25 20:49:42 1999
@@ -703,7 +703,7 @@
 		msg[2] = i2ob_context|0x80000000;
 		msg[3] = (u32)query_done;
 		msg[4] = 60<<16;
-		i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+		i2o_post_wait(dev->controller, msg, 20, 2);
 		/*
 		 *	Unlock the media
 		 */
@@ -712,7 +712,7 @@
 		msg[2] = i2ob_context|0x80000000;
 		msg[3] = (u32)query_done;
 		msg[4] = -1;
-		i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+		i2o_post_wait(dev->controller, msg, 20, 2);
 	
 		/*
  		 * Now unclaim the device.
@@ -766,7 +766,7 @@
 		msg[3] = (u32)query_done;
 		msg[4] = -1;
 		msg[5] = 0;
-		i2o_post_wait(dev->controller, dev->tid, msg, 24, query_done,2);
+		i2o_post_wait(dev->controller, msg, 24, 2);
 		/*
 		 *	Lock the media
 		 */
@@ -775,7 +775,7 @@
 		msg[2] = i2ob_context|0x80000000;
 		msg[3] = (u32)query_done;
 		msg[4] = -1;
-		i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+		i2o_post_wait(dev->controller, msg, 20, 2);
 	}		
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -788,8 +788,8 @@
 static int i2ob_query_device(struct i2ob_device *dev, int table, 
 	int field, void *buf, int buflen)
 {
-	return i2o_query_scalar(dev->controller, dev->tid, i2ob_context,
-		table, field, buf, buflen, &dev->done_flag);
+	return i2o_query_scalar(dev->controller, dev->tid,
+		table, field, buf, buflen);
 }
 
 
@@ -891,7 +891,10 @@
 
 		for(d=c->devices;d!=NULL;d=d->next)
 		{
-			if(d->class!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
+			if(d->lct_data->class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
+				continue;
+
+			if(d->lct_data->user_tid != 0xFFF)
 				continue;
 
 			if(unit<MAX_I2OB<<4)
@@ -903,7 +906,7 @@
 				struct i2ob_device *dev=&i2ob_dev[unit];
 				dev->i2odev = d; 
 				dev->controller = c;
-				dev->tid = d->id;
+				dev->tid = d->lct_data->tid;
  
 				/*
 				 * Insure the device can be claimed
@@ -930,9 +933,10 @@
 			else
 			{
 				if(!warned++)
-					printk("i2o_block: too many controllers, registering only %d.\n", unit>>4);
+					printk("i2o_block: too many device, registering only %d.\n", unit>>4);
 			}
 		}
+		i2o_unlock_controller(c);
 	}
 	i2ob_devices = unit;
 }
@@ -981,7 +985,7 @@
 			msg[2] = i2ob_context|0x80000000;
 			msg[3] = (u32)query_done;
 			msg[4] = 60<<16;
-			i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+			i2o_post_wait(dev->controller, msg, 20, 2);
 			/*
 			 *	Unlock the media
 			 */
@@ -990,7 +994,7 @@
 			msg[2] = i2ob_context|0x80000000;
 			msg[3] = (u32)query_done;
 			msg[4] = -1;
-			i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+			i2o_post_wait(dev->controller, msg, 20, 2);
 		}
 	}	
 	return NOTIFY_DONE;
@@ -1058,7 +1062,7 @@
 {
 	int i;
 
-	printk(KERN_INFO "I2O block device OSM v0.07. (C) 1999 Red Hat Software.\n");
+	printk(KERN_INFO "I2O Block Storage OSM v0.07. (C) 1999 Red Hat Software.\n");
 	
 	/*
 	 *	Register the block device interfaces
diff -u --recursive --new-file v2.3.23/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c
--- v2.3.23/linux/drivers/i2o/i2o_config.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/i2o_config.c	Mon Oct 25 20:49:42 1999
@@ -317,14 +317,14 @@
 		return -ENOMEM;
 	}
 
-        len = i2o_issue_params(i2o_cmd, c, kcmd.tid, cfg_handler.context,
-        			ops, kcmd.oplen, res, 65536, &i2o_cfg_token);
+        len = i2o_issue_params(i2o_cmd, c, kcmd.tid,
+        			ops, kcmd.oplen, res, 65536);
         i2o_unlock_controller(c);
 	kfree(ops);
         
-	if (len < 0) {
+	if (len) {
 		kfree(res);
-		return len; /* -DetailedStatus */
+		return len; /* -DetailedStatus || -ETIMEDOUT */
 	}
 
 	put_user(len, kcmd.reslen);
@@ -413,8 +413,8 @@
 		msg[8] = virt_to_phys(query);
 	}
 
-	token = i2o_post_wait(c, cmd->tid, msg, 9*4, &i2o_cfg_token, 10);
-	if(token != I2O_POST_WAIT_OK)
+	token = i2o_post_wait(c, msg, 9*4, 10);
+	if(token)
 	{
 		i2o_unlock_controller(c);
 		kfree(res);
@@ -531,8 +531,8 @@
 		// Yes...that's one minute, but the spec states that
 		// transfers take a long time, and I've seen just how
 		// long they can take.
-		token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60);
-		if (token != I2O_POST_WAIT_OK )	// Something very wrong
+		token = i2o_post_wait(c, msg, sizeof(msg), 60);
+		if (token)	// Something very wrong
 		{
 			i2o_unlock_controller(c);
 			printk("Timeout downloading software");
@@ -547,8 +547,8 @@
 	msg[4] |= (u32)maxfrag;
 	msg[7] = (0xD0000000 | diff);
 	__copy_from_user(buffer, kxfer.buf, 8192);
-	token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60);
-	if( token != I2O_POST_WAIT_OK )	// Something very wrong
+	token = i2o_post_wait(c, msg, sizeof(msg), 60);
+	if(token)	// Something very wrong
 	{
 		i2o_unlock_controller(c);
 		printk("Timeout downloading software");
@@ -588,10 +588,10 @@
         msg[2] = (u32)i2o_cfg_context;
         msg[3] = 0;
 
-        token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg),&i2o_cfg_token, 10);
+        token = i2o_post_wait(c, msg, sizeof(msg), 10);
         i2o_unlock_controller(c);
 
-        if (token != I2O_POST_WAIT_OK)
+        if (token)
         {
                 printk("Can't validate configuration, ErrorStatus = %d\n",
                 	token);
diff -u --recursive --new-file v2.3.23/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
--- v2.3.23/linux/drivers/i2o/i2o_core.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/i2o_core.c	Mon Oct 25 20:49:42 1999
@@ -1,22 +1,24 @@
-/*
- *	Core I2O structure managment
- *
- *	(C) Copyright 1999   Red Hat Software
+/* 
+ * Core I2O structure managment 
+ * 
+ * (C) Copyright 1999   Red Hat Software 
  *	
- *	Written by Alan Cox, Building Number Three Ltd
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- * 	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
+ * Written by Alan Cox, Building Number Three Ltd 
+ * 
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation; either version 
+ * 2 of the License, or (at your option) any later version.  
+ * 
+ * A lot of the I2O message side code from this is taken from the 
+ * Red Creek RCPCI45 adapter driver by Red Creek Communications 
  *
- *	A lot of the I2O message side code from this is taken from the
- *	Red Creek RCPCI45 adapter driver by Red Creek Communications
- *
- *	Fixes by Philipp Rumpf
- *		      Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- *	         Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
- *				Deepak Saxena <deepak@plexity.net>
+ * Fixes by: 
+ *		Philipp Rumpf 
+ *		Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> 
+ *		Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> 
+ *		Deepak Saxena <deepak@plexity.net> 
+ * 
  */
 
 #include <linux/config.h>
@@ -31,11 +33,16 @@
 #include <linux/malloc.h>
 #include <linux/spinlock.h>
 
+#include <linux/bitops.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+
 #include <asm/io.h>
 
 #include "i2o_lan.h"
 
 #define DRIVERDEBUG
+// #define DEBUG_IRQ
 
 /*
  *	Size of the I2O module table
@@ -48,12 +55,36 @@
 static int reply_flag = 0;
 
 extern int i2o_online_controller(struct i2o_controller *c);
+static int i2o_init_outbound_q(struct i2o_controller *c);
 static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
 			   struct i2o_message *);
 static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *);
 static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *);
+static int i2o_quiesce_system(void);
+static int i2o_enable_system(void);
 static void i2o_dump_message(u32 *);
 
+static int i2o_lct_get(struct i2o_controller *);
+static int i2o_hrt_get(struct i2o_controller *);
+
+static void i2o_sys_init(void);
+static void i2o_sys_shutdown(void);
+
+static int i2o_build_sys_table(void);
+static int i2o_systab_send(struct i2o_controller *c);
+
+/*
+ * I2O System Table.  Contains information about
+ * all the IOPs in the system.  Used to inform IOPs
+ * about each other's existence.
+ *
+ * sys_tbl_ver is the CurrentChangeIndicator that is
+ * used by IOPs to track changes.
+ */
+static struct i2o_sys_tbl *sys_tbl = NULL;
+static int sys_tbl_ind = 0;
+static int sys_tbl_len = 0;
+
 #ifdef MODULE
 /* 
  * Function table to send to bus specific layers
@@ -76,6 +107,21 @@
 
 #endif /* MODULE */
 
+/*
+ * Structures and definitions for synchronous message posting.
+ * See i2o_post_wait() for description.
+ */ 
+struct i2o_post_wait_data
+{
+	int status;
+	u32 id;
+	wait_queue_head_t *wq;
+	struct i2o_post_wait_data *next;
+};
+static struct i2o_post_wait_data *post_wait_queue = NULL;
+static u32 post_wait_id = 0;	// Unique ID for each post_wait
+static spinlock_t post_wait_lock = SPIN_LOCK_UNLOCKED;
+static void i2o_post_wait_complete(u32, int);
 
 /* Message handler */ 
 static struct i2o_handler i2o_core_handler =
@@ -85,6 +131,7 @@
 	0
 };
 
+
 /*
  *	I2O configuration spinlock. This isnt a big deal for contention
  *	so we have one only
@@ -92,11 +139,17 @@
  
 static spinlock_t i2o_configuration_lock = SPIN_LOCK_UNLOCKED;
 
+/*
+ * I2O Core reply handler
+ *
+ * Only messages this should see are i2o_post_wait() replies
+ */
 void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
 		    struct i2o_message *m)
 {
 	u32 *msg=(u32 *)m;
-	u32 *flag = (u32 *)msg[3];
+	u32 status;
+	u32 context = msg[3];
 
 #if 0
 	i2o_report_status(KERN_INFO, "i2o_core", msg);
@@ -117,13 +170,18 @@
                 return;
         }
 
-	if (msg[4] >> 24)
+	if(msg[2]&0x80000000)	// Post wait message
 	{
-		i2o_report_status(KERN_WARNING, "i2o_core", msg);
-		*flag = -(msg[4] & 0xFFFF);
+		if (msg[4] >> 24)
+		{
+			i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
+			status = -(msg[4] & 0xFFFF);
+		}
+		else
+			status = I2O_POST_WAIT_OK;
+	
+		i2o_post_wait_complete(context, status);
 	}
-	else
-		*flag = I2O_POST_WAIT_OK;
 }
 
 /*
@@ -245,6 +303,12 @@
 			c->next=i2o_controller_chain;
 			i2o_controller_chain=c;
 			c->unit = i;
+			c->page_frame = NULL;
+			c->hrt = NULL;
+			c->lct = NULL;
+			c->status_block = NULL;
+			printk(KERN_INFO "lct @ %p hrt @ %p status @ %p",
+					c->lct, c->hrt, c->status_block);
 			sprintf(c->name, "i2o/iop%d", i);
 			i2o_num_controllers++;
 			spin_unlock(&i2o_configuration_lock);
@@ -261,10 +325,14 @@
 	struct i2o_controller **p;
 	int users;
 
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Deleting controller iop%d\n", c->unit);
+#endif
+
 	spin_lock(&i2o_configuration_lock);
 	if((users=atomic_read(&c->users)))
 	{
-		printk("I2O: %d users for controller iop%d\n", users, c->unit);
+		printk(KERN_INFO "I2O: %d users for controller iop%d\n", users, c->unit);
 		spin_unlock(&i2o_configuration_lock);
 		return -EBUSY;
 	}
@@ -280,21 +348,6 @@
 
 	p=&i2o_controller_chain;
 
-	/* Send first SysQuiesce to other IOPs */
-	while(*p)
-	{
-		if(*p!=c)
-		{
-			printk("Quiescing controller %p != %p\n", c, *p);
-			if(i2o_quiesce_controller(*p)<0)
-				printk(KERN_INFO "Unable to quiesce iop%d\n",
-				       (*p)->unit);
-		}
-		p=&((*p)->next);
-	}
-
-	p=&i2o_controller_chain;
-
 	while(*p)
 	{
 		if(*p==c)
@@ -308,15 +361,26 @@
 
 			*p=c->next;
 			spin_unlock(&i2o_configuration_lock);
+
+			printk(KERN_INFO "hrt %p lct %p page_frame %p status_block %p\n",
+				c->hrt, c->lct, c->page_frame, c->status_block);
 			if(c->page_frame)
 				kfree(c->page_frame);
 			if(c->hrt)
 				kfree(c->hrt);
 			if(c->lct)
 				kfree(c->lct);
-			i2o_controllers[c->unit]=NULL;
+			if(c->status_block)
+				kfree(c->status_block);
+
 			kfree(c);
+
+			i2o_controllers[c->unit]=NULL;
+
 			i2o_num_controllers--;
+#ifdef DRIVERDEBUG
+			printk(KERN_INFO "iop deleted\n");
+#endif
 			return 0;
 		}
 		p=&((*p)->next);
@@ -360,7 +424,7 @@
 			return -EBUSY;
 	}
 
-	if(i2o_issue_claim(d->controller,d->id, h->context, 1, &reply_flag, type) < 0)
+	if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 1, &reply_flag, type))
 	{
 		return -EBUSY;
 	}
@@ -395,8 +459,8 @@
 			err = -ENOENT;
 		else
 		{
-			if(i2o_issue_claim(d->controller, d->id, h->context, 0,
-					   &reply_flag, type) < 0)
+			if(i2o_issue_claim(d->controller, d->lct_data->tid, h->context, 0,
+					   &reply_flag, type))
 			{
 				err = -ENXIO;
 			}
@@ -418,8 +482,8 @@
 	{
 		atomic_dec(&d->controller->users);
 
-		if(i2o_issue_claim(d->controller,d->id, h->context, 0, 
-				   &reply_flag, type) < 0)
+		if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 0, 
+				   &reply_flag, type))
 			err = -ENXIO;
 	}
 
@@ -468,7 +532,11 @@
 {
 	struct i2o_message *m;
 	u32 mv;
-	
+
+#ifdef DEBUG_IRQ
+	printk(KERN_INFO "iop%d interrupt\n", c->unit);
+#endif
+
 	while((mv=I2O_REPLY_READ32(c))!=0xFFFFFFFF)
 	{
 		struct i2o_handler *i;
@@ -478,7 +546,11 @@
 		 */
 		if(((m->function_addr>>24)&0xFF)==0x15)
 			printk("UTFR!\n");
-//		printk("dispatching.\n");
+
+#ifdef DEBUG_IRQ
+		i2o_dump_message((u32*)m);
+#endif
+
 		i=i2o_handlers[m->initiator_context&(MAX_I2O_MODULES-1)];
 		if(i)
 			i->reply(i,c,m);
@@ -572,8 +644,10 @@
 	{
 		if((jiffies-time)>=5*HZ)
 		{
+#ifdef DRIVERDEBUG
 			printk(KERN_ERR "%s: Timeout waiting for message frame to send %s.\n", 
 				c->name, why);
+#endif
 			return 0xFFFFFFFF;
 		}
 		schedule();
@@ -596,8 +670,10 @@
 	{
 		if(jiffies-time >= timeout*HZ )
 		{
+#ifdef DRIVERDEBUG
 			printk(KERN_ERR "%s: timeout waiting for %s reply.\n",
 				c->name, why);
+#endif
 			return 0xFFFFFFFF;
 		}
 		schedule();
@@ -686,8 +762,10 @@
 	/* Do we have an error block ? */
 	if(p[1]&0xFF000000)
 	{
+#ifdef DRIVERDEBUG
 		printk(KERN_ERR "%s: error in field read.\n",
 			c->name);
+#endif
 		kfree(rbuf);
 		return -EBADR;
 	}
@@ -711,25 +789,27 @@
 void i2o_report_controller_unit(struct i2o_controller *c, int unit)
 {
 	char buf[64];
+	return;
 	
-	if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 3)>=0)
+	if(i2o_query_scalar(c, unit, 0xF100, 3, buf, 16))
 	{
 		buf[16]=0;
 		printk(KERN_INFO "     Vendor: %s\n", buf);
 	}
-	if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 4)>=0)
+	if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16))
 	{
+
 		buf[16]=0;
 		printk(KERN_INFO "     Device: %s\n", buf);
 	}
 #if 0
-	if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 5)>=0)
+	if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16))
 	{
 		buf[16]=0;
 		printk(KERN_INFO "Description: %s\n", buf);
 	}
 #endif	
-	if(i2o_query_scalar_polled(c, unit, buf, 8, 0xF100, 6)>=0)
+	if(i2o_query_scalar(c, unit, 0xF100, 6, buf, 8))
 	{
 		buf[8]=0;
 		printk(KERN_INFO "        Rev: %s\n", buf);
@@ -749,6 +829,7 @@
  
 static int i2o_parse_hrt(struct i2o_controller *c)
 {
+#ifdef DRIVERDEBUG
 	u32 *rows=c->hrt;
 	u8 *p=(u8 *)c->hrt;
 	u8 *d;
@@ -766,8 +847,8 @@
 	count=p[0]|(p[1]<<8);
 	length = p[2];
 	
-	printk(KERN_INFO "HRT has %d entries of %d bytes each.\n",
-		count, length<<2);
+	printk(KERN_INFO "iop%d: HRT has %d entries of %d bytes each.\n",
+		c->unit, count, length<<2);
 
 	rows+=2;
 	
@@ -829,6 +910,7 @@
 		printk("\n");
 		rows+=length;
 	}
+#endif
 	return 0;
 }
 	
@@ -845,12 +927,12 @@
 	u32 *p;
 	struct i2o_device *d;
 	char str[22];
-	u32 *lct=(u32 *)c->lct;
+	pi2o_lct lct = c->lct;
 
-	max=lct[0]&0xFFFF;
+	max = lct->table_size;
 	
-	max-=3;
-	max/=9;
+	max -= 3;
+	max /= 9;
 
 	if(max==0)
 	{
@@ -866,28 +948,25 @@
 		max=128;
 	}
 	
-	if(lct[1]&(1<<0))
-		printk(KERN_WARNING "Configuration dialog desired.\n");
+	if(lct->iop_flags&(1<<0))
+		printk(KERN_WARNING "I2O: Configuration dialog desired by iop%d.\n", c->unit);
 		
-	p=lct+3;
-	
 	for(i=0;i<max;i++)
 	{
 		d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
 		if(d==NULL)
 		{
-			printk("i2o_core: Out of memory for LCT data.\n");
+			printk("i2o_core: Out of memory for I2O device data.\n");
 			return -ENOMEM;
 		}
 		
 		d->controller = c;
 		d->next = NULL;
-		
-		d->id = tid = (p[0]>>16)&0xFFF;
-		d->class = p[3]&0xFFF;
-		d->subclass = p[4]&0xFFF;
-		d->parent =  (p[5]>>12)&0xFFF;
+
+		d->lct_data = &lct->lct_entry[i];
+
 		d->flags = 0;
+		tid = d->lct_data->tid;
 		
 		printk(KERN_INFO "TID %d.\n", tid);
 
@@ -897,19 +976,19 @@
 		
 		printk(KERN_INFO "  Class: ");
 		
-		sprintf(str, "%-21s", i2o_get_class_name(d->class));
+		sprintf(str, "%-21s", i2o_get_class_name(d->lct_data->class_id));
 		printk("%s", str);
 		
 		printk("  Subclass: 0x%03X   Flags: ",
-			d->subclass);
+			d->lct_data->sub_class);
 			
-		if(p[2]&(1<<0))
+		if(d->lct_data->device_flags&(1<<0))
 			printk("C");		// ConfigDialog requested
-		if(p[2]&(1<<1))
+		if(d->lct_data->device_flags&(1<<1))
 			printk("M");		// Multi-user capable
-		if(!(p[2]&(1<<4)))
+		if(!(d->lct_data->device_flags&(1<<4)))
 			printk("P");		// Peer service enabled!
-		if(!(p[2]&(1<<5)))
+		if(!(d->lct_data->device_flags&(1<<5)))
 			printk("m");		// Mgmt service enabled!
 		printk("\n");
 		p+=9;
@@ -917,30 +996,120 @@
 	return 0;
 }
 
+
 /* Quiesce IOP */
 int i2o_quiesce_controller(struct i2o_controller *c)
 {
 	u32 msg[4];
 
+	if(c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)
+		return -EINVAL;
+
 	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
 	msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[2]=core_context;
+	msg[2]=(u32)core_context;
 	msg[3]=(u32)&reply_flag;
 
 	/* Long timeout needed for quiesce if lots of devices */
-	return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 120);
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Posting quiesce message to iop%d\n", c->unit);
+#endif
+	if(i2o_post_wait(c, msg, sizeof(msg), 120))
+		return -1;
+	else
+		return 0;
+}
+
+/* Enable IOP */
+int i2o_enable_controller(struct i2o_controller *c)
+{
+	u32 msg[4];
+
+	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
+	msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
+	msg[2]=core_context;
+	msg[3]=(u32)&reply_flag;
+
+	/* How long of a timeout do we need? */
+	return i2o_post_wait(c, msg, sizeof(msg), 240);
+}
+
+/*
+ * Quiesce _all_ IOPs in OP state.  
+ * Used during init/shutdown time.
+ */
+int i2o_quiesce_system(void)
+{
+	struct i2o_controller *iop;
+	int ret = 0;
+
+	for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
+	{
+		/* 
+		 * Quiesce only needed on operational IOPs
+		 */
+		i2o_status_get(iop);
+
+		if(iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
+		{
+#ifdef DRIVERDEBUG
+			printk(KERN_INFO "Attempting to quiesce iop%d\n", iop->unit);
+#endif
+			if(i2o_quiesce_controller(iop))
+			{
+				printk(KERN_INFO "Unable to quiesce iop%d\n", iop->unit);
+				ret = -ENXIO;
+			}
+#ifdef DRIVERDEBUG
+			else
+				printk(KERN_INFO "%s quiesced\n", iop->name);
+#endif
+
+			i2o_status_get(iop);	// Update IOP state information
+		}
+	}
+	
+	return ret;
+}
+
+/*
+ * (re)Enable _all_ IOPs in READY state.
+ */
+int i2o_enable_system(void)
+{
+	struct i2o_controller *iop;
+	int ret = 0;
+		
+	for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
+	{
+		/*
+		 * Enable only valid for IOPs in READY state
+		 */
+		i2o_status_get(iop);
+
+		if(iop->status_block->iop_state == ADAPTER_STATE_READY)
+		{
+			if(i2o_enable_controller(iop)<0)
+				printk(KERN_INFO "Unable to (re)enable iop%d\n",
+				       iop->unit);
+			
+			i2o_status_get(iop);	// Update IOP state information
+		}
+	}
+
+	return ret;
 }
 
 
+/* Reset an IOP, but keep message queues alive */
 int i2o_clear_controller(struct i2o_controller *c)
 {
 	u32 msg[4];
+	int ret;
 
-	/* First stop external operations for this IOP */
-	if(i2o_quiesce_controller(c)<0)
-		printk(KERN_INFO "Unable to quiesce iop%d\n", c->unit);
-	else
-		printk(KERN_INFO "Iop%d quiesced\n", c->unit);
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Clearing iop%d\n", c->unit);
+#endif
 
 	/* Then clear the IOP */
 	msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
@@ -948,7 +1117,14 @@
 	msg[2]=core_context;
 	msg[3]=(u32)&reply_flag;
 
-	return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 10);
+	if((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
+		printk(KERN_INFO "ExecIopClear failed: %#10x\n", ret);
+#ifdef DRIVERDEBUG
+	else
+		printk(KERN_INFO "ExecIopClear success!\n");
+#endif
+
+	return ret;
 }
 
 
@@ -959,27 +1135,15 @@
 	u8 *work8;
 	u32 *msg;
 	long time;
-	struct i2o_controller *iop;
 
-	/* First stop external operations */
-	for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
-	{
-		/* Quiesce is rejected on hold state */
-		if(iop->status != ADAPTER_STATE_HOLD)
-		{
-			if(i2o_quiesce_controller(iop)<0)
-				printk(KERN_INFO "Unable to quiesce iop%d\n",
-				       iop->unit);
-			else
-				printk(KERN_DEBUG "%s quiesced\n", iop->name);
-		}
-	}
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Reseting iop%d\n", c->unit);
+#endif
 
-	/* Then reset the IOP */
+	/* Get a message */
 	m=i2o_wait_message(c, "AdapterReset");
-	if(m==0xFFFFFFFF)
+	if(m==0xFFFFFFFF)	
 		return -ETIMEDOUT;
-
 	msg=(u32 *)(c->mem_offset+m);
 	
 	work8=(void *)kmalloc(4, GFP_KERNEL);
@@ -999,12 +1163,16 @@
 	msg[6]=virt_to_phys(work8);
 	msg[7]=0;	/* 64bit host FIXME */
 
+	/* Then reset the IOP */	
 	i2o_post_message(c,m);
 
 	/* Wait for a reply */
 	time=jiffies;
 
-	while(work8[0]==0x01)
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Reset posted, waiting...\n");
+#endif
+	while(work8[0]==0)
 	{
 		if((jiffies-time)>=5*HZ)
 		{
@@ -1016,8 +1184,41 @@
 		barrier();
 	}
 
-	if (work8[0]==0x02)
-		printk(KERN_WARNING "IOP Reset rejected\n");
+	if (work8[0]==0x02) 
+	{ 
+		printk(KERN_WARNING "IOP Reset rejected\n"); 
+	} 
+	else 
+	{
+		/* 
+		 * Once the reset is sent, the IOP goes into the INIT state 
+		 * which is inditerminate.  We need to wait until the IOP 
+		 * has rebooted before we can let the system talk to 
+		 * it. We read the inbound Free_List until a message is 
+		 * available.  If we can't read one in the given ammount of 
+		 * time, we assume the IOP could not reboot properly.  
+		 */ 
+#ifdef DRIVERDEBUG 
+		printk(KERN_INFO "Reset succeeded...waiting for reboot\n"); 
+#endif 
+		time = jiffies; 
+		m = I2O_POST_READ32(c); 
+		while(m == 0XFFFFFFFF) 
+		{ 
+			if((jiffies-time) >= 30*HZ)
+			{
+				printk(KERN_ERR "i2o/iop%d: Timeout waiting for IOP reset.\n", 
+							c->unit); 
+				return -ETIMEDOUT; 
+			} 
+			schedule(); 
+			barrier(); 
+			m = I2O_POST_READ32(c); 
+		} 
+#ifdef DRIVERDEBUG 
+		printk(KERN_INFO "Reboot completed\n"); 
+#endif 
+	}
 
 	return 0;
 }
@@ -1030,13 +1231,24 @@
 	u32 *msg;
 	u8 *status_block;
 
-	status_block=(void *)kmalloc(88, GFP_KERNEL);
-	if(status_block==NULL)
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Getting status block for iop%d\n", c->unit);
+#endif
+	if(c->status_block)
+		kfree(c->status_block);
+
+	c->status_block = 
+		(pi2o_status_block)kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
+	if(c->status_block == NULL)
 	{
-		printk(KERN_ERR "StatusGet failed - no free memory.\n");
+#ifdef DRIVERDEBUG
+		printk(KERN_ERR "No memory in status get!\n");
+#endif
 		return -ENOMEM;
 	}
 
+	status_block = (u8*)c->status_block;
+
 	m=i2o_wait_message(c, "StatusGet");
 	if(m==0xFFFFFFFF)
 		return -ETIMEDOUT;
@@ -1049,7 +1261,7 @@
 	msg[3]=0;
 	msg[4]=0;
 	msg[5]=0;
-	msg[6]=virt_to_phys(status_block);
+	msg[6]=virt_to_phys(c->status_block);
 	msg[7]=0;	/* 64bit host FIXME */
 	msg[8]=88;
 
@@ -1062,7 +1274,9 @@
 	{
 		if((jiffies-time)>=5*HZ)
 		{
+#ifdef DRIVERDEBUG
 			printk(KERN_ERR "IOP get status timeout.\n");
+#endif
 			return -ETIMEDOUT;
 		}
 		schedule();
@@ -1070,8 +1284,6 @@
 	}
 	
 	/* Ok the reply has arrived. Fill in the important stuff */
-	c->status = status_block[10];
-	c->i2oversion = (status_block[9]>>4)&0xFF;
 	c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
 
 	return 0;
@@ -1080,8 +1292,10 @@
 
 int i2o_hrt_get(struct i2o_controller *c)
 {
-	u32 m;
-	u32 *msg;
+	u32 msg[6];
+
+	if(c->hrt)
+		kfree(c->hrt);
 
 	c->hrt=kmalloc(2048, GFP_KERNEL);
 	if(c->hrt==NULL)
@@ -1090,12 +1304,6 @@
 		return -ENOMEM;
 	}
 
-	m=i2o_wait_message(c, "HRTGet");
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-
-	msg=(u32 *)(c->mem_offset+m);
-
 	msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
 	msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
 	msg[2]= core_context;
@@ -1103,134 +1311,271 @@
 	msg[4]= (0xD0000000 | 2048);		/* Simple transaction , 2K */
 	msg[5]= virt_to_phys(c->hrt);		/* Dump it here */
 
-	i2o_post_message(c,m);
-
-	barrier();
-
-	/* Now wait for a reply */
-	m=i2o_wait_reply(c, "HRTGet", 5);
+	return i2o_post_wait(c, msg, sizeof(msg), 20);
+}
 
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
+static int i2o_systab_send(struct i2o_controller* iop)
+{
+	u32 msg[10];
+	u32 privmem[2];
+	u32 privio[2];
+	int ret;
 
-	msg=(u32 *)bus_to_virt(m);
+	privmem[0]=iop->priv_mem;	/* Private memory space base address */
+	privmem[1]=iop->priv_mem_size;
+	privio[0]=iop->priv_io;		/* Private I/O address */
+	privio[1]=iop->priv_io_size;
 
-	if(msg[4]>>24)
-		i2o_report_status(KERN_WARNING, "i2o_core", msg);
+	msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_6;
+	msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
+	msg[2] = 0;	/* Context not needed */
+	msg[3] = 0;
+	msg[4] = (0<<16)|((iop->unit+2)<<12);	/* Host 0 IOP ID (unit + 2) */
+	msg[5] = 0;				/* Segment 0 */
+	
+	/*
+	 *	Scatter Gather List
+	 */
+	msg[6] = 0x54000000|sys_tbl_len;
+	msg[7] = virt_to_phys(sys_tbl);
+	msg[8] = 0xD4000000|48;	/* One table for now */
+	msg[9] = virt_to_phys(privmem);
+/*	msg[10] = virt_to_phys(privio); */
 
-	I2O_REPLY_WRITE32(c,m);
+	ret=i2o_post_wait(iop, msg, sizeof(msg), 120);
+	if(ret)
+		return ret;
 
 	return 0;
 }
 
-
 /*
- *	Bring an I2O controller into HOLD state. See the 1.5
- *	spec. Basically we go
- *
- *	Wait for the message queue to initialise. 
- *	If it didnt -> controller is dead
- *	
- *	Send a get status using the message queue
- *	Poll for a reply block 88 bytes long
- *
- *	Send an initialise outbound queue
- *	Poll for a reply
- *
- *	Post our blank messages to the queue FIFO
- *
- *	Send GetHRT, Parse it
+ * Initialize I2O subsystem.
  */
-
-int i2o_activate_controller(struct i2o_controller *c)
+static void __init i2o_sys_init()
 {
-	long time;
-	u32 m;
-	u8 *workspace;
-	u32 *msg;
-	int i;
+	struct i2o_controller *iop;
 	int ret;
+	u32 m;
 
-	printk(KERN_INFO "Configuring I2O controller at 0x%08X.\n",
-	       (u32)c->mem_phys);
-
-	if((ret=i2o_status_get(c)))
-		return ret;
+	printk(KERN_INFO "Activating I2O controllers\n");
+	printk(KERN_INFO "This may take a few minutes if there are many devices\n");
 
-	if(c->status == ADAPTER_STATE_FAULTED) /* not likely to be seen */
+	/* Get the status for each IOP */
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
 	{
-		printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
-		       c->unit);
-		return -1;
+#ifdef DRIVERDEBUG
+		printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit);
+#endif
+		i2o_status_get(iop);
+
+		if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED)
+		{
+			printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
+					iop->unit);
+			i2o_delete_controller(iop);
+		}
+
+		if(iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
+	   	iop->status_block->iop_state == ADAPTER_STATE_READY ||
+	   	iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
+	   	iop->status_block->iop_state == ADAPTER_STATE_FAILED)
+		{
+			int msg[256];
+
+#ifdef DRIVERDEBUG
+			printk(KERN_INFO "iop%d already running...trying to reboot",
+					iop->unit);
+#endif
+			i2o_init_outbound_q(iop);
+			I2O_REPLY_WRITE32(iop,virt_to_phys(msg));
+			i2o_quiesce_controller(iop);
+			i2o_reset_controller(iop);
+			i2o_status_get(iop);
+		}
 	}
 
 	/*
-	 *	If the board is running, reset it - we have no idea
-	 *	what kind of a mess the previous owner left it in.
+	 * Now init the outbound queue for each one.
 	 */
-	if(c->status == ADAPTER_STATE_HOLD ||
-	   c->status == ADAPTER_STATE_READY ||
-	   c->status == ADAPTER_STATE_OPERATIONAL ||
-	   c->status == ADAPTER_STATE_FAILED)
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
 	{
-		if((ret=i2o_reset_controller(c)))
-			return ret;
+		int i;
 
-		if((ret=i2o_status_get(c)))
-			return ret;
-	}
+		if((ret=i2o_init_outbound_q(iop)))
+		{
+			printk(KERN_ERR 
+				"IOP%d initialization failed: Could not initialize outbound q\n",
+				iop->unit);
+			i2o_delete_controller(iop);
+		}
+		iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
 
-	workspace = (void *)kmalloc(88, GFP_KERNEL);
-	if(workspace==NULL)
-	{
-		printk(KERN_ERR "IOP initialisation failed - no free memory.\n");
-		return -ENOMEM;
+		if(iop->page_frame==NULL)
+		{
+			printk(KERN_ERR "IOP init failed: no memory for message page.\n");
+			i2o_delete_controller(iop);
+			continue;
+		}
+	
+		m=virt_to_phys(iop->page_frame);
+	
+		for(i=0; i< NMBR_MSG_FRAMES; i++)
+		{
+			I2O_REPLY_WRITE32(iop,m);
+			mb();
+			m+=MSG_FRAME_SIZE;
+			mb();
+		}
 	}
 
-	memset(workspace, 0, 88);
-
-	m=i2o_wait_message(c, "OutboundInit");
-	if(m==0xFFFFFFFF)
-	{	
-		kfree(workspace);
-		return -ETIMEDOUT;
+	/*
+	 * OK..parse the HRT
+	 */
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	{
+		if(i2o_hrt_get(iop))
+		{
+			i2o_delete_controller(iop);
+			break;
+		}
+		if(i2o_parse_hrt(iop))
+			i2o_delete_controller(iop);
 	}
 
-	msg=(u32 *)(c->mem_offset+m);
-
-	msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
-	msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= core_context;
-	msg[3]= 0x0106;			/* Transaction context */
-	msg[4]= 4096;			/* Host page frame size */
-	msg[5]= MSG_FRAME_SIZE<<16|0x80;	/* Outbound msg frame size and Initcode */
-	msg[6]= 0xD0000004;		/* Simple SG LE, EOB */
-	msg[7]= virt_to_phys(workspace);
-	*((u32 *)workspace)=0;
+	/*
+	 * Build and send the system table
+	 */
+	i2o_build_sys_table();
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
+#ifdef DRIVERDEBUG
+	{
+		printk(KERN_INFO "Sending system table to iop%d\n", iop->unit);
+#endif
+		i2o_systab_send(iop);
+#ifdef DRIVERDEBUG
+	}
+#endif
 
 	/*
-	 *	Post it
+	 * Enable
 	 */
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	{
+#ifdef DRIVERDEBUG
+		printk(KERN_INFO "Enableing iop%d\n", iop->unit);
+#endif
+		if(i2o_enable_controller(iop))
+		{
+			printk(KERN_ERR "Could not enable iop%d\n", iop->unit);
+			i2o_delete_controller(iop);
+		}
+	}
 
-	i2o_post_message(c,m);
-	
-	barrier();
-	
-	time=jiffies;
-	
-	while(workspace[0]!=I2O_CMD_OUTBOUND_INIT_COMPLETE)
+	/*
+	 * OK..one last thing and we're ready to go!
+	 */
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
 	{
-		if((jiffies-time)>=5*HZ)
+#ifdef DRIVERDEBUG
+		printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit);
+#endif
+		if(i2o_lct_get(iop))
 		{
-			printk(KERN_ERR "IOP outbound initialise failed.\n");
-			kfree(workspace);
-			return -ETIMEDOUT;
+			printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
+			i2o_delete_controller(iop);
 		}
-		schedule();
-		barrier();
+		else	
+			i2o_parse_lct(iop);
 	}
+}
+
+/*
+ * Shutdown I2O system
+ *
+ * 1. Quiesce all controllers
+ * 2. Delete all controllers
+ *
+ */
+static void i2o_sys_shutdown(void)
+{
+	struct i2o_controller *iop = NULL;
 
-	kfree(workspace);
+	i2o_quiesce_system();
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
+		i2o_delete_controller(iop);
+}
+
+/*
+ *	Bring an I2O controller into HOLD state. See the 1.5
+ *	spec. Basically we go
+ *
+ *	Wait for the message queue to initialise. 
+ *	If it didnt -> controller is dead
+ *	
+ *	Send a get status using the message queue
+ *	Poll for a reply block 88 bytes long
+ *
+ *	Send an initialise outbound queue
+ *	Poll for a reply
+ *
+ *	Post our blank messages to the queue FIFO
+ *
+ *	Send GetHRT, Parse it
+ */
+int i2o_activate_controller(struct i2o_controller *c)
+{
+	return 0;
+#ifdef I2O_HOTPLUG_SUPPORT
+	u32 m;
+	int i;
+	int ret;
+
+	printk(KERN_INFO "Configuring I2O controller at 0x%08X.\n",
+	       (u32)c->mem_phys);
+
+	if((ret=i2o_status_get(c)))
+		return ret;
+
+	/* not likely to be seen */
+	if(c->status_block->iop_state == ADAPTER_STATE_FAULTED) 
+	{
+		printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
+		       c->unit);
+		return -1;
+	}
+
+	/*
+	 * If the board is running, reset it - we have no idea
+	 * what kind of a mess the previous owner left it in.
+	 * We need to feed the IOP a single outbound message
+	 * so that it can reply back to the ExecSysQuiesce.
+	 */
+	if(c->status_block->iop_state == ADAPTER_STATE_HOLD ||
+	   c->status_block->iop_state == ADAPTER_STATE_READY ||
+	   c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
+	   c->status_block->iop_state == ADAPTER_STATE_FAILED)
+	{
+		int msg[256];
+		printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit);
+
+		if(i2o_init_outbound_q(c));
+		I2O_REPLY_WRITE32(c,virt_to_phys(msg));
+
+		if((ret=i2o_reset_controller(c)))
+			return ret;
+
+		if((ret=i2o_status_get(c)))
+			return ret;
+	}
+
+	if((ret=i2o_init_outbound_q(c)))
+	{
+		printk(KERN_ERR 
+			"IOP%d initialization failed: Could not initialize outbound queue\n",
+			c->unit);
+		return ret;
+	}
 
 	/* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
 
@@ -1248,46 +1593,101 @@
 		I2O_REPLY_WRITE32(c,m);
 		mb();
 		m+=MSG_FRAME_SIZE;
+		mb();
 	}
 	
-	/*
-	 *	The outbound queue is initialised and loaded,
-	 *
-	 *	Now we need the Hardware Resource Table. We must ask for
-	 *	this next we can't issue random messages yet.
-	 */
-	ret=i2o_hrt_get(c);
-	if(ret)
-		return ret;
+	/* 
+	 *	The outbound queue is initialised and loaded, 
+	 * 
+	 *	Now we need the Hardware Resource Table. We must ask for 
+	 *	this next we can't issue random messages yet.  
+	 */ 
+	ret=i2o_hrt_get(c); if(ret) return ret;
 
 	ret=i2o_parse_hrt(c);
 	if(ret)
 		return ret;
 
 	return i2o_online_controller(c);
-//	i2o_report_controller_unit(c, ADAPTER_TID);
+#endif
 }
 
-
-int i2o_lct_get(struct i2o_controller *c)
+/*
+ * Clear and (re)initialize IOP's outbound queue
+ */
+int i2o_init_outbound_q(struct i2o_controller *c)
 {
+	u8 workspace[88];
 	u32 m;
 	u32 *msg;
+	u32 time;
 
-	m=i2o_wait_message(c, "LCTNotify");
+	memset(workspace, 0, 88);
 
+	printk(KERN_INFO "i2o/iop%d: Initializing Outbound Queue\n", c->unit);
+	m=i2o_wait_message(c, "OutboundInit");
 	if(m==0xFFFFFFFF)
+	{	
+		kfree(workspace);
 		return -ETIMEDOUT;
+	}
 
 	msg=(u32 *)(c->mem_offset+m);
 
+	msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6;
+	msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID;
+	msg[2]= core_context;
+	msg[3]= 0x0106;			/* Transaction context */
+	msg[4]= 4096;			/* Host page frame size */
+	msg[5]= MSG_FRAME_SIZE<<16|0x80;	/* Outbound msg frame size and Initcode */
+	msg[6]= 0xD0000004;		/* Simple SG LE, EOB */
+	msg[7]= virt_to_phys(workspace);
+	*((u32 *)workspace)=0;
+
+	/*
+	 *	Post it
+	 */
+	i2o_post_message(c,m);
+	
+	barrier();
+	
+	time=jiffies;
+	
+	while(workspace[0]!=I2O_CMD_OUTBOUND_INIT_COMPLETE)
+	{
+		if((jiffies-time)>=5*HZ)
+		{
+			printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n",
+						c->unit);
+			kfree(workspace);
+			return -ETIMEDOUT;
+		}
+		schedule();
+		barrier();
+	}
+
+	return 0;
+}
+
+/*
+ * Get the IOP's Logical Configuration Table
+ */
+int i2o_lct_get(struct i2o_controller *c)
+{
+	u32 msg[8];
+
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Getting lct for iop%d\n", c->unit);
+#endif
+
+	if(c->lct)
+		kfree(c->lct);
+
 	c->lct = kmalloc(8192, GFP_KERNEL);
 	if(c->lct==NULL)
 	{
-		msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-		msg[1]= HOST_TID<<12|ADAPTER_TID;	/* NOP */
-		i2o_post_message(c,m);
-		printk(KERN_ERR "No free memory for i2o controller buffer.\n");
+		printk(KERN_ERR "i2o/iop%d: No free memory for i2o controller buffer.\n",
+				c->unit);
 		return -ENOMEM;
 	}
 	
@@ -1302,25 +1702,8 @@
 	msg[6] = 0xD0000000|8192;
 	msg[7] = virt_to_bus(c->lct);
 
-	i2o_post_message(c,m);
-
-	barrier();
-
-	/* Now wait for a reply */
-	m=i2o_wait_reply(c, "LCTNotify", 5);
-
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-
-	msg=(u32 *)bus_to_virt(m);
-
-	/* TODO: Check TableSize for big LCTs and send new ExecLctNotify 
-	 * with bigger workspace */
-
-	if(msg[4]>>24)
-		i2o_report_status(KERN_ERR, "i2o_core", msg);
-
-	return 0;
+	
+	return(i2o_post_wait(c, msg, sizeof(msg), 120));
 }
 
 
@@ -1330,13 +1713,14 @@
  
 int i2o_online_controller(struct i2o_controller *c)
 {
-	u32 m;
-	u32 *msg;
-	u32 systab[32];
+	return 0;
+#ifdef I2O_HOTPLUG_SUPPORT
+	u32 msg[10];
 	u32 privmem[2];
 	u32 privio[2];
+	u32 systab[32];
 	int ret;
-	
+
 	systab[0]=1;
 	systab[1]=0;
 	systab[2]=0;
@@ -1350,103 +1734,45 @@
 	systab[10]=virt_to_phys(c->post_port);
 	systab[11]=0;
 	
+	i2o_build_sys_table();
+	
 	privmem[0]=c->priv_mem;		/* Private memory space base address */
 	privmem[1]=c->priv_mem_size;
 	privio[0]=c->priv_io;		/* Private I/O address */
 	privio[1]=c->priv_io_size;
-	
-	m=i2o_wait_message(c, "SysTabSet");
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-	
-	/* Now we build the systab */
-	msg=(u32 *)(c->mem_offset+m);
-	
+
 	msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_6;
 	msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
 	msg[2] = 0;	/* Context not needed */
 	msg[3] = 0;
-	msg[4] = (1<<16)|(2<<12);	/* Host 1 I2O 2 */
-	msg[5] = 1;			/* Segment 1 */
+	msg[4] = (0<<16)|(2<<12);	/* Host 1 I2O 2 */
+	msg[5] = 0;			/* Segment 1 */
 	
 	/*
 	 *	Scatter Gather List
 	 */
-
-	msg[6] = 0x54000000|48;	/* One table for now */
-	msg[7] = virt_to_phys(systab);
+	msg[6] = 0x54000000|sys_tbl_len;	/* One table for now */
+	msg[7] = virt_to_phys(sys_tbl);
 	msg[8] = 0xD4000000|48;	/* One table for now */
 	msg[9] = virt_to_phys(privmem);
-/* 	msg[10] = virt_to_phys(privio); */
-	
-	i2o_post_message(c,m);
+/*	msg[10] = virt_to_phys(privio); */
 
-	barrier();
-	
-	/*
-	 *	Now wait for a reply
-	 */
-	 
-	 
-	m=i2o_wait_reply(c, "SysTabSet", 5);
-		
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-	
-	msg=(u32 *)bus_to_virt(m);
-	
-	if(msg[4]>>24)
-	{
-		i2o_report_status(KERN_ERR, "i2o_core", msg);
-	}
-	I2O_REPLY_WRITE32(c,m);
+	return(i2o_post_wait(c, msg, sizeof(msg), 120));
 	
 	/*
 	 *	Finally we go online
 	 */
-	 
-	m=i2o_wait_message(c, "SysEnable");
-	
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-	
-	msg=(u32 *)(c->mem_offset+m);
-	
-	msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1] = I2O_CMD_SYS_ENABLE<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2] = 0;		/* Context not needed */
-	msg[3] = 0;
-
-	i2o_post_message(c,m);
-	
-	barrier();
-	
-	/*
-	 *	Now wait for a reply
-	 */
-	 
-	
-	m=i2o_wait_reply(c, "SysEnable", 240);
-
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-	
-	msg=(u32 *)bus_to_virt(m);
-	
-	if(msg[4]>>24)
-	{
-		i2o_report_status(KERN_ERR, "i2o_core", msg);
-	}
-	I2O_REPLY_WRITE32(c,m);
+	ret = i2o_enable_controller(c);
+	if(ret)
+		return ret;
 	
 	/*
 	 *	Grab the LCT, see what is attached
 	 */
-
 	ret=i2o_lct_get(c);
 	if(ret)
 	{
-		/* Maybe we should do also sthg else */
+		/* Maybe we should do also do something else */
 		return ret;
 	}
 
@@ -1454,11 +1780,73 @@
 	if(ret)
 		return ret;
 
-	I2O_REPLY_WRITE32(c,m);
-	
+	return 0;
+#endif
+}
+
+static int i2o_build_sys_table(void)
+{
+	struct i2o_controller *iop = NULL;
+	int count = 0;
+#ifdef DRIVERDEBUG
+	u32 *table;
+#endif
+
+	sys_tbl_len = sizeof(struct i2o_sys_tbl) +	// Header + IOPs
+				(i2o_num_controllers) *
+					sizeof(struct i2o_sys_tbl_entry);
+
+#ifdef DRIVERDEBUG
+	printk(KERN_INFO "Building system table len = %d\n", sys_tbl_len);
+#endif
+	if(sys_tbl)
+		kfree(sys_tbl);
+
+	sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL);
+	if(!sys_tbl)
+		return -ENOMEM;
+	memset((void*)sys_tbl, 0, sys_tbl_len);
+
+	sys_tbl->num_entries = i2o_num_controllers;
+	sys_tbl->version = I2OVERSION; /* TODO: Version 2.0 */
+	sys_tbl->change_ind = sys_tbl_ind++;
+
+	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	{
+		// Get updated IOP state so we have the latest information
+		i2o_status_get(iop);	
+
+		sys_tbl->iops[count].org_id = iop->status_block->org_id;
+		sys_tbl->iops[count].iop_id = iop->unit + 2;
+		sys_tbl->iops[count].seg_num = 0;
+		sys_tbl->iops[count].i2o_version = 
+				iop->status_block->i2o_version;
+		sys_tbl->iops[count].iop_state = 
+				iop->status_block->iop_state;
+		sys_tbl->iops[count].msg_type = 
+				iop->status_block->msg_type;
+		sys_tbl->iops[count].frame_size = 
+				iop->status_block->inbound_frame_size;
+		sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
+		sys_tbl->iops[count].iop_capabilities = 
+				iop->status_block->iop_capabilities;
+		sys_tbl->iops[count].inbound_low = 
+				(u32)virt_to_phys(iop->post_port);
+		sys_tbl->iops[count].inbound_high = 0;	// TODO: 64-bit support
+
+		count++;
+	}
+
+#ifdef DRIVERDEBUG
+	table = (u32*)sys_tbl;
+	for(count = 0; count < (sys_tbl_len >>2); count++)
+		printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]);
+#endif
+
 	return 0;
 }
 
+
 /*
  *	Run time support routines
  */
@@ -1469,11 +1857,11 @@
  *	this is simply not worth optimising
  */
 
-int i2o_post_this(struct i2o_controller *c, int tid, u32 *data, int len)
+int i2o_post_this(struct i2o_controller *c, u32 *data, int len)
 {
 	u32 m;
 	u32 *msg;
-       	unsigned long t=jiffies;
+	unsigned long t=jiffies;
 
 	do
 	{
@@ -1485,8 +1873,9 @@
 	
 	if(m==0xFFFFFFFF)
 	{
-		printk(KERN_ERR "i2o: controller not responding.\n");
-		return -1;
+		printk(KERN_ERR "i2o/iop%d: Timeout waiting for message frame!\n",
+					c->unit);
+		return -ETIMEDOUT;
 	}
 	msg = bus_to_virt(c->mem_offset + m);
  	memcpy(msg, data, len);
@@ -1495,32 +1884,114 @@
 }
 
 /*
- *	Post a message and wait for a response flag to be set. This API will
- *	change to use wait_queue's one day
+ *	Post a message and wait for a response flag to be set.
  */
- 
-int i2o_post_wait(struct i2o_controller *c, int tid, u32 *data, int len, int *flag, int timeout)
+int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
 {
-	unsigned long t=jiffies;
+	DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post);
+	int status = 0;
+	int flags = 0;
+	int ret = 0;
+	struct i2o_post_wait_data *p1, *p2;
+	struct i2o_post_wait_data *wait_data =
+		kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);
+
+	if(!wait_data)
+		return -ETIMEDOUT;
+
+	p1 = p2 = NULL;
 	
-	*flag = 0;
-		
-	if(i2o_post_this(c, tid, data, len))
-		return I2O_POST_WAIT_TIMEOUT;
-		
-	while(!*flag && (jiffies-t)<timeout*HZ)
+	/* 
+	 * The spin locking is needed to keep anyone from playing 
+	 * with the queue pointers and id while we do the same
+	 */
+	spin_lock_irqsave(&post_wait_lock, flags);
+	wait_data->next = post_wait_queue;
+	post_wait_queue = wait_data;
+	wait_data->id = ++post_wait_id;
+	spin_unlock_irqrestore(&post_wait_lock, flags);
+
+	wait_data->wq = &wq_i2o_post;
+	wait_data->status = -ETIMEDOUT;
+
+	msg[3] = (u32)wait_data->id;	
+	msg[2] = 0x80000000|(u32)core_context;
+
+	if((ret=i2o_post_this(c, msg, len)))
+		return ret;
+	/*
+	 * Go to sleep and wait for timeout or wake_up call
+	 */
+	interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout);
+
+	/*
+	 * Grab transaction status
+	 */
+	status = wait_data->status;
+
+	/* 
+	 * Remove the entry from the queue.
+	 * Since i2o_post_wait() may have been called again by
+	 * a different thread while we were waiting for this 
+	 * instance to complete, we're not guaranteed that 
+	 * this entry is at the head of the queue anymore, so 
+	 * we need to search for it, find it, and delete it.
+	 */
+	spin_lock_irqsave(&post_wait_lock, flags);
+	for(p1 = post_wait_queue; p1;  )
 	{
-		schedule();
-		mb();
+		if(p1 == wait_data)
+		{
+			if(p2)
+				p2->next = p1->next;
+			else
+				post_wait_queue = p1->next;
+
+			break;
+		}
+		p1 = p1->next;
 	}
+	spin_unlock_irqrestore(&post_wait_lock, flags);
+	
+	kfree(wait_data);
 
-	if (*flag < 0)
-		return *flag; /* DetailedStatus */
+	return status;
+}
 
-	if (*flag == 0)
-		return I2O_POST_WAIT_TIMEOUT;
-	
-	return I2O_POST_WAIT_OK;
+/*
+ * i2o_post_wait is completed and we want to wake up the 
+ * sleeping proccess. Called by core's reply handler.
+ */
+static void i2o_post_wait_complete(u32 context, int status)
+{
+	struct i2o_post_wait_data *p1 = NULL;
+
+	/* 
+	 * We need to search through the post_wait 
+	 * queue to see if the given message is still
+	 * outstanding.  If not, it means that the IOP 
+	 * took longer to respond to the message than we 
+	 * had allowed and timer has already expired.  
+	 * Not much we can do about that except log
+	 * it for debug purposes, increase timeout, and recompile
+	 *
+	 * Lock needed to keep anyone from moving queue pointers 
+	 * around while we're looking through them.
+	 */
+	spin_lock(&post_wait_lock);
+	for(p1 = post_wait_queue; p1; p1 = p1->next)
+	{
+		if(p1->id == context)
+		{
+			p1->status = status;
+			wake_up_interruptible(p1->wq);
+			spin_unlock(&post_wait_lock);
+			return;
+		}
+	}
+	spin_unlock(&post_wait_lock);
+
+	printk(KERN_DEBUG "i2o_post_wait reply after timeout!");
 }
 
 /*
@@ -1543,7 +2014,7 @@
 	msg[3] = (u32)flag;
 	msg[4] = type;
 	
-	return i2o_post_wait(c, tid, msg, 20, flag,2);
+	return i2o_post_wait(c, msg, 20, 2);
 }
 
 /*	Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
@@ -1554,60 +2025,56 @@
  *	Note that the minimum sized resblk is 8 bytes and contains
  *	ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
  */
-int i2o_issue_params(int cmd, 
-                struct i2o_controller *iop, int tid, int context, 
-                void *opblk, int oplen, void *resblk, int reslen, 
-                int *flag)
+int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid, 
+                void *opblk, int oplen, void *resblk, int reslen)
 {
-        u32 msg[9]; 
+u32 msg[9]; 
 	u8 *res = (u8 *)resblk;
 	int res_count;
 	int blk_size;
 	int bytes;
 	int wait_status;
 
-        msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
-        msg[1] = cmd << 24 | HOST_TID << 12 | tid; 
-        msg[2] = context | 0x80000000;
-        msg[3] = (u32)flag;
-        msg[4] = 0;
-        msg[5] = 0x54000000 | oplen;	/* OperationBlock */
-        msg[6] = virt_to_bus(opblk);
-        msg[7] = 0xD0000000 | reslen;	/* ResultBlock */
-        msg[8] = virt_to_bus(resblk);
-
-        wait_status = i2o_post_wait(iop, tid, msg, sizeof(msg), flag, 10);
-	if (wait_status < 0)       
-                return wait_status; 	/* -DetailedStatus */
-
-        if (res[1]&0x00FF0000) 	/* BlockStatus != SUCCESS */
-        {
-                printk(KERN_WARNING "%s - Error:\n  ErrorInfoSize = 0x%02x, " 
-                	"BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
-                        (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
-                                                         : "PARAMS_GET",   
-                        res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
-                return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
-        }
-
-    	res_count = res[0] & 0xFFFF; /* # of resultblocks */
-    	bytes = 4; 
-    	res  += 4;
-    	while (res_count--)
+	msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
+	msg[1] = cmd << 24 | HOST_TID << 12 | tid; 
+	msg[4] = 0;
+	msg[5] = 0x54000000 | oplen;	/* OperationBlock */
+	msg[6] = virt_to_bus(opblk);
+	msg[7] = 0xD0000000 | reslen;	/* ResultBlock */
+	msg[8] = virt_to_bus(resblk);
+
+	wait_status = i2o_post_wait(iop, msg, sizeof(msg), 10);
+	if (wait_status)       
+   	return wait_status; 	/* -DetailedStatus */
+
+	if (res[1]&0x00FF0000) 	/* BlockStatus != SUCCESS */
+	{
+		printk(KERN_WARNING "%s - Error:\n  ErrorInfoSize = 0x%02x, " 
+					"BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
+					(cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
+					: "PARAMS_GET",   
+					res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
+		return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
+	}
+
+	res_count = res[0] & 0xFFFF; /* # of resultblocks */
+	bytes = 4; 
+	res  += 4;
+	while (res_count--)
 	{
 		blk_size = (res[0] & 0xFFFF) << 2;
 		bytes   += blk_size;
 		res     += blk_size;
 	}
-
-        return bytes; /* total sizeof Result List in bytes */
+  
+	return bytes; /* total sizeof Result List in bytes */
 }
 
 /*
  *	 Query one scalar group value or a whole scalar group.
  */                  	
-int i2o_query_scalar(struct i2o_controller *iop, int tid, int context, 
-                     int group, int field, void *buf, int buflen, int *flag)
+int i2o_query_scalar(struct i2o_controller *iop, int tid, 
+                     int group, int field, void *buf, int buflen)
 {
 	u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
 	u8  resblk[8+buflen]; /* 8 bytes for header */
@@ -1616,8 +2083,8 @@
 	if (field == -1)  		/* whole group */
        		opblk[4] = -1;
               
-        size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, context, 
-			opblk, sizeof(opblk), resblk, sizeof(resblk), flag);
+	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, 
+		opblk, sizeof(opblk), resblk, sizeof(resblk));
 			
 	if (size < 0)
 		return size;	
@@ -1629,38 +2096,38 @@
 /*
  *	Set a scalar group value or a whole group.
  */
-int i2o_set_scalar(struct i2o_controller *iop, int tid, int context, 
-		   int group, int field, void *buf, int buflen, int *flag)
+int i2o_set_scalar(struct i2o_controller *iop, int tid, 
+		   int group, int field, void *buf, int buflen)
 {
 	u16 *opblk;
 	u8  resblk[8+buflen]; /* 8 bytes for header */
         int size;
 
-        opblk = kmalloc(buflen+64, GFP_KERNEL);
-        if (opblk == NULL)
-        {
-                printk(KERN_ERR "i2o: no memory for operation buffer.\n");
-                return -ENOMEM;
-        }
+	opblk = kmalloc(buflen+64, GFP_KERNEL);
+	if (opblk == NULL)
+	{
+		printk(KERN_ERR "i2o: no memory for operation buffer.\n");
+		return -ENOMEM;
+	}
 
-        opblk[0] = 1;                        /* operation count */
-        opblk[1] = 0;                        /* pad */
-        opblk[2] = I2O_PARAMS_FIELD_SET;
-        opblk[3] = group;
-
-        if(field == -1) {               /* whole group */
-                opblk[4] = -1;
-                memcpy(opblk+5, buf, buflen);
-        }
-        else                            /* single field */
-        {
-                opblk[4] = 1;
-                opblk[5] = field;
-                memcpy(opblk+6, buf, buflen);
-        }   
+	opblk[0] = 1;                        /* operation count */
+	opblk[1] = 0;                        /* pad */
+	opblk[2] = I2O_PARAMS_FIELD_SET;
+	opblk[3] = group;
+
+	if(field == -1) {               /* whole group */
+		opblk[4] = -1;
+		memcpy(opblk+5, buf, buflen);
+	}
+	else                            /* single field */
+	{
+		opblk[4] = 1;
+		opblk[5] = field;
+		memcpy(opblk+6, buf, buflen);
+	}   
 
-        size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, 
-			opblk, 12+buflen, resblk, sizeof(resblk), flag);
+	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 
+				opblk, 12+buflen, resblk, sizeof(resblk));
 
 	kfree(opblk);
 	return size;
@@ -1687,10 +2154,9 @@
  *
  *	You could also use directly function i2o_issue_params().
  */
-int i2o_query_table(int oper,
-		struct i2o_controller *iop, int tid, int context, int group,
+int i2o_query_table(int oper, struct i2o_controller *iop, int tid, int group,
 		int fieldcount, void *ibuf, int ibuflen,
-		void *resblk, int reslen, int *flag) 
+		void *resblk, int reslen) 
 {
 	u16 *opblk;
 	int size;
@@ -1709,8 +2175,8 @@
 	opblk[4] = fieldcount;
 	memcpy(opblk+5, ibuf, ibuflen);		/* other params */
 
-        size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, context, 
-			opblk, 10+ibuflen, resblk, reslen, flag);
+	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, 
+				opblk, 10+ibuflen, resblk, reslen);
 
 	kfree(opblk);
 	return size;
@@ -1720,14 +2186,13 @@
  * 	Clear table group, i.e. delete all rows.
  */
 
-int i2o_clear_table(struct i2o_controller *iop, int tid, int context,
-		    int group, int *flag)
+int i2o_clear_table(struct i2o_controller *iop, int tid, int group)
 {
 	u16 opblk[] = { 1, 0, I2O_PARAMS_TABLE_CLEAR, group };
 	u8  resblk[32]; /* min 8 bytes for result header */
 
-        return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, 
-			opblk, sizeof(opblk), resblk, sizeof(resblk), flag);
+	return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 
+				opblk, sizeof(opblk), resblk, sizeof(resblk));
 }
 
 /*
@@ -1739,9 +2204,8 @@
  *  		buf contains fieldindexes, rowcount, keyvalues
  */	
 
-int i2o_row_add_table(struct i2o_controller *iop, int tid, int context,
-		    int group, int fieldcount, void *buf, int buflen,
-		    int *flag)
+int i2o_row_add_table(struct i2o_controller *iop, int tid,
+		    int group, int fieldcount, void *buf, int buflen)
 {
 	u16 *opblk;
 	u8  resblk[32]; /* min 8 bytes for header */
@@ -1761,8 +2225,8 @@
 	opblk[4] = fieldcount;
 	memcpy(opblk+5, buf, buflen);
 
-        size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, 
-			opblk, 10+buflen, resblk, sizeof(resblk), flag);
+	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, 
+				opblk, 10+buflen, resblk, sizeof(resblk));
 
 	kfree(opblk);
 	return size;
@@ -1772,9 +2236,8 @@
  *	Delete rows from a table group.
  */ 
 
-int i2o_row_delete_table(struct i2o_controller *iop, int tid, int context,
-		    int group, int keycount, void *keys, int keyslen,
-		    int *flag)
+int i2o_row_delete_table(struct i2o_controller *iop, int tid,
+		    int group, int keycount, void *keys, int keyslen)
 {
 	u16 *opblk; 
 	u8  resblk[32]; /* min 8 bytes for header */
@@ -1794,8 +2257,8 @@
 	opblk[4] = keycount;
 	memcpy(opblk+5, keys, keyslen);
 
-        size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, 
-			opblk, 10+keyslen, resblk, sizeof(resblk), flag);
+	size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid,
+				opblk, 10+keyslen, resblk, sizeof(resblk));
 
 	kfree(opblk);
 	return size;
@@ -2134,9 +2597,10 @@
 #ifdef DRIVERDEBUG
 	int i;
 
-	printk(KERN_INFO "Dumping I2O message @ %p\n", msg);
+	printk(KERN_INFO "Dumping I2O message size %d @ %p\n", 
+		msg[0]>>16&0xffff, msg);
 	for(i = 0; i < ((msg[0]>>16)&0xffff); i++)
-		printk(KERN_INFO "\tmsg[%d] = %#10x\n", i, msg[i]);
+		printk(KERN_INFO "  msg[%d] = %0#10x\n", i, msg[i]);
 #endif
 }
 
@@ -2181,27 +2645,35 @@
 
 int init_module(void)
 {
+	printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n");
 	if (i2o_install_handler(&i2o_core_handler) < 0)
 	{
-		printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
+		printk(KERN_ERR 
+			"i2o_core: Unable to install core handler.\nI2O stack not loaded!");
 		return 0;
 	}
 
 	core_context = i2o_core_handler.context;
 
 	/*
-	 * Attach core to I2O PCI subsystem
+	 * Attach core to I2O PCI transport (and others as they are developed)
 	 */
 #ifdef CONFIG_I2O_PCI_MODULE
 	if(i2o_pci_core_attach(&i2o_core_functions) < 0)
 		printk(KERN_INFO "No PCI I2O controllers found\n");
 #endif
 
+	if(i2o_num_controllers)
+		i2o_sys_init();
+
 	return 0;
 }
 
 void cleanup_module(void)
 {
+	if(i2o_num_controllers)
+		i2o_sys_shutdown();
+
 #ifdef CONFIG_I2O_PCI_MODULE
 	i2o_pci_core_detach();
 #endif
@@ -2220,16 +2692,23 @@
 
 int __init i2o_init(void)
 {
-        if (i2o_install_handler(&i2o_core_handler) < 0)
-        {
-                printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
-                return 0;
-        }
+	printk(KERN_INFO "Loading I2O Core - (c) Copyright 1999 Red Hat Software\n");
+	if (i2o_install_handler(&i2o_core_handler) < 0)
+	{
+		printk(KERN_ERR 
+			"i2o_core: Unable to install core handler.\nI2O stack not loaded!");
+		return 0;
+	}
+
+	core_context = i2o_core_handler.context;
 
-        core_context = i2o_core_handler.context;
 #ifdef CONFIG_I2O_PCI
 	i2o_pci_init();
 #endif
+
+	if(i2o_num_controllers)
+		i2o_init();
+
 	i2o_config_init();
 #ifdef CONFIG_I2O_BLOCK
 	i2o_block_init();
diff -u --recursive --new-file v2.3.23/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c
--- v2.3.23/linux/drivers/i2o/i2o_lan.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/i2o_lan.c	Mon Oct 25 20:49:42 1999
@@ -302,7 +302,7 @@
 			     : count - total;
 
 		msg[0] = I2O_MESSAGE_SIZE(4 + 3 *  bucket_count) | SGL_OFFSET_4;
-		msg[1] = LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->id;
+		msg[1] = LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
 		msg[2] = priv->unit << 16 | lan_context; // InitiatorContext	
 		msg[3] = bucket_count;			 // BucketCount
 
@@ -343,12 +343,12 @@
 	u32 msg[5];
 
 	msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
-	msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->id;
+	msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
 	msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
 	msg[3] = 0; 				 // TransactionContext
 	msg[4] = 1 << 16; 			 // return posted buckets
 
-	if (i2o_post_this(iop, i2o_dev->id, msg, sizeof(msg)) < 0)
+	if (i2o_post_this(iop, msg, sizeof(msg)) < 0)
 		return -ETIMEDOUT;		
 
 	return 0; 
@@ -368,12 +368,12 @@
 
 	dprintk( "%s: LAN SUSPEND MESSAGE\n", dev->name );
 	msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
-	msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->id;
+	msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
 	msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
 	msg[3] = 0; 				 // TransactionContext
 	msg[4] = 1 << 16; 			 // return posted buckets
 
-	if (i2o_post_this(iop, i2o_dev->id, msg, sizeof(msg)) < 0)
+	if (i2o_post_this(iop, msg, sizeof(msg))< 0)
 		return -ETIMEDOUT;
 
 	return 0;
@@ -400,8 +400,7 @@
 	// enable batch mode, toggle automatically
 	val = 0x00000000;
 //	val = 0x00000001; // turn off batch mode
-	if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0003, 0,
-			&val, 4, &priv->reply_flag) <0)
+	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, 4) < 0)
 		printk(KERN_WARNING "Unable to enter I2O LAN batch mode.\n");
 	else
 		dprintk(KERN_INFO "%s: I2O LAN batch mode enabled.\n",dev->name);
@@ -414,8 +413,7 @@
 	/* set LAN_OPERATION attributes */
 
 	val = dev->mtu + dev->hard_header_len; // PacketOrphanLimit
-	if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0004, 2,
-		&val, 4, &priv->reply_flag) < 0)
+	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0004, 2, &val, 4))
 		printk(KERN_WARNING "i2o_lan: Unable to set PacketOrphanLimit.\n");
 	else
 		dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d\n",
@@ -438,7 +436,7 @@
 		printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name);
 		return -EAGAIN;
 	}
-	dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->id);
+	dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->lct_data->tid);
 
 	i2o_lan_reset(dev);
 	
@@ -467,7 +465,7 @@
 
 	if(i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY))
 		printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device "
-		       "(tid=%d)\n", dev->name, i2o_dev->id);
+		       "(tid=%d)\n", dev->name, i2o_dev->lct_data->tid);
 
 	MOD_DEC_USE_COUNT;
 
@@ -521,7 +519,7 @@
 	msg = bus_to_virt(iop->mem_offset + m);
 	
 	msg[0] = SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4;
-	msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->id;	
+	msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;	
 	msg[2] = priv->unit << 16 | lan_context; // IntiatorContext
 	msg[3] = 1 << 4; 			 // TransmitControlWord
 	
@@ -554,8 +552,8 @@
 	u64 val64[16];
 	u64 supported_group[4] = { 0, 0, 0, 0 };
 
-        if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0100, -1, 
-        		 val64, sizeof(val64), &priv->reply_flag) < 0)
+        if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, 
+        		 val64, sizeof(val64)) < 0)
         	printk("%s: Unable to query LAN_HISTORICAL_STATS.\n",dev->name);
 	else {
         	dprintk("%s: LAN_HISTORICAL_STATS queried.\n",dev->name);
@@ -568,13 +566,13 @@
 		priv->stats.rx_dropped = val64[6];
 	}
 
-        if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0180, -1, 
-        		&supported_group, sizeof(supported_group), &priv->reply_flag) < 0)
+        if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0180, -1, 
+        		&supported_group, sizeof(supported_group)) < 0)
         	printk("%s: Unable to query LAN_SUPPORTED_OPTIONAL_HISTORICAL_STATS.\n",dev->name);
 
 	if (supported_group[2]) {
-        	if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0183, -1, 
-        	 	val64, sizeof(val64), &priv->reply_flag) < 0)
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0183, -1, 
+        	 	val64, sizeof(val64) ) < 0)
         		printk("%s: Unable to query LAN_OPTIONAL_RX_HISTORICAL_STATS.\n",dev->name);
 		else {
         		dprintk("%s: LAN_OPTIONAL_RX_HISTORICAL_STATS queried.\n",dev->name);
@@ -584,12 +582,12 @@
 		}
 	}
 
-	if (i2o_dev->subclass == I2O_LAN_ETHERNET)
+	if (i2o_dev->lct_data->sub_class == I2O_LAN_ETHERNET)
 	{
 		u64 supported_stats = 0;		
 
-        	if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0200, -1, 
-        			 val64, sizeof(val64), &priv->reply_flag) < 0)
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0200, -1, 
+        			 val64, sizeof(val64)) < 0)
         		printk("%s: Unable to query LAN_802_3_HISTORICAL_STATS.\n",dev->name);
 		else {
         		dprintk("%s: LAN_802_3_HISTORICAL_STATS queried.\n",dev->name);
@@ -598,13 +596,13 @@
 			priv->stats.tx_carrier_errors  = val64[6];
 		}
 
-        	if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0280, -1, 
-        			 &supported_stats, 8, &priv->reply_flag) < 0)
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0280, -1, 
+        			 &supported_stats, 8) < 0)
         		printk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS\n", dev->name);
 
         	if (supported_stats != 0) {
-        		if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0281, -1, 
-        				 val64, sizeof(val64), &priv->reply_flag) < 0)
+        		if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0281, -1, 
+        				 val64, sizeof(val64)) < 0)
         			printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name);
 			else {
         			dprintk("%s: LAN_OPTIONAL_802_3_HISTORICAL_STATS queried.\n",dev->name);
@@ -618,10 +616,10 @@
 	}
 
 #ifdef CONFIG_TR
-	if (i2o_dev->subclass == I2O_LAN_TR)
+	if (i2o_dev->lct_data->sub_class == I2O_LAN_TR)
 	{
-        	if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0300, -1, 
-        			 val64, sizeof(val64), &priv->reply_flag) < 0)
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0300, -1, 
+        			 val64, sizeof(val64)) < 0)
         		printk("%s: Unable to query LAN_802_5_HISTORICAL_STATS.\n",dev->name);
 		else {
 			struct tr_statistics *stats = 
@@ -644,10 +642,10 @@
 #endif
 
 #ifdef CONFIG_FDDI
-	if (i2o_dev->subclass == I2O_LAN_FDDI)
+	if (i2o_dev->lct_data->sub_class == I2O_LAN_FDDI)
 	{
-        	if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0400, -1, 
-        			 val64, sizeof(val64), &priv->reply_flag) < 0)
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0400, -1, 
+        			 val64, sizeof(val64)) < 0)
         		printk("%s: Unable to query LAN_FDDI_HISTORICAL_STATS.\n",dev->name);
 		else {
 //        		dprintk("%s: LAN_FDDI_HISTORICAL_STATS queried.\n",dev->name);
@@ -691,8 +689,8 @@
  * *because its trying to sleep in an irq - this must be async - Alan
  */
 
-	if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, -1,
-			     &work32, sizeof(work32), &priv->reply_flag) < 0 ) 
+	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0001, -1,
+			     &work32, sizeof(work32)) < 0) 
 	{
 		printk(KERN_WARNING "i2o_lan: Unable to query "
 			" LAN_MAC_ADDRESS table.\n");	
@@ -734,12 +732,11 @@
 			mclist = mclist->next;
 		} 
 
-		if (i2o_clear_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002,
-				&priv->reply_flag) < 0 ) 
+		if (i2o_clear_table(iop, i2o_dev->lct_data->tid, 0x0002) < 0)
 			dprintk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
 
-		if (i2o_row_add_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002, -1,
-			work32, dev->mc_count*8, &priv->reply_flag) < 0)	
+		if (i2o_row_add_table(iop, i2o_dev->lct_data->tid, 0x0002, -1,
+			work32, dev->mc_count*8) < 0)	
 			dprintk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
 	} 
 	
@@ -748,8 +745,8 @@
 		dprintk(KERN_INFO "i2o_lan: Enabling unicast mode...\n");
         }
 
-	if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, 3,
-			&filter_mask, 4, &priv->reply_flag) <0)
+	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0001, 3,
+			&filter_mask, 4) < 0)
 		printk(KERN_WARNING "i2o_lan: Unable to set MAC FilterMask.\n");
 
 	return;
@@ -764,10 +761,10 @@
 	unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
 	void (*unregister_dev)(struct net_device *dev);
 
-	switch (i2o_dev->subclass)
+	switch (i2o_dev->lct_data->sub_class)
 	{
 	case I2O_LAN_ETHERNET:
-        	dev = init_etherdev(NULL, sizeof(struct i2o_lan_local));
+		dev = init_etherdev(NULL, sizeof(struct i2o_lan_local));
 		if (dev == NULL)
 			return NULL;
 		type_trans = eth_type_trans;
@@ -827,7 +824,7 @@
 	case I2O_LAN_UNKNOWN:
 	default:
 		printk(KERN_ERR "i2o_lan: LAN type 0x%08X not supported\n",
-		       i2o_dev->subclass);
+		       i2o_dev->lct_data->sub_class);
 		return NULL;
 	}
 
@@ -840,9 +837,8 @@
 	i2o_landevs[unit] = dev;
 	priv->unit = unit;
 
-	if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id, 
-			priv->unit << 16 | lan_context,
-			0x0001, 0, &hw_addr, 8, &priv->reply_flag) < 0)
+	if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
+			0x0001, 0, &hw_addr, 8) < 0)
 	{
      	printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name);
 		unit--;
@@ -858,9 +854,8 @@
 	dev->addr_len = 6;
 	memcpy(dev->dev_addr, hw_addr, 6);
 
-   if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id,
-         priv->unit << 16 | lan_context,
-         0x0007, 2, &max_tx, 4, &priv->reply_flag) < 0)
+   if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
+         0x0007, 2, &max_tx, 4) < 0)
    {
       printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name);
       unit--;
@@ -912,7 +907,10 @@
 
 		for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next)
 		{
-			if (i2o_dev->class != I2O_CLASS_LAN) 
+			if (i2o_dev->lct_data->class_id != I2O_CLASS_LAN) 
+				continue;
+
+			if(i2o_dev->lct_data->user_tid != 0xFFF)
 				continue;
 
 			if (unit == MAX_LAN_CARDS)
@@ -931,7 +929,7 @@
 
 			printk(KERN_INFO "%s: I2O LAN device registered, tid = %d,"
 				" subclass = 0x%08X, unit = %d.\n",
-				dev->name, i2o_dev->id, i2o_dev->subclass,
+				dev->name, i2o_dev->lct_data->tid, i2o_dev->lct_data->sub_class,
 				((struct i2o_lan_local *)dev->priv)->unit);
 		}
 
@@ -955,7 +953,7 @@
 		struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 		struct i2o_device *i2o_dev = priv->i2o_dev;	
 
-		switch (i2o_dev->subclass)
+		switch (i2o_dev->lct_data->sub_class)
 		{
 		case I2O_LAN_ETHERNET:
 			unregister_netdev(dev);
@@ -975,7 +973,7 @@
 #endif
 		default:
 			printk(KERN_WARNING "i2o_lan: Spurious I2O LAN subclass 0x%08X.\n",
-			       i2o_dev->subclass);
+			       i2o_dev->lct_data->sub_class);
 		}
 
 		dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n", 
diff -u --recursive --new-file v2.3.23/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c
--- v2.3.23/linux/drivers/i2o/i2o_pci.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/i2o_pci.c	Mon Oct 25 20:49:42 1999
@@ -25,6 +25,10 @@
 #include <linux/malloc.h>
 #include <asm/io.h>
 
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif // CONFIG_MTRR
+
 #ifdef MODULE
 /*
  * Core function table
@@ -46,6 +50,11 @@
 	if(c->bus.pci.irq > 0)
 		free_irq(c->bus.pci.irq, c);
 	iounmap(((u8 *)c->post_port)-0x40);
+
+#ifdef CONFIG_MTRR
+	if(c->bus.pci.mtrr_reg > 0)
+		mtrr_del(c->bus.pci.mtrr_reg, 0, 0);
+#endif
 }
 
 /*
@@ -66,6 +75,19 @@
 }
 
 /*
+ * Bus specific enable/disable functions
+ */
+static void i2o_pci_enable(struct i2o_controller *c)
+{
+	I2O_IRQ_WRITE32(c, 0);
+}
+
+static void i2o_pci_disable(struct i2o_controller *c)
+{
+	I2O_IRQ_WRITE32(c, 0xFFFFFFFF);
+}
+
+/*
  *	Bus specific interrupt handler
  */
  
@@ -81,8 +103,9 @@
 
 /*
  *	Install a PCI (or in theory AGP) i2o controller
+ *
+ * TODO: Add support for polled controllers
  */
- 
 int __init i2o_pci_install(struct pci_dev *dev)
 {
 	struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller),
@@ -128,7 +151,7 @@
 		kfree(c);
 		return -EINVAL;
 	}
-	
+
 	c->bus.pci.irq = -1;
 
 	c->irq_mask = (volatile u32 *)(mem+0x34);
@@ -141,9 +164,19 @@
 	
 	c->bind = i2o_pci_bind;
 	c->unbind = i2o_pci_unbind;
+	c->bus_enable = i2o_pci_enable;
+	c->bus_disable = i2o_pci_disable;
 	
 	c->type = I2O_TYPE_PCI;
 
+	/* 
+	 * Enable Write Combining MTRR for IOP's memory region
+	 */
+#ifdef CONFIG_MTRR
+	c->bus.pci.mtrr_reg = 
+		mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1);
+#endif
+
 	I2O_IRQ_WRITE32(c,0xFFFFFFFF);
 
 #ifdef MODULE
@@ -180,6 +213,9 @@
 			return -EBUSY;
 		}
 	}
+
+	printk(KERN_INFO "Installed iop%d at IRQ%d\n", c->unit, dev->irq);
+	I2O_IRQ_WRITE32(c,0x0);
 	return 0;	
 }
 
@@ -211,102 +247,54 @@
 	return count?count:-ENODEV;
 }
 
-static void i2o_pci_unload(void)
+#ifdef I2O_HOTPLUG_SUPPORT
+/*
+ * Activate a newly found PCI I2O controller
+ * Not used now, but will be needed in future for
+ * hot plug PCI support
+ */
+static void i2o_pci_activate(i2o_controller * c)
 {
 	int i=0;
 	struct i2o_controller *c;
 	
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
+	if(c->type == I2O_TYPE_PCI)
 	{
+		I2O_IRQ_WRITE32(c,0);
 #ifdef MODULE
-		c=core->find(i);
+		if(core->activate(c))
 #else
-		c=i2o_find_controller(i);
+		if(i2o_activate_controller(c))
 #endif /* MODULE */
-
-		if(c==NULL)
-			continue;		
-
-#ifdef MODULE
-		core->unlock(c);
-#else
-		i2o_unlock_controller(c);
-#endif /* MODULE */
-
-		if(c->type == I2O_TYPE_PCI)
+		{
+			printk("I2O: Failed to initialize iop%d\n", c->unit);
 #ifdef MODULE
+			core->unlock(c);
 			core->delete(c);
 #else
+			i2o_unlock_controller(c);
 			i2o_delete_controller(c);
-#endif /* MODULE */
-	}
-}
-
-static void i2o_pci_activate(void)
-{
-	int i=0;
-	struct i2o_controller *c;
-	
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-#ifdef MODULE
-		c=core->find(i);
-#else
-		c=i2o_find_controller(i);
-#endif /* MODULE */
-
-		if(c==NULL)
-			continue;		
-			
-		if(c->type == I2O_TYPE_PCI)
-		{
-#ifdef MODULE
-			if(core->activate(c))
-#else
-			if(i2o_activate_controller(c))
-#endif /* MODULE */
-			{
-				printk("I2O: Failed to initialize iop%d\n", c->unit);
-#ifdef MODULE
-				core->unlock(c);
-				core->delete(c);
-#else
-				i2o_unlock_controller(c);
-				i2o_delete_controller(c);
 #endif
-				continue;
-			}
-			I2O_IRQ_WRITE32(c,0);
+			continue;
 		}
-#ifdef MODULE
-		core->unlock(c);
-#else
-		i2o_unlock_controller(c);
-#endif
 	}
 }
-
+#endif // I2O_HOTPLUG_SUPPORT
 
 #ifdef MODULE
 
 int i2o_pci_core_attach(struct i2o_core_func_table *table)
 {
-	int i;
-
 	MOD_INC_USE_COUNT;
 
 	core = table;
- 
-	if((i = i2o_pci_scan())<0)
- 		return -ENODEV;
- 	i2o_pci_activate();
 
-	return i;
+	return i2o_pci_scan();
 }
 
 void i2o_pci_core_detach(void)
 {
-	i2o_pci_unload();
+	core = NULL;
 
 	MOD_DEC_USE_COUNT;
 }
@@ -314,16 +302,8 @@
 int init_module(void)
 {
 	printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n");
-
-/*
- * Let the core call the scan function for module dependency
- * reasons.  See include/linux/i2o.h for the reason why this
- * is done.
- *
- *	if(i2o_pci_scan()<0)
- *		return -ENODEV;
- *	i2o_pci_activate();
- */
+	
+	core = NULL;
 
  	return 0;
  
@@ -343,9 +323,6 @@
 void __init i2o_pci_init(void)
 {
 	printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n");
-	if(i2o_pci_scan()>=0)
-	{
-		i2o_pci_activate();
-	}
+	i2o_pci_scan();
 }
 #endif
diff -u --recursive --new-file v2.3.23/linux/drivers/i2o/i2o_proc.c linux/drivers/i2o/i2o_proc.c
--- v2.3.23/linux/drivers/i2o/i2o_proc.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/i2o_proc.c	Mon Oct 25 20:49:42 1999
@@ -1,7 +1,7 @@
 /*
  *   procfs handler for Linux I2O subsystem
  *
- *   Copyright (c) 1999 Deepak Saxena
+ *   (c) Copyright 1999 Deepak Saxena
  *   
  *   Originally written by Deepak Saxena(deepak@plexity.net)
  *
@@ -790,16 +790,15 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(c, ADAPTER_TID, proc_context, 
+	token = i2o_query_scalar(c, ADAPTER_TID,
 					0,		// ParamGroup 0x0000h
 					-1,		// all fields
 					&work32,
-					sizeof(work32),
-					&i2o_proc_token);
+					sizeof(work32));
 
 	if(token < 0)
 	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+		len += sprintf(buf, "Error waiting for reply from IOP\n");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -875,10 +874,10 @@
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, proc_context,
+				c, ADAPTER_TID, 
 				0x0003, -1,
 				NULL, 0,
-				&result, sizeof(result), &i2o_proc_token);
+				&result, sizeof(result));
 
 	if (token<0)
 		switch (token)
@@ -941,16 +940,13 @@
 {
 	struct i2o_controller *c = (struct i2o_controller*)data;
 	u32 work32[8];
-	int token;
 
 	spin_lock(&i2o_proc_lock);
 
 	len = 0;
 
-	token = i2o_query_scalar(c, ADAPTER_TID, proc_context, 0x0004, -1, 
-				 &work32, sizeof(work32), &i2o_proc_token);
-
-	if (token<0)
+	if(i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32,
+		sizeof(work32)) < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
 		spin_unlock(&i2o_proc_lock);
@@ -1009,10 +1005,10 @@
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, proc_context,
+				c, ADAPTER_TID,
 				0x0005, -1,
 				NULL, 0,
-				&result, sizeof(result), &i2o_proc_token);
+				&result, sizeof(result));
 
 	if (token<0)
 		switch (token)
@@ -1094,10 +1090,10 @@
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, proc_context,
+				c, ADAPTER_TID,
 				0xF000, -1,
 				NULL, 0,
-				&work16, sizeof(work16), &i2o_proc_token);
+				&work16, sizeof(work16));
 
 	if (token<0)
 		switch (token)
@@ -1181,10 +1177,10 @@
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, proc_context,
+				c, ADAPTER_TID,
 				0xF000, -1,
 				NULL, 0,
-				&work16, sizeof(work16), &i2o_proc_token);
+				&work16, sizeof(work16));
 
 	if (token<0)
 		switch (token)
@@ -1243,12 +1239,11 @@
 	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 					0xF100,		// ParamGroup F100h (Device Identity)
 					-1,		// all fields
 					&work32,
-					sizeof(work32),
-					&i2o_proc_token);
+					sizeof(work32));
 
 	if(token < 0)
 	{
@@ -1308,12 +1303,11 @@
 	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
+	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
 					0xF101,		// ParamGroup F101h (DDM Identity)
 					-1,		// all fields
 					&work32,
-					sizeof(work32),
-					&i2o_proc_token);
+					sizeof(work32));
 
 	if(token < 0)
 	{
@@ -1352,12 +1346,11 @@
 	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 					0xF102,		// ParamGroup F102h (User Information)
 					-1,		// all fields
 					&work32,
-					sizeof(work32),
-					&i2o_proc_token);
+					sizeof(work32));
 
 	if(token < 0)
 	{
@@ -1390,12 +1383,11 @@
 	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
+	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
 				 0xF103,	// ParamGroup F103h (SGL Operating Limits)
 				 -1,		// all fields
 				 &work32,
-				 sizeof(work32),
-				 &i2o_proc_token);
+				 sizeof(work32));
 
 	if(token < 0)
 	{
@@ -1760,8 +1752,8 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0000, -1, &work32, 56*4, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0000, -1, &work32, 56*4);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -1883,8 +1875,8 @@
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0001, -1, &work32, 48*4, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0001, -1, &work32, 48*4);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -1973,9 +1965,8 @@
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-			d->controller, d->id, proc_context, 0x0002, -1, 
-			NULL, 0, &field32, sizeof(field32),
-			&i2o_proc_token);
+			d->controller, d->lct_data->tid, 0x0002, -1, 
+			NULL, 0, &field32, sizeof(field32));
 
 	if (token<0)
 		switch (token) {
@@ -2026,8 +2017,8 @@
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0003, -1, &work32, 9*4, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0003, -1, &work32, 9*4);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2086,8 +2077,8 @@
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0004, -1, &work32, 20, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0004, -1, &work32, 20);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2151,8 +2142,8 @@
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0005, -1, &work32, 36, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0005, -1, &work32, 36);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2225,9 +2216,8 @@
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-			d->controller, d->id, proc_context, 0x0006, -1, 
-			NULL, 0, &field32, sizeof(field32),
-			&i2o_proc_token);
+			d->controller, d->lct_data->tid, 0x0006, -1, 
+			NULL, 0, &field32, sizeof(field32));
 
 	if (token<0)
 		switch (token) {
@@ -2279,8 +2269,8 @@
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0007, -1, &work32, 8*4, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0007, -1, &work32, 8*4);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2341,8 +2331,8 @@
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0008, -1, &work32, 8*4, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0008, -1, &work32, 8*4);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2376,8 +2366,8 @@
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0100, -1, &work64, 9*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0100, -1, &work64, 9*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2421,8 +2411,8 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0180, -1, &work64, 4*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0180, -1, &work64, 4*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2461,8 +2451,8 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0182, -1, &work64, 9*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
+				 0x0182, -1, &work64, 9*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2506,8 +2496,8 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0183, -1, &work64, 11*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0183, -1, &work64, 11*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2555,8 +2545,8 @@
 	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0200, -1, &work64, 8*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
+				 0x0200, -1, &work64, 8*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2597,8 +2587,8 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0280, -1, &work64, 8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
+				 0x0280, -1, &work64, 8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2625,8 +2615,8 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0281, -1, &work64, 3*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0281, -1, &work64, 3*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2677,8 +2667,8 @@
 	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0300, -1, &work64, 13*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
+				 0x0300, -1, &work64, 13*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2771,8 +2761,8 @@
 	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->id, proc_context, 
-				 0x0400, -1, &work64, 11*8, &i2o_proc_token);
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0400, -1, &work64, 11*8);
 	if(token < 0)
 	{
 		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2853,7 +2843,7 @@
 	
 	for(dev = pctrl->devices; dev; dev = dev->next)
 	{
-		sprintf(buff, "%0#5x", dev->id);
+		sprintf(buff, "%0#5x", dev->lct_data->tid);
 
 		dir1 = create_proc_entry(buff, S_IFDIR, dir);
 		dev->proc_entry = dir1;
@@ -2863,7 +2853,7 @@
 		
 		i2o_proc_create_entries(dev, generic_dev_entries, dir1);
 
-		switch(dev->class)
+		switch(dev->lct_data->class_id)
 		{
 		case I2O_CLASS_SCSI_PERIPHERAL:
 		case I2O_CLASS_RANDOM_BLOCK_STORAGE:
@@ -2871,7 +2861,7 @@
 			break;
 		case I2O_CLASS_LAN:
 			i2o_proc_create_entries(dev, lan_entries, dir1);
-			switch(dev->subclass)
+			switch(dev->lct_data->sub_class)
 			{
 			case I2O_LAN_ETHERNET:
 				i2o_proc_create_entries(dev, lan_eth_entries,
@@ -2909,14 +2899,14 @@
 	for(dev=pctrl->devices; dev; dev=dev->next)
 	{
 		de=dev->proc_entry;
-		sprintf(dev_id, "%0#5x", dev->id);
+		sprintf(dev_id, "%0#5x", dev->lct_data->tid);
 
 		/* Would it be safe to remove _files_ even if they are in use? */
 		if((de) && (!de->count))
 		{
 			i2o_proc_remove_entries(generic_dev_entries, de);
 
-			switch(dev->class)
+			switch(dev->lct_data->class_id)
 			{
 			case I2O_CLASS_SCSI_PERIPHERAL:
 			case I2O_CLASS_RANDOM_BLOCK_STORAGE:
@@ -2924,7 +2914,7 @@
 				break;
 			case I2O_CLASS_LAN:
 				i2o_proc_remove_entries(lan_entries, de);
-				switch(dev->subclass)
+				switch(dev->lct_data->sub_class)
 				{
 				case I2O_LAN_ETHERNET:
 					i2o_proc_remove_entries(lan_eth_entries, de);
diff -u --recursive --new-file v2.3.23/linux/drivers/i2o/i2o_scsi.c linux/drivers/i2o/i2o_scsi.c
--- v2.3.23/linux/drivers/i2o/i2o_scsi.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/i2o/i2o_scsi.c	Mon Oct 25 20:49:42 1999
@@ -301,14 +301,12 @@
 {
 	u8 reply[8];
 	
-	if(i2o_query_scalar(c, d->id, scsi_context|0x40000000, 
-		0, 3, reply, 4, &lun_done)<0)
+	if(i2o_query_scalar(c, d->lct_data->tid, 0, 3, reply, 4))
 		return -1;
 		
 	*target=reply[0];
 	
-	if(i2o_query_scalar(c, d->id, scsi_context|0x40000000, 
-		0, 4, reply, 8, &lun_done)<0)
+	if(i2o_query_scalar(c, d->lct_data->tid, 0, 4, reply, 8))
 		return -1;
 
 	*lun=reply[1];
@@ -325,7 +323,7 @@
 	int target;
 	
 	h->controller=c;
-	h->bus_task=d->id;
+	h->bus_task=d->lct_data->tid;
 	
 	for(target=0;target<16;target++)
 		for(lun=0;lun<8;lun++)
@@ -334,34 +332,33 @@
 	for(unit=c->devices;unit!=NULL;unit=unit->next)
 	{
 		dprintk(("Class %03X, parent %d, want %d.\n",
-			unit->class, unit->parent, d->id));
+			unit->lct_data->class_id, unit->lct_data->parent, d->lct_data->tid));
 			
 		/* Only look at scsi and fc devices */
-		if (    (unit->class != I2O_CLASS_SCSI_PERIPHERAL)
-		     && (unit->class != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL)
+		if (    (unit->lct_data->class_id != I2O_CLASS_SCSI_PERIPHERAL)
+		     && (unit->lct_data->class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL)
 		   )
 			continue;
 
 		/* On our bus ? */
 		dprintk(("Found a disk.\n"));
-		if (    (unit->parent == d->id)
-		     || (unit->parent == d->parent)
+		if ((unit->lct_data->parent_tid == d->lct_data->tid)
+		     || (unit->lct_data->parent_tid == d->lct_data->parent_tid)
 		   )
 		{
 			u16 limit;
 			dprintk(("Its ours.\n"));
 			if(i2o_find_lun(c, unit, &target, &lun)==-1)
 			{
-				printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", d->id);
+				printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", d->lct_data->tid);
 				continue;
 			}
 			dprintk(("Found disk %d %d.\n", target, lun));
-			h->task[target][lun]=unit->id;
+			h->task[target][lun]=unit->lct_data->tid;
 			h->tagclock[target][lun]=jiffies;
 
 			/* Get the max fragments/request */
-			i2o_query_scalar(c, d->id, scsi_context|0x40000000,
-					0xF103, 3, &limit, 2, &lun_done);
+			i2o_query_scalar(c, d->lct_data->tid, 0xF103, 3, &limit, 2);
 			
 			/* sanity */
 			if ( limit == 0 )
@@ -435,8 +432,8 @@
 			/*
 			 *	bus_adapter, SCSI (obsolete), or FibreChannel busses only
 			 */
-			if(    (d->class!=I2O_CLASS_BUS_ADAPTER_PORT)	// bus_adapter
-			    && (d->class!=I2O_CLASS_FIBRE_CHANNEL_PORT)	// FC_PORT
+			if(    (d->lct_data->class_id!=I2O_CLASS_BUS_ADAPTER_PORT)	// bus_adapter
+			    && (d->lct_data->class_id!=I2O_CLASS_FIBRE_CHANNEL_PORT)	// FC_PORT
 			  )
 				continue;
 		
diff -u --recursive --new-file v2.3.23/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.3.23/linux/drivers/macintosh/macserial.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/macintosh/macserial.c	Wed Oct 27 15:33:36 1999
@@ -2584,7 +2584,9 @@
  * ------------------------------------------------------------
  */
 #ifdef CONFIG_SERIAL_CONSOLE
-
+#ifdef CONFIG_SERIAL
+#error Cannot build serial console with macserial and serial drivers
+#endif
 
 /*
  *	Print a string to the serial port trying not to disturb
@@ -2843,7 +2845,7 @@
 /*
  *	Register console.
  */
-long __init serial_console_init(long kmem_start, long kmem_end)
+void __init serial_console_init(void)
 {
 	register_console(&sercons);
 	return kmem_start;
diff -u --recursive --new-file v2.3.23/linux/drivers/misc/acpi.c linux/drivers/misc/acpi.c
--- v2.3.23/linux/drivers/misc/acpi.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/misc/acpi.c	Wed Oct 27 16:06:52 1999
@@ -29,8 +29,13 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <linux/sysctl.h>
+#include <linux/delay.h>
 #include <linux/acpi.h>
 
 /*
@@ -49,7 +54,26 @@
 #define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL
 #endif
 
+static int acpi_do_ulong(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len);
+static int acpi_do_event_reg(ctl_table *ctl,
+			     int write,
+			     struct file *file,
+			     void *buffer,
+			     size_t *len);
+static int acpi_do_event(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len);
+
+static struct ctl_table_header *acpi_sysctl = NULL;
+
 static struct acpi_facp *acpi_facp = NULL;
+static int acpi_fake_facp = 0;
 static unsigned long acpi_facp_addr = 0;
 static unsigned long acpi_dsdt_addr = 0;
 
@@ -57,15 +81,64 @@
 static volatile u32 acpi_pm1_status = 0;
 static volatile u32 acpi_gpe_status = 0;
 static volatile u32 acpi_gpe_level = 0;
-static DECLARE_WAIT_QUEUE_HEAD(acpi_wait_event);
+static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
 
 /* Make it impossible to enter L2/L3 until after we've initialized */
 static unsigned long acpi_p_lvl2_lat = ~0UL;
 static unsigned long acpi_p_lvl3_lat = ~0UL;
 
 /* Initialize to guaranteed harmless port read */
-static u16 acpi_p_lvl2 = 0x80;
-static u16 acpi_p_lvl3 = 0x80;
+static unsigned long acpi_p_lvl2 = 0x80;
+static unsigned long acpi_p_lvl3 = 0x80;
+
+static struct ctl_table acpi_table[] =
+{
+	{ACPI_FACP, "facp",
+	 &acpi_facp_addr, sizeof(acpi_facp_addr),
+	 0400, NULL, &acpi_do_ulong},
+
+	{ACPI_DSDT, "dsdt",
+	 &acpi_dsdt_addr, sizeof(acpi_dsdt_addr),
+	 0400, NULL, &acpi_do_ulong},
+
+	{ACPI_PM1_ENABLE, "pm1_enable",
+	 NULL, 0,
+	 0600, NULL, &acpi_do_event_reg},
+
+	{ACPI_GPE_ENABLE, "gpe_enable",
+	 NULL, 0,
+	 0600, NULL, &acpi_do_event_reg},
+
+	{ACPI_GPE_LEVEL, "gpe_level",
+	 NULL, 0,
+	 0600, NULL, &acpi_do_event_reg},
+
+	{ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
+
+	{ACPI_P_LVL2, "p_lvl2",
+	 &acpi_p_lvl2, sizeof(acpi_p_lvl2),
+	 0600, NULL, &acpi_do_ulong},
+
+	{ACPI_P_LVL3, "p_lvl3",
+	 &acpi_p_lvl3, sizeof(acpi_p_lvl3),
+	 0600, NULL, &acpi_do_ulong},
+
+	{ACPI_P_LVL2_LAT, "p_lvl2_lat",
+	 &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat),
+	 0600, NULL, &acpi_do_ulong},
+
+	{ACPI_P_LVL3_LAT, "p_lvl3_lat",
+	 &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat),
+	 0600, NULL, &acpi_do_ulong},
+
+	{0}
+};
+
+static struct ctl_table acpi_dir_table[] =
+{
+	{CTL_ACPI, "acpi", NULL, 0, 0500, acpi_table},
+	{0}
+};
 
 
 /*
@@ -73,7 +146,9 @@
  */
 static u32 acpi_read_pm1_control(struct acpi_facp *facp)
 {
-	u32 value = inw(facp->pm1a_cnt);
+	u32 value = 0;
+	if (facp->pm1a_cnt)
+		value = inw(facp->pm1a_cnt);
 	if (facp->pm1b_cnt)
 		value |= inw(facp->pm1b_cnt);
 	return value;
@@ -84,7 +159,9 @@
  */
 static u32 acpi_read_pm1_status(struct acpi_facp *facp)
 {
-	u32 value = inw(facp->pm1a_evt);
+	u32 value = 0;
+	if (facp->pm1a_evt)
+		value = inw(facp->pm1a_evt);
 	if (facp->pm1b_evt)
 		value |= inw(facp->pm1b_evt);
 	return value;
@@ -95,7 +172,8 @@
  */
 static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
 {
-	outw(value, facp->pm1a_evt);
+	if (facp->pm1a_evt)
+		outw(value, facp->pm1a_evt);
 	if (facp->pm1b_evt)
 		outw(value, facp->pm1b_evt);
 }
@@ -106,7 +184,9 @@
 static u32 acpi_read_pm1_enable(struct acpi_facp *facp)
 {
 	int offset = facp->pm1_evt_len >> 1;
-	u32 value = inw(facp->pm1a_evt + offset);
+	u32 value = 0;
+	if (facp->pm1a_evt)
+		value = inw(facp->pm1a_evt + offset);
 	if (facp->pm1b_evt)
 		value |= inw(facp->pm1b_evt + offset);
 	return value;
@@ -118,7 +198,8 @@
 static void acpi_write_pm1_enable(struct acpi_facp *facp, u32 value)
 {
 	int offset = facp->pm1_evt_len >> 1;
-	outw(value, facp->pm1a_evt + offset);
+	if (facp->pm1a_evt)
+		outw(value, facp->pm1a_evt + offset);
 	if (facp->pm1b_evt)
 		outw(value, facp->pm1b_evt + offset);
 }
@@ -136,9 +217,11 @@
 		for (i = size - 1; i >= 0; i--)
 			value = (value << 8) | inb(facp->gpe1 + i);
 	}
-	size = facp->gpe0_len >> 1;
-	for (i = size - 1; i >= 0; i--)
-		value = (value << 8) | inb(facp->gpe0 + i);
+	if (facp->gpe0) {
+		size = facp->gpe0_len >> 1;
+		for (i = size - 1; i >= 0; i--)
+			value = (value << 8) | inb(facp->gpe0 + i);
+	}
 	return value;
 }
 
@@ -149,10 +232,12 @@
 {
 	int i, size;
 
-	size = facp->gpe0_len >> 1;
-	for (i = 0; i < size; i++) {
-		outb(value & 0xff, facp->gpe0 + i);
-		value >>= 8;
+	if (facp->gpe0) {
+		size = facp->gpe0_len >> 1;
+		for (i = 0; i < size; i++) {
+			outb(value & 0xff, facp->gpe0 + i);
+			value >>= 8;
+		}
 	}
 	if (facp->gpe1) {
 		size = facp->gpe1_len >> 1;
@@ -178,9 +263,11 @@
 			value = (value << 8) | inb(facp->gpe1 + offset + i);
 		}
 	}
-	size = facp->gpe0_len >> 1;
-	for (i = size - 1; i >= 0; i--)
-		value = (value << 8) | inb(facp->gpe0 + offset + i);
+	if (facp->gpe0) {
+		size = facp->gpe0_len >> 1;
+		for (i = size - 1; i >= 0; i--)
+			value = (value << 8) | inb(facp->gpe0 + offset + i);
+	}
 	return value;
 }
 
@@ -192,9 +279,11 @@
 	int i, offset;
 
 	offset = facp->gpe0_len >> 1;
-	for (i = 0; i < offset; i++) {
-		outb(value & 0xff, facp->gpe0 + offset + i);
-		value >>= 8;
+	if (facp->gpe0) {
+		for (i = 0; i < offset; i++) {
+			outb(value & 0xff, facp->gpe0 + offset + i);
+			value >>= 8;
+		}
 	}
 	if (facp->gpe1) {
 		offset = facp->gpe1_len >> 1;
@@ -238,9 +327,9 @@
 }
 
 /*
- * Locate and map ACPI tables (FACP, DSDT, ...)
+ * Locate and map ACPI tables
  */
-static int __init acpi_map_tables(void)
+static int __init acpi_find_tables(void)
 {
 	struct acpi_rsdp *rsdp;
 	struct acpi_table *rsdt;
@@ -251,8 +340,8 @@
 	// search BIOS memory for RSDP
 	for (i = ACPI_BIOS_ROM_BASE; i < ACPI_BIOS_ROM_END; i += 16) {
 		rsdp = (struct acpi_rsdp *) phys_to_virt(i);
-		if (rsdp->signature[0] == ACPI_RSDP1_SIG &&
-		    rsdp->signature[1] == ACPI_RSDP2_SIG) {
+		if (rsdp->signature[0] == ACPI_RSDP1_SIG
+		    && rsdp->signature[1] == ACPI_RSDP2_SIG) {
 			char oem[7];
 			int j;
 
@@ -270,14 +359,13 @@
 			break;
 		}
 	}
-	if (i >= ACPI_BIOS_ROM_END) {
-		printk(KERN_ERR "ACPI: no RSDP found\n");
+	if (i >= ACPI_BIOS_ROM_END)
 		return -ENODEV;
-	}
+
 	// fetch RSDT from RSDP
 	rsdt = acpi_map_table(rsdp->rsdt);
 	if (!rsdt || rsdt->signature != ACPI_RSDT_SIG) {
-		printk(KERN_ERR "ACPI: no RSDT found\n");
+		printk(KERN_ERR "ACPI: missing RSDT\n");
 		acpi_unmap_table(rsdt);
 		return -ENODEV;
 	}
@@ -288,11 +376,11 @@
 	while (rsdt_entry_count) {
 		struct acpi_table *dt = acpi_map_table(*rsdt_entry);
 		if (dt && dt->signature == ACPI_FACP_SIG) {
-			acpi_facp = (struct acpi_facp *) dt;
+			acpi_facp = (struct acpi_facp*) dt;
 			acpi_facp_addr = *rsdt_entry;
 			acpi_dsdt_addr = acpi_facp->dsdt;
-			break;
-		} else {
+		}
+		else {
 			acpi_unmap_table(dt);
 		}
 		rsdt_entry++;
@@ -302,22 +390,89 @@
 	acpi_unmap_table(rsdt);
 
 	if (!acpi_facp) {
-		printk(KERN_ERR "ACPI: no FACP found\n");
+		printk(KERN_ERR "ACPI: missing FACP\n");
 		return -ENODEV;
 	}
 	return 0;
 }
 
 /*
- * Unmap ACPI tables (FACP, DSDT, ...)
+ * Unmap or destroy ACPI tables
  */
-static void acpi_unmap_tables(void)
+static void acpi_destroy_tables(void)
 {
-	acpi_idle = NULL;
+	if (!acpi_fake_facp)
+		acpi_unmap_table((struct acpi_table*) acpi_facp);
+	else
+		kfree(acpi_facp);
+}
+
+/*
+ * Locate PIIX4 device and create a fake FACP
+ */
+static int __init acpi_find_piix4(void)
+{
+	struct pci_dev *dev;
+	u32 base;
+	u16 cmd;
+	u8 pmregmisc;
+
+	dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82371AB_3,
+			      NULL);
+	if (!dev)
+		return -ENODEV;
+	
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	if (!(cmd & PCI_COMMAND_IO))
+		return -ENODEV;
+	
+	pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc);
+	if (!(pmregmisc & ACPI_PIIX4_PMIOSE))
+		return -ENODEV;
+	
+	pci_read_config_dword(dev, 0x40, &base);
+	if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
+		return -ENODEV;
+	
+	base &= PCI_BASE_ADDRESS_IO_MASK;
+	if (!base)
+		return -ENODEV;
+
+	printk(KERN_INFO "ACPI: found PIIX4 at 0x%04x\n", base);
+
+	acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL);
+	if (!acpi_facp)
+		return -ENOMEM;
+
+	acpi_fake_facp = 1;
+	memset(acpi_facp, 0, sizeof(struct acpi_facp));
+	acpi_facp->int_model = ACPI_PIIX4_INT_MODEL;
+	acpi_facp->sci_int = ACPI_PIIX4_SCI_INT;
+	acpi_facp->smi_cmd = ACPI_PIIX4_SMI_CMD;
+	acpi_facp->acpi_enable = ACPI_PIIX4_ACPI_ENABLE;
+	acpi_facp->acpi_disable = ACPI_PIIX4_ACPI_DISABLE;
+	acpi_facp->s4bios_req = ACPI_PIIX4_S4BIOS_REQ;
+	acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT;
+	acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT;
+	acpi_facp->pm2_cnt = ACPI_PIIX4_PM2_CNT;
+	acpi_facp->pm_tmr = base + ACPI_PIIX4_PM_TMR;
+	acpi_facp->gpe0 = base + ACPI_PIIX4_GPE0;
+	acpi_facp->pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN;
+	acpi_facp->pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN;
+	acpi_facp->pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN;
+	acpi_facp->pm_tm_len = ACPI_PIIX4_PM_TM_LEN;
+	acpi_facp->gpe0_len = ACPI_PIIX4_GPE0_LEN;
+	acpi_facp->p_lvl2_lat = ~0;
+	acpi_facp->p_lvl3_lat = ~0;
+
+	acpi_facp_addr = virt_to_phys(acpi_facp);
 	acpi_dsdt_addr = 0;
-	acpi_facp_addr = 0;
-	acpi_unmap_table((struct acpi_table *) acpi_facp);
-	acpi_facp = NULL;
+
+	acpi_p_lvl2 = base + ACPI_PIIX4_P_LVL2;
+	acpi_p_lvl3 = base + ACPI_PIIX4_P_LVL3;
+
+	return 0;
 }
 
 /*
@@ -355,25 +510,7 @@
 	acpi_pm1_status |= pm1_status;
 	acpi_gpe_status |= gpe_status;
 	spin_unlock_irqrestore(&acpi_event_lock, flags);
-	wake_up_interruptible(&acpi_wait_event);
-}
-
-/*
- * Handle open of /dev/acpi
- */
-static int acpi_open(struct inode *inode, struct file *file)
-{
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-/*
- * Handle close of /dev/acpi
- */
-static int acpi_release(struct inode *inode, struct file *file)
-{
-	MOD_DEC_USE_COUNT;
-	return 0;
+	wake_up_interruptible(&acpi_event_wait);
 }
 
 /*
@@ -389,7 +526,8 @@
  */
 static int acpi_enable(struct acpi_facp *facp)
 {
-	outb(facp->acpi_enable, facp->smi_cmd);
+	if (facp->smi_cmd)
+		outb(facp->acpi_enable, facp->smi_cmd);
 	return (acpi_is_enabled(facp) ? 0:-1);
 }
 
@@ -404,132 +542,29 @@
 		acpi_write_gpe_status(facp, acpi_read_gpe_status(facp));
 	acpi_write_pm1_enable(facp, 0);
 	acpi_write_pm1_status(facp, acpi_read_pm1_status(facp));
-	
-	outb(facp->acpi_disable, facp->smi_cmd);
+
+	if (facp->smi_cmd)
+		outb(facp->acpi_disable, facp->smi_cmd);
 	return (acpi_is_enabled(facp) ? -1:0);
 }
 
 /*
- * Handle command to /dev/acpi
+ * Idle loop
  */
-static int acpi_ioctl(struct inode *inode,
-		      struct file *file,
-		      unsigned cmd,
-		      unsigned long arg)
-{
-	int status = -EINVAL;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	switch (cmd) {
-	case ACPI_FIND_TABLES:
-		status = verify_area(VERIFY_WRITE,
-				     (void *) arg,
-				     sizeof(struct acpi_find_tables));
-		if (!status) {
-			struct acpi_find_tables *rqst
-				= (struct acpi_find_tables *) arg;
-			put_user(acpi_facp_addr, &rqst->facp);
-			put_user(acpi_dsdt_addr, &rqst->dsdt);
-			status = 0;
-		}
-		break;
-	case ACPI_ENABLE_EVENT:
-		status = verify_area(VERIFY_READ,
-				     (void *) arg,
-				     sizeof(struct acpi_enable_event));
-		if (!status) {
-			struct acpi_enable_event *rqst
-				= (struct acpi_enable_event *) arg;
-			u32 pm1_enable, gpe_enable, gpe_level;
-			u32 pm1_enabling, gpe_enabling;
-
-			get_user(pm1_enable, &rqst->pm1_enable);
-			get_user(gpe_enable, &rqst->gpe_enable);
-			get_user(gpe_level, &rqst->gpe_level);
-			gpe_level &= gpe_enable;
-			
-			// clear previously disabled events before enabling
-			pm1_enabling = (pm1_enable
-					& ~acpi_read_pm1_enable(acpi_facp));
-			acpi_write_pm1_status(acpi_facp, pm1_enabling);
-			gpe_enabling = (gpe_enable &
-					~acpi_read_gpe_enable(acpi_facp));
-			while (acpi_read_gpe_status(acpi_facp) & gpe_enabling)
-				acpi_write_gpe_status(acpi_facp, gpe_enabling);
-
-			status = 0;
-
-			if (pm1_enable || gpe_enable) {
-				// enable ACPI unless it is already
-				if (!acpi_is_enabled(acpi_facp)
-				    && acpi_enable(acpi_facp)) {
-					status = -EBUSY;
-				}
-			}
-			else {
-				// disable ACPI unless it is already
-				if (acpi_is_enabled(acpi_facp)
-				    && acpi_disable(acpi_facp)) {
-					status = -EBUSY;
-				}
-			}
-
-			if (!status)
-			{
-				acpi_write_pm1_enable(acpi_facp, pm1_enable);
-				acpi_write_gpe_enable(acpi_facp, gpe_enable);
-				acpi_gpe_level = gpe_level;
-			}
-		}
-		break;
-	case ACPI_WAIT_EVENT:
-		status = verify_area(VERIFY_WRITE,
-				     (void *) arg,
-				     sizeof(struct acpi_wait_event));
-		if (!status) {
-			struct acpi_wait_event *rqst
-				= (struct acpi_wait_event *) arg;
-			u32 pm1_status = 0;
-			u32 gpe_status = 0;
-			
-			for (;;) {
-				unsigned long flags;
-				
-				// we need an atomic exchange here
-				spin_lock_irqsave(&acpi_event_lock, flags);
-				pm1_status = acpi_pm1_status;
-				acpi_pm1_status = 0;
-				gpe_status = acpi_gpe_status;
-				acpi_gpe_status = 0;
-				spin_unlock_irqrestore(&acpi_event_lock,
-						       flags);
-
-				if (pm1_status || gpe_status)
-					break;
-
-				// wait for an event to arrive
-				interruptible_sleep_on(&acpi_wait_event);
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-			}
-
-			put_user(pm1_status, &rqst->pm1_status);
-			put_user(gpe_status, &rqst->gpe_status);
-			status = 0;
-		}
-		break;
-	}
-	return status;
-}
-
 static void acpi_idle_handler(void)
 {
-	unsigned long time;
 	static int sleep_level = 1;
+	u32 timer, pm2_cnt;
+	unsigned long time;
+
+	// get current time (fallback to CPU cycles if no PM timer)
+	timer = acpi_facp->pm_tmr;
+	if (timer)
+		time = inl(timer);
+	else
+		time = get_cycles();
 
-	time = inl(acpi_facp->pm_tmr);
+	// sleep
 	switch (sleep_level) {
 	case 1:
 		__asm__ __volatile__("sti ; hlt": : :"memory");
@@ -538,18 +573,25 @@
 		inb(acpi_p_lvl2);
 		break;
 	case 3:
-		/* Disable PCI arbitration while sleeping,
-		   to avoid DMA corruption? */
-		if (acpi_facp->pm2_cnt) {
-			unsigned int port = acpi_facp->pm2_cnt;
-			outb(inb(port) | ACPI_ARB_DIS, port);
+		pm2_cnt = acpi_facp->pm2_cnt;
+		if (pm2_cnt) {
+			/* Disable PCI arbitration while sleeping,
+			   to avoid DMA corruption? */
+			outb(inb(pm2_cnt) | ACPI_ARB_DIS, pm2_cnt);
+			inb(acpi_p_lvl3);
+			outb(inb(pm2_cnt) & ~ACPI_ARB_DIS, pm2_cnt);
+		}
+		else {
 			inb(acpi_p_lvl3);
-			outb(inb(port) & ~ACPI_ARB_DIS, port);
-			break;
 		}
-		inb(acpi_p_lvl3);
+		break;
 	}
-	time = (inl(acpi_facp->pm_tmr) - time) & ACPI_TMR_MASK;
+
+	// calculate time spent sleeping (fallback to CPU cycles)
+	if (timer)
+		time = (inl(timer) - time) & ACPI_TMR_MASK;
+	else
+		time = ACPI_CPU_TO_TMR_TICKS(get_cycles() - time);
 
 	if (time > acpi_p_lvl3_lat)
 		sleep_level = 3;
@@ -559,50 +601,24 @@
 		sleep_level = 1;
 }
 
-static struct file_operations acpi_fops =
-{
-	NULL,			/* llseek */
-	NULL,			/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	acpi_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	acpi_open,		/* open */
-	NULL,			/* flush */
-	acpi_release,		/* release */
-	NULL,			/* fsync */
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
-	NULL,			/* lock */
-};
-
-static struct miscdevice acpi_device =
-{
-	ACPI_MINOR_DEV,
-	"acpi",
-	&acpi_fops,
-	NULL,
-	NULL
-};
-
 /*
  * 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
-	request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi");
+	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");
-	request_region(facp->pm1a_cnt, facp->pm1_cnt_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->pm2_cnt)
-		request_region(facp->pm2_cnt, facp->pm2_cnt_len, "acpi");
-	request_region(facp->pm_tmr, facp->pm_tm_len, "acpi");
-	request_region(facp->gpe0, facp->gpe0_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");
 
@@ -615,16 +631,18 @@
 static int acpi_release_ioports(struct acpi_facp *facp)
 {
 	// we don't get a guarantee of contiguity for any of the ACPI registers
-	release_region(facp->pm1a_evt, facp->pm1_evt_len);
+	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);
-	release_region(facp->pm1a_cnt, facp->pm1_cnt_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->pm2_cnt)
-		release_region(facp->pm2_cnt, facp->pm2_cnt_len);
-	release_region(facp->pm_tmr, facp->pm_tm_len);
-	release_region(facp->gpe0, facp->gpe0_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);
 
@@ -632,28 +650,224 @@
 }
 
 /*
+ * Examine/modify value
+ */
+static int acpi_do_ulong(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len)
+{
+	char str[2 * sizeof(unsigned long) + 4], *strend;
+	unsigned long val;
+	int size;
+
+	if (!write) {
+		if (file->f_pos) {
+			*len = 0;
+			return 0;
+		}
+
+		val = *(unsigned long*) ctl->data;
+		size = sprintf(str, "0x%08lx\n", val);
+		if (*len >= size) {
+			copy_to_user(buffer, str, size);
+			*len = size;
+		}
+		else
+			*len = 0;
+	}
+	else {
+		size = sizeof(str) - 1;
+		if (size > *len)
+			size = *len;
+		copy_from_user(str, buffer, size);
+		str[size] = '\0';
+		val = simple_strtoul(str, &strend, 0);
+		if (strend == str)
+			return -EINVAL;
+		*(unsigned long*) ctl->data = val;
+	}
+
+	file->f_pos += *len;
+	return 0;
+}
+
+/*
+ * Examine/modify event register
+ */
+static int acpi_do_event_reg(ctl_table *ctl,
+			     int write,
+			     struct file *file,
+			     void *buffer,
+			     size_t *len)
+{
+	char str[2 * sizeof(u32) + 4], *strend;
+	u32 val, enabling;
+	int size;
+
+	if (!write) {
+		if (file->f_pos) {
+			*len = 0;
+			return 0;
+		}
+
+		val = 0;
+		switch (ctl->ctl_name) {
+		case ACPI_PM1_ENABLE:
+			val = acpi_read_pm1_enable(acpi_facp);
+			break;
+		case ACPI_GPE_ENABLE:
+			val = acpi_read_gpe_enable(acpi_facp);
+			break;
+		case ACPI_GPE_LEVEL:
+			val = acpi_gpe_level;
+			break;
+		}
+		
+		size = sprintf(str, "0x%08x\n", val);
+		if (*len >= size) {
+			copy_to_user(buffer, str, size);
+			*len = size;
+		}
+		else
+			*len = 0;
+	}
+	else
+	{
+		// fetch user value
+		size = sizeof(str) - 1;
+		if (size > *len)
+			size = *len;
+		copy_from_user(str, buffer, size);
+		str[size] = '\0';
+		val = (u32) simple_strtoul(str, &strend, 0);
+		if (strend == str)
+			return -EINVAL;
+
+		// store value in register
+		switch (ctl->ctl_name) {
+		case ACPI_PM1_ENABLE:
+			// clear previously disabled events
+			enabling = (val
+				    & ~acpi_read_pm1_enable(acpi_facp));
+			acpi_write_pm1_status(acpi_facp, enabling);
+			
+			if (val) {
+				// enable ACPI unless it is already
+				if (!acpi_is_enabled(acpi_facp))
+					acpi_enable(acpi_facp);
+			}
+			else if (!acpi_read_gpe_enable(acpi_facp)) {
+				// disable ACPI unless it is already
+				if (acpi_is_enabled(acpi_facp))
+					acpi_disable(acpi_facp);
+			}
+			
+			acpi_write_pm1_enable(acpi_facp, val);
+			break;
+		case ACPI_GPE_ENABLE:
+			// clear previously disabled events
+			enabling = (val
+				    & ~acpi_read_gpe_enable(acpi_facp));
+			while (acpi_read_gpe_status(acpi_facp) & enabling)
+				acpi_write_gpe_status(acpi_facp, enabling);
+			
+			if (val) {
+				// enable ACPI unless it is already
+				if (!acpi_is_enabled(acpi_facp))
+					acpi_enable(acpi_facp);
+			}
+			else if (!acpi_read_pm1_enable(acpi_facp)) {
+				// disable ACPI unless it is already
+				if (acpi_is_enabled(acpi_facp))
+					acpi_disable(acpi_facp);
+			}
+			
+			acpi_write_gpe_enable(acpi_facp, val);
+			break;
+		case ACPI_GPE_LEVEL:
+			acpi_gpe_level = val;
+			break;
+		}
+	}
+
+	file->f_pos += *len;
+	return 0;
+}
+
+/*
+ * Wait for next event
+ */
+static int acpi_do_event(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len)
+{
+	u32 pm1_status = 0, gpe_status = 0;
+	char str[4 * sizeof(u32) + 6];
+	int size;
+
+	if (write)
+		return -EPERM;
+	if (*len < sizeof(str)) {
+		*len = 0;
+		return 0;
+	}
+
+	for (;;) {
+		unsigned long flags;
+		
+		// we need an atomic exchange here
+		spin_lock_irqsave(&acpi_event_lock, flags);
+		pm1_status = acpi_pm1_status;
+		acpi_pm1_status = 0;
+		gpe_status = acpi_gpe_status;
+		acpi_gpe_status = 0;
+		spin_unlock_irqrestore(&acpi_event_lock, flags);
+		
+		if (pm1_status || gpe_status)
+			break;
+		
+		// wait for an event to arrive
+		interruptible_sleep_on(&acpi_event_wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+
+	size = sprintf(str, "0x%08x 0x%08x\n", pm1_status, gpe_status);
+	copy_to_user(buffer, str, size);
+	*len = size;
+	file->f_pos += size;
+
+	return 0;
+}
+
+/*
  * Initialize and enable ACPI
  */
 static int __init acpi_init(void)
 {
-	if (acpi_map_tables())
+	if (acpi_find_tables() && acpi_find_piix4()) {
+		// no ACPI tables and not PIIX4
 		return -ENODEV;
+	}
 
-	if (request_irq(acpi_facp->sci_int,
-			acpi_irq,
-			SA_INTERRUPT | SA_SHIRQ,
-			"acpi",
-			NULL)) {
+	if (acpi_facp->sci_int
+	    && request_irq(acpi_facp->sci_int,
+			   acpi_irq,
+			   SA_INTERRUPT | SA_SHIRQ,
+			   "acpi",
+			   NULL)) {
 		printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n",
 		       acpi_facp->sci_int);
-		acpi_unmap_tables();
+		acpi_destroy_tables();
 		return -ENODEV;
 	}
 
 	acpi_claim_ioports(acpi_facp);
-
-	if (misc_register(&acpi_device))
-		printk(KERN_ERR "ACPI: misc. register failed\n");
+	acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
 
 	/*
 	 * Set up the ACPI idle function. Note that we can't really
@@ -664,7 +878,9 @@
 	if (smp_num_cpus > 1)
 		return 0;
 #endif
+
 	acpi_idle = acpi_idle_handler;
+
 	return 0;
 }
 
@@ -673,11 +889,16 @@
  */
 static void __exit acpi_exit(void)
 {
-	misc_deregister(&acpi_device);
+	acpi_idle = NULL;
+
+	unregister_sysctl_table(acpi_sysctl);
 	acpi_disable(acpi_facp);
 	acpi_release_ioports(acpi_facp);
-	free_irq(acpi_facp->sci_int, NULL);
-	acpi_unmap_tables();
+
+	if (acpi_facp->sci_int)
+		free_irq(acpi_facp->sci_int, NULL);
+
+	acpi_destroy_tables();
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.23/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.3.23/linux/drivers/net/Config.in	Fri Oct 15 15:25:13 1999
+++ linux/drivers/net/Config.in	Mon Oct 25 09:23:48 1999
@@ -46,6 +46,7 @@
    if [ "$CONFIG_PPC" = "y" ]; then
       tristate '  MACE (Power Mac ethernet) support' CONFIG_MACE
       tristate '  BMAC (G3 ethernet) support' CONFIG_BMAC
+      tristate '  Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E
    fi
    if [ "$CONFIG_ZORRO" = "y" ]; then
       tristate '  Ariadne support' CONFIG_ARIADNE
@@ -214,6 +215,7 @@
 tristate 'PPP (point-to-point protocol) support' CONFIG_PPP
 if [ ! "$CONFIG_PPP" = "n" ]; then
    dep_tristate '  PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
+   dep_tristate '  PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
    dep_tristate '  PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
    dep_tristate '  PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
 fi
diff -u --recursive --new-file v2.3.23/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.3.23/linux/drivers/net/Makefile	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/Makefile	Mon Oct 25 09:23:48 1999
@@ -299,6 +299,13 @@
     MX_OBJS += ppp_async.o
     endif
   endif
+  ifeq ($(CONFIG_PPP_SYNC_TTY),y)
+  LX_OBJS += ppp_synctty.o
+  else
+    ifeq ($(CONFIG_PPP_SYNC_TTY),m)
+    MX_OBJS += ppp_synctty.o
+    endif
+  endif
   ifeq ($(CONFIG_PPP_DEFLATE),y)
   CONFIG_PPPDEF_BUILTIN = y
   else
@@ -316,6 +323,9 @@
     ifeq ($(CONFIG_PPP_ASYNC),m)
     MX_OBJS += ppp_async.o
     endif
+    ifeq ($(CONFIG_PPP_SYNC_TTY),m)
+    MX_OBJS += ppp_synctty.o
+    endif
     ifeq ($(CONFIG_PPP_DEFLATE),m)
     CONFIG_PPPDEF_MODULE = y
     endif
@@ -1024,6 +1034,14 @@
 else
   ifeq ($(CONFIG_BMAC),m)
   M_OBJS += bmac.o
+  endif
+endif
+
+ifeq ($(CONFIG_NCR885E),y)
+L_OBJS += ncr885e.o
+else
+  ifeq ($(CONFIG_NCR885E),m)
+  M_OBJS += ncr885e.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.23/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.3.23/linux/drivers/net/arcnet.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/net/arcnet.c	Mon Oct 25 20:49:42 1999
@@ -1,184 +1,184 @@
-/*	$Id: arcnet.c,v 1.34 1997/11/09 11:04:55 mj Exp $
+/*      $Id: arcnet.c,v 1.34 1997/11/09 11:04:55 mj Exp $
 
-	Written 1994-1996 by Avery Pennarun,
-	derived from skeleton.c by Donald Becker.
+   Written 1994-1996 by Avery Pennarun,
+   derived from skeleton.c by Donald Becker.
 
-	**********************
+   **********************
 
-	The original copyright was as follows:
+   The original copyright was as follows:
 
-	skeleton.c Written 1993 by Donald Becker.
-	Copyright 1993 United States Government as represented by the
-        Director, National Security Agency.  This software may only be used
-        and distributed according to the terms of the GNU Public License as
-        modified by SRC, incorporated herein by reference.
-
-	**********************
-
-	v3.02 (98/06/07)
-	  - Use register_netdevice() instead of register_netdev() to create
-	    new devices for RFC1051 and Ethernet encapsulation in arcnet_open.
-	    Likewise for unregistering them later. This avoids the deadlock 
-	    encountered because the original routines call rtnl_lock() when
-	    it's already locked. [dw]
-
-	v3.01 (98/04/17)
-	  - Interrupt handler now also checks dev->[se]dev are non-NULL
-	    to avoid crashes in interrupts during card init. [dw]
-
-	v3.00 (97/11/09)
-	  - Minor cleanup of debugging messages. [mj]
-
-	v2.93 ALPHA (97/11/06)
-	  - irq2dev mapping removed.
-	  - Interrupt handler now checks whether dev->priv is non-null in order
-	    to avoid crashes in interrupts which come during card init. [mj]
-
-	v2.92 ALPHA (97/09/02)
-	  - Code cleanup [Martin Mares <mj@atrey.karlin.mff.cuni.cz>]
-	  - Better probing for the COM90xx chipset, although only as
-	    a temporary solution until we implement adding of all found
-	    devices at once. [mj]
-
-	v2.91 ALPHA (97/08/19)
-	  - Add counting of octets in/out.
-
-	v2.90 ALPHA (97/08/08)
-	  - Add support for kernel command line parsing so that chipset
-	    drivers are usable when compiled in.
-
-	v2.80 ALPHA (97/08/01)
-	  - Split source into multiple files; generic arcnet support and
-	    individual chipset drivers. <Dave@imladris.demon.co.uk>
-
-	v2.61 ALPHA (97/07/30)  by David Woodhouse (Dave@imladris.demon.co.uk)
-	                            for Nortel (Northern Telecom).
-          - Added support for IO-mapped modes and for SMC COM20020 chipset.
-	  - Fixed (avoided) race condition in send_packet routines which was
-            discovered when the buffer copy routines got slow (?).
-          - Fixed support for device naming at load time.
-	  - Added backplane, clock and timeout options for COM20020.
-	  - Added support for promiscuous mode.
-
-	v2.60 ALPHA (96/11/23)
-	  - Added patch from Vojtech Pavlik <vojtech@atrey.karlin.mff.cuni.cz>
-	    and Martin Mares <mj@k332.feld.cvut.cz> to make the driver work
-	    with the new Linux 2.1.x memory management.  I modified their
-	    patch quite a bit though; bugs are my fault.  More changes should
-	    be made to get eliminate any remaining phys_to_virt calls.
-	  - Quietly ignore protocol id's 0, 1, 8, and 243.  Thanks to Jake
-	    Messinger <jake@ams.com> for reporting these codes and their
-	    meanings.
-	  - Smarter shmem probe for cards with 4k mirrors. (does it work?)
-	  - Initial support for RIM I type cards which use no I/O ports at
-	    all.  To use this option, you need to compile with RIM_I_MODE
-	    enabled.  Thanks to Kolja Waschk <kawk@yo.com> for explaining
-	    RIM I programming to me.  Now, does my RIM I code actually
-	    work?
-
-	v2.56 (96/10/18)
-	  - Turned arc0e/arc0s startup messages back on by default, as most
-	    people will probably not notice the additional devices
-	    otherwise.  This causes undue confusion.
-	  - Fixed a tiny but noticeable bug in the packet debugging routines
-	    (thanks Tomasz)
-
-	The following has been SUMMARIZED.  The complete ChangeLog is
-	available in the full Linux-ARCnet package at
-		http://www.worldvisions.ca/~apenwarr/arcnet
-
-	v2.50 (96/02/24)
-	  - Massively improved autoprobe routines; they now work even as a
-	    module.  Thanks to Vojtech Pavlik <Vojtech.Pavlik@st.mff.cuni.cz>
-	    for his ideas and help in this area.
-	  - Changed printk's around quite a lot.
-
-	v2.22 (95/12/08)
-	  - Major cleanups, speedups, and better code-sharing.
-	  - Eliminated/changed many useless/meaningless/scary debug messages
-	    (and, in most cases, the bugs that caused them).
-	  - Better IPX support.
-	  - lp->stats updated properly.
-	  - RECON checking now by default only prints a message if there are
-	    excessive errors (ie. your cable is probably broken).
-	  - New RFC1051-compliant "arc0s" virtual device by Tomasz
-	    Motylewski.
-	  - Excess debug messages can be compiled out to reduce code size.
-
-	v2.00 (95/09/06)
-	  - ARCnet RECON messages are now detected and logged as "carrier"
-	    errors.
-	  - The TXACK flag is now checked, and errors are logged.
-	  - Debug levels are now completely different.  See the README.
-	  - Massive code cleanups, with several no-longer-necessary and some
-	    completely useless options removed.
-	  - Multiprotocol support.  You can now use the "arc0e" device to
-	    send "Ethernet-Encapsulation" packets, which are compatible with
-	    Windows for Workgroups and LAN Manager, and possibly other
-	    software.  See the README for more information.
-
-	v1.02 (95/06/21)
-          - A fix to make "exception" packets sent from Linux receivable
-	    on other systems.  (The protocol_id byte was sometimes being set
-	    incorrectly, and Linux wasn't checking it on receive so it
-	    didn't show up)
-
-	v1.01 (95/03/24)
-	  - Fixed some IPX-related bugs. (Thanks to Tomasz Motylewski
-            <motyl@tichy.ch.uj.edu.pl> for the patches to make arcnet work
-            with dosemu!)
-
-	v1.00 (95/02/15)
-	  - Initial non-alpha release.
-
-
-	TO DO: (semi-prioritized)
-
-         - Use cleaner "architecture-independent" shared memory access.
-           This is half-done in ARCnet 2.60, but still uses some
-           undocumented i386 stuff.  (We shouldn't call phys_to_virt,
-           for example.)
-	 - Allow use of RFC1051 or Ether devices without RFC1201.
-	 - Keep separate stats for each device.
-         - Support "arpless" mode like NetBSD does, and as recommended
-           by the (obsoleted) RFC1051.
-         - Smarter recovery from RECON-during-transmit conditions. (ie.
-           retransmit immediately)
-         - Add support for the new 1.3.x IP header cache, and other features.
-         - Replace setting of debug level with the "metric" flag hack by
-	   something that still exists. SIOCDEVPRIVATE is a good candidate, 
-	   but it would require an extra user-level utility.
-
-         - What about cards with shared memory that can be "turned off?"
-           (or that have none at all, like the SMC PC500longboard)
-           Does this work now, with IO_MAPPED_BUFFERS?
-
-         - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
-           with temporarily.)  Update: yes, the Pure Data config program
-           for DOS works fine, but the PDI508Plus I have doesn't! :)
-         - ATA protocol support??
-         - VINES TCP/IP encapsulation?? (info needed)
-
-	Sources:
-	 - Crynwr arcnet.com/arcether.com packet drivers.
-	 - arcnet.c v0.00 dated 1/1/94 and apparently by
-	 	Donald Becker - it didn't work :)
-	 - skeleton.c v0.05 dated 11/16/93 by Donald Becker
-	 	(from Linux Kernel 1.1.45)
-	 - RFC's 1201 and 1051 - re: TCP/IP over ARCnet
-	 - The official ARCnet COM9026 data sheets (!) thanks to Ken
-		Cornetet <kcornete@nyx10.cs.du.edu>
-	 - The official ARCnet COM20020 data sheets.
-	 - Information on some more obscure ARCnet controller chips, thanks
-	   to the nice people at SMC.
-	 - net/inet/eth.c (from kernel 1.1.50) for header-building info.
-	 - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
-	 - Textual information and more alternate source from Joachim Koenig
-	 	<jojo@repas.de>
-*/
+   skeleton.c Written 1993 by Donald Becker.
+   Copyright 1993 United States Government as represented by the
+   Director, National Security Agency.  This software may only be used
+   and distributed according to the terms of the GNU Public License as
+   modified by SRC, incorporated herein by reference.
+
+   **********************
+
+   v3.02 (98/06/07)
+   - Use register_netdevice() instead of register_netdev() to create
+   new devices for RFC1051 and Ethernet encapsulation in arcnet_open.
+   Likewise for unregistering them later. This avoids the deadlock 
+   encountered because the original routines call rtnl_lock() when
+   it's already locked. [dw]
+
+   v3.01 (98/04/17)
+   - Interrupt handler now also checks dev->[se]dev are non-NULL
+   to avoid crashes in interrupts during card init. [dw]
+
+   v3.00 (97/11/09)
+   - Minor cleanup of debugging messages. [mj]
+
+   v2.93 ALPHA (97/11/06)
+   - irq2dev mapping removed.
+   - Interrupt handler now checks whether dev->priv is non-null in order
+   to avoid crashes in interrupts which come during card init. [mj]
+
+   v2.92 ALPHA (97/09/02)
+   - Code cleanup [Martin Mares <mj@atrey.karlin.mff.cuni.cz>]
+   - Better probing for the COM90xx chipset, although only as
+   a temporary solution until we implement adding of all found
+   devices at once. [mj]
+
+   v2.91 ALPHA (97/08/19)
+   - Add counting of octets in/out.
+
+   v2.90 ALPHA (97/08/08)
+   - Add support for kernel command line parsing so that chipset
+   drivers are usable when compiled in.
+
+   v2.80 ALPHA (97/08/01)
+   - Split source into multiple files; generic arcnet support and
+   individual chipset drivers. <Dave@imladris.demon.co.uk>
+
+   v2.61 ALPHA (97/07/30)  by David Woodhouse (Dave@imladris.demon.co.uk)
+   for Nortel (Northern Telecom).
+   - Added support for IO-mapped modes and for SMC COM20020 chipset.
+   - Fixed (avoided) race condition in send_packet routines which was
+   discovered when the buffer copy routines got slow (?).
+   - Fixed support for device naming at load time.
+   - Added backplane, clock and timeout options for COM20020.
+   - Added support for promiscuous mode.
+
+   v2.60 ALPHA (96/11/23)
+   - Added patch from Vojtech Pavlik <vojtech@atrey.karlin.mff.cuni.cz>
+   and Martin Mares <mj@k332.feld.cvut.cz> to make the driver work
+   with the new Linux 2.1.x memory management.  I modified their
+   patch quite a bit though; bugs are my fault.  More changes should
+   be made to get eliminate any remaining phys_to_virt calls.
+   - Quietly ignore protocol id's 0, 1, 8, and 243.  Thanks to Jake
+   Messinger <jake@ams.com> for reporting these codes and their
+   meanings.
+   - Smarter shmem probe for cards with 4k mirrors. (does it work?)
+   - Initial support for RIM I type cards which use no I/O ports at
+   all.  To use this option, you need to compile with RIM_I_MODE
+   enabled.  Thanks to Kolja Waschk <kawk@yo.com> for explaining
+   RIM I programming to me.  Now, does my RIM I code actually
+   work?
+
+   v2.56 (96/10/18)
+   - Turned arc0e/arc0s startup messages back on by default, as most
+   people will probably not notice the additional devices
+   otherwise.  This causes undue confusion.
+   - Fixed a tiny but noticeable bug in the packet debugging routines
+   (thanks Tomasz)
+
+   The following has been SUMMARIZED.  The complete ChangeLog is
+   available in the full Linux-ARCnet package at
+   http://www.worldvisions.ca/~apenwarr/arcnet
+
+   v2.50 (96/02/24)
+   - Massively improved autoprobe routines; they now work even as a
+   module.  Thanks to Vojtech Pavlik <Vojtech.Pavlik@st.mff.cuni.cz>
+   for his ideas and help in this area.
+   - Changed printk's around quite a lot.
+
+   v2.22 (95/12/08)
+   - Major cleanups, speedups, and better code-sharing.
+   - Eliminated/changed many useless/meaningless/scary debug messages
+   (and, in most cases, the bugs that caused them).
+   - Better IPX support.
+   - lp->stats updated properly.
+   - RECON checking now by default only prints a message if there are
+   excessive errors (ie. your cable is probably broken).
+   - New RFC1051-compliant "arc0s" virtual device by Tomasz
+   Motylewski.
+   - Excess debug messages can be compiled out to reduce code size.
+
+   v2.00 (95/09/06)
+   - ARCnet RECON messages are now detected and logged as "carrier"
+   errors.
+   - The TXACK flag is now checked, and errors are logged.
+   - Debug levels are now completely different.  See the README.
+   - Massive code cleanups, with several no-longer-necessary and some
+   completely useless options removed.
+   - Multiprotocol support.  You can now use the "arc0e" device to
+   send "Ethernet-Encapsulation" packets, which are compatible with
+   Windows for Workgroups and LAN Manager, and possibly other
+   software.  See the README for more information.
+
+   v1.02 (95/06/21)
+   - A fix to make "exception" packets sent from Linux receivable
+   on other systems.  (The protocol_id byte was sometimes being set
+   incorrectly, and Linux wasn't checking it on receive so it
+   didn't show up)
+
+   v1.01 (95/03/24)
+   - Fixed some IPX-related bugs. (Thanks to Tomasz Motylewski
+   <motyl@tichy.ch.uj.edu.pl> for the patches to make arcnet work
+   with dosemu!)
+
+   v1.00 (95/02/15)
+   - Initial non-alpha release.
+
+
+   TO DO: (semi-prioritized)
+
+   - Use cleaner "architecture-independent" shared memory access.
+   This is half-done in ARCnet 2.60, but still uses some
+   undocumented i386 stuff.  (We shouldn't call phys_to_virt,
+   for example.)
+   - Allow use of RFC1051 or Ether devices without RFC1201.
+   - Keep separate stats for each device.
+   - Support "arpless" mode like NetBSD does, and as recommended
+   by the (obsoleted) RFC1051.
+   - Smarter recovery from RECON-during-transmit conditions. (ie.
+   retransmit immediately)
+   - Add support for the new 1.3.x IP header cache, and other features.
+   - Replace setting of debug level with the "metric" flag hack by
+   something that still exists. SIOCDEVPRIVATE is a good candidate, 
+   but it would require an extra user-level utility.
+
+   - What about cards with shared memory that can be "turned off?"
+   (or that have none at all, like the SMC PC500longboard)
+   Does this work now, with IO_MAPPED_BUFFERS?
+
+   - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
+   with temporarily.)  Update: yes, the Pure Data config program
+   for DOS works fine, but the PDI508Plus I have doesn't! :)
+   - ATA protocol support??
+   - VINES TCP/IP encapsulation?? (info needed)
+
+   Sources:
+   - Crynwr arcnet.com/arcether.com packet drivers.
+   - arcnet.c v0.00 dated 1/1/94 and apparently by
+   Donald Becker - it didn't work :)
+   - skeleton.c v0.05 dated 11/16/93 by Donald Becker
+   (from Linux Kernel 1.1.45)
+   - RFC's 1201 and 1051 - re: TCP/IP over ARCnet
+   - The official ARCnet COM9026 data sheets (!) thanks to Ken
+   Cornetet <kcornete@nyx10.cs.du.edu>
+   - The official ARCnet COM20020 data sheets.
+   - Information on some more obscure ARCnet controller chips, thanks
+   to the nice people at SMC.
+   - net/inet/eth.c (from kernel 1.1.50) for header-building info.
+   - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
+   - Textual information and more alternate source from Joachim Koenig
+   <jojo@repas.de>
+ */
 
 static const char *version =
- "arcnet.c: v3.02 98/06/07 Avery Pennarun <apenwarr@worldvisions.ca> et al.\n";
+"arcnet.c: v3.02 98/06/07 Avery Pennarun <apenwarr@worldvisions.ca> et al.\n";
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -230,15 +230,15 @@
 #define ARCSTATUS ((*lp->astatus)(dev))
 #define ACOMMAND(x) ((*lp->acommand)(dev, x))
 
-int arcnet_debug=ARCNET_DEBUG;
+int arcnet_debug = ARCNET_DEBUG;
 
 /* Exported function prototypes */
 
 #ifdef MODULE
-int  init_module(void);
+int init_module(void);
 void cleanup_module(void);
 #else
-void arcnet_init(void);
+int arcnet_init(void);
 static int init_module(void);
 #ifdef CONFIG_ARCNET_COM90xx
 extern char com90xx_explicit;
@@ -247,13 +247,13 @@
 #endif
 
 void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp);
-void arcnet_use_count (int open);
+void arcnet_use_count(int open);
 void arcnet_setup(struct net_device *dev);
 void arcnet_makename(char *device);
 void arcnetA_continue_tx(struct net_device *dev);
-int arcnet_go_tx(struct net_device *dev,int enable_irq);
-void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
+int arcnet_go_tx(struct net_device *dev, int enable_irq);
+void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+void arcnet_rx(struct arcnet_local *lp, u_char * arcsoft, short length, int saddr, int daddr);
 
 EXPORT_SYMBOL(arcnet_debug);
 EXPORT_SYMBOL(arcnet_tx_done);
@@ -266,32 +266,32 @@
 EXPORT_SYMBOL(arcnet_rx);
 
 #if ARCNET_DEBUG_MAX & D_SKB
-void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,
-	char *desc);
+void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb,
+		     char *desc);
 EXPORT_SYMBOL(arcnet_dump_skb);
 #else
-#	define arcnet_dump_skb(dev,skb,desc) ;
+#define arcnet_dump_skb(dev,skb,desc) ;
 #endif
 
 #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,
-	char *desc);
+void arcnet_dump_packet(struct net_device *dev, u_char * buffer, int ext,
+			char *desc);
 EXPORT_SYMBOL(arcnet_dump_packet);
 #else
-#	define arcnet_dump_packet(dev,buffer,ext,desc) ;
+#define arcnet_dump_packet(dev,buffer,ext,desc) ;
 #endif
 
 /* Internal function prototypes */
 
 static int arcnet_open(struct net_device *dev);
 static int arcnet_close(struct net_device *dev);
-static int arcnetA_header(struct sk_buff *skb,struct net_device *dev,
-		unsigned short type,void *daddr,void *saddr,unsigned len);
+static int arcnetA_header(struct sk_buff *skb, struct net_device *dev,
+	    unsigned short type, void *daddr, void *saddr, unsigned len);
 static int arcnetA_rebuild_header(struct sk_buff *skb);
-static int arcnet_send_packet_bad(struct sk_buff *skb,struct net_device *dev);
+static int arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev);
 static int arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void arcnetA_rx(struct net_device *dev,u_char *buf,
-	int length,u_char saddr, u_char daddr);
+static void arcnetA_rx(struct net_device *dev, u_char * buf,
+		       int length, u_char saddr, u_char daddr);
 static struct net_device_stats *arcnet_get_stats(struct net_device *dev);
 static unsigned short arcnetA_type_trans(struct sk_buff *skb,
 					 struct net_device *dev);
@@ -302,8 +302,8 @@
 static int arcnetE_init(struct net_device *dev);
 static int arcnetE_open_close(struct net_device *dev);
 static int arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void arcnetE_rx(struct net_device *dev,u_char *arcsoft,
-	int length,u_char saddr, u_char daddr);
+static void arcnetE_rx(struct net_device *dev, u_char * arcsoft,
+		       int length, u_char saddr, u_char daddr);
 #endif
 
 
@@ -312,12 +312,12 @@
 static int arcnetS_init(struct net_device *dev);
 static int arcnetS_open_close(struct net_device *dev);
 static int arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void arcnetS_rx(struct net_device *dev,u_char *buf,
-	int length,u_char saddr, u_char daddr);
-static int arcnetS_header(struct sk_buff *skb,struct net_device *dev,
-		unsigned short type,void *daddr,void *saddr,unsigned len);
+static void arcnetS_rx(struct net_device *dev, u_char * buf,
+		       int length, u_char saddr, u_char daddr);
+static int arcnetS_header(struct sk_buff *skb, struct net_device *dev,
+	    unsigned short type, void *daddr, void *saddr, unsigned len);
 static int arcnetS_rebuild_header(struct sk_buff *skb);
-static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev);
+static unsigned short arcnetS_type_trans(struct sk_buff *skb, struct net_device *dev);
 #endif
 
 
@@ -330,22 +330,21 @@
 /* Dump the contents of an sk_buff
  */
 #if ARCNET_DEBUG_MAX & D_SKB
-void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,char *desc)
+void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
 {
 	int i;
 	long flags;
 
 	save_flags(flags);
 	cli();
-	printk(KERN_DEBUG "%6s: skb dump (%s) follows:",dev->name,desc);
-        for(i=0; i<skb->len; i++)
-        {
-		if (i%16==0)
-			printk("\n" KERN_DEBUG "[%04X] ",i);
-               	printk("%02X ",((u_char *)skb->data)[i]);
+	printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc);
+	for (i = 0; i < skb->len; i++) {
+		if (i % 16 == 0)
+			printk("\n" KERN_DEBUG "[%04X] ", i);
+		printk("%02X ", ((u_char *) skb->data)[i]);
 	}
-        printk("\n");
-        restore_flags(flags);
+	printk("\n");
+	restore_flags(flags);
 }
 #endif
 
@@ -353,19 +352,18 @@
 /* Dump the contents of an ARCnet buffer
  */
 #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,char *desc)
+void arcnet_dump_packet(struct net_device *dev, u_char * buffer, int ext, char *desc)
 {
 	int i;
 	long flags;
 
 	save_flags(flags);
 	cli();
-	printk(KERN_DEBUG "%6s: packet dump (%s) follows:",dev->name,desc);
-	for (i=0; i<256+(ext!=0)*256; i++)
-	{
-		if (i%16==0)
-			printk("\n" KERN_DEBUG "[%04X] ",i);
-		printk("%02X ",buffer[i]);
+	printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc);
+	for (i = 0; i < 256 + (ext != 0) * 256; i++) {
+		if (i % 16 == 0)
+			printk("\n" KERN_DEBUG "[%04X] ", i);
+		printk("%02X ", buffer[i]);
 	}
 	printk("\n");
 	restore_flags(flags);
@@ -386,24 +384,24 @@
 {
 	dev_init_buffers(dev);
 
-	dev->broadcast[0]	= 0x00;	/* for us, broadcasts are address 0 */
-	dev->addr_len		= 1;
-	dev->type		= ARPHRD_ARCNET;
-	dev->tx_queue_len	= 30;
+	dev->broadcast[0] = 0x00;	/* for us, broadcasts are address 0 */
+	dev->addr_len = 1;
+	dev->type = ARPHRD_ARCNET;
+	dev->tx_queue_len = 30;
 
 	/* New-style flags. */
-	dev->flags		= IFF_BROADCAST;
+	dev->flags = IFF_BROADCAST;
 
 	/* Put in this stuff here, so we don't have to export the symbols
 	 * to the chipset drivers.
 	 */
 
-  	dev->open=arcnet_open;
-	dev->stop=arcnet_close;
-	dev->hard_start_xmit=arcnetA_send_packet;
-	dev->get_stats=arcnet_get_stats;
-	dev->hard_header=arcnetA_header;
-	dev->rebuild_header=arcnetA_rebuild_header;
+	dev->open = arcnet_open;
+	dev->stop = arcnet_close;
+	dev->hard_start_xmit = arcnetA_send_packet;
+	dev->get_stats = arcnet_get_stats;
+	dev->hard_header = arcnetA_header;
+	dev->rebuild_header = arcnetA_rebuild_header;
 }
 
 
@@ -420,167 +418,164 @@
  * registers that "should" only need to be set once at boot, so that
  * there is non-reboot way to recover if something goes wrong.
  */
-static int
-arcnet_open(struct net_device *dev)
+static int arcnet_open(struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
-  /*  if (dev->metric>=1000)
-   *  {
-   *  arcnet_debug=dev->metric-1000;
-   *  printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
-   *  dev->metric=1;
-   *}
-   */
-  BUGMSG(D_INIT,"arcnet_open: resetting card.\n");
-
-  /* try to put the card in a defined state - if it fails the first
-   * time, actually reset it.
-   */
-  if ((*lp->arcnet_reset)(dev,0) && (*lp->arcnet_reset)(dev,1))
-    return -ENODEV;
-
-  dev->tbusy=0;
-  dev->interrupt=0;
-  lp->intx=0;
-  lp->in_txhandler=0;
+	/*  if (dev->metric>=1000)
+	 *  {
+	 *  arcnet_debug=dev->metric-1000;
+	 *  printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
+	 *  dev->metric=1;
+	 *}
+	 */
+	BUGMSG(D_INIT, "arcnet_open: resetting card.\n");
+
+	/* try to put the card in a defined state - if it fails the first
+	 * time, actually reset it.
+	 */
+	if ((*lp->arcnet_reset) (dev, 0) && (*lp->arcnet_reset) (dev, 1))
+		return -ENODEV;
 
-  /* The RFC1201 driver is the default - just store */
-  lp->adev=dev;
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	lp->intx = 0;
+	lp->in_txhandler = 0;
 
-  /* we're started */
-  dev->start=1;
+	/* The RFC1201 driver is the default - just store */
+	lp->adev = dev;
+
+	/* we're started */
+	dev->start = 1;
 
 #ifdef CONFIG_ARCNET_ETH
-  /* Initialize the ethernet-encap protocol driver */
-  lp->edev=(struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL);
-  if (lp->edev == NULL)
-    return -ENOMEM;
-  memcpy(lp->edev,dev,sizeof(struct net_device));
-  lp->edev->type=ARPHRD_ETHER;
-  lp->edev->name=(char *)kmalloc(10,GFP_KERNEL);
-  if (lp->edev->name == NULL) {
-    kfree(lp->edev);
-    lp->edev = NULL;
-    return -ENOMEM;
-  }
-  sprintf(lp->edev->name,"%se",dev->name);
-  lp->edev->init=arcnetE_init;
-  register_netdevice(lp->edev);
+	/* Initialize the ethernet-encap protocol driver */
+	lp->edev = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	if (lp->edev == NULL)
+		return -ENOMEM;
+	memcpy(lp->edev, dev, sizeof(struct net_device));
+	lp->edev->type = ARPHRD_ETHER;
+	lp->edev->name = (char *) kmalloc(10, GFP_KERNEL);
+	if (lp->edev->name == NULL) {
+		kfree(lp->edev);
+		lp->edev = NULL;
+		return -ENOMEM;
+	}
+	sprintf(lp->edev->name, "%se", dev->name);
+	lp->edev->init = arcnetE_init;
+	register_netdevice(lp->edev);
 #endif
 
 #ifdef CONFIG_ARCNET_1051
-  /* Initialize the RFC1051-encap protocol driver */
-  lp->sdev=(struct net_device *)kmalloc(sizeof(struct net_device)+10,GFP_KERNEL);
-  if(lp->sdev == NULL)
-  {
+	/* Initialize the RFC1051-encap protocol driver */
+	lp->sdev = (struct net_device *) kmalloc(sizeof(struct net_device) + 10, GFP_KERNEL);
+	if (lp->sdev == NULL) {
 #ifdef CONFIG_ARCNET_ETH
-  	if(lp->edev)
-  		kfree(lp->edev);
-  	lp->edev=NULL;
-  	return -ENOMEM;
-#endif 
-  }
-  memcpy(lp->sdev,dev,sizeof(struct net_device));
-  lp->sdev->name=(char *)(lp+1);
-  sprintf(lp->sdev->name,"%ss",dev->name);
-  lp->sdev->init=arcnetS_init;
-  register_netdevice(lp->sdev);
-#endif
-
-  /* Enable TX if we need to */
-  if (lp->en_dis_able_TX)
-    (*lp->en_dis_able_TX)(dev, 1);
-
-  /* make sure we're ready to receive IRQ's.
-   * arcnet_reset sets this for us, but if we receive one before
-   * START is set to 1, it could be ignored.  So, we turn IRQ's
-   * off, then on again to clean out the IRQ controller.
-   */
-
-  AINTMASK(0);
-  udelay(1);	/* give it time to set the mask before
-		 * we reset it again. (may not even be
-		 * necessary)
-		 */
-  SETMASK;
+		if (lp->edev)
+			kfree(lp->edev);
+		lp->edev = NULL;
+		return -ENOMEM;
+#endif
+	}
+	memcpy(lp->sdev, dev, sizeof(struct net_device));
+	lp->sdev->name = (char *) (lp + 1);
+	sprintf(lp->sdev->name, "%ss", dev->name);
+	lp->sdev->init = arcnetS_init;
+	register_netdevice(lp->sdev);
+#endif
+
+	/* Enable TX if we need to */
+	if (lp->en_dis_able_TX)
+		(*lp->en_dis_able_TX) (dev, 1);
+
+	/* make sure we're ready to receive IRQ's.
+	 * arcnet_reset sets this for us, but if we receive one before
+	 * START is set to 1, it could be ignored.  So, we turn IRQ's
+	 * off, then on again to clean out the IRQ controller.
+	 */
 
-  /* Let it increase its use count */
-  (*lp->openclose_device)(1);
+	AINTMASK(0);
+	udelay(1);		/* give it time to set the mask before
+				 * we reset it again. (may not even be
+				 * necessary)
+				 */
+	SETMASK;
+
+	/* Let it increase its use count */
+	(*lp->openclose_device) (1);
 
-  return 0;
+	return 0;
 }
 
 
 /* The inverse routine to arcnet_open - shuts down the card.
  */
-static int
-arcnet_close(struct net_device *dev)
+static int arcnet_close(struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
-  if (test_and_set_bit(0, (int *)&dev->tbusy))
-    BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n");
+	if (test_and_set_bit(0, (int *) &dev->tbusy))
+		BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n");
 
-  dev->start=0;
+	dev->start = 0;
 #ifdef CONFIG_ARCNET_1051
-  lp->sdev->tbusy=1;
-  lp->sdev->start=0;
+	lp->sdev->tbusy = 1;
+	lp->sdev->start = 0;
 #endif
 #ifdef CONFIG_ARCNET_ETH
-  lp->edev->tbusy=1;
-  lp->edev->start=0;
+	lp->edev->tbusy = 1;
+	lp->edev->start = 0;
 #endif
 
-  /* Shut down the card */
+	/* Shut down the card */
 
-  /* Disable TX if we need to */
-  if (lp->en_dis_able_TX)
-    (*lp->en_dis_able_TX)(dev, 0);
+	/* Disable TX if we need to */
+	if (lp->en_dis_able_TX)
+		(*lp->en_dis_able_TX) (dev, 0);
 
-  (*lp->arcnet_reset)(dev, 3);	/* reset IRQ won't run if START=0 */
+	(*lp->arcnet_reset) (dev, 3);	/* reset IRQ won't run if START=0 */
 #if 0
-  lp->intmask=0;
-  SETMASK;		/* no IRQ's (except RESET, of course) */
-  ACOMMAND(NOTXcmd);	/* stop transmit */
-  ACOMMAND(NORXcmd);	/* disable receive */
+	lp->intmask = 0;
+	SETMASK;		/* no IRQ's (except RESET, of course) */
+	ACOMMAND(NOTXcmd);	/* stop transmit */
+	ACOMMAND(NORXcmd);	/* disable receive */
 #endif
 
-  /* reset more flags */
-  dev->interrupt=0;
+	/* reset more flags */
+	dev->interrupt = 0;
 #ifdef CONFIG_ARCNET_ETH
-  lp->edev->interrupt=0;
+	lp->edev->interrupt = 0;
 #endif
 #ifdef CONFIG_ARCNET_1051
-  lp->sdev->interrupt=0;
+	lp->sdev->interrupt = 0;
 #endif
 
-  /* do NOT free lp->adev!!  It's static! */
-  lp->adev=NULL;
+	/* do NOT free lp->adev!!  It's static! */
+	lp->adev = NULL;
 
 #ifdef CONFIG_ARCNET_ETH
-  /* free the ethernet-encap protocol device */
-  lp->edev->priv=NULL;
-  unregister_netdevice(lp->edev);
-  kfree(lp->edev->name);
-  kfree(lp->edev);
-  lp->edev=NULL;
+	/* free the ethernet-encap protocol device */
+	lp->edev->priv = NULL;
+	unregister_netdevice(lp->edev);
+	kfree(lp->edev->name);
+	kfree(lp->edev);
+	lp->edev = NULL;
 #endif
 
 #ifdef CONFIG_ARCNET_1051
-  /* free the RFC1051-encap protocol device */
-  lp->sdev->priv=NULL;
-  unregister_netdevice(lp->sdev);
-  kfree(lp->sdev);
-  lp->sdev=NULL;
+	/* free the RFC1051-encap protocol device */
+	lp->sdev->priv = NULL;
+	unregister_netdevice(lp->sdev);
+	kfree(lp->sdev);
+	lp->sdev = NULL;
 #endif
 
-  /* Update the statistics here. (not necessary in ARCnet) */
+	/* Update the statistics here. (not necessary in ARCnet) */
 
-  /* Decrease the use count */
-  (*lp->openclose_device)(0);
+	/* Decrease the use count */
+	(*lp->openclose_device) (0);
 
-  return 0;
+	return 0;
 }
 
 
@@ -592,241 +587,213 @@
 
 /* Generic error checking routine for arcnet??_send_packet
  */
-static int
-arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev)
+static int arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
-  BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
-	 ARCSTATUS,lp->intx);
+	BUGMSG(D_DURING, "transmit requested (status=%Xh, inTX=%d)\n",
+	       ARCSTATUS, lp->intx);
 
-  if (lp->in_txhandler)
-    {
-      BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n");
-      lp->stats.tx_dropped++;
-      return 1;
-    }
-
-  if (lp->intx>1)
-    {
-      BUGMSG(D_NORMAL,"send_packet called while intx!\n");
-      lp->stats.tx_dropped++;
-      return 1;
-    }
-
-  if (test_bit(0, (int *)&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;
-
-      int status=ARCSTATUS;
-
-      if (tickssofar < TX_TIMEOUT)
-	{
-	  BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
-		 status,tickssofar,lp->outgoing.skb,
-		 lp->outgoing.numsegs,
-		 lp->outgoing.segnum);
-	  return 1;
-	}
-
-      lp->intmask &= ~TXFREEflag;
-      SETMASK;
-
-      if (status&TXFREEflag)	/* transmit _DID_ finish */
-	{
-	  BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
-		 status,tickssofar,lp->intmask,lp->lasttrans_dest);
-	  lp->stats.tx_errors++;
-	}
-      else
-	{
-	  BUGMSG(D_EXTRA,"tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
-		 status,tickssofar,lp->intmask,lp->lasttrans_dest);
-	  lp->stats.tx_errors++;
-	  lp->stats.tx_aborted_errors++;
-
-	  ACOMMAND(NOTXcmd);
-	}
-
-      if (lp->outgoing.skb)
-	{
-	  dev_kfree_skb(lp->outgoing.skb);
-	  lp->stats.tx_dropped++;
+	if (lp->in_txhandler) {
+		BUGMSG(D_NORMAL, "send_packet called while in txhandler!\n");
+		lp->stats.tx_dropped++;
+		return 1;
+	}
+	if (lp->intx > 1) {
+		BUGMSG(D_NORMAL, "send_packet called while intx!\n");
+		lp->stats.tx_dropped++;
+		return 1;
 	}
-      lp->outgoing.skb=NULL;
+	if (test_bit(0, (int *) &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;
+
+		int status = ARCSTATUS;
+
+		if (tickssofar < TX_TIMEOUT) {
+			BUGMSG(D_DURING, "premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
+			       status, tickssofar, lp->outgoing.skb,
+			       lp->outgoing.numsegs,
+			       lp->outgoing.segnum);
+			return 1;
+		}
+		lp->intmask &= ~TXFREEflag;
+		SETMASK;
+
+		if (status & TXFREEflag) {	/* transmit _DID_ finish */
+			BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
+			       status, tickssofar, lp->intmask, lp->lasttrans_dest);
+			lp->stats.tx_errors++;
+		} else {
+			BUGMSG(D_EXTRA, "tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
+			       status, tickssofar, lp->intmask, lp->lasttrans_dest);
+			lp->stats.tx_errors++;
+			lp->stats.tx_aborted_errors++;
+
+			ACOMMAND(NOTXcmd);
+		}
+
+		if (lp->outgoing.skb) {
+			dev_kfree_skb(lp->outgoing.skb);
+			lp->stats.tx_dropped++;
+		}
+		lp->outgoing.skb = NULL;
 
 #ifdef CONFIG_ARCNET_ETH
-      lp->edev->tbusy=0;
+		lp->edev->tbusy = 0;
 #endif
 #ifdef CONFIG_ARCNET_1051
-      lp->sdev->tbusy=0;
+		lp->sdev->tbusy = 0;
 #endif
-      if (!test_and_clear_bit(0,(int *)&dev->tbusy))
-	BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n");
+		if (!test_and_clear_bit(0, (int *) &dev->tbusy))
+			BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n");
 
-      lp->txready=0;
-      lp->sending=0;
+		lp->txready = 0;
+		lp->sending = 0;
 
-      return 1;
-    }
-
-  if (lp->txready)	/* transmit already in progress! */
-    {
-      BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",
-	     ARCSTATUS);
-      lp->intmask &= ~TXFREEflag;
-      SETMASK;
-      ACOMMAND(NOTXcmd); /* abort current send */
-      (*lp->inthandler)(dev); /* fake an interrupt */
-      lp->stats.tx_errors++;
-      lp->stats.tx_fifo_errors++;
-      lp->txready=0;	/* we definitely need this line! */
-
-      return 1;
-    }
-
-  /* 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, (int *)&lp->adev->tbusy))
-    {
-      BUGMSG(D_NORMAL,"transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
-	     ARCSTATUS,lp->intx,jiffies-dev->trans_start);
-      lp->stats.tx_errors++;
-      lp->stats.tx_fifo_errors++;
-      return -EBUSY;
-    }
+		return 1;
+	}
+	if (lp->txready) {	/* transmit already in progress! */
+		BUGMSG(D_NORMAL, "trying to start new packet while busy! (status=%Xh)\n",
+		       ARCSTATUS);
+		lp->intmask &= ~TXFREEflag;
+		SETMASK;
+		ACOMMAND(NOTXcmd);	/* abort current send */
+		(*lp->inthandler) (dev);	/* fake an interrupt */
+		lp->stats.tx_errors++;
+		lp->stats.tx_fifo_errors++;
+		lp->txready = 0;	/* we definitely need this line! */
+
+		return 1;
+	}
+	/* 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, (int *) &lp->adev->tbusy)) {
+		BUGMSG(D_NORMAL, "transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
+		       ARCSTATUS, lp->intx, jiffies - dev->trans_start);
+		lp->stats.tx_errors++;
+		lp->stats.tx_fifo_errors++;
+		return -EBUSY;
+	}
 #ifdef CONFIG_ARCNET_1051
-  lp->sdev->tbusy=1;
+	lp->sdev->tbusy = 1;
 #endif
 #ifdef CONFIG_ARCNET_ETH
-  lp->edev->tbusy=1;
+	lp->edev->tbusy = 1;
 #endif
 
-  return 0;
+	return 0;
 }
 
 
 /* Called by the kernel in order to transmit a packet.
  */
-static int
-arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  int bad,oldmask=0;
-  struct Outgoing *out=&(lp->outgoing);
-
-  lp->intx++;
-
-  oldmask |= lp->intmask;
-  lp->intmask=0;
-  SETMASK;
-
-  bad=arcnet_send_packet_bad(skb,dev);
-  if (bad)
-    {
-      lp->intx--;
-      lp->intmask=oldmask;
-      SETMASK;
-      return bad;
-    }
-
-  /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-
-  lp->intmask = oldmask & ~TXFREEflag;
-  SETMASK;
-
-  out->length = 1 < skb->len ? skb->len : 1;
-  out->hdr=(struct ClientData*)skb->data;
-  out->skb=skb;
-
-  BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-
-  out->hdr->sequence=(lp->sequence++);
-
-  /* fits in one packet? */
-  if (out->length-EXTRA_CLIENTDATA<=XMTU)
-    {
-      BUGMSG(D_DURING,"not splitting %d-byte packet. (split_flag=%d)\n",
-	     out->length,out->hdr->split_flag);
-      if (out->hdr->split_flag)
-	BUGMSG(D_NORMAL,"short packet has split_flag set?! (split_flag=%d)\n",
-	       out->hdr->split_flag);
-      out->numsegs=1;
-      out->segnum=1;
-      (*lp->prepare_tx)(dev,
-			((char *)out->hdr)+EXTRA_CLIENTDATA,
-			sizeof(struct ClientData)-EXTRA_CLIENTDATA,
-			((char *)skb->data)+sizeof(struct ClientData),
-			out->length-sizeof(struct ClientData),
-			out->hdr->daddr,1,0);
-
-      /* done right away */
-      lp->stats.tx_bytes += out->skb->len;
-      dev_kfree_skb(out->skb);
-      out->skb=NULL;
-
-      if (arcnet_go_tx(dev,1))
-	{
-	  /* inform upper layers */
-	  arcnet_tx_done(dev, lp);
-	}
-    }
-  else			/* too big for one - split it */
-    {
-      int maxsegsize=XMTU-4;
-
-      out->data=(u_char *)skb->data
-	+ sizeof(struct ClientData);
-      out->dataleft=out->length-sizeof(struct ClientData);
-      out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
-      out->segnum=0;
-
-      BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
-	     out->length,out->numsegs);
-
-      /* if a packet waiting, launch it */
-      arcnet_go_tx(dev,1);
-
-      if (!lp->txready)
-	{
-	  /* prepare a packet, launch it and prepare
-	   * another.
-	   */
-	  arcnetA_continue_tx(dev);
-	  if (arcnet_go_tx(dev,1))
-	    {
-	      arcnetA_continue_tx(dev);
-	      arcnet_go_tx(dev,1);
-	    }
-	}
-
-      /* if segnum==numsegs, the transmission is finished;
-       * free the skb right away.
-       */
-
-      if (out->segnum==out->numsegs)
-	{
-	  /* transmit completed */
-	  out->segnum++;
-	  if (out->skb)
-	    {
-	      lp->stats.tx_bytes += skb->len;
-	      dev_kfree_skb(out->skb);
-	    }
-	  out->skb=NULL;
-	}
-    }
-
-  dev->trans_start=jiffies;
-  lp->intx--;
-
-  /* make sure we didn't ignore a TX IRQ while we were in here */
-  lp->intmask |= TXFREEflag;
-  SETMASK;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	int bad, oldmask = 0;
+	struct Outgoing *out = &(lp->outgoing);
+
+	lp->intx++;
+
+	oldmask |= lp->intmask;
+	lp->intmask = 0;
+	SETMASK;
 
-  return 0;
+	bad = arcnet_send_packet_bad(skb, dev);
+	if (bad) {
+		lp->intx--;
+		lp->intmask = oldmask;
+		SETMASK;
+		return bad;
+	}
+	/* arcnet_send_packet_pad has already set tbusy - don't bother here. */
+
+	lp->intmask = oldmask & ~TXFREEflag;
+	SETMASK;
+
+	out->length = 1 < skb->len ? skb->len : 1;
+	out->hdr = (struct ClientData *) skb->data;
+	out->skb = skb;
+
+	BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx");
+
+	out->hdr->sequence = (lp->sequence++);
+
+	/* fits in one packet? */
+	if (out->length - EXTRA_CLIENTDATA <= XMTU) {
+		BUGMSG(D_DURING, "not splitting %d-byte packet. (split_flag=%d)\n",
+		       out->length, out->hdr->split_flag);
+		if (out->hdr->split_flag)
+			BUGMSG(D_NORMAL, "short packet has split_flag set?! (split_flag=%d)\n",
+			       out->hdr->split_flag);
+		out->numsegs = 1;
+		out->segnum = 1;
+		(*lp->prepare_tx) (dev,
+				   ((char *) out->hdr) + EXTRA_CLIENTDATA,
+			    sizeof(struct ClientData) - EXTRA_CLIENTDATA,
+		        ((char *) skb->data) + sizeof(struct ClientData),
+				 out->length - sizeof(struct ClientData),
+				   out->hdr->daddr, 1, 0);
+
+		/* done right away */
+		lp->stats.tx_bytes += out->skb->len;
+		dev_kfree_skb(out->skb);
+		out->skb = NULL;
+
+		if (arcnet_go_tx(dev, 1)) {
+			/* inform upper layers */
+			arcnet_tx_done(dev, lp);
+		}
+	} else {		/* too big for one - split it */
+		int maxsegsize = XMTU - 4;
+
+		out->data = (u_char *) skb->data
+		    + sizeof(struct ClientData);
+		out->dataleft = out->length - sizeof(struct ClientData);
+		out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize;
+		out->segnum = 0;
+
+		BUGMSG(D_TX, "packet (%d bytes) split into %d fragments:\n",
+		       out->length, out->numsegs);
+
+		/* if a packet waiting, launch it */
+		arcnet_go_tx(dev, 1);
+
+		if (!lp->txready) {
+			/* prepare a packet, launch it and prepare
+			 * another.
+			 */
+			arcnetA_continue_tx(dev);
+			if (arcnet_go_tx(dev, 1)) {
+				arcnetA_continue_tx(dev);
+				arcnet_go_tx(dev, 1);
+			}
+		}
+		/* if segnum==numsegs, the transmission is finished;
+		 * free the skb right away.
+		 */
+
+		if (out->segnum == out->numsegs) {
+			/* transmit completed */
+			out->segnum++;
+			if (out->skb) {
+				lp->stats.tx_bytes += skb->len;
+				dev_kfree_skb(out->skb);
+			}
+			out->skb = NULL;
+		}
+	}
+
+	dev->trans_start = jiffies;
+	lp->intx--;
+
+	/* make sure we didn't ignore a TX IRQ while we were in here */
+	lp->intmask |= TXFREEflag;
+	SETMASK;
+
+	return 0;
 }
 
 
@@ -836,44 +803,41 @@
  */
 void arcnetA_continue_tx(struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  int maxsegsize=XMTU-4;
-  struct Outgoing *out=&(lp->outgoing);
-
-  BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
-	 ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask);
-
-  if (lp->txready)
-    {
-      BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");
-      return;
-    }
-
-  if (out->segnum>=out->numsegs)
-    {
-      BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n",
-	     out->segnum+1,out->numsegs);
-    }
-
-  if (!out->segnum)	/* first packet */
-    out->hdr->split_flag=((out->numsegs-2)<<1)+1;
-  else
-    out->hdr->split_flag=out->segnum<<1;
-
-  out->seglen=maxsegsize;
-  if (out->seglen>out->dataleft) out->seglen=out->dataleft;
-
-  BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
-	 out->segnum+1,out->seglen,out->numsegs,
-	 out->length,out->hdr->split_flag);
-
-  (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,
-		    sizeof(struct ClientData)-EXTRA_CLIENTDATA,
-		    out->data,out->seglen,out->hdr->daddr,1,0);
-
-  out->dataleft-=out->seglen;
-  out->data+=out->seglen;
-  out->segnum++;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	int maxsegsize = XMTU - 4;
+	struct Outgoing *out = &(lp->outgoing);
+
+	BUGMSG(D_DURING, "continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
+	       ARCSTATUS, lp->intx, lp->in_txhandler, lp->intmask);
+
+	if (lp->txready) {
+		BUGMSG(D_NORMAL, "continue_tx: called with packet in buffer!\n");
+		return;
+	}
+	if (out->segnum >= out->numsegs) {
+		BUGMSG(D_NORMAL, "continue_tx: building segment %d of %d!\n",
+		       out->segnum + 1, out->numsegs);
+	}
+	if (!out->segnum)	/* first packet */
+		out->hdr->split_flag = ((out->numsegs - 2) << 1) + 1;
+	else
+		out->hdr->split_flag = out->segnum << 1;
+
+	out->seglen = maxsegsize;
+	if (out->seglen > out->dataleft)
+		out->seglen = out->dataleft;
+
+	BUGMSG(D_TX, "building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
+	       out->segnum + 1, out->seglen, out->numsegs,
+	       out->length, out->hdr->split_flag);
+
+	(*lp->prepare_tx) (dev, ((char *) out->hdr) + EXTRA_CLIENTDATA,
+			   sizeof(struct ClientData) - EXTRA_CLIENTDATA,
+			   out->data, out->seglen, out->hdr->daddr, 1, 0);
+
+	out->dataleft -= out->seglen;
+	out->data += out->seglen;
+	out->segnum++;
 }
 
 
@@ -887,36 +851,34 @@
  * to the card; TXFREEflag is always OR'ed into the memory variable either
  * way.
  */
-int arcnet_go_tx(struct net_device *dev,int enable_irq)
+int arcnet_go_tx(struct net_device *dev, int enable_irq)
 {
-	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
-	BUGMSG(D_DURING,"go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",
-		ARCSTATUS,lp->intmask,lp->txready,lp->sending);
+	BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",
+	       ARCSTATUS, lp->intmask, lp->txready, lp->sending);
 
-	if (lp->sending || !lp->txready)
-	{
-		if (enable_irq && lp->sending)
-		{
+	if (lp->sending || !lp->txready) {
+		if (enable_irq && lp->sending) {
 			lp->intmask |= TXFREEflag;
 			SETMASK;
 		}
 		return 0;
 	}
-
 	/* start sending */
-	ACOMMAND(TXcmd|(lp->txready<<3));
+	ACOMMAND(TXcmd | (lp->txready << 3));
 
 	lp->stats.tx_packets++;
-	lp->txready=0;
+	lp->txready = 0;
 	lp->sending++;
 
-	lp->lasttrans_dest=lp->lastload_dest;
-	lp->lastload_dest=0;
+	lp->lasttrans_dest = lp->lastload_dest;
+	lp->lastload_dest = 0;
 
 	lp->intmask |= TXFREEflag;
 
-	if (enable_irq)	SETMASK;
+	if (enable_irq)
+		SETMASK;
 
 	return 1;
 }
@@ -933,85 +895,75 @@
  * interrupts. Establish which device needs attention, and call the correct
  * chipset interrupt handler.
  */
-void
-arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
+void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct arcnet_local *lp;
 
-	if (dev==NULL)
-	  {
-	    BUGMSG(D_DURING, "arcnet: irq %d for unknown device.\n", irq);
-	    return;
-	  }
-
-	BUGMSG(D_DURING,"in arcnet_interrupt\n");
-
-	lp=(struct arcnet_local *)dev->priv;
-	if (!lp)
-	  {
-	    BUGMSG(D_DURING, "arcnet: irq ignored.\n");
-	    return;
-	  }
+	if (dev == NULL) {
+		BUGMSG(D_DURING, "arcnet: irq %d for unknown device.\n", irq);
+		return;
+	}
+	BUGMSG(D_DURING, "in arcnet_interrupt\n");
 
+	lp = (struct arcnet_local *) dev->priv;
+	if (!lp) {
+		BUGMSG(D_DURING, "arcnet: irq ignored.\n");
+		return;
+	}
 	/* RESET flag was enabled - if !dev->start, we must clear it right
 	 * away (but nothing else) since inthandler() is never called.
 	 */
 
-	if (!dev->start)
-	  {
-	    if (ARCSTATUS & RESETflag)
-	      ACOMMAND(CFLAGScmd|RESETclear);
-	    return;
-	  }
-
-
-	if (test_and_set_bit(0, (int *)&dev->interrupt))
-	  {
-	    BUGMSG(D_NORMAL,"DRIVER PROBLEM!  Nested arcnet interrupts!\n");
-	    return;	/* don't even try. */
-	  }
+	if (!dev->start) {
+		if (ARCSTATUS & RESETflag)
+			ACOMMAND(CFLAGScmd | RESETclear);
+		return;
+	}
+	if (test_and_set_bit(0, (int *) &dev->interrupt)) {
+		BUGMSG(D_NORMAL, "DRIVER PROBLEM!  Nested arcnet interrupts!\n");
+		return;		/* don't even try. */
+	}
 #ifdef CONFIG_ARCNET_1051
 	if (lp->sdev)
-	  lp->sdev->interrupt=1;
+		lp->sdev->interrupt = 1;
 #endif
 #ifdef CONFIG_ARCNET_ETH
 	if (lp->edev)
-	  lp->edev->interrupt=1;
+		lp->edev->interrupt = 1;
 #endif
 
 	/* Call the "real" interrupt handler. */
-	(*lp->inthandler)(dev);
+	(*lp->inthandler) (dev);
 
 #ifdef CONFIG_ARCNET_ETH
 	if (lp->edev)
-	  lp->edev->interrupt=0;
+		lp->edev->interrupt = 0;
 #endif
 #ifdef CONFIG_ARCNET_1051
 	if (lp->sdev)
-	  lp->sdev->interrupt=0;
+		lp->sdev->interrupt = 0;
 #endif
-	if (!test_and_clear_bit(0, (int *)&dev->interrupt))
-	  BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n");
+	if (!test_and_clear_bit(0, (int *) &dev->interrupt))
+		BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n");
 
 }
 
 void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp)
 {
-  if (dev->tbusy)
-    {
+	if (dev->tbusy) {
 #ifdef CONFIG_ARCNET_ETH
-      lp->edev->tbusy=0;
+		lp->edev->tbusy = 0;
 #endif
 #ifdef CONFIG_ARCNET_1051
-      lp->sdev->tbusy=0;
+		lp->sdev->tbusy = 0;
 #endif
-      if (!test_and_clear_bit(0, (int *)&dev->tbusy))
-	BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"
-	       " flag!\n");
+		if (!test_and_clear_bit(0, (int *) &dev->tbusy))
+			BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"
+			       " flag!\n");
 
-      mark_bh(NET_BH);
-    }
+		mark_bh(NET_BH);
+	}
 }
 
 
@@ -1026,53 +978,52 @@
  * protocol ID found.
  */
 
-void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr)
+void arcnet_rx(struct arcnet_local *lp, u_char * arcsoft, short length, int saddr, int daddr)
 {
-  struct net_device *dev=lp->adev;
+	struct net_device *dev = lp->adev;
 
-  BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
-	 saddr,daddr,length);
+	BUGMSG(D_DURING, "received packet from %02Xh to %02Xh (%d bytes)\n",
+	       saddr, daddr, length);
 
-  /* call the right receiver for the protocol */
-  switch (arcsoft[0])
-    {
-    case ARC_P_IP:
-    case ARC_P_ARP:
-    case ARC_P_RARP:
-    case ARC_P_IPX:
-    case ARC_P_NOVELL_EC:
-      arcnetA_rx(lp->adev,arcsoft,length,saddr,daddr);
-      break;
+	/* call the right receiver for the protocol */
+	switch (arcsoft[0]) {
+	case ARC_P_IP:
+	case ARC_P_ARP:
+	case ARC_P_RARP:
+	case ARC_P_IPX:
+	case ARC_P_NOVELL_EC:
+		arcnetA_rx(lp->adev, arcsoft, length, saddr, daddr);
+		break;
 #ifdef CONFIG_ARCNET_ETH
-    case ARC_P_ETHER:
-      arcnetE_rx(lp->edev,arcsoft,length,saddr,daddr);
-      break;
+	case ARC_P_ETHER:
+		arcnetE_rx(lp->edev, arcsoft, length, saddr, daddr);
+		break;
 #endif
 #ifdef CONFIG_ARCNET_1051
-    case ARC_P_IP_RFC1051:
-    case ARC_P_ARP_RFC1051:
-      arcnetS_rx(lp->sdev,arcsoft,length,saddr,daddr);
-      break;
-#endif
-    case ARC_P_DATAPOINT_BOOT:
-    case ARC_P_DATAPOINT_MOUNT:
-      break;
-    case ARC_P_POWERLAN_BEACON:
-    case ARC_P_POWERLAN_BEACON2:
-      break;
-    case ARC_P_LANSOFT: /* don't understand.  fall through. */
-    default:
-      BUGMSG(D_EXTRA,"received unknown protocol %d (%Xh) from station %d.\n",
-	     arcsoft[0],arcsoft[0],saddr);
-      lp->stats.rx_errors++;
-      lp->stats.rx_crc_errors++;
-      break;
-    }
-
-  /* If any worth-while packets have been received, a mark_bh(NET_BH)
-   * has been done by netif_rx and Linux will handle them after we
-   * return.
-   */
+	case ARC_P_IP_RFC1051:
+	case ARC_P_ARP_RFC1051:
+		arcnetS_rx(lp->sdev, arcsoft, length, saddr, daddr);
+		break;
+#endif
+	case ARC_P_DATAPOINT_BOOT:
+	case ARC_P_DATAPOINT_MOUNT:
+		break;
+	case ARC_P_POWERLAN_BEACON:
+	case ARC_P_POWERLAN_BEACON2:
+		break;
+	case ARC_P_LANSOFT:	/* don't understand.  fall through. */
+	default:
+		BUGMSG(D_EXTRA, "received unknown protocol %d (%Xh) from station %d.\n",
+		       arcsoft[0], arcsoft[0], saddr);
+		lp->stats.rx_errors++;
+		lp->stats.rx_crc_errors++;
+		break;
+	}
+
+	/* If any worth-while packets have been received, a mark_bh(NET_BH)
+	 * has been done by netif_rx and Linux will handle them after we
+	 * return.
+	 */
 
 
 }
@@ -1081,275 +1032,238 @@
 
 /* Packet receiver for "standard" RFC1201-style packets
  */
-static void
-arcnetA_rx(struct net_device *dev,u_char *buf,
-	   int length, u_char saddr, u_char daddr)
-{
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  struct sk_buff *skb;
-  struct ClientData *arcsoft,*soft;
-
-  BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n",
-	 length);
-
-  /* compensate for EXTRA_CLIENTDATA (which isn't actually in the
-   * packet)
-   */
-  arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA);
-  length+=EXTRA_CLIENTDATA;
-
-  if (arcsoft->split_flag==0xFF)  /* Exception Packet */
-    {
-      BUGMSG(D_DURING,"compensating for exception packet\n");
-
-      /* skip over 4-byte junkola */
-      arcsoft=(struct ClientData *)
-	((u_char *)arcsoft + 4);
-      length-=4;
-    }
-
-  if (!arcsoft->split_flag)		/* not split */
-    {
-      struct Incoming *in=&lp->incoming[saddr];
-
-      BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n",
-	     arcsoft->split_flag);
-
-      if (in->skb)	/* already assembling one! */
-	{
-	  BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
-		 in->sequence,arcsoft->split_flag,
-		 arcsoft->sequence);
-	  lp->aborted_seq=arcsoft->sequence;
-	  kfree_skb(in->skb);
-	  lp->stats.rx_errors++;
-	  lp->stats.rx_missed_errors++;
-	  in->skb=NULL;
-	}
-
-      in->sequence=arcsoft->sequence;
-
-      skb = alloc_skb(length, GFP_ATOMIC);
-      if (skb == NULL) {
-	BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
-	lp->stats.rx_dropped++;
-	return;
-      }
-      soft=(struct ClientData *)skb->data;
-
-      skb_put(skb,length);
-      skb->dev = dev;
-
-      memcpy((u_char *)soft+EXTRA_CLIENTDATA,
-	     (u_char *)arcsoft+EXTRA_CLIENTDATA,
-	     length-EXTRA_CLIENTDATA);
-      soft->daddr=daddr;
-      soft->saddr=saddr;
-
-      /* ARP packets have problems when sent from DOS.
-       * source address is always 0 on some systems!  So we take
-       * the hardware source addr (which is impossible to fumble)
-       * and insert it ourselves.
-       */
-      if (soft->protocol_id == ARC_P_ARP)
-	{
-	  struct arphdr *arp=(struct arphdr *)
-	    ((char *)soft+sizeof(struct ClientData));
-
-	  /* make sure addresses are the right length */
-	  if (arp->ar_hln==1 && arp->ar_pln==4)
-	    {
-	      char *cptr=(char *)(arp)+sizeof(struct arphdr);
-
-	      if (!*cptr)	/* is saddr = 00? */
-		{
-		  BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n",
-			 saddr);
-		  lp->stats.rx_crc_errors++;
-		  *cptr=saddr;
+static void arcnetA_rx(struct net_device *dev, u_char * buf,
+		       int length, u_char saddr, u_char daddr)
+{
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct sk_buff *skb;
+	struct ClientData *arcsoft, *soft;
+
+	BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n",
+	       length);
+
+	/* compensate for EXTRA_CLIENTDATA (which isn't actually in the
+	 * packet)
+	 */
+	arcsoft = (struct ClientData *) (buf - EXTRA_CLIENTDATA);
+	length += EXTRA_CLIENTDATA;
+
+	if (arcsoft->split_flag == 0xFF) {	/* Exception Packet */
+		BUGMSG(D_DURING, "compensating for exception packet\n");
+
+		/* skip over 4-byte junkola */
+		arcsoft = (struct ClientData *)
+		    ((u_char *) arcsoft + 4);
+		length -= 4;
+	}
+	if (!arcsoft->split_flag) {	/* not split */
+		struct Incoming *in = &lp->incoming[saddr];
+
+		BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n",
+		       arcsoft->split_flag);
+
+		if (in->skb) {	/* already assembling one! */
+			BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+			       in->sequence, arcsoft->split_flag,
+			       arcsoft->sequence);
+			lp->aborted_seq = arcsoft->sequence;
+			kfree_skb(in->skb);
+			lp->stats.rx_errors++;
+			lp->stats.rx_missed_errors++;
+			in->skb = NULL;
 		}
-	      else
-		{
-		  BUGMSG(D_DURING,"ARP source address (%Xh) is fine.\n",
-			 *cptr);
+		in->sequence = arcsoft->sequence;
+
+		skb = alloc_skb(length, GFP_ATOMIC);
+		if (skb == NULL) {
+			BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+			lp->stats.rx_dropped++;
+			return;
 		}
-	    }
-	  else
-	    {
-	      BUGMSG(D_NORMAL,"funny-shaped ARP packet. (%Xh, %Xh)\n",
-		     arp->ar_hln,arp->ar_pln);
-	      lp->stats.rx_errors++;
-	      lp->stats.rx_crc_errors++;
-	    }
-	}
-
-      BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
-      lp->stats.rx_bytes += skb->len;
-      skb->protocol=arcnetA_type_trans(skb,dev);
-      netif_rx(skb);
-    }
-  else			/* split packet */
-    {
-      /* NOTE:  MSDOS ARP packet correction should only need to
-       * apply to unsplit packets, since ARP packets are so short.
-       *
-       * My interpretation of the RFC1201 (ARCnet) document is that
-       * if a packet is received out of order, the entire assembly
-       * process should be aborted.
-       *
-       * The RFC also mentions "it is possible for successfully
-       * received packets to be retransmitted."  As of 0.40 all
-       * previously received packets are allowed, not just the
-       * most recent one.
-       *
-       * We allow multiple assembly processes, one for each
-       * ARCnet card possible on the network.  Seems rather like
-       * a waste of memory.  Necessary?
-       */
-
-      struct Incoming *in=&lp->incoming[saddr];
-
-      BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n",
-	     arcsoft->split_flag,in->sequence);
-
-      if (in->skb && in->sequence!=arcsoft->sequence)
-	{
-	  BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
-		 saddr,in->sequence,arcsoft->sequence,
-		 arcsoft->split_flag);
-	  kfree_skb(in->skb);
-	  in->skb=NULL;
-	  lp->stats.rx_errors++;
-	  lp->stats.rx_missed_errors++;
-	  in->lastpacket=in->numpackets=0;
-	}
-
-      if (arcsoft->split_flag & 1)	/* first packet in split */
-	{
-	  BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n",
-		 arcsoft->split_flag);
-	  if (in->skb)	/* already assembling one! */
-	    {
-	      BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
-		     in->sequence,arcsoft->split_flag,
-		     arcsoft->sequence);
-	      lp->stats.rx_errors++;
-	      lp->stats.rx_missed_errors++;
-	      kfree_skb(in->skb);
-	    }
-
-	  in->sequence=arcsoft->sequence;
-	  in->numpackets=((unsigned)arcsoft->split_flag>>1)+2;
-	  in->lastpacket=1;
-
-	  if (in->numpackets>16)
-	    {
-	      BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
-		     arcsoft->split_flag);
-	      lp->stats.rx_errors++;
-	      lp->stats.rx_length_errors++;
-	      return;
-	    }
-
-	  in->skb=skb=alloc_skb(508*in->numpackets
-				+ sizeof(struct ClientData),
-				GFP_ATOMIC);
-	  if (skb == NULL) {
-	    BUGMSG(D_NORMAL,"(split) memory squeeze, dropping packet.\n");
-	    lp->stats.rx_dropped++;
-	    return;
-	  }
-
-	  soft=(struct ClientData *)skb->data;
-
-	  skb_put(skb,sizeof(struct ClientData));
-	  skb->dev=dev;
-
-	  memcpy((u_char *)soft+EXTRA_CLIENTDATA,
-		 (u_char *)arcsoft+EXTRA_CLIENTDATA,
-		 sizeof(struct ClientData)-EXTRA_CLIENTDATA);
-	  soft->split_flag=0; /* final packet won't be split */
-	}
-      else			/* not first packet */
-	{
-	  int packetnum=((unsigned)arcsoft->split_flag>>1) + 1;
-
-	  /* if we're not assembling, there's no point
-	   * trying to continue.
-	   */
-	  if (!in->skb)
-	    {
-	      if (lp->aborted_seq != arcsoft->sequence)
-		{
-		  BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n",
-			 arcsoft->split_flag,arcsoft->sequence, lp->aborted_seq);
-		  lp->stats.rx_errors++;
-		  lp->stats.rx_missed_errors++;
+		soft = (struct ClientData *) skb->data;
+
+		skb_put(skb, length);
+		skb->dev = dev;
+
+		memcpy((u_char *) soft + EXTRA_CLIENTDATA,
+		       (u_char *) arcsoft + EXTRA_CLIENTDATA,
+		       length - EXTRA_CLIENTDATA);
+		soft->daddr = daddr;
+		soft->saddr = saddr;
+
+		/* ARP packets have problems when sent from DOS.
+		 * source address is always 0 on some systems!  So we take
+		 * the hardware source addr (which is impossible to fumble)
+		 * and insert it ourselves.
+		 */
+		if (soft->protocol_id == ARC_P_ARP) {
+			struct arphdr *arp = (struct arphdr *)
+			((char *) soft + sizeof(struct ClientData));
+
+			/* make sure addresses are the right length */
+			if (arp->ar_hln == 1 && arp->ar_pln == 4) {
+				char *cptr = (char *) (arp) + sizeof(struct arphdr);
+
+				if (!*cptr) {	/* is saddr = 00? */
+					BUGMSG(D_EXTRA, "ARP source address was 00h, set to %02Xh.\n",
+					       saddr);
+					lp->stats.rx_crc_errors++;
+					*cptr = saddr;
+				} else {
+					BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n",
+					       *cptr);
+				}
+			} else {
+				BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n",
+				       arp->ar_hln, arp->ar_pln);
+				lp->stats.rx_errors++;
+				lp->stats.rx_crc_errors++;
+			}
 		}
-	      return;
-	    }
+		BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+
+		lp->stats.rx_bytes += skb->len;
+		skb->protocol = arcnetA_type_trans(skb, dev);
+		netif_rx(skb);
+	} else {		/* split packet */
+		/* NOTE:  MSDOS ARP packet correction should only need to
+		 * apply to unsplit packets, since ARP packets are so short.
+		 *
+		 * My interpretation of the RFC1201 (ARCnet) document is that
+		 * if a packet is received out of order, the entire assembly
+		 * process should be aborted.
+		 *
+		 * The RFC also mentions "it is possible for successfully
+		 * received packets to be retransmitted."  As of 0.40 all
+		 * previously received packets are allowed, not just the
+		 * most recent one.
+		 *
+		 * We allow multiple assembly processes, one for each
+		 * ARCnet card possible on the network.  Seems rather like
+		 * a waste of memory.  Necessary?
+		 */
+
+		struct Incoming *in = &lp->incoming[saddr];
 
-	  in->lastpacket++;
-	  if (packetnum!=in->lastpacket) /* not the right flag! */
-	    {
-	      /* harmless duplicate? ignore. */
-	      if (packetnum<=in->lastpacket-1)
-		{
-		  BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n",
-			 arcsoft->split_flag);
-		  lp->stats.rx_errors++;
-		  lp->stats.rx_frame_errors++;
-		  return;
+		BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n",
+		       arcsoft->split_flag, in->sequence);
+
+		if (in->skb && in->sequence != arcsoft->sequence) {
+			BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
+			       saddr, in->sequence, arcsoft->sequence,
+			       arcsoft->split_flag);
+			kfree_skb(in->skb);
+			in->skb = NULL;
+			lp->stats.rx_errors++;
+			lp->stats.rx_missed_errors++;
+			in->lastpacket = in->numpackets = 0;
+		}
+		if (arcsoft->split_flag & 1) {	/* first packet in split */
+			BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n",
+			       arcsoft->split_flag);
+			if (in->skb) {	/* already assembling one! */
+				BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+				       in->sequence, arcsoft->split_flag,
+				       arcsoft->sequence);
+				lp->stats.rx_errors++;
+				lp->stats.rx_missed_errors++;
+				kfree_skb(in->skb);
+			}
+			in->sequence = arcsoft->sequence;
+			in->numpackets = ((unsigned) arcsoft->split_flag >> 1) + 2;
+			in->lastpacket = 1;
+
+			if (in->numpackets > 16) {
+				BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+				       arcsoft->split_flag);
+				lp->stats.rx_errors++;
+				lp->stats.rx_length_errors++;
+				return;
+			}
+			in->skb = skb = alloc_skb(508 * in->numpackets
+					     + sizeof(struct ClientData),
+						  GFP_ATOMIC);
+			if (skb == NULL) {
+				BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n");
+				lp->stats.rx_dropped++;
+				return;
+			}
+			soft = (struct ClientData *) skb->data;
+
+			skb_put(skb, sizeof(struct ClientData));
+			skb->dev = dev;
+
+			memcpy((u_char *) soft + EXTRA_CLIENTDATA,
+			       (u_char *) arcsoft + EXTRA_CLIENTDATA,
+			   sizeof(struct ClientData) - EXTRA_CLIENTDATA);
+			soft->split_flag = 0;	/* final packet won't be split */
+		} else {	/* not first packet */
+			int packetnum = ((unsigned) arcsoft->split_flag >> 1) + 1;
+
+			/* if we're not assembling, there's no point
+			 * trying to continue.
+			 */
+			if (!in->skb) {
+				if (lp->aborted_seq != arcsoft->sequence) {
+					BUGMSG(D_EXTRA, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n",
+					       arcsoft->split_flag, arcsoft->sequence, lp->aborted_seq);
+					lp->stats.rx_errors++;
+					lp->stats.rx_missed_errors++;
+				}
+				return;
+			}
+			in->lastpacket++;
+			if (packetnum != in->lastpacket) {	/* not the right flag! */
+				/* harmless duplicate? ignore. */
+				if (packetnum <= in->lastpacket - 1) {
+					BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n",
+					       arcsoft->split_flag);
+					lp->stats.rx_errors++;
+					lp->stats.rx_frame_errors++;
+					return;
+				}
+				/* "bad" duplicate, kill reassembly */
+				BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
+				       in->sequence, arcsoft->split_flag,
+				       arcsoft->sequence);
+				lp->aborted_seq = arcsoft->sequence;
+				kfree_skb(in->skb);
+				in->skb = NULL;
+				lp->stats.rx_errors++;
+				lp->stats.rx_missed_errors++;
+				in->lastpacket = in->numpackets = 0;
+				return;
+			}
+			soft = (struct ClientData *) in->skb->data;
 		}
 
-	      /* "bad" duplicate, kill reassembly */
-	      BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
-		     in->sequence,arcsoft->split_flag,
-		     arcsoft->sequence);
-	      lp->aborted_seq=arcsoft->sequence;
-	      kfree_skb(in->skb);
-	      in->skb=NULL;
-	      lp->stats.rx_errors++;
-	      lp->stats.rx_missed_errors++;
-	      in->lastpacket=in->numpackets=0;
-	      return;
-	    }
-
-	  soft=(struct ClientData *)in->skb->data;
-	}
-
-      skb=in->skb;
-
-      memcpy(skb->data+skb->len,
-	     (u_char *)arcsoft+sizeof(struct ClientData),
-	     length-sizeof(struct ClientData));
-      skb_put(skb,length-sizeof(struct ClientData));
-
-      soft->daddr=daddr;
-      soft->saddr=saddr;
-
-      /* are we done? */
-      if (in->lastpacket == in->numpackets)
-	{
-	  if (!skb || !in->skb)
-	    {
-	      BUGMSG(D_NORMAL,"?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
-		     skb,in->skb);
-	    }
-	  else
-	    {
-	      in->skb=NULL;
-	      in->lastpacket=in->numpackets=0;
-
-	      BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
-	      lp->stats.rx_bytes += skb->len;
-	      skb->protocol=arcnetA_type_trans(skb,dev);
-	      netif_rx(skb);
-	    }
+		skb = in->skb;
+
+		memcpy(skb->data + skb->len,
+		       (u_char *) arcsoft + sizeof(struct ClientData),
+		       length - sizeof(struct ClientData));
+		skb_put(skb, length - sizeof(struct ClientData));
+
+		soft->daddr = daddr;
+		soft->saddr = saddr;
+
+		/* are we done? */
+		if (in->lastpacket == in->numpackets) {
+			if (!skb || !in->skb) {
+				BUGMSG(D_NORMAL, "?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
+				       skb, in->skb);
+			} else {
+				in->skb = NULL;
+				in->lastpacket = in->numpackets = 0;
+
+				BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+
+				lp->stats.rx_bytes += skb->len;
+				skb->protocol = arcnetA_type_trans(skb, dev);
+				netif_rx(skb);
+			}
+		}
 	}
-    }
 }
 
 
@@ -1359,89 +1273,86 @@
  *                                                                          *
  ****************************************************************************/
 
-/* Get the current statistics.	This may be called with the card open or
+/* Get the current statistics.  This may be called with the card open or
  * closed.
  */
 
 static struct net_device_stats *arcnet_get_stats(struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
-  return &lp->stats;
+	return &lp->stats;
 }
 
 
 /* Create the ARCnet ClientData header for an arbitrary protocol layer
- *
- * saddr=NULL	means use device source address (always will anyway)
- * daddr=NULL	means leave destination address (eg unresolved arp)
+
+ * saddr=NULL   means use device source address (always will anyway)
+ * daddr=NULL   means leave destination address (eg unresolved arp)
  */
-static int arcnetA_header(struct sk_buff *skb,struct net_device *dev,
-			  unsigned short type,void *daddr,void *saddr,unsigned len)
+static int arcnetA_header(struct sk_buff *skb, struct net_device *dev,
+	     unsigned short type, void *daddr, void *saddr, unsigned len)
 {
-  struct ClientData *head = (struct ClientData *)
-    skb_push(skb,dev->hard_header_len);
-  struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
-  BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n",
-	 saddr ? *(u_char*)saddr : -1,
-	 daddr ? *(u_char*)daddr : -1,
-	 type,type,len);
-
-  /* set the protocol ID according to RFC1201 */
-  switch(type)
-    {
-    case ETH_P_IP:
-      head->protocol_id=ARC_P_IP;
-      break;
-    case ETH_P_ARP:
-      head->protocol_id=ARC_P_ARP;
-      break;
-    case ETH_P_RARP:
-      head->protocol_id=ARC_P_RARP;
-      break;
-    case ETH_P_IPX:
-    case ETH_P_802_3:
-    case ETH_P_802_2:
-      head->protocol_id=ARC_P_IPX;
-      break;
-    case ETH_P_ATALK:
-      head->protocol_id=ARC_P_ATALK;
-      break;
-    default:
-      BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
-	     type,type);
-      lp->stats.tx_errors++;
-      lp->stats.tx_aborted_errors++;
-      return 0;
-    }
-
-  /*
-   * Set the source hardware address.
-   *
-   * This is pretty pointless for most purposes, but it can help
-   * in debugging.  saddr is stored in the ClientData header and
-   * removed before sending the packet (since ARCnet does not allow
-   * us to change the source address in the actual packet sent)
-   */
-  if(saddr)
-    head->saddr=((u_char*)saddr)[0];
-  else
-    head->saddr=((u_char*)(dev->dev_addr))[0];
-
-  head->split_flag=0;	/* split packets are done elsewhere */
-  head->sequence=0;	/* so are sequence numbers */
-
-  /* supposedly if daddr is NULL, we should ignore it... */
-  if(daddr)
-    {
-      head->daddr=((u_char*)daddr)[0];
-      return dev->hard_header_len;
-    }
-  else
-    head->daddr=0;	/* better fill one in anyway */
+	struct ClientData *head = (struct ClientData *)
+	skb_push(skb, dev->hard_header_len);
+	struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+	BUGMSG(D_DURING, "create header from %d to %d; protocol %d (%Xh); size %u.\n",
+	       saddr ? *(u_char *) saddr : -1,
+	       daddr ? *(u_char *) daddr : -1,
+	       type, type, len);
+
+	/* set the protocol ID according to RFC1201 */
+	switch (type) {
+	case ETH_P_IP:
+		head->protocol_id = ARC_P_IP;
+		break;
+	case ETH_P_ARP:
+		head->protocol_id = ARC_P_ARP;
+		break;
+	case ETH_P_RARP:
+		head->protocol_id = ARC_P_RARP;
+		break;
+	case ETH_P_IPX:
+	case ETH_P_802_3:
+	case ETH_P_802_2:
+		head->protocol_id = ARC_P_IPX;
+		break;
+	case ETH_P_ATALK:
+		head->protocol_id = ARC_P_ATALK;
+		break;
+	default:
+		BUGMSG(D_NORMAL, "I don't understand protocol %d (%Xh)\n",
+		       type, type);
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+		return 0;
+	}
+
+	/*
+	 * Set the source hardware address.
+	 *
+	 * This is pretty pointless for most purposes, but it can help
+	 * in debugging.  saddr is stored in the ClientData header and
+	 * removed before sending the packet (since ARCnet does not allow
+	 * us to change the source address in the actual packet sent)
+	 */
+	if (saddr)
+		head->saddr = ((u_char *) saddr)[0];
+	else
+		head->saddr = ((u_char *) (dev->dev_addr))[0];
+
+	head->split_flag = 0;	/* split packets are done elsewhere */
+	head->sequence = 0;	/* so are sequence numbers */
+
+	/* supposedly if daddr is NULL, we should ignore it... */
+	if (daddr) {
+		head->daddr = ((u_char *) daddr)[0];
+		return dev->hard_header_len;
+	} else
+		head->daddr = 0;	/* better fill one in anyway */
 
-  return -dev->hard_header_len;
+	return -dev->hard_header_len;
 }
 
 
@@ -1451,86 +1362,84 @@
  */
 static int arcnetA_rebuild_header(struct sk_buff *skb)
 {
-  struct ClientData *head = (struct ClientData *)skb->data;
-  struct net_device *dev=skb->dev;
-  struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
+	struct ClientData *head = (struct ClientData *) skb->data;
+	struct net_device *dev = skb->dev;
+	struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
 #ifdef CONFIG_INET
-  int status;
+	int status;
 #endif
 
-  /*
-   * Only ARP and IP are currently supported
-   *
-   * FIXME: Anyone want to spec IPv6 over ARCnet ?
-   */
-
-  if(head->protocol_id != ARC_P_IP)
-    {
-      BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
-	     head->protocol_id,head->protocol_id);
-      lp->stats.tx_errors++;
-      lp->stats.tx_aborted_errors++;
-      head->daddr=0;
-      /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
-      return 0;
-    }
-
-  /*
-   * Try to get ARP to resolve the header.
-   */
+	/*
+	 * Only ARP and IP are currently supported
+	 *
+	 * FIXME: Anyone want to spec IPv6 over ARCnet ?
+	 */
+
+	if (head->protocol_id != ARC_P_IP) {
+		BUGMSG(D_NORMAL, "I don't understand protocol type %d (%Xh) addresses!\n",
+		       head->protocol_id, head->protocol_id);
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+		head->daddr = 0;
+		/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len); */
+		return 0;
+	}
+	/*
+	 * Try to get ARP to resolve the header.
+	 */
 #ifdef CONFIG_INET
-  BUGMSG(D_DURING,"rebuild header from %d to %d; protocol %Xh\n",
-	 head->saddr,head->daddr,head->protocol_id);
-  status=arp_find(&(head->daddr),skb)? 1 : 0;
-  BUGMSG(D_DURING," rebuilt: from %d to %d; protocol %Xh\n",
-	 head->saddr,head->daddr,head->protocol_id);
-  return status;
+	BUGMSG(D_DURING, "rebuild header from %d to %d; protocol %Xh\n",
+	       head->saddr, head->daddr, head->protocol_id);
+	status = arp_find(&(head->daddr), skb) ? 1 : 0;
+	BUGMSG(D_DURING, " rebuilt: from %d to %d; protocol %Xh\n",
+	       head->saddr, head->daddr, head->protocol_id);
+	return status;
 #else
-  return 0;
+	return 0;
 #endif
 }
 
 
 /* Determine a packet's protocol ID.
- *
+
  * With ARCnet we have to convert everything to Ethernet-style stuff.
  */
-static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct net_device *dev)
+static unsigned short arcnetA_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-  struct ClientData *head;
-  struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
+	struct ClientData *head;
+	struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
 
-  /* Pull off the arcnet header. */
-  skb->mac.raw=skb->data;
-  skb_pull(skb,dev->hard_header_len);
-  head=(struct ClientData *)skb->mac.raw;
-
-  if (head->daddr==0)
-    skb->pkt_type=PACKET_BROADCAST;
-  else if (dev->flags&IFF_PROMISC)
-    {
-      /* if we're not sending to ourselves :) */
-      if (head->daddr != dev->dev_addr[0])
-	skb->pkt_type=PACKET_OTHERHOST;
-    }
-
-  /* now return the protocol number */
-  switch (head->protocol_id)
-    {
-    case ARC_P_IP:		return htons(ETH_P_IP);
-    case ARC_P_ARP:		return htons(ETH_P_ARP);
-    case ARC_P_RARP:	return htons(ETH_P_RARP);
-
-    case ARC_P_IPX:
-    case ARC_P_NOVELL_EC:
-      return htons(ETH_P_802_3);
-    default:
-      lp->stats.rx_errors++;
-      lp->stats.rx_crc_errors++;
-      return 0;
-    }
+	/* Pull off the arcnet header. */
+	skb->mac.raw = skb->data;
+	skb_pull(skb, dev->hard_header_len);
+	head = (struct ClientData *) skb->mac.raw;
+
+	if (head->daddr == 0)
+		skb->pkt_type = PACKET_BROADCAST;
+	else if (dev->flags & IFF_PROMISC) {
+		/* if we're not sending to ourselves :) */
+		if (head->daddr != dev->dev_addr[0])
+			skb->pkt_type = PACKET_OTHERHOST;
+	}
+	/* now return the protocol number */
+	switch (head->protocol_id) {
+	case ARC_P_IP:
+		return htons(ETH_P_IP);
+	case ARC_P_ARP:
+		return htons(ETH_P_ARP);
+	case ARC_P_RARP:
+		return htons(ETH_P_RARP);
+
+	case ARC_P_IPX:
+	case ARC_P_NOVELL_EC:
+		return htons(ETH_P_802_3);
+	default:
+		lp->stats.rx_errors++;
+		lp->stats.rx_crc_errors++;
+		return 0;
+	}
 
-  return htons(ETH_P_IP);
+	return htons(ETH_P_IP);
 }
 
 
@@ -1545,17 +1454,17 @@
  */
 static int arcnetE_init(struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
-  ether_setup(dev); /* we're emulating ether here, not ARCnet */
-  dev->dev_addr[0]=0;
-  dev->dev_addr[5]=lp->stationid;
-  dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len-1;
-  dev->open=arcnetE_open_close;
-  dev->stop=arcnetE_open_close;
-  dev->hard_start_xmit=arcnetE_send_packet;
+	ether_setup(dev);	/* we're emulating ether here, not ARCnet */
+	dev->dev_addr[0] = 0;
+	dev->dev_addr[5] = lp->stationid;
+	dev->mtu = 512 - sizeof(struct archdr) - dev->hard_header_len - 1;
+	dev->open = arcnetE_open_close;
+	dev->stop = arcnetE_open_close;
+	dev->hard_start_xmit = arcnetE_send_packet;
 
-  return 0;
+	return 0;
 }
 
 
@@ -1564,86 +1473,77 @@
  */
 static int arcnetE_open_close(struct net_device *dev)
 {
-  return 0;
+	return 0;
 }
 
 
 /* Called by the kernel in order to transmit an ethernet-type packet.
  */
-static int
-arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  int bad,oldmask=0;
-  u_char daddr;
-  short offset,length=skb->len+1;
-  u_char proto=ARC_P_ETHER;
-
-  lp->intx++;
-
-  oldmask |= lp->intmask;
-  lp->intmask=0;
-  SETMASK;
-
-  bad=arcnet_send_packet_bad(skb,dev);
-  if (bad)
-    {
-      lp->intx--;
-      lp->intmask=oldmask;
-      SETMASK;
-      return bad;
-    }
-
-  /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-
-  lp->intmask=oldmask;
-  SETMASK;
-
-  if (length>XMTU)
-    {
-      BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n",
-	     length);
-      BUGMSG(D_NORMAL,"transmit aborted.\n");
-
-      dev_kfree_skb(skb);
-      lp->intx--;
-      return 0;
-    }
-
-  BUGMSG(D_DURING,"starting tx sequence...\n");
-
-  /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
-  if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
-    daddr=0;
-  else
-    daddr=((struct ethhdr*)(skb->data))->h_dest[5];
-
-  /* load packet into shared memory */
-  offset=512-length;
-  if (length>MTU)		/* long/exception packet */
-    {
-      if (length<MinTU) offset-=3;
-    }
-  else			/* short packet */
-    {
-      offset-=256;
-    }
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	int bad, oldmask = 0;
+	u_char daddr;
+	short offset, length = skb->len + 1;
+	u_char proto = ARC_P_ETHER;
 
-  BUGMSG(D_DURING," length=%Xh, offset=%Xh\n",
-	 length,offset);
+	lp->intx++;
 
-  (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0,
-			   offset);
+	oldmask |= lp->intmask;
+	lp->intmask = 0;
+	SETMASK;
 
-  dev_kfree_skb(skb);
+	bad = arcnet_send_packet_bad(skb, dev);
+	if (bad) {
+		lp->intx--;
+		lp->intmask = oldmask;
+		SETMASK;
+		return bad;
+	}
+	/* arcnet_send_packet_pad has already set tbusy - don't bother here. */
 
-  if (arcnet_go_tx(dev,1))
-    {
-      /* inform upper layers */
-      arcnet_tx_done(lp->adev, lp);
-    }
+	lp->intmask = oldmask;
+	SETMASK;
+
+	if (length > XMTU) {
+		BUGMSG(D_NORMAL, "MTU must be <= 493 for ethernet encap (length=%d).\n",
+		       length);
+		BUGMSG(D_NORMAL, "transmit aborted.\n");
+
+		dev_kfree_skb(skb);
+		lp->intx--;
+		return 0;
+	}
+	BUGMSG(D_DURING, "starting tx sequence...\n");
+
+	/* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
+	if (((struct ethhdr *) (skb->data))->h_dest[0] == 0xFF)
+		daddr = 0;
+	else
+		daddr = ((struct ethhdr *) (skb->data))->h_dest[5];
+
+	/* load packet into shared memory */
+	offset = 512 - length;
+	if (length > MTU) {	/* long/exception packet */
+		if (length < MinTU)
+			offset -= 3;
+	} else {		/* short packet */
+		offset -= 256;
+	}
+
+	BUGMSG(D_DURING, " length=%Xh, offset=%Xh\n",
+	       length, offset);
+
+	(*lp->prepare_tx) (dev, &proto, 1, skb->data, length - 1, daddr, 0,
+			   offset);
+
+	dev_kfree_skb(skb);
 
-	dev->trans_start=jiffies;
+	if (arcnet_go_tx(dev, 1)) {
+		/* inform upper layers */
+		arcnet_tx_done(lp->adev, lp);
+	}
+	dev->trans_start = jiffies;
 	lp->intx--;
 
 	/* make sure we didn't ignore a TX IRQ while we were in here */
@@ -1656,37 +1556,35 @@
 
 /* Packet receiver for ethernet-encap packets.
  */
-static void
-arcnetE_rx(struct net_device *dev,u_char *arcsoft,
-	int length,u_char saddr, u_char daddr)
+static void arcnetE_rx(struct net_device *dev, u_char * arcsoft,
+		       int length, u_char saddr, u_char daddr)
 {
-	struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 	struct sk_buff *skb;
 
-	BUGMSG(D_DURING,"it's an ethernet-encap packet (length=%d)\n",
-			length);
-
-       	skb = alloc_skb(length, GFP_ATOMIC);
-       	if (skb == NULL) {
-       		BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
-       		lp->stats.rx_dropped++;
-       		return;
-       	}
+	BUGMSG(D_DURING, "it's an ethernet-encap packet (length=%d)\n",
+	       length);
 
-       	skb_put(skb,length);
+	skb = alloc_skb(length, GFP_ATOMIC);
+	if (skb == NULL) {
+		BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+		lp->stats.rx_dropped++;
+		return;
+	}
+	skb_put(skb, length);
 
-       	skb->dev = dev;
+	skb->dev = dev;
 
-       	memcpy(skb->data,(u_char *)arcsoft+1,length-1);
+	memcpy(skb->data, (u_char *) arcsoft + 1, length - 1);
 
-        BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
+	BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
 
 	lp->stats.rx_bytes += skb->len;
-	skb->protocol=eth_type_trans(skb,dev);
-        netif_rx(skb);
+	skb->protocol = eth_type_trans(skb, dev);
+	netif_rx(skb);
 }
 
-#endif /* CONFIG_ARCNET_ETH */
+#endif				/* CONFIG_ARCNET_ETH */
 
 #ifdef CONFIG_ARCNET_1051
 /****************************************************************************
@@ -1699,22 +1597,22 @@
  */
 static int arcnetS_init(struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
 
-  arcnet_setup(dev);
+	arcnet_setup(dev);
 
-  /* And now fill particular fields with arcnet values */
-  dev->dev_addr[0]=lp->stationid;
-  dev->hard_header_len=sizeof(struct S_ClientData);
-  dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len
-    + S_EXTRA_CLIENTDATA;
-  dev->open=arcnetS_open_close;
-  dev->stop=arcnetS_open_close;
-  dev->hard_start_xmit=arcnetS_send_packet;
-  dev->hard_header=arcnetS_header;
-  dev->rebuild_header=arcnetS_rebuild_header;
+	/* And now fill particular fields with arcnet values */
+	dev->dev_addr[0] = lp->stationid;
+	dev->hard_header_len = sizeof(struct S_ClientData);
+	dev->mtu = 512 - sizeof(struct archdr) - dev->hard_header_len
+	+ S_EXTRA_CLIENTDATA;
+	dev->open = arcnetS_open_close;
+	dev->stop = arcnetS_open_close;
+	dev->hard_start_xmit = arcnetS_send_packet;
+	dev->hard_header = arcnetS_header;
+	dev->rebuild_header = arcnetS_rebuild_header;
 
-  return 0;
+	return 0;
 }
 
 
@@ -1723,171 +1621,160 @@
  */
 static int arcnetS_open_close(struct net_device *dev)
 {
-  return 0;
+	return 0;
 }
 
 
 /* Called by the kernel in order to transmit an RFC1051-type packet.
  */
-static int
-arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  int bad,length;
-  struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
-
-  lp->intx++;
-
-  bad=arcnet_send_packet_bad(skb,dev);
-  if (bad)
-    {
-      lp->intx--;
-      return bad;
-    }
-
-  /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-
-  length = 1 < skb->len ? skb->len : 1;
-
-  BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-
-  /* fits in one packet? */
-  if (length-S_EXTRA_CLIENTDATA<=XMTU)
-    {
-      (*lp->prepare_tx)(dev,
-			skb->data+S_EXTRA_CLIENTDATA,
-			sizeof(struct S_ClientData)-S_EXTRA_CLIENTDATA,
-			skb->data+sizeof(struct S_ClientData),
-			length-sizeof(struct S_ClientData),
-			hdr->daddr,0,0);
-
-      /* done right away */
-      dev_kfree_skb(skb);
-
-      if (arcnet_go_tx(dev,1))
-	{
-	  /* inform upper layers */
-	  arcnet_tx_done(lp->adev, lp);
-	}
-    }
-  else			/* too big for one - not accepted */
-    {
-      BUGMSG(D_NORMAL,"packet too long (length=%d)\n",
-	     length);
-      dev_kfree_skb(skb);
-      lp->stats.tx_dropped++;
-      arcnet_tx_done(lp->adev, lp);
-    }
-
-  dev->trans_start=jiffies;
-  lp->intx--;
-
-  /* make sure we didn't ignore a TX IRQ while we were in here */
-  lp->intmask |= TXFREEflag;
-  SETMASK;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	int bad, length;
+	struct S_ClientData *hdr = (struct S_ClientData *) skb->data;
+
+	lp->intx++;
+
+	bad = arcnet_send_packet_bad(skb, dev);
+	if (bad) {
+		lp->intx--;
+		return bad;
+	}
+	/* arcnet_send_packet_pad has already set tbusy - don't bother here. */
+
+	length = 1 < skb->len ? skb->len : 1;
+
+	BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx");
+
+	/* fits in one packet? */
+	if (length - S_EXTRA_CLIENTDATA <= XMTU) {
+		(*lp->prepare_tx) (dev,
+				   skb->data + S_EXTRA_CLIENTDATA,
+			sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
+				 skb->data + sizeof(struct S_ClientData),
+				   length - sizeof(struct S_ClientData),
+				   hdr->daddr, 0, 0);
+
+		/* done right away */
+		dev_kfree_skb(skb);
+
+		if (arcnet_go_tx(dev, 1)) {
+			/* inform upper layers */
+			arcnet_tx_done(lp->adev, lp);
+		}
+	} else {		/* too big for one - not accepted */
+		BUGMSG(D_NORMAL, "packet too long (length=%d)\n",
+		       length);
+		dev_kfree_skb(skb);
+		lp->stats.tx_dropped++;
+		arcnet_tx_done(lp->adev, lp);
+	}
+
+	dev->trans_start = jiffies;
+	lp->intx--;
 
-  return 0;
+	/* make sure we didn't ignore a TX IRQ while we were in here */
+	lp->intmask |= TXFREEflag;
+	SETMASK;
+
+	return 0;
 }
 
 
 /* Packet receiver for RFC1051 packets;
  */
-static void
-arcnetS_rx(struct net_device *dev,u_char *buf,
-	   int length,u_char saddr, u_char daddr)
-{
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  struct sk_buff *skb;
-  struct S_ClientData *arcsoft,*soft;
-
-  arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA);
-  length+=S_EXTRA_CLIENTDATA;
-
-  BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n",
-	 length);
-
-  {    /* was "if not split" in A protocol, S is never split */
-
-    skb = alloc_skb(length, GFP_ATOMIC);
-    if (skb == NULL) {
-      BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
-      lp->stats.rx_dropped++;
-      return;
-    }
-    soft=(struct S_ClientData *)skb->data;
-    skb_put(skb,length);
-
-    memcpy((u_char *)soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
-	   (u_char *)arcsoft + sizeof(struct S_ClientData) -S_EXTRA_CLIENTDATA,
-	   length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA);
-    soft->protocol_id=arcsoft->protocol_id;
-    soft->daddr=daddr;
-    soft->saddr=saddr;
-    skb->dev = dev;  /* is already lp->sdev */
-
-    BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
-    lp->stats.rx_bytes += skb->len;
-    skb->protocol=arcnetS_type_trans(skb,dev);
-    netif_rx(skb);
-  }
+static void arcnetS_rx(struct net_device *dev, u_char * buf,
+		       int length, u_char saddr, u_char daddr)
+{
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct sk_buff *skb;
+	struct S_ClientData *arcsoft, *soft;
+
+	arcsoft = (struct S_ClientData *) (buf - S_EXTRA_CLIENTDATA);
+	length += S_EXTRA_CLIENTDATA;
+
+	BUGMSG(D_DURING, "it's an RFC1051 packet (length=%d)\n",
+	       length);
+
+	{			/* was "if not split" in A protocol, S is never split */
+
+		skb = alloc_skb(length, GFP_ATOMIC);
+		if (skb == NULL) {
+			BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+			lp->stats.rx_dropped++;
+			return;
+		}
+		soft = (struct S_ClientData *) skb->data;
+		skb_put(skb, length);
+
+		memcpy((u_char *) soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
+		        (u_char *) arcsoft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
+		       length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA);
+		soft->protocol_id = arcsoft->protocol_id;
+		soft->daddr = daddr;
+		soft->saddr = saddr;
+		skb->dev = dev;	/* is already lp->sdev */
+
+		BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+
+		lp->stats.rx_bytes += skb->len;
+		skb->protocol = arcnetS_type_trans(skb, dev);
+		netif_rx(skb);
+	}
 }
 
 
 /* Create the ARCnet ClientData header for an arbitrary protocol layer
- *
- * saddr=NULL	means use device source address (always will anyway)
- * daddr=NULL	means leave destination address (eg unresolved arp)
+
+ * saddr=NULL   means use device source address (always will anyway)
+ * daddr=NULL   means leave destination address (eg unresolved arp)
  */
-static int arcnetS_header(struct sk_buff *skb,struct net_device *dev,
-			  unsigned short type,void *daddr,void *saddr,unsigned len)
+static int arcnetS_header(struct sk_buff *skb, struct net_device *dev,
+	     unsigned short type, void *daddr, void *saddr, unsigned len)
 {
-  struct S_ClientData *head = (struct S_ClientData *)
-    skb_push(skb,dev->hard_header_len);
-  struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
-  /* set the protocol ID according to RFC1051 */
-  switch(type)
-    {
-    case ETH_P_IP:
-      head->protocol_id=ARC_P_IP_RFC1051;
-      BUGMSG(D_DURING,"S_header: IP_RFC1051 packet.\n");
-      break;
-    case ETH_P_ARP:
-      head->protocol_id=ARC_P_ARP_RFC1051;
-      BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n");
-      break;
-    default:
-      BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
-	     type,type);
-      lp->stats.tx_errors++;
-      lp->stats.tx_aborted_errors++;
-      return 0;
-    }
-
-  /*
-   * Set the source hardware address.
-   *
-   * This is pretty pointless for most purposes, but it can help
-   * in debugging.  saddr is stored in the ClientData header and
-   * removed before sending the packet (since ARCnet does not allow
-   * us to change the source address in the actual packet sent)
-   */
-  if(saddr)
-    head->saddr=((u_char*)saddr)[0];
-  else
-    head->saddr=((u_char*)(dev->dev_addr))[0];
-
-  /* supposedly if daddr is NULL, we should ignore it... */
-  if(daddr)
-    {
-		head->daddr=((u_char*)daddr)[0];
+	struct S_ClientData *head = (struct S_ClientData *)
+	skb_push(skb, dev->hard_header_len);
+	struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+	/* set the protocol ID according to RFC1051 */
+	switch (type) {
+	case ETH_P_IP:
+		head->protocol_id = ARC_P_IP_RFC1051;
+		BUGMSG(D_DURING, "S_header: IP_RFC1051 packet.\n");
+		break;
+	case ETH_P_ARP:
+		head->protocol_id = ARC_P_ARP_RFC1051;
+		BUGMSG(D_DURING, "S_header: ARP_RFC1051 packet.\n");
+		break;
+	default:
+		BUGMSG(D_NORMAL, "I don't understand protocol %d (%Xh)\n",
+		       type, type);
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+		return 0;
+	}
+
+	/*
+	 * Set the source hardware address.
+	 *
+	 * This is pretty pointless for most purposes, but it can help
+	 * in debugging.  saddr is stored in the ClientData header and
+	 * removed before sending the packet (since ARCnet does not allow
+	 * us to change the source address in the actual packet sent)
+	 */
+	if (saddr)
+		head->saddr = ((u_char *) saddr)[0];
+	else
+		head->saddr = ((u_char *) (dev->dev_addr))[0];
+
+	/* supposedly if daddr is NULL, we should ignore it... */
+	if (daddr) {
+		head->daddr = ((u_char *) daddr)[0];
 		return dev->hard_header_len;
-    }
-  else
-    head->daddr=0;	/* better fill one in anyway */
+	} else
+		head->daddr = 0;	/* better fill one in anyway */
 
-  return -dev->hard_header_len;
+	return -dev->hard_header_len;
 }
 
 
@@ -1897,75 +1784,73 @@
  */
 static int arcnetS_rebuild_header(struct sk_buff *skb)
 {
-  struct net_device *dev=skb->dev;
-  struct S_ClientData *head = (struct S_ClientData *)skb->data;
-  struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
-  /*
-   * Only ARP and IP are currently supported
-   */
-
-  if(head->protocol_id != ARC_P_IP_RFC1051)
-    {
-      BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
-	     head->protocol_id,head->protocol_id);
-      lp->stats.tx_errors++;
-      lp->stats.tx_aborted_errors++;
-      head->daddr=0;
-      /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
-      return 0;
-    }
-
-  /*
-   * Try to get ARP to resolve the header.
-   */
+	struct net_device *dev = skb->dev;
+	struct S_ClientData *head = (struct S_ClientData *) skb->data;
+	struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+	/*
+	 * Only ARP and IP are currently supported
+	 */
+
+	if (head->protocol_id != ARC_P_IP_RFC1051) {
+		BUGMSG(D_NORMAL, "I don't understand protocol type %d (%Xh) addresses!\n",
+		       head->protocol_id, head->protocol_id);
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+		head->daddr = 0;
+		/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len); */
+		return 0;
+	}
+	/*
+	 * Try to get ARP to resolve the header.
+	 */
 #ifdef CONFIG_INET
-  return arp_find(&(head->daddr),skb)? 1 : 0;
+	return arp_find(&(head->daddr), skb) ? 1 : 0;
 #else
-  return 0;
+	return 0;
 #endif
 }
 
 
 /* Determine a packet's protocol ID.
- *
+
  * With ARCnet we have to convert everything to Ethernet-style stuff.
  */
-unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev)
+unsigned short arcnetS_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-  struct S_ClientData *head;
-  struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
+	struct S_ClientData *head;
+	struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
 
-  /* Pull off the arcnet header. */
-  skb->mac.raw=skb->data;
-  skb_pull(skb,dev->hard_header_len);
-  head=(struct S_ClientData *)skb->mac.raw;
-
-  if (head->daddr==0)
-    skb->pkt_type=PACKET_BROADCAST;
-  else if (dev->flags&IFF_PROMISC)
-    {
-      /* if we're not sending to ourselves :) */
-      if (head->daddr != dev->dev_addr[0])
-	skb->pkt_type=PACKET_OTHERHOST;
-    }
-
-  /* now return the protocol number */
-  switch (head->protocol_id)
-    {
-    case ARC_P_IP_RFC1051:	return htons(ETH_P_IP);
-    case ARC_P_ARP_RFC1051:	return htons(ETH_P_ARP);
-    case ARC_P_ATALK:   return htons(ETH_P_ATALK); /* untested appletalk */
-    default:
-      lp->stats.rx_errors++;
-      lp->stats.rx_crc_errors++;
-      return 0;
-    }
+	/* Pull off the arcnet header. */
+	skb->mac.raw = skb->data;
+	skb_pull(skb, dev->hard_header_len);
+	head = (struct S_ClientData *) skb->mac.raw;
+
+	if (head->daddr == 0)
+		skb->pkt_type = PACKET_BROADCAST;
+	else if (dev->flags & IFF_PROMISC) {
+		/* if we're not sending to ourselves :) */
+		if (head->daddr != dev->dev_addr[0])
+			skb->pkt_type = PACKET_OTHERHOST;
+	}
+	/* now return the protocol number */
+	switch (head->protocol_id) {
+	case ARC_P_IP_RFC1051:
+		return htons(ETH_P_IP);
+	case ARC_P_ARP_RFC1051:
+		return htons(ETH_P_ARP);
+	case ARC_P_ATALK:
+		return htons(ETH_P_ATALK);	/* untested appletalk */
+	default:
+		lp->stats.rx_errors++;
+		lp->stats.rx_crc_errors++;
+		return 0;
+	}
 
-  return htons(ETH_P_IP);
+	return htons(ETH_P_IP);
 }
 
-#endif	/* CONFIG_ARCNET_1051 */
+#endif				/* CONFIG_ARCNET_1051 */
 
 
 /****************************************************************************
@@ -1978,15 +1863,15 @@
 
 void cleanup_module(void)
 {
-  printk("Generic arcnet support removed.\n");
+	printk("Generic arcnet support removed.\n");
 }
 
 void arcnet_use_count(int open)
 {
-  if (open)
-    MOD_INC_USE_COUNT;
-  else
-    MOD_DEC_USE_COUNT;
+	if (open)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
 }
 
 #else
@@ -1996,54 +1881,52 @@
 }
 
 struct net_device arcnet_devs[MAX_ARCNET_DEVS];
-int arcnet_num_devs=0;
+int arcnet_num_devs = 0;
 char arcnet_dev_names[MAX_ARCNET_DEVS][10];
 
-void __init arcnet_init(void)
+int __init arcnet_init(void)
 {
-  int c;
+	int c;
 
-  init_module();
+	init_module();
 
-  /* Don't register_netdev here. The chain hasn't been initialised. */
+	/* Don't register_netdev here. The chain hasn't been initialised. */
 
 #ifdef CONFIG_ARCNET_COM90xx
-  if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS)
-    {
-      arcnet_devs[arcnet_num_devs].init=arc90xx_probe;
-      arcnet_devs[arcnet_num_devs].name=
-	(char *)&arcnet_dev_names[arcnet_num_devs];
-      arcnet_num_devs++;
-    }
+	if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS) {
+		arcnet_devs[arcnet_num_devs].init = arc90xx_probe;
+		arcnet_devs[arcnet_num_devs].name =
+		    (char *) &arcnet_dev_names[arcnet_num_devs];
+		arcnet_num_devs++;
+	}
 #endif
 
-  if (!arcnet_num_devs)
-    {
-      printk("Don't forget to load the chipset driver.\n");
-      return;
-    }
-
-  /* Link into the device chain */
+	if (!arcnet_num_devs) {
+		printk("Don't forget to load the chipset driver.\n");
+		return 0;
+	}
+	/* Link into the device chain */
 
-  /* Q: Should we put ourselves at the beginning or the end of the chain? */
-  /* Probably the end, because we're not so fast, but... */
+	/* Q: Should we put ourselves at the beginning or the end of the chain? */
+	/* Probably the end, because we're not so fast, but... */
 
-  for (c=0; c< (arcnet_num_devs-1); c++)
-    arcnet_devs[c].next=&arcnet_devs[c+1];
+	for (c = 0; c < (arcnet_num_devs - 1); c++)
+		arcnet_devs[c].next = &arcnet_devs[c + 1];
 
-  write_lock_bh(&dev_base_lock);
-  arcnet_devs[c].next=dev_base;
-  dev_base=&arcnet_devs[0];
-  write_unlock_bh(&dev_base_lock);
+	write_lock_bh(&dev_base_lock);
+	arcnet_devs[c].next = dev_base;
+	dev_base = &arcnet_devs[0];
+	write_unlock_bh(&dev_base_lock);
 
-  /* Give names to those without them */
+	/* Give names to those without them */
 
-  for (c=0; c< arcnet_num_devs; c++)
-    if (!arcnet_dev_names[c][0])
-      arcnet_makename((char *)&arcnet_dev_names[c]);
+	for (c = 0; c < arcnet_num_devs; c++)
+		if (!arcnet_dev_names[c][0])
+			arcnet_makename((char *) &arcnet_dev_names[c]);
+	return 0;
 }
 
-#endif /* MODULE */
+#endif				/* MODULE */
 
 
 #ifdef MODULE
@@ -2053,48 +1936,46 @@
 #endif
 {
 #ifdef ALPHA_WARNING
-  BUGLVL(D_EXTRA)
-    {
-      printk("arcnet: ***\n");
-      printk("arcnet: * Read arcnet.txt for important release notes!\n");
-      printk("arcnet: *\n");
-      printk("arcnet: * This is an ALPHA version!  (Last stable release: v2.56)  E-mail me if\n");
-      printk("arcnet: * you have any questions, comments, or bug reports.\n");
-      printk("arcnet: ***\n");
-    }
+	BUGLVL(D_EXTRA) {
+		printk("arcnet: ***\n");
+		printk("arcnet: * Read arcnet.txt for important release notes!\n");
+		printk("arcnet: *\n");
+		printk("arcnet: * This is an ALPHA version!  (Last stable release: v2.56)  E-mail me if\n");
+		printk("arcnet: * you have any questions, comments, or bug reports.\n");
+		printk("arcnet: ***\n");
+	}
 #endif
 
-  printk("%sAvailable protocols: ARCnet RFC1201"
+	printk("%sAvailable protocols: ARCnet RFC1201"
 #ifdef CONFIG_ARCNET_ETH
-	 ", Ethernet-Encap"
+	       ", Ethernet-Encap"
 #endif
 #ifdef CONFIG_ARCNET_1051
-	 ", ARCnet RFC1051"
+	       ", ARCnet RFC1051"
 #endif
 #ifdef MODULE
-	 ".\nDon't forget to load the chipset driver"
+	       ".\nDon't forget to load the chipset driver"
 #endif
-	".\n",version);
-  return 0;
+	       ".\n", version);
+	return 0;
 }
 
 
 void arcnet_makename(char *device)
 {
-  struct net_device *dev;
-  int arcnum;
+	struct net_device *dev;
+	int arcnum;
 
-  arcnum = 0;
-  for (;;)
-    {
-      sprintf(device, "arc%d", arcnum);
-      read_lock_bh(&dev_base_lock);
-      for (dev = dev_base; dev; dev=dev->next)
-	if (dev->name != device && !strcmp(dev->name, device))
-	  break;
-      read_unlock_bh(&dev_base_lock);
-      if (!dev)
-	return;
-      arcnum++;
-    }
+	arcnum = 0;
+	for (;;) {
+		sprintf(device, "arc%d", arcnum);
+		read_lock_bh(&dev_base_lock);
+		for (dev = dev_base; dev; dev = dev->next)
+			if (dev->name != device && !strcmp(dev->name, device))
+				break;
+		read_unlock_bh(&dev_base_lock);
+		if (!dev)
+			return;
+		arcnum++;
+	}
 }
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.3.23/linux/drivers/net/irda/actisys.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/irda/actisys.c	Mon Oct 25 20:49:42 1999
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Sat Jun 26 16:57:57 1999
+ * Modified at:   Mon Oct 18 23:37:06 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -32,33 +32,31 @@
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
-#include <net/irda/dongle.h>
 
-static void actisys_reset(struct irda_device *dev);
-static void actisys_open(struct irda_device *idev, int type);
-static void actisys_close(struct irda_device *dev);
-static void actisys_change_speed( struct irda_device *dev, __u32 speed);
-static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos);
+static int  actisys_change_speed(struct irda_task *task);
+static int  actisys_reset(struct irda_task *task);
+static void actisys_open(dongle_t *self, struct qos_info *qos);
+static void actisys_close(dongle_t *self);
 
 /* These are the baudrates supported */
-static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
+static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
 
-static struct dongle dongle = {
-	ACTISYS_DONGLE,
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_ACTISYS_DONGLE,
 	actisys_open,
 	actisys_close,
 	actisys_reset,
 	actisys_change_speed,
-	actisys_init_qos,
 };
 
-static struct dongle dongle_plus = {
-	ACTISYS_PLUS_DONGLE,
+static struct dongle_reg dongle_plus = {
+	Q_NULL,
+	IRDA_ACTISYS_PLUS_DONGLE,
 	actisys_open,
 	actisys_close,
 	actisys_reset,
 	actisys_change_speed,
-	actisys_init_qos,
 };
 
 int __init actisys_init(void)
@@ -82,20 +80,23 @@
 	irda_device_unregister_dongle(&dongle_plus);
 }
 
-static void actisys_open(struct irda_device *idev, int type)
+static void actisys_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> actisys");
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 
-        idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
+	/* Remove support for 38400 if this is not a 220L+ dongle */
+	if (self->issue->type == IRDA_ACTISYS_DONGLE)
+		qos->baud_rate.bits &= ~IR_38400;
+	
+	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
 
 	MOD_INC_USE_COUNT;
 }
 
-static void actisys_close(struct irda_device *idev)
+static void actisys_close(dongle_t *self)
 {
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
@@ -107,52 +108,84 @@
  *    To cycle through the available baud rates, pulse RTS low for a few
  *    ms.  
  */
-static void actisys_change_speed(struct irda_device *idev, __u32 speed)
+static int actisys_change_speed(struct irda_task *task)
 {
-        __u32 current_baudrate;
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
+        __u32 current_speed;
         int index = 0;
+	int ret = 0;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	current_baudrate = idev->qos.baud_rate.value;
+	current_speed = self->speed;
 
 	/* Find the correct baudrate index for the currently used baudrate */
-	while (current_baudrate != baud_rates[index])
+	while (current_speed != baud_rates[index])
 		index++;
 
-        DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
+        IRDA_DEBUG(4, __FUNCTION__ "(), index=%d\n", index);
 
-	/* Cycle through avaiable baudrates until we reach the correct one */
-        while (current_baudrate != speed) {	
-                DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Lock dongle */
+		if (irda_lock((void *) &self->busy) == FALSE) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+			ret = MSECS_TO_JIFFIES(100);
+			break;
+		}
+	
+                IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
 		      baud_rates[index]);
 		
 		/* Set DTR, clear RTS */
-		irda_device_set_dtr_rts(idev, TRUE, FALSE);
+		self->set_dtr_rts(self->dev, TRUE, FALSE);
 		
-		/* Wait at a few ms */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(MSECS_TO_JIFFIES(20));
+		irda_task_next_state(task, IRDA_TASK_WAIT1);
 
+		/* Wait at a few ms */
+		ret = MSECS_TO_JIFFIES(20);
+		break;
+	case IRDA_TASK_WAIT1:
 		/* Set DTR, Set RTS */
-		irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
 		
-		/* Wait at a few ms again */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(MSECS_TO_JIFFIES(20));
+		irda_task_next_state(task, IRDA_TASK_WAIT2);
 
+		/* Wait at a few ms again */
+		ret = MSECS_TO_JIFFIES(20);
+		break;
+	case IRDA_TASK_WAIT2:
                 /* Go to next baudrate */
-		if (idev->io.dongle_id == ACTISYS_DONGLE)
+		if (self->issue->type == IRDA_ACTISYS_DONGLE)
                         index = (index+1) % 4; /* IR-220L */
 		else
                         index = (index+1) % 5; /* IR-220L+ */
 
-                current_baudrate = baud_rates[index];
+                current_speed = baud_rates[index];
+
+		/* Check if we need to go some more rounds */
+		if (current_speed != speed)
+			irda_task_next_state(task, IRDA_TASK_INIT);
+		else {
+			irda_task_next_state(task, IRDA_TASK_DONE);
+			self->busy = 0;
+		}
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->busy = 0;
+		ret = -1;
+		break;
         }
-	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", baud_rates[index]);
+
+	self->speed = speed;
+
+	IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", 
+	      baud_rates[index]);
+
+	return ret;
 }
 
 /*
@@ -162,45 +195,42 @@
  *      called with a process context!
  *
  *    	1. Clear DTR for a few ms.
- *
  */
-static void actisys_reset(struct irda_device *idev)
+static int actisys_reset(struct irda_task *task)
 {
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	/* Clear DTR */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE);
+	dongle_t *self = (dongle_t *) task->instance;
+	int ret = 0;
 
-	/* Sleep 10-20 ms*/
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
-	
-	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
-	
-	idev->qos.baud_rate.value = 9600;
-}
+	ASSERT(task != NULL, return -1;);
 
-/*
- * Function actisys_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Clear DTR */
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
+		
+		irda_task_next_state(task, IRDA_TASK_WAIT);
 
-	/* Remove support for 38400 if this is not a 220L+ dongle */
-	if (idev->io.dongle_id == ACTISYS_DONGLE)
-		qos->baud_rate.bits &= ~IR_38400;
-	
-	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+		/* Sleep 10-20 ms*/
+		ret = MSECS_TO_JIFFIES(20);
+		break;
+	case IRDA_TASK_WAIT:			
+		/* Go back to normal mode */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+	
+		irda_task_next_state(task, IRDA_TASK_DONE);
+
+		self->speed = 9600;
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		ret = -1;
+		break;
+	}
+	return ret;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");	
 		
@@ -225,5 +255,4 @@
 {
 	actisys_cleanup();
 }
-
-#endif
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/airport.c linux/drivers/net/irda/airport.c
--- v2.3.23/linux/drivers/net/irda/airport.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/irda/airport.c	Mon Oct 25 20:49:42 1999
@@ -56,7 +56,7 @@
 {
 	int ret;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	ret = irda_device_register_dongle(&dongle);
 	if (ret < 0)
 		return ret;
@@ -65,17 +65,17 @@
 
 void airport_cleanup(void)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	irda_device_unregister_dongle(&dongle);
 }
 
 static void airport_open(struct irda_device *idev, int type)
 {
-	DEBUG(2, __FUNCTION__ "(,%d)\n", type);
+	IRDA_DEBUG(2, __FUNCTION__ "(,%d)\n", type);
 	if (strlen(idev->description) < sizeof(idev->description) - 13)
 	  strcat(idev->description, " <-> airport");
 	else
-	  DEBUG(0, __FUNCTION__ " description too long: %s\n", 
+	  IRDA_DEBUG(0, __FUNCTION__ " description too long: %s\n", 
 		idev->description);
 
         idev->io.dongle_id = type;
@@ -86,7 +86,7 @@
 
 static void airport_close(struct irda_device *idev)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	/* Power off dongle */
 	irda_device_set_dtr_rts(idev, FALSE, FALSE);
 
@@ -95,13 +95,13 @@
 
 static void airport_set_command_mode(struct irda_device *idev)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	irda_device_set_dtr_rts(idev, FALSE, TRUE);
 }
 
 static void airport_set_normal_mode(struct irda_device *idev)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
     	irda_device_set_dtr_rts(idev, TRUE, TRUE);
 }
 
@@ -109,7 +109,7 @@
 void airport_write_char(struct irda_device *idev, unsigned char c)
 {
 	int actual;
-	DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
+	IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
 	actual = idev->raw_write(idev, &c, 1);
 	ASSERT(actual == 1, return;);
 }
@@ -120,22 +120,22 @@
 {
 	int i, found = FALSE;
 	int before;
-	DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
+	IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
 
 	/* Sleep approx. 10 ms */
 	before = jiffies;
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(20));
-	DEBUG(4, __FUNCTION__ " waited %ldms\n", 
+	IRDA_DEBUG(4, __FUNCTION__ " waited %ldms\n", 
 	      JIFFIES_TO_MSECS(jiffies - before));
 
 	for ( i = 0 ; !found && i < idev->rx_buff.len ; i++ ) {
-		/* DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
+		/* IRDA_DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
 		found = c == idev->rx_buff.data[i];
 	}
 	idev->rx_buff.len = 0;
 
-	DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
+	IRDA_DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
 	return found;
 }
 
@@ -144,7 +144,7 @@
 	int i;
 	int found = FALSE;
   
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(20));
 	airport_set_command_mode(idev);
@@ -160,9 +160,9 @@
 	}
 
 	if (found) {
-		DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
+		IRDA_DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
 	} else {
-		DEBUG(0, __FUNCTION__ " FAILED!\n");
+		IRDA_DEBUG(0, __FUNCTION__ " FAILED!\n");
 	}
 	return found;
 }
@@ -173,7 +173,7 @@
 	int ok = FALSE;
 	int i;
 
-	DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
+	IRDA_DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
 	airport_check_command_mode(idev);
 
 	for ( i = 0 ; i < 6 ; i++ ) {
@@ -191,9 +191,9 @@
 
 	airport_set_normal_mode(idev);
 	if (ok) {
-		DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
+		IRDA_DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
 	} else {
-		DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
+		IRDA_DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
 	}
 	return ok;
 }
@@ -209,7 +209,7 @@
         __u32 current_baudrate;
         int baudcode;
 	
-	DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
+	IRDA_DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
 
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -224,16 +224,16 @@
 	case 57600:	baudcode = 0x60;	break;
 	case 115200:	baudcode = 0x70;	break;
 	default:
-		DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
+		IRDA_DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
 		return;
 	}
 
 	current_baudrate = idev->qos.baud_rate.value;
-	DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
+	IRDA_DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
 
 	/* The dongle falls back to 9600 baud */
 	if (current_baudrate != 9600) {
-		DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n");
+		IRDA_DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n");
 		ASSERT(idev->change_speed , return;);
 		idev->change_speed(idev, 9600);
 		idev->qos.baud_rate.value = 9600;
@@ -247,11 +247,11 @@
 		if (airport_write_register(idev, baudcode|0x01)) {
 			/* ok */
 		} else {
-			DEBUG(0, __FUNCTION__ 
+			IRDA_DEBUG(0, __FUNCTION__ 
 			      " Cannot set new speed in second register\n");
 		}
 	} else {
-		DEBUG(0, __FUNCTION__ 
+		IRDA_DEBUG(0, __FUNCTION__ 
 		      " Cannot set new speed in first register\n");
 	}
 	
@@ -260,7 +260,7 @@
 
 	/* How do I signal an error in these functions? */
 
-	DEBUG(4, __FUNCTION__ " returning\n");
+	IRDA_DEBUG(4, __FUNCTION__ " returning\n");
 }
 
 
@@ -275,7 +275,7 @@
 {
 	int ok;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	ASSERT(idev->set_raw_mode /* The airport needs this */, return;);
@@ -286,10 +286,10 @@
 	airport_set_normal_mode(idev);
 
 	/* Sleep 2000 ms */
-	DEBUG(2, __FUNCTION__ " waiting for powerup\n");
+	IRDA_DEBUG(2, __FUNCTION__ " waiting for powerup\n");
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(2000));
-	DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
+	IRDA_DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
 	
 	/* set dongle speed to 9600 */
 	ok = TRUE;
@@ -322,12 +322,12 @@
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(20));
-	DEBUG(4, __FUNCTION__ " waited 20ms\n");
+	IRDA_DEBUG(4, __FUNCTION__ " waited 20ms\n");
 
 	idev->qos.baud_rate.value = 9600;
 	if (!ok)
 		MESSAGE(__FUNCTION__ "() failed.\n");
-	DEBUG(2, __FUNCTION__ " returning.\n");
+	IRDA_DEBUG(2, __FUNCTION__ " returning.\n");
 }
 
 /*
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.3.23/linux/drivers/net/irda/esi.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/irda/esi.c	Mon Oct 25 20:49:42 1999
@@ -1,27 +1,33 @@
 /*********************************************************************
  *                
  * Filename:      esi.c
- * Version:       1.4
+ * Version:       1.5
  * Description:   Driver for the Extended Systems JetEye PC dongle
  * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
+ * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sat Jun 26 16:50:17 1999
+ * Modified at:   Mon Oct 18 12:35:43 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  esi.c
- *
- *     Copyright (c) 1998-1999, Dag Brattli, <dagb@cs.uit.no>
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
+ * 
+ *     Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
+ *     Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
  *     All Rights Reserved.
- *
- *     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
+ *     
+ *     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.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
+ * 
+ *     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>
@@ -34,22 +40,19 @@
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
-#include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
-
-static void esi_open(struct irda_device *idev, int type);
-static void esi_close(struct irda_device *driver);
-static void esi_change_speed(struct irda_device *idev, __u32 speed);
-static void esi_reset(struct irda_device *idev);
-static void esi_qos_init(struct irda_device *idev, struct qos_info *qos);
 
-static struct dongle dongle = {
-	ESI_DONGLE,
+static void esi_open(dongle_t *self, struct qos_info *qos);
+static void esi_close(dongle_t *self);
+static int  esi_change_speed(struct irda_task *task);
+static int  esi_reset(struct irda_task *task);
+
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_ESI_DONGLE,
 	esi_open,
 	esi_close,
 	esi_reset,
 	esi_change_speed,
-	esi_qos_init,
 };
 
 int __init esi_init(void)
@@ -62,37 +65,40 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void esi_open(struct irda_device *idev, int type)
+static void esi_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> esi");
-
-	idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
+	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
 
 	MOD_INC_USE_COUNT;
 }
 
-static void esi_close(struct irda_device *idev)
+static void esi_close(dongle_t *dongle)
 {		
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	dongle->set_dtr_rts(dongle->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function esi_change_speed (idev, speed)
+ * Function esi_change_speed (task)
  *
  *    Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
  *
  */
-static void esi_change_speed(struct irda_device *idev, __u32 speed)
+static int esi_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
 	int dtr, rts;
 	
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
+	/* Lock dongle */
+	if (irda_lock((void *) &self->busy) == FALSE) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		return MSECS_TO_JIFFIES(100);
+	}
+
 	switch (speed) {
 	case 19200:
 		dtr = TRUE;
@@ -109,28 +115,34 @@
 	}
 
 	/* Change speed of dongle */
-	irda_device_set_dtr_rts(idev, dtr, rts);
-}
+	self->set_dtr_rts(self->dev, dtr, rts);
+	self->speed = speed;
 
-static void esi_reset( struct irda_device *idev)
-{
-	/* Empty */
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	/* Unlock */
+	self->busy = 0;
+	
+	return 0;
 }
 
 /*
- * Function esi_qos_init (qos)
+ * Function esi_reset (task)
  *
- *    Init QoS capabilities for the dongle
+ *    Reset dongle;
  *
  */
-static void esi_qos_init(struct irda_device *idev, struct qos_info *qos)
+static int esi_reset(struct irda_task *task)
 {
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
-	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
+	dongle_t *self = (dongle_t *) task->instance;
+	
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
 
@@ -155,6 +167,5 @@
 {
         esi_cleanup();
 }
-
-#endif
+#endif /* MODULE */
 
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c
--- v2.3.23/linux/drivers/net/irda/girbil.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/irda/girbil.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb  6 21:02:33 1999
- * Modified at:   Sun Jul 18 12:09:26 1999
+ * Modified at:   Mon Oct 18 22:15:20 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -32,13 +32,11 @@
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
 #include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
 
-static void girbil_reset(struct irda_device *dev);
-static void girbil_open(struct irda_device *dev, int type);
-static void girbil_close(struct irda_device *dev);
-static void girbil_change_speed(struct irda_device *dev, __u32 speed);
-static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
+static int  girbil_reset(struct irda_task *task);
+static void girbil_open(dongle_t *self, struct qos_info *qos);
+static void girbil_close(dongle_t *self);
+static int  girbil_change_speed(struct irda_task *task);
 
 /* Control register 1 */
 #define GIRBIL_TXEN    0x01 /* Enable transmitter */
@@ -67,13 +65,13 @@
 /* Control register 2 (0x5) */
 #define GIRBIL_LOAD    0x51 /* Load the new baud rate value */
 
-static struct dongle dongle = {
-	GIRBIL_DONGLE,
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_GIRBIL_DONGLE,
 	girbil_open,
 	girbil_close,
 	girbil_reset,
 	girbil_change_speed,
-	girbil_init_qos,
 };
 
 int __init girbil_init(void)
@@ -86,20 +84,18 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void girbil_open(struct irda_device *idev, int type)
+static void girbil_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> girbil");
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits &= 0x03;
 
-	idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
-	
 	MOD_INC_USE_COUNT;
 }
 
-static void girbil_close(struct irda_device *idev)
+static void girbil_close(dongle_t *self)
 {
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
@@ -111,47 +107,80 @@
  *    function must be called with a process context!
  *
  */
-static void girbil_change_speed(struct irda_device *idev, __u32 speed)
+static int girbil_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
 	__u8 control[2];
-	
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	switch (speed) {
-	case 9600:
-	default:
-		control[0] = GIRBIL_9600;
+	int ret = 0;
+
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Lock dongle */
+		if (irda_lock((void *) &self->busy) == FALSE) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+			return MSECS_TO_JIFFIES(100);
+		}
+
+		/* Need to reset the dongle and go to 9600 bps before
+                   programming */
+		if (irda_task_execute(self, girbil_reset, NULL, task, 
+				      (void *) speed))
+		{
+			/* Dongle need more time to reset */
+			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+			/* Give reset 1 sec to finish */
+			ret = MSECS_TO_JIFFIES(1000);
+		}
 		break;
-	case 19200:
-		control[0] = GIRBIL_19200;
+	case IRDA_TASK_CHILD_WAIT:
+		WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+		ret = -1;
 		break;
-	case 34800:
-		control[0] = GIRBIL_38400;
+	case IRDA_TASK_CHILD_DONE:
+		/* Set DTR and Clear RTS to enter command mode */
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
+
+		switch (speed) {
+		case 9600:
+		default:
+			control[0] = GIRBIL_9600;
+			break;
+		case 19200:
+			control[0] = GIRBIL_19200;
+			break;
+		case 34800:
+			control[0] = GIRBIL_38400;
+			break;
+		case 57600:
+			control[0] = GIRBIL_57600;
+			break;
+		case 115200:
+			control[0] = GIRBIL_115200;
+			break;
+		}
+		control[1] = GIRBIL_LOAD;
+		
+		/* Write control bytes */
+		self->write(self->dev, control, 2);
+		irda_task_next_state(task, IRDA_TASK_WAIT);
+		ret = MSECS_TO_JIFFIES(100);
 		break;
-	case 57600:
-		control[0] = GIRBIL_57600;
+	case IRDA_TASK_WAIT:
+		/* Go back to normal mode */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->busy = 0;
 		break;
-	case 115200:
-		control[0] = GIRBIL_115200;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->busy = 0;
+		ret = -1;
 		break;
 	}
-	control[1] = GIRBIL_LOAD;
-
-	/* Need to reset the dongle and go to 9600 bps before programming */
-	girbil_reset(idev);
-
-	/* Set DTR and Clear RTS to enter command mode */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE);
-
-	/* Write control bytes */
-	irda_device_raw_write(idev, control, 2);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(100));
-	
-	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	return ret;
 }
 
 /*
@@ -164,54 +193,47 @@
  *    	  0. set RTS, and wait at least 5 ms 
  *        1. clear RTS 
  */
-void girbil_reset(struct irda_device *idev)
+static int girbil_reset(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
 	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
+	int ret = 0;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	/* Make sure the IrDA chip also goes to defalt speed */
-	if (idev->change_speed)
-		idev->change_speed(idev, 9600);
-
-	/* Reset dongle */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
-
-	/* Sleep at least 5 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(10));
-	
-	/* Set DTR and clear RTS to enter command mode */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(10));
-
-	/* Write control byte */
-	irda_device_raw_write(idev, &control, 1);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
-
-	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
-}
-
-/*
- * Function girbil_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x03;
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Reset dongle */
+		self->set_dtr_rts(self->dev, TRUE, FALSE);
+		irda_task_next_state(task, IRDA_TASK_WAIT1);
+		/* Sleep at least 5 ms */
+		ret = MSECS_TO_JIFFIES(10);
+		break;
+	case IRDA_TASK_WAIT1:
+		/* Set DTR and clear RTS to enter command mode */
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
+		irda_task_next_state(task, IRDA_TASK_WAIT2);
+		ret = MSECS_TO_JIFFIES(10);
+		break;
+	case IRDA_TASK_WAIT2:
+		/* Write control byte */
+		self->write(self->dev, &control, 1);
+		irda_task_next_state(task, IRDA_TASK_WAIT3);
+		ret = MSECS_TO_JIFFIES(20);
+		break;
+	case IRDA_TASK_WAIT3:
+		/* Go back to normal mode */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		ret = -1;
+		break;
+	}
+	return ret;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
 	
@@ -236,5 +258,4 @@
 {
         girbil_cleanup();
 }
-
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.3.23/linux/drivers/net/irda/irport.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/irda/irport.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:	  Experimental.
  * Author:	  Dag Brattli <dagb@cs.uit.no>
  * Created at:	  Sun Aug  3 13:49:59 1997
- * Modified at:   Tue Aug 31 13:54:27 1999
+ * Modified at:   Wed Oct 20 00:07:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  serial.c by Linus Torvalds 
  * 
@@ -48,6 +48,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -69,22 +70,22 @@
 
 static unsigned int qos_mtt_bits = 0x03;
 
-static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL};
 static char *driver_name = "irport";
 
 static int irport_open(int i, unsigned int iobase, unsigned int irq);
-static int irport_close(struct irda_device *idev);
+static int irport_close(struct irport_cb *self);
 
-static void irport_write_wakeup(struct irda_device *idev);
+static void irport_write_wakeup(struct irport_cb *self);
 static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
-static void irport_receive(struct irda_device *idev);
+static void irport_receive(struct irport_cb *self);
 
 static int  irport_net_init(struct net_device *dev);
 static int  irport_net_open(struct net_device *dev);
 static int  irport_net_close(struct net_device *dev);
-static int  irport_is_receiving(struct irda_device *idev);
-static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
-static int  irport_raw_write(struct irda_device *idev, __u8 *buf, int len);
+static int  irport_is_receiving(struct irport_cb *self);
+static void irport_set_dtr_rts(struct net_device *dev, int dtr, int rts);
+static int  irport_raw_write(struct net_device *dev, __u8 *buf, int len);
 
 int __init irport_init(void)
 {
@@ -114,7 +115,7 @@
 {
  	int i;
 
-        DEBUG( 4, __FUNCTION__ "()\n");
+        IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	for (i=0; i < 4; i++) {
  		if (dev_self[i])
@@ -125,108 +126,154 @@
 
 static int irport_open(int i, unsigned int iobase, unsigned int irq)
 {
-	struct irda_device *idev;
+	struct net_device *dev;
+	struct irport_cb *self;
 	int ret;
+	int err;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-/* 	if (irport_probe(iobase, irq) == -1) */
-/* 		return -1; */
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	/*
 	 *  Allocate new instance of the driver
 	 */
-	idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL);
-	if (idev == NULL) {
-		printk( KERN_ERR "IrDA: Can't allocate memory for "
-			"IrDA control block!\n");
+	self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
+	if (!self) {
+		ERROR(__FUNCTION__ "(), can't allocate memory for "
+		      "control block!\n");
 		return -ENOMEM;
 	}
-	memset(idev, 0, sizeof(struct irda_device));
+	memset(self, 0, sizeof(struct irport_cb));
    
+	spin_lock_init(&self->lock);
+
 	/* Need to store self somewhere */
-	dev_self[i] = idev;
+	dev_self[i] = self;
 
 	/* Initialize IO */
-	idev->io.iobase2   = iobase;
-        idev->io.irq2      = irq;
-        idev->io.io_ext    = IO_EXTENT;
-        idev->io.fifo_size = 16;
-
-	idev->netdev.base_addr = iobase;
-	idev->netdev.irq = irq;
+	self->io.iobase2   = iobase;
+        self->io.irq2      = irq;
+        self->io.io_ext    = IO_EXTENT;
+        self->io.fifo_size = 16;
 
 	/* Lock the port that we need */
-	ret = check_region(idev->io.iobase2, idev->io.io_ext);
+	ret = check_region(self->io.iobase2, self->io.io_ext);
 	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      idev->io.iobase2);
-		/* irport_cleanup(self->idev);  */
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      self->io.iobase2);
+		/* irport_cleanup(self->self);  */
 		return -ENODEV;
 	}
-	request_region(idev->io.iobase2, idev->io.io_ext, idev->name);
+	request_region(self->io.iobase2, self->io.io_ext, driver_name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&idev->qos);
+	irda_init_max_qos_capabilies(&self->qos);
 	
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200;
 
-	idev->qos.min_turn_time.bits = qos_mtt_bits;
-	irda_qos_bits_to_value(&idev->qos);
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
 	
-	idev->flags = IFF_SIR|IFF_PIO;
+	self->flags = IFF_SIR|IFF_PIO;
+
+	/* Specify how much memory we want */
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+	
+	/* Allocate memory if needed */
+	if (self->rx_buff.truesize > 0) {
+		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+						      GFP_KERNEL);
+		if (self->rx_buff.head == NULL)
+			return -ENOMEM;
+		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	}
+	if (self->tx_buff.truesize > 0) {
+		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+						      GFP_KERNEL);
+		if (self->tx_buff.head == NULL) {
+			kfree(self->rx_buff.head);
+			return -ENOMEM;
+		}
+		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	}	
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	self->mode = IRDA_IRLAP;
 
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL;
-	idev->tx_buff.flags = GFP_KERNEL;
-
-	idev->rx_buff.truesize = 4000; 
-	idev->tx_buff.truesize = 4000;
-	
-	/* Initialize callbacks */
-	idev->change_speed    = irport_change_speed;
-	idev->wait_until_sent = irport_wait_until_sent;
-        idev->is_receiving    = irport_is_receiving;
-	idev->set_dtr_rts     = irport_set_dtr_rts;
-	idev->raw_write       = irport_raw_write;
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct, so lets do a little hack */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+ 	dev->priv = (void *) self;
+	self->netdev = dev;
 
 	/* Override the network functions we need to use */
-	idev->netdev.init            = irport_net_init;
-	idev->netdev.hard_start_xmit = irport_hard_xmit;
-	idev->netdev.open            = irport_net_open;
-	idev->netdev.stop            = irport_net_close;
+	dev->init            = irport_net_init;
+	dev->hard_start_xmit = irport_hard_xmit;
+	dev->open            = irport_net_open;
+	dev->stop            = irport_net_close;
+
+	/* Make ifconfig display some details */
+	dev->base_addr = iobase;
+	dev->irq = irq;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
 
-	/* Open the IrDA device */
-	irda_device_open(idev, driver_name, NULL);
-	
 	return 0;
 }
 
-static int irport_close(struct irda_device *idev)
+static int irport_close(struct irport_cb *self)
 {
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
 
-	/* Release the IO-port that this driver is using */
-	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
-	      idev->io.iobase2);
-	release_region(idev->io.iobase2, idev->io.io_ext);
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		irda_device_dongle_cleanup(self->dongle);
+	self->dongle = NULL;
+	
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+	}
 
-	irda_device_close(idev);
+	/* Release the IO-port that this driver is using */
+	IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
+	      self->io.iobase2);
+	release_region(self->io.iobase2, self->io.io_ext);
 
-	kfree(idev);
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+	
+	kfree(self);
 
 	return 0;
 }
 
-void irport_start(struct irda_device *idev, int iobase)
+void irport_start(struct irport_cb *self, int iobase)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&idev->lock, flags);
+	spin_lock_irqsave(&self->lock, flags);
 
-	irport_stop(idev, iobase);
+	irport_stop(self, iobase);
 
 	/* Initialize UART */
 	outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
@@ -235,14 +282,14 @@
 	/* Turn on interrups */
 	outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	spin_unlock_irqrestore(&self->lock, flags);
 }
 
-void irport_stop(struct irda_device *idev, int iobase)
+void irport_stop(struct irport_cb *self, int iobase)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&idev->lock, flags);
+	spin_lock_irqsave(&self->lock, flags);
 
 	/* Reset UART */
 	outb(0, iobase+UART_MCR);
@@ -250,7 +297,7 @@
 	/* Turn off interrupts */
 	outb(0, iobase+UART_IER);
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	spin_unlock_irqrestore(&self->lock, flags);
 }
 
 /*
@@ -261,18 +308,18 @@
  */
 int irport_probe(int iobase)
 {
-	DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
+	IRDA_DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
 
 	return 0;
 }
 
 /*
- * Function irport_change_speed (idev, speed)
+ * Function irport_change_speed (self, speed)
  *
  *    Set speed of IrDA port to specified baudrate
  *
  */
-void irport_change_speed(struct irda_device *idev, __u32 speed)
+void irport_change_speed(struct irport_cb *self, __u32 speed)
 {
 	unsigned long flags;
 	int iobase; 
@@ -280,17 +327,16 @@
 	int lcr;    /* Line control reg */
 	int divisor;
 
-	DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+	IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed);
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 	
 	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
+	self->io.speed = speed;
 
-	spin_lock_irqsave(&idev->lock, flags);
+	spin_lock_irqsave(&self->lock, flags);
 
 	/* Turn off interrupts */
 	outb(0, iobase+UART_IER); 
@@ -304,7 +350,7 @@
 	 * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
 	 * about this timeout since it will always be fast enough. 
 	 */
-	if (idev->io.baudrate < 38400)
+	if (self->io.speed < 38400)
 		fcr |= UART_FCR_TRIGGER_1;
 	else 
 		fcr |= UART_FCR_TRIGGER_14;
@@ -321,7 +367,7 @@
 	/* Turn on interrups */
 	outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	spin_unlock_irqrestore(&self->lock, flags);
 }
 
 /*
@@ -331,39 +377,38 @@
  *    more packets to send, we send them here.
  *
  */
-static void irport_write_wakeup(struct irda_device *idev)
+static void irport_write_wakeup(struct irport_cb *self)
 {
 	int actual = 0;
 	int iobase;
 	int fcr;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Finished with frame?  */
-	if (idev->tx_buff.len > 0)  {
+	if (self->tx_buff.len > 0)  {
 		/* Write data left in transmit buffer */
-		actual = irport_write(idev->io.iobase2, idev->io.fifo_size, 
-				      idev->tx_buff.data, idev->tx_buff.len);
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
+		actual = irport_write(self->io.iobase2, self->io.fifo_size, 
+				      self->tx_buff.data, self->tx_buff.len);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
 	} else {
-		iobase = idev->io.iobase2;
+		iobase = self->io.iobase2;
 		/* 
 		 *  Now serial buffer is almost free & we can start 
 		 *  transmission of another packet 
 		 */
-		idev->netdev.tbusy = 0; /* Unlock */
-		idev->stats.tx_packets++;
+		self->netdev->tbusy = 0; /* Unlock */
+		self->stats.tx_packets++;
 
 		/* Schedule network layer, so we can get some more frames */
 		mark_bh(NET_BH);
 
 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
 
-		if (idev->io.baudrate < 38400)
+		if (self->io.speed < 38400)
 			fcr |= UART_FCR_TRIGGER_1;
 		else 
 			fcr |= UART_FCR_TRIGGER_14;
@@ -391,7 +436,7 @@
 
 	/* Tx FIFO should be empty! */
 	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
 		return -1;
 	}
         
@@ -415,19 +460,19 @@
  */
 int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *self;
 	unsigned long flags;
 	int actual = 0;
 	int iobase;
+	__u32 speed;
 
 	ASSERT(dev != NULL, return 0;);
 	
-	idev = (struct irda_device *) dev->priv;
+	self = (struct irport_cb *) dev->priv;
 
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE) {
@@ -436,28 +481,32 @@
 			return -EBUSY;
 
 		WARNING("%s: transmit timed out\n", dev->name);
-		irport_start(idev, iobase);
-		irport_change_speed(idev, idev->io.baudrate);
+		irport_start(self, iobase);
+		irport_change_speed(self, self->io.speed );
 
 		dev->trans_start = jiffies;
 	}
 
-	spin_lock_irqsave(&idev->lock, flags);
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		irport_change_speed(self, speed);
+
+	spin_lock_irqsave(&self->lock, flags);
 
 	/* Init tx buffer */
-	idev->tx_buff.data = idev->tx_buff.head;
+	self->tx_buff.data = self->tx_buff.head;
 
         /* Copy skb to tx_buff while wrapping, stuffing and making CRC */
-	idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-					   idev->tx_buff.truesize);
+	self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize);
 	
-	idev->tx_buff.data += actual;
-	idev->tx_buff.len  -= actual;
+	self->tx_buff.data += actual;
+	self->tx_buff.len  -= actual;
 
 	/* Turn on transmit finished interrupt. Will fire immediately!  */
 	outb(UART_IER_THRI, iobase+UART_IER); 
 
-	spin_unlock_irqrestore(&idev->lock, flags);
+	spin_unlock_irqrestore(&self->lock, flags);
 
 	dev_kfree_skb(skb);
 	
@@ -465,30 +514,31 @@
 }
         
 /*
- * Function irport_receive (idev)
+ * Function irport_receive (self)
  *
  *    Receive one frame from the infrared port
  *
  */
-static void irport_receive(struct irda_device *idev) 
+static void irport_receive(struct irport_cb *self) 
 {
 	int boguscount = 0;
 	int iobase;
 
-	ASSERT(idev != NULL, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 
 	/*  
 	 * Receive all characters in Rx FIFO, unwrap and unstuff them. 
          * async_unwrap_char will deliver all found frames  
 	 */
 	do {
-		async_unwrap_char(idev, inb(iobase+UART_RX));
+		async_unwrap_char(self->netdev, &self->rx_buff, 
+				  inb(iobase+UART_RX));
 
 		/* Make sure we don't stay here to long */
 		if (boguscount++ > 32) {
-			DEBUG(2,__FUNCTION__ "(), breaking!\n");
+			IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n");
 			break;
 		}
 	} while (inb(iobase+UART_LSR) & UART_LSR_DR);	
@@ -501,45 +551,47 @@
  */
 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
 {
-	struct irda_device *idev = (struct irda_device *) dev_id;
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct irport_cb *self;
+	int boguscount = 0;
 	int iobase;
 	int iir, lsr;
-	int boguscount = 0;
 
-	if (!idev) {
+	if (!dev) {
 		WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq);
 		return;
 	}
+	self = (struct irport_cb *) dev->priv;
 
-	spin_lock(&idev->lock);
+	spin_lock(&self->lock);
 
-	idev->netdev.interrupt = 1;
+	dev->interrupt = 1;
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 
 	iir = inb(iobase+UART_IIR) & UART_IIR_ID;
 	while (iir) {
 		/* Clear interrupt */
 		lsr = inb(iobase+UART_LSR);
 
-		DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n", 
+		IRDA_DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n", 
 		      iir, lsr, iobase);
 
 		switch (iir) {
 		case UART_IIR_RLSI:
-			DEBUG(2, __FUNCTION__ "(), RLSI\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n");
 			break;
 		case UART_IIR_RDI:
 			/* Receive interrupt */
-			irport_receive(idev);
+			irport_receive(self);
 			break;
 		case UART_IIR_THRI:
 			if (lsr & UART_LSR_THRE)
 				/* Transmitter ready for data */
-				irport_write_wakeup(idev);
+				irport_write_wakeup(self);
 			break;
 		default:
-			DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
+			IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
 			break;
 		} 
 		
@@ -549,9 +601,9 @@
 
  	        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
 	}
-	idev->netdev.interrupt = 0;
+	dev->interrupt = 0;
 
-	spin_unlock(&idev->lock);
+	spin_unlock(&self->lock);
 }
 
 static int irport_net_init(struct net_device *dev)
@@ -572,24 +624,32 @@
  */
 static int irport_net_open(struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *self;
 	int iobase;
 
 	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	self = (struct irport_cb *) dev->priv;
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 
-	if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name, 
-			(void *) idev))
+	if (request_irq(self->io.irq2, irport_interrupt, 0, dev->name, 
+			(void *) dev))
 		return -EAGAIN;
 
-	irport_start(idev, iobase);
-	irda_device_net_open(dev);
+	irport_start(self, iobase);
 
-	/* Change speed to make sure dongles follow us again */
-	if (idev->change_speed)
-		idev->change_speed(idev, 9600);
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
+
+	/* FIXME: change speed of dongle */
 
 	MOD_INC_USE_COUNT;
 
@@ -597,30 +657,37 @@
 }
 
 /*
- * Function irport_net_close (idev)
+ * Function irport_net_close (self)
  *
  *    
  *
  */
 static int irport_net_close(struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct irport_cb *self;
 	int iobase;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	self = (struct irport_cb *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;)
+	iobase = self->io.iobase2;
 
-	iobase = idev->io.iobase2;
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
 
-	irda_device_net_close(dev);
-	irport_stop(idev, iobase);
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
 
-	free_irq(idev->io.irq2, idev);
+	irport_stop(self, iobase);
+
+	free_irq(self->io.irq2, dev);
 
 	MOD_DEC_USE_COUNT;
 
@@ -628,34 +695,36 @@
 }
 
 /*
- * Function irport_wait_until_sent (idev)
+ * Function irport_wait_until_sent (self)
  *
  *    Delay exectution until finished transmitting
  *
  */
-void irport_wait_until_sent(struct irda_device *idev)
+#if 0
+void irport_wait_until_sent(struct irport_cb *self)
 {
 	int iobase;
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 
 	/* Wait until Tx FIFO is empty */
 	while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		DEBUG(2, __FUNCTION__ "(), waiting!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), waiting!\n");
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(MSECS_TO_JIFFIES(60));
 	}
 }
+#endif
 
 /*
- * Function irport_is_receiving (idev)
+ * Function irport_is_receiving (self)
  *
  *    Returns true is we are currently receiving data
  *
  */
-static int irport_is_receiving(struct irda_device *idev)
+static int irport_is_receiving(struct irport_cb *self)
 {
-	return (idev->rx_buff.state != OUTSIDE_FRAME);
+	return (self->rx_buff.state != OUTSIDE_FRAME);
 }
 
 /*
@@ -664,14 +733,14 @@
  *    This function can be used by dongles etc. to set or reset the status
  *    of the dtr and rts lines
  */
-static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+static void irport_set_dtr_rts(struct net_device *dev, int dtr, int rts)
 {
+	struct irport_cb *self = dev->priv;
 	int iobase;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 
 	if (dtr)
 		dtr = UART_MCR_DTR;
@@ -681,19 +750,19 @@
 	outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR);
 }
 
-static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len)
+static int irport_raw_write(struct net_device *dev, __u8 *buf, int len)
 {
-	int iobase;
+	struct irport_cb *self = (struct irport_cb *) dev->priv;
 	int actual = 0;
+	int iobase;
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
 
-	iobase = idev->io.iobase2;
+	iobase = self->io.iobase2;
 
 	/* Tx FIFO should be empty! */
 	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
-		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
 		return -1;
 	}
         
@@ -708,33 +777,20 @@
 }
 
 #ifdef MODULE
-
 MODULE_PARM(io, "1-4i");
 MODULE_PARM(irq, "1-4i");
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode");
 
-/*
- * Function cleanup_module (void)
- *
- *    
- *
- */
 void cleanup_module(void)
 {
 	irport_cleanup();
 }
 
-/*
- * Function init_module (void)
- *
- *    
- */
 int init_module(void)
 {
 	return irport_init();
 }
-
 #endif /* MODULE */
 
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.3.23/linux/drivers/net/irda/irtty.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/irda/irtty.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Tue Sep 28 08:39:29 1999
+ * Modified at:   Wed Oct 20 00:05:43 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
@@ -29,6 +29,8 @@
 #include <linux/tty.h>
 #include <linux/init.h>
 #include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/segment.h>
 #include <asm/uaccess.h>
@@ -36,7 +38,6 @@
 #include <net/irda/irda.h>
 #include <net/irda/irtty.h>
 #include <net/irda/wrapper.h>
-#include <net/irda/irlap.h>
 #include <net/irda/timer.h>
 #include <net/irda/irda_device.h>
 
@@ -46,27 +47,31 @@
 
 static int qos_mtt_bits = 0x03;      /* 5 ms or more */
 
+/* Network device fuction prototypes */
 static int  irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static void irtty_wait_until_sent(struct irda_device *driver);
-static int  irtty_is_receiving(struct irda_device *idev);
-static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
-static int  irtty_raw_write(struct irda_device *idev, __u8 *buf, int len);
-static int  irtty_raw_read(struct irda_device *idev, __u8 *buf, int len, 
-			   int timeout);
-static void irtty_set_raw_mode(struct irda_device *dev, int mode);
 static int  irtty_net_init(struct net_device *dev);
 static int  irtty_net_open(struct net_device *dev);
 static int  irtty_net_close(struct net_device *dev);
+static int  irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *irtty_net_get_stats(struct net_device *dev);
 
+/* Line discipline function prototypes */
 static int  irtty_open(struct tty_struct *tty);
 static void irtty_close(struct tty_struct *tty);
 static int  irtty_ioctl(struct tty_struct *, void *, int, void *);
 static int  irtty_receive_room(struct tty_struct *tty);
-static void irtty_change_speed(struct irda_device *dev, __u32 speed);
 static void irtty_write_wakeup(struct tty_struct *tty);
-
 static void irtty_receive_buf(struct tty_struct *, const unsigned char *, 
 			      char *, int);
+
+/* IrDA specific function protoctypes */
+static int  irtty_is_receiving(struct irtty_cb *self);
+static int  irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts);
+static int  irtty_raw_write(struct net_device *dev, __u8 *buf, int len);
+static int  irtty_raw_read(struct net_device *dev, __u8 *buf, int len);
+static int  irtty_set_mode(struct net_device *dev, int mode);
+static int  irtty_change_speed(struct irda_task *task);
+
 char *driver_name = "irtty";
 
 int __init irtty_init(void)
@@ -140,13 +145,16 @@
  */
 static int irtty_open(struct tty_struct *tty) 
 {
+	struct net_device *dev;
 	struct irtty_cb *self;
 	char name[16];
+	int err;
 	
 	ASSERT(tty != NULL, return -EEXIST;);
 
 	/* First make sure we're not already connected. */
 	self = (struct irtty_cb *) tty->disc_data;
+
 	if (self != NULL && self->magic == IRTTY_MAGIC)
 		return -EEXIST;
 	
@@ -168,9 +176,8 @@
 	sprintf(name, "%s%d", tty->driver.name,
 		MINOR(tty->device) - tty->driver.minor_start +
 		tty->driver.name_base);
-	
-	/* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */
-	hashbin_insert(irtty, (QUEUE*) self, (int) self, NULL);
+
+	hashbin_insert(irtty, (queue_t *) self, (int) self, NULL);
 
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
@@ -179,11 +186,7 @@
 		tty->ldisc.flush_buffer(tty);
 	
 	self->magic = IRTTY_MAGIC;
-
-	/*
-	 *  Initialize driver
-	 */
-	self->idev.rx_buff.state = OUTSIDE_FRAME;
+	self->rx_buff.state = OUTSIDE_FRAME;
 
 	/* 
 	 *  Initialize QoS capabilities, we fill in all the stuff that
@@ -191,40 +194,71 @@
 	 *  that are not device dependent (such as link disconnect time) so
 	 *  this parameter can be set by IrLAP (or the user) instead. DB
 	 */
-	irda_init_max_qos_capabilies(&self->idev.qos);
+	irda_init_max_qos_capabilies(&self->qos);
 
 	/* The only value we must override it the baudrate */
-	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200;
-	self->idev.qos.min_turn_time.bits = qos_mtt_bits;
-	self->idev.flags = IFF_SIR | IFF_PIO;
-	irda_qos_bits_to_value(&self->idev.qos);
-
-	/* Specify which buffer allocation policy we need */
-	self->idev.rx_buff.flags = GFP_KERNEL;
-	self->idev.tx_buff.flags = GFP_KERNEL;
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	self->flags = IFF_SIR | IFF_PIO;
+	irda_qos_bits_to_value(&self->qos);
 
 	/* Specify how much memory we want */
-	self->idev.rx_buff.truesize = 4000; 
-	self->idev.tx_buff.truesize = 4000;
+	self->rx_buff.truesize = 4000; 
+	self->tx_buff.truesize = 4000;
+	
+	/* Allocate memory if needed */
+	if (self->rx_buff.truesize > 0) {
+		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+						      GFP_KERNEL);
+		if (self->rx_buff.head == NULL)
+			return -ENOMEM;
+		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	}
+	if (self->tx_buff.truesize > 0) {
+		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+						      GFP_KERNEL);
+		if (self->tx_buff.head == NULL) {
+			kfree(self->rx_buff.head);
+			return -ENOMEM;
+		}
+		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	}
+	
+      	self->magic = IRTTY_MAGIC;
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
 
-	/* Initialize callbacks */
-	self->idev.change_speed    = irtty_change_speed;
- 	self->idev.is_receiving    = irtty_is_receiving;
-	self->idev.wait_until_sent = irtty_wait_until_sent;
-	self->idev.set_dtr_rts     = irtty_set_dtr_rts;
-	self->idev.set_raw_mode    = irtty_set_raw_mode;
-	self->idev.raw_write       = irtty_raw_write;
-	self->idev.raw_read        = irtty_raw_read;
+	dev->priv = (void *) self;
+	self->netdev = dev;
 
 	/* Override the network functions we need to use */
-	self->idev.netdev.init            = irtty_net_init;
-	self->idev.netdev.hard_start_xmit = irtty_hard_xmit;
-	self->idev.netdev.open            = irtty_net_open;
-	self->idev.netdev.stop            = irtty_net_close;
+	dev->init            = irtty_net_init;
+	dev->hard_start_xmit = irtty_hard_xmit;
+	dev->open            = irtty_net_open;
+	dev->stop            = irtty_net_close;
+	dev->get_stats	     = irtty_net_get_stats;
+	dev->do_ioctl        = irtty_net_ioctl;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
 
-	/* Open the IrDA device */
-	irda_device_open(&self->idev, name, self);
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
 
 	MOD_INC_USE_COUNT;
 
@@ -245,39 +279,50 @@
 	/* First make sure we're connected. */
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRTTY_MAGIC, return;);
-
-	/* Remove driver */
-	irda_device_close(&self->idev);
-
+	
 	/* Stop tty */
 	tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 	tty->disc_data = 0;
-
+	
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		irda_device_dongle_cleanup(self->dongle);
+	self->dongle = NULL;
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdevice(self->netdev);
+		rtnl_unlock();
+	}
+	
 	self->tty = NULL;
 	self->magic = 0;
 	
 	self = hashbin_remove(irtty, (int) self, NULL);
-	
-	if (self != NULL)
-		kfree(self);
 
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
+	
+	kfree(self);
+	
  	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function irtty_stop_receiver (irda_device, stop)
+ * Function irtty_stop_receiver (self, stop)
  *
  *    
  *
  */
-static void irtty_stop_receiver(struct irda_device *idev, int stop)
+static void irtty_stop_receiver(struct irtty_cb *self, int stop)
 {
 	struct termios old_termios;
-	struct irtty_cb *self;
 	int cflag;
 
-	self = (struct irtty_cb *) idev->priv;
-
 	old_termios = *(self->tty->termios);
 	cflag = self->tty->termios->c_cflag;
 	
@@ -291,24 +336,16 @@
 }
 
 /* 
- *  Function irtty_change_speed (self, speed)
+ *  Function irtty_do_change_speed (self, speed)
  *
- *    Change the speed of the serial port. The driver layer must check that
- *    all transmission has finished using the irtty_wait_until_sent() 
- *    function.
+ *    Change the speed of the serial port.
  */
-static void irtty_change_speed(struct irda_device *idev, __u32 speed)
+static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
 {
         struct termios old_termios;
-	struct irtty_cb *self;
 	int cflag;
 
-	DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies); 
-
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	self = (struct irtty_cb *) idev->priv;
+	IRDA_DEBUG(0, __FUNCTION__ "(), <%ld>\n", jiffies); 
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRTTY_MAGIC, return;);
@@ -318,7 +355,7 @@
 
 	cflag &= ~CBAUD;
 
-	DEBUG(4, __FUNCTION__ "(), Setting speed to %d\n", speed);
+	IRDA_DEBUG(0, __FUNCTION__ "(), Setting speed to %d\n", speed);
 
 	switch (speed) {
 	case 1200:
@@ -350,6 +387,81 @@
 
 	self->tty->termios->c_cflag = cflag;
 	self->tty->driver.set_termios(self->tty, &old_termios);
+
+	self->io.speed = speed;
+}
+
+/*
+ * Function irtty_change_speed (instance, state, param)
+ *
+ *    State machine for changing speed of the device. We do it this way since
+ *    we cannot use schedule_timeout() when we are in interrupt context
+ */
+static int irtty_change_speed(struct irda_task *task)
+{
+	struct irtty_cb *self;
+	__u32 speed = (__u32) task->param;
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); 
+
+	self = (struct irtty_cb *) task->instance;
+
+	ASSERT(self != NULL, return -1;);
+
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+	case IRDA_TASK_WAIT:
+		/* Are we ready to change speed yet? */
+		if (self->tty->driver.chars_in_buffer(self->tty)) {
+			task->state = IRDA_TASK_WAIT;
+
+			/* Try again later */
+			ret = MSECS_TO_JIFFIES(20);
+			break;
+		}
+
+		if (self->dongle)
+			irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
+		else
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_INIT:
+		/* Go to default speed */
+		__irtty_change_speed(self, 9600);
+
+		/* Change speed of dongle */
+		if (irda_task_execute(self->dongle,
+				      self->dongle->issue->change_speed, 
+				      NULL, task, (void *) speed))
+		{
+			/* Dongle need more time to change its speed */
+			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+			/* Give dongle 1 sec to finish */
+			ret = MSECS_TO_JIFFIES(1000);
+		} else
+			/* Child finished immediately */
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_WAIT:
+		WARNING(__FUNCTION__ 
+			"(), changing speed of dongle timed out!\n");
+		ret = -1;		
+		break;
+	case IRDA_TASK_CHILD_DONE:
+		/* Finally we are ready to change the speed */
+		__irtty_change_speed(self, speed);
+		
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		ret = -1;
+		break;
+	}	
+	return ret;
 }
 
 /*
@@ -360,9 +472,11 @@
  */
 static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
 {
+	dongle_t *dongle;
+	struct irtty_info info;
 	struct irtty_cb *self;
-	int err = 0;
 	int size = _IOC_SIZE(cmd);
+	int err = 0;
 
 	self = (struct irtty_cb *) tty->disc_data;
 
@@ -370,13 +484,13 @@
 	ASSERT(self->magic == IRTTY_MAGIC, return -EBADR;);
 
 	if (_IOC_DIR(cmd) & _IOC_READ)
-		err = verify_area( VERIFY_WRITE, (void *) arg, size);
+		err = verify_area(VERIFY_WRITE, (void *) arg, size);
 	else if (_IOC_DIR(cmd) & _IOC_WRITE)
-		err = verify_area( VERIFY_READ, (void *) arg, size);
+		err = verify_area(VERIFY_READ, (void *) arg, size);
 	if (err)
 		return err;
 	
-	switch(cmd) {
+	switch (cmd) {
 	case TCGETS:
 	case TCGETA:
 		return n_tty_ioctl(tty, (struct file *) file, cmd, 
@@ -384,7 +498,34 @@
 		break;
 	case IRTTY_IOCTDONGLE:
 		/* Initialize dongle */
-		irda_device_init_dongle(&self->idev, (int) arg);
+		dongle = irda_device_dongle_init(self->netdev, (int) arg);
+		if (!dongle)
+			break;
+		
+		/* Initialize callbacks */
+		dongle->set_mode    = irtty_set_mode;
+		dongle->read        = irtty_raw_read;
+		dongle->write       = irtty_raw_write;
+		dongle->set_dtr_rts = irtty_set_dtr_rts;
+		
+		/* Bind dongle */
+		self->dongle = dongle;
+		
+		/* Now initialize the dongle!  */
+		dongle->issue->open(dongle, &self->qos);
+		
+		/* Reset dongle */
+		irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
+				  NULL);		
+		break;
+	case IRTTY_IOCGET:
+		ASSERT(self->netdev != NULL, return -1;);
+
+		memset(&info, 0, sizeof(struct irtty_info)); 
+		strncpy(info.name, self->netdev->name, 5);
+
+		if (copy_to_user(arg, &info, sizeof(struct irtty_info)))
+			return -EFAULT;
 		break;
 	default:
 		return -ENOIOCTLCMD;
@@ -405,34 +546,61 @@
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
-	DEBUG(5, __FUNCTION__ "(,,,count=%d)\n", count);
 	/* Read the characters out of the buffer */
  	while (count--) {
 		/* 
 		 *  Characters received with a parity error, etc?
 		 */
  		if (fp && *fp++) { 
-			DEBUG( 0, "Framing or parity error!\n");
-			irda_device_set_media_busy(&self->idev.netdev, TRUE);
-
+			IRDA_DEBUG(0, "Framing or parity error!\n");
+			irda_device_set_media_busy(self->netdev, TRUE);
+			
  			cp++;
  			continue;
  		}
+		
+		switch (self->mode) {
+		case IRDA_IRLAP:
+			/* Unwrap and destuff one byte */
+			async_unwrap_char(self->netdev, &self->rx_buff, *cp++);
+			break;
+		case IRDA_RAW:
+			/* What should we do when the buffer is full? */
+			if (self->rx_buff.len == self->rx_buff.truesize)
+				self->rx_buff.len = 0;
+			
+			self->rx_buff.data[self->rx_buff.len++] = *cp++;
+			break;
+		default:
+			break;
+		}
+	}
+}
 
-		DEBUG(6, __FUNCTION__ " char=0x%02x\n", *cp);
- 		if (self->idev.raw_mode) {
-			struct irda_device *idev = &self->idev;
+/*
+ * Function irtty_change_speed_complete (task)
+ *
+ *    Called when the change speed operation completes
+ *
+ */
+static int irtty_change_speed_complete(struct irda_task *task)
+{
+	struct irtty_cb *self;
 
-			/* What should we do when the buffer is full? */
-			if (idev->rx_buff.len == idev->rx_buff.truesize)
-				idev->rx_buff.len = 0;
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
-			idev->rx_buff.data[idev->rx_buff.len++] = *cp++;
-		} else {
-			/* Unwrap and destuff one byte */
-			async_unwrap_char(&self->idev, *cp++);
- 		}
-	}
+	self = (struct irtty_cb *) task->instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->netdev != NULL, return -1;);
+
+	/* Finished changing speed, so we are not busy any longer */
+	self->netdev->tbusy = 0;
+
+	/* Signal network layer so it can try to send the frame */
+	mark_bh(NET_BH);
+
+	return 0;
 }
 
 /*
@@ -444,29 +612,34 @@
 static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct irtty_cb *self;
-	struct irda_device *idev;
 	int actual = 0;
+	__u32 speed;
 
-	idev = (struct irda_device *) dev->priv;
-
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-	
-	self = (struct irtty_cb *) idev->priv;
-
+	self = (struct irtty_cb *) dev->priv;
 	ASSERT(self != NULL, return 0;);
-	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
 
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
+
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed) {
+		if (irda_task_execute(self, irtty_change_speed, 
+				      irtty_change_speed_complete, NULL,
+				      (void *) speed))	
+			/* 
+			 * Task not finished yet, so make the netdevice 
+			 * layer requeue the frame 
+			 */
+			return -EBUSY;
+	}
 	
 	/* Init tx buffer*/
-	idev->tx_buff.data = idev->tx_buff.head;
+	self->tx_buff.data = self->tx_buff.head;
 	
         /* Copy skb to tx_buff while wrapping, stuffing and making CRC */
-        idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-					   idev->tx_buff.truesize); 
+        self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+					   self->tx_buff.truesize); 
 
 	self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 
@@ -474,22 +647,22 @@
 
 	if (self->tty->driver.write)
 		actual = self->tty->driver.write(self->tty, 0, 
-						 idev->tx_buff.data, 
-						 idev->tx_buff.len);
+						 self->tx_buff.data, 
+						 self->tx_buff.len);
 
 	/* Hide the part we just transmitted */
-	idev->tx_buff.data += actual;
-	idev->tx_buff.len -= actual;
+	self->tx_buff.data += actual;
+	self->tx_buff.len -= actual;
 
-	idev->stats.tx_packets++;
-	idev->stats.tx_bytes += idev->tx_buff.len;
+	self->stats.tx_packets++;
+	self->stats.tx_bytes += self->tx_buff.len;
 #if 0
 	/* 
 	 *  Did we transmit the whole frame? Commented out for now since
 	 *  I must check if this optimalization really works. DB.
 	 */
- 	if ((idev->tx_buff.len) == 0) {
- 		DEBUG( 4, "irtty_xmit_buf: finished with frame!\n");
+ 	if ((self->tx_buff.len) == 0) {
+ 		IRDA_DEBUG( 4, "irtty_xmit_buf: finished with frame!\n");
  		self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
  		irda_unlock( &self->tbusy);
  	}
@@ -507,7 +680,7 @@
 */
 static int irtty_receive_room(struct tty_struct *tty) 
 {
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	return 65536;  /* We can handle an infinite amount of data. :-) */
 }
 
@@ -521,7 +694,6 @@
 static void irtty_write_wakeup(struct tty_struct *tty) 
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
-	struct irda_device *idev;
 	int actual = 0;
 	
 	/* 
@@ -530,26 +702,24 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRTTY_MAGIC, return;);
 
-	idev = &self->idev;
-
 	/* Finished with frame?  */
-	if (idev->tx_buff.len > 0)  {
+	if (self->tx_buff.len > 0)  {
 		/* Write data left in transmit buffer */
-		actual = tty->driver.write(tty, 0, idev->tx_buff.data, 
-					   idev->tx_buff.len);
+		actual = tty->driver.write(tty, 0, self->tx_buff.data, 
+					   self->tx_buff.len);
 
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
 	} else {		
 		/* 
 		 *  Now serial buffer is almost free & we can start 
 		 *  transmission of another packet 
 		 */
-		DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
+		IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
 		
 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
-		idev->netdev.tbusy = 0; /* Unlock */
+		self->netdev->tbusy = 0; /* Unlock */
 			
 		/* Tell network layer that we want more frames */
 		mark_bh(NET_BH);
@@ -557,34 +727,14 @@
 }
 
 /*
- * Function irtty_is_receiving (idev)
+ * Function irtty_is_receiving (self)
  *
  *    Return TRUE is we are currently receiving a frame
  *
  */
-static int irtty_is_receiving(struct irda_device *idev)
+static int irtty_is_receiving(struct irtty_cb *self)
 {
-	return (idev->rx_buff.state != OUTSIDE_FRAME);
-}
-
-/*
- * Function irtty_change_speed_ready (idev)
- *
- *    Are we completely finished with transmitting frames so its possible
- *    to change the speed of the serial port. Warning this function must
- *    be called with a process context!
- */
-static void irtty_wait_until_sent(struct irda_device *idev)
-{
-	struct irtty_cb *self = (struct irtty_cb *) idev->priv;
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-	
-	DEBUG(4, "Chars in buffer %d\n", 
-	      self->tty->driver.chars_in_buffer(self->tty));
-	
-	tty_wait_until_sent(self->tty, 0);
+	return (self->rx_buff.state != OUTSIDE_FRAME);
 }
 
 /*
@@ -593,15 +743,14 @@
  *    This function can be used by dongles etc. to set or reset the status
  *    of the dtr and rts lines
  */
-static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
 {
-	struct tty_struct *tty;
 	struct irtty_cb *self;
+	struct tty_struct *tty;
 	mm_segment_t fs;
 	int arg = 0;
 
-	self = (struct irtty_cb *) idev->priv;
-
+	self = (struct irtty_cb *) dev->priv;
 	tty = self->tty;
 
 #ifdef TIOCM_OUT2 /* Not defined for ARM */
@@ -627,52 +776,62 @@
 		ERROR(__FUNCTION__ "(), error doing ioctl!\n");
 	}
 	set_fs(fs);
+
+	return 0;
 }
 
 /*
- * Function irtty_set_raw_mode (idev, status)
+ * Function irtty_set_mode (self, status)
  *
  *    For the airport dongle, we need support for reading raw characters
  *    from the IrDA device. This function switches between those modes. 
  *    FALSE is the default mode, and will then treat incoming data as IrDA 
  *    packets.
  */
-void irtty_set_raw_mode(struct irda_device *idev, int status)
+int irtty_set_mode(struct net_device *dev, int mode)
 {
 	struct irtty_cb *self;
 
-	DEBUG(2, __FUNCTION__ "(), status=%s\n", status ? "TRUE" : "FALSE");
+	self = (struct irtty_cb *) dev->priv;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) idev->priv;
+	ASSERT(self != NULL, return -1;);
 
+	IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]);
+	
 	/* save status for driver */
-	self->idev.raw_mode = status;
+	self->mode = mode;
 	
 	/* reset the buffer state */
-	idev->rx_buff.data = idev->rx_buff.head;
-	idev->rx_buff.len = 0;
-	idev->rx_buff.state = OUTSIDE_FRAME;
+	self->rx_buff.data = self->rx_buff.head;
+	self->rx_buff.len = 0;
+	self->rx_buff.state = OUTSIDE_FRAME;
+
+	return 0;
 }
 
 /*
- * Function irtty_raw_read (idev, buf, len)
+ * Function irtty_raw_read (self, buf, len)
  *
  *    Receive incomming data. This function sleeps, so it must only be
  *    called with a process context. Timeout is currently defined to be
  *    a multiple of 10 ms.
  */
-static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len, 
-			  int timeout)
+static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len)
 {
+	struct irtty_cb *self;
 	int count;
 
-	buf = idev->rx_buff.data;
+	self = (struct irtty_cb *) dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
+
+	return 0;
+#if 0
+	buf = self->rx_buff.data;
 
 	/* Wait for the requested amount of data to arrive */
-	while (len < idev->rx_buff.len) {
+	while (len < self->rx_buff.len) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(MSECS_TO_JIFFIES(10));
 
@@ -680,30 +839,27 @@
 			break;
 	}
 	
-	count = idev->rx_buff.len < len ? idev->rx_buff.len : len;
+	count = self->rx_buff.len < len ? self->rx_buff.len : len;
 
 	/* 
 	 * Reset the state, this mean that a raw read is sort of a 
 	 * datagram read, and _not_ a stream style read. Be aware of the
 	 * difference. Implementing it the other way will just be painful ;-)
 	 */
-	idev->rx_buff.data = idev->rx_buff.head;
-	idev->rx_buff.len = 0;
-	idev->rx_buff.state = OUTSIDE_FRAME;
-
+	self->rx_buff.data = self->rx_buff.head;
+	self->rx_buff.len = 0;
+	self->rx_buff.state = OUTSIDE_FRAME;
+#endif
 	/* Return the amount we were able to get */
 	return count;
 }
 
-static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len)
+static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len)
 {
 	struct irtty_cb *self;
 	int actual = 0;
 
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-	
-	self = (struct irtty_cb *) idev->priv;
+	self = (struct irtty_cb *) dev->priv;
 
 	ASSERT(self != NULL, return 0;);
 	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
@@ -714,8 +870,6 @@
 	return actual;
 }
 
-
-
 static int irtty_net_init(struct net_device *dev)
 {
 	/* Set up to be a normal IrDA network device driver */
@@ -728,12 +882,26 @@
 
 static int irtty_net_open(struct net_device *dev)
 {
-	struct irda_device *idev = dev->priv;
+	struct irtty_cb *self = (struct irtty_cb *) dev->priv;
 
-	irda_device_net_open(dev);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
 
 	/* Make sure we can receive more data */
-	irtty_stop_receiver(idev, FALSE);
+	irtty_stop_receiver(self, FALSE);
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
 
 	MOD_INC_USE_COUNT;
 
@@ -742,16 +910,103 @@
 
 static int irtty_net_close(struct net_device *dev)
 {
-	struct irda_device *idev = dev->priv;
+	struct irtty_cb *self = (struct irtty_cb *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
 
 	/* Make sure we don't receive more data */
-	irtty_stop_receiver(idev, TRUE);
+	irtty_stop_receiver(self, TRUE);
 
-	irda_device_net_close(dev);
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
 
 	MOD_DEC_USE_COUNT;
 
 	return 0;
+}
+
+/*
+ * Function irtty_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct irtty_cb *self;
+	dongle_t *dongle;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRTTY_MAGIC, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		irda_task_execute(self, irtty_change_speed, NULL, NULL, 
+				  (void *) irq->ifr_baudrate);
+		break;
+	case SIOCSDONGLE: /* Set dongle */
+		/* Initialize dongle */
+		dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
+		if (!dongle)
+			break;
+		
+		dongle->set_mode    = irtty_set_mode;
+		dongle->read        = irtty_raw_read;
+		dongle->write       = irtty_raw_write;
+		dongle->set_dtr_rts = irtty_set_dtr_rts;
+		
+		self->dongle = dongle;
+
+		/* Now initialize the dongle!  */
+		dongle->issue->open(dongle, &self->qos);
+		
+		/* Reset dongle */
+		irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
+				  NULL);	
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = irtty_is_receiving(self);
+		break;
+	case SIOCSDTRRTS:
+		irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
+static struct net_device_stats *irtty_net_get_stats(struct net_device *dev)
+{
+	struct irtty_cb *self = (struct irtty_cb *) dev->priv;
+
+	return &self->stats;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c
--- v2.3.23/linux/drivers/net/irda/litelink.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/irda/litelink.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri May  7 12:50:33 1999
- * Modified at:   Sat Jun 26 17:01:05 1999
+ * Modified at:   Mon Oct 18 12:45:51 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -37,27 +37,25 @@
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
-#include <net/irda/dongle.h>
 
 #define MIN_DELAY 25      /* 15 us, but wait a little more to be sure */
 #define MAX_DELAY 10000   /* 1 ms */
 
-static void litelink_open(struct irda_device *idev, int type);
-static void litelink_close(struct irda_device *dev);
-static void litelink_change_speed(struct irda_device *dev, __u32);
-static void litelink_reset(struct irda_device *dev);
-static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos);
+static void litelink_open(dongle_t *self, struct qos_info *qos);
+static void litelink_close(dongle_t *self);
+static int  litelink_change_speed(struct irda_task *task);
+static int  litelink_reset(struct irda_task *task);
 
 /* These are the baudrates supported */
 static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
 
-static struct dongle dongle = {
-	LITELINK_DONGLE,
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_LITELINK_DONGLE,
 	litelink_open,
 	litelink_close,
 	litelink_reset,
 	litelink_change_speed,
-	litelink_init_qos,
 };
 
 int __init litelink_init(void)
@@ -70,114 +68,102 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void litelink_open(struct irda_device *idev, int type)
+static void litelink_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> litelink");
-
-        idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
 
 	MOD_INC_USE_COUNT;
 }
 
-static void litelink_close(struct irda_device *idev)
+static void litelink_close(dongle_t *self)
 {
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function litelink_change_speed (idev, speed)
+ * Function litelink_change_speed (task)
  *
  *    Change speed of the Litelink dongle. To cycle through the available 
  *    baud rates, pulse RTS low for a few ms.  
  */
-static void litelink_change_speed(struct irda_device *idev, __u32 speed)
+static int litelink_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
         int i;
 	
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
 	/* Clear RTS to reset dongle */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+	self->set_dtr_rts(self->dev, TRUE, FALSE);
 
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 	
 	/* Cycle through avaiable baudrates until we reach the correct one */
 	for (i=0; i<5 && baud_rates[i] != speed; i++) {
-
 		/* Set DTR, clear RTS */
-		irda_device_set_dtr_rts(idev, FALSE, TRUE);
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
 		
 		/* Sleep a minimum of 15 us */
 		udelay(MIN_DELAY);
 		
 		/* Set DTR, Set RTS */
-		irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
 		
 		/* Sleep a minimum of 15 us */
 		udelay(MIN_DELAY);
         }
+
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
 }
 
 /*
- * Function litelink_reset (dev)
+ * Function litelink_reset (task)
  *
  *      Reset the Litelink type dongle. Warning, this function must only be
  *      called with a process context!
  *
  */
-static void litelink_reset(struct irda_device *idev)
+static int litelink_reset(struct irda_task *task)
 {
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
+	dongle_t *self = (dongle_t *) task->instance;
+
 	/* Power on dongle */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* Clear RTS to reset dongle */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+	self->set_dtr_rts(self->dev, TRUE, FALSE);
 
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* Go back to normal mode */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
 	/* Sleep a minimum of 15 us */
 	udelay(MIN_DELAY);
 
 	/* This dongles speed defaults to 115200 bps */
-	idev->qos.baud_rate.value = 115200;
-}
+	self->speed = 115200;
 
-/*
- * Function litelink_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+	return 0;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Parallax Litelink dongle driver");	
 		
@@ -202,5 +188,4 @@
 {
 	litelink_cleanup();
 }
-
-#endif
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.3.23/linux/drivers/net/irda/pc87108.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/irda/pc87108.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Wed Aug 11 09:26:26 1999
+ * Modified at:   Wed Oct 20 00:08:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -29,11 +29,11 @@
  *
  *         __u8 bank;
  *     
- *         bank = inb( iobase+BSR);
+ *         bank = inb(iobase+BSR);
  *  
  *         do_your_stuff_here();
  *
- *         outb( bank, iobase+BSR);
+ *         outb(bank, iobase+BSR);
  *
  *    If you find bugs in this file, its very likely that the same bug
  *    will also be in w83977af_ir.c since the implementations is quite
@@ -51,6 +51,7 @@
 #include <linux/delay.h>
 #include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -101,19 +102,19 @@
 static int  pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
 			 unsigned int irq, unsigned int dma);
 #ifdef MODULE
-static int  pc87108_close(struct irda_device *idev);
+static int  pc87108_close(struct pc87108 *self);
 #endif /* MODULE */
 static int  pc87108_probe(int iobase, int board_addr, int irq, int dma);
-static void pc87108_pio_receive(struct irda_device *idev);
-static int  pc87108_dma_receive(struct irda_device *idev); 
-static int  pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
+static void pc87108_pio_receive(struct pc87108 *self);
+static int  pc87108_dma_receive(struct pc87108 *self); 
+static int  pc87108_dma_receive_complete(struct pc87108 *self, int iobase);
 static int  pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void pc87108_dma_write(struct irda_device *idev, int iobase);
-static void pc87108_change_speed(struct irda_device *idev, __u32 baud);
+static void pc87108_dma_write(struct pc87108 *self, int iobase);
+static void pc87108_change_speed(struct pc87108 *self, __u32 baud);
 static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void pc87108_wait_until_sent(struct irda_device *idev);
-static int  pc87108_is_receiving(struct irda_device *idev);
+static void pc87108_wait_until_sent(struct pc87108 *self);
+static int  pc87108_is_receiving(struct pc87108 *self);
 static int  pc87108_read_dongle_id (int iobase);
 static void pc87108_init_dongle_interface (int iobase, int dongle_id);
 
@@ -152,11 +153,11 @@
 {
 	int i;
 
-        DEBUG(4, __FUNCTION__ "()\n");
+        IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	for (i=0; i < 4; i++) {
 		if (dev_self[i])
-			pc87108_close(&(dev_self[i]->idev));
+			pc87108_close(dev_self[i]);
 	}
 }
 #endif /* MODULE */
@@ -170,12 +171,13 @@
 static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, 
 			unsigned int irq, unsigned int dma)
 {
+	struct net_device *dev;
 	struct pc87108 *self;
-	struct irda_device *idev;
-	int ret;
 	int dongle_id;
+	int ret;
+	int err;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1)
 		return -1;
@@ -194,90 +196,127 @@
 	/* Need to store self somewhere */
 	dev_self[i] = self;
 
-	idev = &self->idev;
-
 	/* Initialize IO */
-	idev->io.iobase    = iobase;
-        idev->io.irq       = irq;
-        idev->io.io_ext    = CHIP_IO_EXTENT;
-        idev->io.dma       = dma;
-        idev->io.fifo_size = 32;
+	self->io.iobase    = iobase;
+        self->io.irq       = irq;
+        self->io.io_ext    = CHIP_IO_EXTENT;
+        self->io.dma       = dma;
+        self->io.fifo_size = 32;
 
 	/* Lock the port that we need */
-	ret = check_region(idev->io.iobase, idev->io.io_ext);
+	ret = check_region(self->io.iobase, self->io.io_ext);
 	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      idev->io.iobase);
-		/* pc87108_cleanup( self->idev);  */
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      self->io.iobase);
+		/* pc87108_cleanup(self->self);  */
 		return -ENODEV;
 	}
-	request_region(idev->io.iobase, idev->io.io_ext, idev->name);
+	request_region(self->io.iobase, self->io.io_ext, driver_name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&idev->qos);
+	irda_init_max_qos_capabilies(&self->qos);
 	
 	/* The only value we must override it the baudrate */
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
 	
-	idev->qos.min_turn_time.bits = qos_mtt_bits;
-	irda_qos_bits_to_value(&idev->qos);
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
 	
-	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
-
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
-	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
 
 	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	idev->rx_buff.truesize = 14384; 
-	idev->tx_buff.truesize = 4000;
+	self->rx_buff.truesize = 14384; 
+	self->tx_buff.truesize = 4000;
+
+	/* Allocate memory if needed */
+	if (self->rx_buff.truesize > 0) {
+		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+						      GFP_KERNEL|GFP_DMA);
+		if (self->rx_buff.head == NULL)
+			return -ENOMEM;
+		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	}
+	if (self->tx_buff.truesize > 0) {
+		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+						      GFP_KERNEL|GFP_DMA);
+		if (self->tx_buff.head == NULL) {
+			kfree(self->rx_buff.head);
+			return -ENOMEM;
+		}
+		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	}
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
 	
-	/* Initialize callbacks */
-	idev->change_speed    = pc87108_change_speed;
-	idev->wait_until_sent = pc87108_wait_until_sent;
-	idev->is_receiving    = pc87108_is_receiving;
-     
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct, so lets do a little hack */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+	dev->priv = (void *) self;
+	self->netdev = dev;
+
 	/* Override the network functions we need to use */
-	idev->netdev.init            = pc87108_net_init;
-	idev->netdev.hard_start_xmit = pc87108_hard_xmit;
-	idev->netdev.open            = pc87108_net_open;
-	idev->netdev.stop            = pc87108_net_close;
+	dev->init            = pc87108_net_init;
+	dev->hard_start_xmit = pc87108_hard_xmit;
+	dev->open            = pc87108_net_open;
+	dev->stop            = pc87108_net_close;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
 
-	idev->io.dongle_id = dongle_id;
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
+	
+	self->io.dongle_id = dongle_id;
 	pc87108_init_dongle_interface(iobase, dongle_id);
 
-	/* Open the IrDA device */
-	irda_device_open(idev, driver_name, self);
-	
 	return 0;
 }
 
 #ifdef MODULE
 /*
- * Function pc87108_close (idev)
+ * Function pc87108_close (self)
  *
  *    Close driver instance
  *
  */
-static int pc87108_close(struct irda_device *idev)
+static int pc87108_close(struct pc87108 *self)
 {
-	struct pc87108 *self;
 	int iobase;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
 
-        iobase = idev->io.iobase;
-	self = (struct pc87108 *) idev->priv;
+        iobase = self->io.iobase;
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdev(self->netdev);
+		rtnl_unlock();
+	}
 
 	/* Release the PORT that this driver is using */
-	DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
-	release_region(idev->io.iobase, idev->io.io_ext);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", self->io.iobase);
+	release_region(self->io.iobase, self->io.io_ext);
 
-	irda_device_close(idev);
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
 
 	kfree(self);
 
@@ -297,7 +336,7 @@
 	__u8 temp=0;
 	int dongle_id;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Base Address and Interrupt Control Register BAIC */
 	outb(0, board_addr);
@@ -326,7 +365,7 @@
 	case 0: outb(0x08+temp, board_addr+1); break;
 	case 1: outb(0x10+temp, board_addr+1); break;
 	case 3: outb(0x18+temp, board_addr+1); break;
-	default: DEBUG( 0, __FUNCTION__ "(), invalid dma");
+	default: IRDA_DEBUG(0, __FUNCTION__ "(), invalid dma");
 	}
 
 	/* Mode Control Register MCTL */
@@ -344,13 +383,13 @@
 	}
 	
 	/* Switch to advanced mode */
-	switch_bank( iobase, BANK2);
+	switch_bank(iobase, BANK2);
 	outb(ECR1_EXT_SL, iobase+ECR1);
 	switch_bank(iobase, BANK0);
 
 	dongle_id = pc87108_read_dongle_id(iobase);
-	DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", 
-	      dongle_types[ dongle_id]);
+	IRDA_DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", 
+	      dongle_types[dongle_id]);
 	
 	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
 	switch_bank(iobase, BANK0);	
@@ -380,7 +419,7 @@
 	outb(2048 & 0xff, iobase+4);
 	outb((2048 >> 8) & 0x1f, iobase+5);
 	
-	DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
+	IRDA_DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
 
 	/* Enable receive interrupts */
 	switch_bank(iobase, BANK0);
@@ -397,14 +436,14 @@
  * that the user may have plugged/unplugged the IrDA Dongle.
  * 
  */
-static int pc87108_read_dongle_id ( int iobase)
+static int pc87108_read_dongle_id (int iobase)
 {
 	int dongle_id;
 	__u8 bank;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
 	/* Select Bank 7 */
 	switch_bank(iobase, BANK7);
@@ -416,7 +455,7 @@
 	udelay(50);
 	
 	/* IRCFG1: read the ID bits */
-	dongle_id = inb( iobase+4) & 0x0f;
+	dongle_id = inb(iobase+4) & 0x0f;
 
 #ifdef BROKEN_DONGLE_ID
 	if (dongle_id == 0x0a)
@@ -426,7 +465,7 @@
 	/* Go back to  bank 0 before returning */
 	switch_bank(iobase, BANK0);
 
-	DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
+	IRDA_DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
 
 	outb(bank, iobase+BSR);
 
@@ -446,49 +485,49 @@
 	int bank;
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
 	/* Select Bank 7 */
-	switch_bank( iobase, BANK7);
+	switch_bank(iobase, BANK7);
 	
 	/* IRCFG4: set according to dongle_id */
 	switch (dongle_id) {
 	case 0x00: /* same as */
 	case 0x01: /* Differential serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x02: /* same as */
 	case 0x03: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x04: /* Sharp RY5HD01 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x05: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x06: /* Single-ended serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x07: /* Consumer-IR only */
-		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
-		outb_p( 0x28, iobase+7); /* Set irsl[0-2] as output */
+		outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
 		break;
 	case 0x0A: /* same as */
 	case 0x0B: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x0C: /* same as */
@@ -497,28 +536,28 @@
 		 * Set irsl0 as input, irsl[1-2] as output, and separate 
 		 * inputs are used for SIR and MIR/FIR 
 		 */
-		outb( 0x48, iobase+7); 
+		outb(0x48, iobase+7); 
 		break;
 	case 0x0E: /* Supports SIR Mode only */
-		outb( 0x28, iobase+7); /* Set irsl[0-2] as output */
+		outb(0x28, iobase+7); /* Set irsl[0-2] as output */
 		break;
 	case 0x0F: /* No dongle connected */
-		DEBUG( 0, __FUNCTION__ "(), %s\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
 		       dongle_types[dongle_id]); 
-		DEBUG( 0, "***\n");
+		IRDA_DEBUG(0, "***\n");
 
-		switch_bank( iobase, BANK0);
-		outb( 0x62, iobase+MCR);
+		switch_bank(iobase, BANK0);
+		outb(0x62, iobase+MCR);
 		break;
 	default: 
-		DEBUG( 0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
 	}
 	
 	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
-	outb( 0x00, iobase+4);
+	outb(0x00, iobase+4);
 
 	/* Restore bank register */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 	
 } /* set_up_dongle_interface */
 
@@ -528,66 +567,66 @@
  *    Change speed of the attach dongle
  *
  */
-static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id)
+static void pc87108_change_dongle_speed(int iobase, int speed, int dongle_id)
 {
 	unsigned long flags;
 	__u8 bank;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
 	/* Select Bank 7 */
-	switch_bank( iobase, BANK7);
+	switch_bank(iobase, BANK7);
 	
 	/* IRCFG1: set according to dongle_id */
 	switch (dongle_id) {
 	case 0x00: /* same as */
 	case 0x01: /* Differential serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x02: /* same as */
 	case 0x03: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x04: /* Sharp RY5HD01 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
 		       dongle_types[dongle_id]); 
 	case 0x05: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x06: /* Single-ended serial interface */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x07: /* Consumer-IR only */
-		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
-		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
 		       dongle_types[dongle_id]); 
 	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
-		switch_bank( iobase, BANK7);
-		outb_p( 0x01, iobase+4);
+		switch_bank(iobase, BANK7);
+		outb_p(0x01, iobase+4);
 
-		if ( speed == 4000000) {
+		if (speed == 4000000) {
 			save_flags(flags);
 			cli();
-			outb( 0x81, iobase+4);
-			outb( 0x80, iobase+4);
+			outb(0x81, iobase+4);
+			outb(0x80, iobase+4);
 			restore_flags(flags);
 		}
 		else
-			outb_p( 0x00, iobase+4);
+			outb_p(0x00, iobase+4);
 		break;
 	case 0x0A: /* same as */
 	case 0x0B: /* Reserved */
-		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
 		       dongle_types[dongle_id]); 
 		break;
 	case 0x0C: /* same as */
@@ -596,78 +635,77 @@
 	case 0x0E: /* Supports SIR Mode only */
 		break;
 	case 0x0F: /* No dongle connected */
-		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
 		       dongle_types[dongle_id]);
 
-		switch_bank( iobase, BANK0); 
-		outb( 0x62, iobase+MCR);
+		switch_bank(iobase, BANK0); 
+		outb(0x62, iobase+MCR);
 		break;
 	default: 
-		DEBUG( 0, __FUNCTION__ "(), invalid data_rate\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
 	}
 	/* Restore bank register */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 }
 
 /*
- * Function pc87108_change_speed (idev, baud)
+ * Function pc87108_change_speed (self, baud)
  *
  *    Change the speed of the device
  *
  */
-static void pc87108_change_speed(struct irda_device *idev, __u32 speed)
+static void pc87108_change_speed(struct pc87108 *self, __u32 speed)
 {
 	__u8 mcr = MCR_SIR;
 	__u8 bank;
 	int iobase; 
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
+	self->io.speed = speed;
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
 	/* Disable interrupts */
-	switch_bank( iobase, BANK0);
-	outb( 0, iobase+IER);
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER);
 
 	  /* Select Bank 2 */
-	switch_bank( iobase, BANK2);
+	switch_bank(iobase, BANK2);
 
-	outb( 0x00, iobase+BGDH);
-	switch ( speed) {
-	case 9600:   outb( 0x0c, iobase+BGDL); break;
-	case 19200:  outb( 0x06, iobase+BGDL); break;
-	case 37600:  outb( 0x03, iobase+BGDL); break;
-	case 57600:  outb( 0x02, iobase+BGDL); break;
-	case 115200: outb( 0x01, iobase+BGDL); break;
+	outb(0x00, iobase+BGDH);
+	switch (speed) {
+	case 9600:   outb(0x0c, iobase+BGDL); break;
+	case 19200:  outb(0x06, iobase+BGDL); break;
+	case 37600:  outb(0x03, iobase+BGDL); break;
+	case 57600:  outb(0x02, iobase+BGDL); break;
+	case 115200: outb(0x01, iobase+BGDL); break;
 	case 576000:
-		switch_bank( iobase, BANK5);
+		switch_bank(iobase, BANK5);
 		
 		/* IRCR2: MDRS is set */
-		outb( inb( iobase+4) | 0x04, iobase+4);
+		outb(inb(iobase+4) | 0x04, iobase+4);
 	       
 		mcr = MCR_MIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
 		break;
 	case 1152000:
 		mcr = MCR_MIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
 		mcr = MCR_FIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
 		break;
 	default:
 		mcr = MCR_FIR;
-		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
 		break;
 	}
 
@@ -676,34 +714,34 @@
 	outb(mcr | MCR_TX_DFR, iobase+MCR);
 
 	/* Give some hits to the transceiver */
-	pc87108_change_dongle_speed( iobase, speed, idev->io.dongle_id);
+	pc87108_change_dongle_speed(iobase, speed, self->io.dongle_id);
 
 	/* Set FIFO threshold to TX17, RX16 */
-	switch_bank( iobase, BANK0);
-	outb( FCR_RXTH|     /* Set Rx FIFO threshold */
+	switch_bank(iobase, BANK0);
+	outb(FCR_RXTH|     /* Set Rx FIFO threshold */
 	      FCR_TXTH|     /* Set Tx FIFO threshold */
 	      FCR_TXSR|     /* Reset Tx FIFO */
 	      FCR_RXSR|     /* Reset Rx FIFO */
 	      FCR_FIFO_EN,  /* Enable FIFOs */
 	      iobase+FCR);
-	/* outb( 0xa7, iobase+FCR); */
+	/* outb(0xa7, iobase+FCR); */
 	
 	/* Set FIFO size to 32 */
-	switch_bank( iobase, BANK2);
-	outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
+	switch_bank(iobase, BANK2);
+	outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
 	
-	idev->netdev.tbusy = 0;
+	self->netdev->tbusy = 0;
 	
 	/* Enable some interrupts so we can receive frames */
-	switch_bank( iobase, BANK0); 
-	if ( speed > 115200) {
-		outb( IER_SFIF_IE, iobase+IER);
-		pc87108_dma_receive( idev);
+	switch_bank(iobase, BANK0); 
+	if (speed > 115200) {
+		outb(IER_SFIF_IE, iobase+IER);
+		pc87108_dma_receive(self);
 	} else
-		outb( IER_RXHDL_IE, iobase+IER);
+		outb(IER_RXHDL_IE, iobase+IER);
     	
 	/* Restore BSR */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 }
 
 /*
@@ -712,107 +750,106 @@
  *    Transmit the frame!
  *
  */
-static int pc87108_hard_xmit( struct sk_buff *skb, struct net_device *dev)
+static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct pc87108 *self;
 	int iobase;
 	__u8 bank;
 	int mtt;
 	
-	idev = (struct irda_device *) dev->priv;
+	self = (struct pc87108 *) dev->priv;
 
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
-	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+	IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
 	
 	/* Lock transmit buffer */
-	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
 	/* Decide if we should use PIO or DMA transfer */
-	if ( idev->io.baudrate > 115200) {
-		idev->tx_buff.data = idev->tx_buff.head;
-		memcpy(idev->tx_buff.data, skb->data, skb->len);
-		idev->tx_buff.len = skb->len;
+	if (self->io.speed > 115200) {
+		self->tx_buff.data = self->tx_buff.head;
+		memcpy(self->tx_buff.data, skb->data, skb->len);
+		self->tx_buff.len = skb->len;
 
-		mtt = irda_get_mtt( skb);
-	        if ( mtt > 50) {
+		mtt = irda_get_mtt(skb);
+	        if (mtt > 50) {
 			/* Adjust for timer resolution */
 			mtt = mtt / 125 + 1;
 
 			/* Setup timer */
-			switch_bank( iobase, BANK4);
-			outb( mtt & 0xff, iobase+TMRL);
-			outb(( mtt >> 8) & 0x0f, iobase+TMRH);
+			switch_bank(iobase, BANK4);
+			outb(mtt & 0xff, iobase+TMRL);
+			outb((mtt >> 8) & 0x0f, iobase+TMRH);
 			
 			/* Start timer */
-			outb( IRCR1_TMR_EN, iobase+IRCR1);
-			idev->io.direction = IO_XMIT;
+			outb(IRCR1_TMR_EN, iobase+IRCR1);
+			self->io.direction = IO_XMIT;
 			
 			/* Enable timer interrupt */
-			switch_bank( iobase, BANK0);
-			outb( IER_TMR_IE, iobase+IER);
+			switch_bank(iobase, BANK0);
+			outb(IER_TMR_IE, iobase+IER);
 		} else {
 			/* Use udelay for delays less than 50 us. */
 			if (mtt)
-				udelay( mtt);
+				udelay(mtt);
 
 			/* Enable DMA interrupt */
-			switch_bank( iobase, BANK0);
-	 		outb( IER_DMA_IE, iobase+IER);
-	     		pc87108_dma_write( idev, iobase);
+			switch_bank(iobase, BANK0);
+	 		outb(IER_DMA_IE, iobase+IER);
+	     		pc87108_dma_write(self, iobase);
 		}
         } else {
-	        idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-						   idev->tx_buff.truesize);
+	        self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+						   self->tx_buff.truesize);
 		
-		idev->tx_buff.data = idev->tx_buff.head;
+		self->tx_buff.data = self->tx_buff.head;
 		
 		/* Add interrupt on tx low level (will fire immediately) */
-		switch_bank( iobase, BANK0);
-		outb( IER_TXLDL_IE, iobase+IER);
+		switch_bank(iobase, BANK0);
+		outb(IER_TXLDL_IE, iobase+IER);
 	}
-	dev_kfree_skb( skb);
+	dev_kfree_skb(skb);
 
 	/* Restore bank register */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 
 	return 0;
 }
 
 /*
- * Function pc87108_dma_xmit (idev, iobase)
+ * Function pc87108_dma_xmit (self, iobase)
  *
  *    Transmit data using DMA
  *
  */
-static void pc87108_dma_write( struct irda_device *idev, int iobase)
+static void pc87108_dma_write(struct pc87108 *self, int iobase)
 {
 	int bsr;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Save current bank */
-	bsr = inb( iobase+BSR);
+	bsr = inb(iobase+BSR);
 
 	/* Disable DMA */
 	switch_bank(iobase, BANK0);
-	outb( inb( iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
 
-	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
 		  DMA_MODE_WRITE);
 	
-	idev->io.direction = IO_XMIT;
+	self->io.direction = IO_XMIT;
 	
 	/* Choose transmit DMA channel  */ 
 	switch_bank(iobase, BANK2);
-	outb( inb( iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, 
+	outb(inb(iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, 
 	      iobase+ECR1);
 	
 	/* Enable DMA */
@@ -824,7 +861,7 @@
 }
 
 /*
- * Function pc87108_pio_xmit (idev, iobase)
+ * Function pc87108_pio_xmit (self, iobase)
  *
  *    Transmit data using PIO. Returns the number of bytes that actually
  *    got transfered
@@ -835,17 +872,17 @@
 	int actual = 0;
 	__u8 bank;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
-	switch_bank( iobase, BANK0);
-	if (!(inb_p( iobase+LSR) & LSR_TXEMP)) {
-		DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+	switch_bank(iobase, BANK0);
+	if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
+		IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
 
 		fifo_size -= 17;
-		DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+		IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
 	}
 
 	/* Fill FIFO with current frame */
@@ -854,7 +891,7 @@
 		outb(buf[actual++], iobase+TXD);
 	}
         
-	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
 	      fifo_size, actual, len);
 
 	/* Restore bank */
@@ -864,74 +901,69 @@
 }
 
 /*
- * Function pc87108_dma_xmit_complete (idev)
+ * Function pc87108_dma_xmit_complete (self)
  *
  *    The transfer of a frame in finished. This function will only be called 
  *    by the interrupt handler
  *
  */
-static void pc87108_dma_xmit_complete( struct irda_device *idev)
+static void pc87108_dma_xmit_complete(struct pc87108 *self)
 {
 	int iobase;
 	__u8 bank;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
 	/* Disable DMA */
-	switch_bank( iobase, BANK0);
-	outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	switch_bank(iobase, BANK0);
+	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
 	
 	/* Check for underrrun! */
-	if ( inb( iobase+ASCR) & ASCR_TXUR) {
-		idev->stats.tx_errors++;
-		idev->stats.tx_fifo_errors++;
+	if (inb(iobase+ASCR) & ASCR_TXUR) {
+		self->stats.tx_errors++;
+		self->stats.tx_fifo_errors++;
 		
 		/* Clear bit, by writing 1 into it */
-		outb( ASCR_TXUR, iobase+ASCR);
+		outb(ASCR_TXUR, iobase+ASCR);
 	} else {
-		idev->stats.tx_packets++;
-		idev->stats.tx_bytes +=  idev->tx_buff.len;
+		self->stats.tx_packets++;
+		self->stats.tx_bytes +=  self->tx_buff.len;
 	}
 	
 	/* Unlock tx_buff and request another frame */
-	idev->netdev.tbusy = 0; /* Unlock */
-	idev->media_busy = FALSE;
+	self->netdev->tbusy = 0; /* Unlock */
 	
 	/* Tell the network layer, that we can accept more frames */
-	mark_bh( NET_BH);
+	mark_bh(NET_BH);
 
 	/* Restore bank */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 }
 
 /*
- * Function pc87108_dma_receive (idev)
+ * Function pc87108_dma_receive (self)
  *
  *    Get ready for receiving a frame. The device will initiate a DMA
  *    if it starts to receive a frame.
  *
  */
-static int pc87108_dma_receive(struct irda_device *idev) 
+static int pc87108_dma_receive(struct pc87108 *self) 
 {
-	struct pc87108 *self;
 	int iobase;
 	__u8 bsr;
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
 
-	DEBUG(4, __FUNCTION__ "\n");
+	IRDA_DEBUG(4, __FUNCTION__ "\n");
 
-	self = idev->priv;
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Save current bank */
 	bsr = inb(iobase+BSR);
@@ -940,12 +972,12 @@
 	switch_bank(iobase, BANK0);
 	outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
 
-	setup_dma(idev->io.dma, idev->rx_buff.data, 
-		  idev->rx_buff.truesize, DMA_MODE_READ);
+	setup_dma(self->io.dma, self->rx_buff.data, 
+		  self->rx_buff.truesize, DMA_MODE_READ);
 	
 	/* driver->media_busy = FALSE; */
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
 
 	/* Reset Rx FIFO. This will also flush the ST_FIFO */
 	outb(FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
@@ -953,7 +985,7 @@
 
 	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
 	switch_bank(iobase, BANK2);
-	outb((inb( iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, 
+	outb((inb(iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, 
 	     iobase+ECR1);
 	
 	/* enable DMA */
@@ -963,40 +995,38 @@
 	/* Restore bank register */
 	outb(bsr, iobase+BSR);
 	
-	DEBUG(4, __FUNCTION__ "(), done!\n");	
+	IRDA_DEBUG(4, __FUNCTION__ "(), done!\n");	
 	
 	return 0;
 }
 
 /*
- * Function pc87108_dma_receive_complete (idev)
+ * Function pc87108_dma_receive_complete (self)
  *
  *    Finished with receiving frames
  *
  *    
  */
-static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
+static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase)
 {
 	struct sk_buff *skb;
-	struct pc87108 *self;
 	struct st_fifo *st_fifo;
-	int len;
 	__u8 bank;
 	__u8 status;
+	int len;
 
-	self = idev->priv;
 	st_fifo = &self->st_fifo;
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 	
 	/* Read status FIFO */
 	switch_bank(iobase, BANK5);
-	while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) {
-		st_fifo->entries[ st_fifo->tail].status = status;
+	while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
+		st_fifo->entries[st_fifo->tail].status = status;
 
-		st_fifo->entries[ st_fifo->tail].len  = inb(iobase+RFLFL);
-		st_fifo->entries[ st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+		st_fifo->entries[st_fifo->tail].len  = inb(iobase+RFLFL);
+		st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
 		
 		st_fifo->tail++;
 		st_fifo->len++;
@@ -1016,28 +1046,28 @@
 		if (status & FRM_ST_ERR_MSK) {
 			if (status & FRM_ST_LOST_FR) {
 				/* Add number of lost frames to stats */
-				idev->stats.rx_errors += len;	
+				self->stats.rx_errors += len;	
 			} else {
 				/* Skip frame */
-				idev->stats.rx_errors++;
+				self->stats.rx_errors++;
 				
-				idev->rx_buff.data += len;
+				self->rx_buff.data += len;
 			
 				if (status & FRM_ST_MAX_LEN)
-					idev->stats.rx_length_errors++;
+					self->stats.rx_length_errors++;
 				
 				if (status & FRM_ST_PHY_ERR) 
-					idev->stats.rx_frame_errors++;
+					self->stats.rx_frame_errors++;
 				
 				if (status & FRM_ST_BAD_CRC) 
-					idev->stats.rx_crc_errors++;
+					self->stats.rx_crc_errors++;
 			}
 			/* The errors below can be reported in both cases */
 			if (status & FRM_ST_OVR1)
-				idev->stats.rx_fifo_errors++;
+				self->stats.rx_fifo_errors++;
 			
 			if (status & FRM_ST_OVR2)
-				idev->stats.rx_fifo_errors++;
+				self->stats.rx_fifo_errors++;
 			
 		} else {
 			/* Check if we have transfered all data to memory */
@@ -1057,10 +1087,10 @@
 			/* Should be OK then */			
 			skb = dev_alloc_skb(len+1);
 			if (skb == NULL)  {
-				printk( KERN_INFO __FUNCTION__ 
+				printk(KERN_INFO __FUNCTION__ 
 					"(), memory squeeze, dropping frame.\n");
 				/* Restore bank register */
-				outb( bank, iobase+BSR);
+				outb(bank, iobase+BSR);
 
 				return FALSE;
 			}
@@ -1069,22 +1099,22 @@
 			skb_reserve(skb, 1); 
 
 			/* Copy frame without CRC */
-			if (idev->io.baudrate < 4000000) {
+			if (self->io.speed < 4000000) {
 				skb_put(skb, len-2);
-				memcpy(skb->data, idev->rx_buff.data, len-2);
+				memcpy(skb->data, self->rx_buff.data, len-2);
 			} else {
 				skb_put(skb, len-4);
-				memcpy(skb->data, idev->rx_buff.data, len-4);
+				memcpy(skb->data, self->rx_buff.data, len-4);
 			}
 
 			/* Move to next frame */
-			idev->rx_buff.data += len;
-			idev->stats.rx_packets++;
+			self->rx_buff.data += len;
+			self->stats.rx_packets++;
 
-			skb->dev = &idev->netdev;
+			skb->dev = self->netdev;
 			skb->mac.raw  = skb->data;
 			skb->protocol = htons(ETH_P_IRDA);
-			netif_rx( skb);
+			netif_rx(skb);
 		}
 	}
 	/* Restore bank register */
@@ -1094,60 +1124,59 @@
 }
 
 /*
- * Function pc87108_pio_receive (idev)
+ * Function pc87108_pio_receive (self)
  *
  *    Receive all data in receiver FIFO
  *
  */
-static void pc87108_pio_receive( struct irda_device *idev) 
+static void pc87108_pio_receive(struct pc87108 *self) 
 {
 	__u8 byte = 0x00;
 	int iobase;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 	
 	/*  Receive all characters in Rx FIFO */
 	do {
 		byte = inb(iobase+RXD);
-		async_unwrap_char(idev, byte);
+		async_unwrap_char(self->netdev, &self->rx_buff, byte);
 
 	} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */	
 }
 
 /*
- * Function pc87108_sir_interrupt (idev, eir)
+ * Function pc87108_sir_interrupt (self, eir)
  *
  *    Handle SIR interrupt
  *
  */
-static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir)
+static __u8 pc87108_sir_interrupt(struct pc87108 *self, int eir)
 {
 	int actual;
 	__u8 new_ier = 0;
 
 	/* Transmit FIFO low on data */
-	if ( eir & EIR_TXLDL_EV) {
+	if (eir & EIR_TXLDL_EV) {
 		/* Write data left in transmit buffer */
-		actual = pc87108_pio_write(idev->io.iobase, 
-					   idev->tx_buff.data, 
-					   idev->tx_buff.len, 
-					   idev->io.fifo_size);
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
+		actual = pc87108_pio_write(self->io.iobase, 
+					   self->tx_buff.data, 
+					   self->tx_buff.len, 
+					   self->io.fifo_size);
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
 		
-		idev->io.direction = IO_XMIT;
+		self->io.direction = IO_XMIT;
 
 		/* Check if finished */
-		if (idev->tx_buff.len > 0)
+		if (self->tx_buff.len > 0)
 			new_ier |= IER_TXLDL_IE;
 		else { 
-			idev->netdev.tbusy = 0; /* Unlock */
-			idev->stats.tx_packets++;
+			self->netdev->tbusy = 0; /* Unlock */
+			self->stats.tx_packets++;
 			
 		        mark_bh(NET_BH);	
 
@@ -1156,16 +1185,16 @@
 			
 	}
 	/* Check if transmission has completed */
-	if ( eir & EIR_TXEMP_EV) {
+	if (eir & EIR_TXEMP_EV) {
 		
 		/* Turn around and get ready to receive some data */
-		idev->io.direction = IO_RECV;
+		self->io.direction = IO_RECV;
 		new_ier |= IER_RXHDL_IE;
 	}
 
 	/* Rx FIFO threshold or timeout */
-	if ( eir & EIR_RXHDL_EV) {
-		pc87108_pio_receive( idev);
+	if (eir & EIR_RXHDL_EV) {
+		pc87108_pio_receive(self);
 
 		/* Keep receiving */
 		new_ier |= IER_RXHDL_IE;
@@ -1174,22 +1203,22 @@
 }
 
 /*
- * Function pc87108_fir_interrupt (idev, eir)
+ * Function pc87108_fir_interrupt (self, eir)
  *
  *    Handle MIR/FIR interrupt
  *
  */
-static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase,
-				   int eir)
+static __u8 pc87108_fir_interrupt(struct pc87108 *self, int iobase,
+				  int eir)
 {
 	__u8 new_ier = 0;
 	__u8 bank;
 
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 	
 	/* Status event, or end of frame detected in FIFO */
 	if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
-		if (pc87108_dma_receive_complete( idev, iobase)) {
+		if (pc87108_dma_receive_complete(self, iobase)) {
 
 			/* Wait for next status FIFO interrupt */
 			new_ier |= IER_SFIF_IE;
@@ -1197,52 +1226,52 @@
 			/* DMA not finished yet */
 
 			/* Set timer value, resolution 125 us */
-			switch_bank( iobase, BANK4);
-			outb( 0x0f, iobase+TMRL); /* 125 us */
-			outb( 0x00, iobase+TMRH);
+			switch_bank(iobase, BANK4);
+			outb(0x0f, iobase+TMRL); /* 125 us */
+			outb(0x00, iobase+TMRH);
 
 			/* Start timer */
-			outb( IRCR1_TMR_EN, iobase+IRCR1);
+			outb(IRCR1_TMR_EN, iobase+IRCR1);
 
 			new_ier |= IER_TMR_IE;
 		}
 	}
 	/* Timer finished */
-	if ( eir & EIR_TMR_EV) {
+	if (eir & EIR_TMR_EV) {
 		/* Disable timer */
-		switch_bank( iobase, BANK4);
-		outb( 0, iobase+IRCR1);
+		switch_bank(iobase, BANK4);
+		outb(0, iobase+IRCR1);
 
 		/* Clear timer event */
 		switch_bank(iobase, BANK0);
-		outb( ASCR_CTE, iobase+ASCR);
+		outb(ASCR_CTE, iobase+ASCR);
 
 		/* Check if this is a TX timer interrupt */
-		if ( idev->io.direction == IO_XMIT) {
-			pc87108_dma_write( idev, iobase);
+		if (self->io.direction == IO_XMIT) {
+			pc87108_dma_write(self, iobase);
 
 			/*  Interrupt on DMA */
 			new_ier |= IER_DMA_IE;
 		} else {
 			/* Check if DMA has now finished */
-			pc87108_dma_receive_complete( idev, iobase);
+			pc87108_dma_receive_complete(self, iobase);
 
 			new_ier |= IER_SFIF_IE;
 		}
 	}	
 	/* Finished with transmission */
-	if ( eir & EIR_DMA_EV) {
-		pc87108_dma_xmit_complete( idev);
+	if (eir & EIR_DMA_EV) {
+		pc87108_dma_xmit_complete(self);
 		
 		/* Check if there are more frames to be transmitted */
-		if ( irda_device_txqueue_empty( idev)) {
+		if (irda_device_txqueue_empty(self->netdev)) {
 			/* Prepare for receive */
-			pc87108_dma_receive( idev);
+			pc87108_dma_receive(self);
 			
 			new_ier = IER_LS_IE|IER_SFIF_IE;
 		}
 	}
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 
 	return new_ier;
 }
@@ -1255,51 +1284,52 @@
  */
 static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct pc87108 *self;
 	__u8 bsr, eir, ier;
 	int iobase;
 
-	struct irda_device *idev = (struct irda_device *) dev_id;
-
-	if (idev == NULL) {
-		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
+	if (!dev) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
 			driver_name, irq);
 		return;
 	}
+	self = (struct pc87108 *) dev->priv;
 
-	idev->netdev.interrupt = 1;
+	dev->interrupt = 1;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Save current bank */
-	bsr = inb( iobase+BSR);
+	bsr = inb(iobase+BSR);
 
-	switch_bank( iobase, BANK0);	
-	ier = inb( iobase+IER); 
-	eir = inb( iobase+EIR) & ier; /* Mask out the interesting ones */ 
+	switch_bank(iobase, BANK0);	
+	ier = inb(iobase+IER); 
+	eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */ 
 
-	outb( 0, iobase+IER); /* Disable interrupts */
+	outb(0, iobase+IER); /* Disable interrupts */
 	
-	if ( eir) {
+	if (eir) {
 		/* Dispatch interrupt handler for the current speed */
-		if ( idev->io.baudrate > 115200)
-			ier = pc87108_fir_interrupt( idev, iobase, eir);
+		if (self->io.speed > 115200)
+			ier = pc87108_fir_interrupt(self, iobase, eir);
 		else
-			ier = pc87108_sir_interrupt( idev, eir);
+			ier = pc87108_sir_interrupt(self, eir);
 	}
 
-	outb( ier, iobase+IER);   /* Restore interrupts */
-	outb( bsr, iobase+BSR);   /* Restore bank register */
+	outb(ier, iobase+IER);   /* Restore interrupts */
+	outb(bsr, iobase+BSR);   /* Restore bank register */
 
-	idev->netdev.interrupt = 0;
+	dev->interrupt = 0;
 }
 
 /*
- * Function pc87108_wait_until_sent (idev)
+ * Function pc87108_wait_until_sent (self)
  *
  *    This function should put the current thread to sleep until all data 
  *    have been sent, so it is safe to f.eks. change the speed.
  */
-static void pc87108_wait_until_sent( struct irda_device *idev)
+static void pc87108_wait_until_sent(struct pc87108 *self)
 {
 	/* Just delay 60 ms */
 	current->state = TASK_INTERRUPTIBLE;
@@ -1307,33 +1337,32 @@
 }
 
 /*
- * Function pc87108_is_receiving (idev)
+ * Function pc87108_is_receiving (self)
  *
  *    Return TRUE is we are currently receiving a frame
  *
  */
-static int pc87108_is_receiving( struct irda_device *idev)
+static int pc87108_is_receiving(struct pc87108 *self)
 {
 	int status = FALSE;
 	int iobase;
 	__u8 bank;
 
-	ASSERT( idev != NULL, return FALSE;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	ASSERT(self != NULL, return FALSE;);
 
-	if ( idev->io.baudrate > 115200) {
-		iobase = idev->io.iobase;
+	if (self->io.speed > 115200) {
+		iobase = self->io.iobase;
 
 		/* Check if rx FIFO is not empty */
-		bank = inb( iobase+BSR);
-		switch_bank( iobase, BANK2);
-		if (( inb( iobase+RXFLV) & 0x3f) != 0) {
+		bank = inb(iobase+BSR);
+		switch_bank(iobase, BANK2);
+		if ((inb(iobase+RXFLV) & 0x3f) != 0) {
 			/* We are receiving something */
 			status =  TRUE;
 		}
-		outb( bank, iobase+BSR);
+		outb(bank, iobase+BSR);
 	} else 
-		status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+		status = (self->rx_buff.state != OUTSIDE_FRAME);
 	
 	return status;
 }
@@ -1344,12 +1373,12 @@
  *    Initialize network device
  *
  */
-static int pc87108_net_init( struct net_device *dev)
+static int pc87108_net_init(struct net_device *dev)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Setup to be a normal IrDA network device driver */
-	irda_device_setup( dev);
+	irda_device_setup(dev);
 
 	/* Insert overrides below this line! */
 
@@ -1363,46 +1392,54 @@
  *    Start the device
  *
  */
-static int pc87108_net_open( struct net_device *dev)
+static int pc87108_net_open(struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct pc87108 *self;
 	int iobase;
 	__u8 bank;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	ASSERT(dev != NULL, return -1;);
+	self = (struct pc87108 *) dev->priv;
 	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
-	if (request_irq( idev->io.irq, pc87108_interrupt, 0, idev->name, 
-			 (void *) idev)) {
+	if (request_irq(self->io.irq, pc87108_interrupt, 0, dev->name, 
+			 (void *) dev)) {
 		return -EAGAIN;
 	}
 	/*
 	 * Always allocate the DMA channel after the IRQ,
 	 * and clean up on failure.
 	 */
-	if (request_dma(idev->io.dma, idev->name)) {
-		free_irq( idev->io.irq, idev);
+	if (request_dma(self->io.dma, dev->name)) {
+		free_irq(self->io.irq, self);
 		return -EAGAIN;
 	}
 	
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 	
 	/* turn on interrupts */
-	switch_bank( iobase, BANK0);
-	outb( IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+	switch_bank(iobase, BANK0);
+	outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
 
 	/* Restore bank register */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 
-	irda_device_net_open(dev);
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
 
 	MOD_INC_USE_COUNT;
 
@@ -1417,23 +1454,29 @@
  */
 static int pc87108_net_close(struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct pc87108 *self;
 	int iobase;
 	__u8 bank;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	irda_device_net_close(dev);
-
 	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	self = (struct pc87108 *) dev->priv;
 	
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
+
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
-	disable_dma(idev->io.dma);
+	disable_dma(self->io.dma);
 
 	/* Save current bank */
 	bank = inb(iobase+BSR);
@@ -1442,8 +1485,8 @@
 	switch_bank(iobase, BANK0);
 	outb(0, iobase+IER); 
        
-	free_irq(idev->io.irq, idev);
-	free_dma(idev->io.dma);
+	free_irq(self->io.irq, self);
+	free_dma(self->io.dma);
 
 	/* Restore bank register */
 	outb(bank, iobase+BSR);
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.3.23/linux/drivers/net/irda/smc-ircc.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/irda/smc-ircc.c	Mon Oct 25 20:49:42 1999
@@ -106,7 +106,7 @@
 {
 	int i;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
 		int ioaddr = io[i];
 		if (check_region(ioaddr, CHIP_IO_EXTENT))
@@ -114,7 +114,7 @@
 		if (ircc_open( i, io[i], io2[i]) == 0)
 			return 0;
 	}
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 
 	return -ENODEV;
 }
@@ -130,13 +130,13 @@
 {
 	int i;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	for ( i=0; i < 4; i++) {
 		if ( dev_self[i])
 			ircc_close( &(dev_self[i]->idev));
 	}
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 }
 #endif /* MODULE */
 
@@ -153,10 +153,10 @@
 	int ret;
 	int config;
 
-	DEBUG( ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG( ircc_debug, __FUNCTION__ " -->\n");
 
 	if ((config = ircc_probe( iobase, iobase2)) == -1) {
-	        DEBUG(ircc_debug, 
+	        IRDA_DEBUG(ircc_debug, 
 		      __FUNCTION__ ": addr 0x%04x - no device found!\n", iobase);
 		return -1;
 	}
@@ -199,14 +199,14 @@
 	/* Lock the port that we need */
 	ret = check_region( idev->io.iobase, idev->io.io_ext);
 	if ( ret < 0) { 
-		DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+		IRDA_DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
 		       idev->io.iobase);
 		/* ircc_cleanup( self->idev);  */
 		return -ENODEV;
 	}
 	ret = check_region( idev->io.iobase2, idev->io.io_ext2);
 	if ( ret < 0) { 
-		DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+		IRDA_DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
 		       idev->io.iobase2);
 		/* ircc_cleanup( self->idev);  */
 		return -ENODEV;
@@ -256,7 +256,7 @@
 	/* Open the IrDA device */
 	irda_device_open( idev, driver_name, self);
 	
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -271,7 +271,7 @@
 {
 	int iobase;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	ASSERT( idev != NULL, return -1;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
@@ -291,20 +291,20 @@
         serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR);
  
 	/* Release the PORT that this driver is using */
-	DEBUG( ircc_debug, 
+	IRDA_DEBUG( ircc_debug, 
 	       __FUNCTION__ ": releasing 0x%03x\n", idev->io.iobase);
 
 	release_region( idev->io.iobase, idev->io.io_ext);
 
 	if ( idev->io.iobase2) {
-		DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", 
+		IRDA_DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", 
 		       idev->io.iobase2);
 		release_region( idev->io.iobase2, idev->io.io_ext2);
 	}
 
 	irda_device_close( idev);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 #endif /* MODULE */
@@ -320,7 +320,7 @@
 	int version = 1;
 	int low, high, chip, config, dma, irq;
 	
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	register_bank(iobase, 3);
 	high = serial_in(iobase, UART_ID_HIGH);
@@ -332,7 +332,7 @@
 	dma = config & 0x0f;
 
         if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) { 
-                DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
+                IRDA_DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
 		      "port 0x%04x, dma %d, interrupt %d\n",
                       chip & 0x0f, version, iobase, dma, irq);
 	} else {
@@ -341,7 +341,7 @@
 
 	serial_out(iobase, UART_MASTER, 0);
 
-	DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 
 	return config;
 }
@@ -357,7 +357,7 @@
 	struct ircc_cb *self;
 	int iobase, ir_mode, select, fast; 
 
-	DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
 
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -374,7 +374,7 @@
 	case 37600:
 	case 57600:
 	case 115200:
-	        DEBUG(ircc_debug+1, 
+	        IRDA_DEBUG(ircc_debug+1, 
 		      __FUNCTION__ ": using irport to change speed to %d\n",
 		      speed);
 		register_bank(iobase, 0);
@@ -390,22 +390,22 @@
 		ir_mode = UART_CFGA_IRDA_HDLC;
 		select = 0;
 		fast = 0;
-		DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
+		IRDA_DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
 		break;
 	case 1152000:
 		ir_mode = UART_CFGA_IRDA_HDLC;
 		select = UART_1152;
 		fast = 0;
-		DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
+		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
 		break;
 	case 4000000:
 		ir_mode = UART_CFGA_IRDA_4PPM;
 		select = 0;
 		fast = UART_LCR_A_FAST;
-		DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
+		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
+		IRDA_DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
 		return;
 	}
 
@@ -443,7 +443,7 @@
 
 	serial_out(iobase, UART_LCR_A, fast);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 }
 
 /*
@@ -458,7 +458,7 @@
 	int iobase;
 	int mtt;
 
-	DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
 	idev = (struct irda_device *) dev->priv;
 
 	ASSERT( idev != NULL, return 0;);
@@ -466,15 +466,15 @@
 
 	iobase = idev->io.iobase;
 
-	DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
 
 	/* Use irport for SIR speeds */
 	if (idev->io.baudrate <= 115200) {
-		DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n");
+		IRDA_DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n");
 		return irport_hard_xmit(skb, dev);
 	}
 	
-	DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
 
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
@@ -502,7 +502,7 @@
 	
 	dev_kfree_skb( skb);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -516,7 +516,7 @@
 {
 	struct ircc_cb *self;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -557,7 +557,7 @@
 
 	serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 }
 
 /*
@@ -572,7 +572,7 @@
 	struct ircc_cb *self;
 	int iobase, d;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -585,7 +585,7 @@
 
 	d = get_dma_residue(idev->io.dma);
 
-	DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n", 
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n", 
 	      d, idev->tx_buff.len, idev->tx_buff.len - d);
 
 	self = idev->priv;
@@ -608,7 +608,7 @@
 	/* Tell the network layer, that we can accept more frames */
 	mark_bh( NET_BH);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 }
 
 /*
@@ -623,7 +623,7 @@
 	struct ircc_cb *self;
 	int iobase;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	ASSERT( idev != NULL, return -1;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
@@ -660,7 +660,7 @@
 		   serial_in(iobase, UART_SCE_CFGB) | 
 		   UART_CFGB_DMA_ENABLE | UART_CFGB_DMA_BURST);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -677,18 +677,18 @@
 	struct ircc_cb *self;
 	int len, msgcnt;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	self = idev->priv;
 
 	msgcnt = serial_in(idev->io.iobase, UART_LCR_B) & 0x08;
 
-	DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
 	      get_dma_residue(idev->io.dma));
 
 	len = idev->rx_buff.truesize - get_dma_residue(idev->io.dma) - 4;
 
-	DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
 
 	skb = dev_alloc_skb( len+1);
 
@@ -715,7 +715,7 @@
 		   serial_in(idev->io.iobase, UART_SCE_CFGB) &
 		   ~UART_CFGB_DMA_ENABLE);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return TRUE;
 }
 
@@ -731,7 +731,7 @@
 
 	struct irda_device *idev = (struct irda_device *) dev_id;
 
-	DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
 
 	if (idev == NULL) {
 		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
@@ -740,7 +740,7 @@
 	}
 	
 	if (idev->io.baudrate <= 115200) {
-		DEBUG(ircc_debug+1, __FUNCTION__ 
+		IRDA_DEBUG(ircc_debug+1, __FUNCTION__ 
 		      ": routing interrupt to irport_interrupt\n");
 		return irport_interrupt( irq, dev_id, regs);
 	}
@@ -757,10 +757,10 @@
 
 	serial_out(iobase, UART_IER, 0);
 
-	DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
 
 	if (iir & UART_IIR_EOM) {
-	        DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
+	        IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
 		if (idev->io.direction == IO_RECV) {
 			ircc_dma_receive_complete(idev, iobase);
 		} else {
@@ -770,7 +770,7 @@
 	}
 
 	if (iir & UART_IIR_ACTIVE_FRAME) {
-	        DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
+	        IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
 		idev->rx_buff.state = INSIDE_FRAME;
 #if 0
 		ircc_dma_receive(idev);
@@ -778,7 +778,7 @@
 	}
 
 	if (iir & UART_IIR_RAW_MODE) {
-		DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
+		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
 	}
 
 	idev->netdev.interrupt = 0;
@@ -787,7 +787,7 @@
 	serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME|UART_IER_EOM);
 	serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 }
 
 /*
@@ -798,13 +798,13 @@
  */
 static void ircc_wait_until_sent( struct irda_device *idev)
 {
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	/* Just delay 60 ms */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(60));
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 }
 
 /*
@@ -818,17 +818,17 @@
 	int status = FALSE;
 	/* int iobase; */
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	ASSERT( idev != NULL, return FALSE;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
 
-	DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
 	      get_dma_residue(idev->io.dma));
 
 	status = ( idev->rx_buff.state != OUTSIDE_FRAME);
 	
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 
 	return status;
 }
@@ -841,14 +841,14 @@
  */
 static int ircc_net_init( struct net_device *dev)
 {
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
 	/* Setup to be a normal IrDA network device driver */
 	irda_device_setup( dev);
 
 	/* Insert overrides below this line! */
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -864,7 +864,7 @@
 	struct irda_device *idev;
 	int iobase;
 	
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 	
 	ASSERT( dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
@@ -894,7 +894,7 @@
 	
 	MOD_INC_USE_COUNT;
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
@@ -909,7 +909,7 @@
 	struct irda_device *idev;
 	int iobase;
 
-	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 	
 	ASSERT( dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
@@ -930,7 +930,7 @@
 
 	MOD_DEC_USE_COUNT;
 
-	DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+	IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.3.23/linux/drivers/net/irda/tekram.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/irda/tekram.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Thu Jul 15 01:17:53 1999
+ * Modified at:   Mon Oct 18 23:25:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -29,15 +29,14 @@
 #include <linux/init.h>
 
 #include <net/irda/irda.h>
+#include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
 #include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
 
-static void tekram_reset(struct irda_device *dev);
-static void tekram_open(struct irda_device *dev, int type);
-static void tekram_close(struct irda_device *dev);
-static void tekram_change_speed(struct irda_device *dev, __u32 speed);
-static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos);
+static void tekram_open(dongle_t *self, struct qos_info *qos);
+static void tekram_close(dongle_t *self);
+static int  tekram_change_speed(struct irda_task *task);
+static int  tekram_reset(struct irda_task *task);
 
 #define TEKRAM_115200 0x00
 #define TEKRAM_57600  0x01
@@ -47,13 +46,13 @@
 
 #define TEKRAM_PW     0x10 /* Pulse select bit */
 
-static struct dongle dongle = {
-	TEKRAM_DONGLE,
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_TEKRAM_DONGLE,
 	tekram_open,
 	tekram_close,
 	tekram_reset,
 	tekram_change_speed,
-	tekram_init_qos,
 };
 
 int __init tekram_init(void)
@@ -66,26 +65,29 @@
 	irda_device_unregister_dongle(&dongle);
 }
 
-static void tekram_open(struct irda_device *idev, int type)
+static void tekram_open(dongle_t *self, struct qos_info *qos)
 {
-	strcat(idev->description, " <-> tekram");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
+	irda_qos_bits_to_value(qos);
 
-	idev->io.dongle_id = type;
-	idev->flags |= IFF_DONGLE;
-	
 	MOD_INC_USE_COUNT;
 }
 
-static void tekram_close(struct irda_device *idev)
-{		
+static void tekram_close(dongle_t *self)
+{
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function tekram_change_speed (tty, speed)
+ * Function tekram_change_speed (dev, state, speed)
  *
  *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this 
  *    function must be called with a process context!
@@ -100,14 +102,16 @@
  *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
  *       after
  */
-static void tekram_change_speed(struct irda_device *idev, __u32 speed)
+static int tekram_change_speed(struct irda_task *task)
 {
+	dongle_t *self = (dongle_t *) task->instance;
+	__u32 speed = (__u32) task->param;
 	__u8 byte;
+	int ret = 0;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(task != NULL, return -1;);
 
 	switch (speed) {
 	default:
@@ -128,24 +132,65 @@
 		break;
 	}
 
-	/* Need to reset the dongle and go to 9600 bps before programming */
-	tekram_reset(idev);
-	
-	/* Set DTR, Clear RTS */
-	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		/* Lock dongle */
+		if (irda_lock((void *) &self->busy) == FALSE) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+			return MSECS_TO_JIFFIES(100);
+		}
+		irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
+		break;
+	case IRDA_TASK_CHILD_INIT:		
+		/* 
+		 * Need to reset the dongle and go to 9600 bps before
+                 * programming 
+		 */
+		if (irda_task_execute(self, tekram_reset, NULL, task, 
+				      (void *) speed))
+		{
+			/* Dongle need more time to reset */
+			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+			/* Give reset 1 sec to finish */
+			ret = MSECS_TO_JIFFIES(1000);
+		} else
+			irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+		break;
+	case IRDA_TASK_CHILD_WAIT:
+		WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+		ret = -1;
+		break;
+	case IRDA_TASK_CHILD_DONE:
+		/* Set DTR, Clear RTS */
+		self->set_dtr_rts(self->dev, TRUE, FALSE);
 	
-	/* Wait at least 7us */
-	udelay(10);
+		/* Wait at least 7us */
+		udelay(10);
 
-	/* Write control byte */
-	irda_device_raw_write(idev, &byte, 1);
-	
-	/* Wait at least 100 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(100));
-        
-	/* Set DTR, Set RTS */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		/* Write control byte */
+		self->write(self->dev, &byte, 1);
+		
+		irda_task_next_state(task, IRDA_TASK_WAIT);
+
+		/* Wait at least 100 ms */
+		ret = MSECS_TO_JIFFIES(100);
+		break;
+	case IRDA_TASK_WAIT:
+		/* Set DTR, Set RTS */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->busy = 0;
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->busy = 0;
+		ret = -1;
+		break;
+	}
+	return ret;
 }
 
 /*
@@ -161,50 +206,52 @@
  *        3. clear DTR to SPACE state, wait at least 50 us for further 
  *         operation
  */
-void tekram_reset(struct irda_device *idev)
+int tekram_reset(struct irda_task *task)
 {
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	dongle_t *self = (dongle_t *) task->instance;
+	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(task != NULL, return -1;);
 	
 	/* Power off dongle */
-	irda_device_set_dtr_rts(idev, FALSE, FALSE);
-
-	/* Sleep 50 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(50));
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
-	/* Clear DTR, Set RTS */
-	irda_device_set_dtr_rts(idev, FALSE, TRUE); 
+	switch (task->state) {
+	case IRDA_TASK_INIT:
+		irda_task_next_state(task, IRDA_TASK_WAIT1);
 
-	/* Should sleep 1 ms, but 10-20 should not do any harm */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
+		/* Sleep 50 ms */
+		ret = MSECS_TO_JIFFIES(50);
+		break;
+	case IRDA_TASK_WAIT1:
+		/* Clear DTR, Set RTS */
+		self->set_dtr_rts(self->dev, FALSE, TRUE); 
 
-	/* Set DTR, Set RTS */
-	irda_device_set_dtr_rts(idev, TRUE, TRUE);
-	
-	udelay(50);
+		irda_task_next_state(task, IRDA_TASK_WAIT2);
+		
+		/* Should sleep 1 ms, but 10 should not do any harm */
+		ret = MSECS_TO_JIFFIES(10);
+		break;
+	case IRDA_TASK_WAIT2:
+		/* Set DTR, Set RTS */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
-	/* Make sure the IrDA chip also goes to defalt speed */
-	if (idev->change_speed)
-		idev->change_speed(idev, 9600);
-}
+		udelay(50);
 
-/*
- * Function tekram_init_qos (qos)
- *
- *    Initialize QoS capabilities
- *
- */
-static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
-	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
-	irda_qos_bits_to_value(qos);
+		irda_task_next_state(task, IRDA_TASK_DONE);
+		break;
+	default:
+		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+		irda_task_next_state(task, IRDA_TASK_DONE);		
+
+		ret = -1;
+	}
+	return ret;
 }
 
 #ifdef MODULE
-
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
 		
@@ -229,5 +276,4 @@
 {
         tekram_cleanup();
 }
-
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.3.23/linux/drivers/net/irda/toshoboe.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/irda/toshoboe.c	Mon Oct 25 20:49:42 1999
@@ -95,6 +95,7 @@
 #include <linux/malloc.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -122,7 +123,7 @@
 static void
 toshoboe_stopchip (struct toshoboe_cb *self)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   outb_p (0x0e, OBOE_REG_11);
 
@@ -143,7 +144,7 @@
 toshoboe_setbaud (struct toshoboe_cb *self, int baud)
 {
   unsigned long flags;
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
 
@@ -212,7 +213,7 @@
 {
   __u32 physaddr;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
 
   outb_p (0, OBOE_LOCK);
@@ -241,7 +242,7 @@
 static void
 toshoboe_enablebm (struct toshoboe_cb *self)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
   pci_set_master (self->pdev);
 }
 
@@ -250,7 +251,7 @@
 toshoboe_disablebm (struct toshoboe_cb *self)
 {
   __u8 command;
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
   command &= ~PCI_COMMAND_MASTER;
@@ -265,7 +266,7 @@
   int i;
   unsigned long flags;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   save_flags (flags);
   cli ();
@@ -287,29 +288,27 @@
   restore_flags (flags);
 }
 
-
-
-
 /*Transmit something */
 static int
 toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
 {
-  struct irda_device *idev;
   struct toshoboe_cb *self;
+  __u32 speed;
   int mtt, len;
 
-  idev = (struct irda_device *) dev->priv;
-  ASSERT (idev != NULL, return 0;
-    );
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;
-    );
+  self = (struct toshoboe_cb *) dev->priv;
 
-  self = idev->priv;
   ASSERT (self != NULL, return 0;
     );
 
-  if (self->stopped)
+  /* Check if we need to change the speed */
+  if ((speed = irda_get_speed(skb)) != self->io.speed)
+	   toshoboe_setbaud (self, speed);
+
+  if (self->stopped) {
+	  dev_kfree_skb(skb);
     return 0;
+  }
 
 #ifdef ONETASK
   if (self->txpending)
@@ -376,24 +375,18 @@
 static void
 toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct irda_device *idev = (struct irda_device *) dev_id;
-  struct toshoboe_cb *self;
+  struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
   __u8 irqstat;
   struct sk_buff *skb;
 
-  if (idev == NULL)
+  if (self == NULL)
     {
       printk (KERN_WARNING "%s: irq %d for unknown device.\n",
               driver_name, irq);
       return;
     }
 
-  self = idev->priv;
-
-  if (!self)
-    return;
-
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   irqstat = inb_p (OBOE_ISR);
 
@@ -409,10 +402,10 @@
     {
       self->txpending--;
 
-      idev->stats.tx_packets++;
+      self->stats.tx_packets++;
 
-      idev->media_busy = FALSE;
-      idev->netdev.tbusy = 0;
+      /* idev->media_busy = FALSE; */
+      self->netdev->tbusy = 0;
 
       mark_bh (NET_BH);
     }
@@ -441,8 +434,8 @@
               skb_put (skb, len);
               memcpy (skb->data, self->recv_bufs[self->rxs], len);
 
-              idev->stats.rx_packets++;
-              skb->dev = &idev->netdev;
+              self->stats.rx_packets++;
+              skb->dev = self->netdev;
               skb->mac.raw = skb->data;
               skb->protocol = htons (ETH_P_IRDA);
             }
@@ -479,79 +472,18 @@
     {
       /*FIXME: I think this is a TX or RX error of some sort */
 
-      idev->stats.tx_errors++;
-      idev->stats.rx_errors++;
+      self->stats.tx_errors++;
+      self->stats.rx_errors++;
 
     }
 
 
 }
 
-
-
-/* Change the baud rate */
-static void
-toshoboe_change_speed (struct irda_device *idev, __u32 speed)
-{
-  struct toshoboe_cb *self;
-  DEBUG (4, __FUNCTION__ "()\n");
-
-  ASSERT (idev != NULL, return;
-    );
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;
-    );
-
-  self = idev->priv;
-  ASSERT (self != NULL, return;
-    );
-
-
-  idev->io.baudrate = speed;
-
-  if (self->stopped)
-    return;
-
-  toshoboe_setbaud (self, speed);
-
-}
-
-
-/* Check all xmit_tasks finished */
-static void
-toshoboe_wait_until_sent (struct irda_device *idev)
-{
-  struct toshoboe_cb *self;
-  int i;
-
-  DEBUG (4, __FUNCTION__ "()\n");
-
-  ASSERT (idev != NULL, return;
-    );
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;
-    );
-
-  self = idev->priv;
-  ASSERT (self != NULL, return;
-    );
-
-  if (self->stopped)
-    return;
-
-  for (i = 0; i < TX_SLOTS; ++i)
-    {
-      while (self->taskfile->xmit[i].control)
-        {
-          current->state = TASK_INTERRUPTIBLE;
-          schedule_timeout (MSECS_TO_JIFFIES(60));
-        }
-    }
-
-}
-
 static int
-toshoboe_is_receiving (struct irda_device *idev)
+toshoboe_is_receiving (struct toshoboe_cb *self)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
 /*FIXME Can't tell! */
   return (FALSE);
@@ -561,7 +493,7 @@
 static int
 toshoboe_net_init (struct net_device *dev)
 {
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   /* Setup to be a normal IrDA network device driver */
   irda_device_setup (dev);
@@ -607,30 +539,22 @@
 static int
 toshoboe_net_open (struct net_device *dev)
 {
-  struct irda_device *idev;
   struct toshoboe_cb *self;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   ASSERT (dev != NULL, return -1;
     );
-  idev = (struct irda_device *) dev->priv;
-
-  ASSERT (idev != NULL, return 0;
-    );
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;
-    );
+  self = (struct toshoboe_cb *) dev->priv;
 
-  self = idev->priv;
   ASSERT (self != NULL, return 0;
     );
 
   if (self->stopped)
     return 0;
 
-
-  if (request_irq (idev->io.irq, toshoboe_interrupt,
-                   SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev))
+  if (request_irq (self->io.irq, toshoboe_interrupt,
+                   SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self))
     {
 
       return -EAGAIN;
@@ -641,8 +565,17 @@
   toshoboe_startchip (self);
   toshoboe_initptrs (self);
 
-  irda_device_net_open(dev);
-	
+  /* Ready to play! */
+  dev->tbusy = 0;
+  dev->interrupt = 0;
+  dev->start = 1;
+  
+  /* 
+   * Open new IrLAP layer instance, now that everything should be
+   * initialized properly 
+   */
+  self->irlap = irlap_open(dev, &self->qos);	
+
   self->open = 1;
 	
   MOD_INC_USE_COUNT;
@@ -654,30 +587,26 @@
 static int
 toshoboe_net_close (struct net_device *dev)
 {
-  struct irda_device *idev;
   struct toshoboe_cb *self;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   ASSERT (dev != NULL, return -1;
     );
-  idev = (struct irda_device *) dev->priv;
-
-  ASSERT (idev != NULL, return 0;
-    );
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;
-    );
-
-  irda_device_net_close(dev);
-
-  self = idev->priv;
+  self = (struct toshoboe_cb *) dev->priv;
 
-  ASSERT (self != NULL, return 0;
-    );
+  /* Stop device */
+  dev->tbusy = 1;
+  dev->start = 0;
+  
+  /* Stop and remove instance of IrLAP */
+  if (self->irlap)
+	  irlap_close(self->irlap);
+  self->irlap = NULL;
 
   self->open = 0;
 
-  free_irq (idev->io.irq, (void *) idev);
+  free_irq (self->io.irq, (void *) self);
 
   if (!self->stopped)
     {
@@ -698,19 +627,11 @@
 MODULE_PARM (max_baud, "i");
 
 static int
-toshoboe_close (struct irda_device *idev)
+toshoboe_close (struct toshoboe_cb *self)
 {
-  struct toshoboe_cb *self;
   int i;
 
-  DEBUG (4, __FUNCTION__ "()\n");
-
-  ASSERT (idev != NULL, return -1;
-    );
-  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;
-    );
-
-  self = idev->priv;
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   ASSERT (self != NULL, return -1;
     );
@@ -721,7 +642,7 @@
       toshoboe_disablebm (self);
     }
 
-  release_region (idev->io.iobase, idev->io.io_ext);
+  release_region (self->io.iobase, self->io.io_ext);
 
 
   for (i = 0; i < TX_SLOTS; ++i)
@@ -736,14 +657,17 @@
       self->recv_bufs[i] = NULL;
     }
 
+  if (self->netdev) {
+	  /* Remove netdevice */
+	  rtnl_lock();
+	  unregister_netdevice(self->netdev);
+	  rtnl_unlock();
+  }
 
   kfree (self->taskfilebuf);
   self->taskfilebuf = NULL;
   self->taskfile = NULL;
 
-
-  irda_device_close (idev);
-
   return (0);
 
 }
@@ -756,12 +680,12 @@
 toshoboe_open (struct pci_dev *pci_dev)
 {
   struct toshoboe_cb *self;
-  struct irda_device *idev;
+  struct net_device *dev;
   int i = 0;
   int ok = 0;
+  int err;
 
-
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   while (dev_self[i])
     i++;
@@ -790,21 +714,17 @@
   self->pdev = pci_dev;
   self->base = pci_dev->resource[0].start;
 
-  idev = &self->idev;
-
-  /*Setup idev */
-
-  idev->io.iobase = self->base;
-  idev->io.irq = pci_dev->irq;
-  idev->io.io_ext = CHIP_IO_EXTENT;
-  idev->io.baudrate = 9600;
+  self->io.iobase = self->base;
+  self->io.irq = pci_dev->irq;
+  self->io.io_ext = CHIP_IO_EXTENT;
+  self->io.speed = 9600;
 
   /* Lock the port that we need */
-  i = check_region (idev->io.iobase, idev->io.io_ext);
+  i = check_region (self->io.iobase, self->io.io_ext);
   if (i < 0)
     {
-      DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-             idev->io.iobase);
+      IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+             self->io.iobase);
 
       dev_self[i] = NULL;
       kfree (self);
@@ -813,57 +733,39 @@
     }
 
 
-  irda_init_max_qos_capabilies (&idev->qos);
-  idev->qos.baud_rate.bits = 0;
+  irda_init_max_qos_capabilies (&self->qos);
+  self->qos.baud_rate.bits = 0;
 
   if (max_baud >= 2400)
-    idev->qos.baud_rate.bits |= IR_2400;
+    self->qos.baud_rate.bits |= IR_2400;
   /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
   if (max_baud >= 9600)
-    idev->qos.baud_rate.bits |= IR_9600;
+    self->qos.baud_rate.bits |= IR_9600;
   if (max_baud >= 19200)
-    idev->qos.baud_rate.bits |= IR_19200;
+    self->qos.baud_rate.bits |= IR_19200;
   if (max_baud >= 115200)
-    idev->qos.baud_rate.bits |= IR_115200;
+    self->qos.baud_rate.bits |= IR_115200;
 #ifdef ENABLE_FAST
   if (max_baud >= 576000)
-    idev->qos.baud_rate.bits |= IR_576000;
+    self->qos.baud_rate.bits |= IR_576000;
   if (max_baud >= 1152000)
-    idev->qos.baud_rate.bits |= IR_1152000;
+    self->qos.baud_rate.bits |= IR_1152000;
   if (max_baud >= 4000000)
-    idev->qos.baud_rate.bits |= (IR_4000000 << 8);
+    self->qos.baud_rate.bits |= (IR_4000000 << 8);
 #endif
 
 
-  idev->qos.min_turn_time.bits = 0xff;  /*FIXME: what does this do? */
+  self->qos.min_turn_time.bits = 0xff;  /*FIXME: what does this do? */
 
-  irda_qos_bits_to_value (&idev->qos);
+  irda_qos_bits_to_value (&self->qos);
 
-  idev->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+  self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
 
 #ifdef ENABLE_FAST
   if (max_baud >= 576000)
-    idev->flags |= IFF_FIR;
+    self->flags |= IFF_FIR;
 #endif
 
-  /* These aren't much use as we need to have a whole panoply of
-   * buffers running */
-
-  idev->rx_buff.flags = 0;
-  idev->tx_buff.flags = 0;
-  idev->rx_buff.truesize = 0;
-  idev->rx_buff.truesize = 0;
-
-  idev->change_speed = toshoboe_change_speed;
-  idev->wait_until_sent = toshoboe_wait_until_sent;
-  idev->is_receiving = toshoboe_is_receiving;
-
-  idev->netdev.init = toshoboe_net_init;
-  idev->netdev.hard_start_xmit = toshoboe_hard_xmit;
-  idev->netdev.open = toshoboe_net_open;
-  idev->netdev.stop = toshoboe_net_close;
-
-
   /* Now setup the endless buffers we need */
 
   self->txs = 0;
@@ -922,9 +824,32 @@
 
     }
 
-  request_region (idev->io.iobase, idev->io.io_ext, driver_name);
+  request_region (self->io.iobase, self->io.io_ext, driver_name);
 
-  irda_device_open (idev, driver_name, self);
+  if (!(dev = dev_alloc("irda%d", &err))) {
+	  ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+	  return -ENOMEM;
+  }
+  /* dev_alloc doesn't clear the struct, so lets do a little hack */
+  memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+  dev->priv = (void *) self;
+  self->netdev = dev;
+  
+  MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+  dev->init = toshoboe_net_init;
+  dev->hard_start_xmit = toshoboe_hard_xmit;
+  dev->open = toshoboe_net_open;
+  dev->stop = toshoboe_net_close;
+
+  rtnl_lock();
+  err = register_netdevice(dev);
+  rtnl_unlock();
+  if (err) {
+	  ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+	  return -1;
+  }
 
   printk (KERN_WARNING "ToshOboe: Using ");
 #ifdef ONETASK
@@ -969,8 +894,7 @@
 static void 
 toshoboe_wakeup (struct toshoboe_cb *self)
 {
-  struct irda_device *idev = &self->idev;
-  struct net_device *dev = &idev->netdev;
+  struct net_device *dev = self->netdev;
   unsigned long flags;
 
   if (!self->stopped)
@@ -989,12 +913,10 @@
   toshoboe_enablebm (self);
   toshoboe_startchip (self);
 
-  toshoboe_setbaud (self, idev->io.baudrate);
+  toshoboe_setbaud (self, self->io.speed);
 
   toshoboe_initptrs (self);
 
-
-
   dev->tbusy = 0;
   dev->interrupt = 0;
   dev->start = 1;
@@ -1093,12 +1015,12 @@
 {
   int i;
 
-  DEBUG (4, __FUNCTION__ "()\n");
+  IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
   for (i = 0; i < 4; i++)
     {
       if (dev_self[i])
-        toshoboe_close (&(dev_self[i]->idev));
+        toshoboe_close (dev_self[i]);
     }
 
 #ifdef CONFIG_APM
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.3.23/linux/drivers/net/irda/uircc.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/irda/uircc.c	Mon Oct 25 20:49:42 1999
@@ -113,7 +113,7 @@
 {
 	int i;
 
-        DEBUG(4, __FUNCTION__ "()\n");
+        IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	for (i=0; i < 4; i++) {
 		if (dev_self[i])
@@ -135,7 +135,7 @@
 	struct irda_device *idev;
 	int ret;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	if ((uircc_probe(iobase, iobase2, irq, dma)) == -1)
 		return -1;
@@ -168,14 +168,14 @@
 	/* Lock the port that we need */
 	ret = check_region(idev->io.iobase, idev->io.io_ext);
 	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
 		      idev->io.iobase);
 		/* uircc_cleanup( self->idev);  */
 		return -ENODEV;
 	}
 	ret = check_region(idev->io.iobase2, idev->io.io_ext2);
 	if (ret < 0) { 
-		DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
 		      idev->io.iobase2);
 		/* uircc_cleanup( self->idev);  */
 		return -ENODEV;
@@ -235,7 +235,7 @@
 	int iobase;
 	int status;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(idev != NULL, return -1;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
@@ -252,11 +252,11 @@
 	irport_stop(idev, idev->io.iobase2);
 
 	/* Release the PORT that this driver is using */
-	DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
 	release_region(idev->io.iobase, idev->io.io_ext);
 
 	if (idev->io.iobase2) {
-		DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
+		IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
 		      idev->io.iobase2);
 		release_region(idev->io.iobase2, idev->io.io_ext2);
 	}
@@ -278,13 +278,13 @@
 {
 	int version;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* read the chip version, should be 0x03 */
 	version = inb(iobase+UIRCC_SR8);
 
 	if (version != 0x03) {
-		DEBUG(0, __FUNCTION__ "(), Wrong chip version");	
+		IRDA_DEBUG(0, __FUNCTION__ "(), Wrong chip version");	
 		return -1;
 	}
         printk(KERN_INFO "Sharp UIRCC IrDA driver loaded. Version: 0x%02x\n",
@@ -298,7 +298,7 @@
 	outb(0, iobase+UIRCC_CR11);
 	outb(0, iobase+UIRCC_CR9);
 
-	DEBUG(0, __FUNCTION__ "(), sr15=%#x\n", inb(iobase+UIRCC_SR15));
+	IRDA_DEBUG(0, __FUNCTION__ "(), sr15=%#x\n", inb(iobase+UIRCC_SR15));
 
 	/* Enable DMA single mode */
 	outb(UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, 
@@ -325,7 +325,7 @@
 	int modem = UIRCC_CR10_SIR;
 	int status;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	/* Just test the high speed stuff */
 	/*speed = 4000000;*/
@@ -358,11 +358,11 @@
 		break;
 	case 576000:		
 		
-		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
 		break;
 	case 1152000:
 
-		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
 		irport_stop(idev, idev->io.iobase2);
@@ -371,7 +371,7 @@
 		uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001);
 
 		modem = UIRCC_CR10_FIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
 
 		/* Set self pole address */
 		//outb(0xfe, iobase+UIRCC_CR8);
@@ -379,7 +379,7 @@
 	 	/* outb(0x10, iobase+UIRCC_CR11); */
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		IRDA_DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
 		break;
 	}
 
@@ -419,7 +419,7 @@
 
 	iobase = idev->io.iobase;
 
-	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+	IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
 	
 	/* Reset carrier latch */
 	/*outb(0x02, iobase+UIRCC_CR0);*/
@@ -429,7 +429,7 @@
 		return irport_hard_xmit(skb, dev);
 	}
 	
-	DEBUG(0, __FUNCTION__ "(), sr0=%#x, sr1=%#x, sr2=%#x, sr3=%#x, sr10=%#x, sr11=%#x\n",
+	IRDA_DEBUG(0, __FUNCTION__ "(), sr0=%#x, sr1=%#x, sr2=%#x, sr3=%#x, sr10=%#x, sr11=%#x\n",
 	      inb(iobase+UIRCC_SR0), inb(iobase+UIRCC_SR3),
 	      inb(iobase+UIRCC_SR2), inb(iobase+UIRCC_SR3), 
 	      inb(iobase+UIRCC_SR10), inb(iobase+UIRCC_SR11));
@@ -473,7 +473,7 @@
 {
 	struct uircc_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -519,7 +519,7 @@
 	int iobase;
 	int len;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -535,7 +535,7 @@
 	len  = inb(iobase+UIRCC_SR4);      /* Low byte */
 	len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */
 
-	DEBUG(4, __FUNCTION__ "(), sent %d bytes\n", len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), sent %d bytes\n", len);
 
 	/* Disable transmit */
 	self->cr3 &= ~UIRCC_CR3_XMIT_EN;
@@ -576,7 +576,7 @@
 	ASSERT(idev != NULL, return -1;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 
-	DEBUG(4, __FUNCTION__ "\n");
+	IRDA_DEBUG(4, __FUNCTION__ "\n");
 
 	self = idev->priv;
 	iobase= idev->io.iobase;
@@ -614,7 +614,7 @@
 	self->cr3 = (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN);
 	outb(self->cr3, iobase+UIRCC_CR3);
 #endif
-	DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3);
+	IRDA_DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3);
 	
 	/* Address check? */
 
@@ -636,11 +636,11 @@
 
 	self = idev->priv;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	/* Check for CRC or framing error */
 	if (inb(iobase+UIRCC_SR0) & UIRCC_SR0_RX_CRCFRM) {
-		DEBUG(0, __FUNCTION__ "(), CRC or FRAME error\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), CRC or FRAME error\n");
 		return -1;
 	}
 
@@ -651,7 +651,7 @@
 	len = inb(iobase+UIRCC_SR4);       /* Low byte */
 	len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */
 
-	DEBUG(0, __FUNCTION__ "(), len=%d\n", len);
+	IRDA_DEBUG(0, __FUNCTION__ "(), len=%d\n", len);
 
 	/* Receiving disable */
 	self->cr3 &= ~UIRCC_CR3_RECV_EN;
@@ -716,12 +716,12 @@
 	/* Read interrupt status */
 	sr3 = inb( iobase+UIRCC_SR3); 
 	if (!sr3) {
-		DEBUG(4,"**\n");
+		IRDA_DEBUG(4,"**\n");
 		return;
 	}
 	idev->netdev.interrupt = 1;
 
-	DEBUG(4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n", 
 	      inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2), 
 	      inb( iobase+UIRCC_SR10));
 
@@ -750,7 +750,7 @@
 		     iobase+UIRCC_CR11);
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), unknown interrupt status=%#x\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown interrupt status=%#x\n",
 		      sr3);
 		break;
 	}	
@@ -800,7 +800,7 @@
  */
 static int uircc_net_init( struct net_device *dev)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	/* Setup to be a normal IrDA network device driver */
 	irda_device_setup(dev);
@@ -822,7 +822,7 @@
 	struct irda_device *idev;
 	int iobase;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 	
 	ASSERT(dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
@@ -866,7 +866,7 @@
 	struct irda_device *idev;
 	int iobase;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
diff -u --recursive --new-file v2.3.23/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.3.23/linux/drivers/net/irda/w83977af_ir.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/irda/w83977af_ir.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Wed Aug 11 09:27:54 1999
+ * Modified at:   Wed Oct 20 00:08:30 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -49,6 +49,7 @@
 #include <linux/delay.h>
 #include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/rtnetlink.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -83,17 +84,16 @@
 /* Some prototypes */
 static int  w83977af_open(int i, unsigned int iobase, unsigned int irq, 
                           unsigned int dma);
-static int  w83977af_close(struct irda_device *idev);
+static int  w83977af_close(struct w83977af_ir *self);
 static int  w83977af_probe(int iobase, int irq, int dma);
-static int  w83977af_dma_receive(struct irda_device *idev); 
-static int  w83977af_dma_receive_complete(struct irda_device *idev);
+static int  w83977af_dma_receive(struct w83977af_ir *self); 
+static int  w83977af_dma_receive_complete(struct w83977af_ir *self);
 static int  w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void w83977af_dma_write(struct irda_device *idev, int iobase);
-static void w83977af_change_speed(struct irda_device *idev, __u32 speed);
+static void w83977af_dma_write(struct w83977af_ir *self, int iobase);
+static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed);
 static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void w83977af_wait_until_sent(struct irda_device *idev);
-static int  w83977af_is_receiving(struct irda_device *idev);
+static int  w83977af_is_receiving(struct w83977af_ir *self);
 
 static int  w83977af_net_init(struct net_device *dev);
 static int  w83977af_net_open(struct net_device *dev);
@@ -109,13 +109,13 @@
 {
         int i;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	for (i=0; (io[i] < 2000) && (i < 4); i++) { 
 		int ioaddr = io[i];
 		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
 			continue;
-		if (w83977af_open( i, io[i], irq[i], dma[i]) == 0)
+		if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
 			return 0;
 	}
 	return -ENODEV;
@@ -132,11 +132,11 @@
 {
 	int i;
 
-        DEBUG(4, __FUNCTION__ "()\n");
+        IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	for (i=0; i < 4; i++) {
 		if (dev_self[i])
-			w83977af_close(&(dev_self[i]->idev));
+			w83977af_close(dev_self[i]);
 	}
 }
 #endif /* MODULE */
@@ -147,14 +147,15 @@
  *    Open driver instance
  *
  */
-int w83977af_open( int i, unsigned int iobase, unsigned int irq, 
-		   unsigned int dma)
+int w83977af_open(int i, unsigned int iobase, unsigned int irq, 
+		  unsigned int dma)
 {
-	struct irda_device *idev;
+	struct net_device *dev;
         struct w83977af_ir *self;
 	int ret;
+	int err;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	if (w83977af_probe(iobase, irq, dma) == -1)
 		return -1;
@@ -173,83 +174,107 @@
 	/* Need to store self somewhere */
 	dev_self[i] = self;
 
-	idev = &self->idev;
-
 	/* Initialize IO */
-	idev->io.iobase    = iobase;
-        idev->io.irq       = irq;
-        idev->io.io_ext    = CHIP_IO_EXTENT;
-        idev->io.dma       = dma;
-        idev->io.fifo_size = 32;
+	self->io.iobase    = iobase;
+        self->io.irq       = irq;
+        self->io.io_ext    = CHIP_IO_EXTENT;
+        self->io.dma       = dma;
+        self->io.fifo_size = 32;
 
 	/* Lock the port that we need */
-	ret = check_region(idev->io.iobase, idev->io.io_ext);
+	ret = check_region(self->io.iobase, self->io.io_ext);
 	if (ret < 0) { 
-		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		       idev->io.iobase);
-		/* w83977af_cleanup( self->idev);  */
+		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		      self->io.iobase);
+		/* w83977af_cleanup( self);  */
 		return -ENODEV;
 	}
-	request_region(idev->io.iobase, idev->io.io_ext, idev->name);
+	request_region(self->io.iobase, self->io.io_ext, driver_name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies(&idev->qos);
+	irda_init_max_qos_capabilies(&self->qos);
 	
 	/* The only value we must override it the baudrate */
 
 	/* FIXME: The HP HDLS-1100 does not support 1152000! */
-	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+	self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
 
 	/* The HP HDLS-1100 needs 1 ms according to the specs */
-	idev->qos.min_turn_time.bits = qos_mtt_bits;
-	irda_qos_bits_to_value(&idev->qos);
+	self->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&self->qos);
 	
-	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
-
-	/* Specify which buffer allocation policy we need */
-	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
-	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+	self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 
 	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
-	idev->rx_buff.truesize = 14384; 
-	idev->tx_buff.truesize = 4000;
+	self->rx_buff.truesize = 14384; 
+	self->tx_buff.truesize = 4000;
 	
-	/* Initialize callbacks */
-	idev->change_speed    = w83977af_change_speed;
-	idev->wait_until_sent = w83977af_wait_until_sent;
-        idev->is_receiving    = w83977af_is_receiving;
+	/* Allocate memory if needed */
+	if (self->rx_buff.truesize > 0) {
+		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+						      GFP_KERNEL|GFP_DMA);
+		if (self->rx_buff.head == NULL)
+			return -ENOMEM;
+		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+	}
+	if (self->tx_buff.truesize > 0) {
+		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
+						      GFP_KERNEL|GFP_DMA);
+		if (self->tx_buff.head == NULL) {
+			kfree(self->rx_buff.head);
+			return -ENOMEM;
+		}
+		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+	}
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+	self->tx_buff.data = self->tx_buff.head;
+	self->rx_buff.data = self->rx_buff.head;
+	
+	if (!(dev = dev_alloc("irda%d", &err))) {
+		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+		return -ENOMEM;
+	}
+	/* dev_alloc doesn't clear the struct, so lets do a little hack */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+	dev->priv = (void *) self;
+	self->netdev = dev;
 
 	/* Override the network functions we need to use */
-	idev->netdev.init            = w83977af_net_init;
-	idev->netdev.hard_start_xmit = w83977af_hard_xmit;
-	idev->netdev.open            = w83977af_net_open;
-	idev->netdev.stop            = w83977af_net_close;
+	dev->init            = w83977af_net_init;
+	dev->hard_start_xmit = w83977af_hard_xmit;
+	dev->open            = w83977af_net_open;
+	dev->stop            = w83977af_net_close;
+
+	rtnl_lock();
+	err = register_netdev(dev);
+	rtnl_unlock();
+	if (err) {
+		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+		return -1;
+	}
 
-	/* Open the IrDA device */
-	irda_device_open(idev, driver_name, self);
+	MESSAGE("IrDA: Registered device %s\n", dev->name);
 	
 	return 0;
 }
 
 /*
- * Function w83977af_close (idev)
+ * Function w83977af_close (self)
  *
  *    Close driver instance
  *
  */
-static int w83977af_close( struct irda_device *idev)
+static int w83977af_close(struct w83977af_ir *self)
 {
-	struct w83977af_ir *self;
 	int iobase;
 
-	DEBUG(0, __FUNCTION__ "()\n");
-
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
-        iobase = idev->io.iobase;
-	self = (struct w83977af_ir *) idev->priv;
+        iobase = self->io.iobase;
 
 #ifdef CONFIG_USE_W977_PNP
 	/* enter PnP configuration mode */
@@ -262,12 +287,24 @@
 
 	w977_efm_exit();
 #endif /* CONFIG_USE_W977_PNP */
+
+	/* Remove netdevice */
+	if (self->netdev) {
+		rtnl_lock();
+		unregister_netdev(self->netdev);
+		rtnl_unlock();
+	}
+
 	/* Release the PORT that this driver is using */
-	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
-	      idev->io.iobase);
-	release_region(idev->io.iobase, idev->io.io_ext);
+	IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
+	      self->io.iobase);
+	release_region(self->io.iobase, self->io.io_ext);
 
-	irda_device_close(idev);
+	if (self->tx_buff.head)
+		kfree(self->tx_buff.head);
+	
+	if (self->rx_buff.head)
+		kfree(self->rx_buff.head);
 
 	kfree(self);
 
@@ -284,7 +321,7 @@
 {
 	int version;
 	
-	DEBUG( 0, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "()\n");
 #ifdef CONFIG_USE_W977_PNP
 	/* Enter PnP configuration mode */
 	w977_efm_enter();
@@ -333,7 +370,7 @@
 	
 	/* Should be 0x1? */
 	if (0x10 != (version & 0xf0)) {
-		DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
 		return -1;
 	}
 	
@@ -365,30 +402,21 @@
 	switch_bank(iobase, SET7);
 	outb(0x40, iobase+7);
 		
-	DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
+	IRDA_DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
 	
 	return 0;
 }
 
-/*
- * Function w83977af_change_speed (idev, baud)
- *
- *    Change the speed of the device
- *
- */
-void w83977af_change_speed(struct irda_device *idev, __u32 speed)
+void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
 {
 	int ir_mode = HCR_SIR;
 	int iobase; 
 	__u8 set;
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Update accounting for new speed */
-	idev->io.baudrate = speed;
+	self->io.speed = speed;
 
 	/* Save current bank */
 	set = inb(iobase+SSR);
@@ -409,19 +437,19 @@
 	case 115200: outb(0x01, iobase+ABLL); break;
 	case 576000:
 		ir_mode = HCR_MIR_576;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
 		break;
 	case 1152000:
 		ir_mode = HCR_MIR_1152;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
 		ir_mode = HCR_FIR;
-		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
 		break;
 	default:
 		ir_mode = HCR_FIR;
-		DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
 		break;
 	}
 
@@ -440,13 +468,13 @@
 	outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
 	outb(0xa7, iobase+UFR);
 
-	idev->netdev.tbusy = 0;
+	self->netdev->tbusy = 0;
 	
 	/* Enable some interrupts so we can receive frames */
 	switch_bank(iobase, SET0);
 	if (speed > PIO_MAX_SPEED) {
 		outb(ICR_EFSFI, iobase+ICR);
-		w83977af_dma_receive(idev);
+		w83977af_dma_receive(self);
 	} else
 		outb(ICR_ERBRI, iobase+ICR);
     	
@@ -462,32 +490,34 @@
  */
 int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct w83977af_ir *self;
+	__u32 speed;
 	int iobase;
 	__u8 set;
 	int mtt;
 	
-	idev = (struct irda_device *) dev->priv;
+	self = (struct w83977af_ir *) dev->priv;
 
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	iobase = self->io.iobase;
 
-	iobase = idev->io.iobase;
-
-	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+	IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
 	
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
 
+	/* Check if we need to change the speed */
+	if ((speed = irda_get_speed(skb)) != self->io.speed)
+		w83977af_change_speed(self, speed);
+
 	/* Save current set */
 	set = inb(iobase+SSR);
 	
 	/* Decide if we should use PIO or DMA transfer */
-	if (idev->io.baudrate > PIO_MAX_SPEED) {
-		idev->tx_buff.data = idev->tx_buff.head;
-		memcpy(idev->tx_buff.data, skb->data, skb->len);
-		idev->tx_buff.len = skb->len;
+	if (self->io.speed > PIO_MAX_SPEED) {
+		self->tx_buff.data = self->tx_buff.head;
+		memcpy(self->tx_buff.data, skb->data, skb->len);
+		self->tx_buff.len = skb->len;
 		
 		mtt = irda_get_mtt(skb);
 #ifdef CONFIG_USE_INTERNAL_TIMER
@@ -502,28 +532,28 @@
 			
 			/* Start timer */
 			outb(IR_MSL_EN_TMR, iobase+IR_MSL);
-			idev->io.direction = IO_XMIT;
+			self->io.direction = IO_XMIT;
 			
 			/* Enable timer interrupt */
 			switch_bank(iobase, SET0);
 			outb(ICR_ETMRI, iobase+ICR);
 		} else {
 #endif
-			DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
+			IRDA_DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
 			if (mtt)
 				udelay(mtt);
 
 			/* Enable DMA interrupt */
 			switch_bank(iobase, SET0);
 	 		outb(ICR_EDMAI, iobase+ICR);
-	     		w83977af_dma_write(idev, iobase);
+	     		w83977af_dma_write(self, iobase);
 #ifdef CONFIG_USE_INTERNAL_TIMER
 		}
 #endif
 	} else {
-		idev->tx_buff.data = idev->tx_buff.head;
-		idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
-						   idev->tx_buff.truesize);
+		self->tx_buff.data = self->tx_buff.head;
+		self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
+						   self->tx_buff.truesize);
 		
 		/* Add interrupt on tx low level (will fire immediately) */
 		switch_bank(iobase, SET0);
@@ -538,19 +568,19 @@
 }
 
 /*
- * Function w83977af_dma_write (idev, iobase)
+ * Function w83977af_dma_write (self, iobase)
  *
  *    Send frame using DMA
  *
  */
-static void w83977af_dma_write(struct irda_device *idev, int iobase)
+static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
 {
 	__u8 set;
 #ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
-        DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len);
+        IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", self->tx_buff.len);
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -566,23 +596,23 @@
 	save_flags(flags);
 	cli();
 
-	disable_dma(idev->io.dma);
-	clear_dma_ff(idev->io.dma);
-	set_dma_mode(idev->io.dma, DMA_MODE_READ);
-	set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data));
-	set_dma_count(idev->io.dma, idev->tx_buff.len);
+	disable_dma(self->io.dma);
+	clear_dma_ff(self->io.dma);
+	set_dma_mode(self->io.dma, DMA_MODE_READ);
+	set_dma_addr(self->io.dma, virt_to_bus(self->tx_buff.data));
+	set_dma_count(self->io.dma, self->tx_buff.len);
 #else
-	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
 		  DMA_MODE_WRITE);	
 #endif
-	idev->io.direction = IO_XMIT;
+	self->io.direction = IO_XMIT;
 	
 	/* Enable DMA */
  	switch_bank(iobase, SET0);
 #ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
-	enable_dma(idev->io.dma);
+	enable_dma(self->io.dma);
 	restore_flags(flags);
 #else	
 	outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
@@ -603,17 +633,17 @@
 	int actual = 0;
 	__u8 set;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Save current bank */
 	set = inb(iobase+SSR);
 
 	switch_bank(iobase, SET0);
 	if (!(inb_p(iobase+USR) & USR_TSRE)) {
-		DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
 
 		fifo_size -= 17;
-		DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+		IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
 	}
 
 	/* Fill FIFO with current frame */
@@ -622,7 +652,7 @@
 		outb(buf[actual++], iobase+TBR);
 	}
         
-	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
 	       fifo_size, actual, len);
 
 	/* Restore bank */
@@ -632,23 +662,22 @@
 }
 
 /*
- * Function w83977af_dma_xmit_complete (idev)
+ * Function w83977af_dma_xmit_complete (self)
  *
  *    The transfer of a frame in finished. So do the necessary things
  *
  *    
  */
-void w83977af_dma_xmit_complete(struct irda_device *idev)
+void w83977af_dma_xmit_complete(struct w83977af_ir *self)
 {
 	int iobase;
 	__u8 set;
 
-	DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
+	IRDA_DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -659,19 +688,18 @@
 	
 	/* Check for underrrun! */
 	if (inb(iobase+AUDR) & AUDR_UNDR) {
-		DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n");
 		
-		idev->stats.tx_errors++;
-		idev->stats.tx_fifo_errors++;
+		self->stats.tx_errors++;
+		self->stats.tx_fifo_errors++;
 
 		/* Clear bit, by writing 1 to it */
 		outb(AUDR_UNDR, iobase+AUDR);
 	} else
-		idev->stats.tx_packets++;
+		self->stats.tx_packets++;
 
 	/* Unlock tx_buff and request another frame */
-	idev->netdev.tbusy = 0; /* Unlock */
-	idev->media_busy = FALSE;
+	self->netdev->tbusy = 0; /* Unlock */
 	
 	/* Tell the network layer, that we want more frames */
 	mark_bh(NET_BH);
@@ -681,15 +709,14 @@
 }
 
 /*
- * Function w83977af_dma_receive (idev)
+ * Function w83977af_dma_receive (self)
  *
  *    Get ready for receiving a frame. The device will initiate a DMA
  *    if it starts to receive a frame.
  *
  */
-int w83977af_dma_receive(struct irda_device *idev) 
+int w83977af_dma_receive(struct w83977af_ir *self) 
 {
-	struct w83977af_ir *self;
 	int iobase;
 	__u8 set;
 #ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
@@ -697,13 +724,11 @@
 	__u8 hcr;
 #endif
 
-	ASSERT(idev != NULL, return -1;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
 
-	DEBUG(4, __FUNCTION__ "\n");
+	IRDA_DEBUG(4, __FUNCTION__ "\n");
 
-	self = idev->priv;
-	iobase= idev->io.iobase;
+	iobase= self->io.iobase;
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -717,20 +742,20 @@
 	outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL,
 	     iobase+ADCR1);
 
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
+	self->io.direction = IO_RECV;
+	self->rx_buff.data = self->rx_buff.head;
 
 #ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
-	disable_dma(idev->io.dma);
-	clear_dma_ff(idev->io.dma);
-	set_dma_mode(idev->io.dma, DMA_MODE_READ);
-	set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data));
-	set_dma_count(idev->io.dma, idev->rx_buff.truesize);
+	disable_dma(self->io.dma);
+	clear_dma_ff(self->io.dma);
+	set_dma_mode(self->io.dma, DMA_MODE_READ);
+	set_dma_addr(self->io.dma, virt_to_bus(self->rx_buff.data));
+	set_dma_count(self->io.dma, self->rx_buff.truesize);
 #else
-	setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
+	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
 		  DMA_MODE_READ);
 #endif
 	/* 
@@ -747,7 +772,7 @@
 #ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
-	enable_dma(idev->io.dma);
+	enable_dma(self->io.dma);
 	restore_flags(flags);
 #else	
 	outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
@@ -759,32 +784,30 @@
 }
 
 /*
- * Function w83977af_receive_complete (idev)
+ * Function w83977af_receive_complete (self)
  *
  *    Finished with receiving a frame
  *
  */
-int w83977af_dma_receive_complete(struct irda_device *idev)
+int w83977af_dma_receive_complete(struct w83977af_ir *self)
 {
 	struct sk_buff *skb;
-	struct w83977af_ir *self;
 	struct st_fifo *st_fifo;
 	int len;
 	int iobase;
 	__u8 set;
 	__u8 status;
 
-	DEBUG(4, __FUNCTION__ "\n");
+	IRDA_DEBUG(4, __FUNCTION__ "\n");
 
-	self = idev->priv;
 	st_fifo = &self->st_fifo;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Save current set */
 	set = inb(iobase+SSR);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Read status FIFO */
 	switch_bank(iobase, SET5);
@@ -809,28 +832,28 @@
 		if (status & FS_FO_ERR_MSK) {
 			if (status & FS_FO_LST_FR) {
 				/* Add number of lost frames to stats */
-				idev->stats.rx_errors += len;	
+				self->stats.rx_errors += len;	
 			} else {
 				/* Skip frame */
-				idev->stats.rx_errors++;
+				self->stats.rx_errors++;
 				
-				idev->rx_buff.data += len;
+				self->rx_buff.data += len;
 				
 				if (status & FS_FO_MX_LEX)
-					idev->stats.rx_length_errors++;
+					self->stats.rx_length_errors++;
 				
 				if (status & FS_FO_PHY_ERR) 
-					idev->stats.rx_frame_errors++;
+					self->stats.rx_frame_errors++;
 				
 				if (status & FS_FO_CRC_ERR) 
-					idev->stats.rx_crc_errors++;
+					self->stats.rx_crc_errors++;
 			}
 			/* The errors below can be reported in both cases */
 			if (status & FS_FO_RX_OV)
-				idev->stats.rx_fifo_errors++;
+				self->stats.rx_fifo_errors++;
 			
 			if (status & FS_FO_FSF_OV)
-				idev->stats.rx_fifo_errors++;
+				self->stats.rx_fifo_errors++;
 			
 		} else {
 			/* Check if we have transfered all data to memory */
@@ -866,19 +889,19 @@
 			skb_reserve(skb, 1); 
 			
 			/* Copy frame without CRC */
-			if (idev->io.baudrate < 4000000) {
+			if (self->io.speed < 4000000) {
 				skb_put(skb, len-2);
-				memcpy(skb->data, idev->rx_buff.data, len-2);
+				memcpy(skb->data, self->rx_buff.data, len-2);
 			} else {
 				skb_put(skb, len-4);
-				memcpy(skb->data, idev->rx_buff.data, len-4);
+				memcpy(skb->data, self->rx_buff.data, len-4);
 			}
 
 			/* Move to next frame */
-			idev->rx_buff.data += len;
-			idev->stats.rx_packets++;
+			self->rx_buff.data += len;
+			self->stats.rx_packets++;
 			
-			skb->dev = &idev->netdev;
+			skb->dev = self->netdev;
 			skb->mac.raw  = skb->data;
 			skb->protocol = htons(ETH_P_IRDA);
 			netif_rx(skb);
@@ -891,61 +914,60 @@
 }
 
 /*
- * Function pc87108_pio_receive (idev)
+ * Function pc87108_pio_receive (self)
  *
  *    Receive all data in receiver FIFO
  *
  */
-static void w83977af_pio_receive(struct irda_device *idev) 
+static void w83977af_pio_receive(struct w83977af_ir *self) 
 {
 	__u8 byte = 0x00;
 	int iobase;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(idev != NULL, return;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(self != NULL, return;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 	
 	/*  Receive all characters in Rx FIFO */
 	do {
 		byte = inb(iobase+RBR);
-		async_unwrap_char(idev, byte);
+		async_unwrap_char(self->netdev, &self->rx_buff, byte);
 	} while (inb(iobase+USR) & USR_RDR); /* Data available */	
 }
 
 /*
- * Function w83977af_sir_interrupt (idev, eir)
+ * Function w83977af_sir_interrupt (self, eir)
  *
  *    Handle SIR interrupt
  *
  */
-static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr)
+static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
 {
 	int actual;
 	__u8 new_icr = 0;
 	__u8 set;
 	int iobase;
 
-	DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
+	IRDA_DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 	/* Transmit FIFO low on data */
 	if (isr & ISR_TXTH_I) {
 		/* Write data left in transmit buffer */
-		actual = w83977af_pio_write(idev->io.iobase, 
-					    idev->tx_buff.data, 
-					    idev->tx_buff.len, 
-					    idev->io.fifo_size);
+		actual = w83977af_pio_write(self->io.iobase, 
+					    self->tx_buff.data, 
+					    self->tx_buff.len, 
+					    self->io.fifo_size);
 
-		idev->tx_buff.data += actual;
-		idev->tx_buff.len  -= actual;
+		self->tx_buff.data += actual;
+		self->tx_buff.len  -= actual;
 		
-		idev->io.direction = IO_XMIT;
+		self->io.direction = IO_XMIT;
 
 		/* Check if finished */
-		if (idev->tx_buff.len > 0) {
+		if (self->tx_buff.len > 0) {
 			new_icr |= ICR_ETXTHI;
 		} else {
 			set = inb(iobase+SSR);
@@ -953,8 +975,8 @@
 			outb(AUDR_SFEND, iobase+AUDR);
 			outb(set, iobase+SSR); 
 
-			idev->netdev.tbusy = 0; /* Unlock */
-			idev->stats.tx_packets++;
+			self->netdev->tbusy = 0; /* Unlock */
+			self->stats.tx_packets++;
 
 			/* Schedule network layer */
 		        mark_bh(NET_BH);	
@@ -966,13 +988,13 @@
 	if (isr & ISR_TXEMP_I) {
 		
 		/* Turn around and get ready to receive some data */
-		idev->io.direction = IO_RECV;
+		self->io.direction = IO_RECV;
 		new_icr |= ICR_ERBRI;
 	}
 
 	/* Rx FIFO threshold or timeout */
 	if (isr & ISR_RXTH_I) {
-		w83977af_pio_receive(idev);
+		w83977af_pio_receive(self);
 
 		/* Keep receiving */
 		new_icr |= ICR_ERBRI;
@@ -981,23 +1003,23 @@
 }
 
 /*
- * Function pc87108_fir_interrupt (idev, eir)
+ * Function pc87108_fir_interrupt (self, eir)
  *
  *    Handle MIR/FIR interrupt
  *
  */
-static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr)
+static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
 {
 	__u8 new_icr = 0;
 	__u8 set;
 	int iobase;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 	set = inb(iobase+SSR);
 	
 	/* End of frame detected in FIFO */
 	if (isr & (ISR_FEND_I|ISR_FSF_I)) {
-		if (w83977af_dma_receive_complete(idev)) {
+		if (w83977af_dma_receive_complete(self)) {
 			
 			/* Wait for next status FIFO interrupt */
 			new_icr |= ICR_EFSFI;
@@ -1026,29 +1048,29 @@
 /* 		outb(ASCR_CTE, iobase+ASCR); */
 
 		/* Check if this is a TX timer interrupt */
-		if (idev->io.direction == IO_XMIT) {
-			w83977af_dma_write(idev, iobase);
+		if (self->io.direction == IO_XMIT) {
+			w83977af_dma_write(self, iobase);
 
 			new_icr |= ICR_EDMAI;
 		} else {
 			/* Check if DMA has now finished */
-			w83977af_dma_receive_complete(idev);
+			w83977af_dma_receive_complete(self);
 
 			new_icr |= ICR_EFSFI;
 		}
 	}	
 	/* Finished with DMA */
 	if (isr & ISR_DMA_I) {
-		w83977af_dma_xmit_complete(idev);
+		w83977af_dma_xmit_complete(self);
 
 		/* Check if there are more frames to be transmitted */
-		/* if (irda_device_txqueue_empty(idev)) { */
+		/* if (irda_device_txqueue_empty(self)) { */
 		
 		/* Prepare for receive 
 		 * 
 		 * ** Netwinder Tx DMA likes that we do this anyway **
 		 */
-		w83977af_dma_receive(idev);
+		w83977af_dma_receive(self);
 		new_icr = ICR_EFSFI;
 	       /* } */
 	}
@@ -1067,20 +1089,21 @@
  */
 static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct w83977af_ir *self;
 	__u8 set, icr, isr;
 	int iobase;
 
-	struct irda_device *idev = (struct irda_device *) dev_id;
-
-	if (idev == NULL) {
+	if (!dev) {
 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
 			driver_name, irq);
 		return;
 	}
+	self = (struct w83977af_ir *) dev->priv;
 
-	idev->netdev.interrupt = 1;
+	dev->interrupt = 1;
 
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Save current bank */
 	set = inb(iobase+SSR);
@@ -1093,47 +1116,34 @@
 	
 	if (isr) {
 		/* Dispatch interrupt handler for the current speed */
-		if (idev->io.baudrate > PIO_MAX_SPEED )
-			icr = w83977af_fir_interrupt(idev, isr);
+		if (self->io.speed > PIO_MAX_SPEED )
+			icr = w83977af_fir_interrupt(self, isr);
 		else
-			icr = w83977af_sir_interrupt(idev, isr);
+			icr = w83977af_sir_interrupt(self, isr);
 	}
 
 	outb(icr, iobase+ICR);    /* Restore (new) interrupts */
 	outb(set, iobase+SSR);    /* Restore bank register */
 
-	idev->netdev.interrupt = 0;
+	self->netdev->interrupt = 0;
 }
 
 /*
- * Function w83977af_wait_until_sent (idev)
- *
- *    This function should put the current thread to sleep until all data 
- *    have been sent, so it is safe to f.eks. change the speed.
- */
-static void w83977af_wait_until_sent(struct irda_device *idev)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(60*HZ/1000);
-}
-
-/*
- * Function w83977af_is_receiving (idev)
+ * Function w83977af_is_receiving (self)
  *
  *    Return TRUE is we are currently receiving a frame
  *
  */
-static int w83977af_is_receiving(struct irda_device *idev)
+static int w83977af_is_receiving(struct w83977af_ir *self)
 {
 	int status = FALSE;
 	int iobase;
 	__u8 set;
 
-	ASSERT(idev != NULL, return FALSE;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	ASSERT(self != NULL, return FALSE;);
 
-	if (idev->io.baudrate > 115200) {
-		iobase = idev->io.iobase;
+	if (self->io.speed > 115200) {
+		iobase = self->io.iobase;
 
 		/* Check if rx FIFO is not empty */
 		set = inb(iobase+SSR);
@@ -1144,7 +1154,7 @@
 		}
 		outb(set, iobase+SSR);
 	} else 
-		status = (idev->rx_buff.state != OUTSIDE_FRAME);
+		status = (self->rx_buff.state != OUTSIDE_FRAME);
 	
 	return status;
 }
@@ -1157,7 +1167,7 @@
  */
 static int w83977af_net_init(struct net_device *dev)
 {
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	/* Set up to be a normal IrDA network device driver */
 	irda_device_setup(dev);
@@ -1176,30 +1186,29 @@
  */
 static int w83977af_net_open(struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct w83977af_ir *self;
 	int iobase;
 	__u8 set;
 	
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	
 	ASSERT(dev != NULL, return -1;);
-	idev = (struct irda_device *) dev->priv;
+	self = (struct w83977af_ir *) dev->priv;
 	
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
-	if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name, 
-			 (void *) idev)) {
+	if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name, 
+			 (void *) dev)) {
 		return -EAGAIN;
 	}
 	/*
 	 * Always allocate the DMA channel after the IRQ,
 	 * and clean up on failure.
 	 */
-	if (request_dma(idev->io.dma, idev->name)) {
-		free_irq(idev->io.irq, idev);
+	if (request_dma(self->io.dma, dev->name)) {
+		free_irq(self->io.irq, self);
 		return -EAGAIN;
 	}
 		
@@ -1208,9 +1217,9 @@
 
  	/* Enable some interrupts so we can receive frames again */
  	switch_bank(iobase, SET0);
- 	if (idev->io.baudrate > 115200) {
+ 	if (self->io.speed > 115200) {
  		outb(ICR_EFSFI, iobase+ICR);
- 		w83977af_dma_receive(idev);
+ 		w83977af_dma_receive(self);
  	} else
  		outb(ICR_ERBRI, iobase+ICR);
 
@@ -1218,7 +1227,15 @@
 	outb(set, iobase+SSR);
 
 	/* Ready to play! */
-	irda_device_net_open(dev);
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(dev, &self->qos);
 
 	MOD_INC_USE_COUNT;
 
@@ -1233,25 +1250,30 @@
  */
 static int w83977af_net_close(struct net_device *dev)
 {
-	struct irda_device *idev;
+	struct w83977af_ir *self;
 	int iobase;
 	__u8 set;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	ASSERT(dev != NULL, return -1;);
 	
-	idev = (struct irda_device *) dev->priv;
+	self = (struct w83977af_ir *) dev->priv;
 	
-	ASSERT(idev != NULL, return 0;);
-	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
 	
-	iobase = idev->io.iobase;
+	iobase = self->io.iobase;
 
 	/* Stop device */
-	irda_device_net_close(dev);
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
 
-	disable_dma(idev->io.dma);
+	disable_dma(self->io.dma);
 
 	/* Save current set */
 	set = inb(iobase+SSR);
@@ -1260,8 +1282,8 @@
 	switch_bank(iobase, SET0);
 	outb(0, iobase+ICR); 
 
-	free_irq(idev->io.irq, idev);
-	free_dma(idev->io.dma);
+	free_irq(self->io.irq, self);
+	free_dma(self->io.dma);
 
 	/* Restore bank register */
 	outb(set, iobase+SSR);
diff -u --recursive --new-file v2.3.23/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c
--- v2.3.23/linux/drivers/net/pcmcia/ray_cs.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/net/pcmcia/ray_cs.c	Mon Oct 25 20:54:50 1999
@@ -38,6 +38,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/if_arp.h>
 #include <linux/ioport.h>
 #include <linux/skbuff.h>
 
@@ -49,6 +50,19 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/mem_op.h>
 
+#ifdef HAS_WIRELESS_EXTENSIONS
+#include <linux/wireless.h>
+#if WIRELESS_EXT < 8
+#warning "Wireless extension v8 or newer required"
+#endif	/* WIRELESS_EXT < 8 */
+/* Warning : these stuff will slow down the driver... */
+#define WIRELESS_SPY		/* Enable spying addresses */
+/* Definitions we need for spy */
+typedef struct iw_statistics	iw_stats;
+typedef struct iw_quality	iw_qual;
+typedef u_char	mac_addr[ETH_ALEN];	/* Hardware address */
+#endif	/* HAS_WIRELESS_EXTENSIONS */
+
 #include "rayctl.h"
 #include "ray_cs.h"
 
@@ -72,67 +86,68 @@
 #define DEBUG(n, args...)
 #endif
 /** Prototypes based on PCMCIA skeleton driver *******************************/
-void ray_config(dev_link_t *link);
-void ray_release(u_long arg);
-int ray_event(event_t event, int priority, event_callback_args_t *args);
-dev_link_t *ray_attach(void);
-void ray_detach(dev_link_t *);
+static void ray_config(dev_link_t *link);
+static void ray_release(u_long arg);
+static int ray_event(event_t event, int priority, event_callback_args_t *args);
+static dev_link_t *ray_attach(void);
+static void ray_detach(dev_link_t *);
 
 /***** Prototypes indicated by device structure ******************************/
-int ray_dev_close(struct net_device *dev);
-int ray_dev_config(struct net_device *dev, struct ifmap *map);
-struct enet_statistics *ray_get_stats(struct net_device *dev);
-int ray_dev_init(struct net_device *dev);
-int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-int ray_open(struct net_device *dev);
-int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int ray_dev_close(struct net_device *dev);
+static int ray_dev_config(struct net_device *dev, struct ifmap *map);
+static struct enet_statistics *ray_get_stats(struct net_device *dev);
+static int ray_dev_init(struct net_device *dev);
+static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int ray_open(struct net_device *dev);
+static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void ray_update_multi_list(struct net_device *dev, int all);
-int encapsulate_frame(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
-                unsigned char *data, int len);
-int translate_frame(ray_dev_t *local, struct tx_msg *ptx,
+static int translate_frame(ray_dev_t *local, struct tx_msg *ptx,
                 unsigned char *data, int len);
-void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
                 unsigned char *data);
-void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
+static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
+#if WIRELESS_EXT > 7	/* If wireless extension exist in the kernel */
+static iw_stats * ray_get_wireless_stats(struct device *	dev);
+#endif	/* WIRELESS_EXT > 7 */
 
 /***** Prototypes for raylink functions **************************************/
-int asc_to_int(char a);
-void authenticate(ray_dev_t *local);
-int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type);
-void authenticate_timeout(u_long);
-int get_free_ccs(ray_dev_t *local);
-int get_free_tx_ccs(ray_dev_t *local);
-void init_startup_params(ray_dev_t *local);
-int parse_addr(char *in_str, UCHAR *out);
-int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type);
-int ray_init(struct net_device *dev);
-int interrupt_ecf(ray_dev_t *local, int ccs);
-void ray_reset(struct net_device *dev);
-void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len);
-void verify_dl_startup(u_long);
+static int asc_to_int(char a);
+static void authenticate(ray_dev_t *local);
+static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type);
+static void authenticate_timeout(u_long);
+static int get_free_ccs(ray_dev_t *local);
+static int get_free_tx_ccs(ray_dev_t *local);
+static void init_startup_params(ray_dev_t *local);
+static int parse_addr(char *in_str, UCHAR *out);
+static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type);
+static int ray_init(struct net_device *dev);
+static int interrupt_ecf(ray_dev_t *local, int ccs);
+static void ray_reset(struct net_device *dev);
+static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len);
+static void verify_dl_startup(u_long);
 
 /* Prototypes for interrpt time functions **********************************/
-void ray_interrupt(int reg, void *dev_id, struct pt_regs *regs);
-void clear_interrupt(ray_dev_t *local);
-void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
+static void ray_interrupt (int reg, void *dev_id, struct pt_regs *regs);
+static void clear_interrupt(ray_dev_t *local);
+static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
                        unsigned int pkt_addr, int rx_len);
-int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);
-void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs);
-void release_frag_chain(ray_dev_t *local, struct rcs *prcs);
-void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs);
+static void release_frag_chain(ray_dev_t *local, struct rcs *prcs);
+static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
                      unsigned int pkt_addr, int rx_len);
-void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
+static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
              int rx_len);
-void associate(ray_dev_t *local);
+static void associate(ray_dev_t *local);
 
 /* Card command functions */
-int dl_startup_params(struct net_device *dev);
-void join_net(u_long local);
-void start_net(u_long local);
+static int dl_startup_params(struct net_device *dev);
+static void join_net(u_long local);
+static void start_net(u_long local);
 /* void start_net(ray_dev_t *local); */
 
-int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare);
+static int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare);
 /* Create symbol table for registering with kernel in init_module */
 EXPORT_SYMBOL(ray_dev_ioctl);
 EXPORT_SYMBOL(ray_rx);
@@ -283,6 +298,14 @@
 /*===========================================================================*/
 static unsigned char eth2_llc[] = {0xaa, 0xaa, 3, 0, 0, 0};
 
+static char hop_pattern_length[] = { 1,
+	     USA_HOP_MOD,             EUROPE_HOP_MOD,
+	     JAPAN_HOP_MOD,           KOREA_HOP_MOD,
+	     SPAIN_HOP_MOD,           FRANCE_HOP_MOD,
+	     ISRAEL_HOP_MOD,          AUSTRALIA_HOP_MOD,
+	     JAPAN_TEST_HOP_MOD
+};
+
 static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>";
 
 #ifdef CONFIG_PROC_FS
@@ -298,7 +321,7 @@
 };
 #endif
 /*===========================================================================*/
-void cs_error(client_handle_t handle, int func, int ret)
+static void cs_error(client_handle_t handle, int func, int ret)
 {
     error_info_t err = { func, ret };
     CardServices(ReportError, handle, &err);
@@ -311,7 +334,7 @@
     configure the card at this point -- we wait until we receive a
     card insertion event.
 =============================================================================*/
-dev_link_t *ray_attach(void)
+static dev_link_t *ray_attach(void)
 {
     client_reg_t client_reg;
     dev_link_t *link;
@@ -367,6 +390,9 @@
     dev->set_config = &ray_dev_config;
     dev->get_stats  = &ray_get_stats;
     dev->do_ioctl = &ray_dev_ioctl;
+#if WIRELESS_EXT > 7	/* If wireless extension exist in the kernel */
+    dev->get_wireless_stats = ray_get_wireless_stats;
+#endif
 
     dev->set_multicast_list = &set_multicast_list;
 
@@ -411,7 +437,7 @@
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 =============================================================================*/
-void ray_detach(dev_link_t *link)
+static void ray_detach(dev_link_t *link)
 {
     dev_link_t **linkp;
     struct net_device *dev;
@@ -470,7 +496,7 @@
 #define CS_CHECK(fn, args...) \
 while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
 #define MAX_TUPLE_SIZE 128
-void ray_config(dev_link_t *link)
+static void ray_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
     tuple_t tuple;
@@ -585,7 +611,7 @@
     ray_release((u_long)link);
 } /* ray_config */
 /*===========================================================================*/
-int ray_init(struct net_device *dev)
+static int ray_init(struct net_device *dev)
 {
     int i;
     UCHAR *p;
@@ -648,7 +674,7 @@
 } /* ray_init */
 /*===========================================================================*/
 /* Download startup parameters to the card and command it to read them       */
-int dl_startup_params(struct net_device *dev)
+static int dl_startup_params(struct net_device *dev)
 {
     int ccsindex;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
@@ -694,16 +720,9 @@
     return 0;
 } /* dl_startup_params */
 /*===========================================================================*/
-void init_startup_params(ray_dev_t *local)
+static void init_startup_params(ray_dev_t *local)
 {
     int i; 
-    static char hop_pattern_length[] = { 1,
-                     USA_HOP_MOD,             EUROPE_HOP_MOD,
-                     JAPAN_HOP_MOD,           KOREA_HOP_MOD,
-                     SPAIN_HOP_MOD,           FRANCE_HOP_MOD,
-                     ISRAEL_HOP_MOD,          AUSTRALIA_HOP_MOD,
-                     JAPAN_TEST_HOP_MOD
-    };
 
     if (country > JAPAN_TEST) country = USA;
     else
@@ -762,7 +781,7 @@
         strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);
 } /* init_startup_params */ 
 /*===========================================================================*/
-void verify_dl_startup(u_long data)
+static void verify_dl_startup(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
     struct ccs *pccs = ((struct ccs *)(local->sram + CCS_BASE)) + local->dl_param_ccs;
@@ -779,7 +798,7 @@
     printk(KERN_DEBUG "verify_dl_startup parameters sent via ccs %d:\n",
            local->dl_param_ccs);
         for (i=0; i<sizeof(struct b5_startup_params); i++) {
-            printk(" %2x", readb(local->sram + HOST_TO_ECF_BASE + i));
+            printk(" %2x", (unsigned int) readb(local->sram + HOST_TO_ECF_BASE + i));
         }
     printk("\n");
     }
@@ -802,7 +821,7 @@
 } /* end verify_dl_startup */
 /*===========================================================================*/
 /* Command card to start a network */
-void start_net(u_long data)
+static void start_net(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
     struct ccs *pccs;
@@ -828,7 +847,7 @@
 } /* end start_net */
 /*===========================================================================*/
 /* Command card to join a network */
-void join_net(u_long data)
+static void join_net(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
 
@@ -860,7 +879,7 @@
     device, and release the PCMCIA configuration.  If the device is
     still open, this will be postponed until it is closed.
 =============================================================================*/
-void ray_release(u_long arg)
+static void ray_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *)arg;
     struct net_device *dev = link->priv; 
@@ -912,7 +931,7 @@
     actually access the device should check this flag to make sure
     the card is still present.
 =============================================================================*/
-int ray_event(event_t event, int priority,
+static int ray_event(event_t event, int priority,
                      event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
@@ -991,7 +1010,7 @@
     return 0;
 }
 /*===========================================================================*/
-int ray_dev_config(struct net_device *dev, struct ifmap *map)
+static int ray_dev_config(struct net_device *dev, struct ifmap *map)
 {
     ray_dev_t *local = dev->priv;
     dev_link_t *link = local->finder;
@@ -1005,7 +1024,7 @@
     return 0;
 }
 /*===========================================================================*/
-int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     ray_dev_t *local = dev->priv;
     dev_link_t *link = local->finder;
@@ -1047,7 +1066,7 @@
     return 0;
 } /* ray_dev_start_xmit */
 /*===========================================================================*/
-int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, 
+static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, 
                 UCHAR msg_type)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
@@ -1089,7 +1108,7 @@
     }
     else { /* Encapsulate frame */
         /* TBD TIB length will move address of ptx->var */
-        memcpy( (UCHAR *)&ptx->var, data, len);
+        memcpy_toio(&ptx->var, data, len);
         offset = 0;
     }
 
@@ -1121,7 +1140,7 @@
     return XMIT_OK;
 } /* end ray_hw_xmit */
 /*===========================================================================*/
-int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
+static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
                     int len)
 {
     unsigned short int proto = ((struct ethhdr *)data)->h_proto;
@@ -1137,7 +1156,7 @@
         /* Copy body of ethernet packet without ethernet header */
         memcpy_toio((UCHAR *)&ptx->var + sizeof(struct snaphdr_t), \
                     data + ETH_HLEN,  len - ETH_HLEN);
-        return sizeof(struct snaphdr_t) - ETH_HLEN;
+        return (int) sizeof(struct snaphdr_t) - ETH_HLEN;
     }
     else { /* already  802 type, and proto is length */
         DEBUG(3,"ray_cs translate_frame 802\n");
@@ -1152,15 +1171,16 @@
     /* TBD do other frame types */
 } /* end translate_frame */
 /*===========================================================================*/
-void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
                 unsigned char *data)
 {
     writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1);
 /*** IEEE 802.11 Address field assignments *************
-                     addr_1       addr_2     addr_3
-     AP              destination  AP(BSSID)  source
-     Infra Terminal  AP           terminal   destination
-     Adhoc           destination  terminal   BSSID
+                TODS FROMDS   addr_1     addr_2          addr_3   addr_4
+Adhoc           0    0        dest       src (terminal)  BSSID    N/A
+AP to Terminal  0    1        dest       AP(BSSID)       source   N/A
+Terminal to AP  1    0        AP(BSSID)  src (terminal)  dest     N/A
+AP to AP        1    1        dest AP    src AP          dest     source      
 *******************************************************/
     if (local->net_type == ADHOC) {   
         writeb(0, &ptx->mac.frame_ctl_2);
@@ -1186,11 +1206,14 @@
     }
 } /* end encapsulate_frame */
 /*===========================================================================*/
-int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
     int err = 0;
+#if WIRELESS_EXT > 7
+    struct iwreq *wrq = (struct iwreq *) ifr;
+#endif	/* WIRELESS_EXT > 7 */
 
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_dev_ioctl - device not present\n");
@@ -1200,6 +1223,257 @@
     /* Validate the command */
     switch (cmd)
     {
+#if WIRELESS_EXT > 7
+      /* --------------- WIRELESS EXTENSIONS --------------- */
+      /* Get name */
+    case SIOCGIWNAME:
+      strcpy(wrq->u.name, "IEEE 802.11-FH");
+      break;
+
+      /* Get frequency/channel */
+    case SIOCGIWFREQ:
+      wrq->u.freq.m = local->sparm.b5.a_hop_pattern;
+      wrq->u.freq.e = 0;
+      break;
+
+      /* Get current network name (ESSID) */
+    case SIOCGIWESSID:
+      if (wrq->u.data.pointer)
+	{
+	  char essid[IW_ESSID_MAX_SIZE + 1];
+	  /* Get the essid that was set */
+	  memcpy(essid, local->sparm.b5.a_current_ess_id,
+		 IW_ESSID_MAX_SIZE);
+	  essid[IW_ESSID_MAX_SIZE] = '\0';
+
+	  /* Push it out ! */
+	  wrq->u.data.length = strlen(essid) + 1;
+	  wrq->u.data.flags = 1; /* active */
+	  copy_to_user(wrq->u.data.pointer, essid, sizeof(essid));
+	}
+      break;
+
+      /* Get current Access Point (BSSID in our case) */
+    case SIOCGIWAP:
+      memcpy(wrq->u.ap_addr.sa_data, local->bss_id, ETH_ALEN);
+      wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+      break;
+
+      /* Get the current bit-rate */
+    case SIOCGIWRATE:
+      if(local->net_default_tx_rate == 3)
+	wrq->u.bitrate.value = 2000000;		/* Hum... */
+      else
+	wrq->u.bitrate.value = local->net_default_tx_rate * 500000;
+      wrq->u.bitrate.fixed = 0;		/* We are in auto mode */
+      break;
+
+      /* Set the desired bit-rate */
+    case SIOCSIWRATE:
+      /* Check if rate is in range */
+      if((wrq->u.bitrate.value != 1000000) &&
+	 (wrq->u.bitrate.value != 2000000))
+	{
+	  err = -EINVAL;
+	  break;
+	}
+      /* Hack for 1.5 Mb/s instead of 2 Mb/s */
+      if((local->fw_ver == 0x55) &&		/* Please check */
+	 (wrq->u.bitrate.value == 2000000))
+	local->net_default_tx_rate = 3;
+      else
+	local->net_default_tx_rate = wrq->u.bitrate.value/500000;
+      break;
+
+      /* Get the current RTS threshold */
+    case SIOCGIWRTS:
+      wrq->u.rts.value = (local->sparm.b5.a_rts_threshold[0] << 8)
+	+ local->sparm.b5.a_rts_threshold[1];
+#if WIRELESS_EXT > 8
+      wrq->u.rts.disabled = (wrq->u.rts.value == 32767);
+#endif /* WIRELESS_EXT > 8 */
+      wrq->u.rts.fixed = 1;
+      break;
+
+      /* Get the current fragmentation threshold */
+    case SIOCGIWFRAG:
+      wrq->u.frag.value = (local->sparm.b5.a_frag_threshold[0] << 8)
+	+ local->sparm.b5.a_frag_threshold[1];
+#if WIRELESS_EXT > 8
+      wrq->u.frag.disabled = (wrq->u.frag.value == 32767);
+#endif /* WIRELESS_EXT > 8 */
+      wrq->u.frag.fixed = 1;
+      break;
+#endif	/* WIRELESS_EXT > 7 */
+#if WIRELESS_EXT > 8
+
+      /* Get the current mode of operation */
+    case SIOCGIWMODE:
+      if(local->sparm.b5.a_network_type)
+	wrq->u.mode = IW_MODE_INFRA;
+      else
+	wrq->u.mode = IW_MODE_ADHOC;
+      break;
+#endif /* WIRELESS_EXT > 8 */
+#if WIRELESS_EXT > 7
+      /* ------------------ IWSPY SUPPORT ------------------ */
+      /* Define the range (variations) of above parameters */
+    case SIOCGIWRANGE:
+      /* Basic checking... */
+      if(wrq->u.data.pointer != (caddr_t) 0)
+	{
+	  struct iw_range	range;
+	  memset((char *) &range, 0, sizeof(struct iw_range));
+
+	  /* Set the length (useless : its constant...) */
+	  wrq->u.data.length = sizeof(struct iw_range);
+
+	  /* Set information in the range struct */
+	  range.throughput = 1.1 * 1000 * 1000;	/* Put the right number here */
+	  range.num_channels = hop_pattern_length[(int)country]; 
+	  range.num_frequency = 0;
+	  range.max_qual.qual = 0;
+	  range.max_qual.level = 255;	/* What's the correct value ? */
+	  range.max_qual.noise = 255;	/* Idem */
+	  range.num_bitrates = 2;
+	  range.bitrate[0] = 1000000;	/* 1 Mb/s */
+	  range.bitrate[1] = 2000000;	/* 2 Mb/s */
+
+	  /* Copy structure to the user buffer */
+	  if(copy_to_user(wrq->u.data.pointer, &range,
+			  sizeof(struct iw_range)))
+	    err = -EFAULT;
+	}
+      break;
+
+#ifdef WIRELESS_SPY
+      /* Set addresses to spy */
+    case SIOCSIWSPY:
+      /* Check the number of addresses */
+      if(wrq->u.data.length > IW_MAX_SPY)
+	{
+	  err = -E2BIG;
+	  break;
+	}
+      local->spy_number = wrq->u.data.length;
+
+      /* If there is some addresses to copy */
+      if(local->spy_number > 0)
+	{
+	  struct sockaddr	address[IW_MAX_SPY];
+	  int			i;
+
+	  /* Copy addresses to the driver */
+	  if(copy_from_user(address, wrq->u.data.pointer,
+			    sizeof(struct sockaddr) * local->spy_number))
+	    {
+	      err = -EFAULT;
+	      break;
+	    }
+
+	  /* Copy addresses to the lp structure */
+	  for(i = 0; i < local->spy_number; i++)
+	    memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN);
+
+	  /* Reset structure... */
+	  memset(local->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+
+#ifdef DEBUG_IOCTL_INFO
+	  printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n");
+	  for(i = 0; i < local->spy_number; i++)
+	    printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n",
+		   local->spy_address[i][0],
+		   local->spy_address[i][1],
+		   local->spy_address[i][2],
+		   local->spy_address[i][3],
+		   local->spy_address[i][4],
+		   local->spy_address[i][5]);
+#endif	/* DEBUG_IOCTL_INFO */
+	}
+      break;
+
+      /* Get the spy list and spy stats */
+    case SIOCGIWSPY:
+      /* Set the number of addresses */
+      wrq->u.data.length = local->spy_number;
+
+      /* If the user want to have the addresses back... */
+      if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
+	{
+	  struct sockaddr	address[IW_MAX_SPY];
+	  int			i;
+
+	  /* Copy addresses from the lp structure */
+	  for(i = 0; i < local->spy_number; i++)
+	    {
+	      memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN);
+	      address[i].sa_family = ARPHRD_ETHER;
+	    }
+
+	  /* Copy addresses to the user buffer */
+	  if(copy_to_user(wrq->u.data.pointer, address,
+		       sizeof(struct sockaddr) * local->spy_number))
+	    {
+	      err = -EFAULT;
+	      break;
+	    }
+
+	  /* Copy stats to the user buffer (just after) */
+	  if(copy_to_user(wrq->u.data.pointer +
+		       (sizeof(struct sockaddr) * local->spy_number),
+		       local->spy_stat, sizeof(iw_qual) * local->spy_number))
+	    {
+	      err = -EFAULT;
+	      break;
+	    }
+
+	  /* Reset updated flags */
+	  for(i = 0; i < local->spy_number; i++)
+	    local->spy_stat[i].updated = 0x0;
+	}	/* if(pointer != NULL) */
+
+      break;
+#endif	/* WIRELESS_SPY */
+
+      /* ------------------ PRIVATE IOCTL ------------------ */
+#define SIOCSIPFRAMING	SIOCDEVPRIVATE		/* Set framing mode */
+#define SIOCGIPFRAMING	SIOCDEVPRIVATE + 1	/* Get framing mode */
+#define SIOCGIPCOUNTRY	SIOCDEVPRIVATE + 3	/* Get country code */
+    case SIOCSIPFRAMING:
+      if(!suser())	/* For private IOCTLs, we need to check permissions */
+	{
+	  err = -EPERM;
+	  break;
+	}
+      translate = *(wrq->u.name);	/* Set framing mode */
+      break;
+    case SIOCGIPFRAMING:
+      *(wrq->u.name) = translate;
+      break;
+    case SIOCGIPCOUNTRY:
+      *(wrq->u.name) = country;
+      break;
+    case SIOCGIWPRIV:
+      /* Export our "private" intercace */
+      if(wrq->u.data.pointer != (caddr_t) 0)
+	{
+	  struct iw_priv_args	priv[] =
+	  {	/* cmd,		set_args,	get_args,	name */
+	    { SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" },
+	    { SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" },
+	    { SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" },
+	  };
+	  /* Set the number of ioctl available */
+	  wrq->u.data.length = 3;
+	  /* Copy structure to the user buffer */
+	  if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
+		       sizeof(priv)))
+	    err = -EFAULT;
+	}
+      break;
+#endif	/* WIRELESS_EXT > 7 */
+
+
         default:
             DEBUG(0,"ray_dev_ioctl cmd = 0x%x\n", cmd);
             err = -EOPNOTSUPP;
@@ -1207,7 +1481,38 @@
     return err;
 } /* end ray_dev_ioctl */
 /*===========================================================================*/
-int ray_open(struct net_device *dev)
+#if WIRELESS_EXT > 7	/* If wireless extension exist in the kernel */
+static iw_stats * ray_get_wireless_stats(struct device *	dev)
+{
+  ray_dev_t *	local = (ray_dev_t *) dev->priv;
+  dev_link_t *link = local->finder;
+  struct status *p = (struct status *)(local->sram + STATUS_BASE);
+
+  if(local == (ray_dev_t *) NULL)
+    return (iw_stats *) NULL;
+
+  local->wstats.status = local->card_status;
+#ifdef WIRELESS_SPY
+  if((local->spy_number > 0) && (local->sparm.b5.a_network_type == 0))
+    {
+      /* Get it from the first node in spy list */
+      local->wstats.qual.qual = local->spy_stat[0].qual;
+      local->wstats.qual.level = local->spy_stat[0].level;
+      local->wstats.qual.noise = local->spy_stat[0].noise;
+      local->wstats.qual.updated = local->spy_stat[0].updated;
+    }
+#endif /* WIRELESS_SPY */
+
+  if((link->state & DEV_PRESENT)) {
+    local->wstats.qual.noise = readb(&p->rxnoise);
+    local->wstats.qual.updated |= 4;
+  }
+
+  return &local->wstats;
+} /* end ray_get_wireless_stats */
+#endif	/* WIRELESS_EXT > 7 */
+/*===========================================================================*/
+static int ray_open(struct net_device *dev)
 {
     dev_link_t *link;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
@@ -1232,7 +1537,7 @@
     return 0;
 } /* end ray_open */
 /*===========================================================================*/
-int ray_dev_close(struct net_device *dev)
+static int ray_dev_close(struct net_device *dev)
 {
     dev_link_t *link;
 
@@ -1255,14 +1560,14 @@
     return 0;
 } /* end ray_dev_close */
 /*===========================================================================*/
-void ray_reset(struct net_device *dev) {
+static void ray_reset(struct net_device *dev) {
     DEBUG(1,"ray_reset entered\n");
     return;
 }
 /*===========================================================================*/
 /* Cause a firmware interrupt if it is ready for one                         */
 /* Return nonzero if not ready                                               */
-int interrupt_ecf(ray_dev_t *local, int ccs)
+static int interrupt_ecf(ray_dev_t *local, int ccs)
 {
     int i = 50;
     dev_link_t *link = local->finder;
@@ -1288,7 +1593,7 @@
 /*===========================================================================*/
 /* Get next free transmit CCS                                                */
 /* Return - index of current tx ccs                                          */
-int get_free_tx_ccs(ray_dev_t *local)
+static int get_free_tx_ccs(ray_dev_t *local)
 {
     int i;
     struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
@@ -1319,7 +1624,7 @@
 /*===========================================================================*/
 /* Get next free CCS                                                         */
 /* Return - index of current ccs                                             */
-int get_free_ccs(ray_dev_t *local)
+static int get_free_ccs(ray_dev_t *local)
 {
     int i;
     struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
@@ -1347,7 +1652,7 @@
     return ECCSFULL;
 } /* get_free_ccs */
 /*===========================================================================*/
-void authenticate_timeout(u_long data)
+static void authenticate_timeout(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
     del_timer(&local->timer);
@@ -1356,7 +1661,7 @@
     join_net((u_long)local);
 }
 /*===========================================================================*/
-int asc_to_int(char a)
+static int asc_to_int(char a)
 {
     if (a < '0') return -1;
     if (a <= '9') return (a - '0');
@@ -1367,7 +1672,7 @@
     return -1;
 }
 /*===========================================================================*/
-int parse_addr(char *in_str, UCHAR *out)
+static int parse_addr(char *in_str, UCHAR *out)
 {
     int len;
     int i,j,k;
@@ -1395,7 +1700,7 @@
     return status;
 }
 /*===========================================================================*/
-struct enet_statistics *ray_get_stats(struct net_device *dev)
+static struct enet_statistics *ray_get_stats(struct net_device *dev)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
@@ -1425,7 +1730,7 @@
     return &local->stats;
 }
 /*===========================================================================*/
-void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
+static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
@@ -1542,7 +1847,7 @@
 /*=============================================================================
  * All routines below here are run at interrupt time.
 =============================================================================*/
-void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
     struct net_device *dev = (struct net_device *)dev_id;
     dev_link_t *link;
@@ -1727,7 +2032,7 @@
             break;
         default:
             DEBUG(1,"ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n",\
-                  rcsindex, readb(&prcs->interrupt_id));
+                  rcsindex, (unsigned int) readb(&prcs->interrupt_id));
             break;
         }
         writeb(CCS_BUFFER_FREE, &prcs->buffer_status);
@@ -1736,7 +2041,7 @@
     dev->interrupt = 0;
 } /* ray_interrupt */
 /*===========================================================================*/
-void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
 {
     int rx_len;
     unsigned int pkt_addr;
@@ -1750,6 +2055,7 @@
     rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8)
         + readb(&prcs->var.rx_packet.rx_data_length[1]);
 
+    local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev);
     pmsg = local->rmem + pkt_addr;
     switch(readb(pmsg))
     {
@@ -1778,17 +2084,18 @@
                           rx_len < sizeof(struct beacon_rx) ? 
                           rx_len : sizeof(struct beacon_rx));
 
+	local->beacon_rxed = 1;
         /* Get the statistics so the card counters never overflow */
         ray_get_stats(dev);
             break;
     default:
-        DEBUG(0,"ray_cs unknown pkt type %2x\n", readb(pmsg));
+        DEBUG(0,"ray_cs unknown pkt type %2x\n", (unsigned int) readb(pmsg));
         break;
     }
 
 } /* end ray_rx */
 /*===========================================================================*/
-void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
+static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
              int rx_len)
 {
     struct sk_buff *skb = NULL;
@@ -1797,6 +2104,10 @@
     UCHAR *rx_ptr;
     int total_len;
     int tmp;
+#ifdef WIRELESS_SPY
+    int siglev = prcs->var.rx_packet.rx_sig_lev;
+    u_char linksrcaddr[ETH_ALEN];	/* Other end of the wireless link */
+#endif
 
     if (!sniffer) {
         if (translate) {
@@ -1819,7 +2130,7 @@
     }
     DEBUG(4,"ray_cs rx_data packet\n");
     /* If fragmented packet, verify sizes of fragments add up */
-    if (prcs->var.rx_packet.next_frag_rcs_index != 0xFF) {
+    if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) {
         DEBUG(1,"ray_cs rx'ed fragment\n");
         tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8)
             +  readb(&prcs->var.rx_packet.totalpacketlength[1]);
@@ -1865,7 +2176,10 @@
     rx_ptr = skb_put( skb, total_len);
     /* Copy the whole packet to sk_buff */
     rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len);
-
+    /* Get source address */
+#ifdef WIRELESS_SPY
+    memcpy(linksrcaddr, ((struct mac_header *)skb->data)->addr_2, ETH_ALEN);
+#endif
     /* Now, deal with encapsulation/translation/sniffer */
     if (!sniffer) {
         if (!translate) { 
@@ -1909,9 +2223,39 @@
 
     local->stats.rx_packets++;
     local->stats.rx_bytes += skb->len;
+
+    /* Gather signal strength per address */
+#ifdef WIRELESS_SPY
+    /* For the Access Point or the node having started the ad-hoc net
+     * note : ad-hoc work only in some specific configurations, but we
+     * kludge in ray_get_wireless_stats... */
+    if(!memcmp(linksrcaddr, local->bss_id, ETH_ALEN))
+      {
+	/* Update statistics */
+	/*local->wstats.qual.qual = none ? */
+	local->wstats.qual.level = siglev;
+	/*local->wstats.qual.noise = none ? */
+	local->wstats.qual.updated = 0x2;
+      }
+    /* Now, for the addresses in the spy list */
+    {
+      int	i;
+      /* Look all addresses */
+      for(i = 0; i < local->spy_number; i++)
+	/* If match */
+	if(!memcmp(linksrcaddr, local->spy_address[i], ETH_ALEN))
+	  {
+	    /* Update statistics */
+	    /*local->spy_stat[i].qual = none ? */
+	    local->spy_stat[i].level = siglev;
+	    /*local->spy_stat[i].noise = none ? */
+	    local->spy_stat[i].updated = 0x2;
+	  }
+    }
+#endif	/* WIRELESS_SPY */
 } /* end rx_data */
 /*===========================================================================*/
-void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
+static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
 {
     snaphdr_t *psnap = (snaphdr_t *)(skb->data + RX_MAC_HEADER_LENGTH);
     struct mac_header *pmac = (struct mac_header *)skb->data;
@@ -1923,11 +2267,23 @@
     UCHAR srcaddr[ADDRLEN];
     UCHAR destaddr[ADDRLEN];
 
-    if (local->sparm.b5.a_acting_as_ap_status != TYPE_STA)
-        memcpy(destaddr, pmac->addr_3, ADDRLEN);
-    else
-        memcpy(destaddr, pmac->addr_1, ADDRLEN);
-    memcpy(srcaddr, pmac->addr_2, ADDRLEN);
+    if (pmac->frame_ctl_2 & FC2_FROM_DS) {
+	if (pmac->frame_ctl_2 & FC2_TO_DS) { /* AP to AP */
+	    memcpy(destaddr, pmac->addr_3, ADDRLEN);
+	    memcpy(srcaddr, ((unsigned char *)pmac->addr_3) + ADDRLEN, ADDRLEN);
+	} else { /* AP to terminal */
+	    memcpy(destaddr, pmac->addr_1, ADDRLEN);
+	    memcpy(srcaddr, pmac->addr_3, ADDRLEN); 
+	}
+    } else { /* Terminal to AP */
+	if (pmac->frame_ctl_2 & FC2_TO_DS) {
+	    memcpy(destaddr, pmac->addr_3, ADDRLEN);
+	    memcpy(srcaddr, pmac->addr_2, ADDRLEN); 
+	} else { /* Adhoc */
+	    memcpy(destaddr, pmac->addr_1, ADDRLEN);
+	    memcpy(srcaddr, pmac->addr_2, ADDRLEN); 
+	}
+    }
 
 #ifdef PCMCIA_DEBUG
     if (pc_debug > 3) {
@@ -2005,7 +2361,7 @@
  * pkt_addr = source address in receive buffer
  * len      = length of packet to copy
  */
-int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length)
+static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length)
 {
     int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1);
     if (wrap_bytes <= 0)
@@ -2020,7 +2376,7 @@
     return length;
 }
 /*===========================================================================*/
-void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
+static void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
 {
     struct rcs *prcslink = prcs;
     int tmp = 17;
@@ -2038,7 +2394,7 @@
     writeb(CCS_BUFFER_FREE, &prcslink->buffer_status);
 }
 /*===========================================================================*/
-void authenticate(ray_dev_t *local)
+static void authenticate(ray_dev_t *local)
 {
     dev_link_t *link = local->finder;
     DEBUG(0,"ray_cs Starting authentication.\n");
@@ -2060,7 +2416,7 @@
     local->authentication_state = AWAITING_RESPONSE;
 } /* end authenticate */
 /*===========================================================================*/
-void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
                      unsigned int pkt_addr, int rx_len)
 {
     UCHAR buff[256];
@@ -2103,7 +2459,7 @@
 
 } /* end rx_authenticate */
 /*===========================================================================*/
-void associate(ray_dev_t *local)
+static void associate(ray_dev_t *local)
 {
     struct ccs *pccs;
     dev_link_t *link = local->finder;
@@ -2141,7 +2497,7 @@
 
 } /* end associate */
 /*===========================================================================*/
-void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
+static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
                        unsigned int pkt_addr, int rx_len)
 {
 /*  UCHAR buff[256];
@@ -2154,7 +2510,7 @@
  */
 }
 /*===========================================================================*/
-void clear_interrupt(ray_dev_t *local)
+static void clear_interrupt(ray_dev_t *local)
 {
     writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET);
 }
@@ -2183,7 +2539,7 @@
 static char *framing[] = {"Encapsulation", "Translation"}
 ;
 /*===========================================================================*/
-int ray_cs_proc_read(char *buf, char **start, off_t offset, 
+static int ray_cs_proc_read(char *buf, char **start, off_t offset, 
                      int len, int unused)
 {
 /* Print current values which are not available via other means
@@ -2229,10 +2585,13 @@
 
     len += sprintf(buf + len, "Framing mode         = %s\n",framing[translate]);
 
-    /* Pull some fields out of last beacon received */
-    len += sprintf(buf + len, "Beacon Interval      = %d Kus\n", 
-                   local->last_bcn.beacon_intvl[0]
-                   + 256 * local->last_bcn.beacon_intvl[1]);
+    len += sprintf(buf + len, "Last pkt signal lvl  = %d\n", local->last_rsl);
+
+    if (local->beacon_rxed) {
+	/* Pull some fields out of last beacon received */
+	len += sprintf(buf + len, "Beacon Interval      = %d Kus\n", 
+		       local->last_bcn.beacon_intvl[0]
+		       + 256 * local->last_bcn.beacon_intvl[1]);
     
     p = local->last_bcn.elements;
     if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2;
@@ -2253,25 +2612,28 @@
         return len;
     }
 
-    if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
-        pfh = (struct freq_hop_element *)p;
-        len += sprintf(buf + len, "Hop dwell            = %d Kus\n",
-                       pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
-        len += sprintf(buf + len, "Hop set              = %d \n", pfh->hop_set);
-        len += sprintf(buf + len, "Hop pattern          = %d \n", pfh->hop_pattern);
-        len += sprintf(buf + len, "Hop index            = %d \n", pfh->hop_index);
-        p += p[1] + 2;
-    }
-    else {
-        len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
-        return len;
+	if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
+	    pfh = (struct freq_hop_element *)p;
+	    len += sprintf(buf + len, "Hop dwell            = %d Kus\n",
+			   pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
+	    len += sprintf(buf + len, "Hop set              = %d \n", pfh->hop_set);
+	    len += sprintf(buf + len, "Hop pattern          = %d \n", pfh->hop_pattern);
+	    len += sprintf(buf + len, "Hop index            = %d \n", pfh->hop_index);
+	    p += p[1] + 2;
+	}
+	else {
+	    len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
+	    return len;
+	}
+    } else {
+	len += sprintf(buf + len, "No beacons received\n");
     }
     return len;
 }
 
 #endif
 /*===========================================================================*/
-int  build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
+static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
 {
     int addr;
     struct ccs *pccs;
diff -u --recursive --new-file v2.3.23/linux/drivers/net/pcmcia/ray_cs.h linux/drivers/net/pcmcia/ray_cs.h
--- v2.3.23/linux/drivers/net/pcmcia/ray_cs.h	Sat Oct  9 11:47:50 1999
+++ linux/drivers/net/pcmcia/ray_cs.h	Mon Oct 25 20:54:50 1999
@@ -60,7 +60,18 @@
     UCHAR ASIC_version;
     UCHAR assoc_id[2];
     UCHAR tib_length;
+    UCHAR last_rsl;
+    int beacon_rxed;
     struct beacon_rx last_bcn;
+#ifdef WIRELESS_EXT
+    iw_stats	wstats;		/* Wireless specific stats */
+#endif
+#ifdef WIRELESS_SPY
+    int		spy_number;		/* Number of addresses to spy */
+    mac_addr	spy_address[IW_MAX_SPY + 1];	/* The addresses to spy */
+    iw_qual	spy_stat[IW_MAX_SPY + 1];	/* Statistics gathered */
+#endif	/* WIRELESS_SPY */
+
 } ray_dev_t;
 /*****************************************************************************/
 
diff -u --recursive --new-file v2.3.23/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
--- v2.3.23/linux/drivers/net/ppp_generic.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/net/ppp_generic.c	Mon Oct 25 08:26:52 1999
@@ -561,6 +561,7 @@
 #ifndef MODULE
 	extern struct compressor ppp_deflate, ppp_deflate_draft;
 	extern int ppp_async_init(void);
+	extern int ppp_sync_init(void);
 #endif
 
 	printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
@@ -570,6 +571,9 @@
 #ifndef MODULE
 #ifdef CONFIG_PPP_ASYNC
 	ppp_async_init();
+#endif
+#ifdef CONFIG_PPP_SYNC_TTY
+	ppp_sync_init();
 #endif
 #ifdef CONFIG_PPP_DEFLATE
 	if (ppp_register_compressor(&ppp_deflate) == 0)
diff -u --recursive --new-file v2.3.23/linux/drivers/net/ppp_synctty.c linux/drivers/net/ppp_synctty.c
--- v2.3.23/linux/drivers/net/ppp_synctty.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/ppp_synctty.c	Mon Oct 25 08:26:52 1999
@@ -0,0 +1,768 @@
+/*
+ * PPP synchronous tty channel driver for Linux.
+ *
+ * This is a ppp channel driver that can be used with tty device drivers
+ * that are frame oriented, such as synchronous HDLC devices.
+ *
+ * Complete PPP frames without encoding/decoding are exchanged between
+ * the channel driver and the device driver.
+ * 
+ * The async map IOCTL codes are implemented to keep the user mode
+ * applications happy if they call them. Synchronous PPP does not use
+ * the async maps.
+ *
+ * Copyright 1999 Paul Mackerras.
+ *
+ * Also touched by the grubby hands of Paul Fulghum paulkf@microgate.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.
+ *
+ * This driver provides the encapsulation and framing for sending
+ * and receiving PPP frames over sync serial lines.  It relies on
+ * the generic PPP layer to give it frames to send and to process
+ * received frames.  It implements the PPP line discipline.
+ *
+ * Part of the code in this driver was inspired by the old sync-only
+ * PPP driver, written by Michael Callahan and Al Longyear, and
+ * subsequently hacked by Paul Mackerras.
+ *
+ * ==FILEVERSION 991014==
+ */
+
+/* $Id: ppp_synctty.c,v 1.3 1999/09/02 05:30:10 paulus Exp $ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/tty.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+#include <asm/uaccess.h>
+
+#define PPP_VERSION	"2.4.0"
+
+/* Structure for storing local state. */
+struct syncppp {
+	struct tty_struct *tty;
+	unsigned int	flags;
+	unsigned int	rbits;
+	int		mru;
+	unsigned long	busy;
+	u32		xaccm[8];
+	u32		raccm;
+	unsigned int	bytes_sent;
+	unsigned int	bytes_rcvd;
+
+	struct sk_buff	*tpkt;
+	struct sk_buff_head xq;
+	unsigned long	last_xmit;
+
+	struct sk_buff	*rpkt;
+	struct sk_buff_head rq;
+	wait_queue_head_t rwait;
+
+	struct ppp_channel chan;	/* interface to generic ppp layer */
+	int		connected;
+};
+
+/* Bit numbers in busy */
+#define XMIT_BUSY	0
+#define RECV_BUSY	1
+#define XMIT_WAKEUP	2
+#define XMIT_FULL	3
+
+/* Bits in rbits */
+#define SC_RCV_BITS	(SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+#define PPPSYNC_MAX_RQLEN	32	/* arbitrary */
+
+/*
+ * Prototypes.
+ */
+static struct sk_buff* ppp_sync_txdequeue(struct syncppp *ap);
+static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
+static int ppp_sync_push(struct syncppp *ap);
+static void ppp_sync_flush_output(struct syncppp *ap);
+static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+			    char *flags, int count);
+
+struct ppp_channel_ops sync_ops = {
+	ppp_sync_send
+};
+
+/*
+ * Routines for locking and unlocking the transmit and receive paths.
+ */
+static inline void
+lock_path(struct syncppp *ap, int bit)
+{
+	do {
+		while (test_bit(bit, &ap->busy))
+		       mb();
+	} while (test_and_set_bit(bit, &ap->busy));
+	mb();
+}
+
+static inline int
+trylock_path(struct syncppp *ap, int bit)
+{
+	if (test_and_set_bit(bit, &ap->busy))
+		return 0;
+	mb();
+	return 1;
+}
+
+static inline void
+unlock_path(struct syncppp *ap, int bit)
+{
+	mb();
+	clear_bit(bit, &ap->busy);
+}
+
+#define lock_xmit_path(ap)	lock_path(ap, XMIT_BUSY)
+#define trylock_xmit_path(ap)	trylock_path(ap, XMIT_BUSY)
+#define unlock_xmit_path(ap)	unlock_path(ap, XMIT_BUSY)
+#define lock_recv_path(ap)	lock_path(ap, RECV_BUSY)
+#define trylock_recv_path(ap)	trylock_path(ap, RECV_BUSY)
+#define unlock_recv_path(ap)	unlock_path(ap, RECV_BUSY)
+
+static inline void
+flush_skb_queue(struct sk_buff_head *q)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(q)) != 0)
+		kfree_skb(skb);
+}
+
+/*
+ * Routines implementing the synchronous PPP line discipline.
+ */
+
+/*
+ * Called when a tty is put into line discipline.
+ */
+static int
+ppp_sync_open(struct tty_struct *tty)
+{
+	struct syncppp *ap;
+
+	ap = kmalloc(sizeof(*ap), GFP_KERNEL);
+	if (ap == 0)
+		return -ENOMEM;
+
+	MOD_INC_USE_COUNT;
+
+	/* initialize the syncppp structure */
+	memset(ap, 0, sizeof(*ap));
+	ap->tty = tty;
+	ap->mru = PPP_MRU;
+	ap->xaccm[0] = ~0U;
+	ap->xaccm[3] = 0x60000000U;
+	ap->raccm = ~0U;
+	skb_queue_head_init(&ap->xq);
+	skb_queue_head_init(&ap->rq);
+	init_waitqueue_head(&ap->rwait);
+
+	tty->disc_data = ap;
+
+	return 0;
+}
+
+/*
+ * Called when the tty is put into another line discipline
+ * (or it hangs up).
+ */
+static void
+ppp_sync_close(struct tty_struct *tty)
+{
+	struct syncppp *ap = tty->disc_data;
+
+	if (ap == 0)
+		return;
+	tty->disc_data = 0;
+	lock_xmit_path(ap);
+	lock_recv_path(ap);
+	if (ap->rpkt != 0)
+		kfree_skb(ap->rpkt);
+	flush_skb_queue(&ap->rq);
+	if (ap->tpkt != 0)
+		kfree_skb(ap->tpkt);
+	flush_skb_queue(&ap->xq);
+	if (ap->connected)
+		ppp_unregister_channel(&ap->chan);
+	kfree(ap);
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Read a PPP frame.  pppd can use this to negotiate over the
+ * channel before it joins it to a bundle.
+ */
+static ssize_t
+ppp_sync_read(struct tty_struct *tty, struct file *file,
+	       unsigned char *buf, size_t count)
+{
+	struct syncppp *ap = tty->disc_data;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret;
+	struct sk_buff *skb = 0;
+
+	ret = -ENXIO;
+	if (ap == 0)
+		goto out;		/* should never happen */
+
+	add_wait_queue(&ap->rwait, &wait);
+	current->state = TASK_INTERRUPTIBLE;
+	for (;;) {
+		ret = -EAGAIN;
+		skb = skb_dequeue(&ap->rq);
+		if (skb)
+			break;
+		if (file->f_flags & O_NONBLOCK)
+			break;
+		ret = -ERESTARTSYS;
+		if (signal_pending(current))
+			break;
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&ap->rwait, &wait);
+
+	if (skb == 0)
+		goto out;
+
+	ret = -EOVERFLOW;
+	if (skb->len > count)
+		goto outf;
+	ret = -EFAULT;
+	if (copy_to_user(buf, skb->data, skb->len))
+		goto outf;
+	ret = skb->len;
+
+ outf:
+	kfree_skb(skb);
+ out:
+	return ret;
+}
+
+/*
+ * Write a ppp frame.  pppd can use this to send frames over
+ * this particular channel.
+ */
+static ssize_t
+ppp_sync_write(struct tty_struct *tty, struct file *file,
+		const unsigned char *buf, size_t count)
+{
+	struct syncppp *ap = tty->disc_data;
+	struct sk_buff *skb;
+	ssize_t ret;
+
+	ret = -ENXIO;
+	if (ap == 0)
+		goto out;	/* should never happen */
+
+	ret = -ENOMEM;
+	skb = alloc_skb(count + 2, GFP_KERNEL);
+	if (skb == 0)
+		goto out;
+	skb_reserve(skb, 2);
+	ret = -EFAULT;
+	if (copy_from_user(skb_put(skb, count), buf, count)) {
+		kfree_skb(skb);
+		goto out;
+	}
+
+	skb_queue_tail(&ap->xq, skb);
+	ppp_sync_push(ap);
+
+	ret = count;
+
+ out:
+	return ret;
+}
+
+static int
+ppp_sync_ioctl(struct tty_struct *tty, struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	struct syncppp *ap = tty->disc_data;
+	int err, val;
+	u32 accm[8];
+	struct sk_buff *skb;
+
+	err = -ENXIO;
+	if (ap == 0)
+		goto out;	/* should never happen */
+	err = -EPERM;
+	if (!capable(CAP_NET_ADMIN))
+		goto out;
+
+	err = -EFAULT;
+	switch (cmd) {
+	case PPPIOCGFLAGS:
+		val = ap->flags | ap->rbits;
+		if (put_user(val, (int *) arg))
+			break;
+		err = 0;
+		break;
+	case PPPIOCSFLAGS:
+		if (get_user(val, (int *) arg))
+			break;
+		ap->flags = val & ~SC_RCV_BITS;
+		ap->rbits = val & SC_RCV_BITS;
+		err = 0;
+		break;
+
+	case PPPIOCGASYNCMAP:
+		if (put_user(ap->xaccm[0], (u32 *) arg))
+			break;
+		err = 0;
+		break;
+	case PPPIOCSASYNCMAP:
+		if (get_user(ap->xaccm[0], (u32 *) arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCGRASYNCMAP:
+		if (put_user(ap->raccm, (u32 *) arg))
+			break;
+		err = 0;
+		break;
+	case PPPIOCSRASYNCMAP:
+		if (get_user(ap->raccm, (u32 *) arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCGXASYNCMAP:
+		if (copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm)))
+			break;
+		err = 0;
+		break;
+	case PPPIOCSXASYNCMAP:
+		if (copy_from_user(accm, (void *) arg, sizeof(accm)))
+			break;
+		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
+		accm[3] |= 0x60000000U;		/* must escape 0x7d, 0x7e */
+		memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
+		err = 0;
+		break;
+
+	case PPPIOCGMRU:
+		if (put_user(ap->mru, (int *) arg))
+			break;
+		err = 0;
+		break;
+	case PPPIOCSMRU:
+		if (get_user(val, (int *) arg))
+			break;
+		if (val < PPP_MRU)
+			val = PPP_MRU;
+		ap->mru = val;
+		err = 0;
+		break;
+
+	case PPPIOCATTACH:
+		if (get_user(val, (int *) arg))
+			break;
+		err = -EALREADY;
+		if (ap->connected)
+			break;
+		ap->chan.private = ap;
+		ap->chan.ops = &sync_ops;
+		err = ppp_register_channel(&ap->chan, val);
+		if (err != 0)
+			break;
+		ap->connected = 1;
+		break;
+	case PPPIOCDETACH:
+		err = -ENXIO;
+		if (!ap->connected)
+			break;
+		ppp_unregister_channel(&ap->chan);
+		ap->connected = 0;
+		err = 0;
+		break;
+
+	case TCGETS:
+	case TCGETA:
+		err = n_tty_ioctl(tty, file, cmd, arg);
+		break;
+
+	case TCFLSH:
+		/* flush our buffers and the serial port's buffer */
+		if (arg == TCIFLUSH || arg == TCIOFLUSH)
+			flush_skb_queue(&ap->rq);
+		if (arg == TCIOFLUSH || arg == TCOFLUSH)
+			ppp_sync_flush_output(ap);
+		err = n_tty_ioctl(tty, file, cmd, arg);
+		break;
+
+	case FIONREAD:
+		val = 0;
+		if ((skb = skb_peek(&ap->rq)) != 0)
+			val = skb->len;
+		if (put_user(val, (int *) arg))
+			break;
+		err = 0;
+		break;
+
+	default:
+		err = -ENOIOCTLCMD;
+	}
+ out:
+	return err;
+}
+
+static unsigned int
+ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
+{
+	struct syncppp *ap = tty->disc_data;
+	unsigned int mask;
+
+	if (ap == 0)
+		return 0;	/* should never happen */
+	poll_wait(file, &ap->rwait, wait);
+	mask = POLLOUT | POLLWRNORM;
+	if (skb_peek(&ap->rq))
+		mask |= POLLIN | POLLRDNORM;
+	if (test_bit(TTY_OTHER_CLOSED, &tty->flags) || tty_hung_up_p(file))
+		mask |= POLLHUP;
+	return mask;
+}
+
+static int
+ppp_sync_room(struct tty_struct *tty)
+{
+	return 65535;
+}
+
+static void
+ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
+		  char *flags, int count)
+{
+	struct syncppp *ap = tty->disc_data;
+
+	if (ap == 0)
+		return;
+	trylock_recv_path(ap);
+	ppp_sync_input(ap, buf, flags, count);
+	unlock_recv_path(ap);
+	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+	    && tty->driver.unthrottle)
+		tty->driver.unthrottle(tty);
+}
+
+static void
+ppp_sync_wakeup(struct tty_struct *tty)
+{
+	struct syncppp *ap = tty->disc_data;
+
+	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	if (ap == 0)
+		return;
+	if (ppp_sync_push(ap) && ap->connected)
+		ppp_output_wakeup(&ap->chan);
+}
+
+
+static struct tty_ldisc ppp_sync_ldisc = {
+	magic:	TTY_LDISC_MAGIC,
+	name:	"pppsync",
+	open:	ppp_sync_open,
+	close:	ppp_sync_close,
+	read:	ppp_sync_read,
+	write:	ppp_sync_write,
+	ioctl:	ppp_sync_ioctl,
+	poll:	ppp_sync_poll,
+	receive_room: ppp_sync_room,
+	receive_buf: ppp_sync_receive,
+	write_wakeup: ppp_sync_wakeup,
+};
+
+int
+ppp_sync_init(void)
+{
+	int err;
+
+	err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc);
+	if (err != 0)
+		printk(KERN_ERR "PPP_sync: error %d registering line disc.\n",
+		       err);
+	return err;
+}
+
+/*
+ * Procedures for encapsulation and framing.
+ */
+
+struct sk_buff*
+ppp_sync_txdequeue(struct syncppp *ap)
+{
+	int proto;
+	unsigned char *data;
+	int islcp;
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&ap->xq)) != NULL) {
+
+		data  = skb->data;
+		proto = (data[0] << 8) + data[1];
+
+		/* LCP packets with codes between 1 (configure-request)
+		 * and 7 (code-reject) must be sent as though no options
+		 * have been negotiated.
+		 */
+		islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+		/* prepend address/control fields if necessary */
+		if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
+			if (skb_headroom(skb) < 2) {
+				struct sk_buff *npkt = dev_alloc_skb(skb->len + 2);
+				if (npkt == NULL) {
+					kfree_skb(skb);
+					continue;
+				}
+				skb_reserve(npkt,2);
+				memcpy(skb_put(npkt,skb->len), skb->data, skb->len);
+				kfree_skb(skb);
+				skb = npkt;
+			}
+			skb_pull(skb,2);
+			skb->data[0] = PPP_ALLSTATIONS;
+			skb->data[1] = PPP_UI;
+		}
+
+		ap->last_xmit = jiffies;
+		break;
+	}
+
+	return skb;
+}
+
+/*
+ * Transmit-side routines.
+ */
+
+/*
+ * Send a packet to the peer over an sync tty line.
+ * Returns 1 iff the packet was accepted.
+ * If the packet was not accepted, we will call ppp_output_wakeup
+ * at some later time.
+ */
+static int
+ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb)
+{
+	struct syncppp *ap = chan->private;
+
+	ppp_sync_push(ap);
+
+	if (test_and_set_bit(XMIT_FULL, &ap->busy))
+		return 0;	/* already full */
+	ap->tpkt = skb;
+
+	ppp_sync_push(ap);
+	return 1;
+}
+
+/*
+ * Push as much data as possible out to the tty.
+ */
+static int
+ppp_sync_push(struct syncppp *ap)
+{
+	int sent, done = 0;
+	struct tty_struct *tty = ap->tty;
+	int tty_stuffed = 0;
+
+	if (!trylock_xmit_path(ap)) {
+		set_bit(XMIT_WAKEUP, &ap->busy);
+		return 0;
+	}
+	for (;;) {
+		if (test_and_clear_bit(XMIT_WAKEUP, &ap->busy))
+			tty_stuffed = 0;
+		if (ap->tpkt == 0) {
+			if ((ap->tpkt = ppp_sync_txdequeue(ap)) == 0) {
+				clear_bit(XMIT_FULL, &ap->busy);
+			        done = 1;
+			}
+		}
+		if (!tty_stuffed && ap->tpkt != NULL) {
+			set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+			sent = tty->driver.write(tty, 0, ap->tpkt->data, ap->tpkt->len);
+			if (sent < 0)
+				goto flush;	/* error, e.g. loss of CD */
+			if (sent < ap->tpkt->len) {
+				tty_stuffed = 1;
+			} else {
+				kfree_skb(ap->tpkt);
+				ap->tpkt = 0;
+			}
+			continue;
+		}
+		/* haven't made any progress */
+		unlock_xmit_path(ap);
+		if (!(test_bit(XMIT_WAKEUP, &ap->busy)
+		      || (!tty_stuffed && ap->tpkt != 0)))
+			break;
+		if (!trylock_xmit_path(ap))
+			break;
+	}
+	return done;
+
+flush:
+	if (ap->tpkt != 0) {
+		kfree_skb(ap->tpkt);
+		ap->tpkt = 0;
+		clear_bit(XMIT_FULL, &ap->busy);
+		done = 1;
+	}
+	unlock_xmit_path(ap);
+	return done;
+}
+
+/*
+ * Flush output from our internal buffers.
+ * Called for the TCFLSH ioctl.
+ */
+static void
+ppp_sync_flush_output(struct syncppp *ap)
+{
+	int done = 0;
+
+	flush_skb_queue(&ap->xq);
+	lock_xmit_path(ap);
+	if (ap->tpkt != NULL) {
+		kfree_skb(ap->tpkt);
+		ap->tpkt = 0;
+		clear_bit(XMIT_FULL, &ap->busy);
+		done = 1;
+	}
+	unlock_xmit_path(ap);
+	if (done && ap->connected)
+		ppp_output_wakeup(&ap->chan);
+}
+
+/*
+ * Receive-side routines.
+ */
+
+static inline void
+process_input_packet(struct syncppp *ap)
+{
+	struct sk_buff *skb;
+	unsigned char *p;
+	int code = 0;
+
+	skb = ap->rpkt;
+	ap->rpkt = 0;
+
+	/* strip address/control field if present */
+	p = skb->data;
+	if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
+		/* chop off address/control */
+		if (skb->len < 3)
+			goto err;
+		p = skb_pull(skb, 2);
+	}
+
+	/* decompress protocol field if compressed */
+	if (p[0] & 1) {
+		/* protocol is compressed */
+		skb_push(skb, 1)[0] = 0;
+	} else if (skb->len < 2)
+		goto err;
+
+	/* pass to generic layer or queue it */
+	if (ap->connected) {
+		ppp_input(&ap->chan, skb);
+	} else {
+		skb_queue_tail(&ap->rq, skb);
+		/* drop old frames if queue too long */
+		while (ap->rq.qlen > PPPSYNC_MAX_RQLEN
+		       && (skb = skb_dequeue(&ap->rq)) != 0)
+			kfree(skb);
+		wake_up_interruptible(&ap->rwait);
+	}
+	return;
+
+ err:
+	kfree_skb(skb);
+	if (ap->connected)
+		ppp_input_error(&ap->chan, code);
+}
+
+static inline void
+input_error(struct syncppp *ap, int code)
+{
+	if (ap->connected)
+		ppp_input_error(&ap->chan, code);
+}
+
+/* called when the tty driver has data for us. 
+ *
+ * Data is frame oriented: each call to ppp_sync_input is considered
+ * a whole frame. If the 1st flag byte is non-zero then the whole
+ * frame is considered to be in error and is tossed.
+ */
+static void
+ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+		char *flags, int count)
+{
+	struct sk_buff *skb;
+	unsigned char *sp;
+
+	if (count == 0)
+		return;
+
+	/* if flag set, then error, ignore frame */
+	if (flags != 0 && *flags) {
+		input_error(ap, *flags);
+		return;
+	}
+
+	/* stuff the chars in the skb */
+	if ((skb = ap->rpkt) == 0) {
+		if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
+			printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
+			input_error(ap, 0);
+			return;
+		}
+		/* Try to get the payload 4-byte aligned */
+		if (buf[0] != PPP_ALLSTATIONS)
+			skb_reserve(skb, 2 + (buf[0] & 1));
+		ap->rpkt = skb;
+	}
+	if (count > skb_tailroom(skb)) {
+		/* packet overflowed MRU */
+		input_error(ap, 1);
+	} else {
+		sp = skb_put(skb, count);
+		memcpy(sp, buf, count);
+		process_input_packet(ap);
+	}
+}
+
+#ifdef MODULE
+int
+init_module(void)
+{
+	return ppp_sync_init();
+}
+
+void
+cleanup_module(void)
+{
+	if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0)
+		printk(KERN_ERR "failed to unregister Sync PPP line discipline\n");
+}
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.23/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.3.23/linux/drivers/net/strip.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/net/strip.c	Wed Oct 27 16:06:53 1999
@@ -118,6 +118,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_strip.h>
 #include <linux/proc_fs.h>
+#include <linux/serialP.h>
 #include <linux/serial.h>
 #include <net/arp.h>
 
diff -u --recursive --new-file v2.3.23/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- v2.3.23/linux/drivers/pci/pcisyms.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/pci/pcisyms.c	Mon Oct 25 20:49:42 1999
@@ -19,6 +19,7 @@
 EXPORT_SYMBOL(pci_write_config_dword);
 EXPORT_SYMBOL(pci_devices);
 EXPORT_SYMBOL(pci_root);
+EXPORT_SYMBOL(pci_enable_device);
 EXPORT_SYMBOL(pci_find_class);
 EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_slot);
diff -u --recursive --new-file v2.3.23/linux/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- v2.3.23/linux/drivers/pcmcia/rsrc_mgr.c	Fri Oct 22 13:21:50 1999
+++ linux/drivers/pcmcia/rsrc_mgr.c	Mon Oct 25 11:23:51 1999
@@ -100,16 +100,6 @@
 
 /*======================================================================
 
-    Linux resource management extensions
-    
-======================================================================*/
-
-static spinlock_t rsrc_lock = SPIN_LOCK_UNLOCKED;
-
-#define check_io_region(b,n) (0)
-
-/*======================================================================
-
     These manage the internal databases of available resources.
     
 ======================================================================*/
@@ -190,7 +180,7 @@
     b = kmalloc(256, GFP_KERNEL);
     memset(b, 0, 256);
     for (i = base, most = 0; i < base+num; i += 8) {
-	if (check_region(i, 8) || check_io_region(i, 8))
+	if (check_region(i, 8))
 	    continue;
 	hole = inb(i);
 	for (j = 1; j < 8; j++)
@@ -203,7 +193,7 @@
 
     bad = any = 0;
     for (i = base; i < base+num; i += 8) {
-	if (check_region(i, 8) || check_io_region(i, 8))
+	if (check_region(i, 8))
 	    continue;
 	for (j = 0; j < 8; j++)
 	    if (inb(i+j) != most) break;
@@ -365,8 +355,7 @@
     if (*base != 0) {
 	for (m = io_db.next; m != &io_db; m = m->next) {
 	    if ((*base >= m->base) && (*base+num <= m->base+m->num)) {
-		if (check_region(*base, num) ||
-		    check_io_region(*base, num)) {
+		if (check_region(*base, num)) {
 		    return -1;
 		} else {
 		    request_region(*base, num, name);
@@ -382,8 +371,7 @@
 	for (*base = (m->base + align - 1) & (~(align-1));
 	     *base+align <= m->base + m->num;
 	     *base += align)
-	    if ((check_region(*base, num) == 0) &&
-		(check_io_region(*base, num) == 0)) {
+	    if (check_region(*base, num) == 0) {
 		request_region(*base, num, name);
 		return 0;
 	    }
diff -u --recursive --new-file v2.3.23/linux/drivers/scsi/script_asm.pl linux/drivers/scsi/script_asm.pl
--- v2.3.23/linux/drivers/scsi/script_asm.pl	Mon Jun 16 16:35:56 1997
+++ linux/drivers/scsi/script_asm.pl	Mon Oct 25 20:49:42 1999
@@ -896,7 +896,7 @@
 open (OUTPUT, ">$output") || die "$0 : can't open $output for writing\n";
 open (OUTPUTU, ">$outputu") || die "$0 : can't open $outputu for writing\n";
 
-print OUTPUT "u32 ".$prefix."SCRIPT[] = {\n";
+print OUTPUT "static u32 ".$prefix."SCRIPT[] = {\n";
 $instructions = 0;
 for ($i = 0; $i < $#code; ) {
     if ($list_in_array) {
@@ -935,7 +935,7 @@
     }
     printf OUTPUTU "#undef A_$i\n";
 
-    printf OUTPUT "u32 A_".$i."_used\[\] = {\n";
+    printf OUTPUT "static u32 A_".$i."_used\[\] __attribute((unused)) = {\n";
 printf STDERR "$i is used $symbol_references{$i}\n" if ($debug);
     foreach $j (split (/\s+/,$symbol_references{$i})) {
 	$j =~ /(ABS|REL),(.*),(.*)/;
@@ -957,15 +957,15 @@
 # NCR assembler outputs label patches in the form of indices into 
 # the code.
 #
-printf OUTPUT "u32 ".$prefix."LABELPATCHES[] = {\n";
+printf OUTPUT "static u32 ".$prefix."LABELPATCHES[] __attribute((unused)) = {\n";
 for $patch (sort {$a <=> $b} @label_patches) {
     printf OUTPUT "\t0x%08x,\n", $patch;
 }
 printf OUTPUT "};\n\n";
 
 $num_external_patches = 0;
-printf OUTPUT "struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".
-    "} ".$prefix."EXTERNAL_PATCHES[] = {\n";
+printf OUTPUT "static struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".
+    "} ".$prefix."EXTERNAL_PATCHES[] __attribute((unused)) = {\n";
 while ($ident = pop(@external_patches)) {
     $off = pop(@external_patches);
     printf OUTPUT "\t{0x%08x, &%s},\n", $off, $ident;
@@ -973,11 +973,11 @@
 }
 printf OUTPUT "};\n\n";
 
-printf OUTPUT "u32 ".$prefix."INSTRUCTIONS\t= %d;\n", 
+printf OUTPUT "static u32 ".$prefix."INSTRUCTIONS __attribute((unused))\t= %d;\n", 
     $instructions;
-printf OUTPUT "u32 ".$prefix."PATCHES\t= %d;\n", 
+printf OUTPUT "static u32 ".$prefix."PATCHES __attribute((unused))\t= %d;\n", 
     $#label_patches+1;
-printf OUTPUT "u32 ".$prefix."EXTERNAL_PATCHES_LEN\t= %d;\n",
+printf OUTPUT "static u32 ".$prefix."EXTERNAL_PATCHES_LEN __attribute((unused))\t= %d;\n",
     $num_external_patches;
 close OUTPUT;
 close OUTPUTU;
diff -u --recursive --new-file v2.3.23/linux/drivers/sound/ac97.c linux/drivers/sound/ac97.c
--- v2.3.23/linux/drivers/sound/ac97.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/ac97.c	Mon Oct 25 08:26:52 1999
@@ -5,6 +5,10 @@
 /* And for stereo. */
 #define ST 1
 
+/* Whether or not the bits in the channel are inverted. */
+#define INV 1
+#define NINV 0
+
 static struct ac97_chn_desc {
     int ac97_regnum;
     int oss_channel;
@@ -13,21 +17,22 @@
     int oss_mask;
     int recordNum;
     u16 regmask;
+    int is_inverted;
 } mixerRegs[] = {
-    { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME,   0x3f, ST, SOUND_MASK_VOLUME,   5, 0x0000 },
-    { AC97_MASTER_VOL_MONO,   SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000 },
-    { AC97_MASTER_TONE,       SOUND_MIXER_TREBLE,   0x0f, MO, SOUND_MASK_TREBLE,  -1, 0x00ff },
-    { AC97_MASTER_TONE,       SOUND_MIXER_BASS,     0x0f, MO, SOUND_MASK_BASS,    -1, 0xff00 },
-    { AC97_PCBEEP_VOL,        SOUND_MIXER_SPEAKER,  0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e },
-    { AC97_PHONE_VOL,         SOUND_MIXER_PHONEIN,  0x1f, MO, SOUND_MASK_PHONEIN,  7, 0x0000 },
-    { AC97_MIC_VOL,           SOUND_MIXER_MIC,      0x1f, MO, SOUND_MASK_MIC,      0, 0x0000 },
-    { AC97_LINEIN_VOL,        SOUND_MIXER_LINE,     0x1f, ST, SOUND_MASK_LINE,     4, 0x0000 },
-    { AC97_CD_VOL,            SOUND_MIXER_CD,       0x1f, ST, SOUND_MASK_CD,       1, 0x0000 },
-    { AC97_VIDEO_VOL,         SOUND_MIXER_VIDEO,    0x1f, ST, SOUND_MASK_VIDEO,    2, 0x0000 },
-    { AC97_AUX_VOL,           SOUND_MIXER_LINE1,    0x1f, ST, SOUND_MASK_LINE1,	   3, 0x0000 },
-    { AC97_PCMOUT_VOL,        SOUND_MIXER_PCM,      0x1f, ST, SOUND_MASK_PCM,     -1, 0x0000 },
-    { AC97_RECORD_GAIN,       SOUND_MIXER_IGAIN,    0x0f, ST, SOUND_MASK_IGAIN,   -1, 0x0000 },
-    { -1,   -1,                   0xff, 0, 0,                   -1, 0x0000 },
+    { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME,   0x3f, ST, SOUND_MASK_VOLUME,   5, 0x0000, INV  },
+    { AC97_MASTER_VOL_MONO,   SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000, INV  },
+    { AC97_MASTER_TONE,       SOUND_MIXER_TREBLE,   0x0f, MO, SOUND_MASK_TREBLE,  -1, 0x00ff, INV  },
+    { AC97_MASTER_TONE,       SOUND_MIXER_BASS,     0x0f, MO, SOUND_MASK_BASS,    -1, 0xff00, INV  },
+    { AC97_PCBEEP_VOL,        SOUND_MIXER_SPEAKER,  0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e, INV  },
+    { AC97_PHONE_VOL,         SOUND_MIXER_PHONEIN,  0x1f, MO, SOUND_MASK_PHONEIN,  7, 0x0000, INV  },
+    { AC97_MIC_VOL,           SOUND_MIXER_MIC,      0x1f, MO, SOUND_MASK_MIC,      0, 0x0000, INV  },
+    { AC97_LINEIN_VOL,        SOUND_MIXER_LINE,     0x1f, ST, SOUND_MASK_LINE,     4, 0x0000, INV  },
+    { AC97_CD_VOL,            SOUND_MIXER_CD,       0x1f, ST, SOUND_MASK_CD,       1, 0x0000, INV  },
+    { AC97_VIDEO_VOL,         SOUND_MIXER_VIDEO,    0x1f, ST, SOUND_MASK_VIDEO,    2, 0x0000, INV  },
+    { AC97_AUX_VOL,           SOUND_MIXER_LINE1,    0x1f, ST, SOUND_MASK_LINE1,	   3, 0x0000, INV  },
+    { AC97_PCMOUT_VOL,        SOUND_MIXER_PCM,      0x1f, ST, SOUND_MASK_PCM,     -1, 0x0000, INV  },
+    { AC97_RECORD_GAIN,       SOUND_MIXER_IGAIN,    0x0f, ST, SOUND_MASK_IGAIN,   -1, 0x0000, NINV },
+    { -1,		      -1,		    0xff, 0,  0,                  -1, 0x0000, 0    },
 };
 
 static struct ac97_chn_desc *
@@ -104,6 +109,25 @@
     return 0;
 }
 
+/* Reset the mixer to the currently saved settings.  */
+int
+ac97_reset (struct ac97_hwint *dev)
+{
+    int x;
+
+    if (dev->reset_device (dev))
+	return -1;
+
+    /* Now set the registers back to their last-written values. */
+    for (x = 0; mixerRegs[x].ac97_regnum != -1; x++) {
+	int regnum = mixerRegs[x].ac97_regnum;
+	int value = dev->last_written_mixer_values [regnum / 2];
+	if (value >= 0)
+	    ac97_put_register (dev, regnum, value);
+    }
+    return 0;
+}
+
 /* Return the contents of register REG; use the cache if the value in it
    is valid.  Returns a negative error code on failure. */
 int
@@ -156,38 +180,45 @@
    scaled value on success.  */
 
 static int
-ac97_scale_to_oss_val (int value, int maxval, int is_stereo)
+ac97_scale_to_oss_val (int value, int maxval, int is_stereo, int inv)
 {
     /* Muted?  */
     if (value & AC97_MUTE)
 	return 0;
 
     if (is_stereo)
-	return (ac97_scale_to_oss_val (value & 255, maxval, 0) << 8)
-	| (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0) << 0);
+	return (ac97_scale_to_oss_val (value & 255, maxval, 0, inv) << 8)
+	| (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
     else {
 	int i;
 	
 	/* Inverted. */
-	value = maxval - value;
+	if (inv)
+	    value = maxval - value;
 
 	i = (value * 100 + (maxval / 2)) / maxval;
 	if (i > 100)
 	     i = 100;
+	if (i < 0)
+	    i = 0;
 	return i;
     }
 }
 
 static int
-ac97_scale_from_oss_val (int value, int maxval, int is_stereo)
+ac97_scale_from_oss_val (int value, int maxval, int is_stereo, int inv)
 {
     if (is_stereo)
-	return (ac97_scale_from_oss_val (value & 255, maxval, 0) << 8)
-	| (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0) << 0);
+	return (ac97_scale_from_oss_val (value & 255, maxval, 0, inv) << 8)
+	| (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
     else {
-	int i = maxval - ((value & 255) * maxval + 50) / 100;
+	int i = ((value & 255) * maxval + 50) / 100;
+	if (inv)
+	    i = maxval - i;
 	if (i < 0)
 	    i = 0;
+	if (i > maxval)
+	    i = maxval;
 	return i;
     }
 }
@@ -204,7 +235,8 @@
     if (! ac97_is_valid_channel (dev, channel))
 	return -ENODEV;
     scaled_value = ac97_scale_from_oss_val (oss_value, channel->maxval,
-					    channel->is_stereo);
+					    channel->is_stereo, 
+					    channel->is_inverted);
     if (scaled_value < 0)
 	return scaled_value;
 
@@ -253,7 +285,8 @@
 	    regval >>= 1;
     }
     return ac97_scale_to_oss_val (regval, channel->maxval,
-				  channel->is_stereo);
+				  channel->is_stereo, 
+				  channel->is_inverted);
 }
 
 int
@@ -383,8 +416,9 @@
 		    else
 			ret = -EFAULT;
 		}
-		if (ret >= 0) {
-		    if (dev->last_written_OSS_values[channel] == AC97_REGVAL_UNKNOWN)
+		if (ret >= 0 && (dir & _IOC_READ)) {
+		    if (dev->last_written_OSS_values[channel]
+			== AC97_REGVAL_UNKNOWN)
 			dev->last_written_OSS_values[channel]
 			    = ac97_get_mixer_scaled (dev, channel);
 		    ret = dev->last_written_OSS_values[channel];
diff -u --recursive --new-file v2.3.23/linux/drivers/sound/ac97.h linux/drivers/sound/ac97.h
--- v2.3.23/linux/drivers/sound/ac97.h	Fri Oct 15 15:25:14 1999
+++ linux/drivers/sound/ac97.h	Mon Oct 25 08:26:52 1999
@@ -10,7 +10,7 @@
 #include "sound_config.h"
 #include "sound_calls.h"
 
-#define  AC97_RESET              0x0000      //  */
+#define  AC97_RESET              0x0000      //
 #define  AC97_MASTER_VOL_STEREO  0x0002      // Line Out
 #define  AC97_HEADPHONE_VOL      0x0004      // 
 #define  AC97_MASTER_VOL_MONO    0x0006      // TAD Output
@@ -207,6 +207,10 @@
 /* Default ioctl. */
 extern int ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd,
 			     caddr_t arg);
+
+/* Do a complete reset on the AC97 mixer, restoring all mixer registers to
+   the current values.  Normally used after an APM resume event.  */
+extern int ac97_reset (struct ac97_hwint *dev);
 #endif
 
 /*
diff -u --recursive --new-file v2.3.23/linux/drivers/sound/nm256.h linux/drivers/sound/nm256.h
--- v2.3.23/linux/drivers/sound/nm256.h	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/nm256.h	Mon Oct 25 08:26:52 1999
@@ -3,10 +3,12 @@
 
 #include "ac97.h"
 
+/* The revisions that we currently handle.  */
 enum nm256rev {
     REV_NM256AV, REV_NM256ZX
 };
 
+/* Per-card structure. */
 struct nm256_info 
 {
     /* Magic number used to verify that this struct is valid. */
@@ -34,10 +36,12 @@
     /* The mixer device. */
     int mixer_oss_dev;
 
-    /* Can only be opened once for each operation.  These aren't set
-       until an actual I/O operation is performed; this allows one
-       device to be open for read/write without inhibiting I/O to
-       the other device.  */
+    /* 
+     * Can only be opened once for each operation.  These aren't set
+     * until an actual I/O operation is performed; this allows one
+     * device to be open for read/write without inhibiting I/O to
+     * the other device.
+     */
     int is_open_play;
     int is_open_record;
 
@@ -46,25 +50,40 @@
     /* Ditto for recording a sample. */
     int recording;
 
-    /* The two memory ports. */
-    char *ports[2];
-
-    /* Starting offset of the port1 area mapped into memory. */
-    u32 port1_start;
-    /* Ending offset. */
-    u32 port1_end;
-    /* The offset of the end of the actual buffer area.  */
-    u32 bufend;
+    /* The two memory ports.  */
+    struct nm256_ports {
+	/* Physical address of the port. */
+	u32 physaddr;
+	/* Our mapped-in pointer. */
+	char *ptr;
+	/* PTR's offset within the physical port.  */
+	u32 start_offset;
+	/* And the offset of the end of the buffer.  */
+	u32 end_offset;
+    } port[2];
 
     /* The following are offsets within memory port 1. */
     u32 coeffBuf;
     u32 allCoeffBuf;
+
     /* Record and playback buffers. */
     u32 abuf1, abuf2;
 
     /* Offset of the AC97 mixer in memory port 2. */
     u32 mixer;
 
+    /* Offset of the mixer status register in memory port 2.  */
+    u32 mixer_status_offset;
+
+    /* Non-zero if we have written initial values to the mixer. */
+    u8 mixer_values_init;
+
+    /* 
+     * Status mask bit; (*mixer_status_loc & mixer_status_mask) == 0 means
+     * it's ready.  
+     */
+    u16 mixer_status_mask;
+
     /* The sizes of the playback and record ring buffers. */
     u32 playbackBufferSize;
     u32 recordBufferSize;
@@ -77,7 +96,7 @@
     /* The start of the block currently playing. */
     u32 curPlayPos;
 
-    /* The amount of data we requested to record. */
+    /* The amount of data we were requested to record. */
     u32 requestedRecAmt;
     /* The offset of the currently-recording block. */
     u32 curRecPos;
@@ -107,10 +126,17 @@
 /* Debug flag--bigger numbers mean more output. */
 extern int nm256_debug;
 
-/* Size of the second memory port. */
+/* The BIOS signature. */
+#define NM_SIGNATURE 0x4e4d0000
+/* Signature mask. */
+#define NM_SIG_MASK 0xffff0000
+
+/* Size of the second memory area. */
 #define NM_PORT2_SIZE 4096
-/* The location of the mixer. */
-#define NM_MIXER_BASE 0x600
+
+/* The base offset of the mixer in the second memory area. */
+#define NM_MIXER_OFFSET 0x600
+
 /* The maximum size of a coefficient entry. */
 #define NM_MAX_COEFFICIENT 0x5000
 
@@ -123,21 +149,33 @@
 #define NM_MISC_INT_2 0x1
 #define NM_ACK_INT(CARD, X) nm256_writePort16((CARD), 2, NM_INT_REG, (X) << 1)
 
-/* For the second revision.  It uses the same interrupt register, but it
-   holds 32 bits instead of 16.  */
+/* The AV's "mixer ready" status bit and location. */
+#define NM_MIXER_STATUS_OFFSET 0xa04
+#define NM_MIXER_READY_MASK 0x0800
+#define NM_MIXER_PRESENCE 0xa06
+#define NM_PRESENCE_MASK 0x0050
+#define NM_PRESENCE_VALUE 0x0040
+
+/*
+ * For the ZX.  It uses the same interrupt register, but it holds 32
+ * bits instead of 16.
+ */
 #define NM2_PLAYBACK_INT 0x10000
 #define NM2_RECORD_INT 0x80000
 #define NM2_MISC_INT_1 0x8
 #define NM2_MISC_INT_2 0x2
 #define NM2_ACK_INT(CARD, X) nm256_writePort32((CARD), 2, NM_INT_REG, (X))
 
+/* The ZX's "mixer ready" status bit and location. */
+#define NM2_MIXER_STATUS_OFFSET 0xa06
+#define NM2_MIXER_READY_MASK 0x0800
+
 /* The playback registers start from here. */
 #define NM_PLAYBACK_REG_OFFSET 0x0
 /* The record registers start from here. */
 #define NM_RECORD_REG_OFFSET 0x200
 
-/* The rate register is located 2 bytes from the start of the register
-   area. */
+/* The rate register is located 2 bytes from the start of the register area. */
 #define NM_RATE_REG_OFFSET 2
 
 /* Mono/stereo flag, number of bits on playback, and rate mask. */
@@ -156,7 +194,7 @@
 #define NM_AUDIO_MUTE_LEFT 0x8000
 #define NM_AUDIO_MUTE_RIGHT 0x0080
 
-/* Recording enable register */
+/* Recording enable register. */
 #define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0)
 #define NM_RECORD_ENABLE_FLAG 1
 #define NM_RECORD_FREERUN 2
@@ -179,26 +217,25 @@
   if (port < 1 || port > 2 || card == NULL) \
       return -1; \
 \
-  if (port == 1) { \
-        if (offset < card->port1_start || offset >= card->port1_end) { \
-	    printk (KERN_ERR "Bad port request port 1:0x%x\n", offset); \
-            return -1; \
-        } \
-        offset -= card->port1_start; \
-   } else if (offset < 0 || offset > 4096) { \
-        printk (KERN_ERR "Bad port request port 2: 0x%x\n", offset); \
-        return -1; \
-   }
+    if (offset < card->port[port - 1].start_offset \
+	|| offset >= card->port[port - 1].end_offset) { \
+	printk (KERN_ERR "Bad access: port %d, offset 0x%x\n", port, offset); \
+	return -1; \
+    } \
+    offset -= card->port[port - 1].start_offset;
 
 #define DEFwritePortX(X, func) \
 static inline int nm256_writePort##X (struct nm256_info *card,\
-					int port, int offset, int value)\
+				      int port, int offset, int value)\
 {\
     u##X *addr;\
 \
+    if (nm256_debug > 1)\
+        printk (KERN_DEBUG "Writing 0x%x to %d:0x%x\n", value, port, offset);\
+\
     NM_FIX_PORT;\
 \
-    addr = (u##X *)(card->ports[port - 1] + offset);\
+    addr = (u##X *)(card->port[port - 1].ptr + offset);\
     func (value, addr);\
     return 0;\
 }
@@ -207,29 +244,28 @@
 DEFwritePortX (16, writew)
 DEFwritePortX (32, writel)
 
-#define DEFreadPortX(X) \
+#define DEFreadPortX(X, func) \
 static inline u##X nm256_readPort##X (struct nm256_info *card,\
 					int port, int offset)\
 {\
-    u##X *addr, res;\
+    u##X *addr;\
 \
     NM_FIX_PORT\
 \
-    addr = (u##X *)(card->ports[port - 1] + offset);\
-    memcpy_fromio (&res, addr, sizeof (res));\
-    return res;\
+    addr = (u##X *)(card->port[port - 1].ptr + offset);\
+    return func(addr);\
 }
 
-DEFreadPortX (8)
-DEFreadPortX (16)
-DEFreadPortX (32)
+DEFreadPortX (8, readb)
+DEFreadPortX (16, readw)
+DEFreadPortX (32, readl)
 
 static inline int
 nm256_writeBuffer8 (struct nm256_info *card, u8 *src, int port, int offset,
 		      int amt)
 {
     NM_FIX_PORT;
-    memcpy_toio (card->ports[port - 1] + offset, src, amt);
+    memcpy_toio (card->port[port - 1].ptr + offset, src, amt);
     return 0;
 }
 
@@ -238,7 +274,7 @@
 		     int amt)
 {
     NM_FIX_PORT;
-    memcpy_fromio (dst, card->ports[port - 1] + offset, amt);
+    memcpy_fromio (dst, card->port[port - 1].ptr + offset, amt);
     return 0;
 }
 
diff -u --recursive --new-file v2.3.23/linux/drivers/sound/nm256_audio.c linux/drivers/sound/nm256_audio.c
--- v2.3.23/linux/drivers/sound/nm256_audio.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/nm256_audio.c	Mon Oct 25 08:26:52 1999
@@ -1,27 +1,37 @@
-/* Audio driver for the NeoMagic 256AV and 256ZX chipsets in native
-   mode, with AC97 mixer support.
-
-   Overall design and parts of this code stolen from vidc_*.c and
-   skeleton.c.
-
-   Yeah, there are a lot of magic constants in here.  You tell ME what
-   they are.  I just get this stuff psychically, remember? 
-
-   This driver was written by someone who wishes to remain anonymous. 
-   It is in the public domain, so share and enjoy.  Try to make a profit
-   off of it; go on, I dare you.  */
+/* 
+ * Audio driver for the NeoMagic 256AV and 256ZX chipsets in native
+ * mode, with AC97 mixer support.
+ *
+ * Overall design and parts of this code stolen from vidc_*.c and
+ * skeleton.c.
+ *
+ * Yeah, there are a lot of magic constants in here.  You tell ME what
+ * they are.  I just get this stuff psychically, remember? 
+ *
+ * This driver was written by someone who wishes to remain anonymous. 
+ * It is in the public domain, so share and enjoy.  Try to make a profit
+ * off of it; go on, I dare you.  
+ */
 
 #include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
 #include "sound_config.h"
 #include "soundmodule.h"
 #include "nm256.h"
 #include "nm256_coeff.h"
 
 int nm256_debug = 0;
+static int force_load = 0;
 
-/* The size of the playback reserve. */
+/* 
+ * The size of the playback reserve.  When the playback buffer has less
+ * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new
+ * buffer.
+ */
 #define NM256_PLAY_WMARK_SIZE 512
 
 static struct audio_driver nm256_audio_driver;
@@ -29,16 +39,74 @@
 static int nm256_grabInterrupt (struct nm256_info *card);
 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 void nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy);
 
 /* These belong in linux/pci.h. */
 #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
 
+/* eeeew. */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+#else
+#define RSRCADDRESS(dev,num) ((dev)->base_address[(num)] \
+			      & PCI_BASE_ADDRESS_MEM_MASK)
+
+#endif
+
 /* List of cards.  */
 static struct nm256_info *nmcard_list;
 
+/* Release the mapped-in memory for CARD.  */
+static void
+nm256_release_ports (struct nm256_info *card)
+{
+    int x;
+
+    for (x = 0; x < 2; x++) {
+	if (card->port[x].ptr != NULL) {
+	    u32 size = 
+		card->port[x].end_offset - card->port[x].start_offset;
+	    release_region ((unsigned long) card->port[x].ptr, size);
+	    card->port[x].ptr = NULL;
+	}
+    }
+}
+
+/* 
+ * Map in the memory ports for CARD, if they aren't already mapped in
+ * and have been configured.  If successful, a zero value is returned;
+ * otherwise any previously mapped-in areas are released and a non-zero
+ * value is returned.
+ *
+ * This is invoked twice, once for each port.  Ideally it would only be
+ * called once, but we now need to map in the second port in order to
+ * check how much memory the card has on the 256ZX.
+ */
+static int
+nm256_remap_ports (struct nm256_info *card)
+{
+    int x;
+
+    for (x = 0; x < 2; x++) {
+	if (card->port[x].ptr == NULL && card->port[x].end_offset > 0) {
+	    u32 physaddr 
+		= card->port[x].physaddr + card->port[x].start_offset;
+	    u32 size 
+		= card->port[x].end_offset - card->port[x].start_offset;
+
+	    card->port[x].ptr = ioremap_nocache (physaddr, size);
+						  
+	    if (card->port[x].ptr == NULL) {
+		printk (KERN_ERR "NM256: Unable to remap port %d\n", x + 1);
+		nm256_release_ports (card);
+		return -1;
+	    }
+	}
+    }
+    return 0;
+}
+
 /* Locate the card in our list. */
 static struct nm256_info *
 nm256_find_card (int dev)
@@ -52,8 +120,10 @@
     return NULL;
 }
 
-/* Ditto, but find the card struct corresponding to the mixer device DEV 
-   instead. */
+/*
+ * Ditto, but find the card struct corresponding to the mixer device DEV 
+ * instead. 
+ */
 static struct nm256_info *
 nm256_find_card_for_mixer (int dev)
 {
@@ -81,11 +151,13 @@
     8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999
 };
 
-/* Set the card samplerate, word size and stereo mode to correspond to
-   the settings in the CARD struct for the specified device in DEV.
-   We keep two separate sets of information, one for each device; the
-   hardware is not actually configured until a read or write is
-   attempted. */
+/*
+ * Set the card samplerate, word size and stereo mode to correspond to
+ * the settings in the CARD struct for the specified device in DEV.
+ * We keep two separate sets of information, one for each device; the
+ * hardware is not actually configured until a read or write is
+ * attempted.
+ */
 
 int
 nm256_setInfo (int dev, struct nm256_info *card)
@@ -113,24 +185,33 @@
 	    break;
 
     if (x < 8) {
-	u8 speedbits = ((x << 4) & NM_RATE_MASK)
-	    | (card->sinfo[w].bits == 16 ? NM_RATE_BITS_16: 0) 
-	    | (card->sinfo[w].stereo ? NM_RATE_STEREO : 0);
+	u8 ratebits = ((x << 4) & NM_RATE_MASK);
+	if (card->sinfo[w].bits == 16)
+	    ratebits |= NM_RATE_BITS_16;
+	if (card->sinfo[w].stereo)
+	    ratebits |= NM_RATE_STEREO;
 
 	card->sinfo[w].samplerate = samplerates[x];
 
+
 	if (card->dev_for_play == dev && card->playing) {
+	    if (nm256_debug)
+		printk (KERN_DEBUG "Setting play ratebits to 0x%x\n",
+			ratebits);
 	    nm256_loadCoefficient (card, 0, x);
 	    nm256_writePort8 (card, 2,
-				NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET,
-				speedbits);
+			      NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET,
+			      ratebits);
 	}
 
 	if (card->dev_for_record == dev && card->recording) {
+	    if (nm256_debug)
+		printk (KERN_DEBUG "Setting record ratebits to 0x%x\n",
+			ratebits);
 	    nm256_loadCoefficient (card, 1, x);
-	    nm256_writePort8 (card, 2, 
-				NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET,
-				speedbits);
+	    nm256_writePort8 (card, 2,
+			      NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET,
+			      ratebits);
 	}
 	return 0;
     }
@@ -149,7 +230,7 @@
 
 	    /* Enable playback engine and interrupts. */
 	    nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG,
-				NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN);
+			      NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN);
 
 	    /* Enable both channels. */
 	    nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG, 0x0);
@@ -157,9 +238,11 @@
     }
 }
 
-/* Request one chunk of AMT bytes from the recording device.  When the
-   operation is complete, the data will be copied into BUFFER and the
-   function DMAbuf_inputintr will be invoked. */
+/* 
+ * Request one chunk of AMT bytes from the recording device.  When the
+ * operation is complete, the data will be copied into BUFFER and the
+ * function DMAbuf_inputintr will be invoked.
+ */
 
 static void
 nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
@@ -167,11 +250,14 @@
     u32 endpos;
     int enableEngine = 0;
     u32 ringsize = card->recordBufferSize;
+    unsigned long flags;
 
     if (amt > (ringsize / 2)) {
-	/* Of course this won't actually work right, because the
-	   caller is going to assume we will give what we got asked
-	   for. */
+	/*
+	 * Of course this won't actually work right, because the
+	 * caller is going to assume we will give what we got asked
+	 * for.
+	 */
 	printk (KERN_ERR "NM256: Read request too large: %d\n", amt);
 	amt = ringsize / 2;
     }
@@ -181,8 +267,12 @@
 	return;
     }
 
-    /* If we're not currently recording, set up the start and end registers
-       for the recording engine. */
+    save_flags (flags);
+    cli ();
+    /*
+     * If we're not currently recording, set up the start and end registers
+     * for the recording engine.
+     */
     if (! card->recording) {
 	card->recording = 1;
 	if (nm256_grabInterrupt (card) == 0) {
@@ -198,10 +288,16 @@
 	}
 	else {
 	    /* Not sure what else to do here.  */
+	    restore_flags (flags);
 	    return;
 	}
     }
 
+    /* 
+     * If we happen to go past the end of the buffer a bit (due to a
+     * delayed interrupt) it's OK.  So might as well set the watermark
+     * right at the end of the data we want.
+     */
     endpos = card->abuf2 + ((card->curRecPos + amt) % ringsize);
 
     card->recBuf = buffer;
@@ -211,6 +307,8 @@
     if (enableEngine)
 	nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG,
 			    NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN);
+
+    restore_flags (flags);
 }
 
 /* Stop the play engine. */
@@ -219,7 +317,7 @@
 {
     /* Shut off sound from both channels. */
     nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG,
-			 NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT);
+		       NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT);
     /* Disable play engine. */
     nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG, 0);
     if (card->playing) {
@@ -246,18 +344,22 @@
     }
 }
 
-/* Ring buffers, man.  That's where the hip-hop, wild-n-wooly action's at.
-   1972?
-
-   Write AMT bytes of BUFFER to the playback ring buffer, and start the
-   playback engine running.  It will only accept up to 1/2 of the total
-   size of the ring buffer.  */
+/*
+ * Ring buffers, man.  That's where the hip-hop, wild-n-wooly action's at.
+ * 1972?  (Well, I suppose it was cheep-n-easy to implement.)
+ *
+ * Write AMT bytes of BUFFER to the playback ring buffer, and start the
+ * playback engine running.  It will only accept up to 1/2 of the total
+ * size of the ring buffer.  No check is made that we're about to overwrite
+ * the currently-playing sample.
+ */
 
 static void
 nm256_write_block (struct nm256_info *card, char *buffer, u32 amt)
 {
     u32 ringsize = card->playbackBufferSize;
     u32 endstop;
+    unsigned long flags;
 
     if (amt > (ringsize / 2)) {
 	printk (KERN_ERR "NM256: Write request too large: %d\n", amt);
@@ -273,6 +375,9 @@
 
     card->requested_amt = amt;
 
+    save_flags (flags);
+    cli ();
+
     if ((card->curPlayPos + amt) >= ringsize) {
 	u32 rem = ringsize - card->curPlayPos;
 
@@ -288,33 +393,40 @@
 			      card->abuf1 + card->curPlayPos,
 			      amt);
 
-    /* Setup the start-n-stop-n-limit registers, and start that engine
-       goin'. 
-
-       Normally we just let it wrap around to avoid the click-click
-       action scene. */
+    /*
+     * Setup the start-n-stop-n-limit registers, and start that engine
+     * goin'. 
+     *
+     * Normally we just let it wrap around to avoid the click-click
+     * action scene.
+     */
     if (! card->playing) {
-	/* The PBUFFER_END register in this case points to one "word"
+	/* The PBUFFER_END register in this case points to one sample
 	   before the end of the buffer. */
 	int w = (card->dev_for_play == card->dev[0] ? 0 : 1);
-	int wordsize = (card->sinfo[w].bits == 16 ? 2 : 1)
-	    * (card->sinfo[w].stereo ? 2 : 1);
+	int sampsize = (card->sinfo[w].bits == 16 ? 2 : 1);
+
+	if (card->sinfo[w].stereo)
+	    sampsize *= 2;
 
 	/* Need to set the not-normally-changing-registers up. */
 	nm256_writePort32 (card, 2, NM_PBUFFER_START,
 			     card->abuf1 + card->curPlayPos);
 	nm256_writePort32 (card, 2, NM_PBUFFER_END,
-			     card->abuf1 + ringsize - wordsize);
+			     card->abuf1 + ringsize - sampsize);
 	nm256_writePort32 (card, 2, NM_PBUFFER_CURRP,
 			     card->abuf1 + card->curPlayPos);
     }
     endstop = (card->curPlayPos + amt - NM256_PLAY_WMARK_SIZE) % ringsize;
     nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
+
     if (! card->playing)
 	startPlay (card);
+
+    restore_flags (flags);
 }
 
-/* We just got a card playback interrupt; process it. */
+/*  We just got a card playback interrupt; process it.  */
 static void
 nm256_get_new_block (struct nm256_info *card)
 {
@@ -332,13 +444,14 @@
 	amt -= card->curPlayPos;
 
     if (card->requested_amt > (amt + NM256_PLAY_WMARK_SIZE)) {
-	u32 endstop = 
+	u32 endstop =
 	    card->curPlayPos + card->requested_amt - NM256_PLAY_WMARK_SIZE;
 	nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
-    } else {
+    } 
+    else {
 	card->curPlayPos += card->requested_amt;
 	/* Get a new block to write.  This will eventually invoke
-	   nm256_write_block ().  */
+	   nm256_write_block () or stopPlay ().  */
 	DMAbuf_outputintr (card->dev_for_play, 1);
     }
 }
@@ -346,9 +459,11 @@
 /* Ultra cheez-whiz.  But I'm too lazy to grep headers. */
 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
 
-/* Read the last-recorded block from the ring buffer, copy it into the
-   saved buffer pointer, and invoke DMAuf_inputintr() with the recording
-   device. */
+/* 
+ * Read the last-recorded block from the ring buffer, copy it into the
+ * saved buffer pointer, and invoke DMAuf_inputintr() with the recording
+ * device. 
+ */
 
 static void
 nm256_read_block (struct nm256_info *card)
@@ -363,8 +478,10 @@
         currptr = 0;
     }
 
-    /* This test is probably redundant; we shouldn't be here unless
-       it's true.  */
+    /*
+     * This test is probably redundant; we shouldn't be here unless
+     * it's true.
+     */
     if (card->recording) {
 	/* If we wrapped around, copy everything from the start of our
 	   recording buffer to the end of the buffer. */
@@ -394,52 +511,28 @@
 }
 #undef MIN
 
-/* Initialize the hardware and various other card data we'll need
-   later. */
+/* 
+ * Initialize the hardware. 
+ */
 static void
 nm256_initHw (struct nm256_info *card)
 {
-    int x;
-
-    card->playbackBufferSize = 16384;
-    card->recordBufferSize = 16384;
-
-    card->coeffBuf = card->bufend - NM_MAX_COEFFICIENT;
-    card->abuf2 = card->coeffBuf - card->recordBufferSize;
-    card->abuf1 = card->abuf2 - card->playbackBufferSize;
-    card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4);
-
-    /* Fixed setting. */
-    card->mixer = NM_MIXER_BASE;
-
-    card->playing = 0;
-    card->is_open_play = 0;
-    card->curPlayPos = 0;
-
-    card->recording = 0;
-    card->is_open_record = 0;
-    card->curRecPos = 0;
-
-    card->coeffsCurrent = 0;
-
-    card->opencnt[0] = 0; card->opencnt[1] = 0;
-
     /* Reset everything. */
-    nm256_writePort8 (card, 2, 0, 0x11);
-
-    /* Disable recording. */
-    nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, 0);
+    nm256_writePort8 (card, 2, 0x0, 0x11);
     nm256_writePort16 (card, 2, 0x214, 0);
 
-    /* Reasonable default settings, but largely unnecessary. */
-    for (x = 0; x < 2; x++) {
-	card->sinfo[x].bits = 8;
-	card->sinfo[x].stereo = 0;
-	card->sinfo[x].samplerate = 8000;
-    }
+    stopRecord (card);
+    stopPlay (card);
 }
 
-/* Handle a potential interrupt for the device referred to by DEV_ID. */
+/* 
+ * Handle a potential interrupt for the device referred to by DEV_ID. 
+ *
+ * I don't like the cut-n-paste job here either between the two routines,
+ * but there are sufficient differences between the two interrupt handlers
+ * that parameterizing it isn't all that great either.  (Could use a macro,
+ * I suppose...yucky bleah.)
+ */
 
 static void
 nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
@@ -458,14 +551,32 @@
     /* Not ours. */
     if (status == 0) {
 	if (badintrcount++ > 1000) {
-	    printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n");
-	    nm256_releaseInterrupt (card);
+	    /*
+	     * I'm not sure if the best thing is to stop the card from
+	     * playing or just release the interrupt (after all, we're in
+	     * a bad situation, so doing fancy stuff may not be such a good
+	     * idea).
+	     *
+	     * I worry about the card engine continuing to play noise
+	     * over and over, however--that could become a very
+	     * obnoxious problem.  And we know that when this usually
+	     * happens things are fairly safe, it just means the user's
+	     * inserted a PCMCIA card and someone's spamming us with IRQ 9s.
+	     */
+
+	    if (card->playing)
+		stopPlay (card);
+	    if (card->recording)
+		stopRecord (card);
+	    badintrcount = 0;
 	}
 	return;
     }
 
     badintrcount = 0;
 
+    /* Rather boring; check for individual interrupts and process them. */
+
     if (status & NM_PLAYBACK_INT) {
 	status &= ~NM_PLAYBACK_INT;
 	NM_ACK_INT (card, NM_PLAYBACK_INT);
@@ -503,6 +614,7 @@
 	nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
     }
 
+    /* Unknown interrupt. */
     if (status) {
 	printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
 		status);
@@ -511,8 +623,11 @@
     }
 }
 
-/* Handle a potential interrupt for the device referred to by DEV_ID.
-   This handler is for the 256ZX.  */
+/*
+ * Handle a potential interrupt for the device referred to by DEV_ID.
+ * This handler is for the 256ZX, and is very similar to the non-ZX
+ * routine.
+ */
 
 static void
 nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy)
@@ -532,13 +647,33 @@
     if (status == 0) {
 	if (badintrcount++ > 1000) {
 	    printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n");
-	    nm256_releaseInterrupt (card);
+	    /*
+	     * I'm not sure if the best thing is to stop the card from
+	     * playing or just release the interrupt (after all, we're in
+	     * a bad situation, so doing fancy stuff may not be such a good
+	     * idea).
+	     *
+	     * I worry about the card engine continuing to play noise
+	     * over and over, however--that could become a very
+	     * obnoxious problem.  And we know that when this usually
+	     * happens things are fairly safe, it just means the user's
+	     * inserted a PCMCIA card and someone's spamming us with 
+	     * IRQ 9s.
+	     */
+
+	    if (card->playing)
+		stopPlay (card);
+	    if (card->recording)
+		stopRecord (card);
+	    badintrcount = 0;
 	}
 	return;
     }
 
     badintrcount = 0;
 
+    /* Rather boring; check for individual interrupts and process them. */
+
     if (status & NM2_PLAYBACK_INT) {
 	status &= ~NM2_PLAYBACK_INT;
 	NM2_ACK_INT (card, NM2_PLAYBACK_INT);
@@ -575,6 +710,7 @@
 	nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
     }
 
+    /* Unknown interrupt. */
     if (status) {
 	printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
 		status);
@@ -583,7 +719,9 @@
     }
 }
 
-/* Request our interrupt. */
+/* 
+ * Request our interrupt.
+ */
 static int
 nm256_grabInterrupt (struct nm256_info *card)
 {
@@ -597,7 +735,9 @@
     return 0;
 }
 
-/* Release our interrupt. */
+/* 
+ * Release our interrupt. 
+ */
 static int
 nm256_releaseInterrupt (struct nm256_info *card)
 {
@@ -612,6 +752,11 @@
     return 0;
 }
 
+/*
+ * Waits for the mixer to become ready to be written; returns a zero value
+ * if it timed out.
+ */
+
 static int
 nm256_isReady (struct ac97_hwint *dev)
 {
@@ -626,26 +771,25 @@
 	return 0;
     }
 
-    if (card->rev == REV_NM256AV) {
-	testaddr = 0xa06;
-	testb = 0x0100;
-    } else if (card->rev == REV_NM256ZX) {
-	testaddr = 0xa08;
-	testb = 0x0800;
-    } else {
-	return -1;
-    }
+    testaddr = card->mixer_status_offset;
+    testb = card->mixer_status_mask;
 
-    while (t2-- > 0) {
-	if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0) {
+    /* 
+     * Loop around waiting for the mixer to become ready. 
+     */
+    while (! done && t2-- > 0) {
+	if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0)
 	    done = 1;
-	    break;
-	}
-	udelay (100);
+	else
+	    udelay (100);
     }
     return done;
 }
 
+/*
+ * Return the contents of the AC97 mixer register REG.  Returns a positive
+ * value if successful, or a negative error code.
+ */
 static int
 nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg)
 {
@@ -661,6 +805,7 @@
 
 	nm256_isReady (dev);
 	res = nm256_readPort16 (card, 2, card->mixer + reg);
+	/* Magic delay.  Bleah yucky.  */
         udelay (1000);
 	return res;
     }
@@ -668,6 +813,10 @@
 	return -EINVAL;
 }
 
+/* 
+ * Writes VALUE to AC97 mixer register REG.  Returns 0 if successful, or
+ * a negative error code. 
+ */
 static int
 nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value)
 {
@@ -706,6 +855,13 @@
     return ! done;
 }
 
+/* 
+ * Initial register values to be written to the AC97 mixer.
+ * While most of these are identical to the reset values, we do this
+ * so that we have most of the register contents cached--this avoids
+ * reading from the mixer directly (which seems to be problematic,
+ * probably due to ignorance).
+ */
 struct initialValues 
 {
     unsigned short port;
@@ -714,23 +870,24 @@
 
 static struct initialValues nm256_ac97_initial_values[] = 
 {
-    { 0x0002, 0x8000 },
-    { 0x0004, 0x0000 },
-    { 0x0006, 0x0000 },
-    { 0x000A, 0x0000 },
-    { 0x000C, 0x0008 },
-    { 0x000E, 0x8008 },
-    { 0x0010, 0x8808 },
-    { 0x0012, 0x8808 },
-    { 0x0014, 0x8808 },
-    { 0x0016, 0x8808 },
-    { 0x0018, 0x0808 },
-    { 0x001A, 0x0000 },
-    { 0x001C, 0x0B0B },
-    { 0x0020, 0x0000 },
+    { AC97_MASTER_VOL_STEREO, 0x8000 },
+    { AC97_HEADPHONE_VOL,     0x8000 },
+    { AC97_MASTER_VOL_MONO,   0x0000 },
+    { AC97_PCBEEP_VOL,        0x0000 },
+    { AC97_PHONE_VOL,         0x0008 },
+    { AC97_MIC_VOL,           0x8000 },
+    { AC97_LINEIN_VOL,        0x8808 },
+    { AC97_CD_VOL,            0x8808 },
+    { AC97_VIDEO_VOL,         0x8808 },
+    { AC97_AUX_VOL,           0x8808 },
+    { AC97_PCMOUT_VOL,        0x0808 },
+    { AC97_RECORD_SELECT,     0x0000 },
+    { AC97_RECORD_GAIN,       0x0B0B },
+    { AC97_GENERAL_PURPOSE,   0x0000 },
     { 0xffff, 0xffff }
 };
 
+/* Initialize the AC97 into a known state.  */
 static int
 nm256_resetAC97 (struct ac97_hwint *dev)
 {
@@ -742,22 +899,28 @@
 	return -EINVAL;
     }
 
-    /* Reset the card.  'Tis magic!  */
+    /* Reset the mixer.  'Tis magic!  */
     nm256_writePort8 (card, 2, 0x6c0, 1);
     nm256_writePort8 (card, 2, 0x6cc, 0x87);
     nm256_writePort8 (card, 2, 0x6cc, 0x80);
     nm256_writePort8 (card, 2, 0x6cc, 0x0);
 
-    for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) {
-	ac97_put_register (dev,
-			   nm256_ac97_initial_values[x].port, 
-			   nm256_ac97_initial_values[x].value);
+    if (! card->mixer_values_init) {
+	for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) {
+	    ac97_put_register (dev,
+			       nm256_ac97_initial_values[x].port,
+			       nm256_ac97_initial_values[x].value);
+	    card->mixer_values_init = 1;
+	}
     }
 
     return 0;
 }
 
-/* We don't do anything special here.  */
+/*
+ * We don't do anything particularly special here; it just passes the
+ * mixer ioctl to the AC97 driver.
+ */
 static int
 nm256_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
@@ -774,7 +937,12 @@
     nm256_default_mixer_ioctl
 };
 
-/* I "love" C sometimes.  Got braces?  */
+/*
+ * Default settings for the OSS mixer.  These are set last, after the
+ * mixer is initialized.
+ *
+ * I "love" C sometimes.  Got braces?
+ */
 static struct ac97_mixer_value_list mixer_defaults[] = {
     { SOUND_MIXER_VOLUME,  { { 85, 85 } } },
     { SOUND_MIXER_SPEAKER, { { 100 } } },
@@ -783,6 +951,8 @@
     { -1,                  {  { 0,  0 } } }
 };
 
+
+/* Installs the AC97 mixer into CARD.  */
 static int
 nm256_install_mixer (struct nm256_info *card)
 {
@@ -812,36 +982,67 @@
     return 0;
 }
 
-/* See if the signature left by the NM256 BIOS is intact; if so, we use
-   the associated address as the end of our buffer. */
+/* Perform a full reset on the hardware; this is invoked when an APM
+   resume event occurs.  */
+static void
+nm256_full_reset (struct nm256_info *card)
+{
+    nm256_initHw (card);
+    ac97_reset (&(card->mdev));
+}
+
+/* 
+ * See if the signature left by the NM256 BIOS is intact; if so, we use
+ * the associated address as the end of our audio buffer in the video
+ * RAM.
+ */
+
 static void
-nm256_peek_for_sig (struct nm256_info *card, u32 port1addr)
+nm256_peek_for_sig (struct nm256_info *card)
 {
-    char *temp = ioremap_nocache (port1addr + card->port1_end - 0x0400, 16);
+    u32 port1offset 
+	= card->port[0].physaddr + card->port[0].end_offset - 0x0400;
+    /* The signature is located 1K below the end of video RAM.  */
+    char *temp = ioremap_nocache (port1offset, 16);
+    /* Default buffer end is 5120 bytes below the top of RAM.  */
+    u32 default_value = card->port[0].end_offset - 0x1400;
     u32 sig;
 
+    /* Install the default value first, so we don't have to repeatedly
+       do it if there is a problem.  */
+    card->port[0].end_offset = default_value;
+
     if (temp == NULL) {
 	printk (KERN_ERR "NM256: Unable to scan for card signature in video RAM\n");
 	return;
     }
-    memcpy_fromio (&sig, temp, sizeof (u32));
-    if ((sig & 0xffff0000) == 0x4e4d0000) {
-	memcpy_fromio (&(card->bufend), temp + 4, sizeof (u32));
+    sig = readl (temp);
+    if ((sig & NM_SIG_MASK) == NM_SIGNATURE) {
+	u32 pointer = readl (temp + 4);
+
+	/*
+	 * If it's obviously invalid, don't use it (the port already has a
+	 * suitable default value set).
+	 */
+	if (pointer != 0xffffffff)
+	    card->port[0].end_offset = pointer;
+
 	printk (KERN_INFO "NM256: Found card signature in video RAM: 0x%x\n",
-		card->bufend);
+		pointer);
     }
 
     release_region ((unsigned long) temp, 16);
 }
 
-/* Install a driver for the soundcard referenced by PCIDEV. */
+/* 
+ * Install a driver for the PCI device referenced by PCIDEV.
+ * VERSTR is a human-readable version string.
+ */
 
 static int
 nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
 {
     struct nm256_info *card;
-    u32 port1addr = pcidev->resource[0].start;
-    u32 port2addr = pcidev->resource[1].start;
     int x;
 
     card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL);
@@ -855,52 +1056,85 @@
     card->recording = 0;
     card->rev = rev;
 
-    /* The NM256 has two memory ports.  The first port is nothing
-       more than a chunk of video RAM, which is used as the I/O ring
-       buffer.  The second port has the actual juicy stuff (like the
-       mixer and the playback engine control registers). */
-
-    card->ports[1] = ioremap_nocache (port2addr, NM_PORT2_SIZE);
+    /* Init the memory port info.  */
+    for (x = 0; x < 2; x++) {
+	card->port[x].physaddr = RSRCADDRESS (pcidev, x);
+	card->port[x].ptr = NULL;
+	card->port[x].start_offset = 0;
+	card->port[x].end_offset = 0;
+    }
 
-    if (card->ports[1] == NULL) {
-	printk (KERN_ERR "NM256: Unable to remap port 2\n");
+    /* Port 2 is easy.  */
+    card->port[1].start_offset = 0;
+    card->port[1].end_offset = NM_PORT2_SIZE;
+
+    /* Yuck.  But we have to map in port 2 so we can check how much RAM the
+       card has.  */
+    if (nm256_remap_ports (card)) {
 	kfree_s (card, sizeof (struct nm256_info));
 	return 0;
     }
 
+    /* 
+     * The NM256 has two memory ports.  The first port is nothing
+     * more than a chunk of video RAM, which is used as the I/O ring
+     * buffer.  The second port has the actual juicy stuff (like the
+     * mixer and the playback engine control registers).
+     */
+
     if (card->rev == REV_NM256AV) {
-	card->port1_end = 2560 * 1024;
+	/* Ok, try to see if this is a non-AC97 version of the hardware. */
+	int pval = nm256_readPort16 (card, 2, NM_MIXER_PRESENCE);
+	if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
+	    if (! force_load) {
+		printk (KERN_ERR "NM256: This doesn't look to me like the AC97-compatible version.\n");
+		printk (KERN_ERR "       You can force the driver to load by passing in the module\n");
+		printk (KERN_ERR "       parameter:\n");
+		printk (KERN_ERR "              force_ac97 = 1\n");
+		printk (KERN_ERR "\n");
+		printk (KERN_ERR "       More likely, you should be using the appropriate SB-16 or\n");
+		printk (KERN_ERR "       CS4232 driver instead.  (If your BIOS has settings for\n");
+		printk (KERN_ERR "       IRQ and/or DMA for the sound card, this is *not* the correct\n");
+		printk (KERN_ERR "       driver to use.)\n");
+		nm256_release_ports (card);
+		kfree_s (card, sizeof (struct nm256_info));
+		return 0;
+	    }
+	    else {
+		printk (KERN_INFO "NM256: Forcing driver load as per user request.\n");
+	    }
+	}
+	else {
+	 /*   printk (KERN_INFO "NM256: Congratulations. You're not running Eunice.\n")*/;
+	}
+	card->port[0].end_offset = 2560 * 1024;
 	card->introutine = nm256_interrupt;
+	card->mixer_status_offset = NM_MIXER_STATUS_OFFSET;
+	card->mixer_status_mask = NM_MIXER_READY_MASK;
     } 
     else {
+	/* Not sure if there is any relevant detect for the ZX or not.  */
 	if (nm256_readPort8 (card, 2, 0xa0b) != 0)
-	    card->port1_end = 6144 * 1024;
+	    card->port[0].end_offset = 6144 * 1024;
 	else
-	    card->port1_end = 4096 * 1024;
+	    card->port[0].end_offset = 4096 * 1024;
 
 	card->introutine = nm256_interrupt_zx;
+	card->mixer_status_offset = NM2_MIXER_STATUS_OFFSET;
+	card->mixer_status_mask = NM2_MIXER_READY_MASK;
     }
 
-    /* Default value. */
-    card->bufend = card->port1_end - 0x1400;
-
-    if (buffertop >= 98304 && buffertop < card->port1_end)
-	card->bufend = buffertop;
+    if (buffertop >= 98304 && buffertop < card->port[0].end_offset)
+	card->port[0].end_offset = buffertop;
     else
-	nm256_peek_for_sig (card, port1addr);
+	nm256_peek_for_sig (card);
 
-    card->port1_start = card->bufend - 98304;
+    card->port[0].start_offset = card->port[0].end_offset - 98304;
 
     printk (KERN_INFO "NM256: Mapping port 1 from 0x%x - 0x%x\n",
-	    card->port1_start, card->port1_end);
+	    card->port[0].start_offset, card->port[0].end_offset);
 
-    card->ports[0] =
-	ioremap_nocache (port1addr + card->port1_start,
-			 card->port1_end - card->port1_start);
-
-    if (card->ports[0] == NULL) {
-	printk (KERN_ERR "NM256: Unable to remap port 1\n");
-	release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+    if (nm256_remap_ports (card)) {
 	kfree_s (card, sizeof (struct nm256_info));
 	return 0;
     }
@@ -911,9 +1145,7 @@
     card->has_irq = 0;
 
     if (nm256_grabInterrupt (card) != 0) {
-	release_region ((unsigned long) card->ports[0], 
-			card->port1_end - card->port1_start);
-	release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+	nm256_release_ports (card);
 	kfree_s (card, sizeof (struct nm256_info));
 	return 0;
     }
@@ -924,10 +1156,36 @@
      *	Init the board.
      */
 
+    card->playbackBufferSize = 16384;
+    card->recordBufferSize = 16384;
+
+    card->coeffBuf = card->port[0].end_offset - NM_MAX_COEFFICIENT;
+    card->abuf2 = card->coeffBuf - card->recordBufferSize;
+    card->abuf1 = card->abuf2 - card->playbackBufferSize;
+    card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4);
+
+    /* Fixed setting. */
+    card->mixer = NM_MIXER_OFFSET;
+    card->mixer_values_init = 0;
+
+    card->is_open_play = 0;
+    card->is_open_record = 0;
+
+    card->coeffsCurrent = 0;
+
+    card->opencnt[0] = 0; card->opencnt[1] = 0;
+
+    /* Reasonable default settings, but largely unnecessary. */
+    for (x = 0; x < 2; x++) {
+	card->sinfo[x].bits = 8;
+	card->sinfo[x].stereo = 0;
+	card->sinfo[x].samplerate = 8000;
+    }
+
     nm256_initHw (card);
 
     for (x = 0; x < 2; x++) {
-	if ((card->dev[x] = 
+	if ((card->dev[x] =
 	     sound_install_audiodrv(AUDIO_DRIVER_VERSION,
 				    "NM256", &nm256_audio_driver,
 				    sizeof(struct audio_driver),
@@ -940,9 +1198,7 @@
 	}
 	else {
 	    printk(KERN_ERR "NM256: Too many PCM devices available\n");
-	    release_region ((unsigned long) card->ports[0], 
-			    card->port1_end - card->port1_start);
-	    release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+	    nm256_release_ports (card);
 	    kfree_s (card, sizeof (struct nm256_info));
 	    return 0;
 	}
@@ -964,6 +1220,48 @@
     return 1;
 }
 
+
+#ifdef CONFIG_APM
+/*
+ * APM event handler, so the card is properly reinitialized after a power
+ * event.
+ */
+static int
+handle_apm_event (apm_event_t event)
+{
+    static int down = 0;
+
+    switch (event)
+	{
+	case APM_SYS_SUSPEND:
+	case APM_USER_SUSPEND:
+	    down++;
+	    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);
+			}
+		}
+	    break;
+	}
+    return 0;
+}
+#endif
+
 /*
  * 	This loop walks the PCI configuration database and finds where
  *	the sound cards are.
@@ -993,6 +1291,10 @@
     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;
 }
@@ -1028,10 +1330,13 @@
     if (! ((mode & OPEN_READ) || (mode & OPEN_WRITE)))
 	return -EIO;
 
-    /* If it's open for both read and write, and the card's currently
-       being read or written to, then do the opposite of what has
-       already been done.  Otherwise, don't specify any mode until the
-       user actually tries to do I/O. */
+    /*
+     * If it's open for both read and write, and the card's currently
+     * being read or written to, then do the opposite of what has
+     * already been done.  Otherwise, don't specify any mode until the
+     * user actually tries to do I/O.  (Some programs open the device
+     * for both read and write, but only actually do reading or writing.)
+     */
 
     if ((mode & OPEN_WRITE) && (mode & OPEN_READ)) {
 	if (card->is_open_play)
@@ -1105,6 +1410,7 @@
     }
 }
 
+/* Standard ioctl handler. */
 static int
 nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
@@ -1122,6 +1428,11 @@
     else
 	w = 1;
 
+    /* 
+     * The code here is messy.  There are probably better ways to do
+     * it.  (It should be possible to handle it the same way the AC97 mixer 
+     * is done.)
+     */
     switch (cmd)
 	{
 	case SOUND_PCM_WRITE_RATE:
@@ -1193,8 +1504,12 @@
     return put_user(ret, (int *) arg);
 }
 
-/* Given the dev DEV and an associated physical buffer PHYSBUF, return
-   a pointer to the actual buffer in kernel space. */
+/*
+ * Given the sound device DEV and an associated physical buffer PHYSBUF, 
+ * return a pointer to the actual buffer in kernel space. 
+ *
+ * This routine should exist as part of the soundcore routines.
+ */
 
 static char *
 nm256_getDMAbuffer (int dev, unsigned long physbuf)
@@ -1238,9 +1553,10 @@
     }
 }
 
+/* Ditto, but do recording instead.  */
 static void
 nm256_audio_start_input(int dev, unsigned long physbuf, int count,
-			  int intrflag)
+			int intrflag)
 {
     struct nm256_info *card = nm256_find_card (dev);
 
@@ -1252,6 +1568,12 @@
     }
 }
 
+/* 
+ * Prepare for inputting samples to DEV. 
+ * Each requested buffer will be BSIZE byes long, with a total of
+ * BCOUNT buffers. 
+ */
+
 static int
 nm256_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
@@ -1278,6 +1600,7 @@
  *  2. We get a write buffer without dma_mode setup     (dmabuf.c:1152)
  *  3. We restart a transfer                            (dmabuf.c:1324)
  */
+
 static int
 nm256_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
@@ -1342,12 +1665,13 @@
 MODULE_PARM (usecache, "i");
 MODULE_PARM (buffertop, "i");
 MODULE_PARM (nm256_debug, "i");
+MODULE_PARM (force_load, "i");
 
 int
 init_module (void)
 {
     nmcard_list = NULL;
-    printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.0\n");
+    printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1\n");
 
     if (init_nm256 () == 0) {
 	SOUND_LOCK;
@@ -1372,9 +1696,7 @@
 	    stopRecord (card);
 	    if (card->has_irq)
 		free_irq (card->irq, card);
-	    release_region ((unsigned long) card->ports[0], 
-			    card->port1_end - card->port1_start);
-	    release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+	    nm256_release_ports (card);
 	    sound_unload_mixerdev (card->mixer_oss_dev);
 	    sound_unload_audiodev (card->dev[0]);
 	    sound_unload_audiodev (card->dev[1]);
@@ -1383,6 +1705,9 @@
 	}
 	nmcard_list = NULL;
     }
+#ifdef CONFIG_APM
+    apm_unregister_callback (&handle_apm_event);
+#endif
 }
 #endif
 
diff -u --recursive --new-file v2.3.23/linux/drivers/sound/nm256_coeff.h linux/drivers/sound/nm256_coeff.h
--- v2.3.23/linux/drivers/sound/nm256_coeff.h	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/nm256_coeff.h	Mon Oct 25 08:26:52 1999
@@ -4622,7 +4622,8 @@
 }
 
 static void
-nm256_loadOneCoefficient (struct nm256_info *card, u32 port, u16 which)
+nm256_loadOneCoefficient (struct nm256_info *card, int devnum, u32 port, 
+			  u16 which)
 {
     u32 coeffBuf = (which < 8) ? card->coeffBuf : card->allCoeffBuf;
     u16 offset = nm256_getStartOffset (which);
@@ -4631,11 +4632,14 @@
     card->coeffsCurrent = 0;
 
     if (nm256_debug)
-	printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d\n",
-		coeffBuf, coeffBuf + size - 1, which);
+	printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d, size %d, port 0x%x\n",
+		coeffBuf, coeffBuf + size - 1, which, size, port);
     nm256_writeBuffer8 (card, coefficients + offset, 1, coeffBuf, size);
     nm256_writePort32 (card, 2, port + 0, coeffBuf);
-    nm256_writePort32 (card, 2, port + 4, coeffBuf + size - 1);
+    /* ???  Record seems to behave differently than playback.  */
+    if (devnum == 0)
+	size--;
+    nm256_writePort32 (card, 2, port + 4, coeffBuf + size);
 }
 
 static void
@@ -4663,7 +4667,7 @@
 	number += 8;
 
     if (! nm256_cachedCoefficients (card))
-	nm256_loadOneCoefficient (card, addrs[which], number);
+	nm256_loadOneCoefficient (card, which, addrs[which], number);
     else {
 	u32 base = card->allCoeffBuf;
 	u32 offset = nm256_getStartOffset (number);
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.23/linux/drivers/usb/acm.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/usb/acm.c	Mon Oct 25 10:35:28 1999
@@ -486,8 +486,8 @@
 	if (!acm->present)
 		return;
 
-	printk("disconnecting\n");
-	
+	acm->active=0;
+	acm->present=0;
 	if (acm->writing){
 		usb_terminate_bulk(acm->dev, acm->writetransfer);
 		acm->writing=0;
@@ -498,8 +498,6 @@
 	}
 	usb_release_irq(acm->dev,acm->ctrltransfer, acm->ctrlpipe);
 	//BUG: What to do if a device is open?? Notify process or not allow cleanup?
-	acm->active=0;
-	acm->present=0;
 	kfree(acm->writebuffer);
 	kfree(acm->readbuffer);
 
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c
--- v2.3.23/linux/drivers/usb/cpia.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/usb/cpia.c	Mon Oct 25 08:26:53 1999
@@ -52,7 +52,7 @@
 			ptep = pte_offset(pmd, adr);
 			pte = *ptep;
 			if (pte_present(pte))
-				ret = (pte_page(pte) | (adr & (PAGE_SIZE-1)));
+				ret = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
 		}
 	}
 	MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/ezusb.c linux/drivers/usb/ezusb.c
--- v2.3.23/linux/drivers/usb/ezusb.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/usb/ezusb.c	Mon Oct 25 10:35:14 1999
@@ -1073,11 +1073,8 @@
 
 #ifdef MODULE
 
-int minor = 192;
-
 int init_module(void)
 {
-	ezusb_misc.minor = minor;
 	return ezusb_init();
 }
 
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.23/linux/drivers/usb/hub.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/hub.c	Tue Oct 26 10:22:22 1999
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
+#include <asm/byteorder.h>
 
 #include "usb.h"
 #include "hub.h"
@@ -51,16 +52,16 @@
 
 static int usb_get_hub_status(struct usb_device *dev, void *data)
 {
-	/* FIXME: Don't hardcode 4 */
 	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, 4, HZ);
+		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
+		data, sizeof(struct usb_hub_status), HZ);
 }
 
 static int usb_get_port_status(struct usb_device *dev, int port, void *data)
 {
-	/* FIXME: Don't hardcode 4 */
 	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, 4, HZ);
+		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
+		data, sizeof(struct usb_hub_status), HZ);
 }
 
 /*
@@ -101,6 +102,7 @@
 	unsigned char buffer[4], *bitmap;
 	struct usb_hub_descriptor *descriptor;
 	struct usb_descriptor_header *header;
+	struct usb_hub_status *hubsts;
 	int i;
 
 	/* Set it to the first configuration */
@@ -121,7 +123,7 @@
 	descriptor = (struct usb_hub_descriptor *)bitmap;
 
 	hub->nports = dev->maxchild = descriptor->bNbrPorts;
-	printk(KERN_INFO "hub: %d-port%s detected\n", hub->nports,
+	printk(KERN_INFO "hub: %d port%s detected\n", hub->nports,
 		(hub->nports == 1) ? "" : "s");
 
 	switch (descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
@@ -144,14 +146,14 @@
 
 	switch (descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
 		case 0x00:
-			printk(KERN_INFO "hub: global over current protection\n");
+			printk(KERN_INFO "hub: global over-current protection\n");
 			break;
 		case 0x08:
-			printk(KERN_INFO "hub: individual port over current protection\n");
+			printk(KERN_INFO "hub: individual port over-current protection\n");
 			break;
 		case 0x10:
 		case 0x18:
-			printk(KERN_INFO "hub: no over current protection\n");
+			printk(KERN_INFO "hub: no over-current protection\n");
                         break;
 	}
 
@@ -171,11 +173,12 @@
 	if (usb_get_hub_status(dev, buffer))
 		return -1;
 
+	hubsts = (struct usb_hub_status *)buffer;
 	printk(KERN_INFO "hub: local power source is %s\n",
-		(buffer[0] & 1) ? "lost (inactive)" : "good");
+		(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
 
-	printk(KERN_INFO "hub: %sover current condition exists\n",
-		(buffer[0] & 2) ? "" : "no ");
+	printk(KERN_INFO "hub: %sover-current condition exists\n",
+		(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no ");
 
 	/* Enable power to the ports */
 	printk(KERN_INFO "hub: enabling power on all ports\n");
@@ -292,7 +295,7 @@
 static void usb_hub_port_connect_change(struct usb_device *hub, int port)
 {
 	struct usb_device *usb;
-	unsigned char buf[4];
+	struct usb_port_status portsts;
 	unsigned short portstatus, portchange;
 
 	/* Disconnect anything that may have been there */
@@ -304,13 +307,13 @@
 	wait_ms(50);	/* FIXME: This is from the *BSD stack, thanks! :) */
 
 	/* Check status */
-	if (usb_get_port_status(hub, port + 1, buf)) {
+	if (usb_get_port_status(hub, port + 1, &portsts)) {
 		printk(KERN_ERR "get_port_status failed\n");
 		return;
 	}
 
-	portstatus = le16_to_cpup((unsigned short *)buf + 0);
-	portchange = le16_to_cpup((unsigned short *)buf + 1);
+	portstatus = le16_to_cpu(portsts.wPortStatus);
+	portchange = le16_to_cpu(portsts.wPortChange);
 
 	/* If it's not in CONNECT and ENABLE state, we're done */
 	if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
@@ -373,16 +376,16 @@
 		spin_unlock_irqrestore(&hub_event_lock, flags);
 
 		for (i = 0; i < hub->nports; i++) {
-			unsigned char buf[4];
+			struct usb_port_status portsts;
 			unsigned short portstatus, portchange;
 
-			if (usb_get_port_status(dev, i + 1, buf)) {
+			if (usb_get_port_status(dev, i + 1, &portsts)) {
 				printk(KERN_ERR "get_port_status failed\n");
 				continue;
 			}
 
-			portstatus = le16_to_cpup((unsigned short *)buf + 0);
-			portchange = le16_to_cpup((unsigned short *)buf + 1);
+			portstatus = le16_to_cpu(portsts.wPortStatus);
+			portchange = le16_to_cpu(portsts.wPortChange);
 
 			if (portchange & USB_PORT_STAT_C_CONNECTION) {
 				printk(KERN_INFO "hub: port %d connection change\n",
@@ -415,9 +418,8 @@
 				usb_clear_port_feature(dev, i + 1,
 					USB_PORT_FEAT_C_RESET);
 			}
-
-		}
-        }
+		} /* end for i */
+        } /* end while (1) */
 
 he_unlock:
 	spin_unlock_irqrestore(&hub_event_lock, flags);
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/hub.h linux/drivers/usb/hub.h
--- v2.3.23/linux/drivers/usb/hub.h	Fri Sep 10 23:57:36 1999
+++ linux/drivers/usb/hub.h	Tue Oct 26 10:22:22 1999
@@ -4,7 +4,7 @@
 #include <linux/list.h>
 
 /*
- * Hub feature numbers
+ * Hub Class feature numbers
  */
 #define C_HUB_LOCAL_POWER	0
 #define C_HUB_OVER_CURRENT	1
@@ -25,7 +25,12 @@
 #define USB_PORT_FEAT_C_OVER_CURRENT	19
 #define USB_PORT_FEAT_C_RESET		20
 
-/* wPortStatus */
+struct usb_port_status {
+	__u16 wPortStatus;
+	__u16 wPortChange;	
+} __attribute__ ((packed));
+
+/* wPortStatus bits */
 #define USB_PORT_STAT_CONNECTION	0x0001
 #define USB_PORT_STAT_ENABLE		0x0002
 #define USB_PORT_STAT_SUSPEND		0x0004
@@ -34,7 +39,7 @@
 #define USB_PORT_STAT_POWER		0x0100
 #define USB_PORT_STAT_LOW_SPEED		0x0200
 
-/* wPortChange */
+/* wPortChange bits */
 #define USB_PORT_STAT_C_CONNECTION	0x0001
 #define USB_PORT_STAT_C_ENABLE		0x0002
 #define USB_PORT_STAT_C_SUSPEND		0x0004
@@ -46,6 +51,20 @@
 #define HUB_CHAR_COMPOUND	0x0004
 #define HUB_CHAR_OCPM		0x0018
 
+struct usb_hub_status {
+	__u16 wHubStatus;
+	__u16 wHubChange;
+} __attribute__ ((packed));
+
+/*
+ *Hub Status & Hub Change bit masks
+ */
+#define HUB_STATUS_LOCAL_POWER	0x0001
+#define HUB_STATUS_OVERCURRENT	0x0002
+
+#define HUB_CHANGE_LOCAL_POWER	0x0001
+#define HUB_CHANGE_OVERCURRENT	0x0002
+
 /* Hub descriptor */
 struct usb_hub_descriptor {
 	__u8  bLength;
@@ -103,4 +122,3 @@
 };
 
 #endif
-
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
--- v2.3.23/linux/drivers/usb/ohci-hcd.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/usb/ohci-hcd.c	Wed Oct 27 14:04:25 1999
@@ -14,9 +14,8 @@
  * [ Open Host Controller Interface driver for USB. ]
  * [ (C) Copyright 1999 Linus Torvalds (uhci.c) ]
  * [ (C) Copyright 1999 Gregory P. Smith <greg@electricrain.com> ]
- * [ _Log: ohci-hcd.c,v _
- * [ Revision 1.1  1999/04/05 08:32:30  greg ]
  * 
+ * v4.3 1999/10/27 multiple HCs, bulk_request
  * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
  * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
  * v4.0 1999/08/18 
@@ -48,6 +47,7 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
+#include <linux/list.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -61,6 +61,7 @@
 static int handle_apm_event(apm_event_t event);
 static int apm_resume = 0;
 #endif
+static LIST_HEAD(ohci_hcd_list);
 
 static int ohci_link_ed(struct ohci * ohci, struct usb_ohci_ed *ed);
 static int sohci_kill_isoc (struct usb_isoc_desc *id);
@@ -85,10 +86,11 @@
  **** Interface functions
  ***********************************************/
  
-static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
 {  
+	struct usb_ohci_ed *ed = td->ed;
 	if(lw0 != NULL) {
-		if(USB_ST_CRC < 0 && (status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR)) 
+		if(0 < 0 && (status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR)) 
 			((struct ohci_state * )lw0)->status = data_len;
 		else
 			((struct ohci_state * )lw0)->status = status;
@@ -107,9 +109,9 @@
     return 0;                       
 }
   
-static int sohci_int_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+static int sohci_int_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
 {
-
+	struct usb_ohci_ed *ed = td->ed;
 	struct ohci * ohci = ohci_in; 
 	usb_device_irq handler=(void *) lw0;
 	void *dev_id = (void *) lw1;
@@ -127,9 +129,30 @@
 	return 0;
 }
 
-static int sohci_iso_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) {
+static int sohci_ret_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+{
+	struct usb_ohci_ed *ed = td->ed;
+	struct ohci * ohci = ohci_in; 
+	usb_device_irq handler=(void *) lw0;
+	void *dev_id = (void *) lw1;
+	int ret;
+
+	OHCI_DEBUG({ int i; printk("USB HC RET <<<: %x: data(%d):", ed->hwINFO, data_len);)
+	OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+	OHCI_DEBUG( printk(" ret_status: %x\n", status); })
+ 
+	ret = handler(status, data, data_len, dev_id);
+	if(ret == 0) return 0; /* 0 .. do not requeue  */
+	if(status > 0) return -1; /* error occured do not requeue ? */
+	ohci_trans_req(ohci, ed, 0, NULL, data, dlen, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, td->type & 0x7, sohci_ret_handler); /* requeue int request */
+ 
+	return 0;
+}
+
+static int sohci_iso_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) {
 
 	// struct ohci * ohci = ohci_in; 
+	struct usb_ohci_ed *ed = td->ed;
 	unsigned int ix = (unsigned int) lw0;
 	struct usb_isoc_desc * id = (struct usb_isoc_desc *) lw1;
 	struct usb_ohci_td **tdp = id->td;
@@ -311,7 +334,7 @@
 	
 	OHCI_DEBUG( printk("USB HC BULK_RQ>>>: %x \n", ed->hwINFO);) 
 	
-	ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_int_handler);
+	ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_ret_handler);
 	if (ED_STATE(ed) != ED_OPER)  ohci_link_ed(ohci, ed);
 
 	return ed;   
@@ -482,7 +505,7 @@
 	struct usb_ohci_ed	*ed = NULL;
 	struct usb_ohci_td	**td = id->td;
 	int i;
-printk("KILL_ISOC***:\n");	
+ 
 	for (i = 0; i < id->frame_count; i++) {
 		if(td[i]) {
 			td[i]->type |= DEL;
@@ -490,22 +513,17 @@
 		}
 	} 
 	if(ed) usb_ohci_rm_ep(id->usb_dev, ed, NULL, NULL, NULL, TD_RM);
-printk(": end KILL_ISOC***: %p\n", ed);		
+ 	
 	id->start_frame = -1;
 	return 0;
 }
 
 
 static void sohci_free_isoc(struct usb_isoc_desc *id) {
-printk("FREE_ISOC***\n");
-wait_ms(2000);
+
 	if(id->start_frame >= 0) sohci_kill_isoc(id);
-printk("FREE_ISOC2***\n");
-wait_ms(2000);
 	kfree(id->td);
 	kfree(id);
-printk("FREE_ISOC3***\n");
-wait_ms(2000);
 }
 
 struct usb_operations sohci_device_operations = {
@@ -772,17 +790,14 @@
 
    	// struct ohci * ohci = usb_dev->bus->hcpriv;
 	struct usb_ohci_td * td;  
-	struct usb_ohci_ed * ed, *ed1; 
+	struct usb_ohci_ed * ed; 
 	 
- 	int ed_state, ed_state1;
+ 	int ed_state;
  
 	spin_lock(&usb_ed_lock);
 
 	ed = ohci_find_ep(usb_dev, hcd_ed); 
 
-	 
-	ed1 = ((void *) ed) + 0x40; ed_state1 = ED_STATE(ed1);
-OHCI_DEBUG(printk("++++ USB HC add 60 ed1 %x: %x :state: %x\n", ed1->hwINFO, (unsigned int ) ed1, ed_state1); )
 	ed_state = ED_STATE(ed); /* store state of ed */
 	OHCI_DEBUG(printk("USB HC add ed %x: %x :state: %x\n", ed->hwINFO, (unsigned int ) ed, ed_state); )
 	if (ed_state == ED_NEW) {
@@ -1139,7 +1154,8 @@
   	struct usb_ohci_td      * td_list_next = NULL;
 
 	int cc;
-	int i;
+	int i; 
+	int dlen = 0;
  
   	while(td_list) {
    		td_list_next = td_list->next_dl_td;
@@ -1156,8 +1172,9 @@
  			}
  			else {
  				if(td_list->hwBE != 0) {
+ 					dlen = (bus_to_virt(td_list->hwBE) - td_list->buffer_start + 1);
  					if(td_list->hwCBP == 0)
-  			    		td_list->ed->len += (bus_to_virt(td_list->hwBE) - td_list->buffer_start + 1);
+  			    		td_list->ed->len += dlen;
   					else
   			    		td_list->ed->len += (bus_to_virt(td_list->hwCBP) - td_list->buffer_start);
   			    }
@@ -1170,9 +1187,10 @@
  		
   		if((td_list->type & SEND) && (ED_STATE(td_list->ed) != ED_STOP) && (td_list->handler)) {  /*  send the reply  */	
   			td_list->handler((void *) ohci,
-						td_list->ed,				  
+						td_list,				  
 						td_list->ed->buffer_start, 
 						td_list->ed->len,
+						dlen,
 						cc,
 						td_list->lw0,
 						td_list->lw1); 
@@ -1227,7 +1245,7 @@
 		udelay(1);
 	}	 
 }
-static struct ohci *__ohci;
+
 
 /*
  * Start an OHCI controller, set the BUS operational
@@ -1353,7 +1371,7 @@
 	ohci->irq = -1;
 	ohci->regs = mem_base;   
 	ohci->hc_area = hc_area;
-	__ohci = ohci;
+
 	/*
 	 * for load ballancing of the interrupt branches 
 	 */
@@ -1395,7 +1413,7 @@
     /* disconnect all devices */    
 	if(ohci->bus->root_hub) usb_disconnect(&ohci->bus->root_hub);
 	
-	reset_hc(__ohci);
+	reset_hc(ohci);
 	writel(OHCI_USB_RESET, &ohci->regs->control);
 	wait_ms(10);
 	
@@ -1428,6 +1446,9 @@
 		return -ENOMEM;
 	}
 	
+	INIT_LIST_HEAD(&ohci->ohci_hcd_list);
+	list_add(&ohci->ohci_hcd_list, &ohci_hcd_list);
+	
 	reset_hc(ohci);
 	writel(OHCI_USB_RESET, &ohci->regs->control);
 	wait_ms(10);
@@ -1438,6 +1459,7 @@
 		start_hc(ohci);
 		return 0;
  	}	
+ 	printk(KERN_ERR "USB HC (ohci-hcd): request interrupt %d failed\n", irq);
 	release_ohci(ohci);
 	return -EBUSY;
 }
@@ -1445,7 +1467,8 @@
 static int start_ohci(struct pci_dev *dev)
 {
 	unsigned int mem_base = dev->resource[0].start;
-	 
+	
+	pci_set_master(dev);
 	mem_base = (unsigned int) ioremap_nocache(mem_base, 4096);
 
 	if (!mem_base) {
@@ -1488,17 +1511,18 @@
  
 int ohci_hcd_init(void)
 {
+	int ret = -ENODEV;
 	struct pci_dev *dev = NULL;
  
 	while((dev = pci_find_class(PCI_CLASS_SERIAL_USB_OHCI, dev))) { 
-		if (start_ohci(dev) < 0) return -ENODEV;
+		if (start_ohci(dev) >= 0) ret = 0;
 	}
     
 #ifdef CONFIG_APM
 	apm_register_callback(&handle_apm_event);
 #endif
   
-    return 0;
+    return ret;
 }
 
 #ifdef MODULE
@@ -1509,10 +1533,17 @@
 
 void cleanup_module(void)
 {	
+	struct ohci *ohci;
+	
 #	ifdef CONFIG_APM
 	apm_unregister_callback(&handle_apm_event);
 #	endif
-	release_ohci(__ohci);
+	while(!list_empty(&ohci_hcd_list)) {
+		ohci = list_entry(ohci_hcd_list.next, struct ohci, ohci_hcd_list);
+		list_del(ohci->ohci_hcd_list);
+		INIT_LIST_HEAD(ohci->ohci_hcd_list);
+		release_ohci(ohci);
+	}		
 }
 #endif //MODULE
 
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/ohci-hcd.h linux/drivers/usb/ohci-hcd.h
--- v2.3.23/linux/drivers/usb/ohci-hcd.h	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/ohci-hcd.h	Wed Oct 27 14:04:25 1999
@@ -48,10 +48,11 @@
 #include <linux/list.h>
 #include <asm/io.h>
 struct usb_ohci_ed;
+struct usb_ohci_td;
 /* for ED and TD structures */
 
 typedef void * __OHCI_BAG;
-typedef int (*f_handler )(void * ohci, struct usb_ohci_ed *ed, void *data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1);
+typedef int (*f_handler )(void * ohci, struct usb_ohci_td *td, void *data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1);
 
  
  
@@ -309,7 +310,9 @@
 	int irq;
 	struct ohci_regs *regs;					/* OHCI controller's memory */	
 	struct ohci_hc_area *hc_area;			/* hcca, int ed-tree, ohci itself .. */                
-                             
+
+    struct list_head ohci_hcd_list;         /* list of all ohci_hcd */           
+
 	int ohci_int_load[32];                  /* load of the 32 Interrupt Chains (for load ballancing)*/     
 	struct usb_ohci_ed * ed_rm_list;        /* list of all endpoints to be removed */
 	struct usb_ohci_ed * ed_bulktail;       /* last endpoint of bulk list */
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.23/linux/drivers/usb/uhci.c	Fri Oct 22 13:21:51 1999
+++ linux/drivers/usb/uhci.c	Mon Oct 25 10:35:28 1999
@@ -154,7 +154,10 @@
 			actlength = uhci_actual_length(tmp->status);
 			if (rval)
 				*rval += actlength;
-			if (explength != actlength) {
+			/* This check is bogus, at least for acm. It
+                           always expects 64, but gets as many bytes
+                           as available (typically 1) -- pavel */
+			if (0 && (explength != actlength)) {
 				/* Reset the data toggle on error. */
 				if (debug || uhci_debug)
 					printk(KERN_DEBUG "Set toggle from %p rval %ld%c for status=%x to %d, exp=%d, act=%d\n",
diff -u --recursive --new-file v2.3.23/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.23/linux/drivers/usb/usb-serial.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/usb/usb-serial.c	Tue Oct 26 10:26:13 1999
@@ -11,6 +11,9 @@
  * vendor and device ids for that device.
  *
  * 
+ * version 0.1.2 (10/25/99) gkh
+ *  Fixed bug in detecting device.
+ *
  * version 0.1.1 (10/05/99) gkh
  *  Changed the major number to not conflict with anything else.
  *
@@ -528,7 +531,7 @@
 			serial->interrupt_in_interval = endpoint->bInterval;
 			/* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
 			serial->interrupt_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL);
-			if (!serial->bulk_in_buffer) {
+			if (!serial->interrupt_in_buffer) {
 				printk("USB Serial: Couldn't allocate interrupt_in_buffer\n");
 				goto probe_error;
 			}
diff -u --recursive --new-file v2.3.23/linux/fs/Config.in linux/fs/Config.in
--- v2.3.23/linux/fs/Config.in	Fri Oct 15 15:25:14 1999
+++ linux/fs/Config.in	Mon Oct 25 11:06:29 1999
@@ -59,11 +59,11 @@
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
 tristate 'Second extended fs support' CONFIG_EXT2_FS
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
-if [ "$CONFIG_SYSV_FS" != "n" -a "$CONFIG_EXPERIMENTAL" ]; then
+if [ "$CONFIG_SYSV_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE
 fi
 tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
-if [ "$CONFIG_UFS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" ]; then
+if [ "$CONFIG_UFS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  UFS filesystem write support (DANGEROUS)' CONFIG_UFS_FS_WRITE
 fi
 
@@ -79,11 +79,9 @@
    if [ "$CONFIG_NFS_FS" = "y" -a "$CONFIG_IP_PNP" = "y" ]; then
       bool '  Root file system on NFS' CONFIG_ROOT_NFS
    fi
-   if [ "$CONFIG_EXPERIMENTAL" ]; then
-      tristate 'NFS server support (EXPERIMENTAL)' CONFIG_NFSD
-      if [ "$CONFIG_NFSD" != "n" ]; then
-	 bool '  Emulate SUN NFS server' CONFIG_NFSD_SUN
-      fi
+   tristate 'NFS server support' CONFIG_NFSD
+   if [ "$CONFIG_NFSD" != "n" ]; then
+      bool '  Emulate SUN NFS server' CONFIG_NFSD_SUN
    fi
    if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
       define_bool CONFIG_SUNRPC y
diff -u --recursive --new-file v2.3.23/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.23/linux/fs/buffer.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/buffer.c	Tue Oct 26 15:08:40 1999
@@ -751,9 +751,6 @@
 	if (test_and_clear_bit(PG_decr_after, &page->flags))
 		atomic_dec(&nr_async_pages);
 
-	if (page->owner != (void *)-1)
-		PAGE_BUG(page);
-	page->owner = current;
 	UnlockPage(page);
 
 	return;
@@ -1181,8 +1178,6 @@
 
 	if (!PageLocked(page))
 		BUG();
-	if (page->owner != current)
-		PAGE_BUG(page);
 	/*
 	 * Allocate async buffer heads pointing to this page, just for I/O.
 	 * They don't show up in the buffer hash table, but they *are*
@@ -1297,15 +1292,16 @@
 
 static void unmap_underlying_metadata(struct buffer_head * bh)
 {
+#if 0
 	bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
-	if (bh)
-	{
+	if (bh) {
 		unmap_buffer(bh);
 		/* Here we could run brelse or bforget. We use
 		   bforget because it will try to put the buffer
 		   in the freelist. */
 		__bforget(bh);
 	}
+#endif
 }
 
 /*
@@ -1947,7 +1943,6 @@
 	}
 	if (!page->buffers)
 		BUG();
-	page->owner = (void *)-1;
 
 	head = page->buffers;
 	bh = head;
@@ -1989,7 +1984,6 @@
 	} else {
 		if (!nr && rw == READ) {
 			SetPageUptodate(page);
-			page->owner = current;
 			UnlockPage(page);
 		}
 		if (nr && (rw == WRITE))
@@ -2023,7 +2017,6 @@
 
 	blocks = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
 	iblock = page->offset >> inode->i_sb->s_blocksize_bits;
-	page->owner = (void *)-1;
 	bh = head;
 	nr = 0;
 
@@ -2057,7 +2050,6 @@
 		 * uptodate as well.
 		 */
 		SetPageUptodate(page);
-		page->owner = current;
 		UnlockPage(page);
 	}
 	return 0;
@@ -2201,11 +2193,13 @@
 
 void show_buffers(void)
 {
+#ifdef __SMP__
 	struct buffer_head * bh;
 	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" };
+#endif
 
 	printk("Buffer memory:   %6dkB\n",
 			atomic_read(&buffermem_pages) << (PAGE_SHIFT-10));
diff -u --recursive --new-file v2.3.23/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.3.23/linux/fs/ext2/inode.c	Tue Sep  7 12:14:07 1999
+++ linux/fs/ext2/inode.c	Mon Oct 25 10:40:19 1999
@@ -668,6 +668,16 @@
 	inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
 	inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
 	inode->u.ext2_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
+	/* We now have enough fields to check if the inode was active or not.
+	 * This is needed because nfsd might try to access dead inodes
+	 * the test is that same one that e2fsck uses
+	 * NeilBrown 1999oct15
+	 */
+	if (inode->i_nlink == 0 && (inode->i_mode == 0 || inode->u.ext2_i.i_dtime)) {
+		/* this inode is deleted */
+		brelse (bh);
+		goto bad_inode;
+	}
 	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
 	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
 	inode->i_version = ++event;
diff -u --recursive --new-file v2.3.23/linux/fs/fat/Makefile linux/fs/fat/Makefile
--- v2.3.23/linux/fs/fat/Makefile	Wed Jun 24 14:30:09 1998
+++ linux/fs/fat/Makefile	Tue Oct 26 11:21:31 1999
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
 O_TARGET := fat.o
-O_OBJS   := buffer.o cache.o dir.o file.o inode.o misc.o mmap.o tables.o cvf.o
+O_OBJS   := buffer.o cache.o dir.o file.o inode.o misc.o tables.o cvf.o
 OX_OBJS  := fatfs_syms.o
 M_OBJS   := $(O_TARGET)
 
diff -u --recursive --new-file v2.3.23/linux/fs/fat/fatfs_syms.c linux/fs/fat/fatfs_syms.c
--- v2.3.23/linux/fs/fat/fatfs_syms.c	Mon Aug  9 11:43:49 1999
+++ linux/fs/fat/fatfs_syms.c	Tue Oct 26 11:21:46 1999
@@ -33,7 +33,6 @@
 EXPORT_SYMBOL(fat__get_entry);
 EXPORT_SYMBOL(fat_lock_creation);
 EXPORT_SYMBOL(fat_mark_buffer_dirty);
-EXPORT_SYMBOL(fat_mmap);
 EXPORT_SYMBOL(fat_notify_change);
 EXPORT_SYMBOL(fat_parent_ino);
 EXPORT_SYMBOL(fat_put_super);
@@ -54,7 +53,6 @@
 EXPORT_SYMBOL(lock_fat);
 EXPORT_SYMBOL(unlock_fat);
 EXPORT_SYMBOL(fat_dir_ioctl);
-EXPORT_SYMBOL(fat_readpage);
 EXPORT_SYMBOL(fat_add_entries);
 EXPORT_SYMBOL(fat_dir_empty);
 
diff -u --recursive --new-file v2.3.23/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.3.23/linux/fs/fat/file.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/fat/file.c	Tue Oct 26 11:22:30 1999
@@ -115,13 +115,13 @@
 	struct inode *inode = dentry->d_inode;
 	struct page *new_page, **hash;
 	unsigned long pgpos;
-	unsigned long page_cache = 0;
+	struct page *page_cache = NULL;
 	long status;
 
 	pgpos = MSDOS_I(inode)->i_realsize & PAGE_CACHE_MASK;
 	while (pgpos < page->offset) {
-		hash = page_hash(inode, pgpos);
-repeat_find:	new_page = __find_lock_page(inode, pgpos, hash);
+		hash = page_hash(&inode->i_data, pgpos);
+repeat_find:	new_page = __find_lock_page(&inode->i_data, pgpos, hash);
 		if (!new_page) {
 			if (!page_cache) {
 				page_cache = page_cache_alloc();
@@ -130,10 +130,10 @@
 				status = -ENOMEM;
 				goto out;
 			}
-			new_page = page_cache_entry(page_cache);
-			if (add_to_page_cache_unique(new_page,inode,pgpos,hash))
+			new_page = page_cache;
+			if (add_to_page_cache_unique(new_page,&inode->i_data,pgpos,hash))
 				goto repeat_find;
-			page_cache = 0;
+			page_cache = NULL;
 		}
 		status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
 		UnlockPage(new_page);
diff -u --recursive --new-file v2.3.23/linux/fs/fat/mmap.c linux/fs/fat/mmap.c
--- v2.3.23/linux/fs/fat/mmap.c	Fri Jul  2 15:15:51 1999
+++ linux/fs/fat/mmap.c	Wed Dec 31 16:00:00 1969
@@ -1,131 +0,0 @@
-/*
- *	linux/fs/fat/mmap.c
- *
- *	Written by Jacques Gelinas (jacques@solucorp.qc.ca)
- *	Inspired by fs/nfs/mmap.c (Jon Tombs 15 Aug 1993)
- *
- *	mmap handling for fat-based filesystems
- */
-
-#define ASC_LINUX_VERSION(V, P, S)	(((V) * 65536) + ((P) * 256) + (S))
-#include <linux/version.h>
-
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/shm.h>
-#include <linux/errno.h>
-#include <linux/mman.h>
-#include <linux/string.h>
-#include <linux/malloc.h>
-#include <linux/msdos_fs.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/*
- * Fill in the supplied page for mmap
- */
-static unsigned long fat_file_mmap_nopage(
-	struct vm_area_struct * area,
-	unsigned long address,
-	int error_code)
-{
-	struct inode * inode = area->vm_file->f_dentry->d_inode;
-	unsigned long page;
-	unsigned int clear;
-	int pos;
-	long gap;	/* distance from eof to pos */
-
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return page;
-	address &= PAGE_MASK;
-	pos = address - area->vm_start + area->vm_offset;
-
-	clear = 0;
-	gap = inode->i_size - pos;
-	if (gap <= 0){
-		/* mmaping beyond end of file */
-		clear = PAGE_SIZE;
-	}else{
-		int cur_read;
-		int need_read;
-		struct file filp;
-		if (gap < PAGE_SIZE){
-			clear = PAGE_SIZE - gap;
-		}
-		filp.f_reada = 0;
-		filp.f_pos = pos;
-		filp.f_dentry=area->vm_file->f_dentry;
-		need_read = PAGE_SIZE - clear;
-		{
-			mm_segment_t cur_fs = get_fs();
-			set_fs (KERNEL_DS);
-			cur_read = fat_file_read (&filp, (char*)page,
-						  need_read, &filp.f_pos);
-			set_fs (cur_fs);
-		}
-		if (cur_read != need_read){
-			printk ("MSDOS: Error while reading an mmap file %d <> %d\n"
-				,cur_read,need_read);
-		}
-	}
-	if (clear > 0){
-		memset ((char*)page+PAGE_SIZE-clear,0,clear);
-	}
-	return page;
-}
-
-struct vm_operations_struct fat_file_mmap = {
-	NULL,			/* open */
-	NULL,			/* close */
-	NULL,			/* unmap */
-	NULL,			/* protect */
-	NULL,			/* sync */
-	NULL,			/* advise */
-	fat_file_mmap_nopage,	/* nopage */
-	NULL,			/* wppage */
-	NULL			/* swapout */
-};
-
-/*
- * This is used for a general mmap of an msdos file
- * Returns 0 if ok, or a negative error code if not.
- */
-int fat_mmap(struct file * file, struct vm_area_struct * vma)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	if (MSDOS_SB(inode->i_sb)->cvf_format &&
-	    MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap)
-		return MSDOS_SB(inode->i_sb)->cvf_format->cvf_mmap(file,vma);
-
-	if (vma->vm_flags & VM_SHARED)	/* only PAGE_COW or read-only supported now */
-		return -EINVAL;
-	if (vma->vm_offset & (inode->i_sb->s_blocksize - 1))
-		return -EINVAL;
-	if (!inode->i_sb || !S_ISREG(inode->i_mode))
-		return -EACCES;
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-		mark_inode_dirty(inode);
-	}
-
-	vma->vm_ops = &fat_file_mmap;
-	return 0;
-}
-
-
-int fat_readpage(struct file *file, struct page * page)
-{
-	struct dentry * dentry = file->f_dentry;
-	struct inode * inode = dentry->d_inode;
-	if (MSDOS_SB(inode->i_sb)->cvf_format &&
-	    MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage)
-		return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page);
-	    
-	printk("fat_readpage called with no handler (shouldn't happen)\n");
-	return -1;
-}
-
diff -u --recursive --new-file v2.3.23/linux/fs/hpfs/file.c linux/fs/hpfs/file.c
--- v2.3.23/linux/fs/hpfs/file.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/hpfs/file.c	Tue Oct 26 11:23:31 1999
@@ -91,7 +91,7 @@
 	struct inode *inode = dentry->d_inode;
 	struct page *new_page, **hash;
 	unsigned long pgpos;
-	unsigned long page_cache = 0;
+	struct page * page_cache = NULL;
 	long status;
 
 	printk("- off: %08x\n", (int)page->offset);
@@ -99,8 +99,8 @@
 	while (pgpos < page->offset) {
 long pgp = pgpos;
 		printk("pgpos: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks);
-		hash = page_hash(inode, pgpos);
-repeat_find:	new_page = __find_lock_page(inode, pgpos, hash);
+		hash = page_hash(&inode->i_data, pgpos);
+repeat_find:	new_page = __find_lock_page(&inode->i_data, pgpos, hash);
 		if (!new_page) {
 			if (!page_cache) {
 				page_cache = page_cache_alloc();
@@ -109,10 +109,10 @@
 				status = -ENOMEM;
 				goto out;
 			}
-			new_page = page_cache_entry(page_cache);
-			if (add_to_page_cache_unique(new_page,inode,pgpos,hash))
+			new_page = page_cache;
+			if (add_to_page_cache_unique(new_page,&inode->i_data,pgpos,hash))
 				goto repeat_find;
-			page_cache = 0;
+			page_cache = NULL;
 		}
 		printk("A\n");
 		status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
diff -u --recursive --new-file v2.3.23/linux/fs/inode.c linux/fs/inode.c
--- v2.3.23/linux/fs/inode.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/inode.c	Tue Oct 26 10:41:06 1999
@@ -89,7 +89,7 @@
 		memset(inode, 0, sizeof(*inode));
 		init_waitqueue_head(&inode->i_wait);
 		INIT_LIST_HEAD(&inode->i_hash);
-		INIT_LIST_HEAD(&inode->i_pages);
+		INIT_LIST_HEAD(&inode->i_data.pages);
 		INIT_LIST_HEAD(&inode->i_dentry);
 		sema_init(&inode->i_sem, 1);
 		spin_lock_init(&inode->i_shared_lock);
@@ -247,7 +247,7 @@
  */
 void clear_inode(struct inode *inode)
 {
-	if (inode->i_nrpages)
+	if (inode->i_data.nrpages)
 		BUG();
 	if (!(inode->i_state & I_FREEING))
 		BUG();
@@ -274,7 +274,7 @@
 		list_del(inode_entry);
 
 		inode = list_entry(inode_entry, struct inode, i_list);
-		if (inode->i_nrpages)
+		if (inode->i_data.nrpages)
 			truncate_inode_pages(inode, 0);
 		clear_inode(inode);
 		destroy_inode(inode);
@@ -351,7 +351,7 @@
  *      dispose_list.
  */
 #define CAN_UNUSE(inode) \
-	(((inode)->i_state | (inode)->i_nrpages) == 0)
+	(((inode)->i_state | (inode)->i_data.nrpages) == 0)
 #define INODE(entry)	(list_entry(entry, struct inode, i_list))
 
 void prune_icache(int goal)
@@ -658,7 +658,7 @@
 				if (op && op->delete_inode) {
 					void (*delete)(struct inode *) = op->delete_inode;
 					spin_unlock(&inode_lock);
-					if (inode->i_nrpages)
+					if (inode->i_data.nrpages)
 						truncate_inode_pages(inode, 0);
 					delete(inode);
 					spin_lock(&inode_lock);
diff -u --recursive --new-file v2.3.23/linux/fs/lockd/clntproc.c linux/fs/lockd/clntproc.c
--- v2.3.23/linux/fs/lockd/clntproc.c	Wed Feb 17 09:44:33 1999
+++ linux/fs/lockd/clntproc.c	Mon Oct 25 22:21:09 1999
@@ -69,6 +69,7 @@
 	call->a_args.lock    = *lock;
 	call->a_args.lock.caller = system_utsname.nodename;
 
+	init_waitqueue_head(&lock->fl.fl_wait);
 	/* set default data area */
 	call->a_args.lock.oh.data = call->a_owner;
 
diff -u --recursive --new-file v2.3.23/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.3.23/linux/fs/ncpfs/dir.c	Mon Oct 11 15:38:15 1999
+++ linux/fs/ncpfs/dir.c	Tue Oct 26 10:41:06 1999
@@ -576,9 +576,9 @@
 #endif
 
 	/* cache using inspired by smbfs and nfs */
-	hash = page_hash(dir, 0);
+	hash = page_hash(&dir->i_data, 0);
 
-	page = __find_lock_page(dir, 0, hash);
+	page = __find_lock_page(&dir->i_data, 0, hash);
 
 	if (!page) {
 		unsigned long page_cache;
@@ -586,7 +586,7 @@
 		page_cache = page_cache_alloc();
 		if (page_cache) {
 			page = page_cache_entry(page_cache);
-			if (add_to_page_cache_unique(page, dir, 0, hash)) {
+			if (add_to_page_cache_unique(page, &dir->i_data, 0, hash)) {
 				page_cache_release(page);
 				page = NULL;
 				page_cache_free(page_cache);
diff -u --recursive --new-file v2.3.23/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.3.23/linux/fs/nfs/dir.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/nfs/dir.c	Tue Oct 26 10:41:06 1999
@@ -255,7 +255,7 @@
 again:
 	cur_off = 0;
 	for (;;) {
-		page = find_get_page(inode, cur_off);
+		page = find_get_page(&inode->i_data, cur_off);
 		if (page) {
 			if (!Page_Uptodate(page))
 				goto out_error;
@@ -332,16 +332,16 @@
 		goto out;
 	}
 
-	hash = page_hash(inode, offset);
+	hash = page_hash(&inode->i_data, offset);
 repeat:
-	page = __find_lock_page(inode, offset, hash);
+	page = __find_lock_page(&inode->i_data, offset, hash);
 	if (page) {
 		page_cache_free(page_cache);
 		goto unlock_out;
 	}
 
 	page = page_cache;
-	if (add_to_page_cache_unique(page, inode, offset, hash)) {
+	if (add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
 		page_cache_release(page);
 		goto repeat;
 	}
@@ -431,8 +431,8 @@
 	if ((offset = nfs_readdir_offset(inode, filp->f_pos)) < 0)
 		goto no_dirent_page;
 
-	hash = page_hash(inode, offset);
-	page = __find_get_page(inode, offset, hash);
+	hash = page_hash(&inode->i_data, offset);
+	page = __find_get_page(&inode->i_data, offset, hash);
 	if (!page)
 		goto no_dirent_page;
 	if (!Page_Uptodate(page))
diff -u --recursive --new-file v2.3.23/linux/fs/nfs/read.c linux/fs/nfs/read.c
--- v2.3.23/linux/fs/nfs/read.c	Mon Jul 19 12:29:29 1999
+++ linux/fs/nfs/read.c	Tue Oct 26 11:19:45 1999
@@ -152,7 +152,6 @@
 		fail++;
 		dprintk("NFS: %d successful reads, %d failures\n", succ, fail);
 	}
-	page->owner = current; // HACK, FIXME, will go away.
 	UnlockPage(page);
 	free_page(address);
 
diff -u --recursive --new-file v2.3.23/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v2.3.23/linux/fs/nfs/symlink.c	Fri Oct 22 13:21:52 1999
+++ linux/fs/nfs/symlink.c	Tue Oct 26 10:41:06 1999
@@ -66,16 +66,16 @@
 	if (!page_cache)
 		goto out;
 
-	hash = page_hash(inode, 0);
+	hash = page_hash(&inode->i_data, 0);
 repeat:
-	page = __find_lock_page(inode, 0, hash);
+	page = __find_lock_page(&inode->i_data, 0, hash);
 	if (page) {
 		page_cache_free(page_cache);
 		goto unlock_out;
 	}
 
 	page = page_cache;
-	if (add_to_page_cache_unique(page, inode, 0, hash)) {
+	if (add_to_page_cache_unique(page, &inode->i_data, 0, hash)) {
 		page_cache_release(page);
 		goto repeat;
 	}
@@ -107,7 +107,7 @@
 	u32 *p, len;
 
 	/* Caller revalidated the directory inode already. */
-	page = find_get_page(inode, 0);
+	page = find_get_page(&inode->i_data, 0);
 	if (!page)
 		goto no_readlink_page;
 	if (!Page_Uptodate(page))
@@ -142,7 +142,7 @@
 	u32 *p;
 
 	/* Caller revalidated the directory inode already. */
-	page = find_get_page(inode, 0);
+	page = find_get_page(&inode->i_data, 0);
 	if (!page)
 		goto no_followlink_page;
 	if (!Page_Uptodate(page))
diff -u --recursive --new-file v2.3.23/linux/fs/nfsd/export.c linux/fs/nfsd/export.c
--- v2.3.23/linux/fs/nfsd/export.c	Fri Oct 15 15:25:14 1999
+++ linux/fs/nfsd/export.c	Mon Oct 25 10:40:19 1999
@@ -365,16 +365,6 @@
 				exp->ex_parent = unexp->ex_parent;
 	}
 
-	/*
-	 * Check whether this is the last export for this device,
-	 * and if so flush any cached dentries.
-	 */
-	if (!exp_device_in_use(unexp->ex_dev)) {
-printk("exp_do_unexport: %s last use, flushing cache\n",
-	kdevname(unexp->ex_dev));
-		nfsd_fh_flush(unexp->ex_dev);
-	}
-
 	dentry = unexp->ex_dentry;
 	inode = dentry->d_inode;
 	if (unexp->ex_dev != inode->i_dev || unexp->ex_ino != inode->i_ino)
@@ -628,6 +618,7 @@
 	{ NFSEXP_KERBEROS, { "kerberos", ""}},
 	{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
 	{ NFSEXP_CROSSMNT, {"nohide", ""}},
+	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
 	{ 0, {"", ""}}
 };
 
diff -u --recursive --new-file v2.3.23/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.3.23/linux/fs/nfsd/nfsctl.c	Mon Jul  5 20:35:18 1999
+++ linux/fs/nfsd/nfsctl.c	Mon Oct 25 10:40:19 1999
@@ -39,7 +39,6 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
-extern void nfsd_fh_init(void);
 extern long sys_call_table[];
 
 static int	nfsctl_svc(struct nfsctl_svc *data);
@@ -79,7 +78,6 @@
 	nfsd_cache_init();	/* RPC reply cache */
 	nfsd_export_init();	/* Exports table */
 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
-	nfsd_fh_init();		/* FH table */
 	proc_export_init();
 	initialized = 1;
 }
diff -u --recursive --new-file v2.3.23/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- v2.3.23/linux/fs/nfsd/nfsfh.c	Sat Oct  9 11:47:50 1999
+++ linux/fs/nfsd/nfsfh.c	Mon Oct 25 10:43:43 1999
@@ -4,6 +4,8 @@
  * NFS server file handle treatment.
  *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ * Portions Copyright (C) 1999 G. Allen Morris III <gam3@acm.org>
+ * Extensive cleanup by Neil Brown <neilb@cse.unsw.edu.au> Southern-Spring 1999
  */
 
 #include <linux/sched.h>
@@ -22,308 +24,48 @@
 #define NFSD_PARANOIA 1
 /* #define NFSD_DEBUG_VERBOSE 1 */
 
-extern unsigned long max_mapnr;
-
-#define NFSD_FILE_CACHE 0
-#define NFSD_DIR_CACHE  1
-struct fh_entry {
-	struct dentry * dentry;
-	unsigned long reftime;
-	ino_t	ino;
-	kdev_t	dev;
-};
-
-#define NFSD_MAXFH PAGE_SIZE/sizeof(struct fh_entry)
-static struct fh_entry filetable[NFSD_MAXFH];
-static struct fh_entry dirstable[NFSD_MAXFH];
 
 static int nfsd_nr_verified = 0;
 static int nfsd_nr_put = 0;
-static unsigned long nfsd_next_expire = 0;
-
-static int add_to_fhcache(struct dentry *, int);
-static int nfsd_d_validate(struct dentry *);
-struct dentry * lookup_inode(kdev_t, ino_t, ino_t);
-
-static LIST_HEAD(fixup_head);
-static LIST_HEAD(path_inuse);
-static int nfsd_nr_fixups = 0;
-static int nfsd_nr_paths = 0;
-#define NFSD_MAX_PATHS 500
-#define NFSD_MAX_FIXUPAGE 60*HZ
-
-struct nfsd_fixup {
-	struct list_head lru;
-	ino_t	dir;
-	ino_t	ino;
-	kdev_t	dev;
-	struct dentry *dentry;
-	unsigned long reftime;
-};
-
-struct nfsd_path {
-	struct list_head lru;
-	unsigned long reftime;
-	int	users;
-	ino_t	ino;
-	kdev_t	dev;
-	char	name[1];
-};
-
-static struct nfsd_fixup * find_cached_lookup(kdev_t dev, ino_t dir, ino_t ino)
-{
-	struct list_head *tmp = fixup_head.next;
-
-	for (; tmp != &fixup_head; tmp = tmp->next) {
-		struct nfsd_fixup *fp;
-
-		fp = list_entry(tmp, struct nfsd_fixup, lru);
-		if (fp->ino != ino)
-			continue;
-		if (fp->dir != dir)
-			continue;
-		if (fp->dev != dev)
-			continue;
-		list_del(tmp);
-		list_add(tmp, &fixup_head);
-		fp->reftime = jiffies;
-		return fp;
-	}
-	return NULL;
-}
-
-/*
- * Save the dentry pointer from a successful lookup.
- */
-static void add_to_lookup_cache(struct dentry *dentry, struct knfs_fh *fh)
-{
-	struct nfsd_fixup *fp;
-
-	fp = find_cached_lookup(u32_to_kdev_t(fh->fh_dev), 
-				u32_to_ino_t(fh->fh_dirino),
-				u32_to_ino_t(fh->fh_ino));
-	if (fp) {
-		fp->dentry = dentry;
-		return;
-	}
-
-	/*
-	 * Add a new entry. The small race here is unimportant:
-	 * if another task adds the same lookup, both entries
-	 * will be consistent.
-	 */
-	fp = kmalloc(sizeof(struct nfsd_fixup), GFP_KERNEL);
-	if (fp) {
-		fp->dir = u32_to_kdev_t(fh->fh_dirino);
-		fp->ino = u32_to_ino_t(fh->fh_ino);
-		fp->dev = u32_to_ino_t(fh->fh_dev);
-		fp->dentry = dentry;
-		fp->reftime = jiffies;
-		list_add(&fp->lru, &fixup_head);
-		nfsd_nr_fixups++;
-	}
-}
-
-static void free_fixup_entry(struct nfsd_fixup *fp)
-{
-	list_del(&fp->lru);
-	kfree(fp);
-	nfsd_nr_fixups--;
-}
-
-/*
- * Copy a dentry's path into the specified buffer.
- */
-static int copy_path(char *buffer, struct dentry *dentry, int namelen)
-{
-	char *p, *b = buffer;
-	int result = 0, totlen = 0, len; 
-
-	while (1) {
-		struct dentry *parent;
-		dentry = dentry->d_covers;
-		parent = dentry->d_parent;
-		len = dentry->d_name.len;
-		p = (char *) dentry->d_name.name + len;
-		totlen += len;
-		if (totlen > namelen)
-			goto out;
-		while (len--)
-			*b++ = *(--p);
-		if (dentry == parent)
-			break;
-		dentry = parent;
-		totlen++;
-		if (totlen > namelen)
-			goto out;
-		*b++ = '/';
-	}
-	*b = 0;
-
-	/*
-	 * Now reverse in place ...
-	 */
-	p = buffer;
-	while (p < b) {
-		char c = *(--b);
-		*b = *p;
-		*p++ = c;
-	} 
-	result = 1;
-out:
-	return result;
-}
-
-/*
- * Add a dentry's path to the path cache.
- */
-static int add_to_path_cache(struct dentry *dentry)
-{
-	struct inode *inode = dentry->d_inode;
-	struct dentry *this;
-	struct nfsd_path *new;
-	int len, result = 0;
-
-#ifdef NFSD_DEBUG_VERBOSE
-printk("add_to_path_cache: caching %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
-	/*
-	 * Get the length of the full pathname.
-	 */
-restart:
-	len = 0;
-	this = dentry;
-	while (1) {
-		struct dentry *parent;
-		this = this->d_covers;
-		parent = this->d_parent;
-		len += this->d_name.len;
-		if (this == parent)
-			break;
-		this = parent;
-		len++;
-	}
-	/*
-	 * Allocate a structure to hold the path.
-	 */
-	new = kmalloc(sizeof(struct nfsd_path) + len, GFP_KERNEL);
-	if (new) {
-		new->users = 0;	
-		new->reftime = jiffies;	
-		new->ino = inode->i_ino;	
-		new->dev = inode->i_dev;	
-		result = copy_path(new->name, dentry, len);	
-		if (!result)
-			goto retry;
-		list_add(&new->lru, &path_inuse);
-		nfsd_nr_paths++;
-#ifdef NFSD_DEBUG_VERBOSE
-printk("add_to_path_cache: added %s, paths=%d\n", new->name, nfsd_nr_paths);
-#endif
-	}
-	return result;
 
-	/*
-	 * If the dentry's path length changed, just try again.
-	 */
-retry:
-	kfree(new);
-	printk(KERN_DEBUG "add_to_path_cache: path length changed, retrying\n");
-	goto restart;
-}
-
-/*
- * Search for a path entry for the specified (dev, inode).
- */
-static struct nfsd_path *get_path_entry(kdev_t dev, ino_t ino)
-{
-	struct nfsd_path *pe;
-	struct list_head *tmp;
-
-	for (tmp = path_inuse.next; tmp != &path_inuse; tmp = tmp->next) {
-		pe = list_entry(tmp, struct nfsd_path, lru);
-		if (pe->ino != ino)
-			continue;
-		if (pe->dev != dev)
-			continue;
-		list_del(tmp);
-		list_add(tmp, &path_inuse);
-		pe->users++;
-		pe->reftime = jiffies;
-#ifdef NFSD_PARANOIA
-printk("get_path_entry: found %s for %s/%ld\n", pe->name, kdevname(dev), ino);
-#endif
-		return pe;
-	}
-	return NULL;
-}
-
-static void put_path(struct nfsd_path *pe)
-{
-	pe->users--;
-}
-
-static void free_path_entry(struct nfsd_path *pe)
-{
-	if (pe->users)
-		printk(KERN_DEBUG "free_path_entry: %s in use, users=%d\n",
-			pe->name, pe->users);
-	list_del(&pe->lru);
-	kfree(pe);
-	nfsd_nr_paths--;
-}
 
 struct nfsd_getdents_callback {
-	struct nfsd_dirent *dirent;
-	ino_t dirino;		/* parent inode number */
-	int found;		/* dirent inode matched? */
+	struct qstr *name;	/* name that was found. name->name already points to a buffer */
+	unsigned long ino;	/* the inum we are looking for */
+	int found;		/* inode matched? */
 	int sequence;		/* sequence counter */
 };
 
-struct nfsd_dirent {
-	ino_t ino;		/* preset to desired entry */
-	int len;
-	char name[256];
-};
-
 /*
- * A rather strange filldir function to capture the inode number
- * for the second entry (the parent inode) and the name matching
- * the specified inode number.
+ * A rather strange filldir function to capture
+ * the name matching the specified inode number.
  */
-static int filldir_one(void * __buf, const char * name, int len, 
+static int filldir_one(void * __buf, const char * name, int len,
 			off_t pos, ino_t ino)
 {
 	struct nfsd_getdents_callback *buf = __buf;
-	struct nfsd_dirent *dirent = buf->dirent;
+	struct qstr *qs = buf->name;
+	char *nbuf = (char*)qs->name; /* cast is to get rid of "const" */
 	int result = 0;
 
 	buf->sequence++;
 #ifdef NFSD_DEBUG_VERBOSE
-printk("filldir_one: seq=%d, ino=%ld, name=%s\n", buf->sequence, ino, name);
+dprintk("filldir_one: seq=%d, ino=%ld, name=%s\n", buf->sequence, ino, name);
 #endif
-	if (buf->sequence == 2) {
-		buf->dirino = ino;
-		goto out;
-	}
-	if (dirent->ino == ino) {
-		dirent->len = len;
-		memcpy(dirent->name, name, len);
-		dirent->name[len] = 0;
+	if (buf->ino == ino) {
+		qs->len = len;
+		memcpy(nbuf, name, len);
+		nbuf[len] = '\0';
 		buf->found = 1;
 		result = -1;
 	}
-out:
 	return result;
 }
 
 /*
- * Read a directory and return the parent inode number and the name
- * of the specified entry. The dirent must be initialized with the
- * inode number of the desired entry.
+ * Read a directory and return the name of the specified entry.
  */
-static int get_parent_ino(struct dentry *dentry, struct nfsd_dirent *dirent)
+static int get_ino_name(struct dentry *dentry, struct qstr *name, unsigned long ino)
 {
 	struct inode *dir = dentry->d_inode;
 	int error;
@@ -346,8 +88,8 @@
 	if (!file.f_op->readdir)
 		goto out_close;
 
-	buffer.dirent = dirent;
-	buffer.dirino = 0;
+	buffer.name = name;
+	buffer.ino = ino;
 	buffer.found = 0;
 	buffer.sequence = 0;
 	while (1) {
@@ -365,7 +107,6 @@
 		if (old_seq == buffer.sequence)
 			break;
 	}
-	dirent->ino = buffer.dirino;
 
 out_close:
 	if (file.f_op->release)
@@ -374,663 +115,245 @@
 	return error;
 }
 
-/*
- * Look up a dentry given inode and parent inode numbers.
- *
- * This relies on the ability of a Unix-like filesystem to return
- * the parent inode of a directory as the ".." (second) entry.
- *
- * This could be further optimized if we had an efficient way of
- * searching for a dentry given the inode: as we walk up the tree,
- * it's likely that a dentry exists before we reach the root.
+/* this should be provided by each filesystem in an nfsd_operations interface as
+ * iget isn't really the right interface
  */
-struct dentry * lookup_inode(kdev_t dev, ino_t dirino, ino_t ino)
+static inline struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32 generation)
 {
-	struct super_block *sb;
-	struct dentry *root, *dentry, *result;
-	struct inode *dir;
-	char *name;
-	unsigned long page;
-	ino_t root_ino;
-	int error;
-	struct nfsd_dirent dirent;
-
-	result = ERR_PTR(-ENOMEM);
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		goto out;
-
-	/*
-	 * Get the root dentry for the device.
-	 */
-	result = ERR_PTR(-ENOENT);
-	sb = get_super(dev);
-	if (!sb)
-		goto out_page;
-	result = ERR_PTR(-ENOSYS);
-	if (!sb->s_op->read_inode)	/* No working iget(), e.g. FAT */
-		goto out_page;
-	root = dget(sb->s_root);
-	root_ino = root->d_inode->i_ino; /* usually 2 */
 
-	name = (char *) page + PAGE_SIZE;
-	*(--name) = 0;
-
-	/*
-	 * Walk up the tree to construct the name string.
-	 * When we reach the root inode, look up the name
-	 * relative to the root dentry.
+	/* iget isn't really right if the inode is currently unallocated!!
+	 * This should really all be done inside each filesystem
+	 *
+	 * ext2fs' read_inode has been strengthed to return a bad_inode if the inode
+	 *   had been deleted.
+	 *
+	 * Currently we don't know the generation for parent directory, so a generation
+	 * of 0 means "accept any"
 	 */
-	while (1) {
-		if (ino == root_ino) {
-			if (*name == '/')
-				name++;
-			/*
-			 * Note: this dput()s the root dentry.
-			 */
-			result = lookup_dentry(name, root, 0);
-			break;
-		}
-
-		result = ERR_PTR(-ENOENT);
-		dir = iget(sb, dirino);
-		if (!dir)
-			goto out_root;
-		dentry = d_alloc_root(dir);
-		if (!dentry)
-			goto out_iput;
-
-		/*
-		 * Get the name for this inode and the next parent inode.
-		 */
-		dirent.ino = ino;
-		error = get_parent_ino(dentry, &dirent);
-		result = ERR_PTR(error);
-		dput(dentry);
-		if (error)
-			goto out_root;
-		/*
-		 * Prepend the name to the buffer.
-		 */
-		result = ERR_PTR(-ENAMETOOLONG);
-		name -= (dirent.len + 1);
-		if ((unsigned long) name <= page)
-			goto out_root;
-		memcpy(name + 1, dirent.name, dirent.len);
-		*name = '/';
-
-		/*
-		 * Make sure we can't get caught in a loop ...
-		 */
-		if (dirino == dirent.ino && dirino != root_ino) {
-			printk(KERN_DEBUG 
-			       "lookup_inode: looping?? (ino=%ld, path=%s)\n",
-				dirino, name);	
-			goto out_root;
-		}
-		ino = dirino;
-		dirino = dirent.ino;
+	struct inode *inode;
+	struct list_head *lp;
+	struct dentry *result;
+	inode = iget(sb, ino);
+	if (is_bad_inode(inode)
+	    || (generation && inode->i_generation != generation)
+		) {
+		/* we didn't find the right inode.. */
+		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
+			inode->i_ino,
+			inode->i_nlink, inode->i_count,
+			inode->i_generation,
+			generation);
+
+		iput(inode);
+		return NULL;
+	}
+	/* now to find a dentry.
+	 * If possible, get a well-connected one
+	 */
+	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
+		result = list_entry(lp,struct dentry, d_alias);
+		if (! IS_ROOT(result) || inode->i_sb->s_root == result) {
+			dget(result);
+			iput(inode);
+			return result;
+		}
+	}
+	result = d_alloc_root(inode);
+	if (result == NULL) {
+		iput(inode);
+		return ERR_PTR(-ENOMEM);
 	}
-
-out_page:
-	free_page(page);
-out:
+	d_rehash(result); /* so a dput won't loose it */
 	return result;
-
-	/*
-	 * Error exits ...
-	 */
-out_iput:
-	result = ERR_PTR(-ENOMEM);
-	iput(dir);
-out_root:
-	dput(root);
-	goto out;
-}
-
-/*
- * Find an entry in the cache matching the given dentry pointer.
- */
-static struct fh_entry *find_fhe(struct dentry *dentry, int cache,
-				struct fh_entry **empty)
-{
-	struct fh_entry *fhe;
-	int i, found = (empty == NULL) ? 1 : 0;
-
-	if (!dentry)
-		goto out;
-
-	fhe = (cache == NFSD_FILE_CACHE) ? &filetable[0] : &dirstable[0];
-	for (i = 0; i < NFSD_MAXFH; i++, fhe++) {
-		if (fhe->dentry == dentry) {
-			fhe->reftime = jiffies;
-			return fhe;
-		}
-		if (!found && !fhe->dentry) {
-			found = 1;
-			*empty = fhe;
-		}
-	}
-out:
-	return NULL;
-}
-
-/*
- * Expire a cache entry.
- */
-static void expire_fhe(struct fh_entry *empty, int cache)
-{
-	struct dentry *dentry = empty->dentry;
-
-#ifdef NFSD_DEBUG_VERBOSE
-printk("expire_fhe: expiring %s/%s, d_count=%d, ino=%ld\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count,empty->ino);
-#endif
-	empty->dentry = NULL;	/* no dentry */
-	/*
-	 * Add the parent to the dir cache before releasing the dentry,
-	 * and check whether to save a copy of the dentry's path.
-	 */
-	if (!IS_ROOT(dentry)) {
-		struct dentry *parent = dget(dentry->d_parent);
-		if (add_to_fhcache(parent, NFSD_DIR_CACHE))
-			nfsd_nr_verified++;
-		else
-			dput(parent);
-		/*
-		 * If we're expiring a directory, copy its path.
-		 */
-		if (cache == NFSD_DIR_CACHE) {
-			add_to_path_cache(dentry);
-		}
-	}
-	dput(dentry);
-	nfsd_nr_put++;
-}
-
-/*
- * Look for an empty slot, or select one to expire.
- */
-static void expire_slot(int cache)
-{
-	struct fh_entry *fhe, *empty = NULL;
-	unsigned long oldest = -1;
-	int i;
-
-	fhe = (cache == NFSD_FILE_CACHE) ? &filetable[0] : &dirstable[0];
-	for (i = 0; i < NFSD_MAXFH; i++, fhe++) {
-		if (!fhe->dentry)
-			goto out;
-		if (fhe->reftime < oldest) {
-			oldest = fhe->reftime;
-			empty = fhe;
-		}
-	}
-	if (empty)
-		expire_fhe(empty, cache);
-
-out:
-	return;
 }
 
-/*
- * Expire any cache entries older than a certain age.
+/* this routine links an IS_ROOT dentry into the dcache tree.  It gains "parent"
+ * as a parent and "name" as a name
+ * It should possibly go in dcache.c
  */
-static void expire_old(int cache, int age)
+int d_splice(struct dentry *target, struct dentry *parent, struct qstr *name)
 {
-	struct list_head *tmp;
-	struct fh_entry *fhe;
-	int i;
-
-#ifdef NFSD_DEBUG_VERBOSE
-printk("expire_old: expiring %s older than %d\n",
-(cache == NFSD_FILE_CACHE) ? "file" : "dir", age);
-#endif
-	fhe = (cache == NFSD_FILE_CACHE) ? &filetable[0] : &dirstable[0];
-	for (i = 0; i < NFSD_MAXFH; i++, fhe++) {
-		if (!fhe->dentry)
-			continue;
-		if ((jiffies - fhe->reftime) > age)
-			expire_fhe(fhe, cache);
-	}
-
-	/*
-	 * Remove old entries from the patch-up cache.
-	 */
-	while ((tmp = fixup_head.prev) != &fixup_head) {
-		struct nfsd_fixup *fp;
-		fp = list_entry(tmp, struct nfsd_fixup, lru);
-		if ((jiffies - fp->reftime) < NFSD_MAX_FIXUPAGE)
-			break;
-		free_fixup_entry(fp);
-	}
-
-	/*
-	 * Trim the path cache ...
-	 */
-	while (nfsd_nr_paths > NFSD_MAX_PATHS) {
-		struct nfsd_path *pe;
-		pe = list_entry(path_inuse.prev, struct nfsd_path, lru);
-		if (pe->users)
-			break;
-		free_path_entry(pe);
-	}
-}
-
-/*
- * Add a dentry to the file or dir cache.
- *
- * Note: As NFS file handles must have an inode, we don't accept
- * negative dentries.
- */
-static int add_to_fhcache(struct dentry *dentry, int cache)
-{
-	struct fh_entry *fhe, *empty = NULL;
-	struct inode *inode = dentry->d_inode;
-
-	if (!inode) {
+	struct dentry *tdentry;
 #ifdef NFSD_PARANOIA
-printk("add_to_fhcache: %s/%s rejected, no inode!\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
+	if (!IS_ROOT(target))
+		printk("nfsd: d_splice with no-root target: %s/%s\n", parent->d_name.name, name->name);
 #endif
-		return 0;
-	}
+	name->hash = full_name_hash(name->name, name->len);
+	tdentry = d_alloc(parent, name);
+	if (tdentry == NULL)
+		return -ENOMEM;
+	d_move(target, tdentry);
 
-repeat:
-	fhe = find_fhe(dentry, cache, &empty);
-	if (fhe) {
-		return 0;
-	}
-
-	/*
-	 * Not found ... make a new entry.
+	/* tdentry will have been made a "child" of target (the parent of target)
+	 * make it an IS_ROOT instead
 	 */
-	if (empty) {
-		empty->dentry = dentry;
-		empty->reftime = jiffies;
-		empty->ino = inode->i_ino;
-		empty->dev = inode->i_dev;
-		return 1;
-	}
-
-	expire_slot(cache);
-	goto repeat;
-}
-
-/*
- * Find an entry in the dir cache for the specified inode number.
- */
-static struct fh_entry *find_fhe_by_ino(kdev_t dev, ino_t ino)
-{
-	struct fh_entry * fhe = &dirstable[0];
-	int i;
-
-	for (i = 0; i < NFSD_MAXFH; i++, fhe++) {
-		if (fhe->ino == ino && fhe->dev == dev) {
-			fhe->reftime = jiffies;
-			return fhe;
-		}
-	}
-	return NULL;
+	list_del(&tdentry->d_child);
+	tdentry->d_parent = tdentry;
+	d_rehash(target);
+	dput(tdentry);
+	return 0;
 }
 
-/*
- * Find the (directory) dentry with the specified (dev, inode) number.
- * Note: this leaves the dentry in the cache.
+/* this routine finds the dentry of the parent of a given directory
+ * it should be in the filesystem accessed by nfsd_operations
+ * it assumes lookup("..") works.
  */
-static struct dentry *find_dentry_by_ino(kdev_t dev, ino_t ino)
+struct dentry *nfsd_findparent(struct dentry *child)
 {
-	struct fh_entry *fhe;
-	struct nfsd_path *pe;
-	struct dentry * dentry;
-
-#ifdef NFSD_DEBUG_VERBOSE
-printk("find_dentry_by_ino: looking for inode %ld\n", ino);
-#endif
-	/*
-	 * Special case: inode number 2 is the root inode,
-	 * so we can use the root dentry for the device.
-	 */
-	if (ino == 2) {
-		struct super_block *sb = get_super(dev);
-		if (sb) {
-#ifdef NFSD_PARANOIA
-printk("find_dentry_by_ino: getting root dentry for %s\n", kdevname(dev));
-#endif
-			if (sb->s_root) {
-				dentry = dget(sb->s_root);
-				goto out;
-			} else {
-#ifdef NFSD_PARANOIA
-				printk("find_dentry_by_ino: %s has no root??\n",
-					kdevname(dev));
-#endif
-			}
-		}
-	}
+	struct dentry *tdentry, *pdentry;
+	tdentry = d_alloc(child, &(const struct qstr) {"..", 2, 0});
+	if (!tdentry)
+		return ERR_PTR(-ENOMEM);
 
-	/*
-	 * Search the dentry cache ...
+	/* I'm going to assume that if the returned dentry is different, then
+	 * it is well connected.  But nobody returns different dentrys do they?
 	 */
-	fhe = find_fhe_by_ino(dev, ino);
-	if (fhe) {
-		dentry = dget(fhe->dentry);
-		goto out;
-	}
-	/*
-	 * Search the path cache ...
-	 */
-	dentry = NULL;
-	pe = get_path_entry(dev, ino);
-	if (pe) {
-		struct dentry *res;
-		res = lookup_dentry(pe->name, NULL, 0);
-		if (!IS_ERR(res)) {
-			struct inode *inode = res->d_inode;
-			if (inode && inode->i_ino == ino &&
-				     inode->i_dev == dev) {
-				dentry = res;
-#ifdef NFSD_PARANOIA
-printk("find_dentry_by_ino: found %s/%s, ino=%ld\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ino);
-#endif
-				if (add_to_fhcache(dentry, NFSD_DIR_CACHE)) {
-					dget(dentry);
-					nfsd_nr_verified++;
-				}
-			} else {
-				dput(res);
-			}
-		} else {
-#ifdef NFSD_PARANOIA
-printk("find_dentry_by_ino: %s lookup failed\n", pe->name);
-#endif
-		}
-		put_path(pe);
-	}
-out:
-	return dentry;
-}
-
-/*
- * Look for an entry in the file cache matching the dentry pointer,
- * and verify that the (dev, inode) numbers are correct. If found,
- * the entry is removed from the cache.
- */
-static struct dentry *find_dentry_in_fhcache(struct knfs_fh *fh)
-{
-	struct fh_entry * fhe;
-
-	fhe = find_fhe(fh->fh_dcookie, NFSD_FILE_CACHE, NULL);
-	if (fhe) {
-		struct dentry *parent, *dentry;
-		struct inode *inode;
-
-		dentry = fhe->dentry;
-		inode = dentry->d_inode;
-
-		if (!inode) {
-#ifdef NFSD_PARANOIA
-printk("find_dentry_in_fhcache: %s/%s has no inode!\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
-			goto out;
-		}
-		if (inode->i_ino != u32_to_ino_t(fh->fh_ino))
-			goto out;
- 		if (inode->i_dev != u32_to_kdev_t(fh->fh_dev))
-			goto out;
-
-		fhe->dentry = NULL;
-		fhe->ino = 0;
-		fhe->dev = 0;
-		nfsd_nr_put++;
-		/*
-		 * Make sure the parent is in the dir cache ...
+	pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
+	if (!pdentry) {
+		/* I don't want to return a ".." dentry.
+		 * I would prefer to return an unconnected "IS_ROOT" dentry,
+		 * though a properly connected dentry is even better
 		 */
-		parent = dget(dentry->d_parent);
-		if (add_to_fhcache(parent, NFSD_DIR_CACHE))
-			nfsd_nr_verified++;
-		else
-			dput(parent);
-		return dentry;
-	}
-out:
-	return NULL;
-}
-
-/*
- * Look for an entry in the parent directory with the specified
- * inode number.
- */
-static struct dentry *lookup_by_inode(struct dentry *parent, ino_t ino)
-{
-	struct dentry *dentry;
-	int error;
-	struct nfsd_dirent dirent;
-
-	/*
-	 * Search the directory for the inode number.
-	 */
-	dirent.ino = ino;
-	error = get_parent_ino(parent, &dirent);
-	if (error) {
-#ifdef NFSD_PARANOIA
-printk("lookup_by_inode: ino %ld not found in %s\n", ino, parent->d_name.name);
-#endif
-		goto no_entry;
-	}
-#ifdef NFSD_PARANOIA
-printk("lookup_by_inode: found %s\n", dirent.name);
-#endif
-
-	dentry = lookup_dentry(dirent.name, parent, 0);
-	if (!IS_ERR(dentry)) {
-		if (dentry->d_inode && dentry->d_inode->i_ino == ino)
-			goto out;
-#ifdef NFSD_PARANOIA
-printk("lookup_by_inode: %s/%s inode mismatch??\n",
-parent->d_name.name, dentry->d_name.name);
-#endif
-		dput(dentry);
-	} else {
-#ifdef NFSD_PARANOIA
-printk("lookup_by_inode: %s lookup failed, error=%ld\n",
-dirent.name, PTR_ERR(dentry));
-#endif
-	}
-
-no_entry:
-	dentry = NULL;
-out:
-	return dentry;
-
-}
-
-/*
- * Search the fix-up list for a dentry from a prior lookup.
- */
-static struct dentry *nfsd_cached_lookup(struct knfs_fh *fh)
-{
-	struct nfsd_fixup *fp;
-
-	fp = find_cached_lookup(u32_to_kdev_t(fh->fh_dev),
-				u32_to_ino_t(fh->fh_dirino),
-				u32_to_ino_t(fh->fh_ino));
-	if (fp)
-		return fp->dentry;
-	return NULL;
-}
-
-void
-expire_all(void)
-{
- 	if (time_after_eq(jiffies, nfsd_next_expire)) {
- 		expire_old(NFSD_FILE_CACHE,  5*HZ);
- 		expire_old(NFSD_DIR_CACHE , 60*HZ);
- 		nfsd_next_expire = jiffies + 5*HZ;
- 	}
-}
-
-/* 
- * Free cache after unlink/rmdir.
- */
-void
-expire_by_dentry(struct dentry *dentry)
-{
-	struct fh_entry *fhe;
-
-	fhe = find_fhe(dentry, NFSD_FILE_CACHE, NULL);
-	if (fhe) {
-		expire_fhe(fhe, NFSD_FILE_CACHE);
-	}
-	fhe = find_fhe(dentry, NFSD_DIR_CACHE, NULL);
-	if (fhe) {
-		expire_fhe(fhe, NFSD_DIR_CACHE);
-	}
+		/* if first or last of alias list is not tdentry, use that
+		 * else make a root dentry
+		 */
+		struct list_head *aliases = &tdentry->d_inode->i_dentry;
+		if (aliases->next != aliases) {
+			pdentry = list_entry(aliases->next, struct dentry, d_alias);
+			if (pdentry == tdentry)
+				pdentry = list_entry(aliases->prev, struct dentry, d_alias);
+			if (pdentry == tdentry)
+				pdentry = NULL;
+			if (pdentry) dget(pdentry);
+		}
+		if (pdentry == NULL) {
+			pdentry = d_alloc_root(igrab(tdentry->d_inode));
+			if (pdentry) d_rehash(pdentry);
+		}
+		if (pdentry == NULL)
+			pdentry = ERR_PTR(-ENOMEM);
+	}
+	dput(tdentry); /* it was never rehashed, it will be discarded */
+	return pdentry;
 }
 
 /*
- * The is the basic lookup mechanism for turning an NFS file handle 
- * into a dentry. There are several levels to the search:
- * (1) Look for the dentry pointer the short-term fhcache,
- *     and verify that it has the correct inode number.
- *
- * (2) Try to validate the dentry pointer in the file handle,
- *     and verify that it has the correct inode number. If this
- *     fails, check for a cached lookup in the fix-up list and
- *     repeat step (2) using the new dentry pointer.
- *
- * (3) Look up the dentry by using the inode and parent inode numbers
- *     to build the name string. This should succeed for any Unix-like
- *     filesystem.
- *
- * (4) Search for the parent dentry in the dir cache, and then
- *     look for the name matching the inode number.
- *
- * (5) The most general case ... search the whole volume for the inode.
- *
- * If successful, we return a dentry with the use count incremented.
- *
- * Note: steps (4) and (5) above are probably unnecessary now that (3)
- * is working. Remove the code once this is verified ...
+ * This is the basic lookup mechanism for turning an NFS file handle
+ * into a dentry.
+ * We use nfsd_iget and if that doesn't return a suitably connected dentry,
+ * we try to find the parent, and the parent of that and so-on until a
+ * connection if made.
  */
 static struct dentry *
-find_fh_dentry(struct knfs_fh *fh)
+find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
 {
-	struct dentry *dentry, *parent;
-	int looked_up = 0, retry = 0;
-
-	/*
-	 * Stage 1: Look for the dentry in the short-term fhcache.
-	 */
-	dentry = find_dentry_in_fhcache(fh);
-	if (dentry) {
-		nfsdstats.fh_cached++;
-		goto out;
-	}
-
-	/*
-	 * Stage 2: Attempt to validate the dentry in the file handle.
-	 */
-	dentry = fh->fh_dcookie;
-recheck:
-	if (nfsd_d_validate(dentry)) {
-		struct inode * dir = dentry->d_parent->d_inode;
-
-		if (dir->i_ino == u32_to_ino_t(fh->fh_dirino) && 
-		    dir->i_dev == u32_to_kdev_t(fh->fh_dev)) {
-			struct inode * inode = dentry->d_inode;
-			/*
-			 * NFS file handles must always have an inode,
-			 * so we won't accept a negative dentry.
-			 */
-			if (inode && inode->i_ino == u32_to_ino_t(fh->fh_ino)) {
-				dget(dentry);
-#ifdef NFSD_DEBUG_VERBOSE
-printk("find_fh_dentry: validated %s/%s, ino=%ld\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino);
-#endif
-				if (!retry)
-					nfsdstats.fh_valid++;
-				else {
-					nfsdstats.fh_fixup++;
-#ifdef NFSD_DEBUG_VERBOSE
-printk("find_fh_dentry: retried validation successful\n");
-#endif
-				}
-				goto out;
+	struct dentry *dentry, *result = NULL;
+	struct qstr qs;
+	char namebuf[256];
+	int  found =0;
+	u32 err;
+
+	qs.name = namebuf;
+	/*
+	 * Attempt to find the inode.
+	 */
+	result = nfsd_iget(sb, fh->fh_ino, fh->fh_generation);
+	err = PTR_ERR(result);
+	if (IS_ERR(result))
+		goto err_out;
+	err = -ESTALE;
+	if (!result) {
+		dprintk("find_fh_dentry: No inode found.\n");
+		goto err_out;
+	}
+	if (!IS_ROOT(result) || result->d_inode->i_sb->s_root ==result)
+		return result;
+
+	/* result is now a "root" dentry, which may be adequate as it stands, or else
+	 * will get spliced into the dcache tree */
+
+	if (!S_ISDIR(result->d_inode->i_mode) && ! needpath) {
+		return result;
+	}
+
+	/* It's a directory, or we are required to confirm the file's
+	 * location in the tree.
+	 */
+	found = 0;
+	if (!S_ISDIR(result->d_inode->i_mode)) {
+		if (fh->fh_dirino == 0)
+			goto err_result; /* don't know how to find parent */
+		else {
+			/* need to iget fh->fh_dirino and make sure this inode is in that directory */
+			dentry = nfsd_iget(sb, fh->fh_dirino, 0);
+			err = PTR_ERR(dentry);
+			if (IS_ERR(dentry))
+				goto err_result;
+			err = -ESTALE;
+			if (!dentry->d_inode
+			    || !S_ISDIR(dentry->d_inode->i_mode)) {
+				goto err_dentry;
 			}
+			if (!IS_ROOT(dentry) || dentry->d_inode->i_sb->s_root ==dentry)
+				found = 1;
+			err = get_ino_name(dentry, &qs, result->d_inode->i_ino);
+			if (err)
+				goto err_dentry;
+
+			/* OK, we have the name in parent of inode,  lets fill in the dentry */
+			err = d_splice(result, dentry, &qs);
+			if (err)
+				goto err_dentry;
+		}
+	}
+	else
+		dentry = dget(result);
+
+	while(!found) {
+		/* LOOP INVARIANT */
+		/* haven't found a place in the tree yet, but we do have a path
+		 * from dentry down to result, and dentry is a directory.
+		 * Have a hold on dentry and result */
+		struct dentry *pdentry;
+		struct inode *parent;
+
+		pdentry = nfsd_findparent(dentry);
+		err = PTR_ERR(pdentry);
+		if (IS_ERR(pdentry))
+			goto err_dentry;
+		parent = pdentry->d_inode;
+		err = -EACCES;
+		if (!parent) {
+			dput(pdentry);
+			goto err_dentry;
 		}
-	}
-
-	/*
-	 * Before proceeding to a lookup, check whether we cached a
-	 * prior lookup. If so, try to validate that dentry ...
-	 */
-	if (!retry && (dentry = nfsd_cached_lookup(fh)) != NULL) {
-		retry = 1;
-		goto recheck;
-	}
+		/* I'm not sure that this is the best test for
+		 *  "is it not a floating dentry?"
+		 */
+		if (!IS_ROOT(pdentry) || parent->i_sb->s_root == pdentry)
+			found = 1;
 
-	/*
-	 * Stage 3: Look up the dentry based on the inode and parent inode
-	 * numbers. This should work for all Unix-like filesystems.
-	 */
-	looked_up = 1;
-	dentry = lookup_inode(u32_to_kdev_t(fh->fh_dev),
-			      u32_to_ino_t(fh->fh_dirino),
-			      u32_to_ino_t(fh->fh_ino));
-	if (!IS_ERR(dentry)) {
-		struct inode * inode = dentry->d_inode;
-#ifdef NFSD_DEBUG_VERBOSE
-printk("find_fh_dentry: looked up %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
-		if (inode && inode->i_ino == u32_to_ino_t(fh->fh_ino)) {
-			nfsdstats.fh_lookup++;
-			goto out;
+		err = get_ino_name(pdentry, &qs, dentry->d_inode->i_ino);
+		if (err) {
+			dput(pdentry);
+			goto err_dentry;
 		}
-#ifdef NFSD_PARANOIA
-printk("find_fh_dentry: %s/%s lookup mismatch!\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
+		err = d_splice(dentry, pdentry, &qs);
+		dprintk("nfsd_fh: found name %s for ino %ld\n", dentry->d_name.name, dentry->d_inode->i_ino);
 		dput(dentry);
+		dentry = pdentry;
 	}
+	dput(dentry);
+	return result;
 
-	/*
-	 * Stage 4: Look for the parent dentry in the fhcache ...
-	 */
-	parent = find_dentry_by_ino(u32_to_kdev_t(fh->fh_dev),
-				    u32_to_ino_t(fh->fh_dirino));
-	if (parent) {
-		/*
-		 * ... then search for the inode in the parent directory.
-		 */
-		dentry = lookup_by_inode(dget(parent), u32_to_ino_t(fh->fh_ino));
-		dput(parent);
-		if (dentry)
-			goto out;
-	}
-
-	/*
-	 * Stage 5: Search the whole volume.
-	 */
-#ifdef NFSD_PARANOIA
-printk("find_fh_dentry: %s, %u/%u not found -- need full search!\n",
-kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_dirino, fh->fh_ino);
-#endif
-	dentry = NULL;
-	nfsdstats.fh_stale++;
-	
-out:
-	if (looked_up && dentry) {
-		add_to_lookup_cache(dentry, fh);
-	}
-
-	expire_all();
-
-	return dentry;
+err_dentry:
+	dput(dentry);
+err_result:
+	dput(result);
+err_out:
+	if (err == -ESTALE)
+		nfsdstats.fh_stale++;
+	return ERR_PTR(err);
 }
 
 /*
@@ -1038,6 +361,9 @@
  *
  * Note that the file handle dentry may need to be freed even after
  * an error return.
+ *
+ * This is only called at the start of an nfsproc call, so fhp points to
+ * a svc_fh which is all 0 except for the over-the-wire file handle.
  */
 u32
 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
@@ -1048,20 +374,36 @@
 	struct inode	*inode;
 	u32		error = 0;
 
-	dprintk("nfsd: fh_verify(exp %x/%u cookie %p)\n",
-		fh->fh_xdev, fh->fh_xino, fh->fh_dcookie);
+	dprintk("nfsd: fh_verify(exp %s/%u file (%s/%u dir %u)\n",
+		kdevname(fh->fh_xdev),
+		fh->fh_xino,
+		kdevname(fh->fh_dev),
+		fh->fh_ino,
+		fh->fh_dirino);
+
+	/*
+	 * Security: Check that the fh is internally consistant (from <gam3@acm.org>)
+	 */
+	if (fh->fh_dev != fh->fh_xdev) {
+		printk("fh_verify: Security: export on other device (%s, %s).\n",
+			kdevname(fh->fh_dev), kdevname(fh->fh_xdev));
+		error = nfserr_stale;
+		nfsdstats.fh_stale++;
+		goto out;
+	}
 
-	if (fhp->fh_dverified)
-		goto check_type;
 	/*
 	 * Look up the export entry.
 	 */
 	error = nfserr_stale;
 	exp = exp_get(rqstp->rq_client,
-			u32_to_kdev_t(fh->fh_xdev),
-			u32_to_ino_t(fh->fh_xino));
-	if (!exp) /* export entry revoked */
+		      u32_to_kdev_t(fh->fh_xdev),
+		      u32_to_ino_t(fh->fh_xino));
+	if (!exp) {
+		/* export entry revoked */
+		nfsdstats.fh_stale++;
 		goto out;
+	}
 
 	/* Check if the request originated from a secure port. */
 	error = nfserr_perm;
@@ -1079,32 +421,31 @@
 	/*
 	 * Look up the dentry using the NFS file handle.
 	 */
-	error = nfserr_noent;
-	dentry = find_fh_dentry(fh);
-	if (!dentry)
+
+	dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+				fh,
+				!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+
+	if (IS_ERR(dentry)) {
+		error = nfserrno(-PTR_ERR(dentry));
 		goto out;
+	}
 
-	/*
-	 * Note:  it's possible the returned dentry won't be the one in the
-	 * file handle.  We can correct the file handle for our use, but
-	 * unfortunately the client will keep sending the broken one.  Let's
-	 * hope the lookup will keep patching things up.
-	 */
 	fhp->fh_dentry = dentry;
 	fhp->fh_export = exp;
 	fhp->fh_dverified = 1;
 	nfsd_nr_verified++;
 
+	inode = dentry->d_inode;
+
 	/* Type check. The correct error return for type mismatches
 	 * does not seem to be generally agreed upon. SunOS seems to
 	 * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
 	 * spec says this is incorrect (implementation notes for the
 	 * write call).
 	 */
-check_type:
-	dentry = fhp->fh_dentry;
-	inode = dentry->d_inode;
-	exp = fhp->fh_export;
+
+	/* When is type ever negative? */
 	if (type > 0 && (inode->i_mode & S_IFMT) != type) {
 		error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir;
 		goto out;
@@ -1118,35 +459,37 @@
 	 * Security: Check that the export is valid for dentry <gam3@acm.org>
 	 */
 	error = 0;
-	if (fh->fh_dev != fh->fh_xdev) {
-		printk("fh_verify: Security: export on other device"
-		       " (%d, %d).\n", fh->fh_dev, fh->fh_xdev);
-		error = nfserr_stale;
-	} else if (exp->ex_dentry != dentry) {
-		struct dentry *tdentry = dentry;
 
-		do {
-			tdentry = tdentry->d_parent;
-			if (exp->ex_dentry == tdentry)
-				break;
-			/* executable only by root and we can't be root */
-			if (current->fsuid &&
-			    !(tdentry->d_inode->i_uid  &&
-			        (tdentry->d_inode->i_mode & S_IXUSR)) &&
-			    !(tdentry->d_inode->i_gid &&
-			        (tdentry->d_inode->i_mode & S_IXGRP)) &&
-			    !(tdentry->d_inode->i_mode & S_IXOTH) && 
-			    (exp->ex_flags & NFSEXP_ROOTSQUASH)) {
+	if (!(exp->ex_flags & NFSEXP_NOSUBTREECHECK)) {
+		if (exp->ex_dentry != dentry) {
+			struct dentry *tdentry = dentry;
+
+			do {
+				tdentry = tdentry->d_parent;
+				if (exp->ex_dentry == tdentry)
+					break;
+				/* executable only by root and we can't be root */
+				if (current->fsuid
+				    && (exp->ex_flags & NFSEXP_ROOTSQUASH)
+				    && !(tdentry->d_inode->i_uid
+					 && (tdentry->d_inode->i_mode & S_IXUSR))
+				    && !(tdentry->d_inode->i_gid
+					 && (tdentry->d_inode->i_mode & S_IXGRP))
+				    && !(tdentry->d_inode->i_mode & S_IXOTH)
+					) {
+					error = nfserr_stale;
+					nfsdstats.fh_stale++;
+					dprintk("fh_verify: no root_squashed access.\n");
+				}
+			} while ((tdentry != tdentry->d_parent));
+			if (exp->ex_dentry != tdentry) {
 				error = nfserr_stale;
-dprintk("fh_verify: no root_squashed access.\n");
+				nfsdstats.fh_stale++;
+				printk("nfsd Security: %s/%s bad export.\n",
+				       dentry->d_parent->d_name.name,
+				       dentry->d_name.name);
+				goto out;
 			}
-		} while (!IS_ROOT(tdentry));
-		if (exp->ex_dentry != tdentry) {
-			error = nfserr_stale;
-			printk("nfsd Security: %s/%s bad export.\n",
-			       dentry->d_parent->d_name.name,
-			       dentry->d_name.name);
-			goto out;
 		}
 	}
 
@@ -1155,9 +498,10 @@
 		error = nfsd_permission(exp, dentry, access);
 	}
 #ifdef NFSD_PARANOIA
-if (error)
-printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
+	if (error) {
+		printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
+		       dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
+	}
 #endif
 out:
 	return error;
@@ -1192,14 +536,17 @@
 	}
 	fh_init(fhp);
 
-	fhp->fh_handle.fh_dcookie = dentry;
+	fhp->fh_handle.fh_dirino = ino_t_to_u32(parent->d_inode->i_ino);
+	fhp->fh_handle.fh_dev    = kdev_t_to_u32(parent->d_inode->i_dev);
+	fhp->fh_handle.fh_xdev   = kdev_t_to_u32(exp->ex_dev);
+	fhp->fh_handle.fh_xino   = ino_t_to_u32(exp->ex_ino);
+	fhp->fh_handle.fh_dcookie = (struct dentry *)0xfeebbaca;
 	if (inode) {
 		fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
+		fhp->fh_handle.fh_generation = inode->i_generation;
+		if (S_ISDIR(inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
+			fhp->fh_handle.fh_dirino = 0;
 	}
-	fhp->fh_handle.fh_dirino = ino_t_to_u32(parent->d_inode->i_ino);
-	fhp->fh_handle.fh_dev	 = kdev_t_to_u32(parent->d_inode->i_dev);
-	fhp->fh_handle.fh_xdev	 = kdev_t_to_u32(exp->ex_dev);
-	fhp->fh_handle.fh_xino	 = ino_t_to_u32(exp->ex_ino);
 
 	fhp->fh_dentry = dentry; /* our internal copy */
 	fhp->fh_export = exp;
@@ -1211,6 +558,7 @@
 
 /*
  * Update file handle information after changing a dentry.
+ * This is only called by nfsd_create
  */
 void
 fh_update(struct svc_fh *fhp)
@@ -1226,6 +574,10 @@
 	if (!inode)
 		goto out_negative;
 	fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
+	fhp->fh_handle.fh_generation = inode->i_generation;
+	if (S_ISDIR(inode->i_mode) || (fhp->fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
+		fhp->fh_handle.fh_dirino = 0;
+
 out:
 	return;
 
@@ -1239,8 +591,7 @@
 }
 
 /*
- * Release a file handle.  If the file handle carries a dentry count,
- * we add the dentry to the short-term cache rather than release it.
+ * Release a file handle.
  */
 void
 fh_put(struct svc_fh *fhp)
@@ -1251,10 +602,8 @@
 		fhp->fh_dverified = 0;
 		if (!dentry->d_count)
 			goto out_bad;
-		if (!dentry->d_inode || !add_to_fhcache(dentry, 0)) {
-			dput(dentry);
-			nfsd_nr_put++;
-		}
+		dput(dentry);
+		nfsd_nr_put++;
 	}
 	return;
 
@@ -1262,136 +611,4 @@
 	printk(KERN_ERR "fh_put: %s/%s has d_count 0!\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	return;
-}
-
-/*
- * Verify that the FH dentry is still a valid dentry pointer.
- * After making some preliminary checks, we ask VFS to verify
- * that it is indeed a dentry.
- */
-static int nfsd_d_validate(struct dentry *dentry)
-{
-	unsigned long dent_addr = (unsigned long) dentry;
-	unsigned long min_addr = PAGE_OFFSET;
-	unsigned long max_addr = min_addr + (max_mapnr << PAGE_SHIFT);
-	unsigned long align_mask = 0x0F;
-	unsigned int len;
-	int valid = 0;
-
-	if (dent_addr < min_addr)
-		goto bad_addr;
-	if (dent_addr > max_addr - sizeof(struct dentry))
-		goto bad_addr;
-	if ((dent_addr & ~align_mask) != dent_addr)
-		goto bad_align;
-	if (!kern_addr_valid(dent_addr))
-		goto bad_addr;
-	/*
-	 * Looks safe enough to dereference ...
-	 */
-	len = dentry->d_name.len;
-	if (len > NFS_MAXNAMLEN)
-		goto out;
-	/*
-	 * Note: d_validate doesn't dereference the parent pointer ...
-	 * just combines it with the name hash to find the hash chain.
-	 */
-	valid = d_validate(dentry, dentry->d_parent, dentry->d_name.hash, len);
-
-out:
-	return valid;
-
-bad_addr:
-	printk(KERN_DEBUG "nfsd_d_validate: invalid address %lx\n", dent_addr);
-	goto out;
-bad_align:
-	printk(KERN_DEBUG "nfsd_d_validate: unaligned address %lx\n", dent_addr);
-	goto out;
-}
-
-/*
- * Flush any cached dentries for the specified device
- * or for all devices.
- *
- * This is called when revoking the last export for a
- * device, so that it can be unmounted cleanly.
- */
-void nfsd_fh_flush(kdev_t dev)
-{
-	struct fh_entry *fhe;
-	int i, pass = 2;
-
-	fhe = &filetable[0];
-	while (pass--) {
-		for (i = 0; i < NFSD_MAXFH; i++, fhe++) {
-			struct dentry *dentry = fhe->dentry;
-			if (!dentry)
-				continue;
-			if (dev && dentry->d_inode->i_dev != dev)
-				continue;
-			fhe->dentry = NULL;
-			dput(dentry);
-			nfsd_nr_put++;
-		}
-		fhe = &dirstable[0];
-	}
-}
-
-/*
- * Free the dentry and path caches.
- */
-void nfsd_fh_free(void)
-{
-	struct list_head *tmp;
-	int i;
-
-	/* Flush dentries for all devices */
-	nfsd_fh_flush(0);
-
-	/*
-	 * N.B. write a destructor for these lists ...
-	 */
-	i = 0;
-	while ((tmp = fixup_head.next) != &fixup_head) {
-		struct nfsd_fixup *fp;
-		fp = list_entry(tmp, struct nfsd_fixup, lru);
-		free_fixup_entry(fp);
-		i++;
-	}
-	printk(KERN_DEBUG "nfsd_fh_free: %d fixups freed\n", i);
-
-	i = 0;
-	while ((tmp = path_inuse.next) != &path_inuse) {
-		struct nfsd_path *pe;
-		pe = list_entry(tmp, struct nfsd_path, lru);
-		free_path_entry(pe);
-		i++;
-	}
-	printk(KERN_DEBUG "nfsd_fh_free: %d paths freed\n", i);
-
-	printk(KERN_DEBUG "nfsd_fh_free: verified %d, put %d\n",
-		nfsd_nr_verified, nfsd_nr_put);
-}
-
-void nfsd_fh_init(void)
-{
-	/* Sanity check */ 
-	extern void __my_nfsfh_is_too_big(void); 
-	if (sizeof(struct nfs_fhbase) > 32) 
-		__my_nfsfh_is_too_big(); 
-
-	memset(filetable, 0, NFSD_MAXFH*sizeof(struct fh_entry));
-	memset(dirstable, 0, NFSD_MAXFH*sizeof(struct fh_entry));
-	INIT_LIST_HEAD(&path_inuse);
-	INIT_LIST_HEAD(&fixup_head);
-
-	printk(KERN_DEBUG 
-		"nfsd_init: initialized fhcache, entries=%lu\n", NFSD_MAXFH);
-	/*
-	 * Display a warning if the ino_t is larger than 32 bits.
-	 */
-	if (sizeof(ino_t) > sizeof(__u32))
-		printk(KERN_INFO 
-			"NFSD: ino_t is %d bytes, using lower 4 bytes\n",
-			sizeof(ino_t));
 }
diff -u --recursive --new-file v2.3.23/linux/fs/nfsd/nfssvc.c linux/fs/nfsd/nfssvc.c
--- v2.3.23/linux/fs/nfsd/nfssvc.c	Sat Mar 20 12:28:14 1999
+++ linux/fs/nfsd/nfssvc.c	Mon Oct 25 10:40:19 1999
@@ -101,7 +101,7 @@
 nfsd(struct svc_rqst *rqstp)
 {
 	struct svc_serv	*serv = rqstp->rq_server;
-	int		oldumask, err, first = 0;
+	int		oldumask, err;
 
 	/* Lock module and set up kernel thread */
 	MOD_INC_USE_COUNT;
@@ -117,7 +117,6 @@
 	current->fs->umask = 0;
 	if (!nfsd_active++) {
 		nfssvc_boot = xtime;		/* record boot time */
-		first = 1;
 	}
 	lockd_up();				/* start lockd */
 
@@ -136,13 +135,8 @@
 		 * recvfrom routine.
 		 */
 		while ((err = svc_recv(serv, rqstp,
-		        first?5*HZ:MAX_SCHEDULE_TIMEOUT)) == -EAGAIN) {
-			if (first && 1) {
-				exp_readlock();
-				expire_all();
-				exp_unlock();
-			}
-		}
+				       MAX_SCHEDULE_TIMEOUT)) == -EAGAIN)
+		    ;
 		if (err < 0)
 			break;
 
diff -u --recursive --new-file v2.3.23/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.3.23/linux/fs/nfsd/vfs.c	Fri Oct 15 15:25:14 1999
+++ linux/fs/nfsd/vfs.c	Tue Oct 26 17:33:02 1999
@@ -234,6 +234,7 @@
 	int		ftype = 0;
 	int		imode;
 	int		err;
+	kernel_cap_t	saved_cap = 0;
 
 	if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
 		accmode |= MAY_WRITE;
@@ -242,7 +243,7 @@
 
 	/* Get inode */
 	err = fh_verify(rqstp, fhp, ftype, accmode);
-	if (err)
+	if (err || !iap->ia_valid)
 		goto out;
 
 	dentry = fhp->fh_dentry;
@@ -252,7 +253,7 @@
 	if (err)
 		goto out_nfserr;
 
-	/* The size case is special... */
+	/* The size case is special. It changes the file as well as the attributes.  */
 	if (iap->ia_valid & ATTR_SIZE) {
 if (!S_ISREG(inode->i_mode))
 printk("nfsd_setattr: size change??\n");
@@ -264,15 +265,14 @@
 		err = get_write_access(inode);
 		if (err)
 			goto out_nfserr;
-		/* N.B. Should we update the inode cache here? */
-		inode->i_size = iap->ia_size;
-		if (inode->i_op && inode->i_op->truncate)
-			inode->i_op->truncate(inode);
-		mark_inode_dirty(inode);
-		put_write_access(inode);
-		iap->ia_valid &= ~ATTR_SIZE;
-		iap->ia_valid |= ATTR_MTIME;
-		iap->ia_mtime = CURRENT_TIME;
+
+		err = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
+				  iap->ia_size<inode->i_size ? iap->ia_size : inode->i_size,
+				  abs(inode->i_size - iap->ia_size));
+
+		if (err)
+			goto out_nfserr;
+		DQUOT_INIT(inode);
 	}
 
 	imode = inode->i_mode;
@@ -294,23 +294,32 @@
 	}
 
 	/* Change the attributes. */
-	if (iap->ia_valid) {
-		kernel_cap_t	saved_cap = 0;
 
-		iap->ia_valid |= ATTR_CTIME;
-		iap->ia_ctime = CURRENT_TIME;
-		if (current->fsuid != 0) {
-			saved_cap = current->cap_effective;
-			cap_clear(current->cap_effective);
-		}
+
+	iap->ia_valid |= ATTR_CTIME;
+	if (current->fsuid != 0) {
+		saved_cap = current->cap_effective;
+		cap_clear(current->cap_effective);
+	}
+	if (iap->ia_valid & ATTR_SIZE) {
+		fh_lock(fhp);
 		err = notify_change(dentry, iap);
-		if (current->fsuid != 0)
-			current->cap_effective = saved_cap;
-		if (err)
-			goto out_nfserr;
-		if (EX_ISSYNC(fhp->fh_export))
-			write_inode_now(inode);
+		if (!err) {
+			vmtruncate(inode,iap->ia_size);		
+			if (inode->i_op && inode->i_op->truncate)
+				inode->i_op->truncate(inode);
+		}
+		fh_unlock(fhp);
+		put_write_access(inode);
 	}
+	else
+		err = notify_change(dentry, iap);
+	if (current->fsuid != 0)
+		current->cap_effective = saved_cap;
+	if (err)
+		goto out_nfserr;
+	if (EX_ISSYNC(fhp->fh_export))
+		write_inode_now(inode);
 	err = 0;
 out:
 	return err;
@@ -401,7 +410,6 @@
 		filp->f_op->release(inode, filp);
 	if (filp->f_mode & FMODE_WRITE) {
 		put_write_access(inode);
-		DQUOT_DROP(inode);
 	}
 }
 
@@ -548,7 +556,6 @@
 	if ((stable || (stable = EX_ISSYNC(exp))) && !EX_WGATHER(exp))
 		file.f_flags |= O_SYNC;
 
-	fh_lock(fhp);			/* lock inode */
 	file.f_pos = offset;		/* set write offset */
 
 	/* Write the data. */
@@ -580,8 +587,6 @@
 			current->cap_effective = saved_cap;
 	}
 
-	fh_unlock(fhp);			/* unlock inode */
-
 	if (err >= 0 && stable) {
 		static unsigned long	last_ino = 0;
 		static kdev_t		last_dev = NODEV;
@@ -651,9 +656,13 @@
 	err = nfserr_perm;
 	if (!flen)
 		goto out;
-	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
-	if (err)
-		goto out;
+
+	/* from mkdir it won't be verified, from create it will	 */
+	if (!fhp->fh_dverified) {
+		err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
+		if (err)
+			goto out;
+	}
 
 	dentry = fhp->fh_dentry;
 	dirp = dentry->d_inode;
@@ -731,7 +740,6 @@
 	 */
 	DQUOT_INIT(dirp);
 	err = opfunc(dirp, dchild, iap->ia_mode, rdev);
-	DQUOT_DROP(dirp);
 	if (err < 0)
 		goto out_nfserr;
 
@@ -786,6 +794,11 @@
 	err = get_write_access(inode);
 	if (err)
 		goto out_nfserr;
+	err = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
+				  size<inode->i_size ? size : inode->i_size,
+				  abs(inode->i_size - size));
+	if (err)
+		goto out_nfserr;
 
 	/* Things look sane, lock and do it. */
 	fh_lock(fhp);
@@ -797,15 +810,14 @@
 		cap_clear(current->cap_effective);
 	}
 	err = notify_change(dentry, &newattrs);
-	if (current->fsuid != 0)
-		current->cap_effective = saved_cap;
 	if (!err) {
 		vmtruncate(inode, size);
 		if (inode->i_op && inode->i_op->truncate)
 			inode->i_op->truncate(inode);
 	}
+	if (current->fsuid != 0)
+		current->cap_effective = saved_cap;
 	put_write_access(inode);
-	DQUOT_DROP(inode);
 	fh_unlock(fhp);
 out_nfserr:
 	if (err)
@@ -902,7 +914,6 @@
 	if (!dnew->d_inode) {
 		DQUOT_INIT(dirp);
 		err = dirp->i_op->symlink(dirp, dnew, path);
-		DQUOT_DROP(dirp);
 		if (!err) {
 			if (EX_ISSYNC(fhp->fh_export))
 				write_inode_now(dirp);
@@ -981,7 +992,6 @@
 
 	DQUOT_INIT(dirp);
 	err = dirp->i_op->link(dold, dirp, dnew);
-	DQUOT_DROP(dirp);
 	if (!err) {
 		if (EX_ISSYNC(ffhp->fh_export)) {
 			write_inode_now(dirp);
@@ -1105,8 +1115,6 @@
 		}
 	} else
 		dprintk("nfsd: Caught race in nfsd_rename");
-	DQUOT_DROP(fdir);
-	DQUOT_DROP(tdir);
 
 	nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
 	dput(ndentry);
@@ -1157,7 +1165,6 @@
 		goto out;
 	}
 
-	expire_by_dentry(rdentry);
 
 	if (type != S_IFDIR) {
 		/* It's UNLINK */
@@ -1168,7 +1175,6 @@
 
 		err = vfs_unlink(dirp, rdentry);
 
-		DQUOT_DROP(dirp);
 		fh_unlock(fhp);
 
 		dput(rdentry);
@@ -1188,7 +1194,6 @@
 			err = vfs_rmdir(dirp, rdentry);
 
 		rdentry->d_count--;
-		DQUOT_DROP(dirp);
 		if (!fhp->fh_post_version)
 			fhp->fh_post_version = dirp->i_version;
 		fhp->fh_locked = 0;
diff -u --recursive --new-file v2.3.23/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.3.23/linux/fs/romfs/inode.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/romfs/inode.c	Tue Oct 26 15:03:19 1999
@@ -404,9 +404,6 @@
 	get_page(page);
 	buf = page_address(page);
 
-	/* hack? */
-	page->owner = current;
-
 	offset = page->offset;
 	if (offset < inode->i_size) {
 		avail = inode->i_size-offset;
diff -u --recursive --new-file v2.3.23/linux/fs/smbfs/cache.c linux/fs/smbfs/cache.c
--- v2.3.23/linux/fs/smbfs/cache.c	Fri Oct 15 15:25:14 1999
+++ linux/fs/smbfs/cache.c	Tue Oct 26 13:59:41 1999
@@ -43,16 +43,16 @@
  * the page if it isn't in memory. As I understand it the rest of the
  * smb-cache code assumes we return a locked page.
  */
-unsigned long
-get_cached_page(struct inode * inode, unsigned long offset, int new)
+static unsigned long
+get_cached_page(struct address_space *mapping, unsigned long offset, int new)
 {
 	struct page * page;
 	struct page ** hash;
 	unsigned long new_page;
 
  again:
-	hash = page_hash(inode, offset);
-	page = __find_lock_page(inode, offset, hash);
+	hash = page_hash(mapping, offset);
+	page = __find_lock_page(mapping, offset, hash);
 	if(!page && new) {
 		/* not in cache, alloc a new page */
 		new_page = page_cache_alloc();
@@ -60,7 +60,7 @@
 			return 0;
 		clear_page(new_page);	/* smb code assumes pages are zeroed */
 		page = page_cache_entry(new_page);
-		if (add_to_page_cache_unique(page, inode, offset, hash)) {
+		if (add_to_page_cache_unique(page, mapping, offset, hash)) {
 			/* Hmm, a page has materialized in the
                            cache. Fine. Go back and get that page
                            instead ... throwing away this one first. */
@@ -75,10 +75,10 @@
 	return page_address(page);
 }
 
-static inline struct inode * 
+static inline struct address_space * 
 get_cache_inode(struct cache_head *cachep)
 {
-	return (mem_map + MAP_NR((unsigned long) cachep))->inode;
+	return (mem_map + MAP_NR((unsigned long) cachep))->mapping;
 }
 
 /*
@@ -89,14 +89,14 @@
 struct cache_head *
 smb_get_dircache(struct dentry * dentry)
 {
-	struct inode * inode = dentry->d_inode;
+	struct address_space * mapping = &dentry->d_inode->i_data;
 	struct cache_head * cachep;
 
 #ifdef SMBFS_DEBUG_VERBOSE
 	printk("smb_get_dircache: finding cache for %s/%s\n",
 	       dentry->d_parent->d_name.name, dentry->d_name.name);
 #endif
-	cachep = (struct cache_head *) get_cached_page(inode, 0, 1);
+	cachep = (struct cache_head *) get_cached_page(mapping, 0, 1);
 	if (!cachep)
 		goto out;
 	if (cachep->valid)
@@ -118,7 +118,7 @@
 dentry->d_parent->d_name.name, dentry->d_name.name);
 #endif
 			offset = PAGE_SIZE + (i << PAGE_SHIFT);
-			block = (struct cache_block *) get_cached_page(inode,
+			block = (struct cache_block *) get_cached_page(mapping,
 								offset, 0);
 			if (!block)
 				goto out;
@@ -187,7 +187,7 @@
 smb_add_to_cache(struct cache_head * cachep, struct cache_dirent *entry,
 			off_t fpos)
 {
-	struct inode * inode = get_cache_inode(cachep);
+	struct address_space * mapping = get_cache_inode(cachep);
 	struct cache_index * index;
 	struct cache_block * block;
 	unsigned long page_off;
@@ -195,8 +195,8 @@
 	unsigned int needed = len + sizeof(struct cache_entry);
 
 #ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_add_to_cache: cache inode %p, status %d, adding ", 
-       inode, cachep->status);
+printk("smb_add_to_cache: cache %p, status %d, adding ", 
+       mapping, cachep->status);
 printk_name(entry->name, entry->len);
 printk(" at %ld\n", fpos);
 #endif
@@ -251,14 +251,14 @@
 get_block:
 	cachep->pages++;
 	page_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT);
-	block = (struct cache_block *) get_cached_page(inode, page_off, 1);
+	block = (struct cache_block *) get_cached_page(mapping, page_off, 1);
 	if (block)
 	{
 		index->block = block;
 		index->space = PAGE_SIZE;
 #ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_add_to_cache: inode=%p, pages=%d, block at %ld\n",
-inode, cachep->pages, page_off);
+printk("smb_add_to_cache: mapping=%p, pages=%d, block at %ld\n",
+mapping, cachep->pages, page_off);
 #endif
 		goto add_entry;
 	}
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.3.23/linux/include/asm-i386/io.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-i386/io.h	Wed Oct 27 16:17:20 1999
@@ -28,6 +28,10 @@
  /*
   *  Bit simplified and optimized by Jan Hubicka
   *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
+  *
+  *  isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
+  *  isa_read[wl] and isa_write[wl] fixed
+  *  - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   */
 
 #ifdef SLOW_IO_BY_JUMPING
@@ -192,11 +196,14 @@
 #define __ISA_IO_base ((char *)(PAGE_OFFSET))
 
 #define isa_readb(a) readb(__ISA_IO_base + (a))
-#define isa_readw(a) readb(__ISA_IO_base + (a))
-#define isa_readl(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) writeb(w,__ISA_IO_base + (a))
-#define isa_writel(l,a) writeb(l,__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))
 
 /*
  * Again, i386 does not require mem IO specific function.
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
--- v2.3.23/linux/include/asm-i386/page.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-i386/page.h	Tue Oct 26 17:16:15 1999
@@ -84,9 +84,7 @@
  * see^H^H^Hhear bugs in early bootup as well!
  */
 #define BUG() do { \
-	__asm__ __volatile__ ("movb $0x3,%al; outb %al,$0x61"); \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	console_loglevel = 0; \
 	__asm__ __volatile__(".byte 0x0f,0x0b"); \
 } while (0)
 
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/pgtable-2level.h linux/include/asm-i386/pgtable-2level.h
--- v2.3.23/linux/include/asm-i386/pgtable-2level.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-i386/pgtable-2level.h	Tue Oct 26 10:41:12 1999
@@ -32,7 +32,7 @@
 extern inline int pgd_none(pgd_t pgd)		{ return 0; }
 extern inline int pgd_bad(pgd_t pgd)		{ return 0; }
 extern inline int pgd_present(pgd_t pgd)	{ return 1; }
-#define pgd_clear(xp)	do { pgd_val(*(xp)) = 0; } while (0)
+#define pgd_clear(xp)				do { } while (0)
 
 #define pgd_page(pgd) \
 ((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.3.23/linux/include/asm-i386/processor.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-i386/processor.h	Wed Oct 27 16:17:06 1999
@@ -407,8 +407,8 @@
 }
 
 #define THREAD_SIZE (2*PAGE_SIZE)
-extern struct task_struct * alloc_task_struct(void);
-extern void free_task_struct(struct task_struct *);
+#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
+#define free_task_struct(p) free_pages((unsigned long) (p), 1)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/resource.h linux/include/asm-i386/resource.h
--- v2.3.23/linux/include/asm-i386/resource.h	Mon Jul 26 22:41:09 1999
+++ linux/include/asm-i386/resource.h	Mon Oct 25 09:21:50 1999
@@ -22,16 +22,16 @@
 
 #define INIT_RLIMITS					\
 {							\
-	{ LONG_MAX, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ _STK_LIM, LONG_MAX },				\
-	{        0, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ 0, 0 },					\
-	{ INR_OPEN, INR_OPEN },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
+	{ 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__ */
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h
--- v2.3.23/linux/include/asm-i386/semaphore.h	Fri Sep 10 23:57:36 1999
+++ linux/include/asm-i386/semaphore.h	Wed Oct 27 16:17:07 1999
@@ -98,8 +98,6 @@
 asmlinkage int  __down_trylock(struct semaphore * sem);
 asmlinkage void __up(struct semaphore * sem);
 
-extern spinlock_t semaphore_wake_lock;
-
 /*
  * This is ugly, but we want the default case to fall through.
  * "down_failed" is a special asm handler that calls the C
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/string-486.h linux/include/asm-i386/string-486.h
--- v2.3.23/linux/include/asm-i386/string-486.h	Mon Oct 11 15:38:15 1999
+++ linux/include/asm-i386/string-486.h	Wed Oct 27 16:17:10 1999
@@ -15,7 +15,9 @@
  *
  *	Split into 2 CPU specific files by Alan Cox to keep #ifdef noise down.
  *
- *	99/9/15  Proper reg args for newer gcc/egcs - Petkan (petkan@spct.net)
+ *	1999/10/5	Proper register args for newer GCCs and minor bugs
+ *			fixed - Petko Manolov (petkan@spct.net)
+ *	1999/10/14	3DNow memscpy() added - Petkan
  */
 
 #define __HAVE_ARCH_STRCPY
@@ -103,7 +105,7 @@
 	"incl %1\n\t"
 	"testb %b0,%b0\n\t"
 	"jne 2b\n"
-	"3:\txorl %0,%0\n\t"
+	"3:\txorb %0,%0\n\t"
 	"movb %b0,(%1)\n\t"
 	:"=q" (dummy), "=r" (tmp), "=r" (src), "=r" (count)
 	:"1"  (tmp), "2"  (src), "3"  (count)
@@ -254,6 +256,7 @@
 return __res-cs;
 }
 
+#if 0
 #define __HAVE_ARCH_STRPBRK
 extern inline char * strpbrk(const char * cs,const char * ct)
 {
@@ -261,7 +264,7 @@
 register char * __res;
 __asm__ __volatile__(
 	"cld\n\t"
-	"movl %4,%%edi\n\t"
+	"movl %6,%%edi\n\t"
 	"repne\n\t"
 	"scasb\n\t"
 	"notl %%ecx\n\t"
@@ -270,7 +273,7 @@
 	"1:\tlodsb\n\t"
 	"testb %%al,%%al\n\t"
 	"je 2f\n\t"
-	"movl %4,%%edi\n\t"
+	"movl %6,%%edi\n\t"
 	"movl %%edx,%%ecx\n\t"
 	"repne\n\t"
 	"scasb\n\t"
@@ -284,7 +287,9 @@
 	:"dx", "di");
 return __res;
 }
+#endif
 
+#if 0
 #define __HAVE_ARCH_STRSTR
 extern inline char * strstr(const char * cs,const char * ct)
 {
@@ -292,13 +297,13 @@
 register char * __res;
 __asm__ __volatile__(
 	"cld\n\t" \
-	"movl %4,%%edi\n\t"
+	"movl %6,%%edi\n\t"
 	"repne\n\t"
 	"scasb\n\t"
 	"notl %%ecx\n\t"
 	"decl %%ecx\n\t"	/* NOTE! This also sets Z if searchstring='' */
 	"movl %%ecx,%%edx\n"
-	"1:\tmovl %4,%%edi\n\t"
+	"1:\tmovl %6,%%edi\n\t"
 	"movl %%esi,%%eax\n\t"
 	"movl %%edx,%%ecx\n\t"
 	"repe\n\t"
@@ -315,6 +320,7 @@
 	:"dx", "di");
 return __res;
 }
+#endif
 
 #define __HAVE_ARCH_STRLEN
 extern inline size_t strlen(const char * s)
@@ -343,7 +349,7 @@
 int	d0;
 register int __res;
 __asm__ __volatile__(
-	"movl %1,%0\n\t"
+	"movl %3,%0\n\t"
 	"jmp 2f\n"
 	"1:\tcmpb $0,(%0)\n\t"
 	"je 3f\n\t"
@@ -351,13 +357,14 @@
 	"2:\tdecl %2\n\t"
 	"cmpl $-1,%2\n\t"
 	"jne 1b\n"
-	"3:\tsubl %1,%0"
+	"3:\tsubl %3,%0"
 	:"=a" (__res), "=&d" (d0)
 	:"1" (count), "c" (s));
 return __res;
 }
 /* end of additional stuff */
 
+#if 0
 #define __HAVE_ARCH_STRTOK
 extern inline char * strtok(char * s,const char * ct)
 {
@@ -418,19 +425,7 @@
 	:"ax","cx","dx","di","memory");
 return __res;
 }
-
-#define __memcpy_c(d,s,count) \
-((count%4==0) ? \
- __memcpy_by4((d),(s),(count)) : \
- ((count%2==0) ? \
-  __memcpy_by2((d),(s),(count)) : \
-  __memcpy_g((d),(s),(count))))
-
-#define __HAVE_ARCH_MEMCPY
-#define memcpy(d,s,count) \
-(__builtin_constant_p(count) ? \
- __memcpy_c((d),(s),(count)) : \
- __memcpy_g((d),(s),(count)))
+#endif
 
 /*
  *	These ought to get tweaked to do some cache priming.
@@ -494,6 +489,63 @@
 return (to);
 }
 
+#define __memcpy_c(d,s,count) \
+((count%4==0) ? \
+ __memcpy_by4((d),(s),(count)) : \
+ ((count%2==0) ? \
+  __memcpy_by2((d),(s),(count)) : \
+  __memcpy_g((d),(s),(count))))
+  
+#define __memcpy(d,s,count) \
+(__builtin_constant_p(count) ? \
+ __memcpy_c((d),(s),(count)) : \
+ __memcpy_g((d),(s),(count)))
+ 
+#define __HAVE_ARCH_MEMCPY
+
+#include <linux/config.h>
+
+#ifdef CONFIG_X86_USE_3DNOW
+
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <asm/mmx.h>
+
+/*
+**      This CPU favours 3DNow strongly (eg AMD K6-II, K6-III, Athlon)
+*/
+
+extern inline void * __constant_memcpy3d(void * to, const void * from, size_t len)
+{
+	if(len<512 || in_interrupt())
+		return __memcpy_c(to, from, len);
+	return _mmx_memcpy(to, from, len);
+}
+
+extern __inline__ void *__memcpy3d(void *to, const void *from, size_t len)
+{
+	if(len<512 || in_interrupt())
+		return __memcpy_g(to, from, len);
+	return _mmx_memcpy(to, from, len);
+}
+
+#define memcpy(d, s, count) \
+(__builtin_constant_p(count) ? \
+ __constant_memcpy3d((d),(s),(count)) : \
+ __memcpy3d((d),(s),(count)))
+ 
+#else /* CONFIG_X86_USE_3DNOW */
+
+/*
+**	Generic routines
+*/
+
+#define memcpy(d, s, count) __memcpy(d, s, count)
+
+#endif /* CONFIG_X86_USE_3DNOW */ 
 
 #define __HAVE_ARCH_MEMMOVE
 extern inline void * memmove(void * dest,const void * src, size_t n)
diff -u --recursive --new-file v2.3.23/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h
--- v2.3.23/linux/include/asm-i386/termios.h	Wed Mar 24 11:45:59 1999
+++ linux/include/asm-i386/termios.h	Wed Oct 27 14:21:51 1999
@@ -53,6 +53,7 @@
 #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 messages */
 #define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14	/* synchronous PPP */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.23/linux/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h
--- v2.3.23/linux/include/asm-ppc/dma.h	Fri Sep 10 23:57:36 1999
+++ linux/include/asm-ppc/dma.h	Tue Oct 26 15:02:14 1999
@@ -99,18 +99,21 @@
 
 /* used in nasty hack for sound - see prep_setup_arch() -- Cort */
 extern long ppc_cs4232_dma, ppc_cs4232_dma2;
-#ifdef CONFIG_CS4232
+#if defined(CONFIG_CS4232)
+#if defined(CONFIG_PREP) || defined(CONFIG_ALL_PPC)
 #define SND_DMA1 ppc_cs4232_dma
 #define SND_DMA2 ppc_cs4232_dma2
-#else
-#ifdef CONFIG_MSS
+#else /* !CONFIG_PREP && !CONFIG_ALL_PPC */
+#define SND_DMA1 -1
+#define SND_DMA2 -1
+#endif /* !CONFIG_PREP */
+#elif defined(CONFIG_MSS)
 #define SND_DMA1 CONFIG_MSS_DMA
 #define SND_DMA2 CONFIG_MSS_DMA2
 #else
 #define SND_DMA1 -1
 #define SND_DMA2 -1
 #endif
-#endif
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
@@ -203,6 +206,7 @@
 	 */
 	unsigned char ucDmaCmd=0x00;
 
+#if defined(CONFIG_PREP) || defined(CONFIG_ALL_PPC)
 	if(_prep_type==_PREP_Radstone)
 	{
 		switch(ucSystemType)
@@ -227,6 +231,7 @@
 			}
 		}
 	}
+#endif /* CONFIG_PREP || CONFIG_ALL_PPC */
 
 	if (dmanr != 4)
 	{
diff -u --recursive --new-file v2.3.23/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.3.23/linux/include/asm-ppc/pgtable.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-ppc/pgtable.h	Tue Oct 26 15:02:14 1999
@@ -423,10 +423,10 @@
 #define pgtable_cache_size 	(quicklists.pgtable_cache_sz)
 
 extern unsigned long *zero_cache;    /* head linked list of pre-zero'd pages */
-extern unsigned long zero_sz;	     /* # currently pre-zero'd pages */
-extern unsigned long zeropage_hits;  /* # zero'd pages request that we've done */
-extern unsigned long zeropage_calls; /* # zero'd pages request that've been made */
-extern unsigned long zerototal;      /* # pages zero'd over time */
+extern atomic_t zero_sz;	     /* # currently pre-zero'd pages */
+extern atomic_t zeropage_hits;	     /* # zero'd pages request that we've done */
+extern atomic_t zeropage_calls;      /* # zero'd pages request that've been made */
+extern atomic_t zerototal;	     /* # pages zero'd over time */
 
 #define zero_quicklist     	(zero_cache)
 #define zero_cache_sz  	 	(zero_sz)
@@ -440,12 +440,9 @@
 extern __inline__ pgd_t *get_pgd_slow(void)
 {
 	pgd_t *ret, *init;
-
-	if ( (ret = (pgd_t *)get_zero_page_fast()) == NULL )
-	{
-		if ( (ret = (pgd_t *)__get_free_page(GFP_KERNEL)) != NULL )
-			memset (ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-	}
+	/*if ( (ret = (pgd_t *)get_zero_page_fast()) == NULL )*/
+	if ( (ret = (pgd_t *)__get_free_page(GFP_KERNEL)) != NULL )
+		memset (ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
 	if (ret) {
 		init = pgd_offset(&init_mm, 0);
 		memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
@@ -489,7 +486,7 @@
                 pte_quicklist = (unsigned long *)(*ret);
                 ret[0] = ret[1];
                 pgtable_cache_size--;
-         }
+	}
         return (pte_t *)ret;
 }
 
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/dma.h linux/include/asm-sh/dma.h
--- v2.3.23/linux/include/asm-sh/dma.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sh/dma.h	Mon Oct 25 10:59:18 1999
@@ -6,6 +6,10 @@
 
 #define MAX_DMA_CHANNELS 8
 
+/* The maximum address that we can perform a DMA transfer to on this platform */
+/* XXX: This is not applicable to SuperH, just needed for alloc_bootmem */
+#define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x1000000)
+
 extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
 
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/highmem.h linux/include/asm-sh/highmem.h
--- v2.3.23/linux/include/asm-sh/highmem.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/highmem.h	Mon Oct 25 10:59:18 1999
@@ -0,0 +1,85 @@
+/*
+ * highmem.h: virtual kernel memory mappings for high memory
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual adresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ *		      Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with 
+ * up to 16 Terrabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#include <linux/init.h>
+
+/* undef for production */
+#define HIGHMEM_DEBUG 1
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+extern pte_t *kmap_pte;
+extern pgprot_t kmap_prot;
+
+extern void kmap_init(void) __init;
+
+/* kmap helper functions necessary to access the highmem pages in kernel */
+#include <asm/pgtable.h>
+#include <asm/kmap_types.h>
+
+extern inline unsigned long kmap(struct page *page, enum km_type type)
+{
+	if (page < highmem_start_page)
+		return page_address(page);
+	{
+		enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id();
+		unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN+idx);
+
+#if HIGHMEM_DEBUG
+		if (!pte_none(*(kmap_pte-idx)))
+		{
+			__label__ here;
+		here:
+			printk(KERN_ERR "not null pte on CPU %d from %p\n",
+			       smp_processor_id(), &&here);
+		}
+#endif
+		set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
+		__flush_tlb_one(vaddr);
+
+		return vaddr;
+	}
+}
+
+extern inline void kunmap(unsigned long vaddr, enum km_type type)
+{
+#if HIGHMEM_DEBUG
+	enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id();
+	if ((vaddr & PAGE_MASK) == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+	{
+		/* force other mappings to Oops if they'll try to access
+		   this pte without first remap it */
+		pte_clear(kmap_pte-idx);
+		__flush_tlb_one(vaddr);
+	}
+#endif
+}
+
+extern inline void kmap_check(void)
+{
+#if HIGHMEM_DEBUG
+	int idx_base = KM_TYPE_NR*smp_processor_id(), i;
+	for (i = idx_base; i < idx_base+KM_TYPE_NR; i++)
+		if (!pte_none(*(kmap_pte-i)))
+			BUG();
+#endif
+}
+#endif /* _ASM_HIGHMEM_H */
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/mmu_context.h linux/include/asm-sh/mmu_context.h
--- v2.3.23/linux/include/asm-sh/mmu_context.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-sh/mmu_context.h	Mon Oct 25 10:59:18 1999
@@ -141,7 +141,7 @@
 				 struct task_struct *tsk, unsigned int cpu)
 {
 	if (prev != next) {
-		unsigned long __pgdir = __pa(next->pgd);
+		unsigned long __pgdir = (unsigned long)next->pgd;
 
 		__asm__ __volatile__("mov.l	%0,%1": \
 				     :"r" (__pgdir), "m" (__m(MMU_TTB)));
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/page.h linux/include/asm-sh/page.h
--- v2.3.23/linux/include/asm-sh/page.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-sh/page.h	Mon Oct 25 10:59:18 1999
@@ -23,12 +23,9 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#define STRICT_MM_TYPECHECKS
-
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 #define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
 
-#ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
  */
@@ -47,26 +44,6 @@
 #define __pgd(x)	((pgd_t) { (x) } )
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
-#else
-/*
- * .. 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 __pmd(x)	(x)
-#define __pgd(x)	(x)
-#define __pgprot(x)	(x)
-
-#endif
 #endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
@@ -75,7 +52,7 @@
 /*
  * IF YOU CHANGE THIS, PLEASE ALSO CHANGE
  *
- *	arch/sh/vmlinux.lds
+ *	arch/sh/vmlinux.lds.S
  *
  * which has the same constant encoded..
  */
@@ -89,8 +66,15 @@
 #define MAP_NR(addr)		((__pa(addr)-__MEMORY_START) >> PAGE_SHIFT)
 
 #ifndef __ASSEMBLY__
+
+extern int console_loglevel;
+
+/*
+ * Tell the user there is some problem.
+ */
 #define BUG() do { \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+	console_loglevel = 0; \
 	asm volatile("nop"); \
 } while (0)
 
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/pgtable-2level.h linux/include/asm-sh/pgtable-2level.h
--- v2.3.23/linux/include/asm-sh/pgtable-2level.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/pgtable-2level.h	Mon Oct 25 10:59:18 1999
@@ -0,0 +1,62 @@
+#ifndef __ASM_SH_PGTABLE_2LEVEL_H
+#define __ASM_SH_PGTABLE_2LEVEL_H
+
+/*
+ * traditional two-level paging structure:
+ */
+
+#define PGDIR_SHIFT	22
+#define PTRS_PER_PGD	1024
+
+/*
+ * this is two-level, so we don't really have any
+ * PMD directory physically.
+ */
+#define PMD_SHIFT	22
+#define PTRS_PER_PMD	1
+
+#define PTRS_PER_PTE	1024
+
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+extern inline int pgd_none(pgd_t pgd)		{ return 0; }
+extern inline int pgd_bad(pgd_t pgd)		{ return 0; }
+extern inline int pgd_present(pgd_t pgd)	{ return 1; }
+#define pgd_clear(xp)	do { pgd_val(*(xp)) = 0; } while (0)
+
+#define pgd_page(pgd) \
+((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+	return (pmd_t *) dir;
+}
+
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+	return (pmd_t *)0;
+}
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd) { }
+extern __inline__ void free_pmd_slow(pmd_t *pmd) { }
+
+extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+	if (!pgd)
+		BUG();
+	return (pmd_t *) pgd;
+}
+
+#define SWP_ENTRY(type,offset) __pte((((type) << 1) | ((offset) << 8)))
+
+#endif /* __ASM_SH_PGTABLE_2LEVEL_H */
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/pgtable.h linux/include/asm-sh/pgtable.h
--- v2.3.23/linux/include/asm-sh/pgtable.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-sh/pgtable.h	Mon Oct 25 10:59:18 1999
@@ -65,25 +65,36 @@
 
 #endif /* !__ASSEMBLY__ */
 
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define PMD_SHIFT	22
+#define pgd_quicklist (current_cpu_data.pgd_quick)
+#define pmd_quicklist ((unsigned long *)0)
+#define pte_quicklist (current_cpu_data.pte_quick)
+#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
+
+#include <asm/pgtable-2level.h>
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
+#define __beep() asm("")
+
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT	22
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
-/*
- * Entries per page directory level: we use two-level, so
- * we don't really have any PMD directory physically.
- */
-#define PTRS_PER_PTE	1024
-#define PTRS_PER_PMD	1
-#define PTRS_PER_PGD	1024
 #define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
 
+#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+
+#define TWOLEVEL_PGDIR_SHIFT	22
+#define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
+#define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
+
 #ifndef __ASSEMBLY__
 #define VMALLOC_START	P3SEG
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
@@ -96,7 +107,7 @@
 /*		 	0x010  */
 #define _PAGE_RW	0x020  /* PR0-bit : write access allowed */
 #define _PAGE_USER	0x040  /* PR1-bit : user space access allowed */
-/*		 	0x080  */
+#define _PAGE_PROTNONE	0x080  /* software: if not present */
 #define _PAGE_PRESENT	0x100  /* V-bit   : page is valid */
 
 #if defined(__sh3__)
@@ -115,7 +126,7 @@
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
@@ -156,154 +167,101 @@
 extern pte_t __bad_page(void);
 extern pte_t * __bad_pagetable(void);
 
+/*
+ * 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))
 
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE(vaddr) ((unsigned long) empty_zero_page)
-
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR			(8*sizeof(unsigned long))
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK			(~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-/* 64-bit machines, beware!  SRB. */
-#define SIZEOF_PTR_LOG2			2
-
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
+/*
+ * Handling allocation failures during page table setup.
  */
-extern __inline__ void set_pte(pte_t *ptep, pte_t pteval)
-{
-	*ptep = pteval;
-}
+extern void __handle_bad_pmd(pmd_t * pmd);
+extern void __handle_bad_pmd_kernel(pmd_t * pmd);
 
-extern __inline__ int pte_none(pte_t pte)
-{
-	return !pte_val(pte);
-}
-
-extern __inline__ int pte_present(pte_t pte)
-{
-	return pte_val(pte) & _PAGE_PRESENT;
-}
-
-extern __inline__ void pte_clear(pte_t *ptep)
-{
-	pte_val(*ptep) = 0;
-}
-
-extern __inline__ int pmd_none(pmd_t pmd)
-{
-	return !pmd_val(pmd);
-}
+#define pte_none(x)	(!pte_val(x))
+#define pte_present(x)	(pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
+#define pte_clear(xp)	do { pte_val(*(xp)) = 0; } while (0)
+#define pte_pagenr(x)	((unsigned long)((pte_val(x) >> PAGE_SHIFT)))
 
+#define pmd_none(x)	(!pmd_val(x))
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
-
-extern __inline__ int pmd_present(pmd_t pmd)
-{
-	return pmd_val(pmd) & _PAGE_PRESENT;
-}
-
-extern __inline__ void pmd_clear(pmd_t *pmdp)
-{
-	pmd_val(*pmdp) = 0;
-}
+#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+#define pmd_clear(xp)	do { pmd_val(*(xp)) = 0; } while (0)
 
 /*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
+ * Permanent address of a page. Obviously must never be
+ * called on a highmem page.
  */
-extern __inline__ int pgd_none(pgd_t pgd)	{ return 0; }
-extern __inline__ int pgd_bad(pgd_t pgd)	{ return 0; }
-extern __inline__ int pgd_present(pgd_t pgd)	{ return 1; }
-extern __inline__ void pgd_clear(pgd_t * pgdp)	{ }
+#define page_address(page) ({ if (PageHighMem(page)) BUG(); PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT); })
+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+#define pte_page(x) (mem_map+pte_pagenr(x))
 
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern __inline__ int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-extern __inline__ int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-extern __inline__ int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
-extern __inline__ int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
-extern __inline__ int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_RW; }
-
-extern __inline__ pte_t pte_rdprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern __inline__ pte_t pte_exprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern __inline__ pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern __inline__ pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern __inline__ pte_t pte_wrprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_RW; return pte; }
-extern __inline__ pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
-extern __inline__ pte_t pte_mkexec(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
-extern __inline__ pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern __inline__ pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-extern __inline__ pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_RW; return pte; }
+extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+extern inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
+extern inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_RW; }
+       
+extern inline pte_t pte_rdprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern inline pte_t pte_exprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_wrprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_RW; return pte; }
+extern inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
+extern inline pte_t pte_mkexec(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
+extern inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
+extern inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+extern inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_RW; return pte; }
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+extern inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
 {
-	return __pte(__pa(page) | pgprot_val(pgprot));
+	pte_t __pte;
+
+	pte_val(__pte) = (page-mem_map)*(unsigned long long)PAGE_SIZE +
+				pgprot_val(pgprot);
+	return __pte;
 }
 
 /* This takes a physical page address that is used by the remapping functions */
-extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{
-	return __pte(physpage | pgprot_val(pgprot));
-}
+#define mk_pte_phys(physpage, pgprot) \
+({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
 
-extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
-	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
-}
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
 
-extern __inline__ unsigned long pte_page(pte_t pte)
-{
-	return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
-}
+#define page_pte_prot(page,prot) mk_pte(page, prot)
+#define page_pte(page) page_pte_prot(page, __pgprot(0))
 
-extern __inline__ unsigned long pmd_page(pmd_t pmd)
-{
-	return (unsigned long)__va(pmd_val(pmd) & PAGE_MASK);
-}
+#define pmd_page(pmd) \
+((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
 
-extern __inline__ void pmd_set(pmd_t * pmdp, pte_t * ptep)
-{
-	pmd_val(*pmdp) = __pa(((unsigned long) ptep) & PAGE_MASK) | _PAGE_TABLE;
-}
+/* to find an entry in a page-table-directory. */
+#define __pgd_offset(address) \
+		((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+#define pgd_offset(mm, address) ((mm)->pgd+__pgd_offset(address))
 
 /* to find an entry in a kernel page-table-directory */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-/* to find an entry in a page-table-directory */
-extern __inline__ pgd_t *pgd_offset(struct mm_struct *mm, unsigned long addr)
-{
-	return mm->pgd + (addr >> PGDIR_SHIFT);
-}
+#define __pmd_offset(address) \
+		(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
 
-/* Find an entry in the second-level page table.. */
-extern __inline__ pmd_t * pmd_offset(pgd_t * dir, unsigned long addr)
-{
-	return (pmd_t *) dir;
-}
-
-/* Find an entry in the third-level page table.. */ 
-extern __inline__ pte_t *pte_offset(pmd_t * dir, unsigned long addr)
-{
-	return (pte_t *) (pmd_page(*dir)) +
-	       ((addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
+/* Find an entry in the third-level page table.. */
+#define __pte_offset(address) \
+		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \
+			__pte_offset(address))
 
 /*
  * Allocate and free page tables. The xxx_kernel() versions are
@@ -311,11 +269,6 @@
  * if any.
  */
 
-#define pgd_quicklist (current_cpu_data.pgd_quick)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist (current_cpu_data.pte_quick)
-#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
-
 extern __inline__ pgd_t *get_pgd_slow(void)
 {
 	pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
@@ -379,23 +332,6 @@
 	free_page((unsigned long)pte);
 }
 
-/* We don't use pmd cache, so these are dummy routines */
-extern __inline__ pmd_t *get_pmd_fast(void)
-{
-	return (pmd_t *)0;
-}
-
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
-{
-}
-
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
-{
-}
-
-extern void __bad_pte(pmd_t *pmd);
-extern void __bad_pte_kernel(pmd_t *pmd);
-
 #define pte_free_kernel(pte)    free_pte_slow(pte)
 #define pte_free(pte)           free_pte_slow(pte)
 #define pgd_free(pgd)           free_pgd_slow(pgd)
@@ -405,15 +341,15 @@
 {
 	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 	if (pmd_none(*pmd)) {
-		pte_t *page = get_pte_fast();
+		pte_t *page = (pte_t *) get_pte_fast();
 		
 		if (!page)
 			return get_pte_kernel_slow(pmd, address);
-		pmd_set(pmd, page);
+		pmd_val(*pmd) = _KERNPG_TABLE + __pa(page);
 		return page + address;
 	}
 	if (pmd_bad(*pmd)) {
-		__bad_pte_kernel(pmd);
+		__handle_bad_pmd_kernel(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + address;
@@ -421,13 +357,13 @@
 
 extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
 {
-	address = (address >> (PAGE_SHIFT-2)) & 4*(PTRS_PER_PTE - 1);
+	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 
 	if (pmd_none(*pmd))
 		goto getnew;
 	if (pmd_bad(*pmd))
 		goto fix;
-	return (pte_t *) (pmd_page(*pmd) + address);
+	return (pte_t *)pmd_page(*pmd) + address;
 getnew:
 {
 	unsigned long page = (unsigned long) get_pte_fast();
@@ -435,10 +371,10 @@
 	if (!page)
 		return get_pte_slow(pmd, address);
 	pmd_val(*pmd) = _PAGE_TABLE + __pa(page);
-	return (pte_t *) (page + address);
+	return (pte_t *)page + address;
 }
 fix:
-	__bad_pte(pmd);
+	__handle_bad_pmd(pmd);
 	return NULL;
 }
 
@@ -450,11 +386,6 @@
 {
 }
 
-extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
-{
-	return (pmd_t *) pgd;
-}
-
 #define pmd_free_kernel		pmd_free
 #define pmd_alloc_kernel	pmd_alloc
 
@@ -481,9 +412,8 @@
 extern void update_mmu_cache(struct vm_area_struct * vma,
 			     unsigned long address, pte_t pte);
 
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x3f)
-#define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+#define SWP_TYPE(entry) (((pte_val(entry)) >> 1) & 0x3f)
+#define SWP_OFFSET(entry) ((pte_val(entry)) >> 8)
 
 #define module_map      vmalloc
 #define module_unmap    vfree
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/processor.h linux/include/asm-sh/processor.h
--- v2.3.23/linux/include/asm-sh/processor.h	Fri Oct 22 13:21:54 1999
+++ linux/include/asm-sh/processor.h	Mon Oct 25 10:59:18 1999
@@ -33,7 +33,6 @@
 
 	char	hard_math;
 
-	/* Not yet used */
 	unsigned long *pgd_quick;
 	unsigned long *pte_quick;
 	unsigned long pgtable_cache_sz;
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/spinlock.h linux/include/asm-sh/spinlock.h
--- v2.3.23/linux/include/asm-sh/spinlock.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sh/spinlock.h	Mon Oct 25 10:59:18 1999
@@ -1,6 +1,53 @@
 #ifndef __ASM_SH_SPINLOCK_H
 #define __ASM_SH_SPINLOCK_H
 
+#ifndef __SMP__
+
+typedef struct { } spinlock_t;
+#define SPIN_LOCK_UNLOCKED { }
+
+#define spin_lock_init(lock)	do { } while(0)
+#define spin_lock(lock)		do { } while(0)
+#define spin_trylock(lock)	(1)
+#define spin_unlock_wait(lock)	do { } while(0)
+#define spin_unlock(lock)	do { } while(0)
+#define spin_lock_irq(lock)	cli()
+#define spin_unlock_irq(lock)	sti()
+
+#define spin_lock_irqsave(lock, flags)		save_and_cli(flags)
+#define spin_unlock_irqrestore(lock, flags)	restore_flags(flags)
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct { } rwlock_t;
+#define RW_LOCK_UNLOCKED (rwlock_t) { }
+
+#define read_lock(lock)		do { } while(0)
+#define read_unlock(lock)	do { } while(0)
+#define write_lock(lock)	do { } while(0)
+#define write_unlock(lock)	do { } while(0)
+#define read_lock_irq(lock)	cli()
+#define read_unlock_irq(lock)	sti()
+#define write_lock_irq(lock)	cli()
+#define write_unlock_irq(lock)	sti()
+
+#define read_lock_irqsave(lock, flags)		save_and_cli(flags)
+#define read_unlock_irqrestore(lock, flags)	restore_flags(flags)
+#define write_lock_irqsave(lock, flags)		save_and_cli(flags)
+#define write_unlock_irqrestore(lock, flags)	restore_flags(flags)
+
+#else
+
 #error "No SMP on SH"
+
+#endif /* SMP */
 
 #endif /* __ASM_SH_SPINLOCK_H */
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/string.h linux/include/asm-sh/string.h
--- v2.3.23/linux/include/asm-sh/string.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sh/string.h	Mon Oct 25 10:59:18 1999
@@ -18,9 +18,9 @@
 			     "cmp/eq	#0,%2\n\t"
 			     "bf/s	1b\n\t"
 			     " add	#1,%0\n\t"
-			     :"=&r" (__dest), "=&r" (__src), "=&z" (__dummy)
-			     :"0" (__dest), "1" (__src)
-			     :"memory");
+			     : "=r" (__dest), "=r" (__src), "=&z" (__dummy)
+			     : "0" (__dest), "1" (__src)
+			     : "memory");
 
 	return __xdest;
 }
@@ -37,12 +37,12 @@
 	__asm__ __volatile__(
 		"1:\n"
 		"mov.b	@%1+,%2\n\t"
-		"mov.b  %2,@%0\n\t"
-		"cmp/eq #0,%2\n\t"
-		"bt/s   2f\n\t"
-		" cmp/eq %5,%1\n\t"
-		"bf/s   1b\n\t"
-		" add    #1,%0\n"
+		"mov.b	%2,@%0\n\t"
+		"cmp/eq	#0,%2\n\t"
+		"bt/s	2f\n\t"
+		" cmp/eq	%5,%1\n\t"
+		"bf/s	1b\n\t"
+		" add	#1,%0\n"
 		"2:"
 		: "=r" (__dest), "=r" (__src), "=&z" (__dummy)
 		: "0" (__dest), "1" (__src), "r" (__src+__n)
@@ -112,6 +112,9 @@
 
 #define __HAVE_ARCH_MEMMOVE
 extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
+
+#define __HAVE_ARCH_MEMCHR
+extern void *memchr(const void *__s, int __c, size_t __n);
 
 /* Don't build bcopy at all ...  */
 #define __HAVE_ARCH_BCOPY
diff -u --recursive --new-file v2.3.23/linux/include/asm-sh/system.h linux/include/asm-sh/system.h
--- v2.3.23/linux/include/asm-sh/system.h	Fri Oct 22 13:21:55 1999
+++ linux/include/asm-sh/system.h	Mon Oct 25 10:59:18 1999
@@ -98,7 +98,7 @@
 	__asm__ __volatile__("stc	sr,%0\n\t"
 			     "and	%1,%0\n\t"
 			     "ldc	%0,sr"
-			     : "=&z" (__dummy)
+			     : "=&r" (__dummy)
 			     : "r" (0xefffffff)
 			     : "memory");
 }
@@ -109,24 +109,24 @@
 	__asm__ __volatile__("stc	sr,%0\n\t"
 			     "or	%1,%0\n\t"
 			     "ldc	%0,sr"
-			     : "=&z" (__dummy)
+			     : "=&r" (__dummy)
 			     : "r" (0x10000000)
 			     : "memory");
 }
 
 #define __save_flags(x) \
-__asm__ __volatile__("stc	sr,%0\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop":"=r" (x): /* no inputs */ :"memory")
+__asm__ __volatile__("stc	sr,%0":"=r" (x): /* no inputs */ :"memory")
 
-#define __save_and_cli(x)               \
-({	unsigned long __dummy;		\
-__asm__ __volatile__(                   \
-	"stc	sr,%0\n\t" \
-	"mov	%0,%1\n\t" \
-	"or	%2,%1\n\t" \
-	"ldc	%1,sr"     \
-	: "=&r" (x), "=&z" (__dummy) \
-	: "r" (0x10000000) \
-	: "memory"); })
+#define __save_and_cli(x)    				\
+x = (__extension__ ({	unsigned long __dummy,__sr;	\
+	__asm__ __volatile__(                   	\
+		"stc	sr,%1\n\t" 			\
+		"or	%0,%1\n\t" 			\
+		"stc	sr,%0\n\t" 			\
+		"ldc	%1,sr"     			\
+		: "=r" (__sr), "=&r" (__dummy) 		\
+		: "0" (0x10000000) 			\
+		: "memory"); __sr; }))
 
 #define __restore_flags(x) \
 __asm__ __volatile__("ldc	%0,sr": /* no output */: "r" (x):"memory")
diff -u --recursive --new-file v2.3.23/linux/include/linux/acpi.h linux/include/linux/acpi.h
--- v2.3.23/linux/include/linux/acpi.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/acpi.h	Tue Oct 26 11:18:04 1999
@@ -24,9 +24,6 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
-/* /dev/acpi minor number */
-#define ACPI_MINOR_DEV 167
-
 /* RSDP location */
 #define ACPI_BIOS_ROM_BASE (0x0e0000)
 #define ACPI_BIOS_ROM_END  (0x100000)
@@ -40,7 +37,7 @@
 
 /* PM1_STS/EN flags */
 #define ACPI_TMR    0x0001
-#define ACPI_BM     0x0010
+#define ACPI_BM	    0x0010
 #define ACPI_GBL    0x0020
 #define ACPI_PWRBTN 0x0100
 #define ACPI_SLPBTN 0x0200
@@ -57,27 +54,33 @@
 #define ACPI_SLP_EN   0x2000
 
 /* PM_TMR masks */
-#define ACPI_TMR_MASK   0x00ffffff
+#define ACPI_TMR_MASK	0x00ffffff
 #define ACPI_TMR_HZ	3580000 /* 3.58 MHz */
 
 /* strangess to avoid integer overflow */
 #define ACPI_uS_TO_TMR_TICKS(val) \
   (((val) * (ACPI_TMR_HZ / 10000)) / 100)
 
+/* CPU cycles -> PM timer cycles, looks somewhat heuristic but
+   (ticks = 3/11 * CPU_MHz + 2) comes pretty close for my systems
+ */
+#define ACPI_CPU_TO_TMR_TICKS(cycles) \
+  ((cycles) / (3 * (loops_per_sec + 2500) / 500000 / 11 + 2))
+
 /* PM2_CNT flags */
 #define ACPI_ARB_DIS 0x01
 
 /* FACP flags */
-#define ACPI_WBINVD       0x00000001
+#define ACPI_WBINVD	  0x00000001
 #define ACPI_WBINVD_FLUSH 0x00000002
-#define ACPI_PROC_C1      0x00000004
-#define ACPI_P_LVL2_UP    0x00000008
-#define ACPI_PWR_BUTTON   0x00000010
-#define ACPI_SLP_BUTTON   0x00000020
-#define ACPI_FIX_RTC      0x00000040
-#define ACPI_RTC_64       0x00000080
+#define ACPI_PROC_C1	  0x00000004
+#define ACPI_P_LVL2_UP	  0x00000008
+#define ACPI_PWR_BUTTON	  0x00000010
+#define ACPI_SLP_BUTTON	  0x00000020
+#define ACPI_FIX_RTC	  0x00000040
+#define ACPI_RTC_64	  0x00000080
 #define ACPI_TMR_VAL_EXT  0x00000100
-#define ACPI_DCK_CAP      0x00000200
+#define ACPI_DCK_CAP	  0x00000200
 
 struct acpi_rsdp {
 	__u32 signature[2];
@@ -142,25 +145,65 @@
 	__u32 flags;
 };
 
-#define ACPI_FIND_TABLES	_IOR('A', 1, struct acpi_find_tables)
-#define ACPI_ENABLE_EVENT	_IOW('A', 2, struct acpi_enable_event)
-#define ACPI_WAIT_EVENT		_IOR('A', 3, struct acpi_wait_event)
-
-struct acpi_find_tables {
-	unsigned long facp; /* FACP physical address */
-	unsigned long dsdt; /* DSDT physical address */
-};
+/*
+ * Sysctl declarations
+ */
+
+enum
+{
+	CTL_ACPI = 10
+};
+
+enum
+{
+	ACPI_FACP = 1,
+	ACPI_DSDT,
+	ACPI_PM1_ENABLE,
+	ACPI_GPE_ENABLE,
+	ACPI_GPE_LEVEL,
+	ACPI_EVENT,
+	ACPI_P_LVL2,
+	ACPI_P_LVL3,
+	ACPI_P_LVL2_LAT,
+	ACPI_P_LVL3_LAT,
+};
+
+/*
+ * PIIX4-specific ACPI info (for systems with PIIX4 but no ACPI tables)
+ */
+
+#define ACPI_PIIX4_INT_MODEL	0x00
+#define ACPI_PIIX4_SCI_INT	0x0009
+
+#define ACPI_PIIX4_SMI_CMD	0x00b2
+#define ACPI_PIIX4_ACPI_ENABLE	0xf0
+#define ACPI_PIIX4_ACPI_DISABLE 0xf1
+#define ACPI_PIIX4_S4BIOS_REQ	0xf2
+
+#define ACPI_PIIX4_PM1_EVT	0x0000
+#define ACPI_PIIX4_PM1_CNT	0x0004
+#define	  ACPI_PIIX4_S0_MASK	(0x0005 << 10)
+#define	  ACPI_PIIX4_S1_MASK	(0x0004 << 10)
+#define	  ACPI_PIIX4_S2_MASK	(0x0003 << 10)
+#define	  ACPI_PIIX4_S3_MASK	(0x0002 << 10)
+#define	  ACPI_PIIX4_S4_MASK	(0x0001 << 10)
+#define	  ACPI_PIIX4_S5_MASK	(0x0000 << 10)
+#define ACPI_PIIX4_PM_TMR	0x0008
+#define ACPI_PIIX4_GPE0		0x000c
+#define ACPI_PIIX4_P_CNT	0x0010
+#define ACPI_PIIX4_P_LVL2	0x0014
+#define ACPI_PIIX4_P_LVL3	0x0015
+
+#define ACPI_PIIX4_PM1_EVT_LEN	0x04
+#define ACPI_PIIX4_PM1_CNT_LEN	0x02
+#define ACPI_PIIX4_PM_TM_LEN	0x04
+#define ACPI_PIIX4_GPE0_LEN	0x04
 
-struct acpi_enable_event {
-        __u32 pm1_enable; /* fixed events */
-        __u32 gpe_enable; /* general-purpose events (GPEs) */
-        __u32 gpe_level;  /* level-triggered GPEs */
-};
+#define ACPI_PIIX4_PM2_CNT	0x0022
+#define ACPI_PIIX4_PM2_CNT_LEN	0x01
 
-struct acpi_wait_event {
-        __u32 pm1_status; /* fixed events */
-        __u32 gpe_status; /* general-purpose events */
-};
+#define ACPI_PIIX4_PMREGMISC	0x80
+#define	  ACPI_PIIX4_PMIOSE	0x01
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.23/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.23/linux/include/linux/fs.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/fs.h	Wed Oct 27 16:17:08 1999
@@ -328,6 +328,11 @@
  */
 struct page;
 
+struct address_space {
+	struct list_head	pages;
+	unsigned long		nrpages;
+};
+
 struct inode {
 	struct list_head	i_hash;
 	struct list_head	i_list;
@@ -348,14 +353,13 @@
 	unsigned long		i_blksize;
 	unsigned long		i_blocks;
 	unsigned long		i_version;
-	unsigned long		i_nrpages;
 	struct semaphore	i_sem;
 	struct inode_operations	*i_op;
 	struct super_block	*i_sb;
 	wait_queue_head_t	i_wait;
 	struct file_lock	*i_flock;
 	struct vm_area_struct	*i_mmap;
-	struct list_head	i_pages;
+	struct address_space	i_data;	
 	spinlock_t		i_shared_lock;
 	struct dquot		*i_dquot[MAXQUOTAS];
 	struct pipe_inode_info	*i_pipe;
diff -u --recursive --new-file v2.3.23/linux/include/linux/i2o.h linux/include/linux/i2o.h
--- v2.3.23/linux/include/linux/i2o.h	Mon Oct  4 15:49:30 1999
+++ linux/include/linux/i2o.h	Mon Oct 25 20:49:42 1999
@@ -10,6 +10,209 @@
 /* How many controllers are we allowing */
 #define MAX_I2O_CONTROLLERS	32
 
+#include <linux/ioctl.h>
+
+/*
+ * I2O Control IOCTLs and structures
+ */
+#define I2O_MAGIC_NUMBER	'i'
+#define I2OGETIOPS		_IOR(I2O_MAGIC_NUMBER,0,u8[MAX_I2O_CONTROLLERS])
+#define I2OHRTGET		_IOWR(I2O_MAGIC_NUMBER,1,struct i2o_cmd_hrtlct)
+#define I2OLCTGET		_IOWR(I2O_MAGIC_NUMBER,2,struct i2o_cmd_hrtlct)
+#define I2OPARMSET		_IOWR(I2O_MAGIC_NUMBER,3,struct i2o_cmd_psetget)
+#define I2OPARMGET		_IOWR(I2O_MAGIC_NUMBER,4,struct i2o_cmd_psetget)
+#define I2OSWDL			_IOWR(I2O_MAGIC_NUMBER,5,struct i2o_sw_xfer)
+#define I2OSWUL			_IOWR(I2O_MAGIC_NUMBER,6,struct i2o_sw_xfer)
+#define I2OSWDEL		_IOWR(I2O_MAGIC_NUMBER,7,struct i2o_sw_xfer)
+#define I2OVALIDATE		_IOR(I2O_MAGIC_NUMBER,8,u32)
+#define I2OHTML			_IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
+
+/* On hold until we figure this out
+#define I2OEVTREG		_IO(I2O_MAGIC_NUMBER,10)
+#define I2OEVTCLR		_IO(I2O_MAGIC_NUMBER,11)
+#define I2OEVTGET		_IO(I2O_MAGIC_NUMBER,12)
+ */
+
+struct i2o_cmd_hrtlct
+{
+	unsigned int iop;	/* IOP unit number */
+	void *resbuf;		/* Buffer for result */
+	unsigned int *reslen;	/* Buffer length in bytes */
+};
+
+struct i2o_cmd_psetget
+{
+	unsigned int iop;	/* IOP unit number */
+	unsigned int tid;	/* Target device TID */
+	void *opbuf;		/* Operation List buffer */
+	unsigned int oplen;	/* Operation List buffer length in bytes */
+	void *resbuf;		/* Result List buffer */
+	unsigned int *reslen;	/* Result List buffer length in bytes */
+};
+
+struct i2o_sw_xfer
+{
+	unsigned int iop;	/* IOP unit number */
+	unsigned char flags;	/* Flags field */
+	unsigned char sw_type;	/* Software type */
+	unsigned int sw_id;	/* Software ID */
+	void *buf;		/* Pointer to software buffer */
+	unsigned int *swlen;	/* Length of software data */
+	unsigned int *maxfrag;	/* Maximum fragment count */
+        unsigned int *curfrag;	/* Current fragment count */
+};
+
+struct i2o_html
+{
+	unsigned int iop;	/* IOP unit number */
+	unsigned int tid;	/* Target device ID */
+	unsigned int page;	/* HTML page */
+	void *resbuf;		/* Buffer for reply HTML page */
+	unsigned int *reslen;	/* Length in bytes of reply buffer */
+	void *qbuf;		/* Pointer to HTTP query string */
+	unsigned int qlen;	/* Length in bytes of query string buffer */
+};
+
+
+/**************************************************************************
+ * HRT related constants and structures
+ **************************************************************************/
+#define I2O_BUS_LOCAL	0
+#define I2O_BUS_ISA	1
+#define I2O_BUS_EISA	2
+#define I2O_BUS_MCA	3
+#define I2O_BUS_PCI	4
+#define I2O_BUS_PCMCIA	5
+#define I2O_BUS_NUBUS	6
+#define I2O_BUS_CARDBUS	7
+#define I2O_BUS_UNKNOWN	0x80
+
+#ifndef __KERNEL__
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+#endif /* __KERNEL__ */
+
+typedef struct _i2o_pci_bus {
+	u8 PciFunctionNumber;
+	u8 PciDeviceNumber;
+	u8 PciBusNumber;
+	u8 reserved;
+	u16 PciVendorID;
+	u16 PciDeviceID;
+} i2o_pci_bus, *pi2o_pci_bus;
+
+typedef struct _i2o_local_bus {
+	u16 LbBaseIOPort;
+	u16 reserved;
+	u32 LbBaseMemoryAddress;
+} i2o_local_bus, *pi2o_local_bus;
+
+typedef struct _i2o_isa_bus {
+	u16 IsaBaseIOPort;
+	u8 CSN;
+	u8 reserved;
+	u32 IsaBaseMemoryAddress;
+} i2o_isa_bus, *pi2o_isa_bus;
+
+typedef struct _i2o_eisa_bus_info {
+	u16 EisaBaseIOPort;
+	u8 reserved;
+	u8 EisaSlotNumber;
+	u32 EisaBaseMemoryAddress;
+} i2o_eisa_bus, *pi2o_eisa_bus;
+
+typedef struct _i2o_mca_bus {
+	u16 McaBaseIOPort;
+	u8 reserved;
+	u8 McaSlotNumber;
+	u32 McaBaseMemoryAddress;
+} i2o_mca_bus, *pi2o_mca_bus;
+
+typedef struct _i2o_other_bus {
+	u16 BaseIOPort;
+	u16 reserved;
+	u32 BaseMemoryAddress;
+} i2o_other_bus, *pi2o_other_bus;
+
+typedef struct _i2o_hrt_entry {
+	u32 adapter_id;
+	u32 parent_tid:12;
+	u32 state:4;
+	u32 bus_num:8;
+	u32 bus_type:8;
+	union {
+		i2o_pci_bus pci_bus;
+		i2o_local_bus local_bus;
+		i2o_isa_bus isa_bus;
+		i2o_eisa_bus eisa_bus;
+		i2o_mca_bus mca_bus;
+		i2o_other_bus other_bus;
+	} bus;
+} i2o_hrt_entry, *pi2o_hrt_entry;
+
+typedef struct _i2o_hrt {
+	u16 num_entries;
+	u8 entry_len;
+	u8 hrt_version;
+	u32 change_ind;
+	i2o_hrt_entry hrt_entry[1];
+} i2o_hrt, *pi2o_hrt;
+
+typedef struct _i2o_lct_entry {
+	u32 entry_size:16;
+	u32 tid:12;
+	u32 reserved:4;
+	u32 change_ind;
+	u32 device_flags;
+	u32 class_id:12;
+	u32 version:4;
+	u32 vendor_id:16;
+	u32 sub_class;
+	u32 user_tid:12;
+	u32 parent_tid:12;
+	u32 bios_info:8;
+	u8 identity_tag[8];
+	u32 event_capabilities;
+} i2o_lct_entry, *pi2o_lct_entry;
+
+typedef struct _i2o_lct {
+	u32 table_size:16;
+	u32 boot_tid:12;
+	u32 lct_ver:4;
+	u32 iop_flags;
+	u32 current_change_ind;
+	i2o_lct_entry lct_entry[1];
+} i2o_lct, *pi2o_lct;
+
+typedef struct _i2o_status_block {
+	u16 org_id;
+	u16 reserved;
+	u16 iop_id:12;
+	u16 reserved1:4;
+	u16 host_unit_id;
+	u16 segment_number:12;
+	u16 i2o_version:4;
+	u8 iop_state;
+	u8 msg_type;
+	u16 inbound_frame_size;
+	u8 init_code;	
+	u8 reserved2;
+	u32 max_inbound_frames;
+	u32 max_outbound_frames;
+	char product_id[24];	
+	u32 expected_lct_size;
+	u32 iop_capabilities;
+	u32 desired_mem_size;
+	u32 current_mem_size;
+	u32 current_mem_base;
+	u32 desired_io_size;
+	u32 current_io_size;
+	u32 current_io_base;
+	u32 reserved3:24;
+	u32 cmd_status:8;
+} i2o_status_block, *pi2o_status_block;
+ 
 
 
 #ifdef __KERNEL__   /* ioctl stuff only thing exported to users */
@@ -43,13 +246,11 @@
  
 struct i2o_device
 {
-	int class;		/* Block, Net, SCSI etc (from spec) */
-	int subclass;		/* eth, fddi, tr etc (from spec)   */
-	int id;			/* I2O ID assigned by the controller */
-	int parent;		/* Parent device */
-	int flags;		/* Control flags */
+	pi2o_lct_entry lct_data;/* Device LCT information */
+	u32 flags;		
 	int i2oversion;		/* I2O version supported. Actually there
 				 * should be high and low version */
+
 	struct proc_dir_entry* proc_entry;	/* /proc dir */
 
 	/* Primary user */
@@ -70,6 +271,9 @@
 struct i2o_pci
 {
 	int irq;
+#ifdef CONFIG_MTRR
+	int mtrr_reg;
+#endif
 };
 
 
@@ -81,8 +285,6 @@
 {
 	char name[16];
 	int unit;
-	int status;				/* I2O status */
-	int i2oversion;
 	int type;
 
 #define I2O_TYPE_PCI		0x01		/* PCI I2O controller */	
@@ -94,10 +296,14 @@
 	volatile u32 *post_port;		/* Messaging ports */
 	volatile u32 *reply_port;
 	volatile u32 *irq_mask;			/* Interrupt port */
-	u32 *lct;
-	u32 *hrt;
+
+	pi2o_status_block status_block;		/* IOP status block */
+	pi2o_lct lct;
+	pi2o_hrt hrt;
+
 	u32 mem_offset;				/* MFA offset */
 	u32 mem_phys;				/* MFA physical */
+
 	u32 priv_mem;
 	u32 priv_mem_size;
 	u32 priv_io;
@@ -115,6 +321,9 @@
 	int (*bind)(struct i2o_controller *, struct i2o_device *);	
 	/* Bus specific initiator */
 	int (*unbind)(struct i2o_controller *, struct i2o_device *);
+	/* Bus specific enable/disable */
+	void (*bus_enable)(struct i2o_controller *c);
+	void (*bus_disable)(struct i2o_controller *c);
 
 	void *page_frame;		/* Message buffers */
 	int inbound_size;		/* Inbound queue size */
@@ -144,8 +353,7 @@
 {
 	int	(*install)(struct i2o_controller *);
 	int	(*activate)(struct i2o_controller *);
-	struct i2o_controller*	
-		(*find)(int);
+	struct  i2o_controller*	(*find)(int);
 	void	(*unlock)(struct i2o_controller *);
 	void	(*run_queue)(struct i2o_controller *c);
 	int	(*delete)(struct i2o_controller *);
@@ -153,9 +361,40 @@
 #endif
 
 /*
- *	Messenger inlines
+ * I2O System table entry
  */
+struct i2o_sys_tbl_entry
+{
+	u16	org_id;
+	u16	reserved1;
+	u32	iop_id:12;
+	u32	reserved2:20;
+	u16	seg_num:12;
+	u16 	i2o_version:4;
+	u8 	iop_state;
+	u8 	msg_type;
+	u16	frame_size;
+	u16	reserved3;
+	u32	last_changed;
+	u32	iop_capabilities;
+	u32	inbound_low;
+	u32	inbound_high;
+};
+
+struct i2o_sys_tbl
+{
+	u8 	num_entries;
+	u8 	version;
+	u16 	reserved1;
+	u32	change_ind;
+	u32	reserved2;
+	u32	reserved3;
+	struct i2o_sys_tbl_entry iops[0];
+};	
 
+/*
+ *	Messenger inlines
+ */
 extern inline u32 I2O_POST_READ32(struct i2o_controller *c)
 {
 	return *c->post_port;
@@ -211,6 +450,7 @@
 extern int i2o_activate_controller(struct i2o_controller *);
 extern void i2o_unlock_controller(struct i2o_controller *);
 extern struct i2o_controller *i2o_find_controller(int);
+extern int i2o_status_get(struct i2o_controller *);
 extern int i2o_num_controllers;
 
 extern int i2o_install_handler(struct i2o_handler *);
@@ -221,24 +461,24 @@
 extern int i2o_claim_device(struct i2o_device *, struct i2o_handler *, u32);
 extern int i2o_release_device(struct i2o_device *, struct i2o_handler *, u32);
 
-extern int i2o_post_this(struct i2o_controller *, int, u32 *, int);
-extern int i2o_post_wait(struct i2o_controller *, int, u32 *, int, int *, int);
+extern int i2o_post_this(struct i2o_controller *, u32 *, int);
+extern int i2o_post_wait(struct i2o_controller *, u32 *, int, int);
 extern int i2o_issue_claim(struct i2o_controller *, int, int, int, int *, u32);
-extern int i2o_issue_params(int, struct i2o_controller *, int, int, void *,
-			    int, void *, int, int *); 
+extern int i2o_issue_params(int, struct i2o_controller *, int, void *,
+			    int, void *, int); 
 
-extern int i2o_query_scalar(struct i2o_controller *, int, int, int, int, 
-			void *, int, int *);
-extern int i2o_set_scalar(struct i2o_controller *, int, int, int, int, 
-			void *, int, int *);
-
-extern int i2o_query_table(int, struct i2o_controller *, int, int, int, int, 
-			void *, int, void *, int, int *);
-extern int i2o_clear_table(struct i2o_controller *, int, int, int, int *); 
-extern int i2o_row_add_table(struct i2o_controller *, int, int, int, int,
-			void *, int, int *);
-extern int i2o_row_delete_table(struct i2o_controller *, int, int, int, int,
-			void *, int, int *);
+extern int i2o_query_scalar(struct i2o_controller *, int, int, int, 
+			void *, int);
+extern int i2o_set_scalar(struct i2o_controller *, int, int, int, 
+			void *, int);
+
+extern int i2o_query_table(int, struct i2o_controller *, int, int, int, 
+			void *, int, void *, int);
+extern int i2o_clear_table(struct i2o_controller *, int, int); 
+extern int i2o_row_add_table(struct i2o_controller *, int, int, int,
+			void *, int);
+extern int i2o_row_delete_table(struct i2o_controller *, int, int, int,
+			void *, int);
 
 extern void i2o_run_queue(struct i2o_controller *);
 extern void i2o_report_status(const char *, const char *, u32 *);
@@ -551,182 +791,9 @@
 
 #define MSG_POOL_SIZE		16384
 
-#define I2O_POST_WAIT_OK	1
+#define I2O_POST_WAIT_OK	0
 #define I2O_POST_WAIT_TIMEOUT	-ETIMEDOUT
 
 #endif /* __KERNEL__ */
 
-#include <linux/ioctl.h>
-
-/*
- * I2O Control IOCTLs and structures
- */
-#define I2O_MAGIC_NUMBER	'i'
-#define I2OGETIOPS		_IOR(I2O_MAGIC_NUMBER,0,u8[MAX_I2O_CONTROLLERS])
-#define I2OHRTGET		_IOWR(I2O_MAGIC_NUMBER,1,struct i2o_cmd_hrtlct)
-#define I2OLCTGET		_IOWR(I2O_MAGIC_NUMBER,2,struct i2o_cmd_hrtlct)
-#define I2OPARMSET		_IOWR(I2O_MAGIC_NUMBER,3,struct i2o_cmd_psetget)
-#define I2OPARMGET		_IOWR(I2O_MAGIC_NUMBER,4,struct i2o_cmd_psetget)
-#define I2OSWDL			_IOWR(I2O_MAGIC_NUMBER,5,struct i2o_sw_xfer)
-#define I2OSWUL			_IOWR(I2O_MAGIC_NUMBER,6,struct i2o_sw_xfer)
-#define I2OSWDEL		_IOWR(I2O_MAGIC_NUMBER,7,struct i2o_sw_xfer)
-#define I2OVALIDATE		_IOR(I2O_MAGIC_NUMBER,8,u32)
-#define I2OHTML			_IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
-
-/* On hold until we figure this out
-#define I2OEVTREG		_IO(I2O_MAGIC_NUMBER,10)
-#define I2OEVTCLR		_IO(I2O_MAGIC_NUMBER,11)
-#define I2OEVTGET		_IO(I2O_MAGIC_NUMBER,12)
- */
-
-struct i2o_cmd_hrtlct
-{
-	unsigned int iop;	/* IOP unit number */
-	void *resbuf;		/* Buffer for result */
-	unsigned int *reslen;	/* Buffer length in bytes */
-};
-
-struct i2o_cmd_psetget
-{
-	unsigned int iop;	/* IOP unit number */
-	unsigned int tid;	/* Target device TID */
-	void *opbuf;		/* Operation List buffer */
-	unsigned int oplen;	/* Operation List buffer length in bytes */
-	void *resbuf;		/* Result List buffer */
-	unsigned int *reslen;	/* Result List buffer length in bytes */
-};
-
-struct i2o_sw_xfer
-{
-	unsigned int iop;	/* IOP unit number */
-	unsigned char flags;	/* Flags field */
-	unsigned char sw_type;	/* Software type */
-	unsigned int sw_id;	/* Software ID */
-	void *buf;		/* Pointer to software buffer */
-	unsigned int *swlen;	/* Length of software data */
-	unsigned int *maxfrag;	/* Maximum fragment count */
-        unsigned int *curfrag;	/* Current fragment count */
-};
-
-struct i2o_html
-{
-	unsigned int iop;	/* IOP unit number */
-	unsigned int tid;	/* Target device ID */
-	unsigned int page;	/* HTML page */
-	void *resbuf;		/* Buffer for reply HTML page */
-	unsigned int *reslen;	/* Length in bytes of reply buffer */
-	void *qbuf;		/* Pointer to HTTP query string */
-	unsigned int qlen;	/* Length in bytes of query string buffer */
-};
-
-
-/**************************************************************************
- * HRT related constants and structures
- **************************************************************************/
-#define I2O_BUS_LOCAL	0
-#define I2O_BUS_ISA	1
-#define I2O_BUS_EISA	2
-#define I2O_BUS_MCA	3
-#define I2O_BUS_PCI	4
-#define I2O_BUS_PCMCIA	5
-#define I2O_BUS_NUBUS	6
-#define I2O_BUS_CARDBUS	7
-#define I2O_BUS_UNKNOWN	0x80
-
-#ifndef __KERNEL__
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-#endif /* __KERNEL__ */
-
-typedef struct _i2o_pci_bus {
-	u8 PciFunctionNumber;
-	u8 PciDeviceNumber;
-	u8 PciBusNumber;
-	u8 reserved;
-	u16 PciVendorID;
-	u16 PciDeviceID;
-} i2o_pci_bus, *pi2o_pci_bus;
-
-typedef struct _i2o_local_bus {
-	u16 LbBaseIOPort;
-	u16 reserved;
-	u32 LbBaseMemoryAddress;
-} i2o_local_bus, *pi2o_local_bus;
-
-typedef struct _i2o_isa_bus {
-	u16 IsaBaseIOPort;
-	u8 CSN;
-	u8 reserved;
-	u32 IsaBaseMemoryAddress;
-} i2o_isa_bus, *pi2o_isa_bus;
-
-typedef struct _i2o_eisa_bus_info {
-	u16 EisaBaseIOPort;
-	u8 reserved;
-	u8 EisaSlotNumber;
-	u32 EisaBaseMemoryAddress;
-} i2o_eisa_bus, *pi2o_eisa_bus;
-
-typedef struct _i2o_mca_bus {
-	u16 McaBaseIOPort;
-	u8 reserved;
-	u8 McaSlotNumber;
-	u32 McaBaseMemoryAddress;
-} i2o_mca_bus, *pi2o_mca_bus;
-
-typedef struct _i2o_other_bus {
-	u16 BaseIOPort;
-	u16 reserved;
-	u32 BaseMemoryAddress;
-} i2o_other_bus, *pi2o_other_bus;
-
-typedef struct _i2o_hrt_entry {
-	u32 adapter_id;
-	u32 parent_tid:12;
-	u32 state:4;
-	u32 bus_num:8;
-	u32 bus_type:8;
-	union {
-		i2o_pci_bus pci_bus;
-		i2o_local_bus local_bus;
-		i2o_isa_bus isa_bus;
-		i2o_eisa_bus eisa_bus;
-		i2o_mca_bus mca_bus;
-		i2o_other_bus other_bus;
-	} bus;
-} i2o_hrt_entry, *pi2o_hrt_entry;
-
-typedef struct _i2o_hrt {
-	u16 num_entries;
-	u8 entry_len;
-	u8 hrt_version;
-	u32 change_ind;
-	i2o_hrt_entry hrt_entry[1];
-} i2o_hrt, *pi2o_hrt;
-
-typedef struct _i2o_lct_entry {
-	u32 entry_size:16;
-	u32 tid:12;
-	u32 reserved:4;
-	u32 change_ind;
-	u32 device_flags;
-	u32 class_id;
-	u32 sub_class;
-	u32 user_tid:12;
-	u32 parent_tid:12;
-	u32 bios_info:8;
-	u8 identity_tag[8];
-	u32 event_capabilities;
-} i2o_lct_entry, *pi2o_lct_entry;
-
-typedef struct _i2o_lct {
-	u32 table_size:16;
-	u32 boot_tid:12;
-	u32 lct_ver:4;
-	u32 iop_flags;
-	u32 current_change_ind;
-	i2o_lct_entry lct_entry[1];
-} i2o_lct, *pi2o_lct;
-
-#endif
+#endif /* _I2O_H */
diff -u --recursive --new-file v2.3.23/linux/include/linux/irda.h linux/include/linux/irda.h
--- v2.3.23/linux/include/linux/irda.h	Mon Oct  4 15:49:30 1999
+++ linux/include/linux/irda.h	Mon Oct 25 20:49:42 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irda.h
- * Version:       1.0
- * Description:   Exported IrDA sockets interface
+ * Version:       
+ * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Mar  8 14:06:12 1999
- * Modified at:   Mon Sep 27 12:11:49 1999
+ * Modified at:   Sun Oct 10 23:00:59 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -19,7 +19,7 @@
  *     Neither Dag Brattli nor University of Tromsø admit liability nor
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
- *     
+ *
  ********************************************************************/
 
 #ifndef KERNEL_IRDA_H
@@ -44,17 +44,28 @@
 #define HINT_OBEX        0x20
 
 /* IrLMP character code values */
-#define CS_ASCII       0x00
-#define	CS_ISO_8859_1  0x01
-#define	CS_ISO_8859_2  0x02
-#define	CS_ISO_8859_3  0x03
-#define	CS_ISO_8859_4  0x04
-#define	CS_ISO_8859_5  0x05
-#define	CS_ISO_8859_6  0x06
-#define	CS_ISO_8859_7  0x07
-#define	CS_ISO_8859_8  0x08
-#define	CS_ISO_8859_9  0x09
-#define CS_UNICODE     0xff
+#define CS_ASCII         0x00
+#define	CS_ISO_8859_1    0x01
+#define	CS_ISO_8859_2    0x02
+#define	CS_ISO_8859_3    0x03
+#define	CS_ISO_8859_4    0x04
+#define	CS_ISO_8859_5    0x05
+#define	CS_ISO_8859_6    0x06
+#define	CS_ISO_8859_7    0x07
+#define	CS_ISO_8859_8    0x08
+#define	CS_ISO_8859_9    0x09
+#define CS_UNICODE       0xff
+
+/* These are the currently known dongles */
+typedef enum {
+	IRDA_TEKRAM_DONGLE,
+	IRDA_ESI_DONGLE,
+	IRDA_ACTISYS_DONGLE,
+	IRDA_ACTISYS_PLUS_DONGLE,
+	IRDA_GIRBIL_DONGLE,
+	IRDA_LITELINK_DONGLE,
+	IRDA_AIRPORT_DONGLE,
+} IRDA_DONGLE;
 
 #define SOL_IRLMP      266 /* Same as SOL_IRDA for now */
 #define SOL_IRTTP      266 /* Same as SOL_IRDA for now */
@@ -68,12 +79,12 @@
 #define IRTTP_QOS_GET            6
 #define IRTTP_MAX_SDU_SIZE       7
 
-#define IAS_MAX_STRING           256
-#define IAS_MAX_OCTET_STRING     1024
-#define IAS_MAX_CLASSNAME        64
-#define IAS_MAX_ATTRIBNAME       256
+#define IAS_MAX_STRING         256
+#define IAS_MAX_OCTET_STRING  1024
+#define IAS_MAX_CLASSNAME       64
+#define IAS_MAX_ATTRIBNAME     256
 
-#define LSAP_ANY                 0xff
+#define LSAP_ANY               0xff
 
 struct sockaddr_irda {
 	sa_family_t   sir_family;   /* AF_IRDA */
@@ -112,6 +123,61 @@
 		} irda_attrib_string;
 	} attribute;
 };
+
+/* Some private IOCTL's (max 16) */
+#define SIOCSDONGLE    (SIOCDEVPRIVATE + 0)
+#define SIOCGDONGLE    (SIOCDEVPRIVATE + 1)
+#define SIOCSBANDWIDTH (SIOCDEVPRIVATE + 2)
+#define SIOCSMEDIABUSY (SIOCDEVPRIVATE + 3)
+#define SIOCGMEDIABUSY (SIOCDEVPRIVATE + 4)
+#define SIOCGRECEIVING (SIOCDEVPRIVATE + 5)
+#define SIOCSRAWMODE   (SIOCDEVPRIVATE + 6)
+#define SIOCSDTRRTS    (SIOCDEVPRIVATE + 7)
+#define SIOCGQOS       (SIOCDEVPRIVATE + 8)
+
+/* No reason to include <linux/if.h> just because of this one ;-) */
+#define IRNAMSIZ 16 
+
+/* IrDA quality of service information (must not exceed 16 bytes) */
+struct if_irda_qos {
+	unsigned long  baudrate;
+	unsigned short data_size;
+	unsigned short window_size;
+	unsigned short min_turn_time;
+	unsigned short max_turn_time;
+	unsigned char  add_bofs;
+	unsigned char  link_disc;
+};
+
+/* For setting RTS and DTR lines of a dongle */
+struct if_irda_line {
+	unsigned char dtr;
+	unsigned char rts;
+};
+
+/* IrDA interface configuration (data part must not exceed 16 bytes) */
+struct if_irda_req {
+	union {
+		char ifrn_name[IRNAMSIZ];  /* if name, e.g. "irda0" */
+	} ifr_ifrn;
+	
+	/* Data part */
+	union {
+		struct if_irda_line ifru_line;
+		struct if_irda_qos  ifru_qos;
+		unsigned short      ifru_flags;
+		unsigned int        ifru_receiving;
+		unsigned int        ifru_raw_mode;
+		unsigned int        ifru_dongle;
+	} ifr_ifru;
+};
+
+#define ifr_baudrate  ifr_ifru.ifru_qos.baudrate
+#define ifr_receiving ifr_ifru.ifru_receiving 
+#define ifr_dongle    ifr_ifru.ifru_dongle
+#define ifr_raw_mode  ifr_ifru.ifru_raw_mode
+#define ifr_dtr       ifr_ifru.ifru_line.dtr
+#define ifr_rts       ifr_ifru.ifru_line.rts
 
 #endif /* KERNEL_IRDA_H */
 
diff -u --recursive --new-file v2.3.23/linux/include/linux/major.h linux/include/linux/major.h
--- v2.3.23/linux/include/linux/major.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/major.h	Tue Oct 26 15:02:14 1999
@@ -117,6 +117,7 @@
 
 #define AURORA_MAJOR 79
 
+#define RTF_MAJOR	150
 #define RAW_MAJOR	162
 
 #define UNIX98_PTY_MASTER_MAJOR	128
diff -u --recursive --new-file v2.3.23/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.23/linux/include/linux/mm.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/mm.h	Wed Oct 27 16:17:14 1999
@@ -106,7 +106,7 @@
 	void (*advise)(struct vm_area_struct *area, unsigned long, size_t, unsigned int advise);
 	struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access);
 	struct page * (*wppage)(struct vm_area_struct * area, unsigned long address, struct page * page);
-	int (*swapout)(struct vm_area_struct *, struct page *);
+	int (*swapout)(struct page *, struct file *);
 };
 
 /*
@@ -120,7 +120,7 @@
 typedef struct page {
 	/* these must be first (free area handling) */
 	struct list_head list;
-	struct inode *inode;
+	struct address_space *mapping;
 	unsigned long offset;
 	struct page *next_hash;
 	atomic_t count;
@@ -129,17 +129,13 @@
 	wait_queue_head_t wait;
 	struct page **pprev_hash;
 	struct buffer_head * buffers;
-	void *owner; /* temporary debugging check */
 } mem_map_t;
 
-#define get_page(p) do { atomic_inc(&(p)->count); \
-						} while (0)
-#define put_page(p) __free_page(p)
-#define put_page_testzero(p) ({ int __ret = atomic_dec_and_test(&(p)->count);\
-				__ret; })
-#define page_count(p) atomic_read(&(p)->count)
-#define set_page_count(p,v) do { atomic_set(&(p)->count, v); \
-				} while (0)
+#define get_page(p)		atomic_inc(&(p)->count)
+#define put_page(p)		__free_page(p)
+#define put_page_testzero(p) 	atomic_dec_and_test(&(p)->count)
+#define page_count(p)		atomic_read(&(p)->count)
+#define set_page_count(p,v) 	atomic_set(&(p)->count, v)
 
 /* Page flag bit values */
 #define PG_locked		 0
@@ -158,54 +154,44 @@
 
 
 /* Make it prettier to test the above... */
-#define Page_Uptodate(page)	(test_bit(PG_uptodate, &(page)->flags))
-#define SetPageUptodate(page)	do { set_bit(PG_uptodate, &(page)->flags); \
-					} while (0)
-#define ClearPageUptodate(page)	do { clear_bit(PG_uptodate, &(page)->flags); \
-					} while (0)
-#define PageLocked(page)	(test_bit(PG_locked, &(page)->flags))
-#define LockPage(page)		\
-	do { int _ret = test_and_set_bit(PG_locked, &(page)->flags); \
-	if (_ret) PAGE_BUG(page); \
-	if (page->owner) PAGE_BUG(page); \
-	page->owner = current; } while (0)
-#define TryLockPage(page)	({ int _ret = test_and_set_bit(PG_locked, &(page)->flags); \
-				if (!_ret) page->owner = current; _ret; })
+#define Page_Uptodate(page)	test_bit(PG_uptodate, &(page)->flags)
+#define SetPageUptodate(page)	set_bit(PG_uptodate, &(page)->flags)
+#define ClearPageUptodate(page)	clear_bit(PG_uptodate, &(page)->flags)
+#define PageLocked(page)	test_bit(PG_locked, &(page)->flags)
+#define LockPage(page)		set_bit(PG_locked, &(page)->flags)
+#define TryLockPage(page)	test_and_set_bit(PG_locked, &(page)->flags)
 #define UnlockPage(page)	do { \
-					if (page->owner != current) { \
-BUG(); } page->owner = 0; \
-if (!test_and_clear_bit(PG_locked, &(page)->flags)) { \
-			PAGE_BUG(page); } wake_up(&page->wait); } while (0)
-#define PageError(page)		(test_bit(PG_error, &(page)->flags))
-#define SetPageError(page)	({ int _ret = test_and_set_bit(PG_error, &(page)->flags); _ret; })
-#define ClearPageError(page)	do { if (!test_and_clear_bit(PG_error, &(page)->flags)) BUG(); } while (0)
-#define PageReferenced(page)	(test_bit(PG_referenced, &(page)->flags))
-#define PageDecrAfter(page)	(test_bit(PG_decr_after, &(page)->flags))
-#define PageDMA(page)		(test_bit(PG_DMA, &(page)->flags))
-#define PageSlab(page)		(test_bit(PG_slab, &(page)->flags))
-#define PageSwapCache(page)	(test_bit(PG_swap_cache, &(page)->flags))
-#define PageReserved(page)	(test_bit(PG_reserved, &(page)->flags))
-
-#define PageSetSlab(page)	(set_bit(PG_slab, &(page)->flags))
-#define PageSetSwapCache(page)	(set_bit(PG_swap_cache, &(page)->flags))
+					clear_bit(PG_locked, &(page)->flags); \
+					wake_up(&page->wait); \
+				} while (0)
+#define PageError(page)		test_bit(PG_error, &(page)->flags)
+#define SetPageError(page)	test_and_set_bit(PG_error, &(page)->flags)
+#define ClearPageError(page)	clear_bit(PG_error, &(page)->flags)
+#define PageReferenced(page)	test_bit(PG_referenced, &(page)->flags)
+#define PageDecrAfter(page)	test_bit(PG_decr_after, &(page)->flags)
+#define PageDMA(page)		test_bit(PG_DMA, &(page)->flags)
+#define PageSlab(page)		test_bit(PG_slab, &(page)->flags)
+#define PageSwapCache(page)	test_bit(PG_swap_cache, &(page)->flags)
+#define PageReserved(page)	test_bit(PG_reserved, &(page)->flags)
+
+#define PageSetSlab(page)	set_bit(PG_slab, &(page)->flags)
+#define PageSetSwapCache(page)	set_bit(PG_swap_cache, &(page)->flags)
+
+#define PageTestandSetSwapCache(page)	test_and_set_bit(PG_swap_cache, &(page)->flags)
 
-#define PageTestandSetSwapCache(page)	\
-			(test_and_set_bit(PG_swap_cache, &(page)->flags))
+#define PageClearSlab(page)		clear_bit(PG_slab, &(page)->flags)
+#define PageClearSwapCache(page)	clear_bit(PG_swap_cache, &(page)->flags)
 
-#define PageClearSlab(page)	(clear_bit(PG_slab, &(page)->flags))
-#define PageClearSwapCache(page)(clear_bit(PG_swap_cache, &(page)->flags))
+#define PageTestandClearSwapCache(page)	test_and_clear_bit(PG_swap_cache, &(page)->flags)
 
-#define PageTestandClearSwapCache(page)	\
-			(test_and_clear_bit(PG_swap_cache, &(page)->flags))
 #ifdef CONFIG_HIGHMEM
-#define PageHighMem(page)	(test_bit(PG_highmem, &(page)->flags))
+#define PageHighMem(page)		test_bit(PG_highmem, &(page)->flags)
 #else
-#define PageHighMem(page) 0 /* needed to optimize away at compile time */
+#define PageHighMem(page)		0 /* needed to optimize away at compile time */
 #endif
 
-#define SetPageReserved(page)	do { set_bit(PG_reserved, &(page)->flags); \
-					} while (0)
-#define ClearPageReserved(page)	do { test_and_clear_bit(PG_reserved, &(page)->flags); } while (0)
+#define SetPageReserved(page)		set_bit(PG_reserved, &(page)->flags)
+#define ClearPageReserved(page)		clear_bit(PG_reserved, &(page)->flags)
 
 
 /*
@@ -359,7 +345,6 @@
 extern unsigned long page_unuse(struct page *);
 extern int shrink_mmap(int, int);
 extern void truncate_inode_pages(struct inode *, unsigned long);
-extern unsigned long get_cached_page(struct inode *, unsigned long, int);
 extern void put_cached_page(unsigned long);
 
 /*
@@ -405,10 +390,8 @@
 
 	address &= PAGE_MASK;
 	grow = vma->vm_start - address;
-	if (vma->vm_end - address
-	    > (unsigned long) current->rlim[RLIMIT_STACK].rlim_cur ||
-	    (vma->vm_mm->total_vm << PAGE_SHIFT) + grow
-	    > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur)
+	if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
+	    (vma->vm_mm->total_vm << PAGE_SHIFT) + grow > current->rlim[RLIMIT_AS].rlim_cur)
 		return -ENOMEM;
 	vma->vm_start = address;
 	vma->vm_offset -= grow;
diff -u --recursive --new-file v2.3.23/linux/include/linux/nfsd/export.h linux/include/linux/nfsd/export.h
--- v2.3.23/linux/include/linux/nfsd/export.h	Wed Aug 18 16:44:13 1999
+++ linux/include/linux/nfsd/export.h	Wed Oct 27 16:17:34 1999
@@ -34,8 +34,9 @@
 #define NFSEXP_UIDMAP		0x0040
 #define NFSEXP_KERBEROS		0x0080		/* not available */
 #define NFSEXP_SUNSECURE	0x0100
-#define NFSEXP_CROSSMNT		0x0200		/* not available */
-#define NFSEXP_ALLFLAGS		0x03FF
+#define NFSEXP_CROSSMNT		0x0200
+#define NFSEXP_NOSUBTREECHECK	0x0400
+#define NFSEXP_ALLFLAGS		0x07FF
 
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.3.23/linux/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h
--- v2.3.23/linux/include/linux/nfsd/nfsfh.h	Wed Aug 18 16:44:11 1999
+++ linux/include/linux/nfsd/nfsfh.h	Wed Oct 27 16:17:37 1999
@@ -109,9 +109,6 @@
 void	nfsd_fh_init(void);
 void	nfsd_fh_free(void);
 
-void	expire_all(void);
-void	expire_by_dentry(struct dentry *);
-
 static __inline__ struct svc_fh *
 fh_copy(struct svc_fh *dst, struct svc_fh *src)
 {
diff -u --recursive --new-file v2.3.23/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.3.23/linux/include/linux/pagemap.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/pagemap.h	Wed Oct 27 16:17:18 1999
@@ -59,10 +59,13 @@
  * and get a reasonable hash by knowing roughly how the
  * inode pointer and offsets are distributed (ie, we
  * roughly know which bits are "significant")
+ *
+ * For the time being it will work for struct address_space too (most of
+ * them sitting inside the inodes). We might want to change it later.
  */
-extern inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset)
+extern inline unsigned long _page_hashfn(struct address_space * mapping, unsigned long offset)
 {
-#define i (((unsigned long) inode)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))
+#define i (((unsigned long) mapping)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))
 #define o (offset >> PAGE_SHIFT)
 #define s(x) ((x)+((x)>>PAGE_HASH_BITS))
 	return s(i+o) & (PAGE_HASH_SIZE-1);
@@ -71,33 +74,33 @@
 #undef s
 }
 
-#define page_hash(inode,offset) (page_hash_table+_page_hashfn(inode,offset))
+#define page_hash(mapping,offset) (page_hash_table+_page_hashfn(mapping,offset))
 
-extern struct page * __find_get_page (struct inode * inode,
+extern struct page * __find_get_page (struct address_space *mapping,
 				unsigned long offset, struct page **hash);
-#define find_get_page(inode, offset) \
-		__find_get_page(inode, offset, page_hash(inode, offset))
-extern struct page * __find_lock_page (struct inode * inode,
+#define find_get_page(mapping, offset) \
+		__find_get_page(mapping, offset, page_hash(mapping, offset))
+extern struct page * __find_lock_page (struct address_space * mapping,
 				unsigned long offset, struct page **hash);
 extern void lock_page(struct page *page);
-#define find_lock_page(inode, offset) \
-		__find_lock_page(inode, offset, page_hash(inode, offset))
+#define find_lock_page(mapping, offset) \
+		__find_lock_page(mapping, offset, page_hash(mapping, offset))
 
 extern void __add_page_to_hash_queue(struct page * page, struct page **p);
 
-extern void add_to_page_cache(struct page * page, struct inode * inode, unsigned long offset);
-extern int add_to_page_cache_unique(struct page * page, struct inode * inode, unsigned long offset, struct page **hash);
+extern void add_to_page_cache(struct page * page, struct address_space *mapping, unsigned long offset);
+extern int add_to_page_cache_unique(struct page * page, struct address_space *mapping, unsigned long offset, struct page **hash);
 
 extern inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long offset)
 {
-	__add_page_to_hash_queue(page, page_hash(inode,offset));
+	__add_page_to_hash_queue(page, page_hash(&inode->i_data,offset));
 }
 
-extern inline void add_page_to_inode_queue(struct inode * inode, struct page * page)
+extern inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
 {
-	struct list_head *head = &inode->i_pages;
+	struct list_head *head = &mapping->pages;
 
-	if (!inode->i_nrpages++) {
+	if (!mapping->nrpages++) {
 		if (!list_empty(head))
 			BUG();
 	} else {
@@ -105,14 +108,14 @@
 			BUG();
 	}
 	list_add(&page->list, head);
-	page->inode = inode;
+	page->mapping = mapping;
 }
 
 extern inline void remove_page_from_inode_queue(struct page * page)
 {
-	struct inode * inode = page->inode;
+	struct address_space * mapping = page->mapping;
 
-	inode->i_nrpages--;
+	mapping->nrpages--;
 	list_del(&page->list);
 }
 
diff -u --recursive --new-file v2.3.23/linux/include/linux/resource.h linux/include/linux/resource.h
--- v2.3.23/linux/include/linux/resource.h	Wed Jul 28 10:50:23 1999
+++ linux/include/linux/resource.h	Mon Oct 25 11:19:39 1999
@@ -37,11 +37,16 @@
 	long	ru_nivcsw;		/* involuntary " */
 };
 
-#define RLIM_INFINITY	((long)(~0UL>>1))
+/*
+ * SuS says limits have to be unsigned.
+ *
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY	(~0UL)
 
 struct rlimit {
-	long	rlim_cur;
-	long	rlim_max;
+	unsigned long	rlim_cur;
+	unsigned long	rlim_max;
 };
 
 #define	PRIO_MIN	(-20)
diff -u --recursive --new-file v2.3.23/linux/include/linux/serialP.h linux/include/linux/serialP.h
--- v2.3.23/linux/include/linux/serialP.h	Tue Sep  7 12:14:07 1999
+++ linux/include/linux/serialP.h	Wed Oct 27 16:17:08 1999
@@ -23,9 +23,6 @@
 #include <linux/termios.h>
 #include <linux/tqueue.h>
 #include <linux/wait.h>
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
 
 /*
  * Counters of the input lines (CTS, DSR, RI, CD) interrupts
@@ -151,6 +148,7 @@
 /*
  * Structures and definitions for PCI support
  */
+struct pci_dev;
 struct pci_board {
 	unsigned short vendor;
 	unsigned short device;
diff -u --recursive --new-file v2.3.23/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.3.23/linux/include/linux/swap.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/swap.h	Wed Oct 27 16:17:07 1999
@@ -65,7 +65,7 @@
 extern int nr_lru_pages;
 extern struct list_head lru_cache;
 extern atomic_t nr_async_pages;
-extern struct inode swapper_inode;
+extern struct address_space swapper_space;
 extern atomic_t page_cache_size;
 extern atomic_t buffermem_pages;
 
diff -u --recursive --new-file v2.3.23/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.23/linux/include/linux/sysctl.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/sysctl.h	Mon Oct 25 08:26:53 1999
@@ -103,7 +103,8 @@
 	KERN_MSGPOOL=37,        /* int: Maximum system message pool size */
 	KERN_SYSRQ=38,		/* int: Sysreq enable */
 	KERN_MAX_THREADS=39,    /* int: Maximum nr of threads in the system */
- 	KERN_RANDOM=40		/* Random driver */
+ 	KERN_RANDOM=40,		/* Random driver */
+ 	KERN_SHMALL=41		/* int: Maximum size of shared memory */
 };
 
 
diff -u --recursive --new-file v2.3.23/linux/include/linux/tty.h linux/include/linux/tty.h
--- v2.3.23/linux/include/linux/tty.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/tty.h	Wed Oct 27 16:17:09 1999
@@ -23,7 +23,6 @@
 #include <linux/tqueue.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_ldisc.h>
-#include <linux/serialP.h>
 
 #include <asm/system.h>
 
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/discovery.h linux/include/net/irda/discovery.h
--- v2.3.23/linux/include/net/irda/discovery.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/discovery.h	Wed Oct 27 16:17:04 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr  6 16:53:53 1999
- * Modified at:   Mon Aug 23 09:26:24 1999
+ * Modified at:   Tue Oct  5 10:05:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -45,7 +45,7 @@
  * The DISCOVERY structure is used for both discovery requests and responses
  */
 typedef struct {
-	QUEUE queue;             /* Must be first! */
+	queue_t q;               /* Must be first! */
 
 	__u32      saddr;        /* Which link the device was discovered */
 	__u32      daddr;        /* Remote device address */
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/dongle.h linux/include/net/irda/dongle.h
--- v2.3.23/linux/include/net/irda/dongle.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/dongle.h	Wed Dec 31 16:00:00 1969
@@ -1,52 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      dongle.h
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Sat Jun 26 16:58:44 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *      
- *     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.
- *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#ifndef DONGLE_H
-#define DONGLE_H
-
-#include <net/irda/qos.h>
-
-/* These are the currently known dongles */
-typedef enum {
-	TEKRAM_DONGLE,
-	ESI_DONGLE,
-	ACTISYS_DONGLE,
-	ACTISYS_PLUS_DONGLE,
-	GIRBIL_DONGLE,
-	LITELINK_DONGLE,
-	AIRPORT_DONGLE,
-} IRDA_DONGLE;
-
-struct irda_device;
-
-struct dongle {
-	IRDA_DONGLE type;
-	void (*open)(struct irda_device *, int type);
-	void (*close)(struct irda_device *);
-	void (*reset)( struct irda_device *);
-	void (*change_speed)( struct irda_device *, __u32 speed);
-	void (*qos_init)( struct irda_device *, struct qos_info *);
-};
-
-#endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/ircomm_core.h linux/include/net/irda/ircomm_core.h
--- v2.3.23/linux/include/net/irda/ircomm_core.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/ircomm_core.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Jun  9 08:58:43 1999
- * Modified at:   Fri Aug 13 07:24:18 1999
+ * Modified at:   Tue Oct  5 09:13:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -53,7 +53,7 @@
 } call_t;
 
 struct ircomm_cb {
-	QUEUE   queue;
+	queue_t queue;
 	magic_t magic;
 
 	notify_t notify;
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/ircomm_tty.h linux/include/net/irda/ircomm_tty.h
--- v2.3.23/linux/include/net/irda/ircomm_tty.h	Mon Oct  4 15:49:30 1999
+++ linux/include/net/irda/ircomm_tty.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 23:24:22 1999
- * Modified at:   Tue Aug 31 10:22:02 1999
+ * Modified at:   Tue Oct  5 12:01:07 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -32,6 +32,8 @@
 #define IRCOMM_TTY_H
 
 #include <linux/serial.h>
+#include <linux/termios.h>
+#include <linux/timer.h>
 
 #include <net/irda/irias_object.h>
 #include <net/irda/ircomm_core.h>
@@ -46,7 +48,7 @@
  * IrCOMM TTY driver state
  */
 struct ircomm_tty_cb {
-	QUEUE   queue;
+	queue_t queue;
 	magic_t magic;
 
 	int state;
@@ -54,7 +56,6 @@
 	struct tty_struct *tty;
 	struct ircomm_cb *ircomm;
 
-	struct sk_buff_head tx_queue;  /* Frames to be transmitted */
 	struct sk_buff *tx_skb;
 	struct sk_buff *ctrl_skb;
 
@@ -64,7 +65,7 @@
 	__u8 service_type;
 
 	int line;
-	int flags;
+	__u32 flags;
 
 	__u8 dlsap_sel;
 	__u8 slsap_sel;
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.3.23/linux/include/net/irda/irda.h	Mon Oct  4 15:49:30 1999
+++ linux/include/net/irda/irda.h	Wed Oct 27 16:18:18 1999
@@ -2,11 +2,11 @@
  *                
  * Filename:      irda.h
  * Version:       
- * Description:   
+ * Description:   IrDA common include file for kernel internal use
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon Sep 27 11:13:18 1999
+ * Modified at:   Tue Oct 19 21:12:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -28,6 +28,10 @@
 #include <linux/config.h>
 #include <linux/skbuff.h>
 #include <linux/kernel.h>
+#include <linux/if.h>
+#include <linux/irda.h>
+
+typedef __u32 magic_t;
 
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
@@ -40,12 +44,16 @@
 #define FALSE 0
 #endif
 
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#ifndef IRDA_MIN /* Lets not mix this MIN with other header files */
+#define IRDA_MIN(a, b) (((a) < (b)) ? (a) : (b))
 #endif
 
-#define ALIGN __attribute__((aligned))
-#define PACK __attribute__((packed))
+#ifndef ALIGN
+#  define ALIGN __attribute__((aligned))
+#endif
+#ifndef PACK
+#  define PACK __attribute__((packed))
+#endif
 
 
 #ifdef CONFIG_IRDA_DEBUG
@@ -55,14 +63,14 @@
 /* use 0 for production, 1 for verification, >2 for debug */
 #define IRDA_DEBUG_LEVEL 0
 
-#define DEBUG(n, args...) (irda_debug >= (n)) ? (printk(KERN_DEBUG args)) : 0
+#define IRDA_DEBUG(n, args...) (irda_debug >= (n)) ? (printk(KERN_DEBUG args)) : 0
 #define ASSERT(expr, func) \
 if(!(expr)) { \
         printk( "Assertion failed! %s,%s,%s,line=%d\n",\
         #expr,__FILE__,__FUNCTION__,__LINE__); \
         ##func}
 #else
-#define DEBUG(n, args...)
+#define IRDA_DEBUG(n, args...)
 #define ASSERT(expr, func)
 #endif /* CONFIG_IRDA_DEBUG */
 
@@ -76,7 +84,6 @@
  *  Magic numbers used by Linux-IrDA. Random numbers which must be unique to 
  *  give the best protection
  */
-typedef __u32 magic_t;
 
 #define IRTTY_MAGIC        0x2357
 #define LAP_MAGIC          0x1357
@@ -92,6 +99,7 @@
 #define IRLAN_MAGIC        0x754
 #define IAS_OBJECT_MAGIC   0x34234
 #define IAS_ATTRIB_MAGIC   0x45232
+#define IRDA_TASK_MAGIC    0x38423
 
 #define IAS_DEVICE_ID 0x5342 
 #define IAS_PNP_ID    0xd342
@@ -147,49 +155,17 @@
 	__u8  byte[2];
 } __u16_host_order;
 
-/* Per-packet information we need to hide inside sk_buff */
+/* 
+ * Per-packet information we need to hide inside sk_buff 
+ * (must not exceed 48 bytes, check with struct sk_buff) 
+ */
 struct irda_skb_cb {
 	magic_t magic;     /* Be sure that we can trust the information */
-	int     mtt;       /* minimum turn around time */
-	int     xbofs;     /* number of xbofs required, used by SIR mode */
-	int     line;      /* Used by IrCOMM in IrLPT mode */
-	void    *instance; /* Used by IrTTP */
+	__u32   speed;     /* The Speed this frame should be sent with */
+	__u16     mtt;     /* Minimum turn around time */
+	int     xbofs;     /* Number of xbofs required, used by SIR mode */
+	__u8     line;     /* Used by IrCOMM in IrLPT mode */
 	void (*destructor)(struct sk_buff *skb); /* Used for flow control */
-};
-
-/*
- *  Information monitored by some layers
- */
-struct irda_statistics
-{
-        int     rx_packets;             /* total packets received       */
-        int     tx_packets;             /* total packets transmitted    */
-        int     rx_errors;              /* bad packets received         */
-        int     tx_errors;              /* packet transmit problems     */
-        int     rx_dropped;             /* no space in linux buffers    */
-        int     tx_dropped;             /* no space available in linux  */
-	int     rx_compressed;
-	int     tx_compressed;
-	int     rx_bytes;               /* total bytes received         */
-	int     tx_bytes;               /* total bytes transmitted      */
-
-        int     multicast;              /* multicast packets received   */
-        int     collisions;
-	
-        /* detailed rx_errors: */
-        int     rx_length_errors;
-        int     rx_over_errors;         /* receiver ring buff overflow  */
-        int     rx_crc_errors;          /* recved pkt with crc error    */
-        int     rx_frame_errors;        /* recv'd frame alignment error */
-        int     rx_fifo_errors;         /* recv'r fifo overrun          */
-        int     rx_missed_errors;       /* receiver missed packet       */
-
-        /* detailed tx_errors */
-        int     tx_aborted_errors;
-        int     tx_carrier_errors;
-        int     tx_fifo_errors;
-        int     tx_heartbeat_errors;
-        int     tx_window_errors;
 };
 
 /* Misc status information */
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.3.23/linux/include/net/irda/irda_device.h	Mon Oct  4 15:49:30 1999
+++ linux/include/net/irda/irda_device.h	Wed Oct 27 16:17:04 1999
@@ -1,17 +1,16 @@
 /*********************************************************************
  *                
  * Filename:      irda_device.h
- * Version:       
- * Description:   
+ * Version:       0.9
+ * Description:   Contains various declarations used by the drivers
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Mon Sep 20 11:21:31 1999
+ * Modified at:   Tue Oct 19 20:00:03 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
- *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
  *
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -36,18 +35,13 @@
 #include <linux/tty.h>
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
+#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/qos.h>
-#include <net/irda/dongle.h>
 #include <net/irda/irqueue.h>
 #include <net/irda/irlap_frame.h>
 
-/* Some private IOCTL's */
-#define SIOCSDONGLE    (SIOCDEVPRIVATE + 0)
-#define SIOCSBANDWIDTH (SIOCDEVPRIVATE + 1)
-#define SIOCSMEDIABUSY (SIOCDEVPRIVATE + 2)
-
 /* Some non-standard interface flags (should not conflict with any in if.h) */
 #define IFF_SIR 	0x0001 /* Supports SIR speeds */
 #define IFF_MIR 	0x0002 /* Supports MIR speeds */
@@ -57,14 +51,74 @@
 #define IFF_DMA		0x0020 /* Supports DMA transfer of data */
 #define IFF_SHM         0x0040 /* Supports shared memory data transfers */
 #define IFF_DONGLE      0x0080 /* Interface has a dongle attached */
-#define IFF_AIR         0x0100 /* Supports A(dvanced)IR standards */
+#define IFF_AIR         0x0100 /* Supports Advanced IR (AIR) standards */
 
 #define IO_XMIT 0x01
 #define IO_RECV 0x02
 
-struct dongle_q {
-	QUEUE q;
-	struct dongle *dongle;
+typedef enum {
+	IRDA_IRLAP, /* IrDA mode, and deliver to IrLAP */
+	IRDA_RAW,   /* IrDA mode */
+	SHARP_ASK,
+	TV_REMOTE,  /* Also known as Consumer Electronics IR */
+} INFRARED_MODE;
+
+typedef enum {
+	IRDA_TASK_INIT,        /* All tasks are initialized with this state */
+	IRDA_TASK_DONE,        /* Signals that the task is finished */
+	IRDA_TASK_WAIT,
+	IRDA_TASK_WAIT1,
+	IRDA_TASK_WAIT2,
+	IRDA_TASK_WAIT3,
+	IRDA_TASK_CHILD_INIT,  /* Initializing child task */
+	IRDA_TASK_CHILD_WAIT,  /* Waiting for child task to finish */
+	IRDA_TASK_CHILD_DONE   /* Child task is finished */
+} TASK_STATE;
+
+struct irda_task;
+typedef int (*TASK_CALLBACK) (struct irda_task *task);
+
+struct irda_task {
+	queue_t q;
+	magic_t magic;
+
+	TASK_STATE state;
+	TASK_CALLBACK function;
+	TASK_CALLBACK finished;
+
+	/* struct net_device *dev; */
+	struct irda_task *parent;
+	struct timer_list timer;
+
+	void *instance; /* Instance being called */
+	void *param;    /* Parameter to be used by instance */
+};
+
+/* Dongle info */
+struct dongle_reg;
+typedef struct {
+	struct dongle_reg *issue; /* Registration info */
+	struct net_device *dev;   /* Device we are attached to */
+	__u32 speed;              /* Current speed */
+	
+	int busy;
+
+	/* Callbacks to the IrDA device driver */
+	int (*set_mode)(struct net_device *, int mode);
+	int (*read)(struct net_device *dev, __u8 *buf, int len);
+	int (*write)(struct net_device *dev, __u8 *buf, int len);
+	int (*set_dtr_rts)(struct net_device *dev, int dtr, int rts);
+} dongle_t;
+
+/* Dongle registration info */
+struct dongle_reg {
+	queue_t q;        /* Must be first */
+	IRDA_DONGLE type;
+
+	void (*open)(dongle_t *dongle, struct qos_info *qos);
+	void (*close)(dongle_t *dongle);
+	int  (*reset)(struct irda_task *task);
+	int  (*change_speed)(struct irda_task *task);
 };
 
 /* Chip specific info */
@@ -79,7 +133,7 @@
         int irqflags;         /* interrupt flags (ie, SA_SHIRQ|SA_INTERRUPT) */
 	int direction;        /* Link direction, used by some FIR drivers */
 
-	__u32 baudrate;       /* Currently used baudrate */
+	__u32 speed;          /* Currently used speed */
 	int dongle_id;        /* Dongle or transceiver currently used */
 };
 
@@ -95,87 +149,38 @@
 	int len;	      /* length of data */
 	int truesize;	      /* total size of buffer */
 	__u16 fcs;
-
-	int flags;            /* Allocation flags (GFP_KERNEL | GFP_DMA ) */
 };
 
-/* 
- * This structure contains data that _we_ would have liked to be in the device
- * structure, but we don't want to mess it up more than it is already. Better 
- * to keep the data in separate structures! This structure abstracts common 
- * stuff from IrDA port implementations.
- */
-struct irda_device {
-	QUEUE   q;             /* Must be first */
-        magic_t magic;	       /* Our magic bullet */
-
-	char name[16];         /* Name of device "irda0" */
-	char description[32];  /* Something like "irda0 <-> ttyS0" */
-
-	struct irlap_cb *irlap;   /* The link layer we are connected to  */
-	struct net_device netdev; /* Yes! we are some kind of netdevice */
-	struct enet_statistics stats;
-
- 	__u32 flags;          /* Interface flags (see defs above) */
-
- 	void *priv;           /* Pointer to low level implementation */
-
-	struct qos_info qos;  /* QoS capabilities for this device */
-
-	struct chipio_t io;
-	struct iobuff_t tx_buff;
-	struct iobuff_t rx_buff;
-
-	struct dongle *dongle; /* Dongle driver */
-
-	spinlock_t lock;       /* For serializing operations */
-	
-	/* Media busy stuff */
-	int media_busy;
-	struct timer_list media_busy_timer;
-
-	int raw_mode;
-
-	/* Callbacks to driver specific implementations */
-        void (*change_speed)(struct irda_device *idev, __u32 speed);
- 	int  (*is_receiving)(struct irda_device *);    /* receiving? */
-	void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts);
-	void (*set_raw_mode)(struct irda_device *dev, int mode);
-	int  (*raw_write)(struct irda_device *idev, __u8 *buf, int len);
-	int  (*raw_read)(struct irda_device *idev, __u8 *buf, int len, 
-			 int timeout);
-	void (*wait_until_sent)(struct irda_device *);
-	void (*set_caddr)(struct irda_device *);      /* Set connection addr */
-};
-
-extern hashbin_t *irda_device;
-
 /* Function prototypes */
 int  irda_device_init(void);
 void irda_device_cleanup(void);
 
-int  irda_device_open(struct irda_device *, char *name, void *priv);
-void irda_device_close(struct irda_device *);
-
 /* Interface to be uses by IrLAP */
 void irda_device_set_media_busy(struct net_device *dev, int status);
 int  irda_device_is_media_busy(struct net_device *dev);
 int  irda_device_is_receiving(struct net_device *dev);
-struct qos_info *irda_device_get_qos(struct net_device *dev);
 
 /* Interface for internal use */
-void irda_device_change_speed(struct irda_device *, int);
-int  irda_device_txqueue_empty(struct irda_device *self);
-void irda_device_init_dongle(struct irda_device *self, int type);
-void irda_device_unregister_dongle(struct dongle *dongle);
-int  irda_device_register_dongle(struct dongle *dongle);
-int  irda_device_set_raw_mode(struct irda_device* self, int status);
+int  irda_device_txqueue_empty(struct net_device *dev);
+int  irda_device_set_raw_mode(struct net_device* self, int status);
+int  irda_device_set_dtr_rts(struct net_device *dev, int dtr, int rts);
 int  irda_device_setup(struct net_device *dev);
 
+/* Dongle interface */
+void irda_device_unregister_dongle(struct dongle_reg *dongle);
+int  irda_device_register_dongle(struct dongle_reg *dongle);
+dongle_t *irda_device_dongle_init(struct net_device *dev, int type);
+int irda_device_dongle_cleanup(dongle_t *dongle);
+
 void setup_dma(int channel, char *buffer, int count, int mode);
 
-int irda_device_net_open(struct net_device *dev);
-int irda_device_net_close(struct net_device *dev);
+int  irda_task_kick(struct irda_task *task);
+int  irda_task_execute(void *instance, TASK_CALLBACK function, 
+		       TASK_CALLBACK finished, struct irda_task *parent, 
+		       void *param);
+void irda_task_next_state(struct irda_task *task, TASK_STATE state);
+
+extern const char *infrared_mode[];
 
 /*
  * Function irda_get_mtt (skb)
@@ -197,21 +202,22 @@
 	return mtt;
 }
 
-extern inline void irda_device_set_dtr_rts(struct irda_device *self, int dtr,
-					   int rts)
+/*
+ * Function irda_get_speed (skb)
+ *
+ *    Extact the speed this frame should be sent out with from the skb
+ *
+ */
+extern inline __u32 irda_get_speed(struct sk_buff *skb)
 {
-	if (self->set_dtr_rts)
-		self->set_dtr_rts(self, dtr, rts);
-}
+	__u32 speed;
 
-extern inline int irda_device_raw_write(struct irda_device *self, __u8 *buf,
-					int len)
-{
-	int ret = -1;
+	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC)
+		speed = 9600;
+	else
+		speed = ((struct irda_skb_cb *)(skb->cb))->speed;
 
-	if (self->raw_write)
-		ret = self->raw_write(self, buf, len);
-	return ret;
+	return speed;
 }
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h
--- v2.3.23/linux/include/net/irda/iriap.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/iriap.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Thu Jul  1 10:10:42 1999
+ * Modified at:   Tue Oct  5 10:05:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -57,7 +57,7 @@
 				 struct ias_value *value, void *priv);
 
 struct iriap_cb {
-	QUEUE   queue;  /* Must be first */	
+	queue_t q;      /* Must be first */	
 	magic_t magic;  /* Magic cookie */
 
 	int          mode;   /* Client or server */
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irias_object.h linux/include/net/irda/irias_object.h
--- v2.3.23/linux/include/net/irda/irias_object.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/irias_object.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:49:50 1998
- * Modified at:   Thu Jul  1 11:37:15 1999
+ * Modified at:   Tue Oct  5 10:45:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -38,7 +38,7 @@
  *  LM-IAS Object
  */
 struct ias_object {
-	QUEUE   queue;     /* Must be first! */
+	queue_t q;     /* Must be first! */
 	magic_t magic;
 	
 	char  *name;
@@ -66,7 +66,7 @@
  *  Attributes used by LM-IAS objects
  */
 struct ias_attrib {
-	QUEUE queue; /* Must be first! */
+	queue_t q; /* Must be first! */
 	int magic;
 
         char *name;   	         /* Attribute name */
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h
--- v2.3.23/linux/include/net/irda/irlan_common.h	Wed Aug 18 11:38:47 1999
+++ linux/include/net/irda/irlan_common.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon May 31 13:54:20 1999
+ * Modified at:   Tue Oct  5 11:35:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -159,7 +159,7 @@
  *  IrLAN control block
  */
 struct irlan_cb {
-	QUEUE queue; /* Must be first */
+	queue_t q; /* Must be first */
 
 	int    magic;
 	char   ifname[9];
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.3.23/linux/include/net/irda/irlap.h	Mon Oct  4 15:49:30 1999
+++ linux/include/net/irda/irlap.h	Wed Oct 27 16:17:04 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon Sep 20 10:14:47 1999
+ * Modified at:   Thu Oct  7 23:06:36 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -67,6 +67,7 @@
 #define NS_INVALID     -1
 
 #ifdef CONFIG_IRDA_COMPRESSION
+
 /*  
  *  Just some shortcuts (may give you strange compiler errors if you change 
  *  them :-)
@@ -78,7 +79,7 @@
 #define irda_incomp      (*self->decompressor.cp->incomp)
 
 struct irda_compressor {
-	QUEUE queue;
+	queue_t q;
 
 	struct compressor *cp;
 	void *state; /* Not used by IrDA */
@@ -87,7 +88,7 @@
 
 /* Main structure of IrLAP */
 struct irlap_cb {
-	QUEUE   q;     /* Must be first */
+	queue_t q;     /* Must be first */
 	magic_t magic;
 
 	struct net_device  *netdev;
@@ -104,6 +105,10 @@
 	struct timer_list wd_timer;
 	struct timer_list backoff_timer;
 
+	/* Media busy stuff */
+	struct timer_list media_busy_timer;
+	int media_busy;
+
 	/* Timeouts which will be different with different turn time */
 	int slot_timeout;
 	int poll_timeout;
@@ -157,8 +162,9 @@
 	hashbin_t   *discovery_log;
  	discovery_t *discovery_cmd;
 
-	struct qos_info qos_tx;    /* QoS requested by peer */
-	struct qos_info qos_rx;    /* QoS requested by self */
+	struct qos_info  qos_tx;   /* QoS requested by peer */
+	struct qos_info  qos_rx;   /* QoS requested by self */
+	struct qos_info *qos_dev;  /* QoS supported by device */
 
 	notify_t notify; /* Callbacks to IrLMP */
 
@@ -166,8 +172,6 @@
 	int    xbofs_delay;   /* Nr of XBOF's used to MTT */
 	int    bofs_count;    /* Negotiated extra BOFs */
 
- 	struct irda_statistics stats;
-
 #ifdef CONFIG_IRDA_COMPRESSION
 	struct irda_compressor compressor;
         struct irda_compressor decompressor;
@@ -182,7 +186,7 @@
 int irlap_init(void);
 void irlap_cleanup(void);
 
-struct irlap_cb *irlap_open(struct net_device *dev);
+struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos);
 void irlap_close(struct irlap_cb *self);
 
 void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
@@ -191,10 +195,9 @@
 void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb);
 void irlap_connect_confirm(struct irlap_cb *, struct sk_buff *skb);
 
-inline void irlap_data_indication(struct irlap_cb *, struct sk_buff *);
-inline void irlap_unit_data_indication(struct irlap_cb *, struct sk_buff *);
-inline void irlap_data_request(struct irlap_cb *, struct sk_buff *, 
-			       int reliable);
+void irlap_data_indication(struct irlap_cb *, struct sk_buff *);
+void irlap_unit_data_indication(struct irlap_cb *, struct sk_buff *);
+void irlap_data_request(struct irlap_cb *, struct sk_buff *, int reliable);
 
 void irlap_disconnect_request(struct irlap_cb *);
 void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason);
@@ -225,14 +228,7 @@
 void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *);
 void irlap_set_local_busy(struct irlap_cb *self, int status);
 
-extern inline __u8 irlap_get_header_size(struct irlap_cb *self)
-{
-	return 2;
-}
-
-extern inline int irlap_get_tx_queue_len(struct irlap_cb *self)
-{
-	return skb_queue_len(&self->tx_list);
-}
+#define IRLAP_GET_HEADER_SIZE(self) 2 /* Will be different when we get VFIR */
+#define IRLAP_GET_TX_QUEUE_LEN(self) skb_queue_len(&self->tx_list)
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h
--- v2.3.23/linux/include/net/irda/irlmp.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/irlmp.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Thu Jul  8 13:44:20 1999
+ * Modified at:   Tue Oct  5 15:20:56 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -78,13 +78,13 @@
 typedef void (*DISCOVERY_CALLBACK2) (hashbin_t *);
 
 typedef struct {
-	QUEUE queue; /* Must be first */
+	queue_t queue; /* Must be first */
 
 	__u16 hints; /* Hint bits */
 } irlmp_service_t;
 
 typedef struct {
-	QUEUE queue; /* Must be first */
+	queue_t queue; /* Must be first */
 
 	__u16 hint_mask;
 
@@ -98,14 +98,12 @@
  *  Information about each logical LSAP connection
  */
 struct lsap_cb {
-	QUEUE   queue;      /* Must be first */
+	queue_t queue;      /* Must be first */
 	magic_t magic;
 
 	int   connected;
 	int   persistent;
 
-	struct irda_statistics stats;
-
 	__u8  slsap_sel;   /* Source (this) LSAP address */
 	__u8  dlsap_sel;   /* Destination LSAP address (if connected) */
 
@@ -124,7 +122,7 @@
  *  Information about each registred IrLAP layer
  */
 struct lap_cb {
-	QUEUE   queue;      /* Must be first */
+	queue_t queue;      /* Must be first */
 	magic_t magic;
 
 	int reason;    /* LAP disconnect reason */
@@ -248,7 +246,7 @@
 	ASSERT(self->lap != NULL, return 0;);
 	ASSERT(self->lap->irlap != NULL, return 0;);
 
-	return irlap_get_tx_queue_len(self->lap->irlap);
+	return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap);
 }
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irmod.h linux/include/net/irda/irmod.h
--- v2.3.23/linux/include/net/irda/irmod.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/irmod.h	Mon Oct 25 20:49:42 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:58:52 1997
- * Modified at:   Fri Apr  9 11:13:39 1999
+ * Modified at:   Tue Oct  5 10:26:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -69,7 +69,7 @@
  *  addtional information
  */
 struct irda_event {
-	QUEUE q; /* Must be first */
+	queue_t q; /* Must be first */
 	
 	struct irmanager_event event;
 };
@@ -78,7 +78,7 @@
  *  Funtions with needs to be called with a process context
  */
 struct irda_todo {
-	QUEUE q; /* Must be first */
+	queue_t q; /* Must be first */
 
 	void *self;
 	TODO_CALLBACK callback;
@@ -94,8 +94,8 @@
 
 	int in_use;
 
-	QUEUE *event_queue; /* Events queued for the irmanager */
-	QUEUE *todo_queue;  /* Todo list */
+	queue_t *event_queue; /* Events queued for the irmanager */
+	queue_t *todo_queue;  /* Todo list */
 };
 
 int irmod_init_module(void);
@@ -110,7 +110,7 @@
 static inline int irda_lock(int *lock) 
 {
 	if (test_and_set_bit( 0, (void *) lock))  {
-		DEBUG(3, __FUNCTION__ 
+		IRDA_DEBUG(3, __FUNCTION__ 
 		      "(), Trying to lock, already locked variable!\n");
 		return FALSE;
         }  
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.3.23/linux/include/net/irda/irport.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/irport.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug  3 13:49:59 1997
- * Modified at:   Sat Jun 26 16:57:03 1999
+ * Modified at:   Mon Oct 18 12:55:07 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -29,6 +29,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
+#include <linux/spinlock.h>
 
 #include <net/irda/irda_device.h>
 
@@ -49,14 +50,35 @@
 
 #define FRAME_MAX_SIZE 2048
 
-void irport_start(struct irda_device *idev, int iobase);
-void irport_stop(struct irda_device *idev, int iobase);
+struct irport_cb {
+	queue_t q;     /* Must be first */
+	magic_t magic;
+
+	struct net_device *netdev; /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+
+	struct tty_struct  *tty;
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+
+	struct chipio_t io;        /* IrDA controller information */
+	struct iobuff_t tx_buff;   /* Transmit buffer */
+	struct iobuff_t rx_buff;   /* Receive buffer */
+
+	struct qos_info qos;       /* QoS capabilities for this device */
+	dongle_t *dongle;          /* Dongle driver */
+
+ 	__u32 flags;               /* Interface flags */
+
+	spinlock_t lock;           /* For serializing operations */
+
+	int mode;
+};
+
+void irport_start(struct irport_cb *self, int iobase);
+void irport_stop(struct irport_cb *self, int iobase);
 int  irport_probe(int iobase);
 
-void irport_change_speed(struct irda_device *idev, __u32 speed);
 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
 int  irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-void irport_wait_until_sent(struct irda_device *idev);
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irqueue.h linux/include/net/irda/irqueue.h
--- v2.3.23/linux/include/net/irda/irqueue.h	Fri Sep 10 23:57:37 1999
+++ linux/include/net/irda/irqueue.h	Wed Oct 27 16:17:50 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:26:50 1998
- * Modified at:   Thu Jul  1 10:18:21 1999
+ * Modified at:   Thu Oct  7 13:25:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
@@ -53,56 +53,49 @@
 #define ALIGN __attribute__((aligned))
 #endif
 
-typedef void (*FREE_FUNC)( void *arg);
+#define Q_NULL { NULL, NULL, "", 0 }
+
+typedef void (*FREE_FUNC)(void *arg);
 
 /*
  * Hashbin
  */
 #define GET_HASHBIN(x) ( x & HASHBIN_MASK )
 
-#define QUEUE struct queue_t
-struct queue_t {
-	QUEUE* q_next;
-	QUEUE* q_prev;
+struct irqueue {
+	struct irqueue *q_next;
+	struct irqueue *q_prev;
 
-	char   q_name[ NAME_SIZE];
+	char   q_name[NAME_SIZE];
 	__u32  q_hash;
 };
+typedef struct irqueue queue_t;
 
 typedef struct hashbin_t {
 	__u32      magic;
 	int        hb_type;
 	int        hb_size;
-	spinlock_t hb_mutex[ HASHBIN_SIZE ] ALIGN;
-	QUEUE*     hb_queue[ HASHBIN_SIZE ] ALIGN;
+	spinlock_t hb_mutex[HASHBIN_SIZE] ALIGN;
+	queue_t   *hb_queue[HASHBIN_SIZE] ALIGN;
 
-	QUEUE* hb_current;
+	queue_t* hb_current;
 } hashbin_t;
 
 hashbin_t *hashbin_new(int type);
 int      hashbin_delete(hashbin_t* hashbin, FREE_FUNC func);
 int      hashbin_clear(hashbin_t* hashbin, FREE_FUNC free_func);
-void     hashbin_insert(hashbin_t* hashbin, QUEUE* entry, __u32 hashv, 
+void     hashbin_insert(hashbin_t* hashbin, queue_t* entry, __u32 hashv, 
 			char* name);
 void*    hashbin_find(hashbin_t* hashbin, __u32 hashv, char* name);
 void*    hashbin_remove(hashbin_t* hashbin, __u32 hashv, char* name);
 void*    hashbin_remove_first(hashbin_t *hashbin);
-QUEUE   *hashbin_get_first(hashbin_t *hashbin);
-QUEUE   *hashbin_get_next(hashbin_t *hashbin);
+queue_t *hashbin_get_first(hashbin_t *hashbin);
+queue_t *hashbin_get_next(hashbin_t *hashbin);
 
-void enqueue_last(QUEUE **queue, QUEUE* element);
-void enqueue_first(QUEUE **queue, QUEUE* element);
-QUEUE *dequeue_first(QUEUE **queue);
+void enqueue_last(queue_t **queue, queue_t* element);
+void enqueue_first(queue_t **queue, queue_t* element);
+queue_t *dequeue_first(queue_t **queue);
 
-/*
- * Function hashbin_get_size (hashbin)
- *
- *    Returns the number of elements in the hashbin
- *
- */
-extern __inline__ int  hashbin_get_size(hashbin_t* hashbin) 
-{
-	return hashbin->hb_size;
-}
+#define HASHBIN_GET_SIZE(hashbin) hashbin->hb_size
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h
--- v2.3.23/linux/include/net/irda/irttp.h	Mon Oct  4 15:49:30 1999
+++ linux/include/net/irda/irttp.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Mon Sep 27 11:38:01 1999
+ * Modified at:   Tue Oct  5 15:17:14 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -63,7 +63,7 @@
  *  connection.
  */
 struct tsap_cb {
-	QUEUE   queue;        /* For linking it into the hashbin */
+	queue_t q;            /* Must be first */
 	magic_t magic;        /* Just in case */
 
 	__u8 stsap_sel;       /* Source TSAP */
@@ -88,7 +88,7 @@
 
 	notify_t notify;       /* Callbacks to client layer */
 
-	struct irda_statistics stats;
+	struct net_device_stats stats;
 	struct timer_list todo_timer; 
 	
 	__u32 max_seg_size;     /* Max data that fit into an IrLAP frame */
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/irtty.h linux/include/net/irda/irtty.h
--- v2.3.23/linux/include/net/irda/irtty.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/irtty.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Thu Jul  1 10:13:02 1999
+ * Modified at:   Mon Oct 18 23:24:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -28,29 +28,46 @@
 #include <linux/if.h>
 #include <linux/skbuff.h>
 #include <linux/termios.h>
+#include <linux/netdevice.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irqueue.h>
 #include <net/irda/irda_device.h>
 
+/* Used by ioctl */
+struct irtty_info {
+	char name[6];
+};
+
 #define IRTTY_IOC_MAGIC 'e'
 #define IRTTY_IOCTDONGLE  _IO(IRTTY_IOC_MAGIC, 1)
-#define IRTTY_IOC_MAXNR   1
-
-#ifndef N_IRDA
-#define N_IRDA         11   /* This one should go in </asm/termio.h> */
-#endif
+#define IRTTY_IOCGET     _IOR(IRTTY_IOC_MAGIC, 2, struct irtty_info)
+#define IRTTY_IOC_MAXNR   2
 
 struct irtty_cb {
-	QUEUE   q;     /* Must be first */
+	queue_t q;     /* Must be first */
 	magic_t magic;
-	
-	struct  tty_struct  *tty;
-	struct  irda_device idev;
+
+	struct net_device *netdev; /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+
+	struct tty_struct  *tty;
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+
+	struct chipio_t io;        /* IrDA controller information */
+	struct iobuff_t tx_buff;   /* Transmit buffer */
+	struct iobuff_t rx_buff;   /* Receive buffer */
+
+	struct qos_info qos;       /* QoS capabilities for this device */
+	dongle_t *dongle;          /* Dongle driver */
+
+ 	__u32 flags;               /* Interface flags */
+
+	INFRARED_MODE mode;
 };
  
-int irtty_register_dongle(struct dongle *dongle);
-void irtty_unregister_dongle(struct dongle *dongle);
+int irtty_register_dongle(struct dongle_reg *dongle);
+void irtty_unregister_dongle(struct dongle_reg *dongle);
 
 #endif
 
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/pc87108.h linux/include/net/irda/pc87108.h
--- v2.3.23/linux/include/net/irda/pc87108.h	Sun Mar  7 15:26:44 1999
+++ linux/include/net/irda/pc87108.h	Mon Oct 25 20:49:42 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Nov 13 14:37:40 1998
- * Modified at:   Mon Jan 25 23:10:25 1999
+ * Modified at:   Mon Oct 18 15:08:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
  *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
  *     Copyright (c) 1998 Actisys Corp., www.actisys.com
  *     All Rights Reserved
@@ -183,12 +183,22 @@
 	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
 	int tx_len;          /* Number of frames in tx_buff */
 
-	struct irda_device idev;
+	struct net_device *netdev; /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+	
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+	
+	struct chipio_t io;        /* IrDA controller information */
+	struct iobuff_t tx_buff;   /* Transmit buffer */
+	struct iobuff_t rx_buff;   /* Receive buffer */
+	struct qos_info qos;       /* QoS capabilities for this device */
+	
+	__u32 flags;               /* Interface flags */
 };
 
-static inline void switch_bank( int iobase, int bank)
+static inline void switch_bank(int iobase, int bank)
 {
-		outb( bank, iobase+BSR);
+		outb(bank, iobase+BSR);
 }
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/qos.h linux/include/net/irda/qos.h
--- v2.3.23/linux/include/net/irda/qos.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/qos.h	Wed Oct 27 16:18:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Sep 19 23:21:09 1997
- * Modified at:   Mon Aug 16 10:00:18 1999
+ * Modified at:   Tue Oct  5 11:51:37 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -69,7 +69,7 @@
 } qos_value_t;
 
 struct qos_info {
-	int  magic;
+	magic_t magic;
 
 	qos_value_t baud_rate;       /* IR_11520O | ... */
 	qos_value_t max_turn_time;
@@ -96,9 +96,9 @@
 void irda_qos_compute_intersection(struct qos_info *, struct qos_info *);
 
 int msb_index(__u16 byte);
-__u32 byte_value(__u8 byte, int *array);
-int value_index(__u32 value, int *array);
-__u32 index_value(int index, int *array);
+__u32 byte_value(__u8 byte, __u32 *array);
+int value_index(__u32 value, __u32 *array);
+__u32 index_value(int index, __u32 *array);
 
 void irda_qos_bits_to_value(struct qos_info *qos);
 
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/timer.h linux/include/net/irda/timer.h
--- v2.3.23/linux/include/net/irda/timer.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/timer.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Wed Jun 23 22:56:51 1999
+ * Modified at:   Thu Oct  7 12:25:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -26,6 +26,8 @@
 #ifndef TIMER_H
 #define TIMER_H
 
+#include <linux/netdevice.h>
+
 #include <asm/param.h>  /* for HZ */
 
 #include <net/irda/irda.h>
@@ -73,16 +75,13 @@
 inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
 inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
 
-inline void irda_device_start_mbusy_timer(struct irda_device *self);
+void irlap_start_mbusy_timer(struct irlap_cb *);
 
 struct lsap_cb;
 struct lap_cb;
 inline void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout);
 inline void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout);
 inline void irlmp_start_idle_timer(struct lap_cb *, int timeout);
-
-struct irobex_cb;
-inline void irobex_start_watchdog_timer(struct irobex_cb *, int timeout);
 
 #endif
 
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/toshoboe.h linux/include/net/irda/toshoboe.h
--- v2.3.23/linux/include/net/irda/toshoboe.h	Mon Oct  4 15:49:30 1999
+++ linux/include/net/irda/toshoboe.h	Mon Oct 25 20:49:42 1999
@@ -154,7 +154,16 @@
 
 struct toshoboe_cb
   {
-    struct irda_device idev;    /*IRDA device */
+    struct net_device *netdev; /* Yes! we are some kind of netdevice */
+    struct net_device_stats stats;
+
+    struct irlap_cb    *irlap; /* The link layer we are binded to */
+
+    struct chipio_t io;        /* IrDA controller information */
+    struct qos_info qos;       /* QoS capabilities for this device */
+
+    __u32 flags;               /* Interface flags */
+
     struct pci_dev *pdev;       /*PCI device */
     int base;                   /*IO base */
     int txpending;              /*how many tx's are pending */
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/uircc.h linux/include/net/irda/uircc.h
--- v2.3.23/linux/include/net/irda/uircc.h	Thu Apr 15 05:42:42 1999
+++ linux/include/net/irda/uircc.h	Mon Oct 25 20:49:42 1999
@@ -108,9 +108,11 @@
 #define UIRCC_SR13          0x0d /* Timer counter status (high byte) */
 #define UIRCC_SR15          0x0f
 
+#include <net/irda/irda_device.h>
+
 /* Private data for each instance */
 struct uircc_cb {
-	struct irda_device idev;
+	struct net_device idev;
 	
 	__u8 cr3;                 /* Copy of register sr3 */
 };
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/w83977af_ir.h linux/include/net/irda/w83977af_ir.h
--- v2.3.23/linux/include/net/irda/w83977af_ir.h	Sun May 30 10:27:04 1999
+++ linux/include/net/irda/w83977af_ir.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Thu Nov 19 13:55:34 1998
- * Modified at:   Mon May  3 12:07:25 1999
+ * Modified at:   Fri Oct 15 16:06:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -170,12 +170,22 @@
 	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
 	int tx_len;          /* Number of frames in tx_buff */
 
-	struct irda_device idev;
+	struct net_device *netdev; /* Yes! we are some kind of netdevice */
+	struct net_device_stats stats;
+	
+	struct irlap_cb    *irlap; /* The link layer we are binded to */
+	
+	struct chipio_t io;        /* IrDA controller information */
+	struct iobuff_t tx_buff;   /* Transmit buffer */
+	struct iobuff_t rx_buff;   /* Receive buffer */
+	struct qos_info qos;       /* QoS capabilities for this device */
+	
+	__u32 flags;               /* Interface flags */
 };
 
 static inline void switch_bank( int iobase, int set)
 {
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
 }
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/include/net/irda/wrapper.h linux/include/net/irda/wrapper.h
--- v2.3.23/linux/include/net/irda/wrapper.h	Sun May 30 10:27:04 1999
+++ linux/include/net/irda/wrapper.h	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon May  3 09:02:36 1999
+ * Modified at:   Thu Oct  7 11:40:25 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -28,6 +28,7 @@
 
 #include <linux/types.h>
 #include <linux/skbuff.h>
+#include <linux/netdevice.h>
 
 #include <net/irda/irda_device.h>
 
@@ -51,6 +52,7 @@
 
 /* Proto definitions */
 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize);
-inline void async_unwrap_char(struct irda_device *idev, __u8 byte);
+int async_bump(struct net_device *dev, __u8 *buf, int len);
+int async_unwrap_char(struct net_device *dev, struct iobuff_t *buf, __u8 byte);
 
 #endif
diff -u --recursive --new-file v2.3.23/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.23/linux/ipc/shm.c	Fri Oct 22 13:21:55 1999
+++ linux/ipc/shm.c	Tue Oct 26 10:21:04 1999
@@ -33,7 +33,7 @@
 static void shm_open (struct vm_area_struct *shmd);
 static void shm_close (struct vm_area_struct *shmd);
 static struct page * shm_nopage(struct vm_area_struct *, unsigned long, int);
-static int shm_swapout(struct vm_area_struct *, struct page *);
+static int shm_swapout(struct page *, struct file *);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
@@ -646,7 +646,7 @@
  * data structures already, and shm_swap_out() will just
  * work off them..
  */
-static int shm_swapout(struct vm_area_struct * vma, struct page * page)
+static int shm_swapout(struct page * page, struct file *file)
 {
 	return 0;
 }
@@ -681,7 +681,6 @@
 			pte_t entry = pte;
 
 			spin_unlock(&shm_lock);
-			BUG();
 			page = lookup_swap_cache(entry);
 			if (!page) {
 				lock_kernel();
diff -u --recursive --new-file v2.3.23/linux/ipc/util.c linux/ipc/util.c
--- v2.3.23/linux/ipc/util.c	Thu Aug 26 13:05:41 1999
+++ linux/ipc/util.c	Mon Oct 25 10:58:00 1999
@@ -119,7 +119,7 @@
 	return -ENOSYS;
 }
 
-void shm_unuse(unsigned long entry, unsigned long page)
+void shm_unuse(pte_t entry, struct page *page)
 {
 }
 
diff -u --recursive --new-file v2.3.23/linux/kernel/fork.c linux/kernel/fork.c
--- v2.3.23/linux/kernel/fork.c	Fri Oct 22 13:21:55 1999
+++ linux/kernel/fork.c	Wed Oct 27 14:10:53 1999
@@ -352,7 +352,7 @@
 void mm_release(void)
 {
 	struct task_struct *tsk = current;
-	forget_segments();
+
 	/* notify parent sleeping on vfork() */
 	if (tsk->flags & PF_VFORK) {
 		tsk->flags &= ~PF_VFORK;
diff -u --recursive --new-file v2.3.23/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.23/linux/kernel/ksyms.c	Fri Oct 22 13:21:55 1999
+++ linux/kernel/ksyms.c	Wed Oct 27 16:07:40 1999
@@ -49,6 +49,7 @@
 #include <linux/kmod.h>
 #endif
 
+extern int console_loglevel;
 extern void set_device_ro(kdev_t dev,int flag);
 extern struct file_operations * get_blkfops(unsigned int);
 extern int blkdev_release(struct inode * inode);
@@ -92,6 +93,7 @@
 
 /* internal kernel memory management */
 EXPORT_SYMBOL(__get_free_pages);
+EXPORT_SYMBOL(__get_pages);
 EXPORT_SYMBOL(free_pages);
 EXPORT_SYMBOL(__free_page);
 EXPORT_SYMBOL(kmem_find_general_cachep);
@@ -245,6 +247,7 @@
 EXPORT_SYMBOL(init_buffer);
 EXPORT_SYMBOL(refile_buffer);
 EXPORT_SYMBOL(max_sectors);
+EXPORT_SYMBOL(max_segments);
 EXPORT_SYMBOL(max_readahead);
 EXPORT_SYMBOL(file_moveto);
 
@@ -257,6 +260,7 @@
 EXPORT_SYMBOL(tty_get_baud_rate);
 EXPORT_SYMBOL(do_SAK);
 EXPORT_SYMBOL(console_print);
+EXPORT_SYMBOL(console_loglevel);
 
 /* filesystem registration */
 EXPORT_SYMBOL(register_filesystem);
diff -u --recursive --new-file v2.3.23/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.23/linux/mm/filemap.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/filemap.c	Tue Oct 26 11:12:02 1999
@@ -89,7 +89,7 @@
 	spin_lock(&pagecache_lock);
 	remove_page_from_inode_queue(page);
 	remove_page_from_hash_queue(page);
-	page->inode = NULL;
+	page->mapping = NULL;
 	spin_unlock(&pagecache_lock);
 }
 
@@ -98,8 +98,7 @@
 	struct list_head *head, *curr;
 	struct page * page;
 
-	head = &inode->i_pages;
-repeat:
+	head = &inode->i_data.pages;
 	spin_lock(&pagecache_lock);
 	curr = head->next;
 
@@ -115,7 +114,7 @@
 
 		remove_page_from_inode_queue(page);
 		remove_page_from_hash_queue(page);
-		page->inode = NULL;
+		page->mapping = NULL;
 		page_cache_release(page);
 	}
 	spin_unlock(&pagecache_lock);
@@ -133,7 +132,7 @@
 	int partial = 0;
 
 repeat:
-	head = &inode->i_pages;
+	head = &inode->i_data.pages;
 	spin_lock(&pagecache_lock);
 	curr = head->next;
 	while (curr != head) {
@@ -273,7 +272,7 @@
 			if (!try_to_free_buffers(page))
 				goto unlock_continue;
 			/* page was locked, inode can't go away under us */
-			if (!page->inode) {
+			if (!page->mapping) {
 				atomic_dec(&buffermem_pages);
 				goto made_buffer_progress;
 			}
@@ -299,14 +298,13 @@
 		}	
 
 		/* is it a page-cache page? */
-		if (page->inode)
-		{
+		if (page->mapping) {
 			dispose = &old;
 			if (!pgcache_under_min())
 			{
 				remove_page_from_inode_queue(page);
 				remove_page_from_hash_queue(page);
-				page->inode = NULL;
+				page->mapping = NULL;
 				spin_unlock(&pagecache_lock);
 				goto made_inode_progress;
 			}
@@ -358,7 +356,7 @@
 	return ret;
 }
 
-static inline struct page * __find_page_nolock(struct inode * inode, unsigned long offset, struct page *page)
+static inline struct page * __find_page_nolock(struct address_space *mapping, unsigned long offset, struct page *page)
 {
 	goto inside;
 
@@ -367,7 +365,7 @@
 inside:
 		if (!page)
 			goto not_found;
-		if (page->inode != inode)
+		if (page->mapping != mapping)
 			continue;
 		if (page->offset == offset)
 			break;
@@ -418,7 +416,7 @@
 	struct page *page;
 	int retval = 0;
 
-	head = &inode->i_pages;
+	head = &inode->i_data.pages;
 	start &= PAGE_MASK;
 
 	spin_lock(&pagecache_lock);
@@ -469,7 +467,7 @@
  * owned by us, referenced, but not uptodate and with no errors.
  */
 static inline void __add_to_page_cache(struct page * page,
-	struct inode * inode, unsigned long offset,
+	struct address_space *mapping, unsigned long offset,
 	struct page **hash)
 {
 	struct page *alias;
@@ -477,37 +475,36 @@
 
 	flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced));
 	page->flags = flags | (1 << PG_locked);
-	page->owner = current;	/* REMOVEME */
 	get_page(page);
 	page->offset = offset;
-	add_page_to_inode_queue(inode, page);
+	add_page_to_inode_queue(mapping, page);
 	__add_page_to_hash_queue(page, hash);
 	lru_cache_add(page);
-	alias = __find_page_nolock(inode, offset, *hash);
+	alias = __find_page_nolock(mapping, offset, *hash);
 	if (alias != page)
 		BUG();
 }
 
-void add_to_page_cache(struct page * page, struct inode * inode, unsigned long offset)
+void add_to_page_cache(struct page * page, struct address_space * mapping, unsigned long offset)
 {
 	spin_lock(&pagecache_lock);
-	__add_to_page_cache(page, inode, offset, page_hash(inode, offset));
+	__add_to_page_cache(page, mapping, offset, page_hash(mapping, offset));
 	spin_unlock(&pagecache_lock);
 }
 
 int add_to_page_cache_unique(struct page * page,
-	struct inode * inode, unsigned long offset,
+	struct address_space *mapping, unsigned long offset,
 	struct page **hash)
 {
 	int err;
 	struct page *alias;
 
 	spin_lock(&pagecache_lock);
-	alias = __find_page_nolock(inode, offset, *hash);
+	alias = __find_page_nolock(mapping, offset, *hash);
 
 	err = 1;
 	if (!alias) {
-		__add_to_page_cache(page,inode,offset,hash);
+		__add_to_page_cache(page,mapping,offset,hash);
 		err = 0;
 	}
 
@@ -522,11 +519,11 @@
 static inline void page_cache_read(struct file * file, unsigned long offset) 
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct page **hash = page_hash(inode, offset);
+	struct page **hash = page_hash(&inode->i_data, offset);
 	struct page *page; 
 
 	spin_lock(&pagecache_lock);
-	page = __find_page_nolock(inode, offset, *hash); 
+	page = __find_page_nolock(&inode->i_data, offset, *hash); 
 	spin_unlock(&pagecache_lock);
 	if (page)
 		return;
@@ -535,7 +532,7 @@
 	if (!page)
 		return;
 
-	if (!add_to_page_cache_unique(page, inode, offset, hash)) {
+	if (!add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
 		inode->i_op->readpage(file, page);
 		page_cache_release(page);
 		return;
@@ -605,7 +602,7 @@
  * a rather lightweight function, finding and getting a reference to a
  * hashed page atomically, waiting for it if it's locked.
  */
-struct page * __find_get_page (struct inode * inode,
+struct page * __find_get_page (struct address_space *mapping,
 				unsigned long offset, struct page **hash)
 {
 	struct page *page;
@@ -616,7 +613,7 @@
 	 */
 repeat:
 	spin_lock(&pagecache_lock);
-	page = __find_page_nolock(inode, offset, *hash);
+	page = __find_page_nolock(mapping, offset, *hash);
 	if (page)
 		get_page(page);
 	spin_unlock(&pagecache_lock);
@@ -655,7 +652,7 @@
 /*
  * Get the lock to a page atomically.
  */
-struct page * __find_lock_page (struct inode * inode,
+struct page * __find_lock_page (struct address_space *mapping,
 				unsigned long offset, struct page **hash)
 {
 	struct page *page;
@@ -666,7 +663,7 @@
 	 */
 repeat:
 	spin_lock(&pagecache_lock);
-	page = __find_page_nolock(inode, offset, *hash);
+	page = __find_page_nolock(mapping, offset, *hash);
 	if (page)
 		get_page(page);
 	spin_unlock(&pagecache_lock);
@@ -1005,10 +1002,10 @@
 		/*
 		 * Try to find the data in the page cache..
 		 */
-		hash = page_hash(inode, pos & PAGE_CACHE_MASK);
+		hash = page_hash(&inode->i_data, pos & PAGE_CACHE_MASK);
 
 		spin_lock(&pagecache_lock);
-		page = __find_page_nolock(inode, pos & PAGE_CACHE_MASK, *hash);
+		page = __find_page_nolock(&inode->i_data, pos & PAGE_CACHE_MASK, *hash);
 		if (!page)
 			goto no_cached_page;
 found_page:
@@ -1104,7 +1101,7 @@
 			 * dropped the page cache lock. Check for that.
 			 */
 			spin_lock(&pagecache_lock);
-			page = __find_page_nolock(inode, pos & PAGE_CACHE_MASK, *hash);
+			page = __find_page_nolock(&inode->i_data, pos & PAGE_CACHE_MASK, *hash);
 			if (page)
 				goto found_page;
 		}
@@ -1113,7 +1110,7 @@
 		 * Ok, add the new page to the hash-queues...
 		 */
 		page = cached_page;
-		__add_to_page_cache(page, inode, pos & PAGE_CACHE_MASK, hash);
+		__add_to_page_cache(page, &inode->i_data, pos & PAGE_CACHE_MASK, hash);
 		spin_unlock(&pagecache_lock);
 		cached_page = NULL;
 
@@ -1316,9 +1313,9 @@
 	/*
 	 * Do we have something in the page cache already?
 	 */
-	hash = page_hash(inode, offset);
+	hash = page_hash(&inode->i_data, offset);
 retry_find:
-	page = __find_get_page(inode, offset, hash);
+	page = __find_get_page(&inode->i_data, offset, hash);
 	if (!page)
 		goto no_cached_page;
 
@@ -1441,27 +1438,25 @@
 	return retval;
 }
 
-static int filemap_write_page(struct vm_area_struct * vma,
+static int filemap_write_page(struct file *file,
 			      unsigned long offset,
 			      struct page * page,
 			      int wait)
 {
 	int result;
-	struct file * file;
 	struct dentry * dentry;
 	struct inode * inode;
 
-	file = vma->vm_file;
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 
 	/*
 	 * If a task terminates while we're swapping the page, the vma and
-	 * and file could be released ... increment the count to be safe.
+	 * and file could be released: try_to_swap_out has done a get_file.
+	 * vma/file is guaranteed to exist in the unmap/sync cases because
+	 * mmap_sem is held.
 	 */
-	get_file(file);
 	result = do_write_page(inode, file, page, offset);
-	fput(file);
 	return result;
 }
 
@@ -1472,9 +1467,9 @@
  * at the same time..
  */
 extern void wakeup_bdflush(int);
-int filemap_swapout(struct vm_area_struct * vma, struct page * page)
+int filemap_swapout(struct page * page, struct file * file)
 {
-	int retval = filemap_write_page(vma, page->offset, page, 0);
+	int retval = filemap_write_page(file, page->offset, page, 0);
 	wakeup_bdflush(0);
 	return retval;
 }
@@ -1515,7 +1510,7 @@
 	}
 	if (PageHighMem(page))
 		BUG();
-	error = filemap_write_page(vma, address - vma->vm_start + vma->vm_offset, page, 1);
+	error = filemap_write_page(vma->vm_file, address - vma->vm_start + vma->vm_offset, page, 1);
 	page_cache_free(page);
 	return error;
 }
@@ -1821,9 +1816,9 @@
 		if (bytes > count)
 			bytes = count;
 
-		hash = page_hash(inode, pgpos);
+		hash = page_hash(&inode->i_data, pgpos);
 repeat_find:
-		page = __find_lock_page(inode, pgpos, hash);
+		page = __find_lock_page(&inode->i_data, pgpos, hash);
 		if (!page) {
 			if (!cached_page) {
 				cached_page = page_cache_alloc();
@@ -1833,7 +1828,7 @@
 				break;
 			}
 			page = cached_page;
-			if (add_to_page_cache_unique(page,inode,pgpos,hash))
+			if (add_to_page_cache_unique(page,&inode->i_data,pgpos,hash))
 				goto repeat_find;
 
 			cached_page = NULL;
@@ -1842,10 +1837,6 @@
 		/* We have exclusive IO access to the page.. */
 		if (!PageLocked(page)) {
 			PAGE_BUG(page);
-		} else {
-			if (page->owner != current) {
-				PAGE_BUG(page);
-			}
 		}
 
 		status = write_one_page(file, page, offset, bytes, buf);
diff -u --recursive --new-file v2.3.23/linux/mm/mmap.c linux/mm/mmap.c
--- v2.3.23/linux/mm/mmap.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/mmap.c	Mon Oct 25 11:14:33 1999
@@ -687,11 +687,6 @@
 		end = end > mpnt->vm_end ? mpnt->vm_end : end;
 		size = end - st;
 
-		/*
-		 * The lock_kernel interlocks with kswapd try_to_swap_out
-		 * invoking a driver swapout() method, and being able to
-		 * guarantee vma existance.
-		 */
 		lock_kernel();
 		if (mpnt->vm_ops && mpnt->vm_ops->unmap)
 			mpnt->vm_ops->unmap(mpnt, st, size);
diff -u --recursive --new-file v2.3.23/linux/mm/page_io.c linux/mm/page_io.c
--- v2.3.23/linux/mm/page_io.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/page_io.c	Tue Oct 26 11:13:07 1999
@@ -136,7 +136,7 @@
 		PAGE_BUG(page);
 	if (!PageSwapCache(page))
 		PAGE_BUG(page);
-	if (page->inode != &swapper_inode)
+	if (page->mapping != &swapper_space)
 		PAGE_BUG(page);
 	if (!rw_swap_page_base(rw, entry, page, wait))
 		UnlockPage(page);
diff -u --recursive --new-file v2.3.23/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.3.23/linux/mm/swap_state.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/swap_state.c	Tue Oct 26 11:12:39 1999
@@ -17,42 +17,12 @@
 
 #include <asm/pgtable.h>
 
-/* 
- * Keep a reserved false inode which we will use to mark pages in the
- * page cache are acting as swap cache instead of file cache. 
- *
- * We only need a unique pointer to satisfy the page cache, but we'll
- * reserve an entire zeroed inode structure for the purpose just to
- * ensure that any mistaken dereferences of this structure cause a
- * kernel oops.
- */
-
-static struct inode_operations swapper_inode_operations = {
-	NULL,				/* 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 */
-	NULL,				/* get_block */
-	NULL,				/* readpage */
-	NULL,				/* writepage */
-	block_flushpage,		/* flushpage */
-	NULL,				/* truncate */
-	NULL,				/* permission */
-	NULL,				/* smap */
-	NULL				/* revalidate */
-};
-
-struct inode swapper_inode = {
-	i_op: &swapper_inode_operations,
-	i_pages: {&swapper_inode.i_pages,&swapper_inode.i_pages}
+struct address_space swapper_space = {
+	{				/* pages	*/
+		&swapper_space.pages,	/*        .next */
+		&swapper_space.pages	/*	  .prev */
+	},
+	0				/* nrpages	*/
 };
 
 #ifdef SWAP_CACHE_INFO
@@ -77,9 +47,9 @@
 #endif
 	if (PageTestandSetSwapCache(page))
 		BUG();
-	if (page->inode)
+	if (page->mapping)
 		BUG();
-	add_to_page_cache(page, &swapper_inode, pte_val(entry));
+	add_to_page_cache(page, &swapper_space, pte_val(entry));
 }
 
 /*
@@ -173,11 +143,9 @@
 
 static inline void remove_from_swap_cache(struct page *page)
 {
-	struct inode *inode = page->inode;
+	struct address_space *mapping = page->mapping;
 
-	if (!inode)
-		BUG();
-	if (inode != &swapper_inode)
+	if (mapping != &swapper_space)
 		BUG();
 	if (!PageSwapCache(page))
 		PAGE_BUG(page);
@@ -205,8 +173,7 @@
 
 static void delete_from_swap_cache_nolock(struct page *page)
 {
-	if (!swapper_inode.i_op->flushpage ||
-	    swapper_inode.i_op->flushpage(&swapper_inode, page, 0))
+	if (block_flushpage(NULL, page, 0))
 		lru_cache_del(page);
 
 	__delete_from_swap_cache(page);
@@ -267,10 +234,10 @@
 		/*
 		 * Right now the pagecache is 32-bit only.
 		 */
-		found = find_lock_page(&swapper_inode, pte_val(entry));
+		found = find_lock_page(&swapper_space, pte_val(entry));
 		if (!found)
 			return 0;
-		if (found->inode != &swapper_inode || !PageSwapCache(found))
+		if (found->mapping != &swapper_space || !PageSwapCache(found))
 			goto out_bad;
 #ifdef SWAP_CACHE_INFO
 		swap_cache_find_success++;
diff -u --recursive --new-file v2.3.23/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.23/linux/mm/swapfile.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/swapfile.c	Mon Oct 25 13:04:55 1999
@@ -779,23 +779,26 @@
 
 void si_swapinfo(struct sysinfo *val)
 {
-	unsigned int i, j;
+	unsigned int i;
+	unsigned long freeswap = 0;
+	unsigned long totalswap = 0;
 
-	val->freeswap = val->totalswap = 0;
 	for (i = 0; i < nr_swapfiles; i++) {
+		unsigned int j;
 		if ((swap_info[i].flags & SWP_WRITEOK) != SWP_WRITEOK)
 			continue;
-		for (j = 0; j < swap_info[i].max; ++j)
+		for (j = 0; j < swap_info[i].max; ++j) {
 			switch (swap_info[i].swap_map[j]) {
 				case SWAP_MAP_BAD:
 					continue;
 				case 0:
-					++val->freeswap;
+					freeswap++;
 				default:
-					++val->totalswap;
+					totalswap++;
 			}
+		}
 	}
-	val->freeswap <<= PAGE_SHIFT;
-	val->totalswap <<= PAGE_SHIFT;
+	val->freeswap = freeswap;
+	val->totalswap = totalswap;
 	return;
 }
diff -u --recursive --new-file v2.3.23/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.3.23/linux/mm/vmalloc.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/vmalloc.c	Mon Oct 25 20:49:42 1999
@@ -42,7 +42,7 @@
 				__free_page(mem_map + map_nr);
 			continue;
 		}
-		printk("Whee.. Swapped out page in kernel page table\n");
+		printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");
 	} while (address < end);
 }
 
@@ -96,7 +96,7 @@
 	do {
 		struct page * page;
 		if (!pte_none(*pte))
-			printk("alloc_area_pte: page already exists\n");
+			printk(KERN_ERR "alloc_area_pte: page already exists\n");
 		page = get_free_highpage(GFP_KERNEL|__GFP_HIGHMEM);
 		if (!page)
 			return -ENOMEM;
@@ -184,7 +184,7 @@
 	if (!addr)
 		return;
 	if ((PAGE_SIZE-1) & (unsigned long) addr) {
-		printk("Trying to vfree() bad address (%p)\n", addr);
+		printk(KERN_ERR "Trying to vfree() bad address (%p)\n", addr);
 		return;
 	}
 	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
@@ -195,7 +195,7 @@
 			return;
 		}
 	}
-	printk("Trying to vfree() nonexistent vm area (%p)\n", addr);
+	printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr);
 }
 
 void * vmalloc(unsigned long size)
diff -u --recursive --new-file v2.3.23/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.23/linux/mm/vmscan.c	Fri Oct 22 13:21:55 1999
+++ linux/mm/vmscan.c	Mon Oct 25 11:14:33 1999
@@ -18,6 +18,7 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/file.h>
 
 #include <asm/pgtable.h>
 
@@ -36,6 +37,7 @@
 {
 	pte_t pte, entry;
 	struct page * page;
+	int (*swapout)(struct page *, struct file *);
 
 	pte = *page_table;
 	if (!pte_present(pte))
@@ -126,13 +128,16 @@
 	 * That would get rid of a lot of problems.
 	 */
 	flush_cache_page(vma, address);
-	if (vma->vm_ops && vma->vm_ops->swapout) {
+	if (vma->vm_ops && (swapout = vma->vm_ops->swapout)) {
 		int error;
+		struct file *file = vma->vm_file;
+		if (file) get_file(file);
 		pte_clear(page_table);
 		vma->vm_mm->rss--;
 		flush_tlb_page(vma, address);
 		vmlist_access_unlock(vma->vm_mm);
-		error = vma->vm_ops->swapout(vma, page);
+		error = swapout(page, file);
+		if (file) fput(file);
 		if (!error)
 			goto out_free_success;
 		__free_page(page);
diff -u --recursive --new-file v2.3.23/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.23/linux/net/core/dev.c	Fri Oct 15 15:25:14 1999
+++ linux/net/core/dev.c	Mon Oct 25 20:49:42 1999
@@ -374,6 +374,7 @@
 		*err=-ENOBUFS;
 		return NULL;
 	}
+	memset(dev, 0, sizeof(struct net_device));
 	dev->name=(char *)(dev+1);	/* Name string space */
 	*err=dev_alloc_name(dev,name);
 	if(*err<0)
diff -u --recursive --new-file v2.3.23/linux/net/decnet/Config.in linux/net/decnet/Config.in
--- v2.3.23/linux/net/decnet/Config.in	Fri Oct 15 15:25:14 1999
+++ linux/net/decnet/Config.in	Mon Oct 25 10:51:31 1999
@@ -2,7 +2,7 @@
 # DECnet configuration
 #
 bool '  DECnet: SIOCGIFCONF support' CONFIG_DECNET_SIOCGIFCONF 
-if [ "$CONFIG_EXPERIMENTAL" ]; then
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  DECnet: router support (EXPERIMENTAL)' CONFIG_DECNET_ROUTER
 fi
 bool '  DECnet: raw socket support' CONFIG_DECNET_RAW
diff -u --recursive --new-file v2.3.23/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.23/linux/net/irda/af_irda.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/af_irda.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Mon Sep 27 20:11:52 1999
+ * Modified at:   Fri Oct  1 19:11:04 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
  * 
@@ -76,7 +76,7 @@
 
 	err = sock_queue_rcv_skb(sk, skb);
 	if (err) {
-		DEBUG(1, __FUNCTION__ "(), error: no more mem!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), error: no more mem!\n");
 		self->rx_flow = FLOW_STOP;
 
 		/* When we return error, TTP will need to requeue the skb */
@@ -98,7 +98,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = (struct irda_sock *) instance;
 
@@ -129,7 +129,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = (struct irda_sock *) instance;
 
@@ -145,7 +145,7 @@
 	else
 		self->max_data_size = max_sdu_size;
 
-	DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+	IRDA_DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
 
@@ -173,7 +173,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = (struct irda_sock *) instance;
 
@@ -189,7 +189,7 @@
 	else
 		self->max_data_size = max_sdu_size;
 
-	DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+	IRDA_DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
 
@@ -212,13 +212,13 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 
 	skb = dev_alloc_skb(64);
 	if (skb == NULL) {
-		DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n");
 		return;
 	}
 
@@ -239,7 +239,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 	
 	self = (struct irda_sock *) instance;
 	ASSERT(self != NULL, return;);
@@ -249,16 +249,16 @@
 	
 	switch (flow) {
 	case FLOW_STOP:
-		DEBUG(1, __FUNCTION__ "(), IrTTP wants us to slow down\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), IrTTP wants us to slow down\n");
 		self->tx_flow = flow;
 		break;
 	case FLOW_START:
 		self->tx_flow = flow;
-		DEBUG(1, __FUNCTION__ "(), IrTTP wants us to start again\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), IrTTP wants us to start again\n");
 		wake_up_interruptible(sk->sleep);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 
@@ -273,7 +273,7 @@
 {
 	struct irda_sock *self;
 	
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(priv != NULL, return;);
 	self = (struct irda_sock *) priv;
@@ -283,7 +283,7 @@
 
 	/* Check if request succeeded */
 	if (result != IAS_SUCCESS) {
-		DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
 
 		self->errno = result;
 
@@ -295,7 +295,7 @@
 
 	switch (value->type) {
 	case IAS_INTEGER:
-		DEBUG(4, __FUNCTION__ "() int=%d\n", value->t.integer);
+		IRDA_DEBUG(4, __FUNCTION__ "() int=%d\n", value->t.integer);
 		
 		if (value->t.integer != -1) {
 			self->dtsap_sel = value->t.integer;
@@ -303,7 +303,7 @@
 			self->dtsap_sel = 0;
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), bad type!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), bad type!\n");
 		break;
 	}
 	/* Wake up any processes waiting for result */
@@ -318,7 +318,7 @@
  */
 static void irda_discovery_indication(hashbin_t *log)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	cachelog = log;
 
@@ -349,7 +349,7 @@
 	self->tsap = irttp_open_tsap(tsap_sel, DEFAULT_INITIAL_CREDIT,
 				     &notify);	
 	if (self->tsap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
 		return -1;
 	}
 	/* Remember which TSAP selector we actually got */
@@ -366,7 +366,7 @@
  */
 static int irda_find_lsap_sel(struct irda_sock *self, char *name)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 
@@ -408,8 +408,8 @@
 		saddr.sir_addr = sk->protinfo.irda->saddr;
 	}
 	
-	DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel);
-	DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr);
+	IRDA_DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel);
+	IRDA_DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr);
 
 	if (*uaddr_len > sizeof (struct sockaddr_irda))
 		*uaddr_len = sizeof (struct sockaddr_irda);
@@ -493,7 +493,7 @@
 	struct sk_buff *skb;
 	int err;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
@@ -538,7 +538,7 @@
 	/* Now attach up the new socket */
 	new->tsap = irttp_dup(self->tsap, new);
 	if (!new->tsap) {
-		DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
 		return -1;
 	}
 		
@@ -610,12 +610,12 @@
 		return -EINVAL;
 
 	self->daddr = addr->sir_addr;
-	DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
+	IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
 
 	/* Query remote LM-IAS */
 	err = irda_find_lsap_sel(self, addr->sir_name);
 	if (err) {
-		DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
 		return err;
 	}
 
@@ -632,7 +632,7 @@
 				    self->saddr, self->daddr, NULL, 
 				    self->max_sdu_size_rx, NULL);
 	if (err) {
-		DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
 		return err;
 	}
 
@@ -676,7 +676,7 @@
 	struct sock *sk;
 	struct irda_sock *self;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	/* Check for valid socket type */
 	switch (sock->type) {
@@ -730,7 +730,7 @@
  */
 void irda_destroy_socket(struct irda_sock *self)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 
@@ -766,7 +766,7 @@
 {
 	struct sock *sk = sock->sk;
 	
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
         if (sk == NULL) 
 		return 0;
@@ -800,7 +800,7 @@
 	unsigned char *asmptr;
 	int err;
 
-	DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
 
 	if (msg->msg_flags & ~MSG_DONTWAIT)
 		return -EINVAL;
@@ -815,7 +815,7 @@
 
 	/* Check if IrTTP is wants us to slow down */
 	while (self->tx_flow == FLOW_STOP) {
-		DEBUG(2, __FUNCTION__ "(), IrTTP is busy, going to sleep!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IrTTP is busy, going to sleep!\n");
 		interruptible_sleep_on(sk->sleep);
 		
 		/* Check if we are still connected */
@@ -825,7 +825,7 @@
 
 	/* Check that we don't send out to big frames */
 	if (len > self->max_data_size) {
-		DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+		IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
 		      "Chopping frame from %d to %d bytes!\n", len, 
 		      self->max_data_size);
 		len = self->max_data_size;
@@ -838,7 +838,7 @@
 
 	skb_reserve(skb, self->max_header_size);
 	
-	DEBUG(4, __FUNCTION__ "(), appending user data\n");
+	IRDA_DEBUG(4, __FUNCTION__ "(), appending user data\n");
 	asmptr = skb->h.raw = skb_put(skb, len);
 	memcpy_fromiovec(asmptr, msg->msg_iov, len);
 
@@ -848,7 +848,7 @@
 	 */
 	err = irttp_data_request(self->tsap, skb);
 	if (err) {
-		DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+		IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
 		return err;
 	}
 	return len;
@@ -868,7 +868,7 @@
 	struct sk_buff *skb;
 	int copied, err;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
@@ -897,7 +897,7 @@
 	 */
 	if (self->rx_flow == FLOW_STOP) {
 		if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) {
-			DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
 			self->rx_flow = FLOW_START;
 			irttp_flow_request(self->tsap, FLOW_START);
 		}
@@ -936,7 +936,7 @@
 	int copied = 0;
 	int target = 1;
 
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
@@ -1021,7 +1021,7 @@
 
 			/* put the skb back if we didn't use it up.. */
 			if (skb->len) {
-				DEBUG(1, __FUNCTION__ "(), back on q!\n");
+				IRDA_DEBUG(1, __FUNCTION__ "(), back on q!\n");
 				skb_queue_head(&sk->receive_queue, skb);
 				break;
 			}
@@ -1031,7 +1031,7 @@
 /* 			if (scm->fp) */
 /* 				break; */
 		} else {
-			DEBUG(0, __FUNCTION__ "() questionable!?\n");
+			IRDA_DEBUG(0, __FUNCTION__ "() questionable!?\n");
 			/* It is questionable, see note in unix_dgram_recvmsg. */
 /* 			if (UNIXCB(skb).fp) */
 /* 				scm->fp = scm_fp_dup(UNIXCB(skb).fp); */
@@ -1050,7 +1050,7 @@
 	 */
 	if (self->rx_flow == FLOW_STOP) {
 		if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) {
-			DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
 			self->rx_flow = FLOW_START;
 			irttp_flow_request(self->tsap, FLOW_START);
 		}
@@ -1069,7 +1069,7 @@
  */
 static int irda_shutdown( struct socket *sk, int how)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "()\n");
 
         /* FIXME - generate DM and RNR states */
         return -EOPNOTSUPP;
@@ -1087,7 +1087,7 @@
 	struct sock *sk = sock->sk;
 	unsigned int mask;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	poll_wait(file, sk->sleep, wait);
 	mask = 0;
@@ -1126,7 +1126,7 @@
 {
 	struct sock *sk = sock->sk;
 
-	DEBUG(4, __FUNCTION__ "(), cmd=%#x\n", cmd);
+	IRDA_DEBUG(4, __FUNCTION__ "(), cmd=%#x\n", cmd);
 	
 	switch (cmd) {
 	case TIOCOUTQ: {
@@ -1173,7 +1173,7 @@
 	case SIOCSIFMETRIC:
 		return -EINVAL;		
 	default:
-		DEBUG(1, __FUNCTION__ "(), doing device ioctl!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), doing device ioctl!\n");
 		return dev_ioctl(cmd, (void *) arg);
 	}
 
@@ -1208,10 +1208,10 @@
 	
 	switch (optname) {
 	case IRLMP_IAS_SET:
-		DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
 		return 0;
 	case IRTTP_MAX_SDU_SIZE:
-		DEBUG(2, __FUNCTION__ "(), setting max_sdu_size = %d\n", opt);
+		IRDA_DEBUG(2, __FUNCTION__ "(), setting max_sdu_size = %d\n", opt);
 		self->max_sdu_size_rx = opt;
 		break;
 	default:
@@ -1265,7 +1265,7 @@
 		offset = sizeof(struct irda_device_list) - 
 			sizeof(struct irda_device_info);
 
-		total = offset;    /* Initialized to size of the device list */
+		total = offset;   /* Initialized to size of the device list */
 		list.len = 0;     /* Initialize lenght of list */
 
 		/* 
@@ -1279,7 +1279,7 @@
 			if (discovery->hints.word & self->mask) {
 				
 				/* Check if room for this device entry */
-				if (len - total >= sizeof(struct irda_device_info))
+				if (len - total < sizeof(struct irda_device_info))
 					break;
 
 				/* Copy discovery information */
@@ -1291,7 +1291,7 @@
 				strncpy(info->info, discovery->nickname,
 					NICKNAME_MAX_LEN);
 
-				if (copy_to_user(optval+offset, &info, 
+				if (copy_to_user(optval+offset, info, 
 						 sizeof(struct irda_device_info)))
 					return -EFAULT;
 				list.len++;
@@ -1313,7 +1313,7 @@
 		break;
 	case IRTTP_MAX_SDU_SIZE:
 		val = self->max_data_size;
-		DEBUG(2, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
+		IRDA_DEBUG(2, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
 		len = sizeof(int);
 		if (put_user(len, optlen))
 			return -EFAULT;
@@ -1397,11 +1397,11 @@
 	
         switch (event) {
 	case NETDEV_UP:
-		DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");
+		IRDA_DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");
 		/* irda_dev_device_up(dev); */
 		break;
 	case NETDEV_DOWN:
-		DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");
+		IRDA_DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");
 		/* irda_kill_by_device(dev); */
 		/* irda_rt_device_down(dev); */
 		/* irda_dev_device_down(dev); */
diff -u --recursive --new-file v2.3.23/linux/net/irda/discovery.c linux/net/irda/discovery.c
--- v2.3.23/linux/net/irda/discovery.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/discovery.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr  6 15:33:50 1999
- * Modified at:   Mon Aug 23 09:48:40 1999
+ * Modified at:   Sat Oct  9 17:11:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Fri May 28  3:11 CST 1999
  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
@@ -32,7 +32,6 @@
 
 #include <linux/string.h>
 #include <linux/socket.h>
-#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irlmp.h>
@@ -78,7 +77,7 @@
 
 
 	/* Insert the new and updated version */
-	hashbin_insert(cachelog, (QUEUE *) new, new->daddr, NULL);
+	hashbin_insert(cachelog, (queue_t *) new, new->daddr, NULL);
 
 	spin_unlock_irqrestore(&irlmp->lock, flags);
 }
@@ -93,7 +92,7 @@
 {
 	discovery_t *discovery;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/*
 	 *  If log is missing this means that IrLAP was unable to perform the
@@ -126,7 +125,7 @@
 {
 	discovery_t *discovery, *curr;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	discovery = (discovery_t *) hashbin_get_first(log);
 	while (discovery != NULL) {
@@ -160,10 +159,10 @@
 
 	discovery = (discovery_t *) hashbin_get_first(log);
 	while (discovery != NULL) {
-		DEBUG(0, "Discovery:\n");
-		DEBUG(0, "  daddr=%08x\n", discovery->daddr);
-		DEBUG(0, "  saddr=%08x\n", discovery->saddr); 
-		DEBUG(0, "  nickname=%s\n", discovery->nickname);
+		IRDA_DEBUG(0, "Discovery:\n");
+		IRDA_DEBUG(0, "  daddr=%08x\n", discovery->daddr);
+		IRDA_DEBUG(0, "  saddr=%08x\n", discovery->saddr); 
+		IRDA_DEBUG(0, "  nickname=%s\n", discovery->nickname);
 
 		discovery = (discovery_t *) hashbin_get_next(log);
 	}
@@ -186,9 +185,9 @@
 	/* Look at all discoveries for that link */
 	d = (discovery_t *) hashbin_get_first(cachelog);
 	while (d != NULL) {
-		DEBUG(1, "Discovery:\n");
-		DEBUG(1, "  daddr=%08x\n", d->daddr);
-		DEBUG(1, "  nickname=%s\n", d->nickname);
+		IRDA_DEBUG(1, "Discovery:\n");
+		IRDA_DEBUG(1, "  daddr=%08x\n", d->daddr);
+		IRDA_DEBUG(1, "  nickname=%s\n", d->nickname);
 		
 		if (strcmp(name, d->nickname) == 0) {
 			*saddr = d->saddr;
diff -u --recursive --new-file v2.3.23/linux/net/irda/ircomm/ircomm_core.c linux/net/irda/ircomm/ircomm_core.c
--- v2.3.23/linux/net/irda/ircomm/ircomm_core.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/ircomm/ircomm_core.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 20:37:34 1999
- * Modified at:   Tue Aug 17 11:05:41 1999
+ * Modified at:   Tue Oct  5 11:37:11 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -128,7 +128,7 @@
 	self->service_type = service_type;
 	self->line = line;
 
-	hashbin_insert(ircomm, (QUEUE *) self, line, NULL);
+	hashbin_insert(ircomm, (queue_t *) self, line, NULL);
 
 	ircomm_next_state(self, IRCOMM_IDLE);	
 
diff -u --recursive --new-file v2.3.23/linux/net/irda/ircomm/ircomm_param.c linux/net/irda/ircomm/ircomm_param.c
--- v2.3.23/linux/net/irda/ircomm/ircomm_param.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/ircomm/ircomm_param.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Jun  7 10:25:11 1999
- * Modified at:   Fri Sep  3 09:28:20 1999
+ * Modified at:   Mon Oct  4 09:36:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -236,7 +236,7 @@
 /*
  * Function ircomm_param_port_name (self, param)
  *
- *    
+ *    Exchange port name
  *
  */
 static int ircomm_param_port_name(void *instance, param_t *param, int get)
@@ -259,7 +259,7 @@
 /*
  * Function ircomm_param_data_rate (self, param)
  *
- *    
+ *    Exchange data rate to be used in this session
  *
  */
 static int ircomm_param_data_rate(void *instance, param_t *param, int get)
@@ -282,7 +282,7 @@
 /*
  * Function ircomm_param_data_format (self, param)
  *
- *    
+ *    Exchange data format to be used in this session
  *
  */
 static int ircomm_param_data_format(void *instance, param_t *param, int get)
@@ -303,7 +303,7 @@
 /*
  * Function ircomm_param_flow_control (self, param)
  *
- *    
+ *    Exchange flow control settings to be used in this session
  *
  */
 static int ircomm_param_flow_control(void *instance, param_t *param, int get)
@@ -326,12 +326,26 @@
 /*
  * Function ircomm_param_xon_xoff (self, param)
  *
- *    
+ *    Exchange XON/XOFF characters
  *
  */
 static int ircomm_param_xon_xoff(void *instance, param_t *param, int get)
 {
-	DEBUG(2, __FUNCTION__ "(), not impl.\n");
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get) {
+		param->pv.s = self->session.xonxoff[0];
+		param->pv.s |= self->session.xonxoff[1] << 8;
+	} else {
+		self->session.xonxoff[0] = param->pv.s & 0xff;
+		self->session.xonxoff[1] = param->pv.s >> 8;
+	}
+
+	DEBUG(0, __FUNCTION__ "(), XON/XOFF = 0x%02x\n,0x%02x", 
+	      param->pv.s & 0xff, param->pv.s >> 8);
 
 	return 0;
 }
@@ -339,12 +353,26 @@
 /*
  * Function ircomm_param_enq_ack (self, param)
  *
- *    
+ *    Exchange ENQ/ACK characters
  *
  */
 static int ircomm_param_enq_ack(void *instance, param_t *param, int get)
 {
-	DEBUG(2, __FUNCTION__ "(), not impl.\n");
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get) {
+		param->pv.s = self->session.enqack[0];
+		param->pv.s |= self->session.enqack[1] << 8;
+	} else {
+		self->session.enqack[0] = param->pv.s & 0xff;
+		self->session.enqack[1] = param->pv.s >> 8;
+	}
+
+	DEBUG(0, __FUNCTION__ "(), ENQ/ACK = 0x%02x,0x%02x\n",
+	      param->pv.s & 0xff, param->pv.s >> 8);
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c
--- v2.3.23/linux/net/irda/ircomm/ircomm_tty.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/ircomm/ircomm_tty.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 21:00:56 1999
- * Modified at:   Tue Sep 21 11:46:59 1999
+ * Modified at:   Tue Oct 19 21:32:04 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
  * 
@@ -408,7 +408,7 @@
 		tty->termios->c_oflag = 0;
 
 		/* Insert into hash */
-		hashbin_insert(ircomm_tty, (QUEUE *) self, line, NULL);
+		hashbin_insert(ircomm_tty, (queue_t *) self, line, NULL);
 	}
 	self->open_count++;
 
@@ -796,7 +796,7 @@
 	orig_jiffies = jiffies;
 
 	/* Set poll time to 200 ms */
-	poll_time = MIN(timeout, MSECS_TO_JIFFIES(200));
+	poll_time = IRDA_MIN(timeout, MSECS_TO_JIFFIES(200));
 
 	while (self->tx_skb && self->tx_skb->len) {
 		current->state = TASK_INTERRUPTIBLE;
@@ -939,8 +939,6 @@
  */
 static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
 {
-	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
-
 	DEBUG(0, __FUNCTION__"(), not impl\n");
 }
 
@@ -1082,7 +1080,7 @@
 
 	clen = skb->data[0];
 
-	irda_param_extract_all(self, skb->data+1, MIN(skb->len-1, clen), 
+	irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen), 
 			       &ircomm_param_info);
 	dev_kfree_skb(skb);
 
diff -u --recursive --new-file v2.3.23/linux/net/irda/ircomm/ircomm_tty_attach.c linux/net/irda/ircomm/ircomm_tty_attach.c
--- v2.3.23/linux/net/irda/ircomm/ircomm_tty_attach.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/ircomm/ircomm_tty_attach.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Jun  5 17:42:00 1999
- * Modified at:   Wed Sep  8 11:54:27 1999
+ * Modified at:   Tue Oct 19 21:32:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -208,7 +208,6 @@
 		irias_insert_object(self->obj);
 	} else {
 		hints = irlmp_service_to_hint(S_COMM);
-		hints |= irlmp_service_to_hint(S_TELEPHONY);
 
 		/* Register IrCOMM with LM-IAS */
 		self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID);
@@ -243,13 +242,24 @@
 	if (self->service_type & IRCOMM_3_WIRE_RAW) 
 		return 0;
 
-	/* Set default values */
-	self->session.data_rate = 9600;
-	self->session.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
-	self->session.flow_control = 0;              /* None */
+	/* 
+	 * Set default values, but only if the application for some reason 
+	 * haven't set them already
+	 */
+	DEBUG(2, __FUNCTION__ "(), data-rate = %d\n", self->session.data_rate);
+	if (!self->session.data_rate)
+		self->session.data_rate = 9600;
+	DEBUG(2, __FUNCTION__ "(), data-format = %d\n", 
+	      self->session.data_format);
+	if (!self->session.data_format)
+		self->session.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
+
+	DEBUG(2, __FUNCTION__ "(), flow-control = %d\n", 
+	      self->session.flow_control);
+	/*self->session.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
 
 	/* Do not set delta values for the initial parameters */
-	self->session.dte = (IRCOMM_DTR| IRCOMM_RTS);
+	self->session.dte = IRCOMM_DTR | IRCOMM_RTS;
 
 	ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE);
 	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
@@ -430,7 +440,8 @@
 
 	clen = skb->data[0];
 	if (clen)
-		irda_param_extract_all(self, skb->data+1, MIN(skb->len, clen), 
+		irda_param_extract_all(self, skb->data+1, 
+				       IRDA_MIN(skb->len, clen), 
 				       &ircomm_param_info);
 
 	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
diff -u --recursive --new-file v2.3.23/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.3.23/linux/net/irda/irda_device.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irda_device.c	Mon Oct 25 20:49:42 1999
@@ -1,26 +1,30 @@
 /*********************************************************************
  *                
  * Filename:      irda_device.c
- * Version:       0.6
- * Description:   Abstract device driver layer and helper functions
+ * Version:       0.9
+ * Description:   Utility functions used by the device drivers
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Tue Sep 28 08:40:31 1999
+ * Created at:    Sat Oct  9 09:22:27 1999
+ * Modified at:   Mon Oct 18 22:40:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Modified at:   Fri May 28  3:11 CST 1999
- * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
- *      
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
  *     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.
- *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ * 
+ *     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
  *     
  ********************************************************************/
 
@@ -46,7 +50,7 @@
 #include <net/pkt_sched.h>
 
 #include <net/irda/irda_device.h>
-#include <net/irda/irlap_frame.h>
+#include <net/irda/irlap.h>
 #include <net/irda/timer.h>
 #include <net/irda/wrapper.h>
 
@@ -58,33 +62,38 @@
 extern int actisys_init(void);
 extern int girbil_init(void);
 
-static hashbin_t *irda_device = NULL;
 static hashbin_t *dongles = NULL;
+static hashbin_t *tasks = NULL;
+
+const char *infrared_mode[] = {
+	"IRDA_IRLAP",
+	"IRDA_RAW",
+	"SHARP_ASK",
+	"TV_REMOTE",
+};
+
+static const char *task_state[] = {
+	"IRDA_TASK_INIT",
+	"IRDA_TASK_DONE", 
+	"IRDA_TASK_WAIT",
+	"IRDA_TASK_WAIT1",
+	"IRDA_TASK_WAIT2",
+	"IRDA_TASK_WAIT3",
+	"IRDA_TASK_CHILD_INIT",
+	"IRDA_TASK_CHILD_WAIT",
+	"IRDA_TASK_CHILD_DONE",
+};
+
+static void irda_task_timer_expired(void *data);
 
-/* Netdevice functions */
-static int irda_device_net_rebuild_header(struct sk_buff *skb);
-static int irda_device_net_hard_header(struct sk_buff *skb, 
-				       struct net_device *dev,
-				       unsigned short type, void *daddr, 
-				       void *saddr, unsigned len);
-static int irda_device_net_set_config(struct net_device *dev, struct ifmap *map);
-static int irda_device_net_change_mtu(struct net_device *dev, int new_mtu);
-static int irda_device_net_ioctl(struct net_device *dev, struct ifreq *rq,int cmd);
 #ifdef CONFIG_PROC_FS
-int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
-			   int unused);
+int irda_device_proc_read(char *buf, char **start, off_t offset, int len, 
+			  int unused);
 
 #endif /* CONFIG_PROC_FS */
 
 int __init irda_device_init( void)
 {
-	/* Allocate master array */
-	irda_device = hashbin_new( HB_LOCAL);
-	if (irda_device == NULL) {
-		WARNING("IrDA: Can't allocate irda_device hashbin!\n");
-		return -ENOMEM;
-	}
-
 	dongles = hashbin_new(HB_LOCAL);
 	if (dongles == NULL) {
 		printk(KERN_WARNING 
@@ -92,6 +101,13 @@
 		return -ENOMEM;
 	}
 
+	tasks = hashbin_new(HB_LOCAL);
+	if (tasks == NULL) {
+		printk(KERN_WARNING 
+		       "IrDA: Can't allocate tasks hashbin!\n");
+		return -ENOMEM;
+	}
+
 	/* 
 	 * Call the init function of the device drivers that has not been
 	 * compiled as a module 
@@ -134,287 +150,215 @@
 
 void irda_device_cleanup(void)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(irda_device != NULL, return;);
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
+	hashbin_delete(tasks, NULL);
 	hashbin_delete(dongles, NULL);
-	hashbin_delete(irda_device, (FREE_FUNC) irda_device_close);
 }
 
 /*
- * Function irda_device_open (self)
- *
- *    Open a new IrDA port device
+ * Function irda_device_set_media_busy (self, status)
  *
+ *    Called when we have detected that another station is transmiting
+ *    in contention mode.
  */
-int irda_device_open(struct irda_device *self, char *name, void *priv)
-{        
-	int result;
-	int i=0;
-
-	/* Allocate memory if needed */
-	if (self->rx_buff.truesize > 0) {
-		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
-						      self->rx_buff.flags);
-		if (self->rx_buff.head == NULL)
-			return -ENOMEM;
+void irda_device_set_media_busy(struct net_device *dev, int status) 
+{
+	struct irlap_cb *self;
 
-		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
-	}
-	if (self->tx_buff.truesize > 0) {
-		self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
-						      self->tx_buff.flags);
-		if (self->tx_buff.head == NULL) {
-			kfree(self->rx_buff.head);
-			return -ENOMEM;
-		}
+	IRDA_DEBUG(4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE");
 
-		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
-	}
-	
-      	self->magic = IRDA_DEVICE_MAGIC;
+	self = (struct irlap_cb *) dev->atalk_ptr;
 
-	self->rx_buff.in_frame = FALSE;
-	self->rx_buff.state = OUTSIDE_FRAME;
-	self->tx_buff.data = self->tx_buff.head;
-	self->rx_buff.data = self->rx_buff.head;
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	/* Initialize timers */
-	init_timer(&self->media_busy_timer);	
+	if (status) {
+		self->media_busy = TRUE;
+		irlap_start_mbusy_timer(self);
+		IRDA_DEBUG( 4, "Media busy!\n");
+	} else {
+		self->media_busy = FALSE;
+		del_timer(&self->media_busy_timer);
+	}
+}
 
-	self->lock = SPIN_LOCK_UNLOCKED;
+int irda_device_set_dtr_rts(struct net_device *dev, int dtr, int rts)
+{	
+	struct if_irda_req req;
+	int ret;
 
-	/* A pointer to the low level implementation */
-	self->priv = priv;
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
-	/* Initialize IrDA net device */
-	do {
-		sprintf(self->name, "%s%d", "irda", i++);
-	} while (dev_get(self->name));
-	
-	self->netdev.name = self->name;
-	self->netdev.priv = (void *) self;
-	self->netdev.next = NULL;
-	
-	result = register_netdev(&self->netdev);
-	if (result) {
-		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+	if (!dev->do_ioctl) {
+		ERROR(__FUNCTION__ "(), do_ioctl not impl. by "
+		      "device driver\n");
 		return -1;
 	}
-	
-	/* 
-	 * Make the description for the device. self->netdev.name will get
-	 * a name like "irda0" and the self->descriptin will get a name
-	 * like "irda0 <-> irtty0" 
-	 */
-	strncpy(self->description, self->name, 5);
-	strcat(self->description, " <-> ");
-	strncat(self->description, name, 23);
-	
-	hashbin_insert(irda_device, (QUEUE *) self, (int) self, NULL);
-	
-	MESSAGE("IrDA: Registered device %s\n", self->name);
 
-	irda_device_set_media_busy(&self->netdev, FALSE);
+	req.ifr_dtr = dtr;
+	req.ifr_rts = rts;
 
-	return 0;
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCSDTRRTS);
+
+	return ret;
 }
 
 /*
- * Function irda_device_close (self)
+ * Function irda_device_is_receiving (dev)
  *
- *    Close this instance of the irda_device, just deallocate buffers
+ *    Check if the device driver is currently receiving data
  *
  */
-void __irda_device_close(struct irda_device *self)
+int irda_device_is_receiving(struct net_device *dev)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	struct if_irda_req req;
+	int ret;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	/* We do this test to know if the device has been registered at all */
-	if (self->netdev.type == ARPHRD_IRDA) {
-		/* Remove netdevice */
-		unregister_netdev(&self->netdev);
+	if (!dev->do_ioctl) {
+		ERROR(__FUNCTION__ "(), do_ioctl not impl. by "
+		      "device driver\n");
+		return -1;
 	}
 
-	/* Stop timers */
-	del_timer(&self->media_busy_timer);
-
-	if (self->tx_buff.head)
-		kfree(self->tx_buff.head);
-
-	if (self->rx_buff.head)
-		kfree(self->rx_buff.head);
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCGRECEIVING);
+	if (ret < 0)
+		return ret;
 
-	self->magic = 0;
+	return req.ifr_receiving;
 }
 
-/*
- * Function irda_device_close (self)
- *
- *    Close the device
- *
- */
-void irda_device_close(struct irda_device *self)
+void irda_task_next_state(struct irda_task *task, TASK_STATE state)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
-
-	/* We are not using any dongle anymore! */
-	if (self->dongle)
-		self->dongle->close(self);
+	IRDA_DEBUG(2, __FUNCTION__ "(), state = %s\n", task_state[state]);
 
-	hashbin_remove(irda_device, (int) self, NULL);
-
-	__irda_device_close(self);
+	task->state = state;
 }
 
 /*
- * Function irda_device_set_media_busy (self, status)
+ * Function irda_task_kick (task)
  *
- *    Called when we have detected that another station is transmiting
- *    in contention mode.
+ *    Tries to execute a task possible multiple times until the task is either
+ *    finished, or askes for a timeout. When a task is finished, we do post
+ *    processing, and notify the parent task, that is waiting for this task
+ *    to complete.
  */
-void irda_device_set_media_busy(struct net_device *dev, int status) 
+int irda_task_kick(struct irda_task *task)
 {
-	struct irda_device *self;
+	int timeout;
+	int ret = 0;
+	int count = 0;
 
-	DEBUG(4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	self = dev->priv;
+	ASSERT(task != NULL, return -1;);
+	ASSERT(task->magic == IRDA_TASK_MAGIC, return -1;);
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	/* Execute task until it's finished, or askes for a timeout */
+	do {
+		timeout = task->function(task);
+		if (count++ > 100) {
+			ERROR(__FUNCTION__ "(), error in task handler!\n");
+			return -1;
+		}			
+	} while ((timeout == 0) && (task->state != IRDA_TASK_DONE));
 
-	if (status) {
-		self->media_busy = TRUE;
-		irda_device_start_mbusy_timer(self);
-		DEBUG( 4, "Media busy!\n");
-	} else {
-		self->media_busy = FALSE;
-		del_timer(&self->media_busy_timer);
+	if (timeout < 0) {
+		ERROR(__FUNCTION__ "(), Error executing task!\n");
+		return -1;
 	}
-}
 
-/*
- * Function __irda_device_change_speed (self, speed)
- *
- *    When this function is called, we will have a process context so its
- *    possible for us to sleep, wait or whatever :-)
- */
-static void __irda_device_change_speed(struct irda_device *self, int speed)
-{
-	int n = 0;
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	/*
-	 *  Is is possible to change speed yet? Wait until the last byte 
-	 *  has been transmitted.
-	 */
-	if (!self->wait_until_sent) {
-		ERROR("IrDA: wait_until_sent() "
-		      "has not implemented by the IrDA device driver!\n");
-		return;
+	/* Check if we are finished */
+	if (task->state == IRDA_TASK_DONE) {
+		del_timer(&task->timer);
+
+		/* Do post processing */
+		if (task->finished)
+			task->finished(task);
+
+		/* Notify parent */
+		if (task->parent) {
+			/* Check if parent is waiting for us to complete */
+			if (task->parent->state == IRDA_TASK_CHILD_WAIT) {
+				task->parent->state = IRDA_TASK_CHILD_DONE;
+
+				/* Stop timer now that we are here */
+				del_timer(&task->parent->timer);
+
+				/* Kick parent task */
+				irda_task_kick(task->parent);
+			}
+		}		
+		/* Unregister task */
+		hashbin_remove(tasks, (int) task, NULL);
+
+		kfree(task);
+	} else if (timeout > 0) {
+		irda_start_timer(&task->timer, timeout, (void *) task, 
+				 irda_task_timer_expired);
+		ret = 1;
+	} else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), not finished, and no timeout!\n");
+		ret = 1;
 	}
 
-	/* Make sure all transmitted data has actually been sent */
-	self->wait_until_sent(self);
-
-	/* Make sure nobody tries to transmit during the speed change */
-	while (irda_lock((void *) &self->netdev.tbusy) == FALSE) {
-		WARNING(__FUNCTION__ "(), device locked!\n");
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(MSECS_TO_JIFFIES(10));
-
-		if (n++ > 10) {
-			WARNING(__FUNCTION__ "(), breaking loop!\n");
-			return;
-		}
-	}
-	
-	/* Change speed of dongle */
-	if (self->dongle)
-		self->dongle->change_speed(self, speed);
-	
-	/* Change speed of IrDA port */
-	if (self->change_speed) {
-		self->change_speed(self, speed);
-		
-		/* Update the QoS value only */
-		self->qos.baud_rate.value = speed;
-	}
-	self->netdev.tbusy = FALSE;
+	return ret;
 }
 
 /*
- * Function irda_device_change_speed (self, speed)
- *
- *    Change the speed of the currently used irda_device
+ * Function irda_task_execute (instance, function, finished)
  *
+ *    This function registers and tries to execute tasks that may take some
+ *    time to complete. We do it this hairy way since we may have been
+ *    called from interrupt context, so it's not possible to use
+ *    schedule_timeout() 
  */
-void irda_device_change_speed(struct irda_device *self, int speed)
+int irda_task_execute(void *instance, TASK_CALLBACK function, 
+		      TASK_CALLBACK finished, struct irda_task *parent, 
+		      void *param)
 {
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	struct irda_task *task;
 
-	irda_execute_as_process(self, 
-				(TODO_CALLBACK) __irda_device_change_speed, 
-				speed);
-}
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-int irda_device_is_media_busy(struct net_device *dev)
-{
-	struct irda_device *self;
-	
-	self = dev->priv;
+	task = kmalloc(sizeof(struct irda_task), GFP_ATOMIC);
+	if (!task)
+		return -ENOMEM;
 
-	ASSERT(self != NULL, return FALSE;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
-	
-	return self->media_busy;
-}
+	task->state = IRDA_TASK_INIT;
+	task->instance = instance;
+	task->function = function;
+	task->finished = finished;
+	task->parent = parent;
+	task->param = param;	
+	task->magic = IRDA_TASK_MAGIC;
 
-int irda_device_is_receiving(struct net_device *dev)
-{
-	struct irda_device *self;
-	
-	self = dev->priv;
-	
-	ASSERT(self != NULL, return FALSE;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	init_timer(&task->timer);
 
-	if (self->is_receiving)
-		return self->is_receiving(self);
-	else
-		return FALSE;
+	/* Register task */
+	hashbin_insert(tasks, (queue_t *) task, (int) task, NULL);
+
+	/* No time to waste, so lets get going! */
+	return irda_task_kick(task);
 }
 
-struct qos_info *irda_device_get_qos(struct net_device *dev)
+/*
+ * Function irda_task_timer_expired (data)
+ *
+ *    Task time has expired. We now try to execute task (again), and restart
+ *    the timer if the task has not finished yet
+ */
+static void irda_task_timer_expired(void *data)
 {
-	struct irda_device *self;
-
-	ASSERT(dev != NULL, return NULL;);
-
-	self = dev->priv;
-
-	ASSERT(self != NULL, return NULL;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return NULL;);
+	struct irda_task *task;
 
-	return &self->qos;
-}
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-static struct enet_statistics *irda_device_get_stats(struct net_device *dev)
-{
-	struct irda_device *priv = (struct irda_device *) dev->priv;
+	task = (struct irda_task *) data;
 
-	return &priv->stats;
+	irda_task_kick(task);
 }
 
 /*
@@ -425,24 +369,14 @@
  */
 int irda_device_setup(struct net_device *dev) 
 {
-	struct irda_device *self;
-
 	ASSERT(dev != NULL, return -1;);
 
-	self = (struct irda_device *) dev->priv;
-
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);	
-
-	dev->get_stats	     = irda_device_get_stats;
-	dev->rebuild_header  = irda_device_net_rebuild_header;
-	dev->set_config      = irda_device_net_set_config;
-	dev->change_mtu      = irda_device_net_change_mtu;
-/*  	dev->hard_header     = irda_device_net_hard_header; */
-	dev->do_ioctl        = irda_device_net_ioctl;
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
+	dev->new_style       = 1;
+	/* dev->destructor      = irda_device_destructor; */
+
         dev->type            = ARPHRD_IRDA;
         dev->tx_queue_len    = 8; /* Window size + 1 s-frame */
  
@@ -458,314 +392,72 @@
 	return 0;
 }
 
-int irda_device_net_open(struct net_device *dev)
-{
-	struct irda_device *self;
-
-	ASSERT(dev != NULL, return -1;);
-
-	self = dev->priv;
-
-	ASSERT(self != NULL, return 0;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	/* 
-	 * Open new IrLAP layer instance, now that everything should be
-	 * initialized properly 
-	 */
-	self->irlap = irlap_open(dev);
-        
-	/* It's now safe to initilize the saddr */
-	memcpy(self->netdev.dev_addr, &self->irlap->saddr, 4);
-
-	return 0;
-}
-
-int irda_device_net_close(struct net_device *dev)
-{
-	struct irda_device *self;
-
-	ASSERT(dev != NULL, return -1;);
-
-	self = dev->priv;
-
-	ASSERT(self != NULL, return 0;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	/* Stop and remove instance of IrLAP */
-	if (self->irlap)
-		irlap_close(self->irlap);
-	self->irlap = NULL;
-
-	return 0;
-}
-
-/*
- * Function irda_device_net_rebuild_header (buff, dev, dst, skb)
- *
- *    
- *
- */
-static int irda_device_net_rebuild_header( struct sk_buff *skb)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	return 0;
-}
-
-static int irda_device_net_hard_header(struct sk_buff *skb, 
-				       struct net_device *dev,
-				       unsigned short type, void *daddr, 
-				       void *saddr, unsigned len)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	skb->mac.raw = skb->data;
-        /* skb_push(skb,PPP_HARD_HDR_LEN); */
-        /* return PPP_HARD_HDR_LEN; */
-	
-	return 0;
-}
-
-static int irda_device_net_set_config(struct net_device *dev, 
-				      struct ifmap *map)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	return 0;
-}
-
-static int irda_device_net_change_mtu(struct net_device *dev, int new_mtu)
-{
-     DEBUG( 0, __FUNCTION__ "()\n");
-     
-     return 0;  
-}
-
-static int irda_device_net_ioctl(struct net_device *dev, /* ioctl device */
-				 struct ifreq *rq,   /* Data passed */
-				 int	cmd)	     /* Ioctl number */
-{
-	unsigned long flags;
-	int			ret = 0;
-#ifdef WIRELESS_EXT
-	struct iwreq *wrq = (struct iwreq *) rq;
-#endif
-	struct irda_device *self;
-
-	ASSERT(dev != NULL, return -1;);
-
-	self = dev->priv;
-
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
-
-	DEBUG(0, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
-	
-	/* Disable interrupts & save flags */
-	save_flags(flags);
-	cli();
-	
-	/* Look what is the request */
-	switch (cmd) {
-#ifdef WIRELESS_EXT
-	case SIOCGIWNAME:
-		/* Get name */
-		strcpy(wrq->u.name, self->name);
-		break;
-	case SIOCSIWNWID:
-		/* Set domain */
-		if (wrq->u.nwid.on) {
-			
-		} break;
-	case SIOCGIWNWID:
-		/* Read domain*/
-/* 		wrq->u.nwid.nwid = domain; */
-/* 		wrq->u.nwid.on = 1; */
-		break;
-	case SIOCGIWENCODE:
-		/* Get scramble key */
-		/* 	wrq->u.encoding.code = scramble_key; */
-/* 		wrq->u.encoding.method = 1; */
-		break;
-	case SIOCSIWENCODE:
-		/* Set  scramble key */
-		/* scramble_key = wrq->u.encoding.code; */
-		break;
-	case SIOCGIWRANGE:
-		/* Basic checking... */
-		if(wrq->u.data.pointer != (caddr_t) 0) {
-			struct iw_range	range;
-			
-			/* Verify the user buffer */
-			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-					  sizeof(struct iw_range));
-			if(ret)
-				break;
-			
-			/* Set the length (useless : its constant...) */
-			wrq->u.data.length = sizeof(struct iw_range);
-			
-			/* Set information in the range struct */
-			range.throughput = 1.6 * 1024 * 1024;	/* don't argue on this ! */
-			range.min_nwid = 0x0000;
-			range.max_nwid = 0x01FF;
-			
-			range.num_channels = range.num_frequency = 0;
-			
-			range.sensitivity = 0x3F;
-			range.max_qual.qual = 255;
-			range.max_qual.level = 255;
-			range.max_qual.noise = 0;
-			
-			/* Copy structure to the user buffer */
-			copy_to_user(wrq->u.data.pointer, &range,
-				     sizeof(struct iw_range));
-		}
-		break;
-	case SIOCGIWPRIV:
-		/* Basic checking... */
-#if 0
-		if (wrq->u.data.pointer != (caddr_t) 0) {
-			struct iw_priv_args	priv[] =
-			{	/* cmd,		set_args,	get_args,	name */
-				{ SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0, 
-				  sizeof(struct site_survey), 
-				  "getsitesurvey" },
-			};
-			
-			/* Verify the user buffer */
-			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-					  sizeof(priv));
-			if (ret)
-				break;
-			
-			/* Set the number of ioctl available */
-			wrq->u.data.length = 1;
-			
-			/* Copy structure to the user buffer */
-			copy_to_user(wrq->u.data.pointer, (u_char *) priv,
-				     sizeof(priv));
-		}
-#endif 
-		break;
-#endif
-	case SIOCSBANDWIDTH: /* Set bandwidth */
-		irda_device_change_speed(self, rq->ifr_bandwidth);
-		break;
-	case SIOCSDONGLE: /* Set dongle */
-		/* Initialize dongle */
-		irda_device_init_dongle(self, (int) rq->ifr_data);
-		break;
-	case SIOCSMEDIABUSY: /* Set media busy */
-		irda_device_set_media_busy(&self->netdev, TRUE);
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-	}
-	
-	restore_flags(flags);
-	
-	return ret;
-}
-
 /*
- * Function irda_device_txqueue_empty (irda_device)
+ * Function irda_device_txqueue_empty (dev)
  *
  *    Check if there is still some frames in the transmit queue for this
  *    device. Maybe we should use: q->q.qlen == 0.
  *
  */
-int irda_device_txqueue_empty(struct irda_device *self)
+int irda_device_txqueue_empty(struct net_device *dev)
 {
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);	
-
-	if (skb_queue_len(&self->netdev.qdisc->q))
+	if (skb_queue_len(&dev->qdisc->q))
 		return FALSE;
 
 	return TRUE;
 }
 
 /*
- * Function irda_device_init_dongle (self, type)
+ * Function irda_device_init_dongle (self, type, qos)
  *
- *    Initialize attached dongle. Warning, must be called with a process
- *    context!
+ *    Initialize attached dongle.
  */
-void irda_device_init_dongle(struct irda_device *self, int type)
+dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
 {
-	struct dongle_q *node;
+	struct dongle_reg *reg;
+	char modname[32];
+	dongle_t *dongle;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(dev != NULL, return NULL;);
 
 #ifdef CONFIG_KMOD
 	/* Try to load the module needed */
-	switch (type) {
-	case ESI_DONGLE:
-		MESSAGE("IrDA: Initializing ESI dongle!\n");
-		request_module("esi");
-		break;
-	case TEKRAM_DONGLE:
-		MESSAGE("IrDA: Initializing Tekram dongle!\n");
-		request_module("tekram");
-		break;
-	case ACTISYS_DONGLE:     /* FALLTHROUGH */
-	case ACTISYS_PLUS_DONGLE:
-		MESSAGE("IrDA: Initializing ACTiSYS dongle!\n");
-		request_module("actisys");
-		break;
-	case GIRBIL_DONGLE:
-		MESSAGE("IrDA: Initializing GIrBIL dongle!\n");
-		request_module("girbil");
-		break;
-	case LITELINK_DONGLE:
-		MESSAGE("IrDA: Initializing Litelink dongle!\n");
-		request_module("litelink");
-		break;
-	case AIRPORT_DONGLE:
-		MESSAGE("IrDA: Initializing Airport dongle!\n");
-		request_module("airport");
-		break;
-	default:
-		ERROR("Unknown dongle type!\n");
-		return;
-	}
+	sprintf(modname, "irda-dongle-%d", type);
+	request_module(modname);
 #endif /* CONFIG_KMOD */
 
-	node = hashbin_find(dongles, type, NULL);
-	if (!node) {
+	if (!(reg = hashbin_find(dongles, type, NULL))) {
 		ERROR("IrDA: Unable to find requested dongle\n");
-		return;
-	}
-	
-	/* Check if we're already using a dongle */
-	if (self->dongle) {
-		self->dongle->close(self);
+		return NULL;
 	}
 
-	/* Set the dongle to be used by this driver */
-	self->dongle = node->dongle;
+	/* Allocate dongle info for this instance */
+	dongle = kmalloc(sizeof(dongle_t), GFP_KERNEL);
+	if (!dongle)
+		return NULL;
 
-	/* Now initialize the dongle!  */
-	node->dongle->open(self, type);
-	node->dongle->qos_init(self, &self->qos);
-	
-	/* Reset dongle */
-	node->dongle->reset(self);
+	/* Bind the registration info to this particular instance */
+	dongle->issue = reg;
+	dongle->dev = dev;
 
-	/* Set to default baudrate */
-	irda_device_change_speed(self, 9600);
+	return dongle;
+}
+
+/*
+ * Function irda_device_dongle_cleanup (dongle)
+ *
+ *    
+ *
+ */
+int irda_device_dongle_cleanup(dongle_t *dongle)
+{
+	ASSERT(dongle != NULL, return -1;);
+
+	dongle->issue->close(dongle);
+
+	kfree(dongle);
+
+	return 0;
 }
 
 /*
@@ -774,26 +466,16 @@
  *    
  *
  */
-int irda_device_register_dongle(struct dongle *dongle)
+int irda_device_register_dongle(struct dongle_reg *new)
 {
-	struct dongle_q *new;
-	
 	/* Check if this dongle has been registred before */
-	if (hashbin_find(dongles, dongle->type, NULL)) {
+	if (hashbin_find(dongles, new->type, NULL)) {
 		MESSAGE(__FUNCTION__ "(), Dongle already registered\n");
                 return 0;
         }
 	
-	/* Make new IrDA dongle */
-        new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
-        if (new == NULL)
-                return -1;
-		
-	memset(new, 0, sizeof( struct dongle_q));
-        new->dongle = dongle;
-
 	/* Insert IrDA dongle into hashbin */
-	hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL);
+	hashbin_insert(dongles, (queue_t *) new, new->type, NULL);
 	
         return 0;
 }
@@ -801,44 +483,44 @@
 /*
  * Function irda_device_unregister_dongle (dongle)
  *
- *    
+ *    Unregister dongle, and remove dongle from list of registred dongles
  *
  */
-void irda_device_unregister_dongle(struct dongle *dongle)
+void irda_device_unregister_dongle(struct dongle_reg *dongle)
 {
-	struct dongle_q *node;
+	struct dongle *node;
 
 	node = hashbin_remove(dongles, dongle->type, NULL);
 	if (!node) {
 		ERROR(__FUNCTION__ "(), dongle not found!\n");
 		return;
 	}
-	kfree(node);
 }
 
 /*
- * Function irda_device_set_raw_mode (self, status)
+ * Function irda_device_set_raw_mode (self, mode)
  *
  *    
  *
  */
-int irda_device_set_raw_mode(struct irda_device* self, int status)
+int irda_device_set_raw_mode(struct net_device* dev, int mode)
 {	
-	DEBUG(2, __FUNCTION__ "()\n");
+	struct if_irda_req req;
+	int ret;
 
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
-	
-	if (self->set_raw_mode == NULL) {
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	if (!dev->do_ioctl) {
 		ERROR(__FUNCTION__ "(), set_raw_mode not impl. by "
 		      "device driver\n");
 		return -1;
 	}
 	
-	self->raw_mode = status;
-	self->set_raw_mode(self, status);
+	req.ifr_raw_mode = mode;
+
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCSRAWMODE);
 	
-	return 0;
+	return ret;
 }
 
 /*
@@ -862,88 +544,3 @@
 
 	release_dma_lock(flags);
 }
-
-#ifdef CONFIG_PROC_FS
-
-int irda_device_print_flags(struct irda_device *idev, char *buf)
-{
-	int len=0;
-
-	len += sprintf( buf+len, "\t");
-
-	if (idev->netdev.flags & IFF_UP)
-		len += sprintf( buf+len, "UP ");
-	if (!idev->netdev.tbusy)
-		len += sprintf( buf+len, "RUNNING ");
-
-	if (idev->flags & IFF_SIR)
-		len += sprintf( buf+len, "SIR ");
-	if (idev->flags & IFF_MIR)
-		len += sprintf( buf+len, "MIR ");
-	if (idev->flags & IFF_FIR)
-		len += sprintf( buf+len, "FIR ");
-	if (idev->flags & IFF_PIO)
-		len += sprintf( buf+len, "PIO ");
-	if (idev->flags & IFF_DMA)
-		len += sprintf( buf+len, "DMA ");
-	if (idev->flags & IFF_SHM)
-		len += sprintf( buf+len, "SHM ");
-	if (idev->flags & IFF_DONGLE)
-		len += sprintf( buf+len, "DONGLE ");
-
-	len += sprintf( buf+len, "\n");
-
-	return len;
-}
-
-/*
- * Function irda_device_proc_read (buf, start, offset, len, unused)
- *
- *    Give some info to the /proc file system
- *
- */
-int irda_device_proc_read(char *buf, char **start, off_t offset, int len, 
-			  int unused)
-{
-	struct irda_device *self;
-	unsigned long flags;
-     
-	save_flags(flags);
-	cli();
-
-	len = 0;
-
-	self = (struct irda_device *) hashbin_get_first(irda_device);
-	while ( self != NULL) {
-		len += sprintf(buf+len, "\n%s,", self->name);
-		len += sprintf(buf+len, "\tbinding: %s\n", 
-			       self->description);
-		
-		len += irda_device_print_flags(self, buf+len);
-		len += sprintf(buf+len, "\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
-		
-		len += sprintf(buf+len, "\t%d\t", 
-			       self->qos.baud_rate.value);
-		len += sprintf(buf+len, "%d\t", 
-			       self->qos.max_turn_time.value);
-		len += sprintf(buf+len, "%d\t",
-			       self->qos.data_size.value);
-		len += sprintf(buf+len, "%d\t",
-			       self->qos.window_size.value);
-		len += sprintf(buf+len, "%d\t",
-			       self->qos.additional_bofs.value);
-		len += sprintf(buf+len, "%d\t", 
-			       self->qos.min_turn_time.value);
-		len += sprintf(buf+len, "%d", 
-			       self->qos.link_disc_time.value);
-		len += sprintf(buf+len, "\n");
-		
-		self = (struct irda_device *) hashbin_get_next(irda_device);
-	}
-	restore_flags(flags);
-
-	return len;
-}
-
-#endif /* CONFIG_PROC_FS */
-
diff -u --recursive --new-file v2.3.23/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.3.23/linux/net/irda/iriap.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/iriap.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Fri Aug 20 10:26:39 1999
+ * Modified at:   Sat Oct  9 17:00:56 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -28,7 +28,6 @@
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/irda.h>
 
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
@@ -146,7 +145,7 @@
 	struct lsap_cb *lsap;
 	notify_t notify;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
 	if (!self) {
@@ -184,7 +183,7 @@
 
 	init_timer(&self->watchdog_timer);
 
-	hashbin_insert(iriap, (QUEUE*) self, slsap_sel, NULL);
+	hashbin_insert(iriap, (queue_t *) self, slsap_sel, NULL);
 	
 	/* Initialize state machines */
 	iriap_next_client_state(self, S_DISCONNECT);
@@ -203,7 +202,7 @@
  */
 static void __iriap_close(struct iriap_cb *self)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -251,7 +250,7 @@
 {
 	struct iriap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 
 	self = (struct iriap_cb *) instance;
 
@@ -263,7 +262,7 @@
 	del_timer(&self->watchdog_timer);
 
 	if (self->mode == IAS_CLIENT) {
-		DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
 
 		/* 
 		 * Inform service user that the request failed by sending 
@@ -279,7 +278,7 @@
 		iriap_close(self);
 		
 	} else {
-		DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
 		iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION, 
 				      NULL);
 	}
@@ -298,14 +297,14 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb(64);
 	if (skb == NULL) {
-		DEBUG(0, __FUNCTION__
+		IRDA_DEBUG(0, __FUNCTION__
 		      "(), Could not allocate an sk_buff of length %d\n", 64);
 		return;
 	}
@@ -320,27 +319,27 @@
 
 void iriap_getinfobasedetails_request(void) 
 {
-	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getinfobasedetails_confirm(void) 
 {
-	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_request(void) 
 {
-	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_confirm(void) 
 {
-	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getvalue(void) 
 {
-	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 /*
@@ -434,13 +433,13 @@
 	/* Get length, MSB first */
 	len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
 
-	DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
 
 	/* Get object ID, MSB first */
 	obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
 
 	type = fp[n++];
-	DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
 
 	switch (type) {
 	case IAS_INTEGER:
@@ -449,7 +448,7 @@
 		value = irias_new_integer_value(tmp_cpu32);
 
 		/*  Legal values restricted to 0x01-0x6f, page 15 irttp */
-		DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
+		IRDA_DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
 		break;
 	case IAS_STRING:
 		charset = fp[n++];
@@ -468,19 +467,19 @@
 /* 		case CS_ISO_8859_9: */
 /* 		case CS_UNICODE: */
 		default:
-			DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
+			IRDA_DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
 			      ias_charset_types[charset]);
 			return;
 			/* break; */
 		}
 		value_len = fp[n++];
-		DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
+		IRDA_DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
 		ASSERT(value_len < 64, return;);
 		
 		/* Make sure the string is null-terminated */
 		fp[n+value_len] = 0x00;
 		
-		DEBUG(4, "Got string %s\n", fp+n);
+		IRDA_DEBUG(4, "Got string %s\n", fp+n);
 		value = irias_new_string_value(fp+n);
 		break;
 	case IAS_OCT_SEQ:
@@ -517,7 +516,7 @@
 	__u32 tmp_be32, tmp_be16;
 	__u8 *fp;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -578,12 +577,12 @@
 		memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
 		break;
 	case IAS_MISSING:
-		DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
+		IRDA_DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
 		skb_put( skb, 1);
 		fp[n++] = value->type;
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
 		break;
 	}
 	iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
@@ -607,7 +606,7 @@
 	__u8 *fp;
 	int n;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -629,26 +628,26 @@
 	/* 
 	 *  Now, do some advanced parsing! :-) 
 	 */
-	DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
+	IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
 	obj = irias_find_object(name);
 	
 	if (obj == NULL) {
-		DEBUG(0, "LM-IAS: Object not found\n");
+		IRDA_DEBUG(0, "LM-IAS: Object not found\n");
 		iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
 					       &missing);
 		return;
 	}
-	DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
+	IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
 	
 	attrib = irias_find_attrib(obj, attr);
 	if (attrib == NULL) {
-		DEBUG(0, "LM-IAS: Attribute %s not found\n", attr);
+		IRDA_DEBUG(0, "LM-IAS: Attribute %s not found\n", attr);
 		iriap_getvaluebyclass_response(self, obj->id,
 					       IAS_ATTRIB_UNKNOWN, &missing);
 		return;
 	}
 	
-	DEBUG(4, "LM-IAS: found %s\n", attrib->name);
+	IRDA_DEBUG(4, "LM-IAS: found %s\n", attrib->name);
 	
 	/*
 	 * We have a match; send the value.
@@ -670,7 +669,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG(6, __FUNCTION__ "()\n");
+	IRDA_DEBUG(6, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -707,7 +706,7 @@
 	ASSERT(self->magic == IAS_MAGIC, return;);
 	ASSERT(userdata != NULL, return;);
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	del_timer(&self->watchdog_timer);
 
@@ -748,7 +747,7 @@
 	__u8  *frame;
 	__u8  opcode;
 	
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n"); 
 	
 	self = (struct iriap_cb *) instance;
 
@@ -761,7 +760,7 @@
 	
 	if (self->mode == IAS_SERVER) {
 		/* Call server */
-		DEBUG(4, __FUNCTION__ "(), Calling server!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Calling server!\n");
 		iriap_do_r_connect_event( self, IAP_RECV_F_LST, skb);
 
 		return 0;
@@ -775,7 +774,7 @@
 	
 	/* Check for ack frames since they don't contain any data */
 	if (opcode & IAP_ACK) {
-		DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
 	 	return 0;
 	}
 
@@ -783,7 +782,7 @@
 	
 	switch (opcode) {
 	case GET_INFO_BASE:
-		DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
 		break;
 	case GET_VALUE_BY_CLASS:
 		switch (frame[1]) {
@@ -818,7 +817,7 @@
 		iriap_close(self);
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
 		break;
 	}
 	return 0;
@@ -835,7 +834,7 @@
 	__u8 *fp;
 	__u8 opcode;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -938,7 +937,7 @@
 				len += sprintf(buf+len, "missing\n");
 				break;
 			default:
-				DEBUG(0, __FUNCTION__ 
+				IRDA_DEBUG(0, __FUNCTION__ 
 				      "(), Unknown value type!\n");
 				return -1;
 			}
diff -u --recursive --new-file v2.3.23/linux/net/irda/iriap_event.c linux/net/irda/iriap_event.c
--- v2.3.23/linux/net/irda/iriap_event.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/iriap_event.c	Mon Oct 25 20:49:42 1999
@@ -95,9 +95,9 @@
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
  	switch ( state) { 
- /* 	case S_DISCONNECT: DEBUG( 0, "IAP Client = S_DISCONNECT\n"); break;  */
-/*  	case S_CONNECTING: DEBUG( 0, "IAP Client = S_CONNECTING\n"); break;  */
-/*  	case S_CALL:       DEBUG( 0, "IAP Client = S_CALL\n");       break;  */
+ /* 	case S_DISCONNECT: IRDA_DEBUG( 0, "IAP Client = S_DISCONNECT\n"); break;  */
+/*  	case S_CONNECTING: IRDA_DEBUG( 0, "IAP Client = S_CONNECTING\n"); break;  */
+/*  	case S_CALL:       IRDA_DEBUG( 0, "IAP Client = S_CALL\n");       break;  */
  	default: 
  		break; 
  	} 
@@ -110,12 +110,12 @@
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
 /* 	switch ( state) { */
-/* 	case S_MAKE_CALL:     DEBUG( 0, "IAP Call = S_MAKE_CALL\n"); break; */
-/* 	case S_CALLING:       DEBUG( 0, "IAP Call = S_CALLING\n"); break; */
-/* 	case S_OUTSTANDING:   DEBUG( 0, "IAP Call = S_OUTSTANDING\n");break; */
-/* 	case S_REPLYING:      DEBUG( 0, "IAP Call = S_REPLYING\n"); break; */
-/* 	case S_WAIT_FOR_CALL: DEBUG( 0, "IAP Call = S_WAIT_FOR_CALL\n"); break; */
-/* 	case S_WAIT_ACTIVE:   DEBUG( 0, "IAP Call = S_WAIT_ACTIVE\n"); break; */
+/* 	case S_MAKE_CALL:     IRDA_DEBUG( 0, "IAP Call = S_MAKE_CALL\n"); break; */
+/* 	case S_CALLING:       IRDA_DEBUG( 0, "IAP Call = S_CALLING\n"); break; */
+/* 	case S_OUTSTANDING:   IRDA_DEBUG( 0, "IAP Call = S_OUTSTANDING\n");break; */
+/* 	case S_REPLYING:      IRDA_DEBUG( 0, "IAP Call = S_REPLYING\n"); break; */
+/* 	case S_WAIT_FOR_CALL: IRDA_DEBUG( 0, "IAP Call = S_WAIT_FOR_CALL\n"); break; */
+/* 	case S_WAIT_ACTIVE:   IRDA_DEBUG( 0, "IAP Call = S_WAIT_ACTIVE\n"); break; */
 /* 	default: */
 /* 		break; */
 /* 	} */
@@ -200,7 +200,7 @@
 	case IAP_LM_DISCONNECT_INDICATION:
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
+		IRDA_DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
 		break;
 	}
 }
@@ -232,7 +232,7 @@
 		iriap_next_client_state( self, S_DISCONNECT);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 }
@@ -256,7 +256,7 @@
 		iriap_next_client_state( self, S_DISCONNECT);
 		break;
 	default:
-		DEBUG( 0, "state_s_call: Unknown event %d\n", event);
+		IRDA_DEBUG( 0, "state_s_call: Unknown event %d\n", event);
 		break;
 	}
 }
@@ -278,7 +278,7 @@
 		iriap_next_call_state( self, S_OUTSTANDING);
 		break;
 	default:
-		DEBUG( 0, "state_s_make_call: Unknown event %d\n", event);
+		IRDA_DEBUG( 0, "state_s_make_call: Unknown event %d\n", event);
 		break;
 	}
 	if ( skb) {
@@ -295,7 +295,7 @@
 static void state_s_calling( struct iriap_cb *self, IRIAP_EVENT event, 
 			     struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -318,7 +318,7 @@
 		iriap_next_call_state( self, S_WAIT_FOR_CALL);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}		
 }
@@ -331,7 +331,7 @@
 static void state_s_replying( struct iriap_cb *self, IRIAP_EVENT event, 
 			      struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -343,7 +343,7 @@
 static void state_s_wait_for_call( struct iriap_cb *self, IRIAP_EVENT event, 
 				   struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
 }
 
 
@@ -356,7 +356,7 @@
 static void state_s_wait_active( struct iriap_cb *self, IRIAP_EVENT event, 
 				 struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /**************************************************************************
@@ -380,7 +380,7 @@
 	case IAP_LM_CONNECT_INDICATION:
 		tx_skb = dev_alloc_skb( 64);
 		if ( tx_skb == NULL) {
-			DEBUG( 0,"state_r_disconnect: "
+			IRDA_DEBUG( 0,"state_r_disconnect: "
 			       "Could not allocate an sk_buff of length %d\n",
 			       64);
 			return;
@@ -405,7 +405,7 @@
 		
 		break;
 	default:
-		DEBUG( 0, "state_r_disconnect: Unknown event %d\n", event);
+		IRDA_DEBUG( 0, "state_r_disconnect: Unknown event %d\n", event);
 		break;
 	}		
 }
@@ -419,7 +419,7 @@
 static void state_r_call( struct iriap_cb *self, IRIAP_EVENT event, 
 			  struct sk_buff *skb) 
 {
-	DEBUG( 4, "state_r_call()\n");
+	IRDA_DEBUG( 4, "state_r_call()\n");
 
 	switch( event) {
 	case IAP_LM_DISCONNECT_INDICATION:
@@ -429,7 +429,7 @@
 		
 		break;
 	default:
-		DEBUG( 0, "state_r_call, unknown event!\n");
+		IRDA_DEBUG( 0, "state_r_call, unknown event!\n");
 		break;
 	}
 }
@@ -447,13 +447,13 @@
 static void state_r_waiting( struct iriap_cb *self, IRIAP_EVENT event, 
 			     struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
 }
 
 static void state_r_wait_active( struct iriap_cb *self, 
 				 IRIAP_EVENT event, struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -465,7 +465,7 @@
 static void state_r_receiving( struct iriap_cb *self, IRIAP_EVENT event, 
 			       struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	switch( event) {
 	case IAP_RECV_F_LST:
@@ -474,7 +474,7 @@
 		iriap_call_indication( self, skb);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
 		break;
 	}
 
@@ -489,12 +489,12 @@
 static void state_r_execute( struct iriap_cb *self, IRIAP_EVENT event, 
 			     struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( skb != NULL, return;);
 	
 	if ( !self || self->magic != IAS_MAGIC) {
-		DEBUG( 0, "state_r_execute: bad pointer self\n");
+		IRDA_DEBUG( 0, "state_r_execute: bad pointer self\n");
 		return;
 	}	
 
@@ -509,7 +509,7 @@
 		irlmp_data_request( self->lsap, skb);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
 		break;
 	}
 }
@@ -517,7 +517,7 @@
 static void state_r_returning( struct iriap_cb *self, IRIAP_EVENT event, 
 			       struct sk_buff *skb) 
 {
-	DEBUG( 0, __FUNCTION__ "(), event=%d\n", event);
+	IRDA_DEBUG( 0, __FUNCTION__ "(), event=%d\n", event);
 
 	switch( event) {
 	case IAP_RECV_F_LST:
diff -u --recursive --new-file v2.3.23/linux/net/irda/irias_object.c linux/net/irda/irias_object.c
--- v2.3.23/linux/net/irda/irias_object.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/irias_object.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:50:04 1998
- * Modified at:   Mon Jun 21 16:11:13 1999
+ * Modified at:   Sat Oct  9 17:11:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -24,7 +24,6 @@
 
 #include <linux/string.h>
 #include <linux/socket.h>
-#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -71,12 +70,12 @@
 {
         struct ias_object *obj;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	obj = (struct ias_object *) kmalloc( sizeof( struct ias_object), 
 					     GFP_ATOMIC);
 	if (obj == NULL) {
-		DEBUG(0, __FUNCTION__ "(), Unable to allocate object!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unable to allocate object!\n");
 		return NULL;
 	}
 	memset(obj, 0, sizeof( struct ias_object));
@@ -156,12 +155,10 @@
  */
 void irias_insert_object(struct ias_object *obj)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
-	
 	ASSERT(obj != NULL, return;);
 	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 	
-	hashbin_insert(objects, (QUEUE *) obj, 0, obj->name);
+	hashbin_insert(objects, (queue_t *) obj, 0, obj->name);
 }
 
 /*
@@ -183,18 +180,16 @@
  *    Find named attribute in object
  *
  */
-struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name)
+struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
 {
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( obj != NULL, return NULL;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return NULL;);
-	ASSERT( name != NULL, return NULL;);
+	ASSERT(obj != NULL, return NULL;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;);
+	ASSERT(name != NULL, return NULL;);
 
-	attrib = hashbin_find( obj->attribs, 0, name);
-	if ( attrib == NULL)
+	attrib = hashbin_find(obj->attribs, 0, name);
+	if (attrib == NULL)
 		return NULL;
 
 	return attrib;
@@ -208,15 +203,13 @@
  */
 void irias_add_attrib( struct ias_object *obj, struct ias_attrib *attrib)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 	
-	ASSERT( attrib != NULL, return;);
-	ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;);
+	ASSERT(attrib != NULL, return;);
+	ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
 
-	hashbin_insert( obj->attribs, (QUEUE *) attrib, 0, attrib->name);
+	hashbin_insert(obj->attribs, (queue_t *) attrib, 0, attrib->name);
 }
 
 /*
@@ -225,36 +218,36 @@
  *    Change the value of an objects attribute.
  *
  */
-int irias_object_change_attribute( char *obj_name, char *attrib_name, 
-				   struct ias_value *new_value) 
+int irias_object_change_attribute(char *obj_name, char *attrib_name, 
+				  struct ias_value *new_value) 
 {
 	struct ias_object *obj;
 	struct ias_attrib *attrib;
 
 	/* Find object */
-	obj = hashbin_find( objects, 0, obj_name);
-	if ( obj == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find object: %s\n",
-		       obj_name);
+	obj = hashbin_find(objects, 0, obj_name);
+	if (obj == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to find object: %s\n",
+			obj_name);
 		return -1;
 	}
 
 	/* Find attribute */
-	attrib = hashbin_find( obj->attribs, 0, attrib_name);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find attribute: %s\n",
-		       attrib_name);
+	attrib = hashbin_find(obj->attribs, 0, attrib_name);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to find attribute: %s\n",
+			attrib_name);
 		return -1;
 	}
-
+	
 	if ( attrib->value->type != new_value->type) {
-		DEBUG( 0, __FUNCTION__ 
+		IRDA_DEBUG( 0, __FUNCTION__ 
 		       "(), changing value type not allowed!\n");
 		return -1;
 	}
 
 	/* Delete old value */
-	irias_delete_value( attrib->value);
+	irias_delete_value(attrib->value);
 	
 	/* Insert new value */
 	attrib->value = new_value;
@@ -269,31 +262,29 @@
  *    Add an integer attribute to an LM-IAS object
  *
  */
-void irias_add_integer_attrib( struct ias_object *obj, char *name, int value)
+void irias_add_integer_attrib(struct ias_object *obj, char *name, int value)
 {
 	struct ias_attrib *attrib;
 
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
-	ASSERT( name != NULL, return;);
-	
-	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
-						GFP_ATOMIC);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to allocate attribute!\n");
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(name != NULL, return;);
+	
+	attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib), 
+					       GFP_ATOMIC);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to allocate attribute!\n");
 		return;
 	}
-	memset( attrib, 0, sizeof( struct ias_attrib));
+	memset(attrib, 0, sizeof( struct ias_attrib));
 
 	attrib->magic = IAS_ATTRIB_MAGIC;
-	attrib->name = strdup( name);
-/* 	attrib->attr = NULL; */
+	attrib->name = strdup(name);
 
 	/* Insert value */
-	attrib->value = irias_new_integer_value( value);
+	attrib->value = irias_new_integer_value(value);
 	
-	irias_add_attrib( obj, attrib);
+	irias_add_attrib(obj, attrib);
 }
 
  /*
@@ -303,33 +294,32 @@
  *
  */
 
-void irias_add_octseq_attrib( struct ias_object *obj, char *name, 
-			      __u8 *octets, int len)
+void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+			     int len)
 {
 	struct ias_attrib *attrib;
 	
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+	
+	ASSERT(name != NULL, return;);
+	ASSERT(octets != NULL, return;);
 	
-	ASSERT( name != NULL, return;);
-	ASSERT( octets != NULL, return;);
-	ASSERT( len < 55, return;);          /* FIXME: must be 1024, but... */
-	
-	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
-						GFP_ATOMIC);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to allocate attribute!\n");
+	attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib), 
+					       GFP_ATOMIC);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ 
+			"(), Unable to allocate attribute!\n");
 		return;
 	}
-	memset( attrib, 0, sizeof( struct ias_attrib));
+	memset(attrib, 0, sizeof( struct ias_attrib));
 	
 	attrib->magic = IAS_ATTRIB_MAGIC;
 	attrib->name = strdup( name);
 	
 	attrib->value = irias_new_octseq_value( octets, len);
 	
-	irias_add_attrib( obj, attrib);
+	irias_add_attrib(obj, attrib);
 }
 
 /*
@@ -338,31 +328,30 @@
  *    Add a string attribute to an LM-IAS object
  *
  */
-void irias_add_string_attrib( struct ias_object *obj, char *name, char *value)
+void irias_add_string_attrib(struct ias_object *obj, char *name, char *value)
 {
 	struct ias_attrib *attrib;
 
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 
-	ASSERT( name != NULL, return;);
-	ASSERT( value != NULL, return;);
+	ASSERT(name != NULL, return;);
+	ASSERT(value != NULL, return;);
 	
-	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
-						GFP_ATOMIC);
-	if ( attrib == NULL) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to allocate attribute!\n");
+	attrib = (struct ias_attrib *) kmalloc(sizeof( struct ias_attrib), 
+					       GFP_ATOMIC);
+	if (attrib == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to allocate attribute!\n");
 		return;
 	}
-	memset( attrib, 0, sizeof( struct ias_attrib));
+	memset(attrib, 0, sizeof( struct ias_attrib));
 
 	attrib->magic = IAS_ATTRIB_MAGIC;
-	attrib->name = strdup( name);
+	attrib->name = strdup(name);
 
-	attrib->value = irias_new_string_value( value);
+	attrib->value = irias_new_string_value(value);
 
-	irias_add_attrib( obj, attrib);
+	irias_add_attrib(obj, attrib);
 }
 
 /*
@@ -371,16 +360,16 @@
  *    Create new IAS integer value
  *
  */
-struct ias_value *irias_new_integer_value( int integer)
+struct ias_value *irias_new_integer_value(int integer)
 {
 	struct ias_value *value;
 
-	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
-	if ( value == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+	value = kmalloc(sizeof( struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
-	memset( value, 0, sizeof( struct ias_value));
+	memset(value, 0, sizeof(struct ias_value));
 
 	value->type = IAS_INTEGER;
 	value->len = 4;
@@ -395,21 +384,21 @@
  *    Create new IAS string value
  *
  */
-struct ias_value *irias_new_string_value( char *string)
+struct ias_value *irias_new_string_value(char *string)
 {
 	struct ias_value *value;
 
-	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
-	if ( value == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 	memset( value, 0, sizeof( struct ias_value));
 
 	value->type = IAS_STRING;
 	value->charset = CS_ASCII;
-	value->len = strlen( string);
-	value->t.string = strdup( string);
+	value->len = strlen(string);
+	value->t.string = strdup(string);
 
 	return value;
 }
@@ -421,25 +410,23 @@
  *    Create new IAS octet-sequence value
  *
  */
-struct ias_value *irias_new_octseq_value( __u8 *octseq , int len)
+struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
 {
 	struct ias_value *value;
 
-	ASSERT(len <= 55, return NULL;); /*FIXME: must be 1024, but.....*/
-
-	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
-	if ( value == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
-	memset( value, 0, sizeof( struct ias_value));
+	memset(value, 0, sizeof( struct ias_value));
 
 	value->type = IAS_OCT_SEQ;
 	value->len = len;
 
 	value->t.oct_seq = kmalloc(len, GFP_ATOMIC);
-	if( value->t.oct_seq == NULL){
-		DEBUG(0, __FUNCTION__"(), Unable to kmalloc!\n");
+	if (value->t.oct_seq == NULL){
+		WARNING(__FUNCTION__"(), Unable to kmalloc!\n");
 		return NULL;
 	}
 	memcpy(value->t.oct_seq, octseq , len);
@@ -452,32 +439,32 @@
  *    Delete IAS value
  *
  */
-void irias_delete_value( struct ias_value *value)
+void irias_delete_value(struct ias_value *value)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( value != NULL, return;);
+	ASSERT(value != NULL, return;);
 
-	switch( value->type) {
+	switch (value->type) {
 	case IAS_INTEGER: /* Fallthrough */
 	case IAS_MISSING:
 		/* No need to deallocate */
 		break;
 	case IAS_STRING:
 		/* If string, deallocate string */
-		if ( value->t.string != NULL)
-			kfree( value->t.string);
+		if (value->t.string != NULL)
+			kfree(value->t.string);
 		break;
 	case IAS_OCT_SEQ:
 		/* If byte stream, deallocate byte stream */
-		 if ( value->t.oct_seq != NULL)
+		 if (value->t.oct_seq != NULL)
 			 kfree(value->t.oct_seq);
 		 break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown value type!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown value type!\n");
 		break;
 	}
-	kfree( value);
+	kfree(value);
 }
 
 
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.3.23/linux/net/irda/irlan/irlan_common.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irlan/irlan_common.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Sep  9 11:39:43 1999
+ * Modified at:   Tue Oct  5 11:36:11 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -296,7 +296,7 @@
 	init_timer(&self->watchdog_timer);
 	init_timer(&self->client.kick_timer);
 
-	hashbin_insert(irlan, (QUEUE *) self, daddr, NULL);
+	hashbin_insert(irlan, (queue_t *) self, daddr, NULL);
 	
 	skb_queue_head_init(&self->client.txq);
 	
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.3.23/linux/net/irda/irlap.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irlap.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon Sep 20 11:04:32 1999
+ * Modified at:   Fri Oct  8 23:17:36 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -74,14 +74,15 @@
 	/* Allocate master array */
 	irlap = hashbin_new(HB_LOCAL);
 	if (irlap == NULL) {
-		printk(KERN_WARNING "IrLAP: Can't allocate irlap hashbin!\n");
+	        ERROR(__FUNCTION__ "(), can't allocate irlap hashbin!\n");
 		return -ENOMEM;
 	}
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	irlap_compressors = hashbin_new(HB_LOCAL);
 	if (irlap_compressors == NULL) {
-		printk(KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
+		WARNING(__FUNCTION__ 
+			"(), can't allocate compressors hashbin!\n");
 		return -ENOMEM;
 	}
 #endif
@@ -106,11 +107,11 @@
  *    Initialize IrLAP layer
  *
  */
-struct irlap_cb *irlap_open(struct net_device *dev)
+struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos)
 {
 	struct irlap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	/* Initialize the irlap structure. */
 	self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
@@ -122,6 +123,10 @@
 
 	/* Make a binding between the layers */
 	self->netdev = dev;
+	self->qos_dev = qos;
+
+	/* FIXME: should we get our own field? */
+	dev->atalk_ptr = self;
 
 	irlap_next_state(self, LAP_OFFLINE);
 
@@ -131,6 +136,7 @@
 
 	/* My unique IrLAP device address! */
 	get_random_bytes(&self->saddr, sizeof(self->saddr));
+	memcpy(dev->dev_addr, &self->saddr, 4);
 
 	/* 
 	 * Generate random connection address for this session, which must
@@ -148,12 +154,13 @@
 	init_timer(&self->poll_timer);
 	init_timer(&self->wd_timer);
 	init_timer(&self->backoff_timer);
+	init_timer(&self->media_busy_timer);	
 
 	irlap_apply_default_connection_parameters(self);
 	
 	irlap_next_state(self, LAP_NDM);
 
-	hashbin_insert(irlap, (QUEUE *) self, self->saddr, NULL);
+	hashbin_insert(irlap, (queue_t *) self, self->saddr, NULL);
 
 	irlmp_register_link(self, self->saddr, &self->notify);
 	
@@ -179,6 +186,7 @@
 	del_timer(&self->poll_timer);
 	del_timer(&self->wd_timer);
 	del_timer(&self->backoff_timer);
+	del_timer(&self->media_busy_timer);
 
 	irlap_flush_all_queues(self);
        
@@ -197,7 +205,7 @@
 {
 	struct irlap_cb *lap;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -210,7 +218,7 @@
 	/* Be sure that we manage to remove ourself from the hash */
 	lap = hashbin_remove(irlap, self->saddr, NULL);
 	if (!lap) {
-		DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
 		return;
 	}
 	__irlap_close(lap);
@@ -224,7 +232,7 @@
  */
 void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -243,7 +251,7 @@
  */
 void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
 }
@@ -258,7 +266,7 @@
 void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
 			   struct qos_info *qos_user, int sniff) 
 {
-	DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);
+	IRDA_DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -271,8 +279,7 @@
 	 */
 	irlap_init_qos_capabilities(self, qos_user);
 	
-	if ((self->state == LAP_NDM) && 
-	    !irda_device_is_media_busy(self->netdev))
+	if ((self->state == LAP_NDM) && !self->media_busy)
 		irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);
 	else
 		self->connect_pending = TRUE;
@@ -286,7 +293,7 @@
  */
 void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -310,7 +317,7 @@
 	if (self->qos_tx.compression.value) {
 		skb = irlap_decompress_frame(self, skb);
 		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
@@ -326,7 +333,7 @@
  */
 void irlap_unit_data_indication(struct irlap_cb *self, struct sk_buff *skb)
 {
-	DEBUG(1, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(1, __FUNCTION__ "()\n"); 
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -340,7 +347,7 @@
 		
 		skb = irlap_decompress_frame(self, skb);
 		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
@@ -364,7 +371,7 @@
 	if (self->qos_tx.compression.value) {
 		skb = irlap_compress_frame(self, skb);
 		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Compress error!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Compress error!\n");
 			return;
 		}
 	}
@@ -381,7 +388,7 @@
 	if (reliable)
 		skb->data[1] = I_FRAME;
 	else {
-		DEBUG(4, __FUNCTION__ "(), queueing unreliable frame\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), queueing unreliable frame\n");
 		skb->data[1] = UI_FRAME;
 	}
 
@@ -412,7 +419,7 @@
  */
 void irlap_disconnect_request(struct irlap_cb *self) 
 {
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -434,7 +441,7 @@
 		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), disconnect pending!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), disconnect pending!\n");
 		self->disconnect_pending = TRUE;
 		break;
 	}
@@ -448,7 +455,7 @@
  */
 void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason) 
 {
-	DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
+	IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -461,7 +468,7 @@
 	
 	switch(reason) {
 	case LAP_RESET_INDICATION:
-		DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
 		irlap_do_event(self, RESET_REQUEST, NULL, NULL);
 		break;
 	case LAP_NO_RESPONSE:	   /* FALLTROUGH */	
@@ -472,7 +479,7 @@
 						 reason, NULL);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n", 
 		       reason);
 	}
 }
@@ -491,7 +498,7 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	ASSERT(discovery != NULL, return;);
 	
-	DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
+	IRDA_DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
 
 	ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
 	       (discovery->nslots == 8) || (discovery->nslots == 16), 
@@ -535,7 +542,7 @@
 		
 		irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
 	} else { 
- 		DEBUG(4, __FUNCTION__ 
+ 		IRDA_DEBUG(4, __FUNCTION__ 
 		       "(), discovery only possible in NDM mode\n");
 		irlap_discovery_confirm(self, NULL);
  	} 
@@ -559,7 +566,7 @@
 	 * the media busy condition (irlap p.94). This should allow us to make 
 	 * connection attempts much easier.
 	 */
-	if (discovery_log && hashbin_get_size(discovery_log) > 0)
+	if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0)
 		irda_device_set_media_busy(self->netdev, FALSE);
 	
 	/* Inform IrLMP */
@@ -574,7 +581,7 @@
  */
 void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -595,10 +602,10 @@
 {
 	switch (quality_of_link) {
 	case STATUS_NO_ACTIVITY:
-		printk(KERN_INFO "IrLAP, no activity on link!\n");
+		MESSAGE("IrLAP, no activity on link!\n");
 		break;
 	case STATUS_NOISY:
-		printk(KERN_INFO "IrLAP, noisy link!\n");
+		MESSAGE("IrLAP, noisy link!\n");
 		break;
 	default:
 		break;
@@ -614,7 +621,7 @@
  */
 void irlap_reset_indication(struct irlap_cb *self)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -633,7 +640,7 @@
  */
 void irlap_reset_confirm(void)
 {
- 	DEBUG(1, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 }
 
 /*
@@ -728,7 +735,7 @@
 {
 	/*  nr as expected?  */
 	if (nr == self->vs) {
-		DEBUG(4, __FUNCTION__ "(), expected!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), expected!\n");
 		return NR_EXPECTED;
 	}
 
@@ -756,7 +763,7 @@
  */
 void irlap_initiate_connection_state(struct irlap_cb *self) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -783,9 +790,9 @@
  */
 void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos) 
 {
-	int usecs;
-	int speed;
-	int bytes ;
+	__u32 speed;
+	__u32 usecs;
+	__u32 bytes ;
 	
 	/* Get QoS values.  */
 	speed = qos->baud_rate.value;
@@ -844,25 +851,12 @@
  */
 void irlap_change_speed(struct irlap_cb *self, __u32 speed)
 {
-	struct ifreq req;
-
-	DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
+	IRDA_DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	if (!self->netdev) {
-		DEBUG(1, __FUNCTION__ "(), driver missing!\n");
-		return;
-	}
-
-	/* 
-	 * Warning, ifr_bandwidth is only 16 bits on architectures where ints
-         * are 16 bits wide.
-	 */
-	req.ifr_bandwidth = speed;
-	self->netdev->do_ioctl(self->netdev, &req, SIOCSBANDWIDTH);
-
+	/* Must use the same speed in both directions */
 	self->qos_rx.baud_rate.value = speed;
 	self->qos_tx.baud_rate.value = speed;
 }
@@ -883,24 +877,24 @@
 	 *  actually been loaded. Ths is sort of hairy code but that is what 
 	 *  you get when you do a little bit flicking :-)
 	 */
-	DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n", 
 	       self->qos_rx.compression.bits); 
 	mask = 0x80; /* Start with testing MSB */
 	for (i=0;i<8;i++) {
-		DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
+		IRDA_DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
 		if (self->qos_rx.compression.bits & mask) {
-			DEBUG(4, __FUNCTION__ "(), bit %d is set by defalt\n",
+			IRDA_DEBUG(4, __FUNCTION__ "(), bit %d is set by defalt\n",
 			       8-i);
 			comp = hashbin_find(irlap_compressors, 
 					     compression[ msb_index(mask)], 
 					     NULL);
 			if (!comp) {
 				/* Protocol not supported, so clear the bit */
-				DEBUG(4, __FUNCTION__ "(), Compression "
+				IRDA_DEBUG(4, __FUNCTION__ "(), Compression "
 				       "protocol %d has not been loaded!\n", 
 				       compression[msb_index(mask)]);
 				self->qos_rx.compression.bits &= ~mask;
-				DEBUG(4, __FUNCTION__ 
+				IRDA_DEBUG(4, __FUNCTION__ 
 				       "(), comp bits 0x%02x\n", 
 				       self->qos_rx.compression.bits); 
 			}
@@ -934,8 +928,7 @@
 #endif
 
 	/* Apply drivers QoS capabilities */
-	irda_qos_compute_intersection(&self->qos_rx, 
-				      irda_device_get_qos(self->netdev));
+	irda_qos_compute_intersection(&self->qos_rx, self->qos_dev);
 
 	/*
 	 *  Check for user supplied QoS parameters. The service user is only 
@@ -943,7 +936,7 @@
 	 *  user may not have set all of them.
 	 */
 	if (qos_user) {
-		DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
 
 		if (qos_user->baud_rate.bits)
 			self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
@@ -986,7 +979,7 @@
  */
 void irlap_apply_default_connection_parameters(struct irlap_cb *self)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -1019,7 +1012,7 @@
 void irlap_apply_connection_parameters(struct irlap_cb *self, 
 				       struct qos_info *qos) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -1036,7 +1029,7 @@
 	 */
 	self->window_bytes = qos->baud_rate.value 
 		* qos->max_turn_time.value / 10000;
-	DEBUG(4, "Setting window_bytes = %d\n", self->window_bytes);
+	IRDA_DEBUG(4, "Setting window_bytes = %d\n", self->window_bytes);
 
 	/*
 	 *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
@@ -1049,10 +1042,10 @@
 	else
 		self->N1 = 3000 / qos->max_turn_time.value;
 	
-	DEBUG(4, "Setting N1 = %d\n", self->N1);
+	IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
 	
 	self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
-	DEBUG(4, "Setting N2 = %d\n", self->N2);
+	IRDA_DEBUG(4, "Setting N2 = %d\n", self->N2);
 
 	/* 
 	 *  Initialize timeout values, some of the rules are listed on 
@@ -1064,7 +1057,7 @@
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if (qos->compression.value) {
-		DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
 		irda_set_compression(self, qos->compression.value);
 
 		irlap_compressor_init(self, 0);
@@ -1080,14 +1073,14 @@
  */
 void irlap_set_local_busy(struct irlap_cb *self, int status)
 {
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self->local_busy = status;
 	
 	if (status)
-		DEBUG(0, __FUNCTION__ "(), local busy ON\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), local busy ON\n");
 	else
-		DEBUG(0, __FUNCTION__ "(), local busy OFF\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), local busy OFF\n");
 }
 
 #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlap_comp.c linux/net/irda/irlap_comp.c
--- v2.3.23/linux/net/irda/irlap_comp.c	Tue Jun  1 23:25:48 1999
+++ linux/net/irda/irlap_comp.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Oct  9 09:18:07 1998
- * Modified at:   Sun May  9 11:37:06 1999
+ * Modified at:   Tue Oct  5 11:34:52 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Fri May 28  3:11 CST 1999
  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
@@ -45,11 +45,11 @@
 {
 	struct irda_compressor *new;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	/* Check if this compressor has been registred before */
 	if ( hashbin_find ( irlap_compressors, cp->compress_proto, NULL)) {
-		DEBUG( 0, __FUNCTION__ "(), Compressor already registered\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Compressor already registered\n");
                 return 0;
         }
 	
@@ -63,7 +63,7 @@
         new->cp = cp;
 
 	/* Insert IrDA compressor into hashbin */
-	hashbin_insert( irlap_compressors, (QUEUE *) new, cp->compress_proto,
+	hashbin_insert( irlap_compressors, (queue_t *) new, cp->compress_proto,
 			NULL);
 	
         return 0;
@@ -79,11 +79,11 @@
 {
 	struct irda_compressor *node;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	node = hashbin_remove( irlap_compressors, cp->compress_proto, NULL);
 	if ( !node) {
-		DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
 		return;
 	}	
 	kfree( node);
@@ -102,7 +102,7 @@
 
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return -ENODEV;);
 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -115,7 +115,7 @@
 
 	comp = hashbin_find( irlap_compressors, proto, NULL);
 	if ( !comp) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find compressor\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to find compressor\n");
 		return -1;
 	}
 
@@ -130,7 +130,7 @@
 	self->compressor.cp = cp;
 	self->compressor.state = cp->comp_alloc( options, sizeof( options));
 	if ( self->compressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Failed!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Failed!\n");
 		return -ENOBUFS;
 	}
 
@@ -145,7 +145,7 @@
 	self->decompressor.cp = cp;
 	self->decompressor.state = cp->decomp_alloc( options, sizeof( options));
 	if ( self->decompressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Failed!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Failed!\n");
 		return -ENOBUFS;
 	}
 	return 0;
@@ -159,7 +159,7 @@
  */
 void irda_free_compression( struct irlap_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	if ( self->compressor.state) {
 		irda_comp_free( self->compressor.state);
@@ -183,7 +183,7 @@
 	int debug = TRUE;
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -198,7 +198,7 @@
 	 *  We're agreeing to send compressed packets.
 	 */
 	if ( self->compressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
 		return;
 	}
 	
@@ -206,7 +206,7 @@
 					       options, sizeof( options),
 					       0, 0, debug)) 
 	{
-		DEBUG( 0, __FUNCTION__ "(), Compressor running!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Compressor running!\n");
 		/* ppp->flags |= SC_COMP_RUN; */
 	}
 	
@@ -214,7 +214,7 @@
 	 *  Initialize decompressor
 	 */
 	if ( self->decompressor.state == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
 		return;
 	}
 	
@@ -222,7 +222,7 @@
 						   options, sizeof( options),
 						   0, 0, 0, debug)) 
 	{
-		DEBUG( 0, __FUNCTION__ "(), Decompressor running!\n");	
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Decompressor running!\n");	
 		
 		/* ppp->flags |= SC_DECOMP_RUN; */
 		/* ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); */
@@ -243,7 +243,7 @@
 	
 	ASSERT( skb != NULL, return NULL;);
 	
-	DEBUG(4, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
+	IRDA_DEBUG(4, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
 	      jiffies);
 
 	ASSERT( self != NULL, return NULL;);
@@ -270,7 +270,7 @@
 						 skb->data, new_skb->data, 
 						 skb->len, new_skb->len);
 	if( count <= 0) {
-		DEBUG(4, __FUNCTION__ "(), Unable to compress frame!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unable to compress frame!\n");
 		dev_kfree_skb( new_skb);
 
 		/* Tell peer that this frame is not compressed */
@@ -287,7 +287,7 @@
 
 	dev_kfree_skb( skb);
 	
-	DEBUG(4, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
+	IRDA_DEBUG(4, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
 	      (int) new_skb->len, jiffies);
 	
 	return new_skb;
@@ -305,7 +305,7 @@
 	struct sk_buff *new_skb;
 	int count;
 
-	DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
+	IRDA_DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
 
 	ASSERT( self != NULL, return NULL;);
 	ASSERT( self->magic == LAP_MAGIC, return NULL;);
@@ -339,7 +339,7 @@
 	count = irda_decompress( self->decompressor.state, skb->data, 
 				 skb->len, new_skb->data, new_skb->len);
 	if ( count <= 0) {
-		DEBUG( 4, __FUNCTION__ "(), Unable to decompress frame!\n");
+		IRDA_DEBUG( 4, __FUNCTION__ "(), Unable to decompress frame!\n");
 		
 		dev_kfree_skb( new_skb);
 		return skb;
@@ -347,7 +347,7 @@
 
 	skb_trim( new_skb, count);
 	
-	DEBUG( 4, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
+	IRDA_DEBUG( 4, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
 
 	return new_skb;
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.3.23/linux/net/irda/irlap_event.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irlap_event.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon Sep 20 12:30:31 1999
+ * Modified at:   Sun Oct 10 11:14:22 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
@@ -200,7 +200,7 @@
 	} else
 		self->fast_RR = FALSE;
 
-	DEBUG(4, __FUNCTION__ "(), Timeout=%d\n", timeout);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Timeout=%d\n", timeout);
 #endif
 	if (timeout == 0)
 		irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL);
@@ -223,7 +223,7 @@
 	if (!self || self->magic != LAP_MAGIC)
 		return;
 	
-  	DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n", 
+  	IRDA_DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n", 
 	      irlap_event[event], irlap_state[self->state]); 
 	
 	ret = (*state[self->state])(self, event, skb, info);
@@ -256,9 +256,7 @@
 		break;
 	case LAP_NDM:
 		/* Check if we should try to connect */
-		if ((self->connect_pending) && 
-		    !irda_device_is_media_busy(self->netdev)) 
-		{
+		if ((self->connect_pending) && !self->media_busy) {
 			self->connect_pending = FALSE;
 			
 			ret = (*state[self->state])(self, CONNECT_REQUEST, 
@@ -284,7 +282,7 @@
 	if (!self || self->magic != LAP_MAGIC)
 		return;
 	
-	DEBUG(4, "next LAP state = %s\n", irlap_state[ state]);
+	IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[ state]);
 
 	self->state = state;
 
@@ -317,8 +315,8 @@
 	case CONNECT_REQUEST:
 		ASSERT(self->netdev != NULL, return -1;);
 
-		if (irda_device_is_media_busy(self->netdev)) {
-			DEBUG(0, __FUNCTION__
+		if (self->media_busy) {
+			IRDA_DEBUG(0, __FUNCTION__
 			      "(), CONNECT_REQUEST: media busy!\n");
 			
 			/* Always switch state before calling upper layers */
@@ -345,7 +343,7 @@
 			
 			irlap_connect_indication(self, skb);
 		} else {
-			DEBUG(0, __FUNCTION__ "(), SNRM frame does not contain"
+			IRDA_DEBUG(0, __FUNCTION__ "(), SNRM frame does not contain"
 			      " and I field!\n");
 			dev_kfree_skb(skb);
 		}
@@ -353,8 +351,8 @@
 	case DISCOVERY_REQUEST:		
 		ASSERT(info != NULL, return -1;);
 
-	 	if (irda_device_is_media_busy(self->netdev)) {
- 			DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
+	 	if (self->media_busy) {
+ 			IRDA_DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
 			/* irlap->log.condition = MEDIA_BUSY; */
 			
 			/* Always switch state before calling upper layers */
@@ -382,7 +380,7 @@
 			/* self->daddr = info->daddr;  */
 			self->slot = irlap_generate_rand_time_slot(info->S,
 								   info->s);
-			DEBUG(4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, 
+			IRDA_DEBUG(4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, 
 			      info->s, self->slot);
 
 			if (self->slot == info->s) {
@@ -418,11 +416,11 @@
 		dev_kfree_skb(skb);
 		break;
 	case RECV_TEST_RSP:
-		DEBUG(0, __FUNCTION__ "() not implemented!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() not implemented!\n");
 		dev_kfree_skb(skb);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
 
 		if (skb)
@@ -453,7 +451,7 @@
 		ASSERT(info != NULL, return -1;);
 		ASSERT(info->discovery != NULL, return -1;);
 
-		DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", 
+		IRDA_DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", 
 		      info->discovery->daddr);
 
 		if (!self->discovery_log) {
@@ -463,7 +461,7 @@
 			break;
 		}
 		hashbin_insert(self->discovery_log, 
-			       (QUEUE *) info->discovery,
+			       (queue_t *) info->discovery,
 			       info->discovery->daddr, NULL);
 
 		dev_kfree_skb(skb);
@@ -501,7 +499,7 @@
 		}
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
 		      irlap_event[event]);
 
 		if (skb)
@@ -526,14 +524,14 @@
 	discovery_t *discovery_rsp;
 	int ret=0;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
 	switch (event) {
 	case QUERY_TIMER_EXPIRED:
-		DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
+		IRDA_DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
 		      jiffies);
 		irlap_next_state(self, LAP_NDM);
 		break;
@@ -565,7 +563,7 @@
 		dev_kfree_skb(skb);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
 		      irlap_event[event]);
 
 		if ( skb)
@@ -589,7 +587,7 @@
 {
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
@@ -622,7 +620,7 @@
 		irlap_next_state( self, LAP_NRM_S);
 		break;
 	case RECV_DISCOVERY_XID_CMD:
-		DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
+		IRDA_DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
 		irlap_next_state( self, LAP_NDM);
 		break;		
 	case DISCONNECT_REQUEST:
@@ -630,7 +628,7 @@
 		irlap_next_state( self, LAP_CONN);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
 		      irlap_event[event]);
 
 		if (skb)
@@ -655,7 +653,7 @@
 {
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
@@ -685,7 +683,7 @@
 		break;
 
 	case RECV_SNRM_CMD:
-		DEBUG(4, __FUNCTION__ "(), SNRM battle!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), SNRM battle!\n");
 
 		ASSERT(skb != NULL, return 0;);
 		ASSERT(info != NULL, return 0;);
@@ -759,7 +757,7 @@
 
 	/* DM handled in irlap_frame.c, irlap_driver_rcv() */		
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
 		      irlap_event[event]);
 		
 		if (skb)
@@ -780,7 +778,7 @@
 static int irlap_state_offline(struct irlap_cb *self, IRLAP_EVENT event, 
 			       struct sk_buff *skb, struct irlap_info *info) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Unknown event\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event\n");
 
 	return -1;
 }
@@ -811,7 +809,7 @@
 			 *  speed and turn-around-time.
 			 */
 			if ((skb->len+self->bofs_count) > self->bytes_left) {
-				DEBUG(4, __FUNCTION__ "(), Not allowed to "
+				IRDA_DEBUG(4, __FUNCTION__ "(), Not allowed to "
 				      "transmit more bytes!\n");
 				skb_queue_head(&self->tx_list, skb);
 
@@ -851,7 +849,7 @@
 			self->fast_RR = FALSE;
 #endif
 		} else {
-			DEBUG(4, __FUNCTION__ 
+			IRDA_DEBUG(4, __FUNCTION__ 
 			      "(), Unable to send! remote busy?\n");
 			skb_queue_head(&self->tx_list, skb);
 
@@ -877,7 +875,7 @@
 		irlap_next_state(self, LAP_PCLOSE);
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
 
 		if (skb)
@@ -899,7 +897,7 @@
 {
 	int ret = 0;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);	
@@ -935,7 +933,7 @@
 		}
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
 
 		if (skb)
 			dev_kfree_skb(skb);
@@ -1044,7 +1042,7 @@
 				/* Keep state */
 				irlap_next_state(self, LAP_NRM_P);
 			} else {
-				DEBUG( 4, __FUNCTION__
+				IRDA_DEBUG( 4, __FUNCTION__
 				       "(), missing or duplicate frame!\n");
 				
 				/* Update Nr received */
@@ -1110,7 +1108,7 @@
 		if ((ns_status == NS_UNEXPECTED) && 
 		    (nr_status == NR_UNEXPECTED)) 
 		{
-			DEBUG( 4, "IrLAP: unexpected nr and ns!\n");
+			IRDA_DEBUG( 4, "IrLAP: unexpected nr and ns!\n");
 			if (info->pf) {
 				/* Resend rejected frames */
 				irlap_resend_rejected_frames(self, CMD_FRAME);
@@ -1149,8 +1147,8 @@
 			}
 			break;
 		}
-		DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
-		DEBUG(1, __FUNCTION__ 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
+		IRDA_DEBUG(1, __FUNCTION__ 
 		      "(), event=%s, ns_status=%d, nr_status=%d\n", 
 		      irlap_event[ event], ns_status, nr_status);
 		break;
@@ -1204,7 +1202,7 @@
 			/* Update Nr received */
 			irlap_update_nr_received(self, info->nr);
 
-			DEBUG(4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, "
+			IRDA_DEBUG(4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, "
 			      "vs=%d, vr=%d\n",
 			      self->retry_count, info->nr, self->va, 
 			      self->vs, self->vr);
@@ -1214,7 +1212,7 @@
 			
 			irlap_next_state(self, LAP_NRM_P);
 		} else if (ret == NR_INVALID) {
-			DEBUG(1, __FUNCTION__ "(), Received RR with "
+			IRDA_DEBUG(1, __FUNCTION__ "(), Received RR with "
 			      "invalid nr !\n");
 			del_timer(&self->final_timer);
 
@@ -1227,7 +1225,7 @@
 			dev_kfree_skb(skb);
 		break;
 	case RECV_RNR_FRAME:
-		DEBUG(4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, "
+		IRDA_DEBUG(4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, "
 		      "nr=%d, va=%d, vs=%d, vr=%d\n",
 		      self->retry_count, info->nr, self->va, self->vs, 
 		      self->vr);
@@ -1264,7 +1262,7 @@
 		 *  we only do this once for each frame.
 		 */
 		if (irda_device_is_receiving(self->netdev) && !self->add_wait) {
-			DEBUG(4, "FINAL_TIMER_EXPIRED when receiving a "
+			IRDA_DEBUG(4, "FINAL_TIMER_EXPIRED when receiving a "
 			      "frame! Waiting a little bit more!\n");
 			irlap_start_final_timer(self, MSECS_TO_JIFFIES(300));
 
@@ -1287,7 +1285,7 @@
 			irlap_start_final_timer(self, self->final_timeout);
 		 	self->retry_count++;
 
-			DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
+			IRDA_DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
 			      " retry_count=%d\n", self->retry_count);
 			/* Keep state */
 		} else if (self->retry_count == self->N1) {
@@ -1298,7 +1296,7 @@
 			irlap_start_final_timer(self, self->final_timeout);
 			self->retry_count++;
 
-			DEBUG(4, "retry count = N1; retry_count=%d\n", 
+			IRDA_DEBUG(4, "retry count = N1; retry_count=%d\n", 
 			      self->retry_count);
 			/* Keep state */
 		} else if (self->retry_count >= self->N2) {
@@ -1310,7 +1308,7 @@
 		}
 		break;
 	case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */
-		DEBUG(1, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
 
 		/* Always switch state before calling upper layers */
 		irlap_next_state(self, LAP_NDM);
@@ -1330,7 +1328,7 @@
 		
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
 
 		if (skb)
@@ -1354,7 +1352,7 @@
 {
 	int ret = 0;
 	
-	DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
+	IRDA_DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
 	
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
@@ -1380,7 +1378,7 @@
 		irlap_next_state( self, LAP_PCLOSE);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
 		if (skb)
 			dev_kfree_skb(skb);
@@ -1403,7 +1401,7 @@
 {
 	int ret = 0;
 	
-	DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
+	IRDA_DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
 	
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
@@ -1438,7 +1436,7 @@
 			irlap_wait_min_turn_around(self, &self->qos_tx);
 
 			ASSERT(self->netdev != NULL, return -1;);
-			irlap_send_snrm_frame(self, irda_device_get_qos(self->netdev));
+			irlap_send_snrm_frame(self, self->qos_dev);
 
 			self->retry_count++; /* Experimental!! */
 
@@ -1459,7 +1457,7 @@
 		 * state
 		 */
 		if (!info) {
-			DEBUG(3, __FUNCTION__ "(), RECV_SNRM_CMD\n");
+			IRDA_DEBUG(3, __FUNCTION__ "(), RECV_SNRM_CMD\n");
 			irlap_initiate_connection_state(self);
 			irlap_wait_min_turn_around(self, &self->qos_tx);
 			irlap_send_ua_response_frame(self, &self->qos_rx);
@@ -1467,13 +1465,13 @@
 			irlap_start_wd_timer(self, self->wd_timeout);
 			irlap_next_state(self, LAP_NDM);
 		} else {
-			DEBUG(0, __FUNCTION__ "(), SNRM frame contained an I "
+			IRDA_DEBUG(0, __FUNCTION__ "(), SNRM frame contained an I "
 			      "field!\n");
 			dev_kfree_skb(skb);
 		}
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
 
 		if (skb)
@@ -1497,7 +1495,7 @@
 {
 	int ret = 0;
 	
-	DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
 
 	ASSERT(self != NULL, return -ENODEV;);
 	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
@@ -1547,13 +1545,13 @@
 				ret = -EPROTO;
 			}
 		} else {
-			DEBUG(1, __FUNCTION__ "(), Unable to send!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Unable to send!\n");
 			skb_queue_head( &self->tx_list, skb);
 			ret = -EPROTO;
 		}
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
 		if (skb)
 			dev_kfree_skb(skb);
@@ -1578,7 +1576,7 @@
 	int nr_status;
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
@@ -1586,7 +1584,7 @@
 	switch (event) {
 	case RECV_I_CMD: /* Optimize for the common case */
 		/* FIXME: must check for remote_busy below */
-		DEBUG(4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, "
+		IRDA_DEBUG(4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, "
 		      "vr=%d, pf=%d\n", irlap_event[event], info->nr, 
 		      self->vs, info->ns, self->vr, info->pf);
 
@@ -1690,7 +1688,7 @@
 		if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))
 		{
 			if (info->pf) {
-				DEBUG(4, "RECV_I_RSP: frame(s) lost\n");
+				IRDA_DEBUG(4, "RECV_I_RSP: frame(s) lost\n");
 				
 				self->vr = (self->vr + 1) % 8;
 				
@@ -1726,10 +1724,10 @@
 		}
 		
 		if (ret == NR_INVALID) {
-			DEBUG(0, "NRM_S, NR_INVALID not implemented!\n");
+			IRDA_DEBUG(0, "NRM_S, NR_INVALID not implemented!\n");
 		}
 		if (ret == NS_INVALID) {
-			DEBUG(0, "NRM_S, NS_INVALID not implemented!\n");
+			IRDA_DEBUG(0, "NRM_S, NS_INVALID not implemented!\n");
 		}
 		break;
 	case RECV_UI_FRAME:
@@ -1805,7 +1803,7 @@
 			/* Keep state */
 			irlap_next_state(self, LAP_NRM_S); 
 		} else {
-			DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
 		} 
 		if (skb)
 			dev_kfree_skb(skb);
@@ -1815,12 +1813,12 @@
 		/* SNRM frame is not allowed to contain an I-field */
 		if (!info) {
 			del_timer(&self->wd_timer);
-			DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
 			irlap_next_state(self, LAP_RESET_CHECK);
 			
 			irlap_reset_indication(self);
 		} else {
-			DEBUG(0, __FUNCTION__ "(), SNRM frame contained an "
+			IRDA_DEBUG(0, __FUNCTION__ "(), SNRM frame contained an "
 			      "I-field!\n");
 			dev_kfree_skb(skb);	       
 		}
@@ -1830,7 +1828,7 @@
 		 *  Wait until retry_count * n matches negotiated threshold/
 		 *  disconnect time (note 2 in IrLAP p. 82)
 		 */
-		DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
 		      self->retry_count);
 
 		if ((self->retry_count < (self->N2/2))  && 
@@ -1885,7 +1883,7 @@
 		dev_kfree_skb(skb);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
 		      event, irlap_event[event]);
 		ret = -1;
 		break;
@@ -1902,7 +1900,7 @@
 static int irlap_state_sclose( struct irlap_cb *self, IRLAP_EVENT event, 
 			       struct sk_buff *skb, struct irlap_info *info) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
 
 	return -1;
 }
@@ -1913,7 +1911,7 @@
 {
 	int ret = 0;
 
-	DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	IRDA_DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
 
 	ASSERT( self != NULL, return -ENODEV;);
 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -1933,7 +1931,7 @@
 		irlap_start_wd_timer( self, WD_TIMEOUT);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
 		      event, irlap_event[event]);
 		ret = -1;
 		break;
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.3.23/linux/net/irda/irlap_frame.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irlap_frame.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Tue Sep 28 08:49:58 1999
+ * Modified at:   Sat Oct  9 09:42:11 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -43,23 +43,25 @@
 #include <net/irda/qos.h>
 
 /*
- * Function irlap_insert_mtt (self, skb)
+ * Function irlap_insert_info (self, skb)
  *
- *    Insert minimum turnaround time relevant information into the skb. We 
+ *    Insert minimum turnaround time and speed information into the skb. We 
  *    need to do this since it's per packet relevant information.
  *
  */
-static inline void irlap_insert_mtt(struct irlap_cb *self, struct sk_buff *skb)
+static inline void irlap_insert_info(struct irlap_cb *self, 
+				     struct sk_buff *skb)
 {
 	struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
 
-	/* 
-	 * Insert MTT (min. turn time) into skb, so that the device driver 
-	 * knows which MTT to use 
-	 */	
+	/*  
+	 * Insert MTT (min. turn time) and speed into skb, so that the
+	 * device driver knows which settings to use 
+	 */
 	cb->magic = LAP_MAGIC;
 	cb->mtt = self->mtt_required;
-	
+	cb->speed = self->qos_tx.baud_rate.value;
+
 	/* Reset */
 	self->mtt_required = 0;
 	
@@ -94,10 +96,9 @@
  	skb->protocol = htons(ETH_P_IRDA);
 	skb->priority = TC_PRIO_BESTEFFORT;
 
-	irlap_insert_mtt(self, skb);
+	irlap_insert_info(self, skb);
 
 	dev_queue_xmit(skb);
-	self->stats.tx_packets++;
 }
 
 /*
@@ -169,7 +170,7 @@
 
 		/* Check if the new connection address is valid */
 		if ((info->caddr == 0x00) || (info->caddr == 0xfe)) {
-			DEBUG(3, __FUNCTION__ 
+			IRDA_DEBUG(3, __FUNCTION__ 
 			      "(), invalid connection address!\n");
 			dev_kfree_skb(skb);
 			return;
@@ -181,7 +182,7 @@
 		
 		/* Only accept if addressed directly to us */
 		if (info->saddr != self->saddr) {
-			DEBUG(2, __FUNCTION__ "(), not addressed to us!\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), not addressed to us!\n");
 			dev_kfree_skb(skb);
 			return;
 		}
@@ -203,7 +204,7 @@
 	struct ua_frame *frame;
 	int ret;
 	
-	DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
+	IRDA_DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -280,7 +281,7 @@
 	struct sk_buff *skb = NULL;
 	__u8 *frame;
 	
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -312,7 +313,7 @@
 	__u32 bcast = BROADCAST;
 	__u8 *info;
 
- 	DEBUG(4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command);
+ 	IRDA_DEBUG(4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -404,7 +405,7 @@
 	__u8 *discovery_info;
 	char *text;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -417,7 +418,7 @@
 	/* Make sure frame is addressed to us */
 	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
 		dev_kfree_skb(skb);
-		DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
 		return;
 	}
 
@@ -431,14 +432,14 @@
 	discovery->saddr = self->saddr;
 	discovery->timestamp = jiffies;
 
-	DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
+	IRDA_DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
 
 	discovery_info = skb_pull(skb, sizeof(struct xid_frame));
 
 	/* Get info returned from peer */
 	discovery->hints.byte[0] = discovery_info[0];
 	if (discovery_info[0] & HINT_EXTENSION) {
-		DEBUG(4, "EXTENSION\n");
+		IRDA_DEBUG(4, "EXTENSION\n");
 		discovery->hints.byte[1] = discovery_info[1];
 		discovery->charset = discovery_info[2];
 		text = (char *) &discovery_info[3];
@@ -482,7 +483,7 @@
 
 	/* Make sure frame is addressed to us */
 	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
-		DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
 		dev_kfree_skb(skb);
 		return;
 	}
@@ -619,7 +620,7 @@
 
 	frame[2] = 0;
 
-   	DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
+   	IRDA_DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
 
 	irlap_queue_xmit(self, skb);
 }
@@ -641,7 +642,7 @@
 	frame = skb->data;
 	info->nr = frame[1] >> 5;
 
-	DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+	IRDA_DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
 
 	irlap_do_event( self, RECV_RNR_FRAME, skb, info);
 }
@@ -700,7 +701,7 @@
 
 		irlap_send_i_frame( self, tx_skb, CMD_FRAME);
 	} else {
-		DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n");
+		IRDA_DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n");
 		irlap_send_ui_frame(self, skb, CMD_FRAME);
 		self->window -= 1;
 	}
@@ -759,7 +760,7 @@
 
 		irlap_send_i_frame(self, tx_skb, CMD_FRAME);
 	} else {
-		DEBUG(4, __FUNCTION__ "(), sending unreliable frame\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), sending unreliable frame\n");
 
 		del_timer(&self->poll_timer);
 
@@ -959,7 +960,7 @@
 
 	while (skb_queue_len( &self->tx_list) > 0) {
 		
-		DEBUG(0, __FUNCTION__ "(), sending additional frames!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), sending additional frames!\n");
 		if ((skb_queue_len( &self->tx_list) > 0) && 
 		    (self->window > 0)) {
 			skb = skb_dequeue( &self->tx_list); 
@@ -991,7 +992,7 @@
 {
 	__u8  *frame;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -1056,7 +1057,7 @@
 {
 	__u8 *frame;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	frame = skb->data;
 
@@ -1077,7 +1078,7 @@
 	__u8 *frame;
 	int w, x, y, z;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -1096,20 +1097,20 @@
 	z = frame[3] & 0x08;
 	
 	if (w) {
-		DEBUG(0, "Rejected control field is undefined or not "
+		IRDA_DEBUG(0, "Rejected control field is undefined or not "
 		      "implemented.\n");
 	} 
 	if (x) {
-		DEBUG(0, "Rejected control field was invalid because it "
+		IRDA_DEBUG(0, "Rejected control field was invalid because it "
 		      "contained a non permitted I field.\n");
 	}
 	if (y) {
-		DEBUG(0, "Received I field exceeded the maximum negotiated "
+		IRDA_DEBUG(0, "Received I field exceeded the maximum negotiated "
 		      "for the existing connection or exceeded the maximum "
 		      "this station supports if no connection exists.\n");
 	}
 	if (z) {
-		DEBUG(0, "Rejected control field control field contained an "
+		IRDA_DEBUG(0, "Rejected control field control field contained an "
 		      "invalid Nr count.\n");
 	}
 	irlap_do_event(self, RECV_FRMR_RSP, skb, info);
@@ -1168,10 +1169,10 @@
 {
 	struct test_frame *frame;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	if (skb->len < sizeof(struct test_frame)) {
-		DEBUG(0, __FUNCTION__ "() test frame to short!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() test frame to short!\n");
 		return;
 	}
 
@@ -1205,12 +1206,11 @@
 {
 	struct irlap_info info;
 	struct irlap_cb *self;
-	struct irda_device *idev;
 	int command;
 	__u8 control;
 	
-	idev = (struct irda_device *) dev->priv;
-	self = idev->irlap;
+	/* FIXME: should we get our own field? */
+	self = (struct irlap_cb *) dev->atalk_ptr;
 
 	/* If the net device is down, then IrLAP is gone! */
 	if (!self || self->magic != LAP_MAGIC) {
@@ -1235,7 +1235,7 @@
 
 	/*  First we check if this frame has a valid connection address */
 	if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {
-		DEBUG(0, __FUNCTION__ "(), wrong connection address!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), wrong connection address!\n");
 		dev_kfree_skb(skb);
 		return 0;
 	}
@@ -1245,7 +1245,6 @@
 	 */
 	if (~control & 0x01) {
 		irlap_recv_i_frame(self, skb, &info, command);
-		self->stats.rx_packets++;
 		return 0;
 	}
 	/*
@@ -1260,17 +1259,15 @@
 		switch (control & 0x0f) {
 		case RR:
 			irlap_recv_rr_frame(self, skb, &info, command);
-			self->stats.rx_packets++;
 			break;
 		case RNR:
 			irlap_recv_rnr_frame(self, skb, &info);
-			self->stats.rx_packets++;
 			break;
 		case REJ:
-			DEBUG( 0, "*** REJ frame received! ***\n");
+			IRDA_DEBUG( 0, "*** REJ frame received! ***\n");
 			break;
 		case SREJ:
-			DEBUG( 0, "*** SREJ frame received! ***\n");
+			IRDA_DEBUG( 0, "*** SREJ frame received! ***\n");
 			break;
 		default:
 			WARNING(__FUNCTION__ 
@@ -1294,7 +1291,7 @@
 		irlap_recv_snrm_cmd(self, skb, &info);
 		break;
 	case DM_RSP:
-		DEBUG( 0, "DM rsp frame received!\n");
+		IRDA_DEBUG( 0, "DM rsp frame received!\n");
 		irlap_next_state(self, LAP_NDM);
 		break;
 	case DISC_CMD:
@@ -1310,7 +1307,6 @@
 		irlap_recv_frmr_frame(self, skb, &info);
 		break;
 	case UI_FRAME:
-		DEBUG(4, "UI-frame received!\n");
 		irlap_recv_ui_frame(self, skb, &info);
 		break;
 	default:
@@ -1319,7 +1315,5 @@
 		dev_kfree_skb( skb); 
 		break;
 	}
-	self->stats.rx_packets++;
-
 	return 0;
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.3.23/linux/net/irda/irlmp.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irlmp.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Mon Sep 27 11:15:20 1999
+ * Modified at:   Sat Oct  9 17:00:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/random.h>
-#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -189,7 +188,7 @@
 	/*
 	 *  Insert into queue of unconnected LSAPs
 	 */
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) self, (int) self, 
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self, 
 		       NULL);
 	
 	return self;
@@ -202,7 +201,7 @@
  */
 static void __irlmp_close_lsap(struct lsap_cb *self)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
@@ -249,7 +248,7 @@
 				      NULL);
 	}
 	if (!lsap) {
-		DEBUG(0, __FUNCTION__ 
+		IRDA_DEBUG(0, __FUNCTION__ 
 		       "(), Looks like somebody has removed me already!\n");
 		return;
 	}
@@ -294,7 +293,7 @@
 	/*
 	 *  Insert into queue of unconnected LSAPs
 	 */
-	hashbin_insert(irlmp->links, (QUEUE *) lap, lap->saddr, NULL);
+	hashbin_insert(irlmp->links, (queue_t *) lap, lap->saddr, NULL);
 
 	/* 
 	 *  We set only this variable so IrLAP can tell us on which link the
@@ -314,7 +313,7 @@
 {
 	struct lap_cb *link;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	link = hashbin_remove(irlmp->links, saddr, NULL);
 	if (link) {
@@ -348,7 +347,7 @@
 	ASSERT(self != NULL, return -EBADR;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
 	
-	DEBUG(2, __FUNCTION__ 
+	IRDA_DEBUG(2, __FUNCTION__ 
 	      "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n", 
 	      self->slsap_sel, dlsap_sel, saddr, daddr);
 	
@@ -391,14 +390,14 @@
 	}
 	lap = hashbin_find(irlmp->links, saddr, NULL);	
 	if (lap == NULL) {
-		DEBUG(1, __FUNCTION__ "(), Unable to find a usable link!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unable to find a usable link!\n");
 		return -EHOSTUNREACH;
 	}
 
 	if (lap->daddr == DEV_ADDR_ANY)
 		lap->daddr = daddr;
 	else if (lap->daddr != daddr) {
-		DEBUG(0, __FUNCTION__ "(), sorry, but link is busy!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), sorry, but link is busy!\n");
 		return -EBUSY;
 	}
 
@@ -415,7 +414,7 @@
 	ASSERT(lsap->lap != NULL, return -1;);
 	ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
 
-	hashbin_insert(self->lap->lsaps, (QUEUE *) self, (int) self, NULL);
+	hashbin_insert(self->lap->lsaps, (queue_t *) self, (int) self, NULL);
 
 	self->connected = TRUE;
 	
@@ -447,19 +446,19 @@
 	ASSERT(skb != NULL, return;);
 	ASSERT(self->lap != NULL, return;);
 
-	DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
 	      self->slsap_sel, self->dlsap_sel);
 
 	self->qos = *self->lap->qos;
 
 	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
-	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
 	
-	lap_header_size = irlap_get_header_size(self->lap->irlap);
+	lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);
 
 	max_header_size = LMP_HEADER + lap_header_size;
 
-	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
 
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
@@ -484,7 +483,7 @@
 
 	self->connected = TRUE;
 
-	DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
 	      self->slsap_sel, self->dlsap_sel);
 
 	/* Make room for MUX control header ( 3 bytes) */
@@ -507,7 +506,7 @@
 	int lap_header_size;
 	int max_seg_size;
 
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 	
 	ASSERT(skb != NULL, return;);
 	ASSERT(self != NULL, return;);
@@ -517,10 +516,10 @@
 	self->qos = *self->lap->qos;
 
 	max_seg_size    = self->lap->qos->data_size.value-LMP_HEADER;
-	lap_header_size = irlap_get_header_size(self->lap->irlap);	
+	lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);	
 	max_header_size = LMP_HEADER + lap_header_size;
 
-	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
 
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
@@ -543,16 +542,16 @@
 {
 	struct lsap_cb *new;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	/* Only allowed to duplicate unconnected LSAP's */
 	if (!hashbin_find(irlmp->unconnected_lsaps, (int) orig, NULL)) {
-		DEBUG(0, __FUNCTION__ "(), unable to find LSAP\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to find LSAP\n");
 		return NULL;
 	}
 	new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
 	if (!new)  {
-		DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
 		return NULL;
 	}
 	/* Dup */
@@ -561,7 +560,7 @@
 	
 	init_timer(&new->watchdog_timer);
 	
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) new, (int) new, 
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) new, (int) new, 
 		       NULL);
 
 	/* Make sure that we invalidate the cache */
@@ -616,7 +615,7 @@
 	ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
 	ASSERT(lsap == self, return -1;);
 
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) self, (int) self, 
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self, 
 		       NULL);
 	
 	/* Reset some values */
@@ -637,13 +636,13 @@
 {
 	struct lsap_cb *lsap;
 
-	DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);	
+	IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);	
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
  	ASSERT(self->connected == TRUE, return;); 
 
-	DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
 	      self->slsap_sel, self->dlsap_sel);
 
 	self->connected = FALSE;
@@ -663,7 +662,7 @@
 
 	ASSERT(lsap != NULL, return;);
 	ASSERT(lsap == self, return;);
-	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) lsap, (int) lsap, 
+	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) lsap, (int) lsap, 
 		       NULL);
 
 	self->lap = NULL;
@@ -691,7 +690,7 @@
 	if ((nslots != 1) && (nslots != 6) && 
 	    (nslots != 8) && (nslots != 16)) 
 	{
-		printk(KERN_WARNING __FUNCTION__ 
+		WARNING(__FUNCTION__ 
 		       "(), invalid value for number of slots!\n");
 		nslots = sysctl_discovery_slots = 8;
 	}
@@ -768,8 +767,8 @@
 	__u8 service;
 	int i = 0;
 
-	DEBUG(1, "IrDA Discovered: %s\n", discovery->info);
-	DEBUG(1, "    Services: ");
+	IRDA_DEBUG(1, "IrDA Discovered: %s\n", discovery->info);
+	IRDA_DEBUG(1, "    Services: ");
 
 	service_log = irlmp_hint_to_service(discovery->hints.byte);
 	if (!service_log)
@@ -779,10 +778,10 @@
 	 *  Check all services on the device
 	 */
 	while ((service = service_log[i++]) != S_END) {
-		DEBUG( 4, "service=%02x\n", service);
+		IRDA_DEBUG( 4, "service=%02x\n", service);
 		client = hashbin_find(irlmp->registry, service, NULL);
 		if (entry && entry->discovery_callback) {
-			DEBUG( 4, "discovery_callback!\n");
+			IRDA_DEBUG( 4, "discovery_callback!\n");
 
 			entry->discovery_callback(discovery);
 		} else {
@@ -814,7 +813,7 @@
 {
 	discovery_t *discovery;
 
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 	
 	/* Check if client wants the whole log */
 	if (client->callback2)
@@ -826,7 +825,7 @@
 	 */
 	discovery = (discovery_t *) hashbin_get_first(log);
 	while (discovery != NULL) {
-		DEBUG(3, "discovery->daddr = 0x%08x\n", discovery->daddr); 
+		IRDA_DEBUG(3, "discovery->daddr = 0x%08x\n", discovery->daddr); 
 		
 		/* 
 		 * Any common hint bits? Remember to mask away the extension
@@ -851,11 +850,11 @@
 {
 	irlmp_client_t *client;
 	
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 	
 	ASSERT(log != NULL, return;);
 	
-	if (!hashbin_get_size(log))
+	if (!(HASHBIN_GET_SIZE(log)))
 		return;
 	
 	client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
@@ -875,7 +874,7 @@
  */
 discovery_t *irlmp_get_discovery_response()
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(irlmp != NULL, return NULL;);
 
@@ -936,7 +935,7 @@
  */
 inline void irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG(4, __FUNCTION__ "()\n"); 
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
 	ASSERT(skb != NULL, return;);
 	
@@ -955,7 +954,7 @@
  */
 void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG(4, __FUNCTION__ "()\n"); 
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
@@ -976,7 +975,7 @@
  */
 void irlmp_connectionless_data_request( struct sk_buff *skb)
 {
-	DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n"); 
+	IRDA_DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n"); 
 }
 
 /*
@@ -987,17 +986,17 @@
  */
 void irlmp_connectionless_data_indication(struct sk_buff *skb)
 {
-	DEBUG( 1, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG( 1, __FUNCTION__ "()\n"); 
 }
 
 void irlmp_status_request(void) 
 {
-	DEBUG(0, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock) 
 {
-	DEBUG(1, __FUNCTION__ "(), Not implemented\n");
+	IRDA_DEBUG(1, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -1017,31 +1016,31 @@
 	 */
 	service = kmalloc(16, GFP_ATOMIC);
 	if (!service) {
-		DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
 	if (!hint[0]) {
-		DEBUG(1, "<None>\n");
+		IRDA_DEBUG(1, "<None>\n");
 		kfree(service);
 		return NULL;
 	}
 	if (hint[0] & HINT_PNP)
-		DEBUG(1, "PnP Compatible ");
+		IRDA_DEBUG(1, "PnP Compatible ");
 	if (hint[0] & HINT_PDA)
-		DEBUG(1, "PDA/Palmtop ");
+		IRDA_DEBUG(1, "PDA/Palmtop ");
 	if (hint[0] & HINT_COMPUTER)
-		DEBUG(1, "Computer ");
+		IRDA_DEBUG(1, "Computer ");
 	if (hint[0] & HINT_PRINTER) {
-		DEBUG(1, "Printer ");
+		IRDA_DEBUG(1, "Printer ");
 		service[i++] = S_PRINTER;
 	}
 	if (hint[0] & HINT_MODEM)
-		DEBUG(1, "Modem ");
+		IRDA_DEBUG(1, "Modem ");
 	if (hint[0] & HINT_FAX)
-		DEBUG(1, "Fax ");
+		IRDA_DEBUG(1, "Fax ");
 	if (hint[0] & HINT_LAN) {
-		DEBUG(1, "LAN Access ");		
+		IRDA_DEBUG(1, "LAN Access ");		
 		service[i++] = S_LAN;
 	}
 	/* 
@@ -1051,21 +1050,21 @@
 	 */
 	if (hint[0] & HINT_EXTENSION) {
 		if (hint[1] & HINT_TELEPHONY) {
-			DEBUG(1, "Telephony ");
+			IRDA_DEBUG(1, "Telephony ");
 			service[i++] = S_TELEPHONY;
 		} if (hint[1] & HINT_FILE_SERVER)
-			DEBUG(1, "File Server ");
+			IRDA_DEBUG(1, "File Server ");
 		
 		if (hint[1] & HINT_COMM) {
-			DEBUG(1, "IrCOMM ");
+			IRDA_DEBUG(1, "IrCOMM ");
 			service[i++] = S_COMM;
 		}
 		if (hint[1] & HINT_OBEX) {
-			DEBUG(1, "IrOBEX ");
+			IRDA_DEBUG(1, "IrOBEX ");
 			service[i++] = S_OBEX;
 		}
 	}
-	DEBUG(1, "\n");
+	IRDA_DEBUG(1, "\n");
 
 	/* So that client can be notified about any discovery */
 	service[i++] = S_ANY;
@@ -1123,7 +1122,7 @@
 		hint.word = 0xffff;
 		break;
 	default:
-		DEBUG( 1, __FUNCTION__ "(), Unknown service!\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), Unknown service!\n");
 		break;
 	}
 	return hint.word;
@@ -1140,7 +1139,7 @@
 	irlmp_service_t *service;
 	__u32 handle;
 
-	DEBUG(4, __FUNCTION__ "(), hints = %04x\n", hints);
+	IRDA_DEBUG(4, __FUNCTION__ "(), hints = %04x\n", hints);
 
 	/* Get a unique handle for this service */
 	get_random_bytes(&handle, sizeof(handle));
@@ -1152,11 +1151,11 @@
 	/* Make a new registration */
  	service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);
 	if (!service) {
-		DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return 0;
 	}
 	service->hints = hints;
-	hashbin_insert(irlmp->services, (QUEUE*) service, handle, NULL);
+	hashbin_insert(irlmp->services, (queue_t *) service, handle, NULL);
 
 	return handle;
 }
@@ -1172,14 +1171,14 @@
 {
 	irlmp_service_t *service;
 		
- 	DEBUG(4, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	if (!handle)
 		return -1;
  
 	service = hashbin_find(irlmp->services, handle, NULL);
 	if (!service) {
-		DEBUG(1, __FUNCTION__ "(), Unknown service!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown service!\n");
 		return -1;
 	}
 
@@ -1221,7 +1220,7 @@
 	/* Make a new registration */
  	client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
 	if (!client) {
-		DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
 
 		return 0;
 	}
@@ -1231,7 +1230,7 @@
 	client->callback1 = callback1;
 	client->callback2 = callback2;
 
- 	hashbin_insert(irlmp->clients, (QUEUE *) client, handle, NULL);
+ 	hashbin_insert(irlmp->clients, (queue_t *) client, handle, NULL);
 
 	return handle;
 }
@@ -1255,7 +1254,7 @@
 
 	client = hashbin_find(irlmp->clients, handle, NULL);
 	if (!client) {
-		DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
 		return -1;
 	}
 
@@ -1276,18 +1275,18 @@
 {
  	struct irlmp_client *client;
  
- 	DEBUG(4, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	if (!handle)
 		return -1;
  
 	client = hashbin_find(irlmp->clients, handle, NULL);
 	if (!client) {
-		DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown client!\n");
 		return -1;
 	}
 
-	DEBUG( 4, __FUNCTION__ "(), removing client!\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "(), removing client!\n");
 	client = hashbin_remove( irlmp->clients, handle, NULL);
 	if (client)
 		kfree(client);
@@ -1309,7 +1308,7 @@
 	ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
 	ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Valid values are between 0 and 127 */
 	if (slsap_sel > 127)
@@ -1329,7 +1328,7 @@
 			ASSERT(self->magic == LMP_LSAP_MAGIC, return TRUE;);
 
 			if ((self->slsap_sel == slsap_sel)) {
-				DEBUG(4, "Source LSAP selector=%02x in use\n",
+				IRDA_DEBUG(4, "Source LSAP selector=%02x in use\n",
 				      self->slsap_sel); 
 				return TRUE;
 			}
@@ -1369,7 +1368,7 @@
 				return 0;
 		}
 	}
-	DEBUG(4, __FUNCTION__ "(), next free lsap_sel=%02x\n", lsap_sel);
+	IRDA_DEBUG(4, __FUNCTION__ "(), next free lsap_sel=%02x\n", lsap_sel);
 	
 	return lsap_sel;
 }
@@ -1387,25 +1386,25 @@
 
 	switch (lap_reason) {		
 	case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
-		DEBUG( 1, __FUNCTION__ "(), LAP_DISC_INDICATION\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), LAP_DISC_INDICATION\n");
 		reason = LM_USER_REQUEST;
 		break;
 	case LAP_NO_RESPONSE:    /* To many retransmits without response */
-		DEBUG( 1, __FUNCTION__ "(), LAP_NO_RESPONSE\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), LAP_NO_RESPONSE\n");
 		reason = LM_LAP_DISCONNECT;
 		break;
 	case LAP_RESET_INDICATION:
-		DEBUG( 1, __FUNCTION__ "(), LAP_RESET_INDICATION\n");
+		IRDA_DEBUG( 1, __FUNCTION__ "(), LAP_RESET_INDICATION\n");
 		reason = LM_LAP_RESET;
 		break;
 	case LAP_FOUND_NONE:
 	case LAP_MEDIA_BUSY:
 	case LAP_PRIMARY_CONFLICT:
-		DEBUG(1, __FUNCTION__ "(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n");
 		reason = LM_CONNECT_FAILURE;
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ 
+		IRDA_DEBUG(1, __FUNCTION__ 
 		      "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
 		reason = LM_LAP_DISCONNECT;
 		break;
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.3.23/linux/net/irda/irlmp_event.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irlmp_event.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Tue Sep 21 13:04:33 1999
+ * Modified at:   Tue Oct  5 13:47:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -120,7 +120,7 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
+	IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
 	      irlmp_event[ event], irlmp_state[ self->lsap_state]);
 
 	return (*lsap_state[self->lsap_state]) (self, event, skb);
@@ -138,7 +138,7 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	
-	DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
+	IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
 	      irlmp_event[event], 
 	      irlmp_state[self->lap_state]);
 
@@ -147,7 +147,7 @@
 
 void irlmp_discovery_timer_expired(void *data)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	if (sysctl_discovery)
 		irlmp_do_discovery(sysctl_discovery_slots);
@@ -160,7 +160,7 @@
 {
 	struct lsap_cb *self = (struct lsap_cb *) data;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
@@ -172,7 +172,7 @@
 {
 	struct lap_cb *self = (struct lap_cb *) data;
 	
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
@@ -195,7 +195,7 @@
 static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event, 
 				struct sk_buff *skb)
 {	
-	DEBUG(4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 	ASSERT(self->irlap != NULL, return;);
 	
 	switch (event) {
@@ -219,7 +219,7 @@
 		irlap_connect_response(self->irlap, skb);
 		break;
 	case LM_LAP_CONNECT_REQUEST:
-		DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
+		IRDA_DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
 
 		/* FIXME: need to set users requested QoS */
 		irlap_connect_request(self->irlap, self->daddr, NULL, 0);
@@ -227,13 +227,13 @@
 		irlmp_next_lap_state(self, LAP_U_CONNECT);
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG(4, __FUNCTION__ 
+		IRDA_DEBUG(4, __FUNCTION__ 
 		      "(), Error LM_LAP_DISCONNECT_INDICATION\n");
 		
 		irlmp_next_lap_state( self, LAP_STANDBY);
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}
 }
@@ -251,7 +251,7 @@
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
 	
-	DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
+	IRDA_DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
 
 	switch (event) {
 	case LM_LAP_CONNECT_CONFIRM:
@@ -265,7 +265,7 @@
 		}		
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
 	
 		irlmp_next_lap_state(self, LAP_STANDBY);
 
@@ -285,7 +285,7 @@
 		}
 		break;
 	case LM_LAP_DISCONNECT_REQUEST:
-		DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
 
 		irlmp_next_lap_state(self, LAP_STANDBY);
 
@@ -293,7 +293,7 @@
 /* 		irlap_disconnect_request( self->irlap); */
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}	
 }
@@ -310,11 +310,11 @@
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
 
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n"); 
 
  	switch( event) {
 	case LM_LAP_CONNECT_REQUEST:
-		DEBUG( 4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
+		IRDA_DEBUG( 4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
 
 		/*
 		 *  LAP connection allready active, just bounce back! Since we 
@@ -347,7 +347,7 @@
 		 *  must be the one that tries to close IrLAP. It will be 
 		 *  removed later and moved to the list of unconnected LSAPs
 		 */
-		if (hashbin_get_size(self->lsaps) > 0)
+		if (HASHBIN_GET_SIZE(self->lsaps) > 0)
 			irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
 		else {
 			/* No more connections, so close IrLAP */
@@ -356,7 +356,7 @@
 		}
 		break;
 	case LM_LAP_IDLE_TIMEOUT:
-		if (hashbin_get_size(self->lsaps) == 0) {
+		if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
 			irlmp_next_lap_state(self, LAP_STANDBY);
 			irlap_disconnect_request(self->irlap);
 		}
@@ -381,7 +381,7 @@
 		}
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}	
 }
@@ -403,14 +403,14 @@
 {
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
 	switch (event) {
 	case LM_CONNECT_REQUEST:
-		DEBUG(4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
 		irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
 
 		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
@@ -424,7 +424,7 @@
 		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, skb);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 	return ret;
@@ -442,7 +442,7 @@
 	struct lsap_cb *lsap;
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
@@ -460,7 +460,7 @@
 		ASSERT(self->lap != NULL, return -1;);
 		ASSERT(self->lap->lsaps != NULL, return -1;);
 		
-		hashbin_insert(self->lap->lsaps, (QUEUE *) self, (int) self, 
+		hashbin_insert(self->lap->lsaps, (queue_t *) self, (int) self, 
 			       NULL);
 
 		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
@@ -471,7 +471,7 @@
 		irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}
 	return ret;
@@ -488,7 +488,7 @@
 {
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
@@ -498,22 +498,22 @@
 		/* Keep state */
 		break;
 	case LM_CONNECT_RESPONSE:
-		DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
 		      "no indication issued yet\n");
 		/* Keep state */
 		break;
 	case LM_DISCONNECT_REQUEST:
-		DEBUG(0, __FUNCTION__ "(), LM_DISCONNECT_REQUEST, "
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_DISCONNECT_REQUEST, "
 		      "not yet bound to IrLAP connection\n");
 		/* Keep state */
 		break;
 	case LM_LAP_CONNECT_CONFIRM:
-		DEBUG(4, __FUNCTION__ "(), LS_CONNECT_CONFIRM\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_CONFIRM\n");
 		irlmp_next_lsap_state(self, LSAP_CONNECT);
 		irlmp_connect_indication(self, skb);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
+		IRDA_DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
 		break;	
 	}
 	return ret;
@@ -531,7 +531,7 @@
 	LM_REASON reason;
 	int ret = 0;
 
- 	DEBUG(4, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
@@ -557,12 +557,12 @@
 		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_CONNECT_REQUEST:
-		DEBUG(0, __FUNCTION__ "(), LM_CONNECT_REQUEST, "
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_REQUEST, "
 		      "error, LSAP already connected\n");
 		/* Keep state */
 		break;
 	case LM_CONNECT_RESPONSE:
-		DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, " 
+		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, " 
 		      "error, LSAP allready connected\n");
 		/* Keep state */
 		break;
@@ -573,7 +573,7 @@
 		
 		/* Try to close the LAP connection if its still there */
 		if (self->lap) {
-			DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
+			IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
 			irlmp_do_lap_event(self->lap, 
 					   LM_LAP_DISCONNECT_REQUEST, 
 					   NULL);
@@ -597,13 +597,13 @@
 		reason = skb->data[3];
 
 		 /* Try to close the LAP connection */
-		DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
 
 		irlmp_disconnect_indication(self, reason, skb);
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
 	}
 	return ret;
@@ -625,7 +625,7 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	switch (event) {
 	case LM_CONNECT_CONFIRM:
@@ -646,7 +646,7 @@
 		reason = skb->data[3];
 
 		 /* Try to close the LAP connection */
-		DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
 
 		irlmp_disconnect_indication(self, reason, skb);
@@ -664,7 +664,7 @@
 		irlmp_disconnect_indication(self, reason, skb);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
-		DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 		
 		ASSERT(self->lap != NULL, return -1;);
 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
@@ -673,7 +673,7 @@
 		irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
 	}
 	return ret;
@@ -693,7 +693,7 @@
 	LM_REASON reason;
 	int ret = 0;
 
-	DEBUG(4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(irlmp != NULL, return -1;);
@@ -706,7 +706,7 @@
 		irlmp_next_lsap_state(self, LSAP_SETUP);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
-		DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 
 		ASSERT(self->lap != NULL, return -1;);
 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
@@ -724,7 +724,7 @@
 		irlmp_disconnect_indication(self, reason, NULL);
 		break;
 	default:
-		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
 	}
 	return ret;
@@ -732,7 +732,7 @@
 
 void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state) 
 {
-	DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
 	self->lap_state = state;
 }
 
@@ -740,6 +740,6 @@
 {
 	ASSERT(self != NULL, return;);
 
-	DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
 	self->lsap_state = state;
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.3.23/linux/net/irda/irlmp_frame.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/irlmp_frame.c	Mon Oct 25 20:49:42 1999
@@ -44,7 +44,7 @@
 	skb->data[1] = slsap;
 
 	if (expedited) {
-		DEBUG(4, __FUNCTION__ "(), sending expedited data\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), sending expedited data\n");
 		irlap_data_request(self->irlap, skb, FALSE);
 	} else
 		irlap_data_request(self->irlap, skb, TRUE);
@@ -60,7 +60,7 @@
 {
 	__u8 *frame;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
@@ -114,7 +114,7 @@
 	 *  it in a different way than other established connections.
 	 */
 	if ((fp[0] & CONTROL_BIT) && (fp[2] == CONNECT_CMD)) {
-		DEBUG(3,"Incoming connection, source LSAP=%d, dest LSAP=%d\n",
+		IRDA_DEBUG(3,"Incoming connection, source LSAP=%d, dest LSAP=%d\n",
 		      slsap_sel, dlsap_sel);
 		
 		/* Try to find LSAP among the unconnected LSAPs */
@@ -130,15 +130,15 @@
 				       self->lsaps);
 	
 	if (lsap == NULL) {
-		DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
-		DEBUG(2, __FUNCTION__ 
+		IRDA_DEBUG(2, "IrLMP, Sorry, no LSAP for received frame!\n");
+		IRDA_DEBUG(2, __FUNCTION__ 
 		      "(), slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, 
 		      dlsap_sel);
 		if (fp[0] & CONTROL_BIT) {
-			DEBUG(2, __FUNCTION__ 
+			IRDA_DEBUG(2, __FUNCTION__ 
 			      "(), received control frame %02x\n", fp[2]);
 		} else {
-			DEBUG(2, __FUNCTION__ "(), received data frame\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), received data frame\n");
 		}
 		dev_kfree_skb(skb);
 		return;
@@ -157,18 +157,18 @@
 			irlmp_do_lsap_event(lsap, LM_CONNECT_CONFIRM, skb);
 			break;
 		case DISCONNECT:
-			DEBUG( 4, __FUNCTION__ "(), Disconnect indication!\n");
+			IRDA_DEBUG( 4, __FUNCTION__ "(), Disconnect indication!\n");
 			irlmp_do_lsap_event(lsap, LM_DISCONNECT_INDICATION, 
 					    skb);
 			break;
 		case ACCESSMODE_CMD:
-			DEBUG( 0, "Access mode cmd not implemented!\n");
+			IRDA_DEBUG( 0, "Access mode cmd not implemented!\n");
 			break;
 		case ACCESSMODE_CNF:
-			DEBUG( 0, "Access mode cnf not implemented!\n");
+			IRDA_DEBUG( 0, "Access mode cnf not implemented!\n");
 			break;
 		default:
-			DEBUG( 0, __FUNCTION__ 
+			IRDA_DEBUG( 0, __FUNCTION__ 
 			       "(), Unknown control frame %02x\n", fp[2]);
 			break;
 		}
@@ -198,7 +198,7 @@
 				      LAP_REASON reason, 
 				      struct sk_buff *userdata)
 {
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(lap != NULL, return;);
 	ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
@@ -224,7 +224,7 @@
 				   __u32 daddr, struct qos_info *qos,
 				   struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Copy QoS settings for this session */
 	self->qos = qos;
@@ -245,7 +245,7 @@
 void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, 
 				struct sk_buff *userdata)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
@@ -287,7 +287,7 @@
  */
 void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
diff -u --recursive --new-file v2.3.23/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.23/linux/net/irda/irmod.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irmod.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Mon Sep 20 09:27:25 1999
+ * Modified at:   Mon Oct 18 14:54:35 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -173,28 +173,31 @@
 EXPORT_SYMBOL(hashbin_get_first);
 
 /* IrLAP */
+EXPORT_SYMBOL(irlap_open);
+EXPORT_SYMBOL(irlap_close);
 #ifdef CONFIG_IRDA_COMPRESSION
 EXPORT_SYMBOL(irda_unregister_compressor);
 EXPORT_SYMBOL(irda_register_compressor);
 #endif /* CONFIG_IRDA_COMPRESSION */
 EXPORT_SYMBOL(irda_init_max_qos_capabilies);
 EXPORT_SYMBOL(irda_qos_bits_to_value);
-EXPORT_SYMBOL(irda_device_open);
-EXPORT_SYMBOL(irda_device_close);
 EXPORT_SYMBOL(irda_device_setup);
 EXPORT_SYMBOL(irda_device_set_media_busy);
 EXPORT_SYMBOL(irda_device_txqueue_empty);
-EXPORT_SYMBOL(irda_device_net_open);
-EXPORT_SYMBOL(irda_device_net_close);
 
-EXPORT_SYMBOL(irda_device_init_dongle);
+EXPORT_SYMBOL(irda_device_dongle_init);
+EXPORT_SYMBOL(irda_device_dongle_cleanup);
 EXPORT_SYMBOL(irda_device_register_dongle);
 EXPORT_SYMBOL(irda_device_unregister_dongle);
+EXPORT_SYMBOL(irda_task_execute);
+EXPORT_SYMBOL(irda_task_kick);
+EXPORT_SYMBOL(irda_task_next_state);
 
 EXPORT_SYMBOL(async_wrap_skb);
 EXPORT_SYMBOL(async_unwrap_char);
 EXPORT_SYMBOL(irda_start_timer);
 EXPORT_SYMBOL(setup_dma);
+EXPORT_SYMBOL(infrared_mode);
 
 #ifdef CONFIG_IRTTY
 EXPORT_SYMBOL(irtty_set_dtr_rts);
@@ -205,7 +208,7 @@
 
 int __init irda_init(void)
 {
-	printk(KERN_INFO "IrDA (tm) Protocols for Linux-2.3 (Dag Brattli)\n");
+	MESSAGE("IrDA (tm) Protocols for Linux-2.3 (Dag Brattli)\n");
 	
  	irlmp_init();
 	irlap_init();
@@ -344,7 +347,7 @@
 	new->param = param;
 	
 	/* Queue todo */
-	enqueue_last(&irda.todo_queue, (QUEUE *) new);
+	enqueue_last(&irda.todo_queue, (queue_t *) new);
 
 	event.event = EVENT_NEED_PROCESS_CONTEXT;
 
@@ -362,7 +365,7 @@
 {
 	struct irda_event *new;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	/* Make sure irmanager is running */
 	if (!irda.in_use) {
@@ -380,7 +383,7 @@
 	new->event = *event;
 	
 	/* Queue event */
-	enqueue_last(&irda.event_queue, (QUEUE *) new);
+	enqueue_last(&irda.event_queue, (queue_t *) new);
 	
 	/* Wake up irmanager sleeping on read */
 	wake_up_interruptible(&irda.wait_queue);
@@ -388,10 +391,10 @@
 
 static int irda_open( struct inode * inode, struct file *file)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	if ( irda.in_use) {
-		DEBUG( 0, __FUNCTION__ "(), irmanager is already running!\n");
+		IRDA_DEBUG( 0, __FUNCTION__ "(), irmanager is already running!\n");
 		return -1;
 	}
 	irda.in_use = TRUE;
@@ -414,7 +417,7 @@
 	int err = 0;
 	int size = _IOC_SIZE(cmd);
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	if ( _IOC_DIR(cmd) & _IOC_READ)
 		err = verify_area( VERIFY_WRITE, (void *) arg, size);
@@ -426,7 +429,7 @@
 	switch( cmd) {
 	case IRMGR_IOCTNPC:
 		/* Got process context! */
-		DEBUG(4, __FUNCTION__ "(), got process context!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), got process context!\n");
 		
 		while ((todo = (struct irda_todo *) dequeue_first( 
 			&irda.todo_queue)) != NULL)
@@ -446,7 +449,7 @@
 
 static int irda_close(struct inode *inode, struct file *file)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	MOD_DEC_USE_COUNT;
 	
@@ -462,7 +465,7 @@
 	unsigned long flags;
 	int len;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* * Go to sleep and wait for event if there is no event to be read! */
 	save_flags( flags);
@@ -494,14 +497,14 @@
 static ssize_t irda_write(struct file *file, const char *buffer,
 			  size_t count, loff_t *noidea)
 {
-	DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 	
 	return 0;
 }
 
 static u_int irda_poll(struct file *file, poll_table *wait)
 {
-	DEBUG(0, __FUNCTION__ "(), Sorry not implemented yet!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Sorry not implemented yet!\n");
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.3.23/linux/net/irda/irproc.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/irproc.c	Mon Oct 25 20:49:42 1999
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Fri Jun  4 09:39:49 1999
+ * Modified at:   Fri Oct  8 09:26:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999, Thomas Davis, <ratbert@radiks.net>, 
+ *
+ *     Copyright (c) 1998-1999, Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
  *     All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
@@ -30,8 +31,6 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp.h>
 
-extern int irda_device_proc_read(char *buf, char **start, off_t offset, 
-				 int len, int unused);
 extern int irlap_proc_read(char *buf, char **start, off_t offset, int len, 
 			   int unused);
 extern int irlmp_proc_read(char *buf, char **start, off_t offset, int len, 
@@ -43,16 +42,6 @@
 extern int discovery_proc_read(char *buf, char **start, off_t offset, int len, 
 			       int unused);
 
-/* enum irda_directory_inos { */
-/* 	PROC_IRDA_LAP = 1, */
-/* 	PROC_IRDA_LMP, */
-/* 	PROC_IRDA_TTP, */
-/* 	PROC_IRDA_LPT, */
-/* 	PROC_IRDA_COMM, */
-/*  	PROC_IRDA_IRDA_DEVICE, */
-/* 	PROC_IRDA_IRIAS */
-/* }; */
-
 struct irda_entry {
 	char *name;
 	int (*fn)(char*, char**, off_t, int, int);
@@ -62,7 +51,6 @@
  
 static struct irda_entry dir[] = {
 	{"discovery",	discovery_proc_read},
-	{"irda_device",	irda_device_proc_read},
 	{"irttp",	irttp_proc_read},
 	{"irlmp",	irlmp_proc_read},
 	{"irlap",	irlap_proc_read},
diff -u --recursive --new-file v2.3.23/linux/net/irda/irqueue.c linux/net/irda/irqueue.c
--- v2.3.23/linux/net/irda/irqueue.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/irqueue.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Thu Jun 10 11:00:12 1999
+ * Modified at:   Tue Oct  5 09:02:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
@@ -36,7 +36,7 @@
 #include <net/irda/irqueue.h>
 #include <net/irda/irmod.h>
 
-static QUEUE *dequeue_general( QUEUE **queue, QUEUE* element);
+static queue_t *dequeue_general( queue_t **queue, queue_t* element);
 static __u32 hash( char* name);
 
 /*
@@ -79,7 +79,7 @@
  */
 int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func)
 {
-	QUEUE* queue;
+	queue_t* queue;
 	int i;
 	
 	ASSERT(hashbin != NULL, return -1;);
@@ -89,12 +89,12 @@
 	 * Free the entries in the hashbin
 	 */
 	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i]);
+		queue = dequeue_first( (queue_t**) &hashbin->hb_queue[ i]);
 		while( queue ) {
 			if ( free_func)
 				(*free_func)( queue );
 			queue = dequeue_first( 
-				(QUEUE**) &hashbin->hb_queue[ i]);
+				(queue_t**) &hashbin->hb_queue[ i]);
 		}
 	}
 	hashbin->hb_size = 0;
@@ -112,7 +112,7 @@
  */
 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
 {
-	QUEUE* queue;
+	queue_t* queue;
 	int i;
 
 	ASSERT(hashbin != NULL, return -1;);
@@ -123,12 +123,12 @@
 	 *  it has been shown to work
 	 */
 	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first((QUEUE**) &hashbin->hb_queue[i]);
+		queue = dequeue_first((queue_t**) &hashbin->hb_queue[i]);
 		while (queue ) {
 			if (free_func)
 				(*free_func)(queue);
 			queue = dequeue_first( 
-				(QUEUE**) &hashbin->hb_queue[i]);
+				(queue_t**) &hashbin->hb_queue[i]);
 		}
 	}
 	
@@ -152,7 +152,7 @@
 {
 	int bin;
 	
-	DEBUG(0, "hashbin_lock\n");
+	IRDA_DEBUG(0, "hashbin_lock\n");
 
 	ASSERT(hashbin != NULL, return;);
 	ASSERT(hashbin->magic == HB_MAGIC, return;);
@@ -184,7 +184,7 @@
 {
 	int bin;
 
-	DEBUG(0, "hashbin_unlock()\n");
+	IRDA_DEBUG(0, "hashbin_unlock()\n");
 
 	ASSERT(hashbin != NULL, return;);
 	ASSERT(hashbin->magic == HB_MAGIC, return;);
@@ -210,12 +210,12 @@
  *    Insert an entry into the hashbin
  *
  */
-void hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, char* name)
+void hashbin_insert( hashbin_t* hashbin, queue_t* entry, __u32 hashv, char* name)
 {
 	unsigned long flags = 0;
 	int bin;
 
-	DEBUG( 4, __FUNCTION__"()\n");
+	IRDA_DEBUG( 4, __FUNCTION__"()\n");
 
 	ASSERT( hashbin != NULL, return;);
 	ASSERT( hashbin->magic == HB_MAGIC, return;);
@@ -250,7 +250,7 @@
 	 */
 	if ( hashbin->hb_type & HB_SORTED) {
 	} else {
-		enqueue_first( (QUEUE**) &hashbin->hb_queue[ bin ],
+		enqueue_first( (queue_t**) &hashbin->hb_queue[ bin ],
 			       entry);
 	}
 	hashbin->hb_size++;
@@ -275,9 +275,9 @@
 {
 	int bin, found = FALSE;
 	unsigned long flags = 0;
-	QUEUE* entry;
+	queue_t* entry;
 
-	DEBUG( 4, "hashbin_find()\n");
+	IRDA_DEBUG( 4, "hashbin_find()\n");
 
 	ASSERT( hashbin != NULL, return NULL;);
 	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
@@ -342,7 +342,7 @@
 void *hashbin_remove_first( hashbin_t *hashbin)
 {
 	unsigned long flags;
-	QUEUE *entry = NULL;
+	queue_t *entry = NULL;
 
 	save_flags(flags);
 	cli();
@@ -367,9 +367,9 @@
 {
 	int bin, found = FALSE;
 	unsigned long flags = 0;
-	QUEUE* entry;
+	queue_t* entry;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( hashbin != NULL, return NULL;);
 	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
@@ -421,8 +421,8 @@
 	 * If entry was found, dequeue it
 	 */
 	if ( found ) {
-		dequeue_general( (QUEUE**) &hashbin->hb_queue[ bin ],
-				 (QUEUE*) entry );
+		dequeue_general( (queue_t**) &hashbin->hb_queue[ bin ],
+				 (queue_t*) entry );
 		hashbin->hb_size--;
 
 		/*
@@ -457,9 +457,9 @@
  *    called before any calls to hashbin_get_next()!
  *
  */
-QUEUE *hashbin_get_first( hashbin_t* hashbin) 
+queue_t *hashbin_get_first( hashbin_t* hashbin) 
 {
-	QUEUE *entry;
+	queue_t *entry;
 	int i;
 
 	ASSERT( hashbin != NULL, return NULL;);
@@ -489,9 +489,9 @@
  *    NULL when all items have been traversed
  * 
  */
-QUEUE *hashbin_get_next( hashbin_t *hashbin)
+queue_t *hashbin_get_next( hashbin_t *hashbin)
 {
-	QUEUE* entry;
+	queue_t* entry;
 	int bin;
 	int i;
 
@@ -542,9 +542,9 @@
  *    Insert item into end of queue.
  *
  */
-static void __enqueue_last( QUEUE **queue, QUEUE* element)
+static void __enqueue_last( queue_t **queue, queue_t* element)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 * Check if queue is empty.
@@ -566,7 +566,7 @@
 	}	
 }
 
-inline void enqueue_last( QUEUE **queue, QUEUE* element)
+inline void enqueue_last( queue_t **queue, queue_t* element)
 {
 	unsigned long flags;
 	
@@ -584,10 +584,10 @@
  *    Insert item first in queue.
  *
  */
-void enqueue_first(QUEUE **queue, QUEUE* element)
+void enqueue_first(queue_t **queue, queue_t* element)
 {
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 * Check if queue is empty.
@@ -616,9 +616,9 @@
  *    Insert a queue (list) into the start of the first queue
  *
  */
-void enqueue_queue( QUEUE** queue, QUEUE** list )
+void enqueue_queue( queue_t** queue, queue_t** list )
 {
-	QUEUE* tmp;
+	queue_t* tmp;
 	
 	/*
 	 * Check if queue is empty
@@ -643,9 +643,9 @@
  *
  */
 #if 0
-static void enqueue_second(QUEUE **queue, QUEUE* element)
+static void enqueue_second(queue_t **queue, queue_t* element)
 {
-	DEBUG( 0, "enqueue_second()\n");
+	IRDA_DEBUG( 0, "enqueue_second()\n");
 
 	/*
 	 * Check if queue is empty.
@@ -674,11 +674,11 @@
  *    Remove first entry in queue
  *
  */
-QUEUE *dequeue_first(QUEUE **queue)
+queue_t *dequeue_first(queue_t **queue)
 {
-	QUEUE *ret;
+	queue_t *ret;
 
-	DEBUG( 4, "dequeue_first()\n");
+	IRDA_DEBUG( 4, "dequeue_first()\n");
 	
 	/*
 	 * Set return value
@@ -715,11 +715,11 @@
  *
  *
  */
-static QUEUE *dequeue_general(QUEUE **queue, QUEUE* element)
+static queue_t *dequeue_general(queue_t **queue, queue_t* element)
 {
-	QUEUE *ret;
+	queue_t *ret;
 	
-	DEBUG( 4, "dequeue_general()\n");
+	IRDA_DEBUG( 4, "dequeue_general()\n");
 	
 	/*
 	 * Set return value
diff -u --recursive --new-file v2.3.23/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.3.23/linux/net/irda/irttp.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/irttp.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Mon Sep 27 12:02:52 1999
+ * Modified at:   Tue Oct 19 21:40:00 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -90,7 +90,7 @@
 
 	irttp->tsaps = hashbin_new(HB_LOCAL);
 	if (!irttp->tsaps) {
-		printk(KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
+		ERROR(__FUNCTION__ "(), can't allocate IrTTP hashbin!\n");
 		return -ENOMEM;
 	}
 	
@@ -140,7 +140,7 @@
 
 	self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
 	if (self == NULL) {
-		DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
 		return NULL;
 	}
 	memset(self, 0, sizeof(struct tsap_cb));
@@ -168,7 +168,7 @@
 	 */
 	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
 	if (lsap == NULL) {
-		printk(KERN_ERR "IrTTP, Unable to get LSAP!!\n");
+		WARNING(__FUNCTION__ "(), unable to allocate LSAP!!\n");
 		return NULL;
 	}
 	
@@ -178,12 +178,12 @@
 	 *  the stsap_sel we have might not be valid anymore
 	 */
 	self->stsap_sel = lsap->slsap_sel;
-	DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
+	IRDA_DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
 
 	self->notify = *notify;
 	self->lsap = lsap;
 
-	hashbin_insert(irttp->tsaps, (QUEUE *) self, (int) self, NULL);
+	hashbin_insert(irttp->tsaps, (queue_t *) self, (int) self, NULL);
 
 	if (credit > TTP_MAX_QUEUE)
 		self->initial_credit = TTP_MAX_QUEUE;
@@ -227,7 +227,7 @@
 {
 	struct tsap_cb *tsap;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
@@ -236,7 +236,7 @@
 	if (self->connected) {
 		/* Check if disconnect is not pending */
 		if (!self->disconnect_pend) {
-			DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+			IRDA_DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
 			irttp_disconnect_request(self, NULL, P_NORMAL);
 		}
 		self->close_pend = TRUE;
@@ -272,16 +272,16 @@
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 	ASSERT(skb != NULL, return -1;);
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Check that nothing bad happens */
 	if ((skb->len == 0) || (!self->connected)) {
-		DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
 		return -1;
 	}
 	
 	if (skb->len > self->max_seg_size) {
-		DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
 		return -1;
 	}
 		    
@@ -476,7 +476,7 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	
 
-	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
 	       self->send_credit, self->avail_credit, self->remote_credit);
 	
 	/* Give credit to peer */
@@ -524,7 +524,7 @@
 {
 	struct tsap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct tsap_cb *) instance;
 
@@ -610,24 +610,24 @@
  */
 void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	switch (flow) {
 	case FLOW_STOP:
-		DEBUG(1, __FUNCTION__ "(), flow stop\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), flow stop\n");
 		self->rx_sdu_busy = TRUE;
 		break;
 	case FLOW_START:
-		DEBUG(1, __FUNCTION__ "(), flow start\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), flow start\n");
 		self->rx_sdu_busy = FALSE;
 		
 		irttp_run_rx_queue(self);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 	
@@ -646,7 +646,7 @@
 	__u8 *frame;
 	__u8 n;
 	
-	DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
+	IRDA_DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
 	
 	ASSERT(self != NULL, return -EBADR;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
@@ -738,7 +738,7 @@
 	__u8 plen;
 	__u8 n;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	self = (struct tsap_cb *) instance;
 
@@ -754,15 +754,15 @@
 	 *  negotiated QoS for the link.
 	 */
 	if (qos) {
-		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
+		IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
 		       qos->baud_rate.bits);			
-		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
+		IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
 		       qos->baud_rate.value);
 	}
 
 	n = skb->data[0] & 0x7f;
 	
-	DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
 	
 	self->send_credit = n;
 	self->tx_max_sdu_size = 0;
@@ -777,7 +777,7 @@
 		plen = skb->data[0];
 
 		ret = irda_param_extract_all(self, skb->data+1,
-					     MIN(skb->len-1, plen), 
+					     IRDA_MIN(skb->len-1, plen), 
 					     &param_info);
 
 		/* Any errors in the parameter list? */
@@ -790,13 +790,13 @@
 			return;
 		}
 		/* Remove parameters */
-		skb_pull(skb, MIN(skb->len, plen+1));
+		skb_pull(skb, IRDA_MIN(skb->len, plen+1));
 	}
 	
-	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
 	      self->send_credit, self->avail_credit, self->remote_credit);
 
-	DEBUG(2, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
 
 	if (self->notify.connect_confirm) {
 		self->notify.connect_confirm(self->notify.instance, self, qos,
@@ -833,7 +833,7 @@
 	self->max_seg_size = max_seg_size;
 	self->max_header_size = max_header_size+TTP_HEADER;
 
-	DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
+	IRDA_DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
 
 	/* Need to update dtsap_sel if its equal to LSAP_ANY */
 	self->dtsap_sel = lsap->dlsap_sel;
@@ -852,7 +852,7 @@
 		plen = skb->data[0];
 		
 		ret = irda_param_extract_all(self, skb->data+1,
-					     MIN(skb->len-1, plen), 
+					     IRDA_MIN(skb->len-1, plen), 
 					     &param_info);
 
 		/* Any errors in the parameter list? */
@@ -866,7 +866,7 @@
 		}
 
 		/* Remove parameters */
-		skb_pull(skb, MIN(skb->len, plen+1));
+		skb_pull(skb, IRDA_MIN(skb->len, plen+1));
 	}
 
 	if (self->notify.connect_indication) {
@@ -894,7 +894,7 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
-	DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
 	      self->stsap_sel);
 	
 	/* Any userdata supplied? */
@@ -972,15 +972,15 @@
 {
 	struct tsap_cb *new;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
-		DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
 		return NULL;
 	}
 	new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
 	if (!new) {
-		DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
 		return NULL;
 	}
 	/* Dup */
@@ -995,7 +995,7 @@
 	skb_queue_head_init(&new->tx_queue);
 	skb_queue_head_init(&new->rx_fragments);
 
-	hashbin_insert(irttp->tsaps, (QUEUE *) new, (int) new, NULL);
+	hashbin_insert(irttp->tsaps, (queue_t *) new, (int) new, NULL);
 
 	return new;
 }
@@ -1018,13 +1018,13 @@
 
 	/* Already disconnected? */
 	if (!self->connected) {
-		DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
 		return -1;
 	}
 
 	/* Disconnect already pending? */
 	if (self->disconnect_pend) {
-		DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
 		if (userdata) {
 			dev_kfree_skb(userdata);
 		}
@@ -1039,7 +1039,7 @@
 	 */
 	if (skb_queue_len(&self->tx_queue) > 0) {
 		if (priority == P_HIGH) {
-			DEBUG(1, __FUNCTION__  "High priority!!()\n" );
+			IRDA_DEBUG(1, __FUNCTION__  "High priority!!()\n" );
 			
 			/* 
 			 *  No need to send the queued data, if we are 
@@ -1065,7 +1065,7 @@
 			return -1;
 		}
 	}
-	DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
+	IRDA_DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
 
 	self->connected = FALSE;
 	
@@ -1097,7 +1097,7 @@
 {
 	struct tsap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct tsap_cb *) instance;
 	
@@ -1132,7 +1132,7 @@
 	 * give an error back 
 	 */
 	if (err == -ENOMEM) {
-		DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
 
 		/* Make sure we take a break */
 		self->rx_sdu_busy = TRUE;
@@ -1157,7 +1157,7 @@
 	struct sk_buff *skb;
 	int more = 0;
 
-	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
 	       self->send_credit, self->avail_credit, self->remote_credit);
 
 	if (irda_lock(&self->rx_queue_lock) == FALSE)
@@ -1197,7 +1197,7 @@
 			 *  limits of the maximum size of the rx_sdu
 			 */
 			if (self->rx_sdu_size <= self->rx_max_sdu_size) {
-				DEBUG(4, __FUNCTION__ "(), queueing frag\n");
+				IRDA_DEBUG(4, __FUNCTION__ "(), queueing frag\n");
 				skb_queue_tail(&self->rx_fragments, skb);
 			} else {
 				/* Free the part of the SDU that is too big */
@@ -1227,7 +1227,7 @@
 			/* Now we can deliver the reassembled skb */
 			irttp_do_data_indication(self, skb);
 		} else {
-			DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
 			
 			/* Free the part of the SDU that is too big */
 			dev_kfree_skb(skb);
@@ -1252,7 +1252,7 @@
 {
 	struct sk_buff* skb;
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1285,7 +1285,7 @@
       	ASSERT(self != NULL, return NULL;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
 
-	DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
+	IRDA_DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
 	      self->rx_sdu_size);
 
 	skb = dev_alloc_skb(self->rx_sdu_size);
@@ -1308,10 +1308,10 @@
 		
 		dev_kfree_skb(frag);
 	}
-	DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
+	IRDA_DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
 	/* Set the new length */
 
-	DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+	IRDA_DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
 	ASSERT(n <= self->rx_sdu_size, return NULL;);
 	skb_trim(skb, n);
 
@@ -1331,7 +1331,7 @@
 	struct sk_buff *frag;
 	__u8 *frame;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1346,7 +1346,7 @@
 		 *  queue what is left of the original skb
 		 */
 		if (skb->len < self->max_seg_size) {
-			DEBUG(4, __FUNCTION__ 
+			IRDA_DEBUG(4, __FUNCTION__ 
 			       "(), queuing last segment\n");
 
 			frame = skb_push(skb, TTP_HEADER);
@@ -1399,7 +1399,7 @@
 	else
 		self->tx_max_sdu_size = param->pv.i;
 
-	DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
+	IRDA_DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
 	
 	return 0;
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/parameters.c linux/net/irda/parameters.c
--- v2.3.23/linux/net/irda/parameters.c	Tue Aug 31 17:29:15 1999
+++ linux/net/irda/parameters.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Jun  7 10:25:11 1999
- * Modified at:   Wed Aug 25 13:31:32 1999
+ * Modified at:   Tue Oct  5 11:52:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -29,6 +29,7 @@
  ********************************************************************/
 
 #include <asm/unaligned.h>
+#include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/parameters.h>
@@ -148,13 +149,13 @@
 	 */
 	if (p.pl == 0) {
 		if (p.pv.i < 0xff) {
-			DEBUG(2, __FUNCTION__ "(), using 1 byte\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), using 1 byte\n");
 			p.pl = 1;
 		} else if (p.pv.i < 0xffff) {
-			DEBUG(2, __FUNCTION__ "(), using 2 bytes\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), using 2 bytes\n");
 			p.pl = 2;
 		} else {
-			DEBUG(2, __FUNCTION__ "(), using 4 bytes\n");
+			IRDA_DEBUG(2, __FUNCTION__ "(), using 4 bytes\n");
 			p.pl = 4; /* Default length */
 		}
 	}
@@ -163,7 +164,7 @@
 		WARNING(__FUNCTION__ "(), buffer to short for insertion!\n");
 		return -1;
 	}
-	DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d, pi=%d\n", p.pi, p.pl, p.pv.i);
+	IRDA_DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d, pi=%d\n", p.pi, p.pl, p.pv.i);
 	switch (p.pl) {
 	case 1:
 		n += irda_param_pack(buf, "bbb", p.pi, p.pl, p.pv.b);
@@ -275,12 +276,12 @@
 	param_t p;
 	int err;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	p.pi = pi;     /* In case handler needs to know */
 	p.pl = buf[1]; /* Extract lenght of value */
 
-	DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d\n", p.pi, p.pl);
+	IRDA_DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d\n", p.pi, p.pl);
 
 	/* Check if buffer is long enough for parsing */
 	if (len < (2+p.pl)) {
@@ -293,7 +294,7 @@
 	 * checked that the buffer is long enough */
 	strncpy(str, buf+2, p.pl);
 
-	DEBUG(2, __FUNCTION__ "(), str=0x%02x 0x%02x\n", (__u8) str[0], 
+	IRDA_DEBUG(2, __FUNCTION__ "(), str=0x%02x 0x%02x\n", (__u8) str[0], 
 	      (__u8) str[1]);
 	
 	/* Null terminate string */
@@ -330,7 +331,7 @@
 		return -1;
 	}
 
-	DEBUG(0, __FUNCTION__ "(), not impl\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), not impl\n");
 	
 	return p.pl+2; /* Extracted pl+2 bytes */
 }
@@ -454,7 +455,7 @@
 	if ((pi_major > info->len-1) || 
 	    (pi_minor > info->tables[pi_major].len-1))
 	{
-		DEBUG(0, __FUNCTION__ 
+		IRDA_DEBUG(0, __FUNCTION__ 
 		      "(), no handler for parameter=0x%02x\n", pi);
 		
 		/* Skip this parameter */
@@ -467,7 +468,7 @@
 	/* Find expected data type for this parameter identifier (pi)*/
 	type = pi_minor_info->type;
 
-	DEBUG(3, __FUNCTION__ "(), pi=[%d,%d], type=%d\n",
+	IRDA_DEBUG(3, __FUNCTION__ "(), pi=[%d,%d], type=%d\n",
 	      pi_major, pi_minor, type);
 		
 	/*  Check if handler has been implemented */
@@ -509,7 +510,7 @@
 	if ((pi_major > info->len-1) || 
 	    (pi_minor > info->tables[pi_major].len-1))
 	{
-		DEBUG(0, __FUNCTION__ "(), no handler for parameter=0x%02x\n",
+		IRDA_DEBUG(0, __FUNCTION__ "(), no handler for parameter=0x%02x\n",
 		      buf[0]);
 		
 		/* Skip this parameter */
@@ -525,7 +526,7 @@
 	/* Find expected data type for this parameter identifier (pi)*/
 	type = pi_minor_info->type;
 	
-	DEBUG(3, __FUNCTION__ "(), pi=[%d,%d], type=%d\n",
+	IRDA_DEBUG(3, __FUNCTION__ "(), pi=[%d,%d], type=%d\n",
 	      pi_major, pi_minor, type);
 	
 	/*  Check if handler has been implemented */
diff -u --recursive --new-file v2.3.23/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.3.23/linux/net/irda/qos.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/qos.c	Mon Oct 25 20:49:42 1999
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Wed Sep  1 09:14:55 1999
+ * Modified at:   Tue Oct  5 11:50:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -167,7 +167,7 @@
 	
 #ifdef CONFIG_IRDA_COMPRESSION
 	if (!comp_seen) {
-		DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
+		IRDA_DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
 		self->qos_tx.compression.bits = 0x00;
 		self->qos_rx.compression.bits = 0x00;
 	}
@@ -177,22 +177,22 @@
 	irda_qos_bits_to_value(&self->qos_tx);
 	irda_qos_bits_to_value(&self->qos_rx);
 		
-	DEBUG(2, "Setting BAUD_RATE to %d bps.\n", 
+	IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n", 
 	      self->qos_tx.baud_rate.value);
-	DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
+	IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
 	      self->qos_tx.data_size.value);
-	DEBUG(2, "Setting WINDOW_SIZE to %d\n", 
+	IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n", 
 	      self->qos_tx.window_size.value);
-	DEBUG(2, "Setting XBOFS to %d\n", 
+	IRDA_DEBUG(2, "Setting XBOFS to %d\n", 
 	      self->qos_tx.additional_bofs.value);
-	DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
+	IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
 	      self->qos_tx.max_turn_time.value);
-	DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
+	IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
 	      self->qos_tx.min_turn_time.value);
-	DEBUG(2, "Setting LINK_DISC to %d secs.\n", 
+	IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n", 
 	      self->qos_tx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
-	DEBUG(2, "Setting COMPRESSION to %d\n", 
+	IRDA_DEBUG(2, "Setting COMPRESSION to %d\n", 
 	      self->qos_tx.compression.value);
 #endif	
 	return ret;
@@ -278,16 +278,16 @@
 
 	if (get) {
 		param->pv.i = self->qos_rx.baud_rate.bits;
-		DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n", param->pv.i);		
+		IRDA_DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n", param->pv.i);		
 	} else {
 		/* 
 		 *  Stations must agree on baud rate, so calculate
 		 *  intersection 
 		 */
-		DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", param->pv.s);
+		IRDA_DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", param->pv.s);
 		final = param->pv.s & self->qos_rx.baud_rate.bits;
 
-		DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final);
+		IRDA_DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final);
 		self->qos_tx.baud_rate.bits = final;
 		self->qos_rx.baud_rate.bits = final;	       
 	}
@@ -317,10 +317,10 @@
 		 *  Stations must agree on link disconnect/threshold 
 		 *  time.
 		 */
-		DEBUG(2, "LINK_DISC: %02x\n", param->pv.b);
+		IRDA_DEBUG(2, "LINK_DISC: %02x\n", param->pv.b);
 		final = param->pv.b & self->qos_rx.link_disc_time.bits;
 
-		DEBUG(2, "Final LINK_DISC: %02x\n", final);
+		IRDA_DEBUG(2, "Final LINK_DISC: %02x\n", final);
 		self->qos_tx.link_disc_time.bits = final;
 		self->qos_rx.link_disc_time.bits = final;
 	}
@@ -435,7 +435,7 @@
 	return 0;
 }
 
-__u32 byte_value(__u8 byte, int *array) 
+__u32 byte_value(__u8 byte, __u32 *array) 
 {
 	int index;
 
@@ -472,7 +472,7 @@
  *
  *    Returns the index to the value in the specified array
  */
-int value_index(__u32 value, int *array) 
+int value_index(__u32 value, __u32 *array) 
 {
 	int i;
 	
@@ -488,7 +488,7 @@
  *    Returns value to index in array, easy!
  *
  */
-__u32 index_value(int index, int *array) 
+__u32 index_value(int index, __u32 *array) 
 {
 	return array[index];
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/timer.c linux/net/irda/timer.c
--- v2.3.23/linux/net/irda/timer.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/timer.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon Sep 20 11:32:37 1999
+ * Modified at:   Thu Oct  7 12:30:19 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -32,13 +32,13 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp_event.h>
 
-static void irlap_slot_timer_expired( void* data);
-static void irlap_query_timer_expired( void* data);
-static void irlap_final_timer_expired( void* data);
-static void irlap_wd_timer_expired( void* data);
-static void irlap_backoff_timer_expired( void* data);
+static void irlap_slot_timer_expired(void* data);
+static void irlap_query_timer_expired(void* data);
+static void irlap_final_timer_expired(void* data);
+static void irlap_wd_timer_expired(void* data);
+static void irlap_backoff_timer_expired(void* data);
 
-static void irda_device_media_busy_expired( void* data); 
+static void irlap_media_busy_expired(void* data); 
 /*
  * Function irda_start_timer (timer, timeout)
  *
@@ -63,57 +63,55 @@
 	add_timer(ptimer);
 }
 
-inline void irlap_start_slot_timer(struct irlap_cb *self, int timeout)
+void irlap_start_slot_timer(struct irlap_cb *self, int timeout)
 {
 	irda_start_timer(&self->slot_timer, timeout, (void *) self, 
 			 irlap_slot_timer_expired);
 }
 
-inline void irlap_start_query_timer(struct irlap_cb *self, int timeout)
+void irlap_start_query_timer(struct irlap_cb *self, int timeout)
 {
 	irda_start_timer( &self->query_timer, timeout, (void *) self, 
 			  irlap_query_timer_expired);
 }
 
-inline void irlap_start_final_timer(struct irlap_cb *self, int timeout)
+void irlap_start_final_timer(struct irlap_cb *self, int timeout)
 {
 	irda_start_timer(&self->final_timer, timeout, (void *) self, 
 			 irlap_final_timer_expired);
 }
 
-inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout)
+void irlap_start_wd_timer(struct irlap_cb *self, int timeout)
 {
 	irda_start_timer(&self->wd_timer, timeout, (void *) self, 
 			 irlap_wd_timer_expired);
 }
 
-inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout)
+void irlap_start_backoff_timer(struct irlap_cb *self, int timeout)
 {
 	irda_start_timer(&self->backoff_timer, timeout, (void *) self, 
 			 irlap_backoff_timer_expired);
 }
 
-inline void irda_device_start_mbusy_timer(struct irda_device *self) 
+void irlap_start_mbusy_timer(struct irlap_cb *self)
 {
 	irda_start_timer(&self->media_busy_timer, MEDIABUSY_TIMEOUT, 
-			 (void *) self, 
-			 irda_device_media_busy_expired);
-	
+			 (void *) self, irlap_media_busy_expired);
 }
 
-inline void irlmp_start_watchdog_timer(struct lsap_cb *self, int timeout) 
+void irlmp_start_watchdog_timer(struct lsap_cb *self, int timeout) 
 {
 	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
 			 irlmp_watchdog_timer_expired);
 }
 
-inline void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
+void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
 {
 	irda_start_timer(&self->discovery_timer, timeout, (void *) self,
 			 irlmp_discovery_timer_expired);
 }
 
-inline void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
+void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
 {
 	irda_start_timer(&self->idle_timer, timeout, (void *) self,
 			 irlmp_idle_timer_expired);
@@ -205,12 +203,11 @@
  *
  *    
  */
-void irda_device_media_busy_expired(void* data)
+void irlap_media_busy_expired(void* data)
 {
-	struct irda_device *self = (struct irda_device *) data;
+	struct irlap_cb *self = (struct irlap_cb *) data;
 
 	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
 
-	irda_device_set_media_busy(&self->netdev, FALSE);
+	irda_device_set_media_busy(self->netdev, FALSE);
 }
diff -u --recursive --new-file v2.3.23/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.3.23/linux/net/irda/wrapper.c	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/wrapper.c	Mon Oct 25 20:49:42 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon Sep 20 11:18:44 1999
+ * Modified at:   Mon Oct 18 15:51:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Fri May 28  3:11 CST 1999
  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
@@ -39,12 +39,17 @@
 
 static inline int stuff_byte(__u8 byte, __u8 *buf);
 
-static void state_outside_frame(struct irda_device *idev, __u8 byte);
-static void state_begin_frame(struct irda_device *idev, __u8 byte);
-static void state_link_escape(struct irda_device *idev, __u8 byte);
-static void state_inside_frame(struct irda_device *idev, __u8 byte);
+static int state_outside_frame(struct net_device *dev, 
+			       struct iobuff_t *rx_buff, __u8 byte);
+static int state_begin_frame(struct net_device *dev, 
+			     struct iobuff_t *rx_buff, __u8 byte);
+static int state_link_escape(struct net_device *dev, 
+			     struct iobuff_t *rx_buff, __u8 byte);
+static int state_inside_frame(struct net_device *dev, 
+			      struct iobuff_t *rx_buff, __u8 byte);
 
-static void (*state[])(struct irda_device *idev, __u8 byte) = 
+static int (*state[])(struct net_device *dev, struct iobuff_t *rx_buff, 
+		      __u8 byte) = 
 { 
 	state_outside_frame,
 	state_begin_frame,
@@ -60,9 +65,9 @@
  */
 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
 {
+	int xbofs;
  	int i;
 	int n;
-	int xbofs;
 	union {
 		__u16 value;
 		__u8 bytes[2];
@@ -77,7 +82,7 @@
 	 *  additional XBOFS
 	 */
 	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
-		DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
 		xbofs = 10;
 	} else
 		xbofs = ((struct irda_skb_cb *)(skb->cb))->xbofs;
@@ -116,40 +121,6 @@
 }
 
 /*
- * Function async_bump (idev, buf, len)
- *
- *    Got a frame, make a copy of it, and pass it up the stack!
- *
- */
-static inline void async_bump(struct irda_device *idev, __u8 *buf, int len)
-{
-       	struct sk_buff *skb;
-
-	skb = dev_alloc_skb(len+1);
-	if (!skb)  {
-		idev->stats.rx_dropped++;
-		return;
-	}
-
-	/*  Align IP header to 20 bytes */
-	skb_reserve(skb, 1);
-	
-        /* Copy data without CRC */
-	memcpy(skb_put(skb, len-2), buf, len-2); 
-	
-	/* 
-	 *  Feed it to IrLAP layer 
-	 */
-	skb->dev = &idev->netdev;
-	skb->mac.raw  = skb->data;
-	skb->protocol = htons(ETH_P_IRDA);
-
-	netif_rx(skb);
-	idev->stats.rx_packets++;
-	idev->stats.rx_bytes += skb->len;	
-}
-
-/*
  * Function stuff_byte (byte, buf)
  *
  *    Byte stuff one single byte and put the result in buffer pointed to by
@@ -176,38 +147,77 @@
 }
 
 /*
- * Function async_unwrap_char (idev, byte)
+ * Function async_bump (buf, len, stats)
+ *
+ *    Got a frame, make a copy of it, and pass it up the stack!
+ *
+ */
+int async_bump(struct net_device *dev, __u8 *buf, int len)
+{
+	struct net_device_stats *stats = dev->get_stats(dev);
+       	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(len+1);
+	if (!skb)  {
+		stats->rx_dropped++;
+		return -ENOMEM;
+	}
+
+	/*  Align IP header to 20 bytes */
+	skb_reserve(skb, 1);
+	
+        /* Copy data without CRC */
+	memcpy(skb_put(skb, len-2), buf, len-2); 
+	
+	/* Feed it to IrLAP layer */
+	skb->dev = dev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = htons(ETH_P_IRDA);
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += len;
+	
+	return skb->len;
+}
+
+/*
+ * Function async_unwrap_char (dev, rx_buff, byte)
  *
  *    Parse and de-stuff frame received from the IrDA-port
  *
  */
-inline void async_unwrap_char(struct irda_device *idev, __u8 byte)
+inline int async_unwrap_char(struct net_device *dev, struct iobuff_t *rx_buff,
+			     __u8 byte)
 {
-	(*state[idev->rx_buff.state]) (idev, byte);
+	return (*state[rx_buff->state])(dev, rx_buff, byte);
 }
 	 
 /*
- * Function state_outside_frame (idev, byte)
+ * Function state_outside_frame (dev, rx_buff, byte)
  *
  *    
  *
  */
-static void state_outside_frame(struct irda_device *idev, __u8 byte)
+static int state_outside_frame(struct net_device *dev, 
+			       struct iobuff_t *rx_buff, __u8 byte)
 {
 	switch (byte) {
 	case BOF:
-		idev->rx_buff.state = BEGIN_FRAME;
-		idev->rx_buff.in_frame = TRUE;
+		rx_buff->state = BEGIN_FRAME;
+		rx_buff->in_frame = TRUE;
 		break;
 	case XBOF:
 		/* idev->xbofs++; */
 		break;
 	case EOF:
-		irda_device_set_media_busy(&idev->netdev, TRUE);
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	default:
 		break;
 	}
+	return 0;
 }
 
 /*
@@ -216,38 +226,39 @@
  *    Begin of frame detected
  *
  */
-static void state_begin_frame(struct irda_device *idev, __u8 byte)
+static int state_begin_frame(struct net_device *dev, 
+			     struct iobuff_t *rx_buff, __u8 byte)
 {
+	struct net_device_stats *stats = dev->get_stats(dev);
+
+	/* Time to initialize receive buffer */
+	rx_buff->data = rx_buff->head;
+	rx_buff->len = 0;
+	rx_buff->fcs = INIT_FCS;
+
 	switch (byte) {
 	case BOF:
 		/* Continue */
 		break;
 	case CE:
 		/* Stuffed byte */
-		idev->rx_buff.state = LINK_ESCAPE;
-
-		/* Time to initialize receive buffer */
-		idev->rx_buff.data = idev->rx_buff.head;
-		idev->rx_buff.len = 0;
+		rx_buff->state = LINK_ESCAPE;
 		break;
 	case EOF:
 		/* Abort frame */
-		idev->rx_buff.state = OUTSIDE_FRAME;
-		
-		idev->stats.rx_errors++;
-		idev->stats.rx_frame_errors++;
-		break;
-	default:	
-		/* Time to initialize receive buffer */
-		idev->rx_buff.data = idev->rx_buff.head;
-		idev->rx_buff.len = 0;
+		rx_buff->state = OUTSIDE_FRAME;
 
-		idev->rx_buff.data[idev->rx_buff.len++] = byte;
+		stats->rx_errors++;
+		stats->rx_frame_errors++;
+		break;
+	default:
+		rx_buff->data[rx_buff->len++] = byte;
 		
-		idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte);
-		idev->rx_buff.state = INSIDE_FRAME;
+		rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
+		rx_buff->state = INSIDE_FRAME;
 		break;
 	}
+	return 0;
 }
 
 /*
@@ -256,18 +267,19 @@
  *    
  *
  */
-static void state_link_escape(struct irda_device *idev, __u8 byte)
+static int state_link_escape(struct net_device *dev, 
+			     struct iobuff_t *rx_buff, __u8 byte)
 {
 	switch (byte) {
 	case BOF: /* New frame? */
-		idev->rx_buff.state = BEGIN_FRAME;
-		irda_device_set_media_busy(&idev->netdev, TRUE);
+		rx_buff->state = BEGIN_FRAME;
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	case CE:
-		DEBUG(4, "WARNING: State not defined\n");
+		IRDA_DEBUG(4, "WARNING: State not defined\n");
 		break;
 	case EOF: /* Abort frame */
-		idev->rx_buff.state = OUTSIDE_FRAME;
+		rx_buff->state = OUTSIDE_FRAME;
 		break;
 	default:
 		/* 
@@ -275,17 +287,18 @@
 		 *  following CE, IrLAP p.114 
 		 */
 		byte ^= IRDA_TRANS;
-		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
-			idev->rx_buff.data[idev->rx_buff.len++] = byte;
-			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
-			idev->rx_buff.state = INSIDE_FRAME;
+		if (rx_buff->len < rx_buff->truesize)  {
+			rx_buff->data[rx_buff->len++] = byte;
+			rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
+			rx_buff->state = INSIDE_FRAME;
 		} else {
-			DEBUG(1, __FUNCTION__ 
+			IRDA_DEBUG(1, __FUNCTION__ 
 			      "(), Rx buffer overflow, aborting\n");
-			idev->rx_buff.state = OUTSIDE_FRAME;
+			rx_buff->state = OUTSIDE_FRAME;
 		}
 		break;
 	}
+	return 0;
 }
 
 /*
@@ -294,43 +307,50 @@
  *    Handle bytes received within a frame
  *
  */
-static void state_inside_frame(struct irda_device *idev, __u8 byte)
+static int state_inside_frame(struct net_device *dev, 
+			      struct iobuff_t *rx_buff, __u8 byte)
 {
+	struct net_device_stats *stats = dev->get_stats(dev);
+	int ret = 0; 
+
 	switch (byte) {
 	case BOF: /* New frame? */
-		idev->rx_buff.state = BEGIN_FRAME;
-		irda_device_set_media_busy(&idev->netdev, TRUE);
+		rx_buff->state = BEGIN_FRAME;
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	case CE: /* Stuffed char */
-		idev->rx_buff.state = LINK_ESCAPE;
+		rx_buff->state = LINK_ESCAPE;
 		break;
 	case EOF: /* End of frame */
-		idev->rx_buff.state = OUTSIDE_FRAME;
-		idev->rx_buff.in_frame = FALSE;
+		rx_buff->state = OUTSIDE_FRAME;
+		rx_buff->in_frame = FALSE;
 		
-		/* Test FCS and deliver frame if it's good */
-		if (idev->rx_buff.fcs == GOOD_FCS) {
-			async_bump(idev, idev->rx_buff.data, 
-				   idev->rx_buff.len);
+		/* Test FCS and signal success if the frame is good */
+		if (rx_buff->fcs == GOOD_FCS) {
+			/* Deliver frame */
+			async_bump(dev, rx_buff->data, rx_buff->len);
+			ret = TRUE;
+			break;
 		} else {
 			/* Wrong CRC, discard frame!  */
-			irda_device_set_media_busy(&idev->netdev, TRUE); 
-			
-			idev->stats.rx_errors++;
-			idev->stats.rx_crc_errors++;
+			irda_device_set_media_busy(dev, TRUE); 
+
+			stats->rx_errors++;
+			stats->rx_crc_errors++;
 		}			
 		break;
 	default: /* Must be the next byte of the frame */
-		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
-			idev->rx_buff.data[idev->rx_buff.len++] = byte;
-			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
+		if (rx_buff->len < rx_buff->truesize)  {
+			rx_buff->data[rx_buff->len++] = byte;
+			rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
 		} else {
-			DEBUG(1, __FUNCTION__ 
+			IRDA_DEBUG(1, __FUNCTION__ 
 			      "(), Rx buffer overflow, aborting\n");
-			idev->rx_buff.state = OUTSIDE_FRAME;
+			rx_buff->state = OUTSIDE_FRAME;
 		}
 		break;
 	}
+	return 0;
 }
 
 
