## Automatically generated incremental diff
## From:   linux-2.2.3-pre2
## To:     linux-2.2.3-pre3
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.2.3-pre2/arch/i386/defconfig linux-2.2.3-pre3/arch/i386/defconfig
--- linux-2.2.3-pre2/arch/i386/defconfig	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/arch/i386/defconfig	2003-08-15 15:05:26.000000000 -0700
@@ -120,7 +120,6 @@
 # (it is safe to leave these untouched)
 #
 # CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
 
 #
@@ -283,6 +282,7 @@
 # Joystick support
 #
 # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
 
 #
 # Ftape, the floppy tape device driver
diff -urN linux-2.2.3-pre2/arch/i386/kernel/bios32.c linux-2.2.3-pre3/arch/i386/kernel/bios32.c
--- linux-2.2.3-pre2/arch/i386/kernel/bios32.c	1999-01-20 10:18:53.000000000 -0800
+++ linux-2.2.3-pre3/arch/i386/kernel/bios32.c	2003-08-15 15:05:26.000000000 -0700
@@ -14,7 +14,7 @@
  *	Hannover, Germany
  *	hm@ix.de
  *
- * Copyright 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  * For more information, please consult the following manuals (look at
  * http://www.pcisig.com/ for how to get them):
@@ -71,6 +71,10 @@
  *	a large gallery of common hardware bug workarounds (watch the comments)
  *	-- the PCI specs themselves are sane, but most implementors should be
  *	hit hard with \hammer scaled \magstep5. [mj]
+ *
+ * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
+ *
+ * Feb 8,  1999 : Added UM8886BF I/O address fixup. [mj]
  */
 
 #include <linux/config.h>
@@ -171,6 +175,7 @@
 #define PCI_NO_SORT 0x100
 #define PCI_BIOS_SORT 0x200
 #define PCI_NO_CHECKS 0x400
+#define PCI_NO_PEER_FIXUP 0x800
 
 static unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
 
@@ -521,6 +526,8 @@
 	unsigned short segment;
 } pci_indirect = { 0, __KERNEL_CS };
 
+static int pci_bios_present;
+
 __initfunc(static int check_pcibios(void))
 {
 	u32 signature, eax, ebx, ecx;
@@ -803,7 +810,7 @@
  * which used BIOS ordering, we are bound to do this...
  */
 
-__initfunc(void pcibios_sort(void))
+static void __init pcibios_sort(void)
 {
 	struct pci_dev *dev = pci_devices;
 	struct pci_dev **last = &pci_devices;
@@ -856,7 +863,7 @@
 
 static int pci_last_io_addr __initdata = 0x5800;
 
-__initfunc(void pcibios_fixup_io_addr(struct pci_dev *dev, int idx))
+static void __init pcibios_fixup_io_addr(struct pci_dev *dev, int idx)
 {
 	unsigned short cmd;
 	unsigned int reg = PCI_BASE_ADDRESS_0 + 4*idx;
@@ -868,13 +875,16 @@
 		printk("PCI: Unassigned I/O space for %02x:%02x\n", bus, devfn);
 		return;
 	}
-	if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4) {
+	if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4 ||
+	    (dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
 		/*
 		 * In case the BIOS didn't assign an address 0--3 to an IDE
 		 * controller, we don't try to fix it as it means "use default
 		 * addresses" at least with several broken chips and the IDE
 		 * driver needs the original settings to recognize which devices
 		 * correspond to the primary controller.
+		 *
+		 * We don't assign VGA I/O ranges as well.
 		 */
 		return;
 	}
@@ -914,7 +924,7 @@
  * expected to be unique) and remove the ghost devices.
  */
 
-__initfunc(void pcibios_fixup_ghosts(struct pci_bus *b))
+static void __init pcibios_fixup_ghosts(struct pci_bus *b)
 {
 	struct pci_dev *d, *e, **z;
 	int mirror = PCI_DEVFN(16,0);
@@ -954,12 +964,17 @@
  * the reality doesn't pass this test and the bus number is usually
  * set by BIOS to the first free value.
  */
-__initfunc(void pcibios_fixup_peer_bridges(void))
+static void __init pcibios_fixup_peer_bridges(void)
 {
 	struct pci_bus *b = &pci_root;
 	int i, n, cnt=-1;
 	struct pci_dev *d;
 
+#ifdef CONFIG_VISWS
+	pci_scan_peer_bridge(1);
+	return;
+#endif
+
 #ifdef CONFIG_PCI_DIRECT
 	/*
 	 * Don't search for peer host bridges if we use config type 2
@@ -969,6 +984,7 @@
 	if (access_pci == &pci_direct_conf2)
 		return;
 #endif
+
 	for(d=b->devices; d; d=d->sibling)
 		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
 			cnt++;
@@ -979,6 +995,20 @@
 		for(i=0; i<256; i += 8)
 			if (!pcibios_read_config_word(n, i, PCI_VENDOR_ID, &l) &&
 			    l != 0x0000 && l != 0xffff) {
+#ifdef CONFIG_PCI_BIOS
+				if (pci_bios_present) {
+					int succ, idx = 0;
+					u8 bios_bus, bios_dfn;
+					u16 d;
+					pcibios_read_config_word(n, i, PCI_DEVICE_ID, &d);
+					DBG("BIOS test for %02x:%02x (%04x:%04x)\n", n, i, l, d);
+					while ((succ = pci_bios_find_device(l, d, idx, &bios_bus, &bios_dfn)) &&
+					       (bios_bus != n || bios_dfn != i))
+						idx++;
+					if (!succ)
+						break;
+				}
+#endif
 				DBG("Found device at %02x:%02x\n", n, i);
 				found++;
 				if (!pcibios_read_config_word(n, i, PCI_CLASS_DEVICE, &l) &&
@@ -989,13 +1019,7 @@
 			break;
 		if (found) {
 			printk("PCI: Discovered primary peer bus %02x\n", n);
-			b = kmalloc(sizeof(*b), GFP_KERNEL);
-			memset(b, 0, sizeof(*b));
-			b->next = pci_root.next;
-			pci_root.next = b;
-			b->number = b->secondary = n;
-			b->subordinate = 0xff;
-			b->subordinate = pci_scan_bus(b);
+			b = pci_scan_peer_bridge(n);
 			n = b->subordinate;
 		}
 		n++;
@@ -1003,11 +1027,75 @@
 }
 
 /*
+ * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
+ */
+
+static void __init pci_fixup_i450nx(struct pci_dev *d)
+{
+	/*
+	 * i450NX -- Find and scan all secondary buses on all PXB's.
+	 */
+	int pxb, reg;
+	u8 busno, suba, subb;
+	reg = 0xd0;
+	for(pxb=0; pxb<2; pxb++) {
+		pci_read_config_byte(d, reg++, &busno);
+		pci_read_config_byte(d, reg++, &suba);
+		pci_read_config_byte(d, reg++, &subb);
+		DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
+		if (busno)
+			pci_scan_peer_bridge(busno);	/* Bus A */
+		if (suba < subb)
+			pci_scan_peer_bridge(suba+1);	/* Bus B */
+	}
+	pci_probe |= PCI_NO_PEER_FIXUP;
+}
+
+static void __init pci_fixup_umc_ide(struct pci_dev *d)
+{
+	/*
+	 * UM8886BF IDE controller sets region type bits incorrectly,
+	 * therefore they look like memory despite of them being I/O.
+	 */
+	int i;
+
+	for(i=0; i<4; i++)
+		d->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+}
+
+struct dev_ex {
+	u16 vendor, device;
+	void (*handler)(struct pci_dev *);
+	char *comment;
+};
+
+static struct dev_ex __initdata dev_ex_table[] = {
+ { PCI_VENDOR_ID_INTEL,		PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx, 	"Scanning peer host bridges" },
+ { PCI_VENDOR_ID_UMC,		PCI_DEVICE_ID_UMC_UM8886BF,	pci_fixup_umc_ide,	"Working around UM8886BF bugs" }
+};
+
+static void __init pcibios_scan_buglist(struct pci_bus *b)
+{
+	struct pci_dev *d;
+	int i;
+
+	for(d=b->devices; d; d=d->sibling)
+		for(i=0; i<sizeof(dev_ex_table)/sizeof(dev_ex_table[0]); i++) {
+			struct dev_ex *e = &dev_ex_table[i];
+			if (e->vendor == d->vendor && e->device == d->device) {
+				printk("PCI: %02x:%02x [%04x/%04x]: %s\n",
+					b->number, d->devfn, d->vendor, d->device, e->comment);
+				e->handler(d);
+			}
+		}
+}
+
+/*
  * Fix base addresses, I/O and memory enables and IRQ's (mostly work-arounds
  * for buggy PCI BIOS'es :-[).
  */
 
-__initfunc(void pcibios_fixup_devices(void))
+static void __init pcibios_fixup_devices(void)
 {
 	struct pci_dev *dev;
 	int i, has_io, has_mem;
@@ -1099,7 +1187,8 @@
 
 __initfunc(void pcibios_fixup(void))
 {
-	pcibios_fixup_peer_bridges();
+	if (!(pci_probe & PCI_NO_PEER_FIXUP))
+		pcibios_fixup_peer_bridges();
 	pcibios_fixup_devices();
 
 #ifdef CONFIG_PCI_BIOS
@@ -1111,6 +1200,7 @@
 __initfunc(void pcibios_fixup_bus(struct pci_bus *b))
 {
 	pcibios_fixup_ghosts(b);
+	pcibios_scan_buglist(b);
 }
 
 /*
@@ -1126,8 +1216,10 @@
 	struct pci_access *dir = NULL;
 
 #ifdef CONFIG_PCI_BIOS
-	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios())))
+	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
 		pci_probe |= PCI_BIOS_SORT;
+		pci_bios_present = 1;
+	}
 #endif
 #ifdef CONFIG_PCI_DIRECT
 	if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
@@ -1139,10 +1231,6 @@
 		access_pci = bios;
 }
 
-#if !defined(CONFIG_PCI_BIOS) && !defined(CONFIG_PCI_DIRECT)
-#error PCI configured with neither PCI BIOS or PCI direct access support.
-#endif
-
 __initfunc(char *pcibios_setup(char *str))
 {
 	if (!strcmp(str, "off")) {
@@ -1178,5 +1266,9 @@
 		return NULL;
 	}
 #endif
+	else if (!strcmp(str, "nopeer")) {
+		pci_probe |= PCI_NO_PEER_FIXUP;
+		return NULL;
+	}
 	return str;
 }
diff -urN linux-2.2.3-pre2/CREDITS linux-2.2.3-pre3/CREDITS
--- linux-2.2.3-pre2/CREDITS	1999-02-06 12:46:20.000000000 -0800
+++ linux-2.2.3-pre3/CREDITS	2003-08-15 15:05:26.000000000 -0700
@@ -1061,6 +1061,14 @@
 S: L3R 8B2
 S: Canada
 
+N: Russell Kroll
+E: rkroll@exploits.org
+W: http://www.exploits.org/
+D: V4L Aztech radio card driver, mods to Aimslab driver
+S: Post Office Box 49458
+S: Colorado Springs, Colorado 80949-9458
+S: USA
+
 N: Gero Kuhlmann
 E: gero@gkminix.han.de
 D: mounting root via NFS
@@ -2004,6 +2012,14 @@
 S: 10200 Prague 10, Hostivar
 S: Czech Republic
 
+N: James R. Van Zandt
+E: jrv@vanzandt.mv.com
+P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
+D: Author and maintainer of the Double Talk speech synthesizer driver
+S: 27 Spencer Drive
+S: Nashua, New Hampshire 03062
+S: USA
+
 N: Andrew Veliath
 E: andrewtv@usa.net
 D: Turtle Beach MultiSound sound driver
diff -urN linux-2.2.3-pre2/Documentation/Configure.help linux-2.2.3-pre3/Documentation/Configure.help
--- linux-2.2.3-pre2/Documentation/Configure.help	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/Documentation/Configure.help	2003-08-15 15:05:26.000000000 -0700
@@ -8466,6 +8466,15 @@
   This driver does not exist at this point, so you might as well 
   say N.
 
+Double Talk PC internal speech card support
+CONFIG_DTLK
+  This driver is for the DoubleTalk PC, a speech synthesizer
+  manufactured by RC Systems (http://www.rcsys.com/).  It is also
+  called the `internal DoubleTalk'.  If you want to compile this as a
+  module ( = code which can be inserted in and removed from the
+  running kernel whenever you want), say M here and read
+  Documentation/modules.txt. The module will be called dtlk.o.
+
 Advanced Power Management
 CONFIG_APM
   APM is a BIOS specification for saving power using several different
diff -urN linux-2.2.3-pre2/Documentation/sound/CMI8330 linux-2.2.3-pre3/Documentation/sound/CMI8330
--- linux-2.2.3-pre2/Documentation/sound/CMI8330	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/Documentation/sound/CMI8330	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,86 @@
+How to enable CMI 8330 soundchip on Linux
+------------------------------------------
+Stefan Laudat <Stefan.Laudat@asit.ro>
+
+Hello folks, 
+	
+	The CMI8330 soundchip is a very small chip found on many recent 
+	motherboards. In order to use it you just have to use a proper 
+        isapnp.conf and a little bit of patience. 
+	
+	Of course you will have to compile kernel sound support as module, 
+        as shown below:
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_ADLIB=m
+CONFIG_SOUND_MPU401=m
+# Just for fun :)
+CONFIG_SOUND_MSS=m
+
+	The /etc/isapnp.conf file will be:
+
+<snip below>
+
+(READPORT 0x0203)
+(ISOLATE PRESERVE)
+(IDENTIFY *)
+(VERBOSITY 2)
+(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
+(VERIFYLD N)
+# WSS 
+
+(CONFIGURE CMI0001/16777472 (LD 0
+(IO 0 (SIZE 8) (BASE 0x0530))
+(IO 1 (SIZE 8) (BASE 0x0388))
+(INT 0 (IRQ 5 (MODE +E)))
+(DMA 0 (CHANNEL 0))
+(NAME "CMI0001/16777472[0]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Control device ? 
+
+(CONFIGURE CMI0001/16777472 (LD 1
+(IO 0 (SIZE 2) (BASE 0x0330))
+(INT 0 (IRQ 11 (MODE +E)))
+(NAME "CMI0001/16777472[1]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Joystick
+
+(CONFIGURE CMI0001/16777472 (LD 2
+(IO 0 (SIZE 8) (BASE 0x0200))
+(NAME "CMI0001/16777472[2]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+#  SB... 
+(CONFIGURE CMI0001/16777472 (LD 3
+(IO 0 (SIZE 16) (BASE 0x0220))
+(INT 0 (IRQ 7 (MODE +E)))
+(DMA 0 (CHANNEL 1))
+(DMA 1 (CHANNEL 5))
+(NAME "CMI0001/16777472[3]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+
+(WAITFORKEY)
+
+<end of snip>
+
+	The module sequence is trivial:
+
+/sbin/modprobe sound
+# You need to load the ad1848 module first. That matters, otherwise the 
+# chip falls into soundblaster compatibility and you won't get it back out
+/sbin/insmod ad1848 io=0x530 dma=0 irq=5 soundpro=1
+/sbin/insmod uart401
+/sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1
+/sbin/insmod mpu401 io=0x330
+/sbin/insmod opl3 io=0x388
+
+	The soundchip is now fully initialized. Enjoy it.
diff -urN linux-2.2.3-pre2/Documentation/sound/VIBRA16 linux-2.2.3-pre3/Documentation/sound/VIBRA16
--- linux-2.2.3-pre2/Documentation/sound/VIBRA16	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/Documentation/sound/VIBRA16	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,80 @@
+Sound Blaster 16X Vibra addendum
+--------------------------------
+by Marius Ilioaea <mariusi@protv.ro>
+   Stefan Laudat  <stefan@asit.ro>
+
+Sat Mar 6 23:55:27 EET 1999
+
+			Hello again,
+	
+	Playing with a SB Vibra 16x soundcard we found it very difficult
+to setup because the kernel reported a lot of DMA errors and wouldn't
+simply play any sound.
+	A good starting point is that the vibra16x chip full-duplex facility
+is neither still exploited by the sb driver found in the linux kernel 
+(tried it with a 2.2.2-ac7), nor in the commercial OSS package (it reports
+it as half-duplex soundcard). Oh, I almost forgot, the RedHat sndconfig
+failed detecting it ;)
+	So, the big problem still remains, because the sb module wants a
+8-bit and a 16-bit dma, which we could not allocate for vibra... it supports
+only two 8-bit dma channels, the second one will be passed to the module
+as a 16 bit channel, the kernel will yield about that but everything will
+be okay, trust us. 
+	The only inconvenient you may find is that you will have
+some sound playing jitters if you have HDD dma support enabled - but this
+will happen with almost all soundcards...
+
+	A fully working isapnp.conf is just here:
+
+<snip here>
+
+(READPORT 0x0203)
+(ISOLATE PRESERVE)
+(IDENTIFY *)
+(VERBOSITY 2)
+(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
+# SB 16 and OPL3 devices
+(CONFIGURE CTL00f0/-1 (LD 0
+(INT 0 (IRQ 5 (MODE +E)))
+(DMA 0 (CHANNEL 1))
+(DMA 1 (CHANNEL 3))
+(IO 0 (SIZE 16) (BASE 0x0220))
+(IO 2 (SIZE 4) (BASE 0x0388))
+(NAME "CTL00f0/-1[0]{Audio               }")
+(ACT Y)
+))
+
+# Joystick device - only if you need it :-/
+
+(CONFIGURE CTL00f0/-1 (LD 1
+(IO 0 (SIZE 1) (BASE 0x0200))
+(NAME "CTL00f0/-1[1]{Game                }")
+(ACT Y)
+))
+(WAITFORKEY)
+
+<end of snipping>
+
+	So, after a good kernel modules compilation and a 'depmod -a kernel_ver'
+you may want to:
+
+modprobe sb io=0x220 irq=5 dma=1 dma16=3
+
+	Or, take the hard way:
+
+insmod souncore
+insmod sound
+insmod uart401
+insmod sb io=0x220 irq=5 dma=1 dma16=3
+# do you need MIDI?
+insmod opl3=0x388
+
+	Just in case, the kernel sound support should be:
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_SB=m
+	
+	Enjoy your new noisy Linux box! ;)
+	
+
diff -urN linux-2.2.3-pre2/drivers/char/Config.in linux-2.2.3-pre3/drivers/char/Config.in
--- linux-2.2.3-pre2/drivers/char/Config.in	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/drivers/char/Config.in	2003-08-15 15:05:26.000000000 -0700
@@ -166,6 +166,8 @@
 fi
 endmenu
 
+tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
+
 mainmenu_option next_comment
 comment 'Ftape, the floppy tape device driver'
 tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE
diff -urN linux-2.2.3-pre2/drivers/char/dtlk.c linux-2.2.3-pre3/drivers/char/dtlk.c
--- linux-2.2.3-pre2/drivers/char/dtlk.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/char/dtlk.c	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,722 @@
+/*                                              -*- linux-c -*-
+ * dtlk.c - DoubleTalk PC driver for Linux kernel 2.0.29
+ * 
+ * $Id: dtlk.c,v 1.19 1999/02/28 12:13:13 jrv Exp jrv $
+ *
+ * Original author: Chris Pallotta <chris@allmedia.com>
+ * Current maintainer: Jim Van Zandt <jrv@vanzandt.mv.com>
+ */
+
+/* This driver is for the DoubleTalk PC, a speech synthesizer
+   manufactured by RC Systems (http://www.rcsys.com/).  It was written
+   based on documentation in their User's Manual file and Developer's
+   Tools disk.
+
+   The DoubleTalk PC contains four voice synthesizers: text-to-speech
+   (TTS), linear predictive coding (LPC), PCM/ADPCM, and CVSD.  It
+   also has a tone generator.  Output data for LPC are written to the
+   LPC port, and output data for the other modes are written to the
+   TTS port.
+
+   Two kinds of data can be read from the DoubleTalk: status
+   information (in response to the "\001?" interrogation command) is
+   read from the TTS port, and index markers (which mark the progress
+   of the speech) are read from the LPC port.  Not all models of the
+   DoubleTalk PC implement index markers.  Both the TTS and LPC ports
+   can also display status flags.
+
+   The DoubleTalk PC generates no interrupts.
+
+   These characteristics are mapped into the Unix stream I/O model as
+   follows:
+
+   "write" sends bytes to the TTS port.  It is the responsibility of
+   the user program to switch modes among TTS, PCM/ADPCM, and CVSD.
+   This driver was written for use with the text-to-speech
+   synthesizer.  If LPC output is needed some day, other minor device
+   numbers can be used to select among output modes.
+
+   "read" gets index markers from the LPC port.  If the device does
+   not implement index markers, the read will fail with error EINVAL.
+
+   Status information is available using the DTLK_INTERROGATE ioctl.
+
+ */
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#define KERNEL
+#include <linux/config.h>
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>		/* for verify_area */
+#include <linux/errno.h>	/* for -EBUSY */
+#include <linux/ioport.h>	/* for check_region, request_region */
+#include <linux/delay.h>	/* for loops_per_sec */
+#include <asm/segment.h>	/* for put_user_byte */
+#include <asm/io.h>		/* for inb_p, outb_p, inb, outb, etc. */
+#include <asm/uaccess.h>	/* for get_user, etc. */
+#include <linux/wait.h>		/* for wait_queue */
+#include <linux/init.h>		/* for __init */
+#include <linux/poll.h>		/* for POLLIN, etc. */
+#include <linux/dtlk.h>		/* local header file for DoubleTalk values */
+
+#ifdef TRACING
+#define TRACE_TEXT(str) printk(str);
+#define TRACE_RET printk(")")
+#else				/* !TRACING */
+#define TRACE_TEXT(str) ((void) 0)
+#define TRACE_RET ((void) 0)
+#endif				/* TRACING */
+
+
+static int dtlk_major;
+static int dtlk_port_lpc;
+static int dtlk_port_tts;
+static int dtlk_busy;
+static int dtlk_timer_active;
+static int dtlk_has_indexing;
+static unsigned int dtlk_portlist[] =
+{0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0};
+static struct wait_queue *dtlk_process_list = NULL;
+static struct timer_list dtlk_timer;
+
+/* prototypes for file_operations struct */
+static ssize_t dtlk_read(struct file *, char *,
+			 size_t nbytes, loff_t * ppos);
+static ssize_t dtlk_write(struct file *, const char *,
+			  size_t nbytes, loff_t * ppos);
+static unsigned int dtlk_poll(struct file *, poll_table *);
+static int dtlk_open(struct inode *, struct file *);
+static int dtlk_release(struct inode *, struct file *);
+static int dtlk_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg);
+
+static struct file_operations dtlk_fops =
+{
+	NULL,			/* lseek */
+	dtlk_read,
+	dtlk_write,
+	NULL,			/* readdir */
+	dtlk_poll,
+	dtlk_ioctl,
+	NULL,			/* mmap */
+	dtlk_open,
+	NULL,			/* flush */
+	dtlk_release,
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL,			/* revalidate */
+	NULL			/* lock */
+};
+
+/* local prototypes */
+static void dtlk_delay(int ms);
+static int dtlk_dev_probe(void);
+static struct dtlk_settings *dtlk_interrogate(void);
+static int dtlk_readable(void);
+static char dtlk_read_lpc(void);
+static char dtlk_read_tts(void);
+static void dtlk_stop_timer(void);
+static int dtlk_writeable(void);
+static char dtlk_write_bytes(const char *buf, int n);
+static char dtlk_write_tts(char);
+/*
+   static void dtlk_handle_error(char, char, unsigned int);
+   static char dtlk_write_byte(unsigned int, const char*);
+ */
+static void dtlk_timer_tick(unsigned long data);
+
+static ssize_t dtlk_read(struct file *file, char *buf,
+			 size_t count, loff_t * ppos)
+{
+	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	char ch;
+	int retval, i = 0, retries;
+
+	/* Can't seek (pread) on the DoubleTalk.  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	TRACE_TEXT("(dtlk_read");
+	/*  printk("DoubleTalk PC - dtlk_read()\n"); */
+
+	if (minor != DTLK_MINOR || !dtlk_has_indexing)
+		return -EINVAL;
+
+	for (retries = 0; retries < loops_per_sec / 10; retries++) {
+		while (i < count && dtlk_readable()) {
+			ch = dtlk_read_lpc();
+			/*        printk("dtlk_read() reads 0x%02x\n", ch); */
+			if ((retval = put_user(ch, buf++)))
+				return retval;
+			i++;
+		}
+		if (i)
+			return i;
+		if (file->f_flags & O_NONBLOCK)
+			break;
+		dtlk_delay(10);
+	}
+	if (retries == loops_per_sec)
+		printk(KERN_ERR "dtlk_read times out\n");
+	TRACE_RET;
+	return -EAGAIN;
+}
+
+static ssize_t dtlk_write(struct file *file, const char *buf,
+			  size_t count, loff_t * ppos)
+{
+	int i = 0, retries = 0, err, ch;
+
+	TRACE_TEXT("(dtlk_write");
+#ifdef TRACING
+	printk(" \"");
+	{
+		int i, ch;
+		for (i = 0; i < count; i++) {
+			err = get_user(ch, buf + i);
+			if (' ' <= ch && ch <= '~')
+				printk("%c", ch);
+			else
+				printk("\\%03o", ch);
+		}
+		printk("\"");
+	}
+#endif
+
+	/* Can't seek (pwrite) on the DoubleTalk.  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	if (MINOR(file->f_dentry->d_inode->i_rdev) != DTLK_MINOR)
+		return -EINVAL;
+
+	while (1) {
+		while (i < count && (err = get_user(ch, buf)) == 0 &&
+		       (ch == DTLK_CLEAR || dtlk_writeable())) {
+			dtlk_write_tts(ch);
+			buf++;
+			i++;
+			if (i % 5 == 0)
+				/* We yield our time until scheduled
+				   again.  This reduces the transfer
+				   rate to 500 bytes/sec, but that's
+				   still enough to keep up with the
+				   speech synthesizer. */
+				dtlk_delay(1);
+			else {
+				/* the RDY bit goes zero 2-3 usec
+				   after writing, and goes 1 again
+				   180-190 usec later.  Here, we wait
+				   up to 250 usec for the RDY bit to
+				   go nonzero. */
+				for (retries = 0;
+				     retries < loops_per_sec / 4000;
+				     retries++)
+					if (inb_p(dtlk_port_tts) &
+					    TTS_WRITABLE)
+						break;
+			}
+			retries = 0;
+		}
+		if (i == count)
+			return i;
+		if (file->f_flags & O_NONBLOCK)
+			break;
+
+		dtlk_delay(1);
+
+		if (++retries > 10 * HZ) { /* wait no more than 10 sec
+					      from last write */
+			printk("dtlk: write timeout.  "
+			       "inb_p(dtlk_port_tts) = 0x%02x\n",
+			       inb_p(dtlk_port_tts));
+			TRACE_RET;
+			return -EBUSY;
+		}
+	}
+	TRACE_RET;
+	return -EAGAIN;
+}
+
+static unsigned int dtlk_poll(struct file *file, poll_table * wait)
+{
+	int mask = 0;
+	TRACE_TEXT(" dtlk_poll");
+	/*
+	   static long int j;
+	   printk(".");
+	   printk("<%ld>", jiffies-j);
+	   j=jiffies;
+	 */
+	poll_wait(file, &dtlk_process_list, wait);
+
+	if (dtlk_has_indexing && dtlk_readable()) {
+		dtlk_stop_timer();
+		mask = POLLIN | POLLRDNORM;
+	}
+	if (dtlk_writeable()) {
+		dtlk_stop_timer();
+		mask |= POLLOUT | POLLWRNORM;
+	}
+	/* there are no exception conditions */
+
+	if (mask == 0 && !dtlk_timer_active) {
+		/* not ready just yet.  There won't be any interrupts,
+		   so we set a timer instead. */
+		dtlk_timer_active = 1;
+		dtlk_timer.expires = jiffies + HZ / 100;
+		add_timer(&dtlk_timer);
+	}
+	return 0;
+}
+
+static void dtlk_stop_timer()
+{
+	if (dtlk_timer_active) {
+		dtlk_timer_active = 0;
+		del_timer(&dtlk_timer);
+	}
+}
+
+static void dtlk_timer_tick(unsigned long data)
+{
+
+	wake_up_interruptible(&dtlk_process_list);
+
+	if (dtlk_timer_active) {
+		del_timer(&dtlk_timer);
+		dtlk_timer.expires = jiffies + HZ / 100;
+		add_timer(&dtlk_timer);
+	}
+}
+
+static int dtlk_ioctl(struct inode *inode,
+		      struct file *file,
+		      unsigned int cmd,
+		      unsigned long arg)
+{
+	struct dtlk_settings *sp;
+	int err;
+	char portval;
+	TRACE_TEXT(" dtlk_ioctl");
+
+	switch (cmd) {
+
+	case DTLK_INTERROGATE:
+		sp = dtlk_interrogate();
+		err = copy_to_user((char *) arg, (char *) sp,
+				   sizeof(struct dtlk_settings));
+		if (err)
+			return -EINVAL;
+		return 0;
+
+	case DTLK_STATUS:
+		portval = inb_p(dtlk_port_tts);
+		return put_user(portval, (char *) arg);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int dtlk_open(struct inode *inode, struct file *file)
+{
+	MOD_INC_USE_COUNT;
+	TRACE_TEXT("(dtlk_open");
+
+	switch (MINOR(inode->i_rdev)) {
+	case DTLK_MINOR:
+		if (dtlk_busy)
+			return -EBUSY;
+		return 0;
+
+	default:
+		return -ENXIO;
+	}
+}
+
+static int dtlk_release(struct inode *inode, struct file *file)
+{
+	MOD_DEC_USE_COUNT;
+	TRACE_TEXT("(dtlk_release");
+
+	switch (MINOR(inode->i_rdev)) {
+	case DTLK_MINOR:
+		break;
+
+	default:
+		break;
+	}
+	TRACE_RET;
+
+	dtlk_stop_timer();
+
+	return 0;
+}
+
+int __init dtlk_init(void)
+{
+	dtlk_port_lpc = 0;
+	dtlk_port_tts = 0;
+	dtlk_busy = 0;
+	dtlk_timer_active = 0;
+	dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops);
+	if (dtlk_major == 0) {
+		printk(KERN_ERR "DoubleTalk PC - cannot register device\n");
+		return 0;
+	}
+	if (dtlk_dev_probe() == 0)
+		printk(", MAJOR %d\n", dtlk_major);
+
+	init_timer(&dtlk_timer);
+	dtlk_timer.function = dtlk_timer_tick;
+	dtlk_process_list = NULL;
+
+	return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return dtlk_init();
+}
+
+void cleanup_module(void)
+{
+	dtlk_write_bytes("goodbye", 8);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(5 * HZ / 10);		/* nap 0.50 sec but
+						   could be awakened
+						   earlier by
+						   signals... */
+
+	dtlk_write_tts(DTLK_CLEAR);
+	unregister_chrdev(dtlk_major, "dtlk");
+	release_region(dtlk_port_lpc, DTLK_IO_EXTENT);
+}
+
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+/* sleep for ms milliseconds */
+static void dtlk_delay(int ms)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((ms * HZ + 1000 - HZ) / 1000);
+	current->state = TASK_RUNNING;
+}
+
+static int dtlk_readable(void)
+{
+	TRACE_TEXT(" dtlk_readable");
+	return inb_p(dtlk_port_lpc) != 0x7f;
+}
+
+static int dtlk_writeable(void)
+{
+	/* TRACE_TEXT(" dtlk_writeable"); */
+#ifdef TRACING
+	printk(" dtlk_writeable(%02x)", inb_p(dtlk_port_tts));
+#endif
+	return inb_p(dtlk_port_tts) & TTS_WRITABLE;
+}
+
+static int __init dtlk_dev_probe(void)
+{
+	unsigned int testval = 0;
+	int i = 0;
+	struct dtlk_settings *sp;
+
+	if (dtlk_port_lpc | dtlk_port_tts)
+		return -EBUSY;
+
+	for (i = 0; dtlk_portlist[i]; i++) {
+#if 0
+		printk("DoubleTalk PC - Port %03x = %04x\n",
+		       dtlk_portlist[i], (testval = inw_p(dtlk_portlist[i])));
+#endif
+
+		if (check_region(dtlk_portlist[i], DTLK_IO_EXTENT))
+			continue;
+		testval = inw_p(dtlk_portlist[i]);
+		if ((testval &= 0xfbff) == 0x107f) {
+			request_region(dtlk_portlist[i], DTLK_IO_EXTENT, 
+				       "dtlk");
+			dtlk_port_lpc = dtlk_portlist[i];
+			dtlk_port_tts = dtlk_port_lpc + 1;
+
+			sp = dtlk_interrogate();
+			printk("DoubleTalk PC at %03x-%03x, "
+			       "ROM version %s, serial number %u",
+			       dtlk_portlist[i], dtlk_portlist[i] +
+			       DTLK_IO_EXTENT - 1,
+			       sp->rom_version, sp->serial_number);
+
+                        /* put LPC port into known state, so
+			   dtlk_readable() gives valid result */
+			outb_p(0xff, dtlk_port_lpc); 
+
+                        /* INIT string and index marker */
+			dtlk_write_bytes("\036\1@\0\0012I\r", 8);
+			/* posting an index takes 18 msec.  Here, we
+			   wait up to 100 msec to see whether it
+			   appears. */
+			dtlk_delay(100);
+			dtlk_has_indexing = dtlk_readable();
+
+#ifdef INSCOPE
+			{
+/* This macro records ten samples read from the LPC port, for later display */
+#define LOOK					\
+for (i = 0; i < 10; i++)			\
+  {						\
+    buffer[b++] = inb_p(dtlk_port_lpc);		\
+    __delay(loops_per_sec/1000000);             \
+  }
+				char buffer[1000];
+				int b = 0, i, j;
+
+				LOOK
+				    outb_p(0xff, dtlk_port_lpc);
+				buffer[b++] = 0;
+				LOOK
+				    dtlk_write_bytes("\0012I\r", 4);
+				buffer[b++] = 0;
+				__delay(50 * loops_per_sec / 1000);
+				outb_p(0xff, dtlk_port_lpc);
+				buffer[b++] = 0;
+				LOOK
+
+				    printk("\n");
+				for (j = 0; j < b; j++)
+					printk(" %02x", buffer[j]);
+				printk("\n");
+			}
+#endif				/* INSCOPE */
+
+#ifdef OUTSCOPE
+			{
+/* This macro records ten samples read from the TTS port, for later display */
+#define LOOK					\
+for (i = 0; i < 10; i++)			\
+  {						\
+    buffer[b++] = inb_p(dtlk_port_tts);		\
+    __delay(loops_per_sec/1000000);  /* 1 us */ \
+  }
+				char buffer[1000];
+				int b = 0, i, j;
+
+				__delay(loops_per_sec / 100);	/* 10 ms */
+				LOOK
+				    outb_p(0x03, dtlk_port_tts);
+				buffer[b++] = 0;
+				LOOK
+				    LOOK
+
+				    printk("\n");
+				for (j = 0; j < b; j++)
+					printk(" %02x", buffer[j]);
+				printk("\n");
+			}
+#endif				/* OUTSCOPE */
+
+			dtlk_write_bytes("Double Talk found", 18);
+
+			return 0;
+		}
+	}
+
+	printk(KERN_INFO "\nDoubleTalk PC - not found\n");
+	return -ENODEV;
+}
+
+/*
+   static void dtlk_handle_error(char op, char rc, unsigned int minor)
+   {
+   printk(KERN_INFO"\nDoubleTalk PC - MINOR: %d, OPCODE: %d, ERROR: %d\n", 
+   minor, op, rc);
+   return;
+   }
+ */
+
+/* interrogate the DoubleTalk PC and return its settings */
+static struct dtlk_settings *dtlk_interrogate(void)
+{
+	unsigned char *t;
+	static char buf[sizeof(struct dtlk_settings) + 1];
+	int total, i;
+	static struct dtlk_settings status;
+	TRACE_TEXT("(dtlk_interrogate");
+	dtlk_write_bytes("\030\001?", 3);
+	for (total = 0, i = 0; i < 50; i++) {
+		buf[total] = dtlk_read_tts();
+		if (total > 2 && buf[total] == 0x7f)
+			break;
+		if (total < sizeof(struct dtlk_settings))
+			 total++;
+	}
+	/*
+	   if (i==50) printk("interrogate() read overrun\n");
+	   for (i=0; i<sizeof(buf); i++)
+	   printk(" %02x", buf[i]);
+	   printk("\n");
+	 */
+	t = buf;
+	status.serial_number = t[0] + t[1] * 256; /* serial number is
+						     little endian */
+	t += 2;
+
+	i = 0;
+	while (*t != '\r') {
+		status.rom_version[i] = *t;
+		if (i < sizeof(status.rom_version) - 1)
+			i++;
+		t++;
+	}
+	status.rom_version[i] = 0;
+	t++;
+
+	status.mode = *t++;
+	status.punc_level = *t++;
+	status.formant_freq = *t++;
+	status.pitch = *t++;
+	status.speed = *t++;
+	status.volume = *t++;
+	status.tone = *t++;
+	status.expression = *t++;
+	status.ext_dict_loaded = *t++;
+	status.ext_dict_status = *t++;
+	status.free_ram = *t++;
+	status.articulation = *t++;
+	status.reverb = *t++;
+	status.eob = *t++;
+	status.has_indexing = dtlk_has_indexing;
+	TRACE_RET;
+	return &status;
+}
+
+static char dtlk_read_tts(void)
+{
+	int portval, retries = 0;
+	char ch;
+	TRACE_TEXT("(dtlk_read_tts");
+
+	/* verify DT is ready, read char, wait for ACK */
+	do {
+		portval = inb_p(dtlk_port_tts);
+	} while ((portval & TTS_READABLE) == 0 && retries++ < DTLK_MAX_RETRIES);
+	if (retries == DTLK_MAX_RETRIES)
+		printk(KERN_ERR "dtlk_read_tts() timeout\n");
+
+	ch = inb_p(dtlk_port_tts);	/* input from TTS port */
+	ch &= 0x7f;
+	outb_p(ch, dtlk_port_tts);
+
+	retries = 0;
+	do {
+		portval = inb_p(dtlk_port_tts);
+	} while ((portval & TTS_READABLE) != 0 && retries++ < DTLK_MAX_RETRIES);
+	if (retries == DTLK_MAX_RETRIES)
+		printk(KERN_ERR "dtlk_read_tts() timeout\n");
+
+	TRACE_RET;
+	return ch;
+}
+
+static char dtlk_read_lpc(void)
+{
+	int retries = 0;
+	char ch;
+	TRACE_TEXT("(dtlk_read_lpc");
+
+	/* no need to test -- this is only called when the port is readable */
+
+	ch = inb_p(dtlk_port_lpc);	/* input from LPC port */
+
+	outb_p(0xff, dtlk_port_lpc);
+
+	/* acknowledging a read takes 3-4
+	   usec.  Here, we wait up to 20 usec
+	   for the acknowledgement */
+	retries = (loops_per_sec * 20) / 1000000;
+	while (inb_p(dtlk_port_lpc) != 0x7f && --retries > 0);
+	if (retries == 0)
+		printk(KERN_ERR "dtlk_read_lpc() timeout\n");
+
+	TRACE_RET;
+	return ch;
+}
+
+#ifdef NEVER
+static char dtlk_write_byte(unsigned int minor, const char *buf)
+{
+	char ch;
+	int err;
+	/* TRACE_TEXT("(dtlk_write_byte"); */
+	err = get_user(ch, buf);
+	/* printk("  dtlk_write_byte(%d, 0x%02x)", minor, (int)ch); */
+
+	ch = dtlk_write_tts(ch);
+	/* 
+	   TRACE_RET; */
+	return ch;
+}
+#endif				/* NEVER */
+
+/* write n bytes to tts port */
+static char dtlk_write_bytes(const char *buf, int n)
+{
+	char val = 0;
+	/*  printk("dtlk_write_bytes(\"%-*s\", %d)\n", n, buf, n); */
+	TRACE_TEXT("(dtlk_write_bytes");
+	while (n-- > 0)
+		val = dtlk_write_tts(*buf++);
+	TRACE_RET;
+	return val;
+}
+
+static char dtlk_write_tts(char ch)
+{
+	int retries = 0;
+#ifdef TRACING
+	printk("  dtlk_write_tts(");
+	if (' ' <= ch && ch <= '~')
+		printk("'%c'", ch);
+	else
+		printk("0x%02x", ch);
+#endif
+	if (ch != DTLK_CLEAR)	/* no flow control for CLEAR command */
+		while ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0 &&
+		       retries++ < DTLK_MAX_RETRIES)	/* DT ready? */
+			;
+	if (retries == DTLK_MAX_RETRIES)
+		printk(KERN_ERR "dtlk_write_tts() timeout\n");
+
+	outb_p(ch, dtlk_port_tts);	/* output to TTS port */
+	/* the RDY bit goes zero 2-3 usec after writing, and goes
+	   1 again 180-190 usec later.  Here, we wait up to 10
+	   usec for the RDY bit to go zero. */
+	for (retries = 0; retries < loops_per_sec / 100000; retries++)
+		if ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0)
+			break;
+
+#ifdef TRACING
+	printk(")\n");
+#endif
+	return 0;
+}
diff -urN linux-2.2.3-pre2/drivers/char/ftape/zftape/zftape-init.c linux-2.2.3-pre3/drivers/char/ftape/zftape/zftape-init.c
--- linux-2.2.3-pre2/drivers/char/ftape/zftape/zftape-init.c	1998-08-24 13:02:45.000000000 -0700
+++ linux-2.2.3-pre3/drivers/char/ftape/zftape/zftape-init.c	2003-08-15 15:05:26.000000000 -0700
@@ -280,8 +280,6 @@
 		static struct vm_operations_struct dummy = { NULL, };
 		vma->vm_ops = &dummy;
 #endif
-		vma->vm_file = filep;
-		filep->f_count++;
 	}
 	current->blocked = old_sigmask; /* restore mask */
 	TRACE_EXIT result;
diff -urN linux-2.2.3-pre2/drivers/char/Makefile linux-2.2.3-pre3/drivers/char/Makefile
--- linux-2.2.3-pre2/drivers/char/Makefile	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/drivers/char/Makefile	2003-08-15 15:05:26.000000000 -0700
@@ -176,6 +176,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_DTLK),y)
+L_OBJS += dtlk.o
+else
+  ifeq ($(CONFIG_DTLK),m)
+  M_OBJS += dtlk.o
+  endif
+endif
+
 ifeq ($(CONFIG_MS_BUSMOUSE),y)
 L_OBJS += msbusmouse.o
 else
diff -urN linux-2.2.3-pre2/drivers/char/mem.c linux-2.2.3-pre3/drivers/char/mem.c
--- linux-2.2.3-pre2/drivers/char/mem.c	1999-01-24 21:55:04.000000000 -0800
+++ linux-2.2.3-pre3/drivers/char/mem.c	2003-08-15 15:05:26.000000000 -0700
@@ -178,8 +178,6 @@
 	if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
 			     vma->vm_page_prot))
 		return -EAGAIN;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -urN linux-2.2.3-pre2/drivers/char/misc.c linux-2.2.3-pre3/drivers/char/misc.c
--- linux-2.2.3-pre2/drivers/char/misc.c	1999-01-15 17:46:27.000000000 -0800
+++ linux-2.2.3-pre3/drivers/char/misc.c	2003-08-15 15:05:26.000000000 -0700
@@ -231,6 +231,9 @@
 #ifdef CONFIG_SOFT_WATCHDOG
 	watchdog_init();
 #endif
+#ifdef CONFIG_DTLK
+	dtlk_init();
+#endif
 #ifdef CONFIG_APM
 	apm_bios_init();
 #endif
diff -urN linux-2.2.3-pre2/drivers/char/radio-aimslab.c linux-2.2.3-pre3/drivers/char/radio-aimslab.c
--- linux-2.2.3-pre2/drivers/char/radio-aimslab.c	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/drivers/char/radio-aimslab.c	2003-08-15 15:05:26.000000000 -0700
@@ -3,6 +3,11 @@
  * Coverted to new API by Alan Cox <Alan.Cox@linux.org>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
  *
+ * History:
+ * 1999-02-24	Russell Kroll <rkroll@exploits.org>
+ * 		Fine tuning/VIDEO_TUNER_LOW
+ *		Frequency range expanded to start at 87 MHz
+ *
  * TODO: Allow for more than one of these foolish entities :-)
  *
  * Notes on the hardware (reverse engineered from other peoples'
@@ -156,14 +161,11 @@
 
 	/* adapted from radio-aztech.c */
 
-	/* We want to compute x * 100 / 16 without overflow 
-	 * So we compute x*6 + (x/100)*25 to give x*6.25
-	 */
-	 
-	freq = freq * 6 + freq/4;	/* massage the data a little	*/
-	freq += 1070;			/* IF = 10.7 MHz 		*/
-	freq /= 5;			/* ref = 25 kHz			*/
+	/* now uses VIDEO_TUNER_LOW for fine tuning */
 
+	freq += 171200;			/* Add 10.7 MHz IF 		*/
+	freq /= 800;			/* Convert to 50 kHz units	*/
+	 
 	send_0_byte (io, dev);		/*  0: LSB of frequency		*/
 
 	for (i = 0; i < 13; i++)	/*   : frequency bits (1-13)	*/
@@ -200,16 +202,6 @@
 	return 1;		/* signal present		*/
 }
 
-int rt_chkstereo(struct rt_device *dev)
-{
-	outb(0xd8, io);
-	sleep_delay(100000);
-	if (inb(io) & 0x0fd)
-		return VIDEO_SOUND_STEREO;	/* stereo detected */
-	else 
-		return VIDEO_SOUND_MONO;	/* mono */
-}
-
 static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
 	struct rt_device *rt=dev->priv;
@@ -239,9 +231,9 @@
 				return -EFAULT;
 			if(v.tuner)	/* Only 1 tuner */ 
 				return -EINVAL;
-			v.rangelow=(88*16);
-			v.rangehigh=(108*16);
-			v.flags=0;
+			v.rangelow=(87*16000);
+			v.rangehigh=(108*16000);
+			v.flags=VIDEO_TUNER_LOW;
 			v.mode=VIDEO_MODE_AUTO;
 			v.signal=0xFFFF*rt_getsigstr(rt);
 			if(copy_to_user(arg,&v, sizeof(v)))
@@ -273,7 +265,6 @@
 			memset(&v,0, sizeof(v));
 			v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
 			v.volume=rt->curvol * 6554;
-			v.mode=rt_chkstereo(rt);
 			v.step=6554;
 			strcpy(v.name, "Radio");
 			if(copy_to_user(arg,&v, sizeof(v)))
diff -urN linux-2.2.3-pre2/drivers/char/radio-aztech.c linux-2.2.3-pre3/drivers/char/radio-aztech.c
--- linux-2.2.3-pre2/drivers/char/radio-aztech.c	1998-08-23 13:32:25.000000000 -0700
+++ linux-2.2.3-pre3/drivers/char/radio-aztech.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,9 +1,7 @@
-/* aztech.c - Aztech radio card driver for Linux 2.1 by Russell Kroll
+/* radio-aztech.c - Aztech radio card driver for Linux 2.2 
  *
- * Heavily modified to support the new 2.1 radio card interfaces by
- * Russell Kroll (rkroll@exploits.org)
- *
- * Based on code by
+ * Adapted to support the Video for Linux API by 
+ * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
  * Quay Ly
  * Donald Song
@@ -14,6 +12,11 @@
  * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
  * along with more information on the card itself.
  *
+ * History:
+ * 1999-02-24	Russell Kroll <rkroll@exploits.org>
+ *		Fine tuning/VIDEO_TUNER_LOW
+ * 		Range expanded to 87-108 MHz (from 87.9-107.8)
+ *
  * Notable changes from the original source:
  * - includes stripped down to the essentials
  * - for loops used as delays replaced with udelay()
@@ -113,11 +116,8 @@
 {
 	int  i;
 
-	/*  6.25 *  */
-	frequency = frequency*6 + frequency/4;	/* massage data a bit */
-  
-	frequency += 1070;		/* tuning needs 24 data bits  */
-	frequency /= 5;
+	frequency += 171200;		/* Add 10.7 MHz IF		*/
+	frequency /= 800;		/* Convert to 50 kHz units	*/
 					
 	send_0_byte (dev);		/*  0: LSB of frequency       */
 
@@ -179,9 +179,9 @@
 				return -EFAULT;
 			if(v.tuner)	/* Only 1 tuner */ 
 				return -EINVAL;
-			v.rangelow=(879*16)/10;
-			v.rangehigh=(1078*16)/10;
-			v.flags=0;
+			v.rangelow=(87*16000);
+			v.rangehigh=(108*16000);
+			v.flags=VIDEO_TUNER_LOW;
 			v.mode=VIDEO_MODE_AUTO;
 			v.signal=0xFFFF*az_getsigstr(az);
 			if(az_getstereo(az))
@@ -292,7 +292,7 @@
 		return -EINVAL;
 		
 	request_region(io, 2, "aztech");
-	printk(KERN_INFO "Aztech radio card driver v0.40/19980422 rkroll@exploits.org\n");
+	printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
 	/* mute card - prevents noisy bootups */
 	outb (0, io);
 	return 0;
diff -urN linux-2.2.3-pre2/drivers/net/cosa.c linux-2.2.3-pre3/drivers/net/cosa.c
--- linux-2.2.3-pre2/drivers/net/cosa.c	1998-12-28 11:05:14.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/cosa.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: cosa.c,v 1.11 1998/12/24 23:44:23 kas Exp $ */
+/* $Id: cosa.c,v 1.21 1999/02/06 19:49:18 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -27,7 +27,7 @@
  * Masaryk University (http://www.ics.muni.cz/). The hardware is
  * developed by Jiri Novotny <novotny@ics.muni.cz>. More information
  * and the photo of both cards is available at
- * http://www.kozakmartin.cz/cosa.html. The card documentation, firmwares
+ * http://www.pavoucek.cz/cosa.html. The card documentation, firmwares
  * and other goods can be downloaded from ftp://ftp.ics.muni.cz/pub/cosa/.
  * For Linux-specific utilities, see below in the "Software info" section.
  * If you want to order the card, contact Jiri Novotny.
@@ -141,11 +141,13 @@
 	unsigned int datareg, statusreg;	/* I/O ports */
 	unsigned short irq, dma;	/* IRQ and DMA number */
 	unsigned short startaddr;	/* Firmware start address */
+	unsigned short busmaster;	/* Use busmastering? */
 	int nchannels;			/* # of channels on this card */
 	int driver_status;		/* For communicating with firware */
 	int firmware_status;		/* Downloaded, reseted, etc. */
 	int rxbitmap, txbitmap;		/* Bitmap of channels who are willing to send/receive data */
 	int rxtx;			/* RX or TX in progress? */
+	int enabled;
 	int usage;				/* usage count */
 	int txchan, txsize, rxsize;
 	struct channel_data *rxchan;
@@ -331,9 +333,8 @@
 static int get_wait_data(struct cosa_data *cosa);
 static int put_wait_data(struct cosa_data *cosa, int data);
 static int puthexnumber(struct cosa_data *cosa, int number);
-static void put_driver_status_common(struct cosa_data *cosa, int nolock);
-#define put_driver_status(x) put_driver_status_common((x), 0)
-#define put_driver_status_nolock(x) put_driver_status_common((x), 1)
+static void put_driver_status(struct cosa_data *cosa);
+static void put_driver_status_nolock(struct cosa_data *cosa);
 
 /* Interrupt handling */
 static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
@@ -357,7 +358,7 @@
 #endif
 {
 	int i;
-	printk(KERN_INFO "cosa v1.03 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
+	printk(KERN_INFO "cosa v1.04 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
 #ifdef __SMP__
 	printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
 #endif
@@ -630,9 +631,14 @@
 	if (dev->tbusy) { 
 		if (time_before(jiffies, dev->trans_start+2*HZ))
 			return 1;	/* Two seconds timeout */
+		if (test_bit(RXBIT, &chan->cosa->rxtx)) {
+			chan->stats.rx_errors++;
+			chan->stats.rx_missed_errors++;
+		} else {
+			chan->stats.tx_errors++;
+			chan->stats.tx_aborted_errors++;
+		}
 		cosa_kick(chan->cosa);
-		chan->stats.tx_errors++;
-		chan->stats.tx_aborted_errors++;
 		if (chan->tx_skb) {
 			dev_kfree_skb(chan->tx_skb);
 			chan->tx_skb = 0;
@@ -659,6 +665,14 @@
 	d->tbusy = 1;
 	cosa_disable_rx(chan);
 	spin_lock_irqsave(&chan->cosa->lock, flags);
+	if (chan->rx_skb) {
+		kfree_skb(chan->rx_skb);
+		chan->rx_skb = 0;
+	}
+	if (chan->tx_skb) {
+		kfree_skb(chan->tx_skb);
+		chan->tx_skb = 0;
+	}
 	chan->usage=0;
 	chan->cosa->usage--;
 	MOD_DEC_USE_COUNT;
@@ -1128,6 +1142,17 @@
 		return nr_cards;
 	case COSAIONRCHANS:
 		return cosa->nchannels;
+	case COSAIOBMSET:
+		if (!suser())
+			return -EACCES;
+		if (is_8bit(cosa))
+			return -EINVAL;
+		if (arg != COSA_BM_OFF && arg != COSA_BM_ON)
+			return -EINVAL;
+		cosa->busmaster = arg;
+		return 0;
+	case COSAIOBMGET:
+		return cosa->busmaster;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -1208,37 +1233,67 @@
 	return 0;
 }
 
-static void put_driver_status_common(struct cosa_data *cosa, int nolock)
+static void put_driver_status(struct cosa_data *cosa)
 {
 	unsigned flags=0;
 	int status;
 
-	if (!nolock)
-		spin_lock_irqsave(&cosa->lock, flags);
+	spin_lock_irqsave(&cosa->lock, flags);
 
 	status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
 		| (cosa->txbitmap ? DRIVER_TX_READY : 0)
 		| (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
 			&DRIVER_TXMAP_MASK : 0);
-	if (!cosa->rxtx || nolock) {
-#ifdef DEBUG_IO
-		debug_data_cmd(cosa, status);
-#endif
-		cosa_putdata8(cosa, status);
+	if (!cosa->rxtx) {
 		if (cosa->rxbitmap|cosa->txbitmap) {
-			cosa_putstatus(cosa, SR_RX_INT_ENA);
+			if (!cosa->enabled) {
+				cosa_putstatus(cosa, SR_RX_INT_ENA);
 #ifdef DEBUG_IO
-			debug_status_out(cosa, SR_RX_INT_ENA);
+				debug_status_out(cosa, SR_RX_INT_ENA);
 #endif
-		} else {
+				cosa->enabled = 1;
+			}
+		} else if (cosa->enabled) {
+			cosa->enabled = 0;
 			cosa_putstatus(cosa, 0);
 #ifdef DEBUG_IO
 			debug_status_out(cosa, 0);
 #endif
 		}
+		cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+		debug_data_cmd(cosa, status);
+#endif
 	}
-	if (!nolock)
-		spin_unlock_irqrestore(&cosa->lock, flags);
+	spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void put_driver_status_nolock(struct cosa_data *cosa)
+{
+	int status;
+
+	status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
+		| (cosa->txbitmap ? DRIVER_TX_READY : 0)
+		| (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
+			&DRIVER_TXMAP_MASK : 0);
+
+	if (cosa->rxbitmap|cosa->txbitmap) {
+		cosa_putstatus(cosa, SR_RX_INT_ENA);
+#ifdef DEBUG_IO
+		debug_status_out(cosa, SR_RX_INT_ENA);
+#endif
+		cosa->enabled = 1;
+	} else {
+		cosa_putstatus(cosa, 0);
+#ifdef DEBUG_IO
+		debug_status_out(cosa, 0);
+#endif
+		cosa->enabled = 0;
+	}
+	cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+	debug_data_cmd(cosa, status);
+#endif
 }
 
 /*
@@ -1249,9 +1304,14 @@
 static void cosa_kick(struct cosa_data *cosa)
 {
 	unsigned flags, flags1;
+	char *s = "Unknown";
 
-	printk(KERN_INFO "%s: DMA timeout - restarting.\n", cosa->name);
+	if (test_bit(RXBIT, &cosa->rxtx))
+		s = "RX";
+	if (test_bit(TXBIT, &cosa->rxtx))
+		s = "TX";
 
+	printk(KERN_INFO "%s: %s DMA timeout - restarting.\n", cosa->name, s); 
 	spin_lock_irqsave(&cosa->lock, flags);
 	cosa->rxtx = 0;
 
@@ -1261,6 +1321,13 @@
 	release_dma_lock(flags1);
 
 	/* FIXME: Anything else? */
+	udelay(100);
+	cosa_putstatus(cosa, 0);
+	udelay(100);
+	(void) cosa_getdata8(cosa);
+	udelay(100);
+	cosa_putdata8(cosa, 0);
+	udelay(100);
 	put_driver_status_nolock(cosa);
 	spin_unlock_irqrestore(&cosa->lock, flags);
 }
@@ -1556,6 +1623,10 @@
  * COSA status byte. I have moved the rx/tx/eot interrupt handling into
  * separate functions to make it more readable. These functions are inline,
  * so there should be no overhead of function call.
+ * 
+ * In the COSA bus-master mode, we need to tell the card the address of a
+ * buffer. Unfortunately, COSA may be too slow for us, so we must busy-wait.
+ * It's time to use the bottom half :-(
  */
 
 /*
@@ -1606,13 +1677,13 @@
 
 	if (is_8bit(cosa)) {
 		if (!test_bit(IRQBIT, &cosa->rxtx)) {
+			cosa_putstatus(cosa, SR_TX_INT_ENA);
 			cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)|
 				((cosa->txsize >> 8) & 0x1f));
-			cosa_putstatus(cosa, SR_TX_INT_ENA);
 #ifdef DEBUG_IO
+			debug_status_out(cosa, SR_TX_INT_ENA);
 			debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)|
                                 ((cosa->txsize >> 8) & 0x1f));
-			debug_status_out(cosa, SR_TX_INT_ENA);
 			debug_data_in(cosa, cosa_getdata8(cosa));
 #else
 			cosa_getdata8(cosa);
@@ -1630,27 +1701,57 @@
 #endif
 		}
 	} else {
+		cosa_putstatus(cosa, SR_TX_INT_ENA);
 		cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000)
 			| (cosa->txsize & 0x1fff));
-		cosa_getdata16(cosa);
 #ifdef DEBUG_IO
-		debug_status_out(cosa, ((cosa->txchan<<13) & 0xe000)
+		debug_status_out(cosa, SR_TX_INT_ENA);
+		debug_data_out(cosa, ((cosa->txchan<<13) & 0xe000)
                         | (cosa->txsize & 0x1fff));
-		debug_data_in(cosa, cosa_getdata16(cosa));
+		debug_data_in(cosa, cosa_getdata8(cosa));
+		debug_status_out(cosa, 0);
 #else
-		cosa_getdata16(cosa);
+		cosa_getdata8(cosa);
 #endif
+		cosa_putstatus(cosa, 0);
 	}
 
-	/* start the DMA */
-	flags1 = claim_dma_lock();
-	disable_dma(cosa->dma);
-	clear_dma_ff(cosa->dma);
-	set_dma_mode(cosa->dma, DMA_MODE_WRITE);
-	set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
-	set_dma_count(cosa->dma, cosa->txsize);
-	enable_dma(cosa->dma);
-	release_dma_lock(flags1);
+	if (cosa->busmaster) {
+		unsigned long addr = virt_to_bus(cosa->txbuf);
+		int count=0;
+		printk(KERN_INFO "busmaster IRQ\n");
+		while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+			count++;
+			udelay(10);
+			if (count > 1000) break;
+		}
+		printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
+		printk(KERN_INFO "ready after %d loops\n", count);
+		cosa_putdata16(cosa, (addr >> 16)&0xffff);
+
+		count = 0;
+		while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+			count++;
+			if (count > 1000) break;
+			udelay(10);
+		}
+		printk(KERN_INFO "ready after %d loops\n", count);
+		cosa_putdata16(cosa, addr &0xffff);
+		flags1 = claim_dma_lock();
+		set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
+		enable_dma(cosa->dma);
+		release_dma_lock(flags1);
+	} else {
+		/* start the DMA */
+		flags1 = claim_dma_lock();
+		disable_dma(cosa->dma);
+		clear_dma_ff(cosa->dma);
+		set_dma_mode(cosa->dma, DMA_MODE_WRITE);
+		set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
+		set_dma_count(cosa->dma, cosa->txsize);
+		enable_dma(cosa->dma);
+		release_dma_lock(flags1);
+	}
 	cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
 #ifdef DEBUG_IO
 	debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
@@ -1671,21 +1772,16 @@
 	if (is_8bit(cosa)) {
 		if (!test_bit(IRQBIT, &cosa->rxtx)) {
 			set_bit(IRQBIT, &cosa->rxtx);
-			cosa_putstatus(cosa, 0);
 			cosa->rxsize = cosa_getdata8(cosa) <<8;
 #ifdef DEBUG_IO
-			debug_status_out(cosa, 0);
 			debug_data_in(cosa, cosa->rxsize >> 8);
 #endif
-			put_driver_status_nolock(cosa);
 			spin_unlock_irqrestore(&cosa->lock, flags);
 			return;
 		} else {
 			clear_bit(IRQBIT, &cosa->rxtx);
-			cosa_putstatus(cosa, 0);
 			cosa->rxsize |= cosa_getdata8(cosa) & 0xff;
 #ifdef DEBUG_IO
-			debug_status_out(cosa, 0);
 			debug_data_in(cosa, cosa->rxsize & 0xff);
 #endif
 #if 0
@@ -1695,12 +1791,8 @@
 		}
 	} else {
 		cosa->rxsize = cosa_getdata16(cosa);
-		cosa_putstatus(cosa, 0);
-		cosa_putdata8(cosa, DRIVER_RX_READY);
 #ifdef DEBUG_IO
 		debug_data_in(cosa, cosa->rxsize);
-		debug_status_out(cosa, 0);
-		debug_cmd_out(cosa, DRIVER_RX_READY);
 #endif
 #if 0
 		printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
@@ -1725,10 +1817,7 @@
 reject:		/* Reject the packet */
 		printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
 			cosa->num, cosa->rxchan->num);
-		/* FIXME: This works for COSA only (not SRP) */
-		cosa->rxtx = 0;
-		put_driver_status(cosa);
-		return;
+		cosa->rxbuf = cosa->bouncebuf;
 	}
 
 	/* start the DMA */
@@ -1746,8 +1835,12 @@
 	release_dma_lock(flags);
 	spin_lock_irqsave(&cosa->lock, flags);
 	cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+	if (!is_8bit(cosa) && (status & SR_TX_RDY))
+		cosa_putdata8(cosa, DRIVER_RX_READY);
 #ifdef DEBUG_IO
 	debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+	if (!is_8bit(cosa) && (status & SR_TX_RDY))
+		debug_data_cmd(cosa, DRIVER_RX_READY);
 #endif
 	spin_unlock_irqrestore(&cosa->lock, flags);
 }
@@ -1756,11 +1849,12 @@
 {
 	unsigned long flags, flags1;
 	spin_lock_irqsave(&cosa->lock, flags);
+	flags1 = claim_dma_lock();
+	disable_dma(cosa->dma);
+	clear_dma_ff(cosa->dma);
+	release_dma_lock(flags1);
 	if (test_bit(TXBIT, &cosa->rxtx)) {
 		struct channel_data *chan = cosa->chan+cosa->txchan;
-#ifdef DEBUG_IRQS
-		printk(KERN_INFO "cosa%d: end of transfer.\n", cosa->num);
-#endif
 		if (chan->tx_done)
 			if (chan->tx_done(chan, cosa->txsize))
 				clear_bit(chan->num, &cosa->txbitmap);
@@ -1775,6 +1869,9 @@
 		printk("\n");
 	}
 #endif
+		/* Packet for unknown channel? */
+		if (cosa->rxbuf == cosa->bouncebuf)
+			goto out;
 		if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize))
 			memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize);
 		if (cosa->rxchan->rx_done)
@@ -1786,12 +1883,11 @@
 	}
 	/*
 	 * Clear the RXBIT, TXBIT and IRQBIT (the latest should be
-	 * cleared anyway).
+	 * cleared anyway). We should do it as soon as possible
+	 * so that we can tell the COSA we are done and to give it a time
+	 * for recovery.
 	 */
-	flags1 = claim_dma_lock();
-	disable_dma(cosa->dma);
-	clear_dma_ff(cosa->dma);
-	release_dma_lock(flags1);
+out:
 	cosa->rxtx = 0;
 	put_driver_status_nolock(cosa);
 	spin_unlock_irqrestore(&cosa->lock, flags);
@@ -1799,7 +1895,7 @@
 
 static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
 {
-	int status;
+	unsigned status;
 	int count = 0;
 	struct cosa_data *cosa = cosa_;
 again:
diff -urN linux-2.2.3-pre2/drivers/net/cosa.h linux-2.2.3-pre3/drivers/net/cosa.h
--- linux-2.2.3-pre2/drivers/net/cosa.h	1998-12-28 11:05:14.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/cosa.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: cosa.h,v 1.5 1998/12/24 12:40:18 kas Exp $ */
+/* $Id: cosa.h,v 1.6 1999/01/06 14:02:44 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -99,4 +99,13 @@
 /* Get the number of channels on this card */
 #define COSAIONRCHANS	_IO('C',0xf8)
 
+/* Set the driver for the bus-master operations */
+#define COSAIOBMSET	_IOW('C', 0xf9, sizeof(unsigned short))
+
+#define COSA_BM_OFF	0	/* Bus-mastering off - use ISA DMA (default) */
+#define COSA_BM_ON	1	/* Bus-mastering on - faster but untested */
+
+/* Gets the busmaster status */
+#define COSAIOBMGET	_IO('C', 0xfa)
+
 #endif /* !COSA_H__ */
diff -urN linux-2.2.3-pre2/drivers/net/irda/actisys.c linux-2.2.3-pre3/drivers/net/irda/actisys.c
--- linux-2.2.3-pre2/drivers/net/irda/actisys.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/actisys.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,13 +1,13 @@
 /*********************************************************************
  *                
  * Filename:      actisys.c
- * Version:       0.4
+ * Version:       0.5
  * Description:   Implementation for the ACTiSYS IR-220L and IR-220L+ 
  *                dongles
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Jan 18 11:30:25 1999
+ * Modified at:   Tue Feb  9 15:38:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -70,9 +70,10 @@
 
 static void actisys_open( struct irda_device *idev, int type)
 {
-	strcat( idev->name, " <-> actisys");
+	strcat(idev->description, " <-> actisys");
 
         idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
 
 	MOD_INC_USE_COUNT;
 }
@@ -85,24 +86,20 @@
 /*
  * Function actisys_change_speed (tty, baud)
  *
- *    Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.  
- *    To cycle through the available baud rates, pulse RTS low for a few ms.
- *    To be compatible with the new IR-220L+, we have to reset the dongle 
- *    first since its not possible cycle around anymore and still be 
- *    compatible with both dongles :-(
+ *    Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
+ *    To cycle through the available baud rates, pulse RTS low for a few
+ *    ms.  
  */
 static void actisys_change_speed( struct irda_device *idev, int baudrate)
 {
         struct irtty_cb *self;
         struct tty_struct *tty;
-        int arg;
         struct termios old_termios;
 	int cflag;
         int current_baudrate;
         int index = 0;
-	mm_segment_t fs;
 	
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -115,10 +112,10 @@
 	current_baudrate = idev->qos.baud_rate.value;
 
 	/* Find the correct baudrate index for the currently used baudrate */
-	while ( current_baudrate != baud_rates[index])
+	while (current_baudrate != baud_rates[index])
 		index++;
 
-        DEBUG( 0, __FUNCTION__ "(), index=%d\n", index);
+        DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
 
 	if ( !self->tty)
 		return;
@@ -127,38 +124,18 @@
 
 	/* Cycle through avaiable baudrates until we reach the correct one */
         while ( current_baudrate != baudrate) {	
-                DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
+                DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n",
                        baud_rates[index]);
-		DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n");
 		
 		/* Set DTR, clear RTS */
-		arg = TIOCM_DTR|TIOCM_OUT2;
-		
-		fs = get_fs();
-		set_fs( get_ds());
-		
-		if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-					(unsigned long) &arg)) { 
-			DEBUG( 0, __FUNCTION__ 
-			       "Error clearing RTS!\n");
-		}
-		set_fs(fs);
+		irtty_set_dtr_rts(tty, TRUE, FALSE);
 		
 		/* Wait at a few ms */
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(2);
 
 		/* Set DTR, Set RTS */
-                arg = TIOCM_DTR | TIOCM_RTS |TIOCM_OUT2;
-
-		fs = get_fs();
-		set_fs( get_ds());
-		
-		if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-					(unsigned long) &arg)) { 
-			DEBUG( 0, __FUNCTION__  "Error setting RTS!\n");
-		}
-		set_fs(fs);
+		irtty_set_dtr_rts(tty, TRUE, TRUE);
 		
 		/* Wait at a few ms again */
 		current->state = TASK_INTERRUPTIBLE;
@@ -172,8 +149,8 @@
 
                 current_baudrate = baud_rates[index];
         }
-	DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n", 
-                  baud_rates[index]);
+	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", 
+	      baud_rates[index]);
 
 	/* Now change the speed of the serial port */
 	old_termios = *(tty->termios);
@@ -200,9 +177,8 @@
 		break;
 	}
 
+	/* Change speed of serial port */
 	tty->termios->c_cflag = cflag;
-
-	DEBUG( 0, __FUNCTION__ "(), Setting the speed of the serial port\n");
 	tty->driver.set_termios( tty, &old_termios);
 }
 
@@ -219,10 +195,6 @@
 {
 	struct irtty_cb *self;
         struct tty_struct *tty;
-        int arg = 0;
-	mm_segment_t fs;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -236,36 +208,16 @@
 	if ( !tty)
 		return;
 
-	DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n");
-	arg = TIOCM_RTS | TIOCM_OUT2;
-
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) 
-	{ 
-		DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
-	}
-	set_fs(fs);
+	/* Clear DTR */
+	irtty_set_dtr_rts(tty, FALSE, TRUE);
 
 	/* Sleep 10-20 ms*/
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(2);
 	
-	DEBUG( 0, __FUNCTION__ "(), Setting DTR\n");
-	arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
+	/* Go back to normal mode */
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
 	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) 
-	{ 
-		DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
-	}
-	set_fs(fs);
-
 	idev->qos.baud_rate.value = 9600;
 }
 
@@ -287,6 +239,9 @@
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");	
 		
 /*
  * Function init_module (void)
diff -urN linux-2.2.3-pre2/drivers/net/irda/Config.in linux-2.2.3-pre3/drivers/net/irda/Config.in
--- linux-2.2.3-pre2/drivers/net/irda/Config.in	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/Config.in	2003-08-15 15:05:26.000000000 -0700
@@ -9,6 +9,7 @@
     dep_tristate '   ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR
     dep_tristate '   ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR
     dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR
+    dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRTTY_SIR
   fi
 fi
 dep_tristate '  NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
diff -urN linux-2.2.3-pre2/drivers/net/irda/esi.c linux-2.2.3-pre3/drivers/net/irda/esi.c
--- linux-2.2.3-pre2/drivers/net/irda/esi.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/esi.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      esi.c
- * Version:       1.1
- * Description:   Driver for the Extended Systems JetEye PC
+ * Version:       1.2
+ * Description:   Driver for the Extended Systems JetEye PC dongle
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Mon Jan 18 11:30:32 1999
+ * Modified at:   Tue Feb  9 15:36:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  esi.c
  *
@@ -71,6 +71,7 @@
 	strcat( idev->description, " <-> esi");
 
 	idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
 
 	MOD_INC_USE_COUNT;
 }
@@ -90,10 +91,9 @@
 {
 	struct irtty_cb *self;
 	struct tty_struct *tty;
-	int arg = TIOCM_OUT2;
+	int dtr, rts;
         struct termios old_termios;
 	int cflag;
-	mm_segment_t fs;
 	
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -116,37 +116,25 @@
 	switch (baud) {
 	case 19200:
 		cflag |= B19200;
-		arg |= TIOCM_DTR;
+		dtr = TRUE;
+		rts = FALSE;
 		break;
 	case 115200:
 		cflag |= B115200;
-		arg |= TIOCM_RTS | TIOCM_DTR;
+		dtr = rts = TRUE;
 		break;
 	case 9600:
 	default:
 		cflag |= B9600;
-		arg |= TIOCM_RTS;
+		dtr = FALSE;
+		rts = TRUE;
 		break;
 	}
-		
+	/* Change speed of serial driver */
 	tty->termios->c_cflag = cflag;
 	tty->driver.set_termios( tty, &old_termios);
 
-	/*
-	 *  The ioctl function, or actually set_modem_info in serial.c
-	 *  expects a pointer to the argument in user space. To hack us
-	 *  around this we use the set_fs function to fool the routines 
-	 *  that check if they are called from user space. We also need 
-	 *  to send a pointer to the argument so get_user() gets happy. 
-	 *  DB.
-	 */
-	fs = get_fs();
-	set_fs( get_ds());
-
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		DEBUG( 0, __FUNCTION__ "(), error setting ESI speed!\n");
-	}
-	set_fs(fs);
+	irtty_set_dtr_rts(tty, dtr, rts);
 }
 
 static void esi_reset( struct irda_device *idev, int unused)
diff -urN linux-2.2.3-pre2/drivers/net/irda/girbil.c linux-2.2.3-pre3/drivers/net/irda/girbil.c
--- linux-2.2.3-pre2/drivers/net/irda/girbil.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/girbil.c	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,276 @@
+/*********************************************************************
+ *                
+ * Filename:      girbil.c
+ * Version:       1.0
+ * Description:   Implementation for the Greenwich GIrBIL dongle
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Feb  6 21:02:33 1999
+ * Modified at:   Tue Feb  9 15:36:36 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     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.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.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 girbil_reset(struct irda_device *dev, int unused);
+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, int baud);
+static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
+
+/* Control register 1 */
+#define GIRBIL_TXEN    0x01 /* Enable transmitter */
+#define GIRBIL_RXEN    0x02 /* Enable receiver */
+#define GIRBIL_ECAN    0x04 /* Cancel self emmited data */
+#define GIRBIL_ECHO    0x08 /* Echo control characters */
+
+/* LED Current Register (0x2) */
+#define GIRBIL_HIGH    0x20
+#define GIRBIL_MEDIUM  0x21
+#define GIRBIL_LOW     0x22
+
+/* Baud register (0x3) */
+#define GIRBIL_2400    0x30
+#define GIRBIL_4800    0x31	
+#define GIRBIL_9600    0x32
+#define GIRBIL_19200   0x33
+#define GIRBIL_38400   0x34	
+#define GIRBIL_57600   0x35	
+#define GIRBIL_115200  0x36
+
+/* Mode register (0x4) */
+#define GIRBIL_IRDA    0x40
+#define GIRBIL_ASK     0x41
+
+/* Control register 2 (0x5) */
+#define GIRBIL_LOAD    0x51 /* Load the new baud rate value */
+
+static struct dongle dongle = {
+	GIRBIL_DONGLE,
+	girbil_open,
+	girbil_close,
+	girbil_reset,
+	girbil_change_speed,
+	girbil_init_qos,
+};
+
+__initfunc(void girbil_init(void))
+{
+	irtty_register_dongle(&dongle);
+}
+
+void girbil_cleanup(void)
+{
+	irtty_unregister_dongle(&dongle);
+}
+
+static void girbil_open(struct irda_device *idev, int type)
+{
+	strcat( idev->description, " <-> girbil");
+
+	idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
+	
+	MOD_INC_USE_COUNT;
+}
+
+static void girbil_close(struct irda_device *dev)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function girbil_change_speed (dev, speed)
+ *
+ *    Set the speed for the Girbil type dongle. Warning, this 
+ *    function must be called with a process context!
+ *
+ */
+static void girbil_change_speed(struct irda_device *idev, int speed)
+{
+	struct irtty_cb *self;
+	struct tty_struct *tty;
+	struct termios old_termios;
+	int cflag;
+	__u8 control[2];
+	
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	self = (struct irtty_cb *) idev->priv;
+	
+	ASSERT(self != NULL, return;); 
+	ASSERT(self->magic == IRTTY_MAGIC, return;);
+	
+	if (!self->tty)
+		return;
+
+	tty = self->tty;
+	
+	old_termios = *(tty->termios);
+	cflag = tty->termios->c_cflag;
+
+	cflag &= ~CBAUD;
+
+	switch (speed) {
+	case 9600:
+	default:
+		cflag |= B9600;
+		control[0] = GIRBIL_9600;
+		break;
+	case 19200:
+		cflag |= B19200;
+		control[0] = GIRBIL_19200;
+		break;
+	case 34800:
+		cflag |= B38400;
+		control[0] = GIRBIL_38400;
+		break;
+	case 57600:
+		cflag |= B57600;
+		control[0] = GIRBIL_57600;
+		break;
+	case 115200:
+		cflag |= B115200;
+		control[0] = GIRBIL_115200;
+		break;
+	}
+	control[1] = GIRBIL_LOAD;
+
+	/* Set DTR and Clear RTS to enter command mode */
+	irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+	/* Write control bytes */
+	if (tty->driver.write)
+		tty->driver.write(self->tty, 0, control, 2);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+	
+	/* Go back to normal mode */
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
+
+	/* Now change the speed of the serial port */
+	tty->termios->c_cflag = cflag;
+	tty->driver.set_termios(tty, &old_termios);	
+}
+
+/*
+ * Function girbil_reset (driver)
+ *
+ *      This function resets the girbil dongle. Warning, this function 
+ *      must be called with a process context!! 
+ *
+ *      Algorithm:
+ *    	  0. set RTS, and wait at least 5 ms 
+ *        1. clear RTS 
+ */
+void girbil_reset(struct irda_device *idev, int unused)
+{
+	struct irtty_cb *self;
+	struct tty_struct *tty;
+	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN /* | GIRBIL_ECAN */;
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	self = (struct irtty_cb *) idev->priv;
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRTTY_MAGIC, return;);
+
+	tty = self->tty;
+	if (!tty)
+		return;
+
+	/* Reset dongle */
+	irtty_set_dtr_rts(tty, TRUE, FALSE);
+
+	/* Sleep at least 5 ms */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+	
+	/* Set DTR and clear RTS to enter command mode */
+	irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+
+	/* Write control byte */
+	if (tty->driver.write)
+		tty->driver.write(self->tty, 0, &control, 1);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+
+	/* Go back to normal mode */
+	irtty_set_dtr_rts(tty, 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 &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
+	
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Girbil module
+ *
+ */
+int init_module(void)
+{
+	girbil_init();
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Girbil module
+ *
+ */
+void cleanup_module(void)
+{
+        girbil_cleanup();
+}
+
+#endif /* MODULE */
diff -urN linux-2.2.3-pre2/drivers/net/irda/irport.c linux-2.2.3-pre3/drivers/net/irda/irport.c
--- linux-2.2.3-pre2/drivers/net/irda/irport.c	1999-01-24 21:55:04.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/irport.c	2003-08-15 15:05:26.000000000 -0700
@@ -96,7 +96,7 @@
 #ifdef MODULE
 static void irport_cleanup(void)
 {
-	int i;
+/* 	int i; */
 
         DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -303,7 +303,6 @@
 int irport_hard_xmit( struct sk_buff *skb, struct device *dev)
 {
 	struct irda_device *idev;
-	int xbofs;
 	int actual;
 
 	DEBUG( 4, __FUNCTION__ "()\n");
diff -urN linux-2.2.3-pre2/drivers/net/irda/irtty.c linux-2.2.3-pre3/drivers/net/irda/irtty.c
--- linux-2.2.3-pre2/drivers/net/irda/irtty.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/irtty.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irtty.c
- * Version:       1.0
+ * Version:       1.1
  * Description:   IrDA line discipline implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Mon Jan 18 15:32:03 1999
+ * Modified at:   Tue Feb  9 13:08:25 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>
@@ -206,6 +206,7 @@
 	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200;
 	self->idev.qos.min_turn_time.bits = 0x03;
+	self->idev.flags = IFF_SIR | IFF_PIO;
 	irda_qos_bits_to_value( &self->idev.qos);
 
 	/* Specify which buffer allocation policy we need */
@@ -272,8 +273,6 @@
 		kfree( self);
 
  	MOD_DEC_USE_COUNT;
-
-	DEBUG( 4, "IrTTY: close() -->\n");
 }
 
 /* 
@@ -289,6 +288,8 @@
 	struct irtty_cb *self;
 	int cflag;
 
+	DEBUG(4,__FUNCTION__ "(), <%ld>\n", jiffies); 
+
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
 
@@ -360,10 +361,15 @@
 		DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n");
 		request_module( "tekram");
 		break;
-	case ACTISYS_DONGLE:
+	case ACTISYS_DONGLE:     /* FALLTHROUGH */
+	case ACTISYS_PLUS_DONGLE:
 		DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n");
 		request_module( "actisys");
 		break;
+	case GIRBIL_DONGLE:
+		DEBUG( 0, __FUNCTION__ "(), GIrBIL dongle!\n");
+		request_module( "girbil");
+		break;
 	default:
 		DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n");
 		return;
@@ -373,8 +379,7 @@
 
 	node = hashbin_find( dongles, type, NULL);
 	if ( !node) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to find requested dongle\n");
+		DEBUG(0, __FUNCTION__ "(), Unable to find requested dongle\n");
 		return;
 	}
 	self->dongle_q = node;
@@ -401,8 +406,7 @@
  *     The Swiss army knife of system calls :-)
  *
  */
-static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd, 
-			void *arg) 
+static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
 {
 	struct irtty_cb *self;
 	int err = 0;
@@ -444,8 +448,8 @@
  *    been received, which can now be decapsulated and delivered for
  *    further processing 
  */
-static void irtty_receive_buf( struct tty_struct *tty, const unsigned 
-			       char *cp, char *fp, int count) 
+static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+			      char *fp, int count) 
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
@@ -464,11 +468,8 @@
  			cp++;
  			continue;
  		}
-		/*
-		 *  Unwrap and destuff one byte
-		 */
+		/* Unwrap and destuff one byte */
 		async_unwrap_char( &self->idev, *cp++);
-		/* self->rx_over_errors++; */
 	}
 }
 
@@ -478,7 +479,7 @@
  *    Transmit skb
  *
  */
-static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
+static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct irtty_cb *self;
 	struct irda_device *idev;
@@ -487,43 +488,40 @@
 	ASSERT( dev != NULL, return 0;);
 	ASSERT( skb != NULL, return 0;);
 
-	if ( dev->tbusy) {
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-		
-		return -EBUSY;
-	}
-
 	idev = (struct irda_device *) dev->priv;
 
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(idev != NULL, return 0;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 	
 	self = (struct irtty_cb *) idev->priv;
 
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRTTY_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
 
 	/* Lock transmit buffer */
-	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
-		return 0;
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
 
         /*  
 	 *  Transfer 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); 
+        idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
+					   idev->tx_buff.truesize); 
 
 	self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 
 	dev->trans_start = jiffies;
 
 	if ( self->tty->driver.write)
-		actual = self->tty->driver.write( self->tty, 0, 
-						  idev->tx_buff.data, 
-						  idev->tx_buff.len);
+		actual = self->tty->driver.write(self->tty, 0, 
+						 idev->tx_buff.data, 
+						 idev->tx_buff.len);
 
 	idev->tx_buff.offset = actual;
 	idev->tx_buff.head = idev->tx_buff.data + actual;
+
+	idev->stats.tx_packets++;
+	idev->stats.tx_bytes += idev->tx_buff.len;
 #if 0
 	/* 
 	 *  Did we transmit the whole frame? Commented out for now since
@@ -535,8 +533,7 @@
  		irda_unlock( &self->tbusy);
  	}
 #endif
-
-	dev_kfree_skb( skb);
+	dev_kfree_skb(skb);
 
 	return 0;
 }
@@ -587,8 +584,6 @@
 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
 		idev->netdev.tbusy = 0; /* Unlock */
-		idev->stats.tx_packets++;
-		idev->stats.tx_bytes += idev->tx_buff.len;
 
 		/* Tell network layer that we want more frames */
 		mark_bh( NET_BH);
@@ -602,8 +597,6 @@
 	actual = tty->driver.write( tty, 0, idev->tx_buff.head, count);
 	idev->tx_buff.offset += actual;
 	idev->tx_buff.head += actual;
-
-	DEBUG( 4, "actual=%d, sent %d\n", actual, count);
 }
 
 /*
@@ -648,8 +641,7 @@
         }
 	
 	/* Make new IrDA dongle */
-        new = (struct dongle_q *) kmalloc (sizeof (struct dongle_q), 
-					      GFP_KERNEL);
+        new = (struct dongle_q *)kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
         if (new == NULL) {
                 return 1;
 		
@@ -675,6 +667,35 @@
 	kfree( node);
 }
 
+
+void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts)
+{
+	mm_segment_t fs;
+	int arg = TIOCM_OUT2;
+
+	if (rts)
+		arg |= TIOCM_RTS;
+	if (dtr)
+		arg |= TIOCM_DTR;
+
+	/*
+	 *  The ioctl() function, or actually set_modem_info() in serial.c
+	 *  expects a pointer to the argument in user space. To hack us
+	 *  around this, we use the set_fs() function to fool the routines 
+	 *  that check if they are called from user space. We also need 
+	 *  to send a pointer to the argument so get_user() gets happy. DB.
+	 */
+
+	fs = get_fs();
+	set_fs(get_ds());
+	
+	if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
+		DEBUG(0, __FUNCTION__ "(), error!\n");
+	}
+	set_fs(fs);
+}
+
+
 static int irtty_net_init( struct device *dev)
 {
 	/* Set up to be a normal IrDA network device driver */
@@ -715,6 +736,9 @@
 
 #ifdef MODULE
 
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("IrDA TTY device driver");
+
 /*
  * Function init_module (void)
  *
diff -urN linux-2.2.3-pre2/drivers/net/irda/Makefile linux-2.2.3-pre3/drivers/net/irda/Makefile
--- linux-2.2.3-pre2/drivers/net/irda/Makefile	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/Makefile	2003-08-15 15:05:26.000000000 -0700
@@ -68,6 +68,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_GIRBIL_DONGLE),y)
+L_OBJS += girbil.o
+else
+  ifeq ($(CONFIG_GIRBIL_DONGLE),m)
+  M_OBJS += girbil.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 clean:
diff -urN linux-2.2.3-pre2/drivers/net/irda/pc87108.c linux-2.2.3-pre3/drivers/net/irda/pc87108.c
--- linux-2.2.3-pre2/drivers/net/irda/pc87108.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/pc87108.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Mon Dec 28 08:46:16 1998
+ * Modified at:   Tue Feb  9 13:29:40 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
@@ -50,7 +50,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
@@ -100,7 +99,9 @@
 /* Some prototypes */
 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);
+#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); 
@@ -221,6 +222,8 @@
 	idev->qos.min_turn_time.bits = 0x07;
 	irda_qos_bits_to_value( &idev->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;
@@ -250,6 +253,7 @@
 	return 0;
 }
 
+#ifdef MODULE
 /*
  * Function pc87108_close (idev)
  *
@@ -276,6 +280,7 @@
 
 	return 0;
 }
+#endif /* MODULE */
 
 /*
  * Function pc87108_probe (iobase, board_addr, irq, dma)
@@ -720,12 +725,6 @@
 	iobase = idev->io.iobase;
 
 	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
-	if ( dev->tbusy) {
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-			
-		return -EBUSY;
-	}
 	
 	/* Lock transmit buffer */
 	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
diff -urN linux-2.2.3-pre2/drivers/net/irda/tekram.c linux-2.2.3-pre3/drivers/net/irda/tekram.c
--- linux-2.2.3-pre2/drivers/net/irda/tekram.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/tekram.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      tekram.c
- * Version:       0.4
+ * Version:       0.5
  * Description:   Implementation of the Tekram IrMate IR-210B dongle
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Jan 18 11:30:38 1999
+ * Modified at:   Tue Feb  9 15:36:55 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -63,9 +63,12 @@
 	irtty_unregister_dongle( &dongle);
 }
 
-static void tekram_open( struct irda_device *dev, int type)
+static void tekram_open( struct irda_device *idev, int type)
 {
-	strcat( dev->name, " <-> tekram");
+	strcat(idev->description, " <-> tekram");
+
+	idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
 	
 	MOD_INC_USE_COUNT;
 }
@@ -96,11 +99,8 @@
 	struct irtty_cb *self;
 	struct tty_struct *tty;
 	struct termios old_termios;
-	int arg = 0;
 	int cflag;
 	__u8 byte;
-	int actual;
-	mm_segment_t fs;
 	
 	DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -147,44 +147,22 @@
 	}
 
 	/* Set DTR, Clear RTS */
-	DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n");
-	arg = TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                                (unsigned long) &arg)) { 
-		DEBUG( 0, "error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+	irtty_set_dtr_rts(tty, TRUE, FALSE);
 	
 	/* Wait at least 7us */
 	udelay( 7);
 
-	DEBUG( 0, __FUNCTION__ "(), Writing control byte\n");
 	/* Write control byte */
 	if ( tty->driver.write)
-		actual = tty->driver.write( self->tty, 0, &byte, 1);
+		tty->driver.write( self->tty, 0, &byte, 1);
 	
 	/* Wait at least 100 ms */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout( 10);
         
 	/* Set DTR, Set RTS */
-	DEBUG( 0, __FUNCTION__ "(), Setting DTR, Setting RTS\n");
-	arg = TIOCM_DTR | TIOCM_RTS | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) { 
-		DEBUG( 0, "error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
 
-	DEBUG( 0, __FUNCTION__ "(), Setting new speed on serial port\n");
 	/* Now change the speed of the serial port */
 	tty->termios->c_cflag = cflag;
 	tty->driver.set_termios( tty, &old_termios);	
@@ -208,8 +186,6 @@
 {
 	struct irtty_cb *self;
 	struct tty_struct *tty;
-	int arg = 0;
-	mm_segment_t fs;
 
 	DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -225,51 +201,22 @@
 	if ( !tty)
 		return;
 
-	DEBUG( 0, __FUNCTION__ "(), Power off dongle\n");
-	arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) 
-	{ 
-		DEBUG(0, "error setting ESI speed!\n");
-	}
-	set_fs(fs);
+	/* Power off dongle */
+	irtty_set_dtr_rts(tty, FALSE, FALSE);
 
 	/* Sleep 50 ms */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(5);
-	
-	DEBUG( 0, __FUNCTION__ "(), Set DTR, clear RTS\n");
-	/* Set DTR, clear RTS */
-	arg = TIOCM_DTR | TIOCM_OUT2;
-	
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-				(unsigned long) &arg)) { 
-		DEBUG( 0, "Error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+
+	/* Clear DTR, Set RTS */
+	irtty_set_dtr_rts(tty, FALSE, TRUE); 
 
 	/* Should sleep 1 ms, but 10-20 should not do any harm */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(2);
 
-	DEBUG( 0, __FUNCTION__ "(), STATE3\n");
-	/* Clear DTR, clear RTS */
-	arg = TIOCM_OUT2;
-
-	fs = get_fs();
-	set_fs( get_ds());
-	
-	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		DEBUG( 0, "error setting Tekram speed!\n");
-	}
-	set_fs(fs);
+	/* Set DTR, Set RTS */
+	irtty_set_dtr_rts(tty, TRUE, TRUE);
 	
 	/* Finished! */
 }
@@ -287,6 +234,9 @@
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
 		
 /*
  * Function init_module (void)
@@ -311,4 +261,4 @@
         tekram_cleanup();
 }
 
-#endif
+#endif /* MODULE */
diff -urN linux-2.2.3-pre2/drivers/net/irda/uircc.c linux-2.2.3-pre3/drivers/net/irda/uircc.c
--- linux-2.2.3-pre2/drivers/net/irda/uircc.c	1999-01-24 21:55:04.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/uircc.c	2003-08-15 15:05:26.000000000 -0700
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Dec 26 10:59:03 1998
- * Modified at:   Tue Jan 19 23:54:04 1999
+ * Modified at:   Tue Feb  9 13:30:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -196,6 +196,8 @@
 
 	idev->qos.min_turn_time.bits = 0x07;
 	irda_qos_bits_to_value( &idev->qos);
+
+	idev->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
 	
 	/* Specify which buffer allocation policy we need */
 	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
@@ -271,9 +273,11 @@
 static int uircc_probe( int iobase, int iobase2, int irq, int dma) 
 {
 	int version;
+#if 0
 	int probe_irq=0;
 	unsigned long mask;
 	int i;
+#endif
 	
 	DEBUG( 0, __FUNCTION__ "()\n");
 
@@ -442,20 +446,12 @@
 	DEBUG(0, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
 
 	/* Use irport for SIR speeds */
-	if ( idev->io.baudrate <= 115200) {
-		return irport_hard_xmit( skb, dev);
-	}
-
-	if ( dev->tbusy) {
-		__u8 sr3;
-
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-			
-		return -EBUSY;
+	if (idev->io.baudrate <= 115200) {
+		return irport_hard_xmit(skb, dev);
 	}
 	
 	/* Lock transmit buffer */
-	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
 
 	memcpy( idev->tx_buff.data, skb->data, skb->len);
diff -urN linux-2.2.3-pre2/drivers/net/irda/w83977af_ir.c linux-2.2.3-pre3/drivers/net/irda/w83977af_ir.c
--- linux-2.2.3-pre2/drivers/net/irda/w83977af_ir.c	1998-12-18 08:06:39.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/irda/w83977af_ir.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Mon Dec 14 21:51:53 1998
+ * Modified at:   Tue Feb  9 13:30:35 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Corel Computer Corp.
@@ -204,6 +204,8 @@
 	/* The HP HDLS-1100 needs 1 ms according to the specs */
 	idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
 	irda_qos_bits_to_value( &idev->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;
@@ -468,12 +470,6 @@
 	iobase = idev->io.iobase;
 
 	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
-	if ( dev->tbusy) {
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-
-		return -EBUSY;
-	}
 	
 	/* Lock transmit buffer */
 	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
diff -urN linux-2.2.3-pre2/drivers/net/Makefile linux-2.2.3-pre3/drivers/net/Makefile
--- linux-2.2.3-pre2/drivers/net/Makefile	1999-01-14 22:58:47.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/Makefile	2003-08-15 15:05:26.000000000 -0700
@@ -1046,6 +1046,7 @@
 
 ifeq ($(CONFIG_IRDA),y)
 SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
 else
   ifeq ($(CONFIG_IRDA),m)
   MOD_SUB_DIRS += irda
diff -urN linux-2.2.3-pre2/drivers/net/ne.c linux-2.2.3-pre3/drivers/net/ne.c
--- linux-2.2.3-pre2/drivers/net/ne.c	1998-12-16 13:35:49.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/ne.c	2003-08-15 15:05:26.000000000 -0700
@@ -105,6 +105,7 @@
     {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
     {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
     {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
+    {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */    
     {0,}
 };
 #endif
diff -urN linux-2.2.3-pre2/drivers/net/plip.c linux-2.2.3-pre3/drivers/net/plip.c
--- linux-2.2.3-pre2/drivers/net/plip.c	1999-01-04 16:06:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/net/plip.c	2003-08-15 15:05:26.000000000 -0700
@@ -1217,7 +1217,7 @@
 plip_searchfor(int list[], int a)
 {
 	int i;
-	for (i = 0; i < 3 && list[i] != -1; i++) {
+	for (i = 0; i < PLIP_MAX && list[i] != -1; i++) {
 		if (list[i] == a) return 1;
 	}
 	return 0;
@@ -1240,7 +1240,7 @@
 	/* If the user feeds parameters, use them */
 	while (pb) {
 		if ((parport[0] == -1 && (!timid || !pb->devices)) || 
-		    plip_searchfor(parport, i)) {
+		    plip_searchfor(parport, pb->number)) {
 			if (i == PLIP_MAX) {
 				printk(KERN_ERR "plip: too many devices\n");
 				break;
diff -urN linux-2.2.3-pre2/drivers/net/sk_g16.c linux-2.2.3-pre3/drivers/net/sk_g16.c
--- linux-2.2.3-pre2/drivers/net/sk_g16.c	1998-07-26 23:35:56.000000000 -0700
+++ linux-2.2.3-pre3/drivers/net/sk_g16.c	2003-08-15 15:05:26.000000000 -0700
@@ -733,7 +733,7 @@
     SK_print_pos(dev, "POS registers after ROM, RAM config");
 #endif
 
-    board = (SK_RAM *) rom_addr; 
+    board = (SK_RAM *) bus_to_virt(rom_addr);
 
     /* Read in station address */
     for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
diff -urN linux-2.2.3-pre2/drivers/pci/pci.c linux-2.2.3-pre3/drivers/pci/pci.c
--- linux-2.2.3-pre2/drivers/pci/pci.c	1999-01-20 10:18:53.000000000 -0800
+++ linux-2.2.3-pre3/drivers/pci/pci.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*
- *	$Id: pci.c,v 1.90 1998/09/05 12:39:39 mj Exp $
+ *	$Id: pci.c,v 1.91 1999/01/21 13:34:01 davem Exp $
  *
  *	PCI Bus Services, see include/linux/pci.h for further explanation.
  *
  *	Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
  *	David Mosberger-Tang
  *
- *	Copyright 1997 -- 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *	Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <linux/config.h>
@@ -28,9 +28,6 @@
 #endif
 
 struct pci_bus pci_root;
-#ifdef CONFIG_VISWS
-struct pci_bus pci_other;
-#endif
 struct pci_dev *pci_devices = NULL;
 static struct pci_dev **pci_last_dev_p = &pci_devices;
 static int pci_reverse __initdata = 0;
@@ -371,6 +368,18 @@
 	return max;
 }
 
+struct pci_bus * __init pci_scan_peer_bridge(int bus)
+{
+	struct pci_bus *b;
+
+	b = kmalloc(sizeof(*b), GFP_KERNEL);
+	memset(b, 0, sizeof(*b));
+	b->next = pci_root.next;
+	pci_root.next = b;
+	b->number = b->secondary = bus;
+	b->subordinate = pci_scan_bus(b);
+	return b;
+}
 
 __initfunc(void pci_init(void))
 {
@@ -385,11 +394,6 @@
 
 	memset(&pci_root, 0, sizeof(pci_root));
 	pci_root.subordinate = pci_scan_bus(&pci_root);
-#ifdef CONFIG_VISWS
-	pci_other.number = 1; /* XXX unless bridge(s) on pci_root */
-	pci_other.subordinate = pci_scan_bus(&pci_other);
-	pci_root.next = &pci_other;
-#endif
 
 	/* give BIOS a chance to apply platform specific fixes: */
 	pcibios_fixup();
@@ -403,7 +407,6 @@
 #endif
 }
 
-
 __initfunc(void pci_setup (char *str, int *ints))
 {
 	while (str) {
diff -urN linux-2.2.3-pre2/drivers/sbus/char/flash.c linux-2.2.3-pre3/drivers/sbus/char/flash.c
--- linux-2.2.3-pre2/drivers/sbus/char/flash.c	1998-10-04 10:22:44.000000000 -0700
+++ linux-2.2.3-pre3/drivers/sbus/char/flash.c	2003-08-15 15:05:26.000000000 -0700
@@ -72,8 +72,6 @@
 	if (remap_page_range(vma->vm_start, addr, size, vma->vm_page_prot))
 		return -EAGAIN;
 		
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -urN linux-2.2.3-pre2/drivers/sbus/char/vfc_dev.c linux-2.2.3-pre3/drivers/sbus/char/vfc_dev.c
--- linux-2.2.3-pre2/drivers/sbus/char/vfc_dev.c	1998-10-27 09:52:21.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sbus/char/vfc_dev.c	2003-08-15 15:05:26.000000000 -0700
@@ -582,8 +582,6 @@
 	if(ret)
 		return -EAGAIN;
 
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -urN linux-2.2.3-pre2/drivers/scsi/ChangeLog.ncr53c8xx linux-2.2.3-pre3/drivers/scsi/ChangeLog.ncr53c8xx
--- linux-2.2.3-pre2/drivers/scsi/ChangeLog.ncr53c8xx	1999-01-16 16:57:16.000000000 -0800
+++ linux-2.2.3-pre3/drivers/scsi/ChangeLog.ncr53c8xx	2003-08-15 15:05:26.000000000 -0700
@@ -1,4 +1,26 @@
-Sat Jan 16  17:30 1998 Gerard Roudier (groudier@club-internet.fr)
+Sat Mar 6  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1h
+	- Fix some oooold bug that hangs the bus if a device rejects a 
+	  negotiation. Btw, the corresponding stuff also needed some cleanup 
+	  and thus the change is a bit larger than it could have been.
+	- Still some typo that made compilation fail for 64 bit (trivial fix).
+
+Sun Feb  14:00 1999 Gerard Roudier (groudier@club-internet.fr)
+	* revision 3.1g
+	- Deal correctly with 64 bit PCI address registers on Linux 2.2.
+	  Pointed out by Leonard Zubkoff.
+	- Allow to tune request_irq() flags from the boot command line using 
+	  ncr53c8xx=irqm:??, as follows:
+	  a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
+	  b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
+	  By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+	  Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
+	  a 53C8XX adapter and a network board.
+	- Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately 
+	  harmless.
+	- Negotiate SYNC data transfers with CCS devices.
+
+Sat Jan 16  17:30 1999 Gerard Roudier (groudier@club-internet.fr)
 	* revision 3.1f
 	- Some PCI fix-ups not needed any more for PPC (from Cort).
 	- Cache line size set to 16 DWORDS for Sparc   (from DSM).
diff -urN linux-2.2.3-pre2/drivers/scsi/ncr53c8xx.c linux-2.2.3-pre3/drivers/scsi/ncr53c8xx.c
--- linux-2.2.3-pre2/drivers/scsi/ncr53c8xx.c	1999-02-14 23:17:31.000000000 -0800
+++ linux-2.2.3-pre3/drivers/scsi/ncr53c8xx.c	2003-08-15 15:05:26.000000000 -0700
@@ -73,7 +73,7 @@
 */
 
 /*
-**	January 16 1998, version 3.1f
+**	March 6 1999, version 3.1h
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -2081,6 +2081,7 @@
 	ncrcmd  msg_ext_3	[ 10];
 	ncrcmd	msg_sdtr	[ 14];
 	ncrcmd	send_sdtr	[  7];
+	ncrcmd	nego_bad_phase	[  4];
 	ncrcmd	msg_out_abort	[ 10];
 	ncrcmd  hdata_in	[MAX_SCATTERH * 4];
 	ncrcmd  hdata_in2	[  2];
@@ -3185,16 +3186,15 @@
 	/*
 	**	If a negotiation was in progress,
 	**	negotiation failed.
+	**	Otherwise, let the C code print 
+	**	some message.
 	*/
 	SCR_FROM_REG (HS_REG),
 		0,
-	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
-		SIR_NEGO_FAILED,
-	/*
-	**	else make host log this message
-	*/
 	SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)),
 		SIR_REJECT_RECEIVED,
+	SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
+		SIR_NEGO_FAILED,
 	SCR_JUMP,
 		PADDR (clrack),
 
@@ -3304,10 +3304,9 @@
 		0,
 	SCR_CLR (SCR_ACK),
 		0,
+	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+		PADDRH (nego_bad_phase),
 
-/* CHECK THE SOURCE FOR 'send_wdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
-	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
-		SIR_NEGO_PROTO,
 }/*-------------------------< SEND_WDTR >----------------*/,{
 	/*
 	**	Send the M_X_WIDE_REQ
@@ -3360,10 +3359,9 @@
 		0,
 	SCR_CLR (SCR_ACK),
 		0,
+	SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+		PADDRH (nego_bad_phase),
 
-/* CHECK THE SOURCE FOR 'send_sdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
-	SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
-		SIR_NEGO_PROTO,
 }/*-------------------------< SEND_SDTR >-------------*/,{
 	/*
 	**	Send the M_X_SYNC_REQ
@@ -3376,6 +3374,12 @@
 	SCR_JUMP,
 		PADDR (msg_out_done),
 
+}/*-------------------------< NEGO_BAD_PHASE >------------*/,{
+	SCR_INT,
+		SIR_NEGO_PROTO,
+	SCR_JUMP,
+		PADDR (dispatch),
+
 }/*-------------------------< MSG_OUT_ABORT >-------------*/,{
 	/*
 	**	After ABORT message,
@@ -4274,7 +4278,7 @@
 	/*
 	**	Set irq mode.
 	*/
-	switch(driver_setup.irqm) {
+	switch(driver_setup.irqm & 3) {
 	case 2:
 		np->rv_dcntl	|= IRQM;
 		break;
@@ -4665,21 +4669,11 @@
 	/*
 	**	Install the interrupt handler.
 	*/
-#ifdef	SCSI_NCR_SHARE_IRQ
-#define	NCR_SA_INTERRUPT_FLAGS (SA_INTERRUPT | SA_SHIRQ)
-	if (bootverbose > 1)
-#ifdef __sparc__
-		printk(KERN_INFO "%s: requesting shared irq %s (dev_id=0x%lx)\n",
-		        ncr_name(np), __irq_itoa(device->slot.irq), (u_long) np);
-#else
-		printk(KERN_INFO "%s: requesting shared irq %d (dev_id=0x%lx)\n",
-		        ncr_name(np), device->slot.irq, (u_long) np);
-#endif
-#else
-#define	NCR_SA_INTERRUPT_FLAGS SA_INTERRUPT
-#endif
+
 	if (request_irq(device->slot.irq, ncr53c8xx_intr,
-			NCR_SA_INTERRUPT_FLAGS, "ncr53c8xx", np)) {
+			((driver_setup.irqm & 0x10) ? 0 : SA_SHIRQ) |
+			((driver_setup.irqm & 0x20) ? 0 : SA_INTERRUPT),
+			"ncr53c8xx", np)) {
 #ifdef __sparc__
 		printk(KERN_ERR "%s: request irq %s failure\n",
 			ncr_name(np), __irq_itoa(device->slot.irq));
@@ -4689,6 +4683,7 @@
 #endif
 		goto attach_error;
 	}
+
 	np->irq = device->slot.irq;
 
 	/*
@@ -4956,9 +4951,8 @@
 				nego = NS_SYNC;
 			} else {
 				tp->period  =0xffff;
-				tp->sval = 0xe0;
 				PRINT_TARGET(np, cmd->target);
-				printk ("SYNC transfers not supported.\n");
+				printk ("device did not report SYNC.\n");
 			};
 		};
 
@@ -5824,7 +5818,7 @@
 		**	announced capabilities (we need the 1rst 7 bytes).
 		*/
 		if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) &&
-		    cmd->cmnd[4] >= 7) {
+		    cmd->cmnd[4] >= 7 && !cmd->use_sg) {
 			ncr_setup_lcb (np, cmd->target, cmd->lun,
 				       (char *) cmd->request_buffer);
 		}
@@ -7051,7 +7045,7 @@
 	OUTONB (nc_ctest3, CLF);
 
 	if ((sist & (SGE)) ||
-		(dstat & (MDPE|BF|ABORT|IID))) {
+		(dstat & (MDPE|BF|ABRT|IID))) {
 		ncr_start_reset(np);
 		return;
 	};
@@ -7528,7 +7522,7 @@
 		}
 		else if	(dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) ||
 			 dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) {
-			nxtdsp = dsp - 8; /* Should raise SIR_NEGO_PROTO */
+			nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase);
 		}
 		break;
 #if 0
@@ -7882,9 +7876,7 @@
 		np->msgin [0] = M_NOOP;
 		np->msgout[0] = M_NOOP;
 		cp->nego_status = 0;
-		OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch));
-		return;
-/*		break;	*/
+		break;
 
 	case SIR_NEGO_SYNC:
 		/*
@@ -8657,10 +8649,15 @@
 	**	Evaluate trustable target/unit capabilities.
 	**	We only believe device version >= SCSI-2 that 
 	**	use appropriate response data format (2).
+	**	But it seems that some CCS devices also 
+	**	support SYNC and I donnot want to frustrate 
+	**	anybody. ;-)
 	*/
 	inq_byte7 = 0;
-	if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
+	if	((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
 		inq_byte7 = inq_data[7];
+	else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1)
+		inq_byte7 = INQ7_SYNC;
 
 	/*
 	**	Throw away announced LUN capabilities if we are told 
@@ -9586,6 +9583,50 @@
 }
 
 /*
+**   Generically read a base address from the PCI configuration space.
+**   Return the offset immediately after the base address that has 
+**   been read. Btw, we blindly assume that the high 32 bits of 64 bit 
+**   base addresses are set to zero on 32 bit architectures.
+**
+*/
+#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
+__initfunc(
+static int 
+pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
+)
+{
+	u_int32 tmp;
+
+	pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+	*base = tmp;
+	offset += sizeof(u_int32);
+	if ((tmp & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+		pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+		*base |= (((u_long)tmp) << 32);
+#endif
+		offset += sizeof(u_int32);
+	}
+	return offset;
+}
+#else	/* LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) */
+__initfunc(
+static int 
+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+)
+{
+	*base = pdev->base_address[index++];
+	if ((*base & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+		*base |= (((u_long)pdev->base_address[index]) << 32);
+#endif
+		++index;
+	}
+	return index;
+}
+#endif
+
+/*
 **   Read and check the PCI configuration for any detected NCR 
 **   boards and save data for attaching after all boards have 
 **   been detected.
@@ -9601,61 +9642,46 @@
 	uchar revision;
 #if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
 	struct pci_dev *pdev;
-	ulong base, base_2, io_port; 
 	uint irq;
 #else
 	uchar irq;
-	uint base, base_2, io_port; 
 #endif
+	ulong base, base_2, io_port; 
 	int i;
-
 #ifdef SCSI_NCR_NVRAM_SUPPORT
 	ncr_nvram *nvram = device->nvram;
 #endif
 	ncr_chip *chip;
 
 	/*
-	 * Read info from the PCI config space.
-	 * pcibios_read_config_xxx() functions are assumed to be used for 
-	 * successfully detected PCI devices.
-	 * Expecting error conditions from them is just paranoia,
-	 * thus void cast.
-	 */
-	(void) pcibios_read_config_word(bus, device_fn,
-					PCI_VENDOR_ID, &vendor_id);
-	(void) pcibios_read_config_word(bus, device_fn,
-					PCI_DEVICE_ID, &device_id);
-	(void) pcibios_read_config_word(bus, device_fn,
-					PCI_COMMAND, &command);
+	**    Read info from the PCI config space.
+	**    pcibios_read_config_xxx() functions are assumed to be used for 
+	**    successfully detected PCI devices.
+	*/
 #if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
 	pdev = pci_find_slot(bus, device_fn);
-	io_port = pdev->base_address[0];
-	base = pdev->base_address[1];
-	base_2 = pdev->base_address[2];
+	vendor_id = pdev->vendor;
+	device_id = pdev->device;
 	irq = pdev->irq;
-	if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
-		base_2 = pdev->base_address[3];
-#else
-	(void) pcibios_read_config_dword(bus, device_fn,
-					PCI_BASE_ADDRESS_0, &io_port);	
-	(void) pcibios_read_config_dword(bus, device_fn,
-					PCI_BASE_ADDRESS_1, &base);
-	(void) pcibios_read_config_dword(bus, device_fn,
-					PCI_BASE_ADDRESS_2, &base_2);
-
-	/* Handle 64bit base addresses for 53C896. */
-	if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
-		(void) pcibios_read_config_dword(bus, device_fn,
-						 PCI_BASE_ADDRESS_3, &base_2);
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_INTERRUPT_LINE, &irq);
-#endif
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_CLASS_REVISION,&revision);	
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_CACHE_LINE_SIZE, &cache_line_size);
-	(void) pcibios_read_config_byte(bus, device_fn,
-					PCI_LATENCY_TIMER, &latency_timer);
+	i =	0;
+	i =	pci_get_base_address(pdev, i, &io_port);
+	i =	pci_get_base_address(pdev, i, &base);
+	(void)	pci_get_base_address(pdev, i, &base_2);
+#else
+	pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id);
+	pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id);
+	pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq);
+	i =	PCI_BASE_ADDRESS_0;
+	i =	pci_read_base_address(bus, device_fn, i, &io_port);
+	i =	pci_read_base_address(bus, device_fn, i, &base);
+	(void)	pci_read_base_address(bus, device_fn, i, &base_2);
+#endif
+	pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+	pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION, &revision);
+	pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE,
+				 &cache_line_size);
+	pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER,
+				 &latency_timer);
 
 	/*
 	 *	Check if the chip is supported
diff -urN linux-2.2.3-pre2/drivers/scsi/ncr53c8xx.h linux-2.2.3-pre3/drivers/scsi/ncr53c8xx.h
--- linux-2.2.3-pre2/drivers/scsi/ncr53c8xx.h	1999-02-22 14:51:03.000000000 -0800
+++ linux-2.2.3-pre3/drivers/scsi/ncr53c8xx.h	2003-08-15 15:05:26.000000000 -0700
@@ -45,7 +45,7 @@
 /*
 **	Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.1f"
+#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 3.1h"
 
 /*
 **	Check supported Linux versions
@@ -69,7 +69,6 @@
 **	These options are not tunable from 'make config'
 */
 #define	SCSI_NCR_PROC_INFO_SUPPORT
-#define SCSI_NCR_SHARE_IRQ
 
 /*
 **	If you want a driver as small as possible, donnot define the 
diff -urN linux-2.2.3-pre2/drivers/scsi/README.ncr53c8xx linux-2.2.3-pre3/drivers/scsi/README.ncr53c8xx
--- linux-2.2.3-pre2/drivers/scsi/README.ncr53c8xx	1999-01-07 09:21:53.000000000 -0800
+++ linux-2.2.3-pre3/drivers/scsi/README.ncr53c8xx	2003-08-15 15:05:26.000000000 -0700
@@ -4,7 +4,7 @@
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-22 November 1998
+14 February 1999
 ===============================================================================
 
 1.  Introduction
@@ -39,6 +39,7 @@
       14.2 Device names change when another controller is added
       14.3 Using only 8 bit devices with a WIDE SCSI controller.
       14.4 Possible data corruption during a Memory Write and Invalidate
+      14.5 IRQ sharing problems
 15. SCSI problem troubleshooting
 16. Synchonous transfer negotiation tables
       16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers
@@ -669,6 +670,10 @@
     irqm:0	always open drain
     irqm:1	same as initial settings (assumed BIOS settings)
     irqm:2	always totem pole
+    irqm:0x10	driver will not use SA_SHIRQ flag when requesting irq
+    irqm:0x20	driver will not use SA_INTERRUPT flag when requesting irq
+
+    (Bits 0x10 and 0x20 can be combined with hardware irq mode option)
 
 Reverse probe
     revprob:n   probe chip ids from the PCI configuration in this order:
@@ -1027,7 +1032,25 @@
 may only be needed under Linux when a scatter/gather list is not used and 
 when the SCSI DATA IN phase is reentered after a phase mismatch.
 
- 
+14.5 IRQ sharing problems
+
+When an IRQ is shared by devices that are handled by different drivers, it 
+may happen that one driver complains about the request of the IRQ having 
+failed. This may be due to one driver having requested the IRQ using the 
+SA_INTERRUPT flag but some other having requested the same IRQ without this 
+flag, or to one driver not having requested the IRQ with the SA_SHIRQ flag.
+
+By default, the ncr53c8xx driver requests IRQs with both the SA_INTERRUPT 
+and the SA_SHIRQ flag, but you can disable use of SA_INTERRUPT flags from 
+the boot command line by using the following option:
+
+                      ncr53c8xx=irqm:0x20
+
+If this does not fix the problem, then you may want to check how all other 
+drivers are requesting the IRQ and report the problem. Note that if at least 
+a single driver does not request the IRQ with the SA_SHIRQ flag (share IRQ), 
+then the request of the IRQ obviously will not succeed for all the drivers.
+
 15. SCSI problem troubleshooting
 
 Most SCSI problems are due to a non conformant SCSI bus or to buggy
diff -urN linux-2.2.3-pre2/drivers/scsi/README.st linux-2.2.3-pre3/drivers/scsi/README.st
--- linux-2.2.3-pre2/drivers/scsi/README.st	1998-09-06 09:48:30.000000000 -0700
+++ linux-2.2.3-pre3/drivers/scsi/README.st	2003-08-15 15:05:26.000000000 -0700
@@ -2,7 +2,7 @@
 The driver is currently maintained by Kai M{kisara (email
 Kai.Makisara@metla.fi)
 
-Last modified: Sun Sep  6 10:03:47 1998 by makisara@home
+Last modified: Sun Jan 17 10:57:41 1999 by makisara@home
 
 
 BASICS
@@ -60,11 +60,20 @@
 alternative is to make a small script that uses mt to set the defaults
 tailored to the system.
 
-
 The driver supports fixed and variable block size (within buffer
 limits). Both the auto-rewind (minor equals device number) and
 non-rewind devices (minor is 128 + device number) are implemented.
 
+In variable block mode, the byte count in write() determines the size
+of the physical block on tape. When reading, the drive reads the next
+tape block and returns to the user the data if the read() byte count
+is at least the block size. Otherwise the data is truncated.
+
+In fixed block mode, the data transfer between the drive and the
+driver is in multiples of the block size. The write() byte count must
+be a multiple of the block size. This is not required when reading but
+may be advisable for portability.
+
 Support is provided for changing the tape partition and partitioning
 of the tape with one or two partitions. By default support for
 partitioned tape is disabled for each driver and it can be enabled
diff -urN linux-2.2.3-pre2/drivers/scsi/st.c linux-2.2.3-pre3/drivers/scsi/st.c
--- linux-2.2.3-pre2/drivers/scsi/st.c	1998-12-27 10:18:55.000000000 -0800
+++ linux-2.2.3-pre3/drivers/scsi/st.c	2003-08-15 15:05:26.000000000 -0700
@@ -8,10 +8,10 @@
   order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
   Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
 
-  Copyright 1992 - 1998 Kai Makisara
+  Copyright 1992 - 1999 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Thu Dec  3 20:27:46 1998 by makisara@home
+  Last modified: Sun Mar  7 09:03:17 1999 by makisara@home
   Some small formal changes - aeb, 950809
 */
 
@@ -1094,8 +1094,11 @@
 #endif
 
     /* Write must be integral number of blocks */
-    if (STp->block_size != 0 && (count % STp->block_size) != 0)
+    if (STp->block_size != 0 && (count % STp->block_size) != 0) {
+	printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n",
+	       dev);
 	return (-EIO);
+    }
 
     if (STp->can_partitions &&
 	(retval = update_partition(inode)) < 0)
diff -urN linux-2.2.3-pre2/drivers/sound/ad1848.c linux-2.2.3-pre3/drivers/sound/ad1848.c
--- linux-2.2.3-pre2/drivers/sound/ad1848.c	1999-01-19 14:47:48.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/ad1848.c	2003-08-15 15:05:26.000000000 -0700
@@ -100,6 +100,11 @@
 
 static int nr_ad1848_devs = 0;
 int deskpro_xl = 0;
+#ifdef CONFIG_SOUND_SPRO
+int soundpro = 1;
+#else
+int soundpro = 0;
+#endif
 
 static volatile char irq2dev[17] = {
 	-1, -1, -1, -1, -1, -1, -1, -1,
@@ -312,22 +317,21 @@
 		if (mask & (1 << i))
 			n++;
 
-	if (n == 0)
-		mask = SOUND_MASK_MIC;
-	else if (n != 1)	/* Too many devices selected */
-	{
-		  mask &= ~devc->recmask;	/* Filter out active settings */
+	if (!soundpro) {
+		if (n == 0)
+			mask = SOUND_MASK_MIC;
+		else if (n != 1) {	/* Too many devices selected */
+			mask &= ~devc->recmask;	/* Filter out active settings */
 
-		n = 0;
-		for (i = 0; i < 32; i++)	/* Count selected device bits */
-			if (mask & (1 << i))
-				n++;
+			n = 0;
+			for (i = 0; i < 32; i++)	/* Count selected device bits */
+				if (mask & (1 << i))
+					n++;
 
-		if (n != 1)
-			mask = SOUND_MASK_MIC;
-	}
-	switch (mask)
-	{
+			if (n != 1)
+				mask = SOUND_MASK_MIC;
+		}
+		switch (mask) {
 		case SOUND_MASK_MIC:
 			recdev = 2;
 			break;
@@ -349,11 +353,38 @@
 		default:
 			mask = SOUND_MASK_MIC;
 			recdev = 2;
-	}
+		}
+
+		recdev <<= 6;
+		ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
+		ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+	} else { /* soundpro */
+		unsigned char val;
+		int set_rec_bit;
+		int j;
+
+		for (i = 0; i < 32; i++) {	/* For each bit */
+			if ((devc->supported_rec_devices & (1 << i)) == 0)
+				continue;	/* Device not supported */
+
+			for (j = LEFT_CHN; j <= RIGHT_CHN; j++) {
+				if (devc->mix_devices[i][j].nbits == 0) /* Inexistent channel */
+					continue;
+
+				/*
+				 * This is tricky:
+				 * set_rec_bit becomes 1 if the corresponding bit in mask is set
+				 * then it gets flipped if the polarity is inverse
+				 */
+				set_rec_bit = ((mask & (1 << i)) != 0) ^ devc->mix_devices[i][j].recpol;
 
-	recdev <<= 6;
-	ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
-	ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+				val = ad_read(devc, devc->mix_devices[i][j].recreg);
+				val &= ~(1 << devc->mix_devices[i][j].recpos);
+				val |= (set_rec_bit << devc->mix_devices[i][j].recpos);
+				ad_write(devc, devc->mix_devices[i][j].recreg, val);
+			}
+		}
+	}
 
 	/* Rename the mixer bits back if necessary */
 	for (i = 0; i < 32; i++)
@@ -371,7 +402,8 @@
 	return mask;
 }
 
-static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
+static void change_bits(ad1848_info * devc, unsigned char *regval,
+			unsigned char *muteval, int dev, int chn, int newval)
 {
 	unsigned char mask;
 	int shift;
@@ -379,7 +411,7 @@
 	int mutemask;
 	int set_mute_bit;
 
-	set_mute_bit = (newval == 0);
+	set_mute_bit = (newval == 0) ^ devc->mix_devices[dev][chn].mutepol;
 
 	if (devc->mix_devices[dev][chn].polarity == 1)	/* Reverse */
 		newval = 100 - newval;
@@ -399,8 +431,11 @@
 	}
 
 	newval = (int) ((newval * mask) + 50) / 100;	/* Scale it */
-	*regval &= (~(mask << shift)) & (mutemask);	/* Clear bits */
-	*regval |= ((newval & mask) << shift) | mute;	/* Set new value */
+	*regval &= ~(mask << shift);			/* Clear bits */
+	*regval |= (newval & mask) << shift;		/* Set new value */
+
+	*muteval &= mutemask;
+	*muteval |= mute;
 }
 
 static int ad1848_mixer_get(ad1848_info * devc, int dev)
@@ -413,15 +448,36 @@
 	return devc->levels[dev];
 }
 
+static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int channel)
+{
+	int regoffs, muteregoffs;
+	unsigned char val, muteval;
+
+	regoffs = devc->mix_devices[dev][channel].regno;
+	muteregoffs = devc->mix_devices[dev][channel].mutereg;
+	val = ad_read(devc, regoffs);
+
+	if (muteregoffs != regoffs) {
+		muteval = ad_read(devc, muteregoffs);
+		change_bits(devc, &val, &muteval, dev, channel, value);
+	}
+	else
+		change_bits(devc, &val, &val, dev, channel, value);
+
+	ad_write(devc, regoffs, val);
+	devc->saved_regs[regoffs] = val;
+	if (muteregoffs != regoffs) {
+		ad_write(devc, muteregoffs, muteval);
+		devc->saved_regs[muteregoffs] = muteval;
+	}
+}
+
 static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
 {
 	int left = value & 0x000000ff;
 	int right = (value & 0x0000ff00) >> 8;
 	int retvol;
 
-	int regoffs;
-	unsigned char val;
-
 	if (dev > 31)
 		return -EINVAL;
 
@@ -430,6 +486,9 @@
 
 	dev = devc->mixer_reroute[dev];
 
+	if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
+		return -EINVAL;
+
 	if (left > 100)
 		left = 100;
 	if (right > 100)
@@ -444,34 +503,21 @@
 	left = mix_cvt[left];
 	right = mix_cvt[right];
 
-	if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
-		return -EINVAL;
-
 	devc->levels[dev] = retvol;
 
 	/*
 	 * Set the left channel
 	 */
-
-	regoffs = devc->mix_devices[dev][LEFT_CHN].regno;
-	val = ad_read(devc, regoffs);
-	change_bits(devc, &val, dev, LEFT_CHN, left);
-	ad_write(devc, regoffs, val);
-	devc->saved_regs[regoffs] = val;
+	ad1848_mixer_set_channel(devc, dev, left, LEFT_CHN);
 
 	/*
 	 * Set the right channel
 	 */
-
 	if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)
-		return retvol;	/* Was just a mono channel */
-
-	regoffs = devc->mix_devices[dev][RIGHT_CHN].regno;
-	val = ad_read(devc, regoffs);
-	change_bits(devc, &val, dev, RIGHT_CHN, right);
-	ad_write(devc, regoffs, val);
-	devc->saved_regs[regoffs] = val;
+		goto out;
+	ad1848_mixer_set_channel(devc, dev, right, RIGHT_CHN);
 
+ out:
 	return retvol;
 }
 
@@ -487,6 +533,8 @@
 	for (i = 0; i < 32; i++)
 		devc->mixer_reroute[i] = i;
 
+	devc->supported_rec_devices = MODE1_REC_DEVICES;
+
 	switch (devc->model)
 	{
 		case MD_4231:
@@ -509,11 +557,18 @@
 			devc->supported_devices = MODE3_MIXER_DEVICES;
 			break;
 
+		case MD_1848:
+			if (soundpro) {
+				devc->supported_devices = SPRO_MIXER_DEVICES;
+				devc->supported_rec_devices = SPRO_REC_DEVICES;
+				devc->mix_devices = &(spro_mix_devices[0]);
+				break;
+			}
+
 		default:
 			devc->supported_devices = MODE1_MIXER_DEVICES;
 	}
 
-	devc->supported_rec_devices = MODE1_REC_DEVICES;
 	devc->orig_devices = devc->supported_devices;
 	devc->orig_rec_devices = devc->supported_rec_devices;
 
@@ -528,10 +583,20 @@
 	ad1848_set_recmask(devc, SOUND_MASK_MIC);
 	
 	devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT;
-	if (devc->mixer_output_port & AUDIO_SPEAKER)
-		ad_write(devc, 26, ad_read(devc, 26) & ~0x40);	/* Unmute mono out */
-	else
-		ad_write(devc, 26, ad_read(devc, 26) | 0x40);	/* Mute mono out */
+
+	if (!soundpro) {
+		if (devc->mixer_output_port & AUDIO_SPEAKER)
+			ad_write(devc, 26, ad_read(devc, 26) & ~0x40);	/* Unmute mono out */
+		else
+			ad_write(devc, 26, ad_read(devc, 26) | 0x40);	/* Mute mono out */
+	} else {
+		/*
+		 * From the "wouldn't it be nice if the mixer API had (better)
+		 * support for custom stuff" category
+		 */
+		/* Enable surround mode and SB16 mixer */
+		ad_write(devc, 16, 0x60);
+	}
 }
 
 static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
@@ -1357,6 +1422,8 @@
 	{
 		  devc->audio_flags &= ~DMA_DUPLEX;
 		  ad_write(devc, 9, ad_read(devc, 9) | 0x04);	/* Single DMA mode */
+		  if (soundpro)
+			  ad_write(devc, 12, ad_read(devc, 12) | 0x40);	/* Mode2 = enabled */
 	}
 
 	outb((0), io_Status(devc));	/* Clear pending interrupts */
@@ -1706,7 +1773,27 @@
 
 			DDB(printk("ad1848_detect() - step K\n"));
 		}
+	} else if (tmp1 == 0x0a) {
+		/*
+		 * Is it perhaps a SoundPro CMI8330?
+		 * If so, then we should be able to change indirect registers
+		 * greater than I15 after activating MODE2, even though reading
+		 * back I12 does not show it.
+		 */
+
+		/*
+		 * Let's try comparing register values
+		 */
+		for (i = 0; i < 16; i++) {
+			if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) {
+				DDB(printk("ad1848 detect step H(%d/%x/%x) - SoundPro chip?\n", i, tmp1, tmp2));
+				soundpro = 1;
+				devc->chip_name = "SoundPro CMI 8330";
+				break;
+			}
+		}
 	}
+
 	DDB(printk("ad1848_detect() - step L\n"));
 	if (ad_flags)
 	{
@@ -2302,7 +2389,8 @@
 	    (hw_config->irq != 7)  &&
 	    (hw_config->irq != 9)  &&
 	    (hw_config->irq != 10) &&
-	    (hw_config->irq != 11))
+	    (hw_config->irq != 11) &&
+	    (hw_config->irq != 12))
 	{
 		printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
 		return 0;
@@ -2555,6 +2643,7 @@
 MODULE_PARM(dma2, "i");			/* Second DMA channel */
 MODULE_PARM(type, "i");			/* Card type */
 MODULE_PARM(deskpro_xl, "i");		/* Special magic for Deskpro XL boxen */
+MODULE_PARM(soundpro, "i");		/* More special magic for SoundPro chips */
 
 int io = -1;
 int irq = -1;
diff -urN linux-2.2.3-pre2/drivers/sound/ad1848_mixer.h linux-2.2.3-pre3/drivers/sound/ad1848_mixer.h
--- linux-2.2.3-pre2/drivers/sound/ad1848_mixer.h	1998-10-09 11:56:59.000000000 -0700
+++ linux-2.2.3-pre3/drivers/sound/ad1848_mixer.h	2003-08-15 15:05:26.000000000 -0700
@@ -24,7 +24,10 @@
  * solution).
  */
 #define MODE1_REC_DEVICES		(SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
-					 SOUND_MASK_LINE1|SOUND_MASK_IMIX)
+					 SOUND_MASK_LINE1 | SOUND_MASK_IMIX)
+
+#define SPRO_REC_DEVICES		(SOUND_MASK_LINE | SOUND_MASK_MIC | \
+					 SOUND_MASK_CD | SOUND_MASK_LINE1)
 
 #define MODE1_MIXER_DEVICES		(SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
 					 SOUND_MASK_LINE2 | \
@@ -47,16 +50,27 @@
 				 SOUND_MASK_LINE3 | \
 				 SOUND_MASK_IGAIN | SOUND_MASK_PCM)
 
+#define SPRO_MIXER_DEVICES	(SOUND_MASK_VOLUME | SOUND_MASK_PCM | \
+				 SOUND_MASK_LINE | SOUND_MASK_SYNTH | \
+				 SOUND_MASK_CD | SOUND_MASK_MIC | \
+				 SOUND_MASK_SPEAKER | SOUND_MASK_LINE1 | \
+				 SOUND_MASK_OGAIN)
+
 struct mixer_def {
-	unsigned int regno: 5;
-	unsigned int polarity:1;	/* 0=normal, 1=reversed */
-	unsigned int bitpos:3;
-	unsigned int nbits:3;
-	unsigned int mutepos:4;
+	unsigned int regno:5;		/* register number for volume */
+	unsigned int polarity:1;	/* volume polarity: 0=normal, 1=reversed */
+	unsigned int bitpos:3;		/* position of bits in register for volume */
+	unsigned int nbits:3;		/* number of bits in register for volume */
+	unsigned int mutereg:5;		/* register number for mute bit */
+	unsigned int mutepol:1;		/* mute polarity: 0=normal, 1=reversed */
+	unsigned int mutepos:4;		/* position of mute bit in register */
+	unsigned int recreg:5;		/* register number for recording bit */
+	unsigned int recpol:1;		/* recording polarity: 0=normal, 1=reversed */
+	unsigned int recpos:4;		/* position of recording bit in register */
 };
 
 static char mix_cvt[101] = {
-	0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+	 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
 	43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
 	65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
 	80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
@@ -77,7 +91,17 @@
  */
 
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit)	\
-	{{reg_l, pola_l, pos_l, len_l, mute_bit}, {reg_r, pola_r, pos_r, len_r, mute_bit}}
+	[name] = {{reg_l, pola_l, pos_l, len_l, reg_l, 0, mute_bit, 0, 0, 8},			\
+		  {reg_r, pola_r, pos_r, len_r, reg_r, 0, mute_bit, 0, 0, 8}}
+
+#define MIX_ENT2(name, reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \
+		    rec_reg_l, rec_pola_l, rec_pos_l,					 \
+		 reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r,	 \
+		    rec_reg_r, rec_pola_r, rec_pos_r)					 \
+	[name] = {{reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l,	 \
+		    rec_reg_l, rec_pola_l, rec_pos_l},					 \
+		  {reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r,	 \
+		    rec_reg_r, rec_pola_r, rec_pos_r}}
 
 static mixer_ents ad1848_mix_devices[32] = {
 MIX_ENT(SOUND_MIXER_VOLUME,	27, 1, 0, 4,	29, 1, 0, 4,  8),
@@ -144,6 +168,30 @@
 MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 1, 4,	19, 1, 1, 4,  7)
 };
 
+static mixer_ents spro_mix_devices[32] = {
+MIX_ENT (SOUND_MIXER_VOLUME,	19, 0, 4, 4,			 19, 0, 0, 4,  8),
+MIX_ENT (SOUND_MIXER_BASS,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_TREBLE,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT2(SOUND_MIXER_SYNTH,	 4, 1, 1, 4, 23, 0, 3,  0, 0, 8,
+	 			 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_PCM,	 6, 1, 1, 4,			  7, 1, 1, 4,  8),
+MIX_ENT (SOUND_MIXER_SPEAKER,	18, 0, 3, 2,			  0, 0, 0, 0,  8),
+MIX_ENT2(SOUND_MIXER_LINE,	20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
+	 			20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
+MIX_ENT2(SOUND_MIXER_MIC,	18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
+	 			 0, 0, 0, 0,  0, 0, 0,  0, 0, 0),
+MIX_ENT2(SOUND_MIXER_CD,	21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
+				21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
+MIX_ENT (SOUND_MIXER_IMIX,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_RECLEV,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_IGAIN,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_OGAIN,	17, 1, 6, 1,			  0, 0, 0, 0,  8),
+/* This is external wavetable */
+MIX_ENT2(SOUND_MIXER_LINE1,	22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
+	 			22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
+};
+
 static int default_mixer_levels[32] =
 {
   0x3232,			/* Master Volume */
diff -urN linux-2.2.3-pre2/drivers/sound/Config.in linux-2.2.3-pre3/drivers/sound/Config.in
--- linux-2.2.3-pre2/drivers/sound/Config.in	1999-01-14 22:59:47.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/Config.in	2003-08-15 15:05:26.000000000 -0700
@@ -12,7 +12,7 @@
 dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
 if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
    bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
-fi  
+fi
 dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
 if [ "$CONFIG_SOUND_ES1371" = "y" ]; then
    bool 'Joystick support at boot time' CONFIG_SOUND_ES1371_JOYPORT_BOOT
@@ -75,6 +75,10 @@
 dep_tristate 'OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
 
 if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
+  if [ "$CONFIG_SOUND_OSS" = "y" ]; then
+    bool 'Persistent DMA buffers' CONFIG_SOUND_DMAP
+  fi
+
   dep_tristate 'ProAudioSpectrum 16 support' CONFIG_SOUND_PAS $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_PAS" = "y" ]; then
       int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' CONFIG_PAS_IRQ 10
@@ -138,6 +142,7 @@
   
   dep_tristate 'Microsoft Sound System support' CONFIG_SOUND_MSS $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_MSS" = "y" ]; then
+      bool 'Enable support for the SoundPro mixer' CONFIG_SOUND_SPRO
       hex 'MSS/WSS I/O base 530, 604, E80 or F40' CONFIG_MSS_BASE 530
       int 'MSS/WSS IRQ 7, 9, 10 or 11' CONFIG_MSS_IRQ 11
       int 'MSS/WSS DMA 0, 1 or 3' CONFIG_MSS_DMA 3
diff -urN linux-2.2.3-pre2/drivers/sound/es1370.c linux-2.2.3-pre3/drivers/sound/es1370.c
--- linux-2.2.3-pre2/drivers/sound/es1370.c	1999-01-07 09:24:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/es1370.c	2003-08-15 15:05:26.000000000 -0700
@@ -1228,8 +1228,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	db->mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
@@ -1597,6 +1595,7 @@
 	down(&s->open_sem);
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac2(s);
+		synchronize_irq();
 		dealloc_dmabuf(&s->dma_dac2);
 	}
 	if (file->f_mode & FMODE_READ) {
@@ -1725,8 +1724,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	s->dma_dac1.mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -urN linux-2.2.3-pre2/drivers/sound/es1371.c linux-2.2.3-pre3/drivers/sound/es1371.c
--- linux-2.2.3-pre2/drivers/sound/es1371.c	1999-01-07 09:24:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/es1371.c	2003-08-15 15:05:26.000000000 -0700
@@ -1675,8 +1675,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	db->mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
@@ -2172,8 +2170,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	s->dma_dac1.mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -urN linux-2.2.3-pre2/drivers/sound/lowlevel/awe_compat.h linux-2.2.3-pre3/drivers/sound/lowlevel/awe_compat.h
--- linux-2.2.3-pre2/drivers/sound/lowlevel/awe_compat.h	1999-01-07 09:24:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/lowlevel/awe_compat.h	2003-08-15 15:05:26.000000000 -0700
@@ -54,7 +54,7 @@
 #include "../soundvers.h"
 #endif
 
-#if SOUND_INTERNAL_VERSION >= 0x30803
+#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
 /* OSS/Free-3.8 */
 #define AWE_NO_PATCHMGR
 #define AWE_OSS38
@@ -151,18 +151,9 @@
 #define my_malloc_memptr()	_mem_start
 #define my_free(ptr)	/* do nothing */
 
-static void *my_malloc(int size)
-{
-	char *ptr;
-	PERMANENT_MALLOC(ptr, char*, size, _mem_start);
-	return (void*)ptr;
-}
-#define my_kmalloc(size) my_malloc(size)
-#define kfree(ptr)	/* do nothing */
-
 /* allocate buffer only once */
 #define INIT_TABLE(buffer,index,nums,type) {\
-buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
+PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
 }
 
 #else
@@ -173,8 +164,6 @@
 #define my_malloc_memptr()	0
 #define my_malloc(size)		vmalloc(size)
 #define my_free(ptr)		if (ptr) {vfree(ptr);}
-#define my_kmalloc(size)	kmalloc(size,GFP_KERNEL)
-#define my_kfree(ptr)		kfree(ptr)
 
 /* do not allocate buffer at beginning */
 #define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
@@ -255,6 +244,14 @@
 
 #endif /* AWE_MODULE_SUPPORT */
 
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+inline static void interruptible_sleep_on_timeout(struct wait_queue **q, unsigned long timeout)
+{
+	current->timeout = jiffies + timeout;
+	interruptible_sleep_on(q);
+}
+#endif
+
 #endif /* CONFIG_AWE32_SYNTH */
 
 #endif /* AWE_COMPAT_H_DEF */
diff -urN linux-2.2.3-pre2/drivers/sound/lowlevel/awe_wave.c linux-2.2.3-pre3/drivers/sound/lowlevel/awe_wave.c
--- linux-2.2.3-pre2/drivers/sound/lowlevel/awe_wave.c	1998-12-16 12:52:01.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/lowlevel/awe_wave.c	2003-08-15 15:05:26.000000000 -0700
@@ -2,9 +2,9 @@
  * sound/awe_wave.c
  *
  * The low level driver for the AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Nov. 1, 1998
+ *   version 0.4.3; Feb. 1, 1999
  *
- * Copyright (C) 1996-1998 Takashi Iwai
+ * Copyright (C) 1996-1999 Takashi Iwai
  *
  * 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
@@ -204,16 +204,20 @@
 #if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
 /* replace awe_port variable with exported variable */
 #define awe_port	io
-#define BASEVAR_DECL	/**/
+#define awe_mem_size	memsize
+int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */
+int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */
+#ifdef MODULE_PARM
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "base i/o port of Emu8000");
+MODULE_PARM(memsize, "i");
+MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes");
+#endif
 #else
-#define BASEVAR_DECL	static
+static int awe_port = AWE_DEFAULT_BASE_ADDR;
+static int awe_mem_size = AWE_DEFAULT_MEM_SIZE;
 #endif /* module */
 
-/* awe32 base address (overwritten at initialization) */
-BASEVAR_DECL int awe_port = AWE_DEFAULT_BASE_ADDR;
-/* memory byte size */
-BASEVAR_DECL int memsize = AWE_DEFAULT_MEM_SIZE; /* for module option */
-static int awe_mem_size = -1;
 /* DRAM start offset */
 static int awe_mem_start = AWE_DRAM_OFFSET;
 
@@ -669,7 +673,7 @@
 
 #include <linux/pnp.h>
 
-BASEVAR_DECL int pnp = 1;	/* use PnP as default */
+static int pnp = 1;	/* use PnP as default */
 
 #define AWE_NUM_CHIPS	3
 static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
@@ -812,6 +816,7 @@
 }
 
 #ifdef MODULE_PARM
+EXPORT_NO_SYMBOLS;
 MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
 MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
 MODULE_SUPPORTED_DEVICE("sound");
@@ -975,23 +980,9 @@
 #else
 
 static struct wait_queue *awe_sleeper = NULL;
-static void awe_wakeup(unsigned long dummy)
-{
-	wake_up(&awe_sleeper);
-}
-
-static struct timer_list awe_timer =
-{NULL, NULL, 0, 0, awe_wakeup};
-
 static void awe_wait(unsigned short delay)
 {
-	unsigned long   flags;
-	awe_timer.expires = jiffies + (HZ * (unsigned long)delay + 44099) / 44100;
-	add_timer(&awe_timer);
-	save_flags (flags);
-	cli();
-	sleep_on(&awe_sleeper);
-	restore_flags(flags);
+	interruptible_sleep_on_timeout(&awe_sleeper, (HZ * (unsigned long)delay + 44099) / 44100);
 }
 #endif /* wait by loop */
 
@@ -1553,7 +1544,7 @@
 			  vp->parm.moddcysus));
 
 	if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
-		awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+		awe_poke(AWE_ENVVOL(voice), 0xBFFF);
 		vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
 	} else {
 		awe_poke(AWE_ENVVOL(voice),
@@ -3268,7 +3259,7 @@
 	sf_list *sf;
 
 	/* search for all sharing lists */
-	for (sf_id = rec->v.sf_id; sf_id > 0; sf_id = sf->shared) {
+	for (sf_id = rec->v.sf_id; sf_id > 0 && sf_id <= current_sf_id; sf_id = sf->shared) {
 		sf = &sflists[sf_id - 1];
 		for (j = sf->infos; j >= 0; j = infos[j].next) {
 			awe_voice_list *p = &infos[j];
@@ -4201,7 +4192,7 @@
 		if (id1 < id2) { /* make sure id1 > id2 */
 			int tmp; tmp = id1; id1 = id2; id2 = tmp;
 		}
-		for (i = sflists[id1-1].shared; i > 0; i = sflists[i-1].shared) {
+		for (i = sflists[id1-1].shared; i > 0 && i <= current_sf_id; i = sflists[i-1].shared) {
 			if (i == id2)
 				return TRUE;
 		}
@@ -4223,10 +4214,10 @@
 			return i;
 	}
 #ifdef AWE_ALLOW_SAMPLE_SHARING
-	if (sflists[sf-1].shared) { /* search recursively */
+	if ((i = sflists[sf-1].shared) > 0 && i <= current_sf_id) { /* search recursively */
 		if (level > current_sf_id)
 			return -1; /* strange sharing loop.. quit */
-		return search_sample_index(sflists[sf-1].shared, sample, level + 1);
+		return search_sample_index(i, sample, level + 1);
 	}
 #endif
 	return -1;
@@ -4272,10 +4263,12 @@
 		    note <= infos[rec].v.high &&
 		    velocity >= infos[rec].v.vellow &&
 		    velocity <= infos[rec].v.velhigh) {
-			vlist[nvoices] = &infos[rec].v;
-			if (infos[rec].type == V_ST_MAPPED) /* mapper */
+			if (infos[rec].type == V_ST_MAPPED) {
+				/* mapper */
+				vlist[0] = &infos[rec].v;
 				return -1;
-			nvoices++;
+			}
+			vlist[nvoices++] = &infos[rec].v;
 			if (nvoices >= AWE_MAX_VOICES)
 				break;
 		}
@@ -5009,8 +5002,6 @@
 		DEBUG(0,printk("AWE32 not found\n"));
 		return 0;
 	}
-	if (memsize >= 0) /* given by config file or module option */
-		awe_mem_size = memsize * 1024; /* convert to Kbytes */
 
 	return 1;
 }
@@ -5028,9 +5019,14 @@
 static void
 awe_check_dram(void)
 {
-	if (awe_mem_size >= 0) /* already initialized */
+	if (awe_present) /* already initialized */
 		return;
 
+	if (awe_mem_size >= 0) { /* given by config file or module option */
+		awe_mem_size *= 1024; /* convert to Kbytes */
+		return;
+	}
+
 	awe_open_dram_for_check();
 
 	awe_mem_size = 0;
diff -urN linux-2.2.3-pre2/drivers/sound/mad16.c linux-2.2.3-pre3/drivers/sound/mad16.c
--- linux-2.2.3-pre2/drivers/sound/mad16.c	1999-01-07 09:24:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/mad16.c	2003-08-15 15:05:26.000000000 -0700
@@ -800,7 +800,7 @@
 
 		mad_write(MC3_PORT, tmp | 0x04);
 		hw_config->driver_use_1 = SB_MIDI_ONLY;
-		return sb_dsp_detect(hw_config);
+		return sb_dsp_detect(hw_config, 0, 0);
 #else
 		return 0;
 #endif
diff -urN linux-2.2.3-pre2/drivers/sound/sb_card.c linux-2.2.3-pre3/drivers/sound/sb_card.c
--- linux-2.2.3-pre2/drivers/sound/sb_card.c	1999-02-01 14:04:42.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/sb_card.c	2003-08-15 15:05:26.000000000 -0700
@@ -103,7 +103,7 @@
 		printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base);
 		return 0;
 	}
-	return sb_dsp_detect(hw_config);
+	return sb_dsp_detect(hw_config, 0, 0);
 }
 
 void unload_sb(struct address_info *hw_config)
@@ -135,6 +135,7 @@
 int mad16 = 0;		/* Set mad16=1 to load this as support for mad16 */
 int trix = 0;		/* Set trix=1 to load this as support for trix */
 int pas2 = 0;		/* Set pas2=1 to load this as support for pas2 */
+int support = 0;	/* Set support to load this as a support module */
 int sm_games = 0;	/* Mixer - see sb_mixer.c */
 int acer = 0;		/* Do acer notebook init */
 
@@ -145,6 +146,7 @@
 MODULE_PARM(mpu_io, "i");
 MODULE_PARM(type, "i");
 MODULE_PARM(mad16, "i");
+MODULE_PARM(support, "i");
 MODULE_PARM(trix, "i");
 MODULE_PARM(pas2, "i");
 MODULE_PARM(sm_games, "i");
@@ -156,7 +158,7 @@
 {
 	printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
-	if (mad16 == 0 && trix == 0 && pas2 == 0)
+	if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
 	{
 		if (io == -1 || dma == -1 || irq == -1)
 		{
@@ -191,7 +193,7 @@
 {
 	if (smw_free)
 		vfree(smw_free);
-	if (!mad16 && !trix && !pas2)
+	if (!mad16 && !trix && !pas2 && !support)
 		unload_sb(&config);
 	if (sbmpu)
 		unload_sbmpu(&config_mpu);
diff -urN linux-2.2.3-pre2/drivers/sound/sb_common.c linux-2.2.3-pre3/drivers/sound/sb_common.c
--- linux-2.2.3-pre2/drivers/sound/sb_common.c	1999-01-24 22:04:02.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/sb_common.c	2003-08-15 15:05:26.000000000 -0700
@@ -179,13 +179,25 @@
 		status = inb(DSP_DATA_AVL16);
 }
 
+static void pci_intr(sb_devc *devc)
+{
+	int src = inb(devc->pcibase+0x1A);
+	src&=3;
+	if(src)
+		sb_intr(devc);
+}
+
 static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
 {
-    sb_devc *devc = dev_id;
+	sb_devc *devc = dev_id;
 
 	devc->irq_ok = 1;
 
 	switch (devc->model) {
+	case MDL_ESSPCI:
+		pci_intr (devc);
+		break;
+		
 	case MDL_ESS:
 		ess_intr (devc);
 		break;
@@ -478,7 +490,7 @@
 #endif
 }
 
-int sb_dsp_detect(struct address_info *hw_config)
+int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio)
 {
 	sb_devc sb_info;
 	sb_devc *devc = &sb_info;
@@ -508,7 +520,22 @@
 	devc->dma8 = hw_config->dma;
 
 	devc->dma16 = -1;
-
+	devc->pcibase = pciio;
+	
+	if(pci == SB_PCI_ESSMAESTRO)
+	{
+		devc->model = MDL_ESSPCI;
+		devc->caps |= SB_PCI_IRQ;
+		hw_config->driver_use_1 |= SB_PCI_IRQ;
+		hw_config->card_subtype	= MDL_ESSPCI;
+	}
+	
+	if(pci == SB_PCI_YAMAHA)
+	{
+		devc->caps |= SB_PCI_IRQ;
+		hw_config->driver_use_1 |= SB_PCI_IRQ;
+	}
+	
 	if (acer)
 	{
 		cli();
@@ -569,6 +596,10 @@
 				}
 		}
 	}
+	
+	if(devc->type == MDL_ESSPCI)
+		devc->model = MDL_ESSPCI;
+		
 	/*
 	 * Save device information for sb_dsp_init()
 	 */
@@ -619,7 +650,15 @@
 
 	if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && hw_config->irq > 0)
 	{			/* IRQ setup */
-		if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0)
+		
+		/*
+		 *	ESS PCI cards do shared PCI IRQ stuff. Since they
+		 *	will get shared PCI irq lines we must cope.
+		 */
+		 
+		int i=(devc->caps&SB_PCI_IRQ)?SA_SHIRQ:0;
+		
+		if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)
 		{
 			printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
 			return 0;
diff -urN linux-2.2.3-pre2/drivers/sound/sb.h linux-2.2.3-pre3/drivers/sound/sb.h
--- linux-2.2.3-pre2/drivers/sound/sb.h	1999-02-01 14:04:42.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/sb.h	2003-08-15 15:05:26.000000000 -0700
@@ -47,11 +47,13 @@
 #define MDL_AZTECH	13	/* Aztech Sound Galaxy family */
 #define MDL_ES1868MIDI	14	/* MIDI port of ESS1868 */
 #define MDL_AEDSP	15	/* Audio Excel DSP 16 */
+#define MDL_ESSPCI	16	/* ESS PCI card */
 
 #define SUBMDL_ALS007	42	/* ALS-007 differs from SB16 only in mixer */
 				/* register assignment */
 #define SUBMDL_ALS100	43	/* ALS-100 allows sampling rates of up */
 				/* to 48kHz */
+				
 /*
  * Config flags
  */
@@ -60,6 +62,7 @@
 #define SB_NO_AUDIO	0x00000004
 #define SB_NO_RECORDING	0x00000008 /* No audio recording */
 #define SB_MIDI_ONLY	(SB_NO_AUDIO|SB_NO_MIXER)
+#define SB_PCI_IRQ	0x00000010 /* PCI shared IRQ */
 
 struct mixer_def {
 	unsigned int regno: 8;
@@ -86,6 +89,8 @@
 	   int base;
 	   int irq;
 	   int dma8, dma16;
+	   
+	   int pcibase;		/* For ESS Maestro etc */
 
 	/* State variables */
  	   int opened;
@@ -128,13 +133,24 @@
 	   void (*midi_input_intr) (int dev, unsigned char data);
 	   void *midi_irq_cookie;	/* IRQ cookie for the midi */
 	} sb_devc;
+	
+/*
+ *	PCI card types
+ */
 
+#define	SB_PCI_ESSMAESTRO	1	/* ESS Maestro Legacy */
+#define	SB_PCI_YAMAHA		2	/* Yamaha Legacy */
+
+/* 
+ *	Functions
+ */
+ 
 int sb_dsp_command (sb_devc *devc, unsigned char val);
 int sb_dsp_get_byte(sb_devc * devc);
 int sb_dsp_reset (sb_devc *devc);
 void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
 unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
-int sb_dsp_detect (struct address_info *hw_config);
+int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio);
 int sb_dsp_init (struct address_info *hw_config);
 void sb_dsp_unload(struct address_info *hw_config, int sbmpu);
 int sb_mixer_init(sb_devc *devc);
diff -urN linux-2.2.3-pre2/drivers/sound/sb_mixer.c linux-2.2.3-pre3/drivers/sound/sb_mixer.c
--- linux-2.2.3-pre2/drivers/sound/sb_mixer.c	1999-01-23 10:45:25.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/sb_mixer.c	2003-08-15 15:05:26.000000000 -0700
@@ -673,6 +673,7 @@
 
 	switch (devc->model)
 	{
+		case MDL_ESSPCI:
 		case MDL_SBPRO:
 		case MDL_AZTECH:
 		case MDL_JAZZ:
diff -urN linux-2.2.3-pre2/drivers/sound/sequencer.c linux-2.2.3-pre3/drivers/sound/sequencer.c
--- linux-2.2.3-pre2/drivers/sound/sequencer.c	1999-01-15 17:46:27.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/sequencer.c	2003-08-15 15:05:26.000000000 -0700
@@ -1105,7 +1105,7 @@
 		 */
 
 		for (i = 0; i < max_mididev; i++)
-			if (!midi_opened[i])
+			if (!midi_opened[i] && midi_devs[i])
 			{
 				if ((retval = midi_devs[i]->open(i, mode,
 					sequencer_midi_input, sequencer_midi_output)) >= 0)
@@ -1411,7 +1411,7 @@
 		case SNDCTL_SEQ_TESTMIDI:
 			if (__get_user(midi_dev, (int *)arg))
 				return -EFAULT;
-			if (midi_dev < 0 || midi_dev >= max_mididev)
+			if (midi_dev < 0 || midi_dev >= max_mididev || !midi_devs[midi_dev])
 				return -ENXIO;
 
 			if (!midi_opened[midi_dev] &&
@@ -1529,7 +1529,7 @@
 		case SNDCTL_MIDI_INFO:
 			if (get_user(dev, (int *)(&(((struct midi_info *)arg)->device))))
 				return -EFAULT;
-			if (dev < 0 || dev >= max_mididev)
+			if (dev < 0 || dev >= max_mididev || !midi_devs[dev])
 				return -ENXIO;
 			midi_devs[dev]->info.device = dev;
 			return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct midi_info))?-EFAULT:0;
diff -urN linux-2.2.3-pre2/drivers/sound/sonicvibes.c linux-2.2.3-pre3/drivers/sound/sonicvibes.c
--- linux-2.2.3-pre2/drivers/sound/sonicvibes.c	1999-01-07 09:24:00.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/sonicvibes.c	2003-08-15 15:05:26.000000000 -0700
@@ -1431,8 +1431,6 @@
 	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
 		return -EAGAIN;
 	db->mapped = 1;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -urN linux-2.2.3-pre2/drivers/sound/soundcard.c linux-2.2.3-pre3/drivers/sound/soundcard.c
--- linux-2.2.3-pre2/drivers/sound/soundcard.c	1999-01-15 17:46:27.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/soundcard.c	2003-08-15 15:05:26.000000000 -0700
@@ -67,7 +67,11 @@
 int             sound_nblocks = 0;
 
 /* Persistent DMA buffers */
-int		sound_dmap_flag = 0;	/* Off by default */
+#ifdef CONFIG_SOUND_DMAP
+int		sound_dmap_flag = 1;
+#else
+int		sound_dmap_flag = 0;
+#endif
 
 static int      soundcard_configured = 0;
 
@@ -751,9 +755,6 @@
 		vma->vm_page_prot))
 		return -EAGAIN;
 
-	vma->vm_file = file;
-	file->f_count++;
-
 	dmap->mapping_flags |= DMA_MAP_MAPPED;
 
 	if( audio_devs[dev]->d->mmap)
@@ -802,13 +803,6 @@
 	return -1;
 }
 
-static void destroy_special_devices(void)
-{
-	unregister_sound_special(6);
-	unregister_sound_special(1);
-	unregister_sound_special(8);
-}
-
 #ifdef MODULE
 static void
 #else
@@ -849,12 +843,19 @@
 #endif		
 }
 
+#ifdef MODULE
+
+static void destroy_special_devices(void)
+{
+	unregister_sound_special(6);
+	unregister_sound_special(1);
+	unregister_sound_special(8);
+}
+
 static int      sound[20] = {
 	0
 };
 
-#ifdef MODULE
-
 int traceinit = 0;
 static int dmabuf = 0;
 MODULE_PARM(traceinit, "i");
diff -urN linux-2.2.3-pre2/drivers/sound/sound_core.c linux-2.2.3-pre3/drivers/sound/sound_core.c
--- linux-2.2.3-pre2/drivers/sound/sound_core.c	1999-02-06 12:46:21.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/sound_core.c	2003-08-15 15:05:26.000000000 -0700
@@ -39,7 +39,6 @@
 #include <linux/malloc.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
 #include <linux/fs.h>
 #include <linux/sound.h>
 #include <linux/major.h>
diff -urN linux-2.2.3-pre2/drivers/sound/trix.c linux-2.2.3-pre3/drivers/sound/trix.c
--- linux-2.2.3-pre2/drivers/sound/trix.c	1998-12-27 10:53:45.000000000 -0800
+++ linux-2.2.3-pre3/drivers/sound/trix.c	2003-08-15 15:05:26.000000000 -0700
@@ -323,7 +323,7 @@
 
 	hw_config->name = "AudioTrix SB";
 #ifdef CONFIG_SBDSP
-	return sb_dsp_detect(hw_config);
+	return sb_dsp_detect(hw_config, 0, 0);
 #else
 	return 0;
 #endif
diff -urN linux-2.2.3-pre2/drivers/video/atyfb.c linux-2.2.3-pre3/drivers/video/atyfb.c
--- linux-2.2.3-pre2/drivers/video/atyfb.c	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/drivers/video/atyfb.c	2003-08-15 15:05:26.000000000 -0700
@@ -2323,8 +2323,6 @@
 	if (!map_size)
 		return -EINVAL;
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_flags |= VM_IO;
 
 	if (!fb->mmaped) {
diff -urN linux-2.2.3-pre2/drivers/video/fbmem.c linux-2.2.3-pre3/drivers/video/fbmem.c
--- linux-2.2.3-pre2/drivers/video/fbmem.c	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/drivers/video/fbmem.c	2003-08-15 15:05:26.000000000 -0700
@@ -495,8 +495,6 @@
 	if (remap_page_range(vma->vm_start, vma->vm_offset,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
-	vma->vm_file = file;
-	file->f_count++;
 	return 0;
 }
 
diff -urN linux-2.2.3-pre2/drivers/video/igafb.c linux-2.2.3-pre3/drivers/video/igafb.c
--- linux-2.2.3-pre2/drivers/video/igafb.c	1998-10-16 23:30:21.000000000 -0700
+++ linux-2.2.3-pre3/drivers/video/igafb.c	2003-08-15 15:05:26.000000000 -0700
@@ -304,8 +304,6 @@
 	if (!map_size)
 		return -EINVAL;
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_flags |= VM_IO;
 
 	if (!fb->mmaped) {
diff -urN linux-2.2.3-pre2/drivers/video/sbusfb.c linux-2.2.3-pre3/drivers/video/sbusfb.c
--- linux-2.2.3-pre2/drivers/video/sbusfb.c	1999-01-19 10:48:41.000000000 -0800
+++ linux-2.2.3-pre3/drivers/video/sbusfb.c	2003-08-15 15:05:26.000000000 -0700
@@ -244,8 +244,6 @@
 		page += map_size;
 	}
 	
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_flags |= VM_IO;
 	if (!fb->mmaped) {
 		int lastconsole = 0;
diff -urN linux-2.2.3-pre2/fs/affs/inode.c linux-2.2.3-pre3/fs/affs/inode.c
--- linux-2.2.3-pre2/fs/affs/inode.c	1999-02-06 12:46:21.000000000 -0800
+++ linux-2.2.3-pre3/fs/affs/inode.c	2003-08-15 15:05:26.000000000 -0700
@@ -21,7 +21,6 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/amigaffs.h>
 #include <linux/major.h>
diff -urN linux-2.2.3-pre2/fs/affs/super.c linux-2.2.3-pre3/fs/affs/super.c
--- linux-2.2.3-pre2/fs/affs/super.c	1998-06-24 14:30:09.000000000 -0700
+++ linux-2.2.3-pre3/fs/affs/super.c	2003-08-15 15:05:26.000000000 -0700
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/amigaffs.h>
 #include <linux/major.h>
diff -urN linux-2.2.3-pre2/fs/Config.in linux-2.2.3-pre3/fs/Config.in
--- linux-2.2.3-pre2/fs/Config.in	1999-01-19 11:07:53.000000000 -0800
+++ linux-2.2.3-pre3/fs/Config.in	2003-08-15 15:05:26.000000000 -0700
@@ -100,10 +100,6 @@
 endmenu
 fi
 
-if [ "$CONFIG_AFFS_FS" != "n" ]; then
-  define_bool CONFIG_AMIGA_PARTITION y
-fi
-
 mainmenu_option next_comment
 comment 'Partition Types'
 
@@ -116,6 +112,10 @@
 fi
 endmenu
 
+if [ "$CONFIG_AFFS_FS" != "n" ]; then
+  define_bool CONFIG_AMIGA_PARTITION y
+fi
+
 source fs/nls/Config.in
 
 endmenu
diff -urN linux-2.2.3-pre2/fs/dquot.c linux-2.2.3-pre3/fs/dquot.c
--- linux-2.2.3-pre2/fs/dquot.c	1998-09-25 16:24:56.000000000 -0700
+++ linux-2.2.3-pre3/fs/dquot.c	2003-08-15 15:05:26.000000000 -0700
@@ -483,7 +483,10 @@
 	if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) {
 		wait_on_dquot(dquot);
 		if (dquot->dq_flags & DQ_MOD)
-			write_dquot(dquot);
+		{
+			if(dquot->dq_mnt != (struct vfsmount *)NULL)
+				write_dquot(dquot);
+		}
 		/*
 		 * The dquot may be back in use now, so we
 		 * must recheck the free list.
diff -urN linux-2.2.3-pre2/fs/fat/mmap.c linux-2.2.3-pre3/fs/fat/mmap.c
--- linux-2.2.3-pre2/fs/fat/mmap.c	1998-11-02 13:26:51.000000000 -0800
+++ linux-2.2.3-pre3/fs/fat/mmap.c	2003-08-15 15:05:26.000000000 -0700
@@ -113,8 +113,6 @@
 		mark_inode_dirty(inode);
 	}
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_ops = &fat_file_mmap;
 	return 0;
 }
diff -urN linux-2.2.3-pre2/fs/isofs/file.c linux-2.2.3-pre3/fs/isofs/file.c
--- linux-2.2.3-pre2/fs/isofs/file.c	1998-08-24 13:02:44.000000000 -0700
+++ linux-2.2.3-pre3/fs/isofs/file.c	2003-08-15 15:05:26.000000000 -0700
@@ -16,7 +16,6 @@
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
-#include <linux/iso_fs.h>
 
 /*
  * We have mostly NULLs here: the current defaults are OK for
diff -urN linux-2.2.3-pre2/fs/ncpfs/mmap.c linux-2.2.3-pre3/fs/ncpfs/mmap.c
--- linux-2.2.3-pre2/fs/ncpfs/mmap.c	1998-02-27 10:58:34.000000000 -0800
+++ linux-2.2.3-pre3/fs/ncpfs/mmap.c	2003-08-15 15:05:26.000000000 -0700
@@ -137,8 +137,6 @@
 		inode->i_atime = CURRENT_TIME;
 	}
 
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_ops = &ncp_file_mmap;
 	return 0;
 }
diff -urN linux-2.2.3-pre2/fs/smbfs/cache.c linux-2.2.3-pre3/fs/smbfs/cache.c
--- linux-2.2.3-pre2/fs/smbfs/cache.c	1997-11-24 10:30:40.000000000 -0800
+++ linux-2.2.3-pre3/fs/smbfs/cache.c	2003-08-15 15:05:26.000000000 -0700
@@ -12,7 +12,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/errno.h>
 #include <linux/dirent.h>
 #include <linux/smb_fs.h>
 
@@ -142,7 +141,7 @@
 
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_add_to_cache: cache inode %p, status %d, adding %s at %ld\n",
-inode, cachep->status, entry->d_name, fpos);
+inode, cachep->status, entry->name, fpos);
 #endif
 	/*
 	 * Don't do anything if we've had an error ...
@@ -171,7 +170,7 @@
 		cachep->entries++;
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_add_to_cache: added entry %s, len=%d, pos=%ld, entries=%d\n",
-entry->d_name, len, fpos, cachep->entries);
+entry->name, len, fpos, cachep->entries);
 #endif
 		return;
 	}
diff -urN linux-2.2.3-pre2/include/linux/awe_voice.h linux-2.2.3-pre3/include/linux/awe_voice.h
--- linux-2.2.3-pre2/include/linux/awe_voice.h	1998-12-16 12:52:01.000000000 -0800
+++ linux-2.2.3-pre3/include/linux/awe_voice.h	2003-08-15 15:05:26.000000000 -0700
@@ -3,9 +3,9 @@
  *
  * Voice information definitions for the low level driver for the 
  * AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Mar. 1, 1998
+ *   version 0.4.3; Feb. 1, 1999
  *
- * Copyright (C) 1996-1998 Takashi Iwai
+ * Copyright (C) 1996-1999 Takashi Iwai
  *
  * 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
@@ -133,7 +133,7 @@
 	unsigned short moddelay;	/* modulation delay (0x8000) */
 	unsigned char modatk, modhld;
 	unsigned char moddcy, modsus;
-	unsigned short modrel, moddummy;
+	unsigned char modrel, moddummy;
 	short modkeyhold, modkeydecay;	/* envelope change per key (not used) */
 	unsigned short voldelay;	/* volume delay (0x8000) */
 	unsigned char volatk, volhld;
diff -urN linux-2.2.3-pre2/include/linux/dtlk.h linux-2.2.3-pre3/include/linux/dtlk.h
--- linux-2.2.3-pre2/include/linux/dtlk.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/include/linux/dtlk.h	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,104 @@
+#if 0
+
+#define TRACE_TXT(text) \
+	{ \
+	  if(dtlk_trace) \
+	  { \
+	    console_print(text); \
+	    console_print("\n"); \
+	  } \
+	}
+
+#define TRACE_CHR(chr) \
+	{ \
+	  if(dtlk_trace) \
+	    console_print(chr); \
+	} \
+
+#endif
+
+#define DTLK_MINOR	0
+#define DTLK_IO_EXTENT	0x02
+
+	/* ioctl's use magic number of 0xa3 */
+#define DTLK_INTERROGATE 0xa390	/* get settings from the DoubleTalk */
+#define DTLK_STATUS 0xa391	/* get status from the DoubleTalk */
+
+
+#define DTLK_CLEAR 0x18		/* stops speech */
+
+#define DTLK_MAX_RETRIES (loops_per_sec/10000)
+
+	/* TTS Port Status Flags */
+#define TTS_READABLE     0x80	/* mask for bit which is nonzero if a
+				   byte can be read from the TTS port */
+#define TTS_SPEAKING     0x40	/* mask for SYNC bit, which is nonzero
+				   while DoubleTalk is producing
+				   output with TTS, PCM or CVSD
+				   synthesizers or tone generators
+				   (that is, all but LPC) */
+#define TTS_SPEAKING2    0x20	/* mask for SYNC2 bit,
+				   which falls to zero up to 0.4 sec
+				   before speech stops */
+#define TTS_WRITABLE     0x10	/* mask for RDY bit, which when set to
+             			   1, indicates the TTS port is ready
+             			   to accept a byte of data.  The RDY
+             			   bit goes zero 2-3 usec after
+             			   writing, and goes 1 again 180-190
+             			   usec later. */
+#define TTS_ALMOST_FULL  0x08	/* mask for AF bit: When set to 1,
+				   indicates that less than 300 free
+				   bytes are available in the TTS
+				   input buffer. AF is always 0 in the
+				   PCM, TGN and CVSD modes. */
+#define TTS_ALMOST_EMPTY 0x04	/* mask for AE bit: When set to 1,
+				   indicates that less than 300 bytes
+				   of data remain in DoubleTalk's
+				   input (TTS or PCM) buffer. AE is
+				   always 1 in the TGN and CVSD
+				   modes. */
+
+	/* LPC speak commands */
+#define LPC_5220_NORMAL 0x60	/* 5220 format decoding table, normal rate */
+#define LPC_5220_FAST 0x64	/* 5220 format decoding table, fast rate */
+#define LPC_D6_NORMAL 0x20	/* D6 format decoding table, normal rate */
+#define LPC_D6_FAST 0x24	/* D6 format decoding table, fast rate */
+
+	/* LPC Port Status Flags (valid only after one of the LPC
+           speak commands) */
+#define LPC_SPEAKING     0x80	/* mask for TS bit: When set to 1,
+				   indicates the LPC synthesizer is
+				   producing speech.*/
+#define LPC_BUFFER_LOW   0x40	/* mask for BL bit: When set to 1,
+				   indicates that the hardware LPC
+				   data buffer has less than 30 bytes
+				   remaining. (Total internal buffer
+				   size = 4096 bytes.) */
+#define LPC_BUFFER_EMPTY 0x20	/* mask for BE bit: When set to 1,
+				   indicates that the LPC data buffer
+				   ran out of data (error condition if
+				   TS is also 1).  */
+
+				/* data returned by Interrogate command */
+struct dtlk_settings
+{
+  unsigned short serial_number;	/* 0-7Fh:0-7Fh */
+  unsigned char rom_version[24]; /* null terminated string */
+  unsigned char mode;		/* 0=Character; 1=Phoneme; 2=Text */
+  unsigned char punc_level;	/* nB; 0-7 */
+  unsigned char formant_freq;	/* nF; 0-9 */
+  unsigned char pitch;		/* nP; 0-99 */
+  unsigned char speed;		/* nS; 0-9 */
+  unsigned char volume;		/* nV; 0-9 */
+  unsigned char tone;		/* nX; 0-2 */
+  unsigned char expression;	/* nE; 0-9 */
+  unsigned char ext_dict_loaded; /* 1=exception dictionary loaded */
+  unsigned char ext_dict_status; /* 1=exception dictionary enabled */
+  unsigned char free_ram;	/* # pages (truncated) remaining for
+                                   text buffer */
+  unsigned char articulation;	/* nA; 0-9 */
+  unsigned char reverb;		/* nR; 0-9 */
+  unsigned char eob;		/* 7Fh value indicating end of
+                                   parameter block */
+  unsigned char has_indexing;	/* nonzero if indexing is implemented */
+};
diff -urN linux-2.2.3-pre2/include/linux/miscdevice.h linux-2.2.3-pre3/include/linux/miscdevice.h
--- linux-2.2.3-pre2/include/linux/miscdevice.h	1998-03-21 11:06:17.000000000 -0800
+++ linux-2.2.3-pre3/include/linux/miscdevice.h	2003-08-15 15:05:26.000000000 -0700
@@ -16,7 +16,7 @@
 #define RTC_MINOR 135
 #define SUN_OPENPROM_MINOR 139
 #define NVRAM_MINOR 144
-#define RADIO_MINOR 152
+#define I2O_MINOR 166
 #define MISC_DYNAMIC_MINOR 255
 
 extern int misc_init(void);
diff -urN linux-2.2.3-pre2/include/linux/pci.h linux-2.2.3-pre3/include/linux/pci.h
--- linux-2.2.3-pre2/include/linux/pci.h	1999-02-22 14:50:24.000000000 -0800
+++ linux-2.2.3-pre3/include/linux/pci.h	2003-08-15 15:05:26.000000000 -0700
@@ -3,7 +3,7 @@
  *
  *	PCI defines and function prototypes
  *	Copyright 1994, Drew Eckhardt
- *	Copyright 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *	Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  *	For more information, please consult the following manuals (look at
  *	http://www.pcisig.com/ for how to get them):
@@ -36,9 +36,9 @@
 #define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
 
 #define PCI_STATUS		0x06	/* 16 bits */
+#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
 #define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
 #define  PCI_STATUS_UDF		0x40	/* Support User Definable Features */
-
 #define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
 #define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
 #define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
@@ -101,7 +101,9 @@
 #define  PCI_ROM_ADDRESS_ENABLE	0x01
 #define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
 
-/* 0x34-0x3b are reserved */
+#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
 #define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
 #define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
 #define PCI_MIN_GNT		0x3e	/* 8 bits */
@@ -182,6 +184,12 @@
 #define PCI_CB_LEGACY_MODE_BASE	0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
 /* 0x48-0x7f reserved */
 
+/* Capability lists */
+#define PCI_CAP_LIST_ID		0	/* Capability ID */
+#define  PCI_CAP_ID_PM		0x01	/* Power Management */
+#define  PCI_CAP_ID_AGP		0x02	/* Accelerated Graphics Port */
+#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
+
 /* Device classes and subclasses */
 
 #define PCI_CLASS_NOT_DEFINED		0x0000
@@ -356,6 +364,7 @@
 #define PCI_DEVICE_ID_DEC_21052		0x0021
 #define PCI_DEVICE_ID_DEC_21150		0x0022
 #define PCI_DEVICE_ID_DEC_21152		0x0024
+#define PCI_DEVICE_ID_DEC_21153		0x0025
 
 #define PCI_VENDOR_ID_CIRRUS		0x1013
 #define PCI_DEVICE_ID_CIRRUS_7548	0x0038
@@ -949,6 +958,9 @@
 #define PCI_VENDOR_ID_CBOARDS		0x1307
 #define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
 
+#define PCI_VENDOR_ID_NETGEAR		0x1385
+#define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
+
 #define PCI_VENDOR_ID_SYMPHONY		0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101	0x0001
 
@@ -1031,6 +1043,7 @@
 #define PCI_DEVICE_ID_INTEL_82443BX_2	0x7192
 #define PCI_DEVICE_ID_INTEL_P6		0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
+#define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
 
 #define PCI_VENDOR_ID_KTI		0x8e2e
 #define PCI_DEVICE_ID_KTI_ET32P2	0x3000
@@ -1197,6 +1210,7 @@
 void pci_setup(char *str, int *ints);
 void pci_quirks_init(void);
 unsigned int pci_scan_bus(struct pci_bus *bus);
+struct pci_bus *pci_scan_peer_bridge(int bus);
 void pci_proc_init(void);
 void proc_old_pci_init(void);
 int get_pci_list(char *buf);
diff -urN linux-2.2.3-pre2/include/net/br.h linux-2.2.3-pre3/include/net/br.h
--- linux-2.2.3-pre2/include/net/br.h	1999-01-07 09:25:02.000000000 -0800
+++ linux-2.2.3-pre3/include/net/br.h	2003-08-15 15:05:26.000000000 -0700
@@ -258,6 +258,7 @@
 #define BR_UP		0x0001	/* bridging enabled */
 #define BR_DEBUG	0x0002	/* debugging enabled */
 #define BR_PROT_STATS	0x0004	/* protocol statistics enabled */
+#define BR_STP_DISABLED	0x0008	/* Spanning tree protocol disabled */
 
 struct br_cf {
 	unsigned int cmd;
@@ -281,6 +282,7 @@
 #define BRCMD_ENABLE_PROT_STATS	13
 #define BRCMD_DISABLE_PROT_STATS 14
 #define BRCMD_ZERO_PROT_STATS	15
+#define BRCMD_TOGGLE_STP	16
 
 /* prototypes of exported bridging functions... */
 
@@ -295,7 +297,7 @@
 struct fdb *br_avl_insert (struct fdb * new_node);
 void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length);
 int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
-
+void br_avl_delete_by_port(int port);
 /* externs */
 
 extern struct br_stat br_stats;
diff -urN linux-2.2.3-pre2/include/net/irda/dongle.h linux-2.2.3-pre3/include/net/irda/dongle.h
--- linux-2.2.3-pre2/include/net/irda/dongle.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/dongle.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Mon Dec 14 11:47:25 1998
+ * Modified at:   Sat Feb  6 07:37:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -34,6 +34,7 @@
 	ESI_DONGLE,
 	ACTISYS_DONGLE,
 	ACTISYS_PLUS_DONGLE,
+	GIRBIL_DONGLE,
 } DONGLE_T;
 
 struct dongle {
diff -urN linux-2.2.3-pre2/include/net/irda/ircomm_common.h linux-2.2.3-pre3/include/net/irda/ircomm_common.h
--- linux-2.2.3-pre2/include/net/irda/ircomm_common.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/ircomm_common.h	2003-08-15 15:05:26.000000000 -0700
@@ -149,6 +149,7 @@
 	int max_txbuff_size;          
 	int maxsdusize;
  	__u32 daddr;        /* Device address of the peer device */ 
+	__u32 saddr;
 
 	void (*d_handler)(struct ircomm_cb *self);
 	struct notify_t notify;     /* container of callbacks */
diff -urN linux-2.2.3-pre2/include/net/irda/irda_device.h linux-2.2.3-pre3/include/net/irda/irda_device.h
--- linux-2.2.3-pre2/include/net/irda/irda_device.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irda_device.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Haris Zukanovic <haris@stud.cs.uit.no>
  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Mon Jan 18 10:52:10 1999
+ * Modified at:   Tue Feb  9 14:01:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
@@ -35,11 +35,13 @@
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
 
-#define SIR_MODE 	0x01
-#define MIR_MODE 	0x02
-#define FIR_MODE 	0x04
-#define IO_PIO   	0x08
-#define IO_DMA		0x10
+/* Some non-standard interface flags (should not conflict with any in if.h */
+#define IFF_SIR 	0x01 /* Supports SIR speeds */
+#define IFF_MIR 	0x02 /* Supports MIR speeds */
+#define IFF_FIR 	0x04 /* Supports FIR speeds */
+#define IFF_PIO   	0x08 /* Supports PIO transfer of data */
+#define IFF_DMA		0x10 /* Supports DMA transfer of data */
+#define IFF_DONGLE      0x20 /* Interface has a dongle attached */
 
 #define IO_XMIT 0x01
 #define IO_RECV 0x02
@@ -93,7 +95,7 @@
 	struct device netdev;   /* Yes! we are some kind of netdevice */
 	struct enet_statistics stats;
 
-/* 	int flags; */
+ 	int flags;            /* Interface flags (see defs above) */
 
  	void *priv;           /* Pointer to low level implementation */
 
@@ -103,6 +105,7 @@
 	struct iobuff_t tx_buff;
 	struct iobuff_t rx_buff;
 
+	int xbofs;
 	int media_busy;
 	
 	/* Media busy stuff */
diff -urN linux-2.2.3-pre2/include/net/irda/irda.h linux-2.2.3-pre3/include/net/irda/irda.h
--- linux-2.2.3-pre2/include/net/irda/irda.h	1999-01-24 21:55:04.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irda.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Sat Jan 16 01:23:15 1999
+ * Modified at:   Wed Jan 27 14:15:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -44,7 +44,7 @@
 
 extern __u32 irda_debug;
 
-#define IRDA_DEBUG 3
+#define IRDA_DEBUG 0
 
 #define DEBUG(n, args...) if (irda_debug >= (n)) printk( KERN_DEBUG args)
 #define ASSERT(expr, func) \
diff -urN linux-2.2.3-pre2/include/net/irda/iriap.h linux-2.2.3-pre3/include/net/irda/iriap.h
--- linux-2.2.3-pre2/include/net/irda/iriap.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/iriap.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      iriap.h
- * Version:       
+ * Version:       0.5
  * Description:   Information Access Protocol (IAP)
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sat Dec  5 13:45:37 1998
+ * Modified at:   Tue Jan 26 11:50:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -55,23 +55,13 @@
 typedef void (*CONFIRM_CALLBACK)( __u16 obj_id, struct ias_value *value,
 				  void *priv);
 
-struct iap_value {
-	char *full;
-        char *name;
-        char *attr;
-        __u16   obj_id;
-        __u8    ret_code;
-        __u8    type;
-        int     len;
-        int value_int;
-        char *value_char;
-};
-
 struct iriap_cb {
 	QUEUE queue; /* Must be first */
 	
 	int          magic;  /* Magic cookie */
 	int          mode;   /* Client or server */
+
+	__u32        saddr;
 	__u32        daddr;
 	__u8         operation;
 
@@ -95,10 +85,10 @@
 
 int  iriap_init(void);
 void iriap_cleanup(void);
-void iriap_getvaluebyclass_request( __u32 addr, char *name, char *attr, 
+void iriap_getvaluebyclass_request( char *name, char *attr, 
+				    __u32 saddr, __u32 daddr,
 				    CONFIRM_CALLBACK callback, void *priv);
-void iriap_getvaluebyclass_confirm( struct iriap_cb *self, 
-				    struct sk_buff *skb);
+void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
 
 void iriap_send_ack( struct iriap_cb *self);
 void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb);
@@ -121,3 +111,5 @@
 }
 
 #endif
+
+
diff -urN linux-2.2.3-pre2/include/net/irda/irias_object.h linux-2.2.3-pre3/include/net/irda/irias_object.h
--- linux-2.2.3-pre2/include/net/irda/irias_object.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irias_object.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:49:50 1998
- * Modified at:   Sun Oct 25 00:28:56 1998
+ * Modified at:   Wed Feb  3 10:38:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -25,7 +25,7 @@
 #ifndef LM_IAS_OBJECT_H
 #define LM_IAS_OBJECT_H
 
-#include "irqueue.h"
+#include <net/irda/irqueue.h>
 
 /* LM-IAS Attribute types */
 #define IAS_MISSING 0
@@ -38,12 +38,10 @@
  */
 struct ias_object {
 	QUEUE queue;     /* Must be first! */
-
 	int magic;
 	
 	char  *name;
 	int   id;
-
 	hashbin_t *attribs;
 };
 
@@ -51,8 +49,7 @@
  *  Values used by LM-IAS attributes
  */
 struct ias_value {
-	/* Value description */
-        __u8    type;
+        __u8    type;    /* Value description */
 	int     charset; /* Only used by string type */
         int     len;
 	
@@ -68,16 +65,11 @@
  *  Attributes used by LM-IAS objects
  */
 struct ias_attrib {
-	QUEUE queue;     /* Must be first! */
-
+	QUEUE queue; /* Must be first! */
 	int magic;
 
-	/* Attribute name */
-        char *name;
- /*        char *attr; What do we need this for?  */
-
-	/* Attribute value */
-	struct ias_value *value;
+        char *name;   	         /* Attribute name */
+	struct ias_value *value; /* Attribute value */
 };
 
 char *strdup( char *str);
@@ -87,12 +79,12 @@
 void __irias_delete_object( struct ias_object *obj);
 void irias_delete_object( char *name);
 
-void irias_add_integer_attrib( struct ias_object *obj, char *name, 
-			       int value);
-void irias_add_string_attrib( struct ias_object *obj, char *name, 
-			      char *value);
-void irias_add_octseq_attrib( struct ias_object *obj, char *name, 
-			      __u8 *octets, int len);
+void irias_add_integer_attrib(struct ias_object *obj, char *name, int value);
+void irias_add_string_attrib(struct ias_object *obj, char *name, char *value);
+void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+			     int len);
+int irias_object_change_attribute(char *obj_name, char *attrib_name, 
+				  struct ias_value *new_value);
 struct ias_object *irias_find_object( char *name);
 struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name);
 
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_client.h linux-2.2.3-pre3/include/net/irda/irlan_client.h
--- linux-2.2.3-pre2/include/net/irda/irlan_client.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_client.h	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,44 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client.h
+ * Version:       0.3
+ * Description:   IrDA LAN access layer
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb  3 14:29:49 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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 IRLAN_CLIENT_H
+#define IRLAN_CLIENT_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irlan_event.h>
+
+void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout);
+void irlan_client_discovery_indication(DISCOVERY*);
+void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr);
+
+void irlan_client_open_ctrl_tsap( struct irlan_cb *self);
+
+void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb);
+void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, 
+				     void *priv);
+#endif
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_cli.h linux-2.2.3-pre3/include/net/irda/irlan_cli.h
--- linux-2.2.3-pre2/include/net/irda/irlan_cli.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_cli.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,65 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      client.h
- * Version:       0.3
- * Description:   IrDA LAN access layer
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Oct 19 12:37:20 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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 IRLAN_CLIENT_H
-#define IRLAN_CLIENT_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-int  irlan_client_init(void);
-void irlan_client_cleanup(void);
-
-void irlan_discovery_indication( DISCOVERY*);
-void irlan_client_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, struct sk_buff *);
-
-void irlan_client_data_indication( void *instance, void *sap, 
-				   struct sk_buff *skb);
-
-void irlan_client_control_data_indication( void *instance, void *sap, 
-					   struct sk_buff *skb);
-
-void irlan_client_connect_confirm( void *instance, void *sap, 
-				   struct qos_info *qos, int max_sdu_size,
-				   struct sk_buff *);
-void irlan_client_connect_indication( void *instance, void *sap, 
-				      struct sk_buff *);
-void irlan_client_connect_response( void *instance, void *sap, 
-				    int max_sdu_size, struct sk_buff *skb);
-
-void irlan_client_open_tsaps( struct irlan_cb *self);
-
-void irlan_client_extract_params( struct irlan_cb *self, 
-				  struct sk_buff *skb);
-void check_response_param( struct irlan_cb *self, char *param, 
-			   char *value, int val_len);
-void handle_request( struct irlan_cb *self);
-void irlan_client_register_server(void);
-void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, 
-				     void *priv);
-
-#endif
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_common.h linux-2.2.3-pre3/include/net/irda/irlan_common.h
--- linux-2.2.3-pre2/include/net/irda/irlan_common.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_common.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
- * Filename:      irlan.h
- * Version:       0.1
+ * Filename:      irlan_common.h
+ * Version:       0.8
  * Description:   IrDA LAN access layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Oct 29 13:23:11 1998
+ * Modified at:   Wed Feb 17 23:28:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -30,10 +30,11 @@
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 
-#include "irqueue.h"
-#include "irttp.h"
+#include <net/irda/irqueue.h>
+#include <net/irda/irttp.h>
 
-#define IRLAN_MTU 1518
+#define IRLAN_MTU        1518
+#define IRLAN_TIMEOUT    1000
 
 /* Command packet types */
 #define CMD_GET_PROVIDER_INFO   0
@@ -61,23 +62,23 @@
 #define MEDIA_802_5 2
 
 /* Filter parameters */
-#define DATA_CHAN 1
+#define DATA_CHAN   1
 #define FILTER_TYPE 2
 #define FILTER_MODE 3
 
 /* Filter types */
-#define IR_DIRECTED   1
-#define IR_FUNCTIONAL 2
-#define IR_GROUP      3
-#define IR_MAC_FRAME  4
-#define IR_MULTICAST  5
-#define IR_BROADCAST  6
-#define IR_IPX_SOCKET 7
+#define IRLAN_DIRECTED   0x01
+#define IRLAN_FUNCTIONAL 0x02
+#define IRLAN_GROUP      0x04
+#define IRLAN_MAC_FRAME  0x08
+#define IRLAN_MULTICAST  0x10
+#define IRLAN_BROADCAST  0x20
+#define IRLAN_IPX_SOCKET 0x40
 
 /* Filter modes */
-#define ALL    1
-#define FILTER 2
-#define NONE   3
+#define ALL     1
+#define FILTER  2
+#define NONE    3
 
 /* Filter operations */
 #define GET     1
@@ -87,36 +88,51 @@
 #define DYNAMIC 5
 
 /* Access types */
-#define DIRECT 1
-#define PEER   2
-#define HOSTED 3
+#define ACCESS_DIRECT  1
+#define ACCESS_PEER    2
+#define ACCESS_HOSTED  3
+
+#define IRLAN_BYTE   0
+#define IRLAN_SHORT  1
+#define IRLAN_ARRAY  2
 
 #define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
 
 /*
- *  IrLAN client subclass
+ *  IrLAN client
  */
 struct irlan_client_cb {
-	/*
-	 *  Client fields
-	 */
+	int state;
+
 	int open_retries;
+
+	struct tsap_cb *tsap_ctrl;
 	
 	__u8 reconnect_key[255];
 	__u8 key_len;
 	
+	__u16 recv_arb_val;
+	__u16 max_frame;
+	int filter_type;
+
 	int unicast_open;
 	int broadcast_open;
+
+	struct timer_list kick_timer;
+	int start_new_provider;
 };
 
 /*
- * IrLAN servers subclass
+ * IrLAN provider
  */
-struct irlan_server_cb {
+struct irlan_provider_cb {
+	int state;
 	
+	struct tsap_cb *tsap_ctrl;
+
 	/*
-	 *  Store some values here which are used by the irlan_server to parse
-	 *  FILTER_OPERATIONs
+	 *  Store some values here which are used by the provider to parse
+	 *  the filter operations
 	 */
 	int data_chan;
 	int filter_type;
@@ -124,11 +140,13 @@
 	int filter_operation;
 	int filter_entry;
 
+	__u16 send_arb_val;
+
 	__u8 mac_address[6]; /* Generated MAC address for peer device */
 };
 
 /*
- *  IrLAN super class
+ *  IrLAN
  */
 struct irlan_cb {
 	QUEUE queue; /* Must be first */
@@ -140,57 +158,52 @@
 
 	__u32 saddr;        /* Source devcie address */
 	__u32 daddr;        /* Destination device address */
-	int   connected;    /* TTP layer ready to exchange ether frames */
+	int   netdev_registered;
+	int   notify_irmanager;
 	
-	int state;  /* Current state of IrLAN layer */
-
-	int media;	
+	int media;          /* Media type */
+	int access_type;    /* Currently used access type */
+	__u8 version[2];    /* IrLAN version */
 	
-	struct tsap_cb *tsap_ctrl;
 	struct tsap_cb *tsap_data;
 
 	int  use_udata;  /* Use Unit Data transfers */
 
-	__u8 dtsap_sel_data; /* Destination data TSAP selector */
 	__u8 stsap_sel_data; /* Source data TSAP selector */
+	__u8 dtsap_sel_data; /* Destination data TSAP selector */
 	__u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */
 
-	int client; /* Client or server */
-	union {
-		struct irlan_client_cb client;
-		struct irlan_server_cb server;
-	} t;
-
-	/* void (*irlan_dev_init)(struct irlan_cb *); */
-
-	/* 
-         *  Used by extract_params, placed here for now to avoid placing 
-         *  them on the stack. FIXME: remove these!
-         */
-        char name[255];
-        char value[1016];
+	struct irlan_client_cb client;     /* Client specific fields */
+	struct irlan_provider_cb provider; /* Provider specific fields */
+	
+	struct timer_list watchdog_timer;
 };
 
-struct irlan_cb *irlan_open(void);
-
-void irlan_get_provider_info( struct irlan_cb *self);
-void irlan_get_unicast_addr( struct irlan_cb *self);
-void irlan_get_media_char( struct irlan_cb *self);
-void irlan_open_data_channel( struct irlan_cb *self);
-void irlan_set_multicast_filter( struct irlan_cb *self, int status);
-void irlan_set_broadcast_filter( struct irlan_cb *self, int status);
-void irlan_open_unicast_addr( struct irlan_cb *self);
-
-int insert_byte_param( struct sk_buff *skb, char *param, __u8 value);
-int insert_string_param( struct sk_buff *skb, char *param, char *value);
-int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, 
-			__u16 value_len);
-
-int insert_param( struct sk_buff *skb, char *param, int type, char *value_char,
-		  __u8 value_byte, __u16 value_short);
+struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev);
+void irlan_close(struct irlan_cb *self);
+int  irlan_register_netdev(struct irlan_cb *self);
+void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel);
+void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout);
+
+void irlan_open_data_tsap(struct irlan_cb *self);
+
+void irlan_get_provider_info(struct irlan_cb *self);
+void irlan_get_unicast_addr(struct irlan_cb *self);
+void irlan_get_media_char(struct irlan_cb *self);
+void irlan_open_data_channel(struct irlan_cb *self);
+void irlan_close_data_channel(struct irlan_cb *self);
+void irlan_set_multicast_filter(struct irlan_cb *self, int status);
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status);
+void irlan_open_unicast_addr(struct irlan_cb *self);
+
+int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value);
+int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value);
+int irlan_insert_string_param(struct sk_buff *skb, char *param, char *value);
+int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *value, 
+			     __u16 value_len);
 
-int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len);
-void print_ret_code( __u8 code);
+int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len);
+void print_ret_code(__u8 code);
 
 extern hashbin_t *irlan;
 
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_eth.h linux-2.2.3-pre3/include/net/irda/irlan_eth.h
--- linux-2.2.3-pre2/include/net/irda/irlan_eth.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_eth.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:36:58 1998
- * Modified at:   Thu Oct 15 12:28:12 1998
+ * Modified at:   Fri Jan 29 15:20:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -25,12 +25,8 @@
 #ifndef IRLAN_ETH_H
 #define IRLAN_ETH_H
 
-int irlan_eth_init( struct device *dev);
-int irlan_eth_open( struct device *dev);
-int irlan_eth_close( struct device *dev);
-
-void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb);
-int irlan_eth_tx( struct sk_buff *skb, struct device *dev);
+void irlan_eth_receive( void *instance, void *sap, struct sk_buff *skb);
+int  irlan_eth_xmit( struct sk_buff *skb, struct device *dev);
 
 void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
 
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_event.h linux-2.2.3-pre3/include/net/irda/irlan_event.h
--- linux-2.2.3-pre2/include/net/irda/irlan_event.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_event.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Tue Oct 20 09:59:31 1998
+ * Modified at:   Tue Feb  2 09:45:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -44,7 +44,6 @@
 	IRLAN_SYNC
 } IRLAN_STATE;
 
-/* IrLAN Client Events */
 typedef enum {
 	IRLAN_DISCOVERY_INDICATION,
 	IRLAN_IAS_PROVIDER_AVAIL,
@@ -61,26 +60,22 @@
 	IRLAN_GET_MEDIA_CMD,
 	IRLAN_OPEN_DATA_CMD,
 	IRLAN_FILTER_CONFIG_CMD,
-} IRLAN_EVENT;
 
-struct irlan_info {
-	__u8   dlsap_sel;
-	__u32  daddr;
-	struct tsap_cb *tsap;
-};
+	IRLAN_CHECK_CON_ARB,
+	IRLAN_PROVIDER_SIGNAL,
+
+	IRLAN_WATCHDOG_TIMEOUT,
+} IRLAN_EVENT;
 
 extern char *irlan_state[];
 
-void irlan_do_client_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb);
-
-void irlan_do_server_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlan_info *info);
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			   struct sk_buff *skb);
+
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			     struct sk_buff *skb);
 
-void irlan_next_state( struct irlan_cb *self, 
-		       IRLAN_STATE state);
+void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state);
+void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state);
 
 #endif
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_filter.h linux-2.2.3-pre3/include/net/irda/irlan_filter.h
--- linux-2.2.3-pre2/include/net/irda/irlan_filter.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_filter.h	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,33 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_filter.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Jan 29 15:24:08 1999
+ * Modified at:   Sun Feb  7 23:35:31 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 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 IRLAN_FILTER_H
+#define IRLAN_FILTER_H
+
+void irlan_check_command_param(struct irlan_cb *self, char *param, 
+			       char *value);
+void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb);
+int irlan_print_filter(int filter_type, char *buf);
+
+#endif /* IRLAN_FILTER_H */
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_provider.h linux-2.2.3-pre3/include/net/irda/irlan_provider.h
--- linux-2.2.3-pre2/include/net/irda/irlan_provider.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_provider.h	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,57 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider.h
+ * Version:       0.1
+ * Description:   IrDA LAN access layer
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Sat Jan 30 16:22:24 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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 IRLAN_SERVER_H
+#define IRLAN_SERVER_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irlan_common.h>
+
+void irlan_provider_ctrl_disconnect_indication(void *instance, void *sap, 
+					       LM_REASON reason, 
+					       struct sk_buff *skb);
+
+void irlan_provider_ctrl_data_indication(void *instance, void *sap,
+					 struct sk_buff *skb);
+
+void irlan_provider_connect_indication(void *instance, void *sap, 
+				       struct qos_info *qos, int max_sdu_size,
+				       struct sk_buff *skb);
+void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *);
+
+int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb);
+int irlan_provider_extract_params(struct irlan_cb *self, int cmd,
+				  struct sk_buff *skb);
+
+void irlan_provider_send_reply(struct irlan_cb *self, int command, 
+			       int ret_code);
+void irlan_provider_open_ctrl_tsap( struct irlan_cb *self);
+
+#endif
+
+
diff -urN linux-2.2.3-pre2/include/net/irda/irlan_srv.h linux-2.2.3-pre3/include/net/irda/irlan_srv.h
--- linux-2.2.3-pre2/include/net/irda/irlan_srv.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlan_srv.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,62 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      server.h
- * Version:       0.1
- * Description:   IrDA LAN access layer
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Fri Oct 16 11:25:37 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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 IRLAN_SERVER_H
-#define IRLAN_SERVER_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-#include <net/irda/irlan_common.h>
-
-int  irlan_server_init(void);
-void irlan_server_cleanup(void);
-struct irlan_cb *irlan_server_open(void);
-void irlan_server_close( struct irlan_cb *self);
-
-void irlan_server_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *skb);
-
-void irlan_server_data_indication( void *instance, void *sap,
-				   struct sk_buff *skb);
-void irlan_server_control_data_indication( void *instance, void *sap,
-					   struct sk_buff *skb);
-
-void irlan_server_connect_indication( void *instance, void *sap, 
-				      struct qos_info *qos, int max_sdu_size,
-				      struct sk_buff *skb);
-void irlan_server_connect_response( struct irlan_cb *, struct tsap_cb *);
-
-int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb);
-int irlan_server_extract_params( struct irlan_cb *self, int cmd,
-				  struct sk_buff *skb);
-
-void irlan_server_send_reply( struct irlan_cb *self, int command, 
-			      int ret_code);
-void irlan_server_register(void);
-
-#endif
diff -urN linux-2.2.3-pre2/include/net/irda/irlap_event.h linux-2.2.3-pre3/include/net/irda/irlap_event.h
--- linux-2.2.3-pre2/include/net/irda/irlap_event.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlap_event.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Thu Dec 17 11:58:10 1998
+ * Modified at:   Thu Feb 11 00:41:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -111,7 +111,7 @@
 	DISCOVERY *discovery; /* Discovery information */
 };
 
-extern char *irlap_state[];
+extern const char *irlap_state[];
 
 void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
 		     struct sk_buff *skb, struct irlap_info *info);
diff -urN linux-2.2.3-pre2/include/net/irda/irlap.h linux-2.2.3-pre3/include/net/irda/irlap.h
--- linux-2.2.3-pre2/include/net/irda/irlap.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlap.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap.h
- * Version:       0.3
+ * Version:       0.8
  * Description:   An IrDA LAP driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Dec 12 12:25:33 1998
+ * Modified at:   Mon Jan 25 13:58:59 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -105,6 +105,7 @@
 	struct timer_list backoff_timer;
 
 	/* Timeouts which will be different with different turn time */
+	int slot_timeout;
 	int poll_timeout;
 	int final_timeout;
 	int wd_timeout;
@@ -118,14 +119,15 @@
 	int     retry_count;  /* Times tried to establish connection */
 	int     add_wait;     /* True if we are waiting for frame */
 
+	__u8    connect_pending;
+	__u8    disconnect_pending;
+
+	/*  To send a faster RR if tx queue empty */
 #ifdef CONFIG_IRDA_FAST_RR
-	/* 
-	 *  To send a faster RR if tx queue empty 
-	 */
 	int     fast_RR_timeout;
 	int     fast_RR;      
 #endif
-
+	
 	int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */
 	int N2; /* N2 * F-timer = Negitiated link disconnect time */
 	int N3; /* Connection retry count */
diff -urN linux-2.2.3-pre2/include/net/irda/irlmp_event.h linux-2.2.3-pre3/include/net/irda/irlmp_event.h
--- linux-2.2.3-pre2/include/net/irda/irlmp_event.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlmp_event.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Wed Oct 28 14:58:23 1998
+ * Modified at:   Thu Feb 11 00:42:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -72,7 +72,7 @@
 	LM_LAP_DISCONNECT_REQUEST,
 	LM_LAP_DISCOVERY_REQUEST,
  	LM_LAP_DISCOVERY_CONFIRM,
-
+	LM_LAP_IDLE_TIMEOUT,
 } IRLMP_EVENT;
 
 /*
@@ -95,11 +95,12 @@
 	DISCOVERY *discovery;
 };
 
-extern char *irlmp_state[];
-extern char *irlsap_state[];
+extern const char *irlmp_state[];
+extern const char *irlsap_state[];
 
 void irlmp_watchdog_timer_expired( unsigned long data);
 void irlmp_discovery_timer_expired( unsigned long data);
+void irlmp_idle_timer_expired( unsigned long data);
 
 void irlmp_next_station_state( IRLMP_STATE state);
 void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state);
diff -urN linux-2.2.3-pre2/include/net/irda/irlmp_frame.h linux-2.2.3-pre3/include/net/irda/irlmp_frame.h
--- linux-2.2.3-pre2/include/net/irda/irlmp_frame.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlmp_frame.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Sun Oct 25 00:30:31 1998
+ * Modified at:   Tue Feb  2 11:07:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -42,8 +42,8 @@
 			 __u8 opcode, struct sk_buff *skb);
 void irlmp_link_data_indication( struct lap_cb *, int reliable, 
 				 struct sk_buff *);
-void irlmp_link_connect_indication( struct lap_cb *, struct qos_info *qos, 
-				    struct sk_buff *skb);
+void irlmp_link_connect_indication( struct lap_cb *, __u32 saddr, __u32 daddr,
+				    struct qos_info *qos, struct sk_buff *skb);
 void irlmp_link_connect_request( __u32 daddr);
 void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, 
 				 struct sk_buff *skb);
diff -urN linux-2.2.3-pre2/include/net/irda/irlmp.h linux-2.2.3-pre3/include/net/irda/irlmp.h
--- linux-2.2.3-pre2/include/net/irda/irlmp.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlmp.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Mon Dec  7 21:11:32 1998
+ * Modified at:   Thu Feb  4 11:06:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -28,17 +28,19 @@
 #include <linux/config.h>
 #include <linux/types.h>
 
-#include "irmod.h"
-#include "qos.h"
-#include "irlap.h"
-#include "irlmp_event.h"
-#include "irqueue.h"
+#include <net/irda/irmod.h>
+#include <net/irda/qos.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp_event.h>
+#include <net/irda/irqueue.h>
 
 /* LSAP-SEL's */
 #define LSAP_MASK     0x7f
 #define LSAP_IAS      0x00
 #define LSAP_ANY      0xff
 
+#define DEV_ADDR_ANY  0xffffffff
+
 /* Predefined LSAPs used by the various servers */
 #define TSAP_IRLAN    0x05
 #define LSAP_IRLPT    0x06
@@ -69,6 +71,8 @@
 #define HINT_HTTP        0x10
 #define HINT_OBEX        0x20
 
+#define LM_IDLE_TIMEOUT  200 /* 2 seconds for now */
+
 typedef enum {
 	S_PNP,
 	S_PDA,
@@ -150,6 +154,7 @@
 	hashbin_t *cachelog;    /* Discovered devices for this link */
 
 	struct qos_info *qos;  /* LAP QoS for this session */
+	struct timer_list idle_timer;
 };
 
 /*
@@ -171,10 +176,8 @@
 
 	__u8 conflict_flag;
 	
-	/* int discovery; */
-
-	DISCOVERY  discovery_rsp; /* Discovery response to use by IrLAP */
 	DISCOVERY  discovery_cmd; /* Discovery command to use by IrLAP */
+	DISCOVERY  discovery_rsp; /* Discovery response to use by IrLAP */
 
 	int free_lsap_sel;
 
@@ -205,7 +208,8 @@
 			   struct notify_t *);
 void irlmp_unregister_irlap( __u32 saddr);
 
-void irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, __u32 daddr, 
+int  irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, 
+			    __u32 saddr, __u32 daddr,
 			    struct qos_info *, struct sk_buff *);
 void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb);
 void irlmp_connect_response( struct lsap_cb *, struct sk_buff *);
@@ -231,9 +235,14 @@
 
 int  irlmp_slsap_inuse( __u8 slsap);
 __u8 irlmp_find_free_slsap(void);
-
 LM_REASON irlmp_convert_lap_reason( LAP_REASON);
 
+__u32 irlmp_get_saddr(struct lsap_cb *self);
+__u32 irlmp_get_daddr(struct lsap_cb *self);
+
+
+extern char *lmp_reasons[];
+extern int sysctl_discovery_slots;
 extern struct irlmp_cb *irlmp;
 
 #endif
diff -urN linux-2.2.3-pre2/include/net/irda/irlpt_cli_fsm.h linux-2.2.3-pre3/include/net/irda/irlpt_cli_fsm.h
--- linux-2.2.3-pre2/include/net/irda/irlpt_cli_fsm.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlpt_cli_fsm.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,19 +1,21 @@
 /*********************************************************************
  *                
- * Filename:      irlpt_client_fsm.h
+ * Filename:      irlpt_cli_fsm.h
  * Version:       0.1
  * Sources:       irlan_event.h
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, All Rights Reserved.
+ *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, 
+ *		All Rights Reserved.
+ *     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 
  *     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.
+ *     I, Thomas Davis, provide no warranty for any of this software. 
+ *     This material is provided "AS-IS" and at no charge.
  *
  ********************************************************************/
 
diff -urN linux-2.2.3-pre2/include/net/irda/irlpt_cli.h linux-2.2.3-pre3/include/net/irda/irlpt_cli.h
--- linux-2.2.3-pre2/include/net/irda/irlpt_cli.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlpt_cli.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,6 +1,6 @@
 /*********************************************************************
  *                
- * Filename:      irlpt_client.h
+ * Filename:      irlpt_cli.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
@@ -35,8 +35,10 @@
  */
 
 void irlpt_client_get_value_confirm(__u16 obj_id, 
-				    struct ias_value *value, void *priv);
-void irlpt_client_connect_indication( void *instance, void *sap, 
+				    struct ias_value *value, 
+				    void *priv);
+void irlpt_client_connect_indication( void *instance, 
+				      void *sap, 
 				      struct qos_info *qos, 
 				      int max_seg_size,
 				      struct sk_buff *skb);
diff -urN linux-2.2.3-pre2/include/net/irda/irlpt_common.h linux-2.2.3-pre3/include/net/irda/irlpt_common.h
--- linux-2.2.3-pre2/include/net/irda/irlpt_common.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlpt_common.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,6 +1,6 @@
 /*********************************************************************
  *
- * Filename:      irlpt.c
+ * Filename:      irlpt_common.h
  * Version:       
  * Description:   
  * Status:        Experimental.
@@ -67,7 +67,6 @@
 	IRLPT_CLIENT_QUERY,
 	IRLPT_CLIENT_READY,
 	IRLPT_CLIENT_WAITI,
-	IRLPT_CLIENT_WAITR,
 	IRLPT_CLIENT_CONN,
 } IRLPT_CLIENT_STATE;
 
@@ -87,10 +86,6 @@
 	LMP_DISCONNECT,
 	LMP_CONNECT_INDICATION,
 	LMP_DISCONNECT_INDICATION,
-#if 0
-	TTP_CONNECT_INDICATION,
-	TTP_DISCONNECT_INDICATION,
-#endif
         IRLPT_DISCOVERY_INDICATION,
 	IRLPT_CONNECT_REQUEST,
 	IRLPT_DISCONNECT_REQUEST,
@@ -101,6 +96,7 @@
 	struct lsap_cb *lsap;
 	__u8 dlsap_sel;
 	__u32 daddr;
+	__u32 saddr;
 };
 
 /* Command packet types */
@@ -142,7 +138,8 @@
 
 	int magic;		/* magic used to detect corruption of 
 				   the struct */
-	__u32 daddr;		/* my local address. */
+	__u32 daddr;		/* address of remote printer */
+	__u32 saddr;            /* my local address. */
 
 	struct timer_list retry_timer;
 	
@@ -168,6 +165,14 @@
 	struct wait_queue *write_wait;
 	struct wait_queue *ex_wait;
 
+	/* this is used to remove the printer when it's gone */
+	struct timer_list lpt_timer;
+	void (*timeout) (unsigned long data);
+
+	void (*do_event) (struct irlpt_cb *self, IRLPT_EVENT event, 
+			  struct sk_buff *skb,
+			  struct irlpt_info *info);
+
 	/* this is used by the server side of the system */
 
         IRLPT_SERVER_STATE connected;
diff -urN linux-2.2.3-pre2/include/net/irda/irlpt_server_fsm.h linux-2.2.3-pre3/include/net/irda/irlpt_server_fsm.h
--- linux-2.2.3-pre2/include/net/irda/irlpt_server_fsm.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlpt_server_fsm.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,19 +1,21 @@
 /*********************************************************************
  *                
- * Filename:      server_fsm.h<2>
+ * Filename:      server_server_fsm.h
  * Version:       0.1
  * Sources:       irlan_event.h
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, All Rights Reserved.
+ *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, 
+ *		All Rights Reserved.
+ *     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 
  *     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.
+ *     I, Thomas Davis, provide no warranty for any of this software. 
+ *     This material is provided "AS-IS" and at no charge.
  *
  ********************************************************************/
 
@@ -23,8 +25,11 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 
-void irlpt_server_do_event( struct irlpt_cb *self,  IRLPT_EVENT event, 
-			    struct sk_buff *skb, struct irlpt_info *info);
-void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_SERVER_STATE state);
+void irlpt_server_do_event( struct irlpt_cb *self, 
+			    IRLPT_EVENT event, 
+			    struct sk_buff *skb, 
+			    struct irlpt_info *info);
+void irlpt_server_next_state( struct irlpt_cb *self, 
+			      IRLPT_SERVER_STATE state);
 
 #endif
diff -urN linux-2.2.3-pre2/include/net/irda/irlpt_server.h linux-2.2.3-pre3/include/net/irda/irlpt_server.h
--- linux-2.2.3-pre2/include/net/irda/irlpt_server.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irlpt_server.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,6 +1,6 @@
 /*********************************************************************
  *                
- * Filename:      server.h
+ * Filename:      irlpt_server.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
diff -urN linux-2.2.3-pre2/include/net/irda/irmod.h linux-2.2.3-pre3/include/net/irda/irmod.h
--- linux-2.2.3-pre2/include/net/irda/irmod.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irmod.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:58:52 1997
- * Modified at:   Tue Jan 12 14:56:11 1999
+ * Modified at:   Thu Feb 11 15:14:30 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -45,6 +45,7 @@
 	EVENT_IRLAN_STOP,
 	EVENT_IRLPT_START,
 	EVENT_IRLPT_STOP,
+/* 	EVENT_IROBEX_INIT, */
 	EVENT_IROBEX_START,
 	EVENT_IROBEX_STOP,
 	EVENT_IRDA_STOP,
@@ -190,7 +191,13 @@
 	LM_CONNECT_FAILURE,   /* Failed to establish IrLAP connection */
 	LM_LAP_RESET,         /* IrLAP reset */
 	LM_INIT_DISCONNECT,   /* Link Management initiated disconnect */
-} LM_REASON; /* FIXME: Just for now */
+	LM_LSAP_NOTCONN,      /* Data delivered on unconnected LSAP */
+	LM_NON_RESP_CLIENT,   /* Non responsive LM-MUX client */
+	LM_NO_AVAIL_CLIENT,   /* No available LM-MUX client */
+	LM_CONN_HALF_OPEN,    /* Connection is half open */
+	LM_BAD_SOURCE_ADDR,   /* Illegal source address (i.e 0x00) */
+} LM_REASON;
+#define LM_UNKNOWN 0xff       /* Unspecified disconnect reason */
 
 /*
  *  IrLMP character code values
@@ -214,16 +221,17 @@
 struct discovery_t {
 	QUEUE queue;              /* Must be first! */
 
-	__u32       saddr;        /* Which link the device was discovered */
-	__u32       daddr;        /* Remote device address */
-	LAP_REASON  condition;    /* More info about the discovery */
-
-	__u8        hint[2];      /* Discovery hint bits */
-	__u8        charset;
-	char        info[32];     /* Usually the name of the device */
-	__u8        info_len;     /* Length of device info field */
+	__u32      saddr;        /* Which link the device was discovered */
+	__u32      daddr;        /* Remote device address */
+	LAP_REASON condition;    /* More info about the discovery */
+
+	__u8       hint[2];      /* Discovery hint bits */
+	__u8       charset;
+	char       info[32];     /* Usually the name of the device */
+	__u8       info_len;     /* Length of device info field */
 
-	int         gen_addr_bit; /* Need to generate a new device address? */
+	int        gen_addr_bit; /* Need to generate a new device address? */
+	int        nslots;       /* Number of slots to use when discovering */
 };
 
 typedef enum { FLOW_STOP, FLOW_START } LOCAL_FLOW;
@@ -254,12 +262,14 @@
 int irmod_init_module(void);
 void irmod_cleanup_module(void);
 
-inline int irda_lock( int *lock);
-inline int irda_unlock( int *lock);
+inline int irda_lock(int *lock);
+inline int irda_unlock(int *lock);
 
-void irda_notify_init( struct notify_t *notify);
+void irda_notify_init(struct notify_t *notify);
 
-void irda_execute_as_process( void *self, TODO_CALLBACK callback, __u32 param);
-void irmanager_notify( struct irmanager_event *event);
+void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param);
+void irmanager_notify(struct irmanager_event *event);
+
+extern void irda_proc_modcount(struct inode *, int);
 
 #endif
diff -urN linux-2.2.3-pre2/include/net/irda/irobex.h linux-2.2.3-pre3/include/net/irda/irobex.h
--- linux-2.2.3-pre2/include/net/irda/irobex.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irobex.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irobex.h
- * Version:       
+ * Version:       0.8
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Jul  4 22:43:57 1998
- * Modified at:   Wed Jan 13 15:55:28 1999
+ * Modified at:   Tue Jan 26 11:49:55 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
-/* #include <linux/netdevice.h> */
 #include <linux/miscdevice.h>
 
 #include <net/irda/timer.h>
@@ -97,30 +96,7 @@
 	LOCAL_FLOW rx_flow;
 };
 
-int    irobex_init(void);
-void   irobex_cleanup(void);
-struct irobex_cb *irobex_open(void);
-void   irobex_close( struct irobex_cb *self);
-
-void irobex_discovery_indication( DISCOVERY *);
-
-void irobex_data_request( int handle, struct sk_buff *skb);
-void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb);
-void irobex_control_data_indication( void *instance, void *sap, 
-				     struct sk_buff *skb);
-
-void irobex_connect_request( struct irobex_cb *self);
-void irobex_connect(struct irobex_cb *self, struct sk_buff *skb);
-void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-			     int max_sdu_size, struct sk_buff *skb);
-void irobex_disconnect_indication( void *instance, void *sap, LM_REASON reason,
-				   struct sk_buff *skb);
-void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
-
-void irobex_extract_params( struct sk_buff *skb);
-void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, 
-			      void *priv);
-void irobex_register_server( struct irobex_cb *self);
+int irobex_init(void);
 
 void irobex_watchdog_timer_expired( unsigned long data);
 
diff -urN linux-2.2.3-pre2/include/net/irda/irttp.h linux-2.2.3-pre3/include/net/irda/irttp.h
--- linux-2.2.3-pre2/include/net/irda/irttp.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irttp.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irttp.h
- * Version:       0.3
+ * Version:       1.0
  * Description:   Tiny Transport Protocol (TTP) definitions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Sat Dec  5 13:48:12 1998
+ * Modified at:   Tue Feb  2 10:55:18 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -33,21 +33,21 @@
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
 
-#define TTP_MAX_CONNECTIONS   LM_MAX_CONNECTIONS
-#define TTP_HEADER            1
-#define TTP_HEADER_WITH_SAR   6
-#define TTP_PARAMETERS        0x80
-#define TTP_MORE              0x80
+#define TTP_MAX_CONNECTIONS    LM_MAX_CONNECTIONS
+#define TTP_HEADER             1
+#define TTP_HEADER_WITH_SAR    6
+#define TTP_PARAMETERS         0x80
+#define TTP_MORE               0x80
 
 #define DEFAULT_INITIAL_CREDIT 22
 
-#define LOW_THRESHOLD  4
-#define HIGH_THRESHOLD 8
-#define TTP_MAX_QUEUE 22
+#define LOW_THRESHOLD   4
+#define HIGH_THRESHOLD  8
+#define TTP_MAX_QUEUE  22
 
 /* Some priorities for disconnect requests */
-#define P_NORMAL 0
-#define P_HIGH 1
+#define P_NORMAL    0
+#define P_HIGH      1
 
 #define SAR_DISABLE 0
 
@@ -56,13 +56,13 @@
  *  connection.
  */
 struct tsap_cb {
-	QUEUE queue;         /* For linking it into the hashbin */
-	int  magic;          /* Just in case */
+	QUEUE queue;          /* For linking it into the hashbin */
+	int  magic;           /* Just in case */
 
-	int max_seg_size;    /* Max data that fit into an IrLAP frame */
+	int max_seg_size;     /* Max data that fit into an IrLAP frame */
 
-	__u8 stsap_sel;      /* Source TSAP */
-	__u8 dtsap_sel;      /* Destination TSAP */
+	__u8 stsap_sel;       /* Source TSAP */
+	__u8 dtsap_sel;       /* Destination TSAP */
 
 	struct lsap_cb *lsap; /* Corresponding LSAP to this TSAP */
 
@@ -85,8 +85,8 @@
 	struct irda_statistics stats;
 	struct timer_list todo_timer; 
 	
-	int rx_sdu_busy;   /* RxSdu.busy */
-	int rx_sdu_size;   /* The current size of a partially received frame */
+	int rx_sdu_busy;     /* RxSdu.busy */
+	int rx_sdu_size;     /* Current size of a partially received frame */
 	int rx_max_sdu_size; /* Max receive user data size */
 
 	int tx_sdu_busy;     /* TxSdu.busy */
@@ -94,7 +94,8 @@
 
         int no_defrag;       /* Don't reassemble received fragments */
 
-	int disconnect_pend;   /* Disconnect, but still data to send */
+	int close_pend;      /* Close, but disconnect_pend */
+	int disconnect_pend; /* Disconnect, but still data to send */
 	struct sk_buff *disconnect_skb;
 };
 
@@ -107,30 +108,41 @@
 int  irttp_init(void);
 void irttp_cleanup(void);
 
-struct tsap_cb *irttp_open_tsap( __u8 stsap, int credit, 
-				 struct notify_t *notify);
-void irttp_close_tsap( struct tsap_cb *self);
-
-int  irttp_data_request( struct tsap_cb *self, struct sk_buff *skb);
-int  irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb);
-
-void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
-			    struct qos_info *qos, int max_sdu_size, 
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
+				struct notify_t *notify);
+int irttp_close_tsap(struct tsap_cb *self);
+
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb);
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb);
+
+void irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, 
+			   __u32 saddr, __u32 daddr,
+			   struct qos_info *qos, int max_sdu_size, 
+			   struct sk_buff *userdata);
+void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
+			   int max_sdu_size, struct sk_buff *skb);
+void irttp_connect_response(struct tsap_cb *self, int max_sdu_size, 
 			    struct sk_buff *userdata);
-void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos, 
-			    int max_sdu_size, struct sk_buff *skb);
-void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, 
-			     struct sk_buff *userdata);
-
-void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *skb,
-			       int priority);
-void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow);
 
-static __inline__ void irttp_no_reassemble( struct tsap_cb *self)
+void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
+			      int priority);
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow);
+
+static __inline__ void irttp_no_reassemble(struct tsap_cb *self)
 {
 	self->no_defrag = TRUE;
 }
 
+static __inline __u32 irttp_get_saddr(struct tsap_cb *self)
+{
+	return irlmp_get_saddr(self->lsap);
+}
+
+static __inline __u32 irttp_get_daddr(struct tsap_cb *self)
+{
+	return irlmp_get_daddr(self->lsap);
+}
+
 extern struct irttp_cb *irttp;
 
 #endif /* IRTTP_H */
diff -urN linux-2.2.3-pre2/include/net/irda/irtty.h linux-2.2.3-pre3/include/net/irda/irtty.h
--- linux-2.2.3-pre2/include/net/irda/irtty.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/irtty.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irtty.h
- * Version:       0.1
+ * Version:       1.0
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon Dec 14 11:22:37 1998
+ * Modified at:   Sun Feb  7 01:57:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -65,4 +65,6 @@
 int irtty_register_dongle( struct dongle *dongle);
 void irtty_unregister_dongle( struct dongle *dongle);
 
+void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts);
+
 #endif
diff -urN linux-2.2.3-pre2/include/net/irda/pc87108.h linux-2.2.3-pre3/include/net/irda/pc87108.h
--- linux-2.2.3-pre2/include/net/irda/pc87108.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/pc87108.h	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Nov 13 14:37:40 1998
- * Modified at:   Thu Dec 10 19:58:20 1998
+ * Modified at:   Mon Jan 25 23:10:25 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
@@ -148,8 +148,8 @@
 #define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
 #define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
 #define FRM_ST_BAD_CRC  0x04 
-#define FRM_ST_OVR2     0x02 /* Receive overrun */
-#define FRM_ST_OVR1     0x01 /* Frame status FIFO overrun */
+#define FRM_ST_OVR1     0x02 /* Receive overrun */
+#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
 
 #define RFLFL           0x06
 #define RFLFH           0x07
diff -urN linux-2.2.3-pre2/include/net/irda/timer.h linux-2.2.3-pre3/include/net/irda/timer.h
--- linux-2.2.3-pre2/include/net/irda/timer.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/timer.h	2003-08-15 15:05:26.000000000 -0700
@@ -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 Nov  2 14:31:55 1998
+ * Modified at:   Thu Feb  4 11:05:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -26,11 +26,11 @@
 #ifndef TIMER_H
 #define TIMER_H
 
-#include "irda.h"
-#include "irmod.h"
-#include "irlap.h"
-#include "irlmp.h"
-#include "irda_device.h"
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irda_device.h>
 
 /* 
  *  Timeout definitions, some defined in IrLAP p. 92
@@ -53,7 +53,6 @@
 #define QUERY_TIMEOUT          100
 
 #define WATCHDOG_TIMEOUT      2000                /* 20 sec */
-#define RETRY_TIMEOUT           51
 
 typedef void (*TIMER_CALLBACK)( unsigned long);
 
@@ -69,8 +68,10 @@
 inline void irda_device_start_mbusy_timer( struct irda_device *self);
 
 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_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);
diff -urN linux-2.2.3-pre2/include/net/irda/wrapper.h linux-2.2.3-pre3/include/net/irda/wrapper.h
--- linux-2.2.3-pre2/include/net/irda/wrapper.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/include/net/irda/wrapper.h	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.h
- * Version:       
+ * Version:       1.0
  * Description:   IrDA Wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Thu Nov 19 13:17:56 1998
+ * Modified at:   Fri Jan 29 10:15:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -28,7 +28,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 
-#include "irda_device.h"
+#include <net/irda/irda_device.h>
 
 #define BOF  0xc0 /* Beginning of frame */
 #define XBOF 0xff
@@ -40,9 +40,6 @@
 
 #define IR_TRANS 0x20    /* Asynchronous transparency modifier */       
 
-#define SOP BOF  /* Start of */
-#define EOP EOF  /* End of */
-
 enum {
 	OUTSIDE_FRAME = 1, 
 	BEGIN_FRAME, 
diff -urN linux-2.2.3-pre2/MAINTAINERS linux-2.2.3-pre3/MAINTAINERS
--- linux-2.2.3-pre2/MAINTAINERS	2003-08-15 15:05:25.000000000 -0700
+++ linux-2.2.3-pre3/MAINTAINERS	2003-08-15 15:05:26.000000000 -0700
@@ -246,6 +246,12 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
+DOUBLETALK DRIVER
+P:	James R. Van Zandt
+M:	jrv@vanzandt.mv.com
+L:	blinux-list@redhat.com
+S:	Maintained
+
 EATA-DMA SCSI DRIVER
 P:	Michael Neuffer
 M:	mike@i-Connect.Net
diff -urN linux-2.2.3-pre2/mm/filemap.c linux-2.2.3-pre3/mm/filemap.c
--- linux-2.2.3-pre2/mm/filemap.c	2003-08-15 15:05:26.000000000 -0700
+++ linux-2.2.3-pre3/mm/filemap.c	2003-08-15 15:05:26.000000000 -0700
@@ -1334,8 +1334,6 @@
 	if (!inode->i_op || !inode->i_op->readpage)
 		return -ENOEXEC;
 	UPDATE_ATIME(inode);
-	vma->vm_file = file;
-	file->f_count++;
 	vma->vm_ops = ops;
 	return 0;
 }
diff -urN linux-2.2.3-pre2/mm/mmap.c linux-2.2.3-pre3/mm/mmap.c
--- linux-2.2.3-pre2/mm/mmap.c	1999-01-27 10:43:41.000000000 -0800
+++ linux-2.2.3-pre3/mm/mmap.c	2003-08-15 15:05:26.000000000 -0700
@@ -319,6 +319,8 @@
 			file->f_dentry->d_inode->i_writecount++;
 		if (error)
 			goto unmap_and_free_vma;
+		vma->vm_file = file;
+		file->f_count++;
 	}
 
 	/*
diff -urN linux-2.2.3-pre2/mm/swapfile.c linux-2.2.3-pre3/mm/swapfile.c
--- linux-2.2.3-pre2/mm/swapfile.c	1999-01-19 10:01:37.000000000 -0800
+++ linux-2.2.3-pre3/mm/swapfile.c	2003-08-15 15:05:26.000000000 -0700
@@ -556,7 +556,7 @@
 		for (i = 0 ; i < nr_swapfiles ; i++) {
 			if (i == type)
 				continue;
-			if (p->swap_file == swap_info[i].swap_file)
+			if (swap_dentry->d_inode == swap_info[i].swap_file->d_inode)
 				goto bad_swap;
 		}
 	} else
@@ -701,6 +701,8 @@
 	p->swap_map = NULL;
 	p->swap_lockmap = NULL;
 	p->flags = 0;
+	if (!(swap_flags & SWAP_FLAG_PREFER))
+		++least_priority;
 out:
 	if (swap_header)
 		free_page((long) swap_header);
diff -urN linux-2.2.3-pre2/net/ax25/af_ax25.c linux-2.2.3-pre3/net/ax25/af_ax25.c
--- linux-2.2.3-pre2/net/ax25/af_ax25.c	1999-01-04 15:31:35.000000000 -0800
+++ linux-2.2.3-pre3/net/ax25/af_ax25.c	2003-08-15 15:05:26.000000000 -0700
@@ -957,7 +957,7 @@
 						ax25_stop_t3timer(sk->protinfo.ax25);
 						ax25_stop_idletimer(sk->protinfo.ax25);
 						break;
-#ifdef AX25_CONFIG_DAMA_SLAVE
+#ifdef CONFIG_AX25_DAMA_SLAVE
 					case AX25_PROTO_DAMA_SLAVE:
 						ax25_stop_t3timer(sk->protinfo.ax25);
 						ax25_stop_idletimer(sk->protinfo.ax25);
diff -urN linux-2.2.3-pre2/net/bridge/br.c linux-2.2.3-pre3/net/bridge/br.c
--- linux-2.2.3-pre2/net/bridge/br.c	2003-08-15 15:05:26.000000000 -0700
+++ linux-2.2.3-pre3/net/bridge/br.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  *	More hacks to be able to switch protocols on and off by Christoph Lameter
  *	<clameter@debian.org>
  *	Software and more Documentation for the bridge is available from ftp.debian.org
- *	in the bridge package or at ftp.fuller.edu/Linux/bridge
+ *	in the bridgex package
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -63,7 +63,6 @@
 #include <linux/net.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
-#include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ip.h>
@@ -1239,11 +1238,12 @@
 	struct sk_buff *skb;
 	
 	/*
-	 *	Keep silent when disabled
+	 *	Keep silent when disabled or when STP disabled
 	 */
 	 
-	if(!(br_stats.flags & BR_UP))
+	if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
 		return -1;
+
 	/*
 	 *	Create and send the message
 	 */
@@ -1278,10 +1278,10 @@
 	struct sk_buff *skb;
 	
 	/*
-	 *	Keep silent when disabled
+	 *	Keep silent when disabled or when STP disabled
 	 */
 	 
-	if(!(br_stats.flags & BR_UP))
+	if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
 		return -1;
 	
  	
@@ -1350,13 +1350,25 @@
 							enable_port(i);
 						set_path_cost(i, br_port_cost(dev));
 						set_port_priority(i); 
-						make_forwarding(i);
+						if (br_stats.flags & BR_STP_DISABLED)
+							port_info[i].state = Forwarding;
+						else
+							make_forwarding(i);
 					}
 					return NOTIFY_DONE;
 					break;
 				}
 			}
 			break;
+		case NETDEV_UNREGISTER:
+			if (br_stats.flags & BR_DEBUG)
+				printk(KERN_DEBUG "br_device_event: NETDEV_UNREGISTER...\n");
+                        i = find_port(dev);
+                        if (i > 0) {
+				br_avl_delete_by_port(i);
+				port_info[i].dev = NULL;
+			}
+			break;
 	}
 	return NOTIFY_DONE;
 }
@@ -1847,6 +1859,8 @@
  
 static int br_port_cost(struct device *dev)	/* 4.10.2 */
 {
+	if (strncmp(dev->name, "lec", 3) == 0)	/* ATM Lan Emulation (LANE) */
+		return(7);                      /* 155 Mbs */
 	if (strncmp(dev->name, "eth", 3) == 0)	/* ethernet */
 		return(100);
 	if (strncmp(dev->name, "plip",4) == 0) /* plip */
@@ -1864,7 +1878,8 @@
 	Tcn_bpdu *bpdu = (Tcn_bpdu *) (bufp + BRIDGE_LLC1_HS);
 	Config_bpdu rcv_bpdu;
 
-	if((*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
+	if(!(br_stats.flags & BR_STP_DISABLED) &&
+	        (*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
 		(*bufp++ == BRIDGE_LLC1_CTRL) &&
 		(bpdu->protocol_id == BRIDGE_BPDU_8021_PROTOCOL_ID) &&
 		(bpdu->protocol_version_id == BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID)) 
@@ -1984,6 +1999,10 @@
 						}
 					}
 					port_state_selection();	  /* (4.8.1.5)	 */
+					if (br_stats.flags & BR_STP_DISABLED)
+						for(i=One;i<=No_of_ports; i++)
+							if((user_port_state[i] != Disabled) && port_info[i].dev)
+								port_info[i].state = Forwarding;
 					config_bpdu_generation();  /* (4.8.1.6)	 */
 					/* initialize system timer */
 					tl.expires = jiffies+HZ;	/* 1 second */
@@ -2001,6 +2020,20 @@
 						if (port_info[i].state != Disabled)
 							disable_port(i);
 					break;
+				case BRCMD_TOGGLE_STP:
+					printk(KERN_DEBUG "br: %s spanning tree protcol\n",
+					       (br_stats.flags & BR_STP_DISABLED) ? "enabling" : "disabling");
+					if (br_stats.flags & BR_STP_DISABLED) { /* enable STP */
+						for(i=One;i<=No_of_ports; i++)
+							if((user_port_state[i] != Disabled) && port_info[i].dev)
+								enable_port(i);
+					} else { /* STP was enabled, now disable it */
+						for (i = One; i <= No_of_ports; i++)
+							if (port_info[i].state != Disabled && port_info[i].dev)
+								port_info[i].state = Forwarding;
+					}
+					br_stats.flags ^= BR_STP_DISABLED;
+					break;
 				case BRCMD_PORT_ENABLE:
 					if (port_info[bcf.arg1].dev == 0)
 						return(-EINVAL);
diff -urN linux-2.2.3-pre2/net/bridge/br_tree.c linux-2.2.3-pre3/net/bridge/br_tree.c
--- linux-2.2.3-pre2/net/bridge/br_tree.c	1999-01-07 09:25:03.000000000 -0800
+++ linux-2.2.3-pre3/net/bridge/br_tree.c	2003-08-15 15:05:26.000000000 -0700
@@ -474,3 +474,27 @@
 
 	return;
 }
+
+/*
+ * Delete all nodes learnt by the port
+ */
+void br_avl_delete_by_port(int port)
+{
+        struct fdb *fdb, *next;
+
+	if (!fdb_inited)
+		fdb_init();
+
+        for(fdb = port_info[port].fdb; fdb != NULL; fdb = next) {
+                next = fdb->fdb_next;
+                br_avl_remove(fdb);
+        }
+        port_info[port].fdb = NULL;
+
+        /* remove the local mac too */
+        next = br_avl_find_addr(port_info[port].dev->dev_addr);
+        if (next != NULL)
+                br_avl_remove(next);
+
+        return;
+}
diff -urN linux-2.2.3-pre2/net/core/scm.c linux-2.2.3-pre3/net/core/scm.c
--- linux-2.2.3-pre2/net/core/scm.c	1998-10-27 09:57:19.000000000 -0800
+++ linux-2.2.3-pre3/net/core/scm.c	2003-08-15 15:05:26.000000000 -0700
@@ -27,7 +27,6 @@
 #include <asm/uaccess.h>
 
 #include <linux/inet.h>
-#include <linux/netdevice.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <net/rarp.h>
diff -urN linux-2.2.3-pre2/net/core/skbuff.c linux-2.2.3-pre3/net/core/skbuff.c
--- linux-2.2.3-pre2/net/core/skbuff.c	1999-02-06 12:46:21.000000000 -0800
+++ linux-2.2.3-pre3/net/core/skbuff.c	2003-08-15 15:05:26.000000000 -0700
@@ -4,7 +4,7 @@
  *	Authors:	Alan Cox <iiitac@pyr.swan.ac.uk>
  *			Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *	Version:	$Id: skbuff.c,v 1.54 1998/09/15 02:11:09 davem Exp $
+ *	Version:	$Id: skbuff.c,v 1.55 1999/02/23 08:12:27 davem Exp $
  *
  *	Fixes:	
  *		Alan Cox	:	Fixed the worst of the load balancer bugs.
diff -urN linux-2.2.3-pre2/net/core/sock.c linux-2.2.3-pre3/net/core/sock.c
--- linux-2.2.3-pre2/net/core/sock.c	1999-02-18 11:59:28.000000000 -0800
+++ linux-2.2.3-pre3/net/core/sock.c	2003-08-15 15:05:26.000000000 -0700
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.75 1998/11/07 10:54:38 davem Exp $
+ * Version:	$Id: sock.c,v 1.76 1999/02/23 08:12:29 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -urN linux-2.2.3-pre2/net/econet/econet.c linux-2.2.3-pre3/net/econet/econet.c
--- linux-2.2.3-pre2/net/econet/econet.c	1998-11-16 15:09:36.000000000 -0800
+++ linux-2.2.3-pre3/net/econet/econet.c	2003-08-15 15:05:26.000000000 -0700
@@ -44,7 +44,6 @@
 #include <net/udp.h>
 #include <net/ip.h>
 #include <asm/spinlock.h>
-#include <linux/inetdevice.h>
 
 static struct proto_ops econet_ops;
 static struct sock *econet_sklist;
diff -urN linux-2.2.3-pre2/net/ipv4/arp.c linux-2.2.3-pre3/net/ipv4/arp.c
--- linux-2.2.3-pre2/net/ipv4/arp.c	1998-11-18 09:06:05.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv4/arp.c	2003-08-15 15:05:26.000000000 -0700
@@ -557,6 +557,19 @@
 		if (htons(dev_type) != arp->ar_hrd)
 			goto out;
 		break;
+#ifdef CONFIG_NET_ETHERNET
+	case ARPHRD_ETHER:
+		/*
+		 * ETHERNET devices will accept ARP hardware types of either
+		 * 1 (Ethernet) or 6 (IEEE 802.2).
+		 */
+		if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&
+		    arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))
+			goto out;
+		if (arp->ar_pro != __constant_htons(ETH_P_IP))
+			goto out;
+		break;
+#endif
 #ifdef CONFIG_FDDI
 	case ARPHRD_FDDI:
 		/*
diff -urN linux-2.2.3-pre2/net/ipv4/Config.in linux-2.2.3-pre3/net/ipv4/Config.in
--- linux-2.2.3-pre2/net/ipv4/Config.in	1999-01-09 10:01:56.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv4/Config.in	2003-08-15 15:05:26.000000000 -0700
@@ -78,7 +78,6 @@
 tristate 'IP: Reverse ARP' CONFIG_INET_RARP
 #bool 'IP: Path MTU Discovery (normally enabled)' CONFIG_PATH_MTU_DISCOVERY
 #bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF
-bool 'IP: Drop source routed frames' CONFIG_IP_NOSR
 bool 'IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE
 #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 
 #bool 'IP: support experimental checksum copy to user for UDP'  CONFIG_UDP_DELAY_CSUM
diff -urN linux-2.2.3-pre2/net/ipv4/icmp.c linux-2.2.3-pre3/net/ipv4/icmp.c
--- linux-2.2.3-pre2/net/ipv4/icmp.c	1999-02-18 19:15:41.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv4/icmp.c	2003-08-15 15:05:26.000000000 -0700
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@cymru.net>
  *
- *	Version: $Id: icmp.c,v 1.48 1999/01/02 16:51:41 davem Exp $
+ *	Version: $Id: icmp.c,v 1.49 1999/02/23 08:12:37 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
diff -urN linux-2.2.3-pre2/net/ipv4/tcp.c linux-2.2.3-pre3/net/ipv4/tcp.c
--- linux-2.2.3-pre2/net/ipv4/tcp.c	1999-02-22 09:05:55.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv4/tcp.c	2003-08-15 15:05:26.000000000 -0700
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.135 1999/02/22 13:54:21 davem Exp $
+ * Version:	$Id: tcp.c,v 1.136 1999/03/07 13:26:01 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1070,6 +1070,7 @@
 	if(copied > 0) {
 		struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 		__u32 rcv_window_now = tcp_receive_window(tp);
+		__u32 new_window = __tcp_select_window(sk);
 
 		/* We won't be raising the window any further than
 		 * the window-clamp allows.  Our window selection
@@ -1077,7 +1078,7 @@
 		 * checks are necessary to prevent spurious ACKs
 		 * which don't advertize a larger window.
 		 */
-		if((copied >= rcv_window_now) &&
+		if((new_window && (new_window >= rcv_window_now * 2)) &&
 		   ((rcv_window_now + tp->mss_cache) <= tp->window_clamp))
 			tcp_read_wakeup(sk);
 	}
diff -urN linux-2.2.3-pre2/net/ipv4/tcp_input.c linux-2.2.3-pre3/net/ipv4/tcp_input.c
--- linux-2.2.3-pre2/net/ipv4/tcp_input.c	1999-02-22 09:05:55.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv4/tcp_input.c	2003-08-15 15:05:26.000000000 -0700
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.156 1999/02/22 13:54:13 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.157 1999/03/05 09:35:06 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -241,8 +241,8 @@
 extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct tcphdr *th, unsigned len)
 {
 	/* ts_recent must be younger than 24 days */
-	return (((jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
-		(((s32)(tp->rcv_tsval-tp->ts_recent) < 0) &&
+	return (((s32)(jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
+		(((s32)(tp->rcv_tsval - tp->ts_recent) < 0) &&
 		 /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */
 		 (len != (th->doff * 4))));
 }
diff -urN linux-2.2.3-pre2/net/ipv4/tcp_ipv4.c linux-2.2.3-pre3/net/ipv4/tcp_ipv4.c
--- linux-2.2.3-pre2/net/ipv4/tcp_ipv4.c	1999-02-18 11:59:28.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv4/tcp_ipv4.c	2003-08-15 15:05:26.000000000 -0700
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.165 1999/02/08 11:19:56 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.166 1999/02/23 08:12:41 davem Exp $
  *
  *		IPv4 specific functions
  *
diff -urN linux-2.2.3-pre2/net/ipv4/tcp_output.c linux-2.2.3-pre3/net/ipv4/tcp_output.c
--- linux-2.2.3-pre2/net/ipv4/tcp_output.c	1999-02-22 09:05:55.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv4/tcp_output.c	2003-08-15 15:05:26.000000000 -0700
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.102 1999/02/22 13:54:26 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.104 1999/03/07 13:26:04 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -580,6 +580,18 @@
 	if(tp->af_specific->rebuild_header(sk))
 		return 1; /* Routing failure or similar. */
 
+	/* Some Solaris stacks overoptimize and ignore the FIN on a
+	 * retransmit when old data is attached.  So strip it off
+	 * since it is cheap to do so and saves bytes on the network.
+	 */
+	if(skb->len > 0 &&
+	   (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+	   tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
+		TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+		skb_trim(skb, 0);
+		skb->csum = 0;
+	}
+
 	/* Ok, we're gonna send it out, update state. */
 	TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_RETRANS;
 	tp->retrans_out++;
@@ -592,6 +604,7 @@
 		skb = skb_copy(skb, GFP_ATOMIC);
 	else
 		skb = skb_clone(skb, GFP_ATOMIC);
+
 	tcp_transmit_skb(sk, skb);
 
 	/* Update global TCP statistics and return success. */
diff -urN linux-2.2.3-pre2/net/ipv6/tcp_ipv6.c linux-2.2.3-pre3/net/ipv6/tcp_ipv6.c
--- linux-2.2.3-pre2/net/ipv6/tcp_ipv6.c	1999-02-08 09:26:30.000000000 -0800
+++ linux-2.2.3-pre3/net/ipv6/tcp_ipv6.c	2003-08-15 15:05:26.000000000 -0700
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.95 1999/02/08 11:20:03 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.96 1999/03/05 13:23:13 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -1238,7 +1238,6 @@
 			goto reset;
 		if (users)
 			goto ipv6_pktoptions;
-		release_sock(sk);
 		return 0;
 	}
 
diff -urN linux-2.2.3-pre2/net/irda/af_irda.c linux-2.2.3-pre3/net/irda/af_irda.c
--- linux-2.2.3-pre2/net/irda/af_irda.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/af_irda.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Thu Jan 14 13:42:16 1999
+ * Modified at:   Sat Feb 20 01:31:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.x
  * 
@@ -23,11 +23,17 @@
  *     
  ********************************************************************/
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
+#include <linux/init.h>
+#include <linux/if_arp.h>
+#include <linux/net.h>
+
+#include <asm/uaccess.h>
+
 #include <net/sock.h>
-#include <asm/segment.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -37,8 +43,12 @@
 extern void irda_cleanup(void);
 extern int irlap_input(struct sk_buff *, struct device *, struct packet_type *);
 
+static struct proto_ops irda_proto_ops;
+
 #define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
 
+#define IRDA_SOCKETS
+
 #ifdef IRDA_SOCKETS
 
 /*
@@ -56,120 +66,6 @@
 }
 
 /*
- * Function irda_sendmsg (sock, msg, len, noblock, flags)
- *
- *    
- *
- */
-static int irda_sendmsg( struct socket *sock, struct msghdr *msg, int len, 
-			 int noblock, int flags)
-{
-#if 0
-	struct sock *sk = (struct sock *) sock->data;
-	/* struct sockaddr_irda *usax = (struct sockaddr_irda *)msg->msg_name; */
-	int err;
-	struct sk_buff *skb;
-	unsigned char *asmptr;
-	int size;
-	struct tsap_cb *tsap;
-	
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	if (sk->err)
-		return sock_error(sk);
-
-	if (flags)
-		return -EINVAL;
-	
-	if (sk->zapped)
-		return -EADDRNOTAVAIL;
-	
-	if (sk->debug)
-		printk( "IrDA: sendto: Addresses built.\n");
-	
-	/* Build a packet */
-	if (sk->debug)
-		printk( "IrDA: sendto: building packet.\n");
-	
-	size = len + IRDA_MAX_HEADER;
-	
-	if ((skb = sock_alloc_send_skb(sk, size, 0, 0, &err)) == NULL)
-		return err;
-	
-	skb->sk   = sk;
-	skb->free = 1;
-	skb->arp  = 1;
-	
-	skb_reserve(skb, size - len);
-	
-	memcpy_fromiovec( asmptr, msg->msg_iov, len);
-	
-	if (sk->debug)
-		printk( "IrDA: Transmitting buffer\n");
-	
-        if (sk->state != TCP_ESTABLISHED) {
-                kfree_skb( skb, FREE_WRITE);
-		return -ENOTCONN;
-	}
-	
-	tsap = (struct tsap_cb *) sk->protinfo.irda;
-	ASSERT( tsap != NULL, return -ENODEV;);
-	ASSERT( tsap->magic == TTP_TSAP_MAGIC, return -EBADR;);
-	
-	irttp_data_request( tsap, skb);
-#endif	
-	return len;
-}
-
-/*
- * Function irda_recvmsg (sock, msg, size, noblock, flags, addr_len)
- *
- *    
- *
- */
-static int irda_recvmsg( struct socket *sock, struct msghdr *msg, int size, 
-			 int noblock, int flags, int *addr_len)
-{
-	int copied=0;
-#if 0
-	struct sock *sk = (struct sock *)sock->data;
-	struct sockaddr_irda *sax = (struct sockaddr_irda *)msg->msg_name;
-	struct sk_buff *skb;
-	int er;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	if (sk->err)
-		return sock_error(sk);
-	
-	if (addr_len != NULL)
-		*addr_len = sizeof(*sax);
-
-	/*
-	 * This works for seqpacket too. The receiver has ordered the queue for
-	 * us! We do one quick check first though
-	 */
-	if (sk->state != TCP_ESTABLISHED)
-		return -ENOTCONN;
-
-	/* Now we can treat all alike */
-	if ((skb = skb_recv_datagram( sk, flags, noblock, &er)) == NULL)
-		return er;
-
-/* 	if (!sk->nr->hdrincl) { */
-/* 		skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); */
-/* 		skb->h.raw = skb->data; */
-/* 	} */
-
-	copied = (size < skb->len) ? size : skb->len;
-	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-
-	skb_free_datagram(sk, skb);
-#endif
-	return copied;
-}
-
-/*
  * Function irda_listen (sock, backlog)
  *
  *    
@@ -177,52 +73,17 @@
  */
 static int irda_listen( struct socket *sock, int backlog)
 {
-#if 0
-	struct sock *sk = (struct sock *)sock->data;
+	struct sock *sk = sock->sk;
 
-	if (sk->state != TCP_LISTEN) {
+	if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) {
 		sk->max_ack_backlog = backlog;
 		sk->state           = TCP_LISTEN;
 		return 0;
-        }
-#endif
+	}
+
 	return -EOPNOTSUPP;
 }
 
-/*
- * Function irda_bind (sock, uaddr, addr_len)
- *
- *    Bind to a specified TSAP
- *
- */
-static int irda_bind( struct socket *sock, struct sockaddr *uaddr, 
-		      int addr_len)
-{
-#if 0	
-	struct sock *sk;
-	struct full_sockaddr_irda *addr = (struct full_sockaddr_irda *)uaddr;
-	struct device *dev;
-        irda_address *user, *source;
-        struct tsap_cb *tsap;
-	struct notify_t notify;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	sk = (struct sock *) sock->data;
-
-	if ( sk->zapped == 0)
-		return -EIO;
-	
-	irda_notify_init( &notify);
-	tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
-
-	sk->zapped = 0;
-
-	if (sk->debug)
-		printk("IrDA: socket is bound\n");
-#endif
-	return 0;
-}
 
 /*
  * Function irda_connect (sock, uaddr, addr_len, flags)
@@ -289,83 +150,6 @@
 #endif
 	return 0;
 }
-	
-static int irda_socketpair( struct socket *sock1, struct socket *sock2)
-{
-	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
-
-	return -EOPNOTSUPP;
-}
-
-static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-	struct sock *sk;
-	struct sock *newsk;
-	struct sk_buff *skb;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-#if 0
-	if (newsock->data)
-		sk_free(newsock->data);
-
-	newsock->data = NULL;
-	
-	sk = (struct sock *)sock->data;
-
-	if (sk->type != SOCK_SEQPACKET)
-		return -EOPNOTSUPP;
-	
-	if (sk->state != TCP_LISTEN)
-		return -EINVAL;
-		
-	/*
-	 *	The write queue this time is holding sockets ready to use
-	 *	hooked into the SABM we saved
-	 */
-	do {
-		cli();
-		if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {
-			if (flags & O_NONBLOCK) {
-				sti();
-				return 0;
-			}
-			interruptible_sleep_on(sk->sleep);
-			if (current->signal & ~current->blocked) {
-				sti();
-				return -ERESTARTSYS;
-			}
-		}
-	} while (skb == NULL);
-
-	newsk = skb->sk;
-	newsk->pair = NULL;
-	sti();
-
-	/* Now attach up the new socket */
-	skb->sk = NULL;
-	kfree_skb(skb, FREE_READ);
-	sk->ack_backlog--;
-	newsock->data = newsk;
-#endif
-	return 0;
-}
-
-static void def_callback1(struct sock *sk)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (!sk->dead)
-                wake_up_interruptible(sk->sleep);
-}
-
-static void def_callback2(struct sock *sk, int len)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (!sk->dead)
-                wake_up_interruptible(sk->sleep);
-}
-
 
 /*
  * Function irda_create (sock, protocol)
@@ -373,47 +157,42 @@
  *    Create IrDA socket
  *
  */
-static int irda_create( struct socket *sock, int protocol)
+static int irda_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
 
 	DEBUG( 0, __FUNCTION__ "()\n");
-#if 0
-	if (sock->type != SOCK_SEQPACKET || protocol != 0)
-		return -ESOCKTNOSUPPORT;
+
+	/* Compatibility */
+	if (sock->type == SOCK_PACKET) {
+		static int warned; 
+		if (net_families[PF_PACKET]==NULL)
+		{
+#if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE)
+			char module_name[30];
+			sprintf(module_name,"net-pf-%d", PF_PACKET);
+			request_module(module_name);
+			if (net_families[PF_PACKET] == NULL)
+#endif
+				return -ESOCKTNOSUPPORT;
+		}
+		if (!warned++)
+			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
+		return net_families[PF_PACKET]->create(sock, protocol);
+	}
+	
+/* 	if (sock->type != SOCK_SEQPACKET || protocol != 0) */
+/* 		return -ESOCKTNOSUPPORT; */
 
 	/* Allocate socket */
-	if ((sk = sk_alloc( GFP_ATOMIC)) == NULL)
+	if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1)) == NULL)
 		return -ENOMEM;
+	
+	sock_init_data(sock, sk);
+
+	sock->ops    = &irda_proto_ops;
+	sk->protocol = protocol;
 
-	skb_queue_head_init(&sk->receive_queue);
-	skb_queue_head_init(&sk->write_queue);
-	skb_queue_head_init(&sk->back_log);
-
-	init_timer( &sk->timer);
-
-	sk->socket        = sock;
-	sk->type          = sock->type;
-	sk->protocol      = protocol;
-	sk->allocation	  = GFP_KERNEL;
-	sk->rcvbuf        = SK_RMEM_MAX;
-	sk->sndbuf        = SK_WMEM_MAX;
-	sk->state         = TCP_CLOSE;
-	sk->priority      = SOPRI_NORMAL;
-	sk->mtu           = 2048; /* FIXME, insert the right size*/
-	sk->zapped        = 1;
-/* 	sk->window	  = nr_default.window; */
-
-	sk->state_change = def_callback1;
-	sk->data_ready   = def_callback2;
-	sk->write_space  = def_callback1;
-	sk->error_report = def_callback1;
-
-	if (sock != NULL) {
-		sock->data = (void *)sk;
-		sk->sleep  = sock->wait;
-	}
-#endif
 	return 0;
 }
 
@@ -463,26 +242,32 @@
         return 0;
 }
 
-
-/*
- * Function irda_dup (newsock, oldsock)
- *
- *    
- *
- */
-static int irda_dup( struct socket *newsock, struct socket *oldsock)
+static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+			int flags, struct scm_cookie *scm)
 {
-#if 0
-        struct sock *sk = (struct sock *)oldsock->data;
+	struct sock *sk = sock->sk;
+	struct sk_buff *skb;
+	int copied, err;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
 
-        if (sk == NULL || newsock == NULL)
-                return -EINVAL;
+	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 
+				flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return err;
 
-        return irda_create( newsock, sk->protocol);
-#endif
-	return 0;
+	skb->h.raw = skb->data;
+	copied     = skb->len;
+	
+	if (copied > size) {
+		copied = size;
+		msg->msg_flags |= MSG_TRUNC;
+	}
+	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+
+	skb_free_datagram(sk, skb);
+
+	return copied;
 }
 
 static int irda_shutdown( struct socket *sk, int how)
@@ -497,7 +282,8 @@
 unsigned int irda_poll( struct file *file, struct socket *sock, 
 			struct poll_table_struct *wait)
 {
-	
+	DEBUG(0, __FUNCTION__ "()\n");
+	return 0;
 }
 
 /*
@@ -506,172 +292,114 @@
  *    
  *
  */
-static int irda_ioctl( struct socket *sock, unsigned int cmd, 
-		       unsigned long arg)
-{
-#if 0
-        struct sock *sk = (struct sock *) sock->data;
-        int err;
-
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
-#endif
-	return 0;
-}
-
-static int irda_setsockopt( struct socket *sock, int level, int optname,
-			    char *optval, int optlen)
-{
-#if 0
-        struct sock *sk = (struct sock *)sock->data;
-        int err, opt;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (level == SOL_SOCKET)
-                return sock_setsockopt(sk, level, optname, optval, optlen);
-
-        /* if (level != SOL_AX25) */
-/*                 return -EOPNOTSUPP; */
-
-        if (optval == NULL)
-                return -EINVAL;
-
-        if ((err = verify_area(VERIFY_READ, optval, sizeof(int))) != 0)
-                return err;
-
-        opt = get_fs_long((int *)optval);
-
-        switch (optname) {  
-	default:
-		return -ENOPROTOOPT;
-        }
-#endif
-	return -ENOPROTOOPT;
-}
-
-static int irda_getsockopt(struct socket *sock, int level, int optname,
-        char *optval, int *optlen)
+static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
-#if 0
-        struct sock *sk = (struct sock *)sock->data;
-        int val = 0;
-        int err;
+	struct sock *sk = sock->sk;
 
 	DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (level == SOL_SOCKET)
-                return sock_getsockopt(sk, level, optname, optval, optlen);
-
-        /* if (level != SOL_AX25) */
-/*                 return -EOPNOTSUPP; */
-
-        switch (optname) {
-	default:
-		return -ENOPROTOOPT;
-        }
 	
-        if ((err = verify_area(VERIFY_WRITE, optlen, sizeof(int))) != 0)
-                return err;
-
-        put_user(sizeof(int), optlen);
+	switch (cmd) {
+	case TIOCOUTQ: {
+		long amount;
+		amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
+		if (amount < 0)
+			amount = 0;
+		if (put_user(amount, (unsigned int *)arg))
+			return -EFAULT;
+		return 0;
+	}
 	
-        if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0)
-                return err;
-
-        put_user(val, (int *)optval);
-#endif
-        return 0;
-}
-
-static int irda_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-        return -EINVAL;
-}
-/*
- * Function irda_rcv (skb, dev, dev_addr, ptype)
- *
- *    
- *
- */
-static int irda_rcv( struct sk_buff *skb, struct device *dev, 
-		     irda_address *dev_addr, struct packet_type *ptype)
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
+	case TIOCINQ: {
+		struct sk_buff *skb;
+		long amount = 0L;
+		/* These two are safe on a single CPU system as only user tasks fiddle here */
+		if ((skb = skb_peek(&sk->receive_queue)) != NULL)
+			amount = skb->len;
+		if (put_user(amount, (unsigned int *)arg))
+			return -EFAULT;
+		return 0;
+	}
+	
+	case SIOCGSTAMP:
+		if (sk != NULL) {
+			if (sk->stamp.tv_sec == 0)
+				return -ENOENT;
+			if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+				return -EFAULT;
+			return 0;
+		}
+		return -EINVAL;
+		
+	case SIOCGIFADDR:
+	case SIOCSIFADDR:
+	case SIOCGIFDSTADDR:
+	case SIOCSIFDSTADDR:
+	case SIOCGIFBRDADDR:
+	case SIOCSIFBRDADDR:
+	case SIOCGIFNETMASK:
+	case SIOCSIFNETMASK:
+	case SIOCGIFMETRIC:
+	case SIOCSIFMETRIC:
+		return -EINVAL;
+		
+	default:
+		return dev_ioctl(cmd, (void *)arg);
+	}
 
+	/*NOTREACHED*/
 	return 0;
 }
 
-/*
- * Function irda_driver_rcv (skb, dev, ptype)
- *
- *    
- *
- */
-static int irda_driver_rcv( struct sk_buff *skb, struct device *dev, 
-			    struct packet_type *ptype)
+static struct net_proto_family irda_family_ops =
 {
-        skb->sk = NULL;         /* Initially we don't know who it's for */
-	
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-#if 0
-        if ((*skb->data & 0x0F) != 0) {
-                kfree_skb(skb, FREE_READ);      /* Not a KISS data frame */
-                return 0;
-        }
-
-        /* skb_pull(skb, AX25_KISS_HEADER_LEN);  */   /* Remove the KISS byte */
-
-        return irda_rcv( skb, dev, (irda_address *)dev->dev_addr, ptype);
-#endif
-	return NULL;
-}
+	PF_IRDA,
+	irda_create
+};
 
 static struct proto_ops irda_proto_ops = {
-	AF_IRDA,
+	PF_IRDA,
 	
-	irda_create,
-	irda_dup,
+	sock_no_dup,
 	irda_release,
-	irda_bind,
+	sock_no_bind,
 	irda_connect,
-	irda_socketpair,
-	irda_accept,
+	sock_no_socketpair,
+	sock_no_accept,
 	irda_getname,
 	irda_poll,
 	irda_ioctl,
 	irda_listen,
 	irda_shutdown,
-	irda_setsockopt,
-	irda_getsockopt,
-	irda_fcntl,
-	irda_sendmsg,
+	sock_no_setsockopt,
+	sock_no_getsockopt,
+	sock_no_fcntl,
+	sock_no_sendmsg,
 	irda_recvmsg
 };
 
 #endif /* IRDA_SOCKETS */
 
-static int irda_device_event( struct notifier_block *this, unsigned long event,
-			      void *ptr)
+static int irda_device_event(struct notifier_block *this, unsigned long event,
+			     void *ptr)
 {
-	/* struct device *dev = (struct device *) ptr; */
+	struct device *dev = (struct device *) ptr;
 	
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(3, __FUNCTION__ "()\n");
 	
-        /* Reject non AX.25 devices */
-	/*  if (dev->type != ARPHRD_AX25) */
-/*                 return NOTIFY_DONE; */
+        /* Reject non IrDA devices */
+	if (dev->type != ARPHRD_IRDA) 
+		return NOTIFY_DONE;
 	
         switch (event) {
 	case NETDEV_UP:
-		/* ax25_dev_device_up(dev); */
+		DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");
+		/* irda_dev_device_up(dev); */
 		break;
 	case NETDEV_DOWN:
-		/* ax25_kill_by_device(dev); */
-/*                         ax25_rt_device_down(dev); */
-/*                         ax25_dev_device_down(dev); */
+		DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");
+		/* irda_kill_by_device(dev); */
+		/* irda_rt_device_down(dev); */
+		/* irda_dev_device_down(dev); */
 		break;
 	default:
 		break;
@@ -701,17 +429,17 @@
  *    Initialize IrDA protocol layer
  *
  */
-void irda_proto_init(struct net_proto *pro)
+__initfunc(void irda_proto_init(struct net_proto *pro))
 {
 	DEBUG( 4, __FUNCTION__ "\n");
 
-	/* sock_register( irda_proto_ops.family, &irda_proto_ops); */
+	sock_register(&irda_family_ops);
+
 	irda_packet_type.type = htons(ETH_P_IRDA);
         dev_add_pack(&irda_packet_type);
 
-	/* register_netdevice_notifier( &irda_dev_notifier); */
+	register_netdevice_notifier( &irda_dev_notifier);
 
-	/* printk( KERN_INFO "IrDA Sockets for Linux (Dag Brattli)\n"); */
 	irda_init();
 }
 
@@ -728,9 +456,9 @@
 	irda_packet_type.type = htons(ETH_P_IRDA);
         dev_remove_pack(&irda_packet_type);
 
-        /* unregister_netdevice_notifier( &irda_dev_notifier); */
+        unregister_netdevice_notifier( &irda_dev_notifier);
 	
-	/* (void) sock_unregister( irda_proto_ops.family); */
+	sock_unregister(PF_IRDA);
 	irda_cleanup();
 	
         return;
diff -urN linux-2.2.3-pre2/net/irda/ircomm/attach.c linux-2.2.3-pre3/net/irda/ircomm/attach.c
--- linux-2.2.3-pre2/net/irda/ircomm/attach.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/ircomm/attach.c	2003-08-15 15:05:26.000000000 -0700
@@ -44,7 +44,8 @@
 
 static void got_lsapsel(struct ircomm_cb * info);
 static void query_lsapsel(struct ircomm_cb * self);
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv );
+void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, 
+			      void *priv);
 
 #if 0
 static char *rcsid = "$Id: attach.c,v 1.11 1998/10/22 12:02:20 dagb Exp $";
@@ -55,14 +56,20 @@
  * handler for iriap_getvaluebyclass_request() 
  *
  */
-
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv ){
-
+void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value,void *priv)
+{
 	struct ircomm_cb *self = (struct ircomm_cb *) priv;
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
 
+	/* Check if request succeeded */
+	if ( !value) {
+		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+
+		return;
+	}
+
 	DEBUG(0, __FUNCTION__"type(%d)\n", value->type);
 
 	switch(value->type){
@@ -100,9 +107,8 @@
 		break;
 
 	case IAS_STRING:
-		DEBUG( 0, __FUNCTION__":STRING is not implemented\n");
-		DEBUG( 0, __FUNCTION__":received string:%s\n",
-		       value->t.string);
+		DEBUG(0, __FUNCTION__":STRING is not implemented\n");
+		DEBUG(0, __FUNCTION__":received string:%s\n", value->t.string);
 		query_lsapsel(self);  /* experiment */
 		break;
 
@@ -116,9 +122,8 @@
 	}
 }
 
-
-static void got_lsapsel(struct ircomm_cb * self){
-
+static void got_lsapsel(struct ircomm_cb * self)
+{
 	struct notify_t notify;
 
 	DEBUG(0, "ircomm:got_lsapsel: got peersap!(%d)\n", self->dlsap );
@@ -136,11 +141,10 @@
 	strncpy( notify.name, "IrCOMM cli", NOTIFY_MAX_NAME);
 	notify.instance = self;
 	
-	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
-				     &notify );
+	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, 
+				     &notify);
 	ASSERT(self->tsap != NULL, return;);
 
-
 	/*
 	 * invoke state machine  
 	 * and notify that I'm ready to accept connect_request
@@ -150,26 +154,22 @@
   	if(self->d_handler)
  		self->d_handler(self);
 }
-
-
-
-
 		
-static void query_lsapsel(struct ircomm_cb * self){
-
+static void query_lsapsel(struct ircomm_cb * self)
+{
 	DEBUG(0, "ircomm:query_lsapsel..\n");
 
 	/*  
 	 *  since we've got Parameters field of IAS, we are to get peersap.
 	 */
 	
-	if(!(self->servicetype & THREE_WIRE_RAW)){
-		iriap_getvaluebyclass_request
-			(self->daddr, "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
-			 ircomm_getvalue_confirm, self );
+	if (!(self->servicetype & THREE_WIRE_RAW)) {
+		iriap_getvaluebyclass_request( 
+			"IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
+			self->saddr, self->daddr,
+			ircomm_getvalue_confirm, self );
 	} else {
-		DEBUG(0,"ircomm:query_lsap:"
-		      "THREE_WIRE_RAW is not implemented!\n");
+		DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n");
 	}
 }
 
@@ -183,7 +183,6 @@
 
 void ircomm_discovery_indication( DISCOVERY *discovery)
 {
-
 	struct ircomm_cb *self;
 
  	DEBUG( 0, "ircomm_discovery_indication\n");
@@ -193,6 +192,7 @@
 	ASSERT(self->magic == IRCOMM_MAGIC, return;);
 
 	self->daddr = discovery->daddr;
+	self->saddr = discovery->saddr;
 
 	DEBUG( 0, "ircomm_discovery_indication:daddr=%08x\n", self->daddr);
 
@@ -201,7 +201,6 @@
 	DEBUG(0, "ircomm:querying parameters..\n");
 #if 0
 	iriap_getvaluebyclass_request(self->daddr, "IrDA:IrCOMM",
-
 				      "Parameters",
 				      ircomm_getvalue_confirm,
 				      self);
@@ -214,8 +213,8 @@
 
 struct ircomm_cb * ircomm_attach_cable( __u8 servicetype,
 					struct notify_t notify, 
-					void *handler ){
-
+					void *handler )
+{
 	int i;
 	struct ircomm_cb *self = NULL;
 	struct notify_t server_notify;
@@ -317,15 +316,11 @@
 	return (self);
 }
 
-
-
-
-int ircomm_detach_cable(struct ircomm_cb *self){
-
+int ircomm_detach_cable(struct ircomm_cb *self)
+{
 	ASSERT( self != NULL, return -EIO;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;);
 
-
 	DEBUG(0,"ircomm_detach_cable:\n");
 
 	/* shutdown ircomm layer */
@@ -360,5 +355,6 @@
 
 	self->tsap = NULL;
 	self->in_use = 0;
+
 	return 0;
 }
diff -urN linux-2.2.3-pre2/net/irda/ircomm/ircomm_common.c linux-2.2.3-pre3/net/irda/ircomm/ircomm_common.c
--- linux-2.2.3-pre2/net/irda/ircomm/ircomm_common.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/ircomm/ircomm_common.c	2003-08-15 15:05:26.000000000 -0700
@@ -236,7 +236,9 @@
  * ---------------------------------------------------------------------- 
  */
 
-void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb){
+void ircomm_accept_data_indication(void *instance, void *sap, 
+				   struct sk_buff *skb)
+{
 	
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -250,7 +252,8 @@
 
 void ircomm_accept_connect_confirm(void *instance, void *sap,
 				   struct qos_info *qos, 
-				   int maxsdusize, struct sk_buff *skb){
+				   int maxsdusize, struct sk_buff *skb)
+{
 
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -277,8 +280,8 @@
 void ircomm_accept_connect_indication(void *instance, void *sap,
 				      struct qos_info *qos,
 				      int maxsdusize,
-				      struct sk_buff *skb ){
-
+				      struct sk_buff *skb )
+{
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
 	ASSERT( self != NULL, return;);
@@ -297,8 +300,10 @@
 	ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
 }
 
-void ircomm_accept_disconnect_indication(void *instance, void *sap, LM_REASON reason,
-					 struct sk_buff *skb){
+void ircomm_accept_disconnect_indication(void *instance, void *sap, 
+					 LM_REASON reason,
+					 struct sk_buff *skb)
+{
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
 	ASSERT( self != NULL, return;);
@@ -309,7 +314,8 @@
 	ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
 }
 
-void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd){
+void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd)
+{
 	
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -349,10 +355,9 @@
  * ----------------------------------------------------------------------
  */
 
-
 static void issue_connect_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata ){
-
+				  struct sk_buff *userdata )
+{
 	/* TODO: we have to send/build userdata field which contains 
 	   InitialControlParameters */
 	/* but userdata field is not implemeted in irttp.c.. */
@@ -365,7 +370,8 @@
 		break;
 
 	case DEFAULT: 
-		irttp_connect_request(self->tsap, self->dlsap, self->daddr,
+		irttp_connect_request(self->tsap, self->dlsap, 
+				      self->saddr, self->daddr,
 				      NULL, self->maxsdusize, NULL);  
  		break; 
 		
@@ -373,7 +379,8 @@
 	case NINE_WIRE:
 	case CENTRONICS:
 
-		irttp_connect_request(self->tsap, self->dlsap, self->daddr, 
+		irttp_connect_request(self->tsap, self->dlsap, 
+				      self->saddr, self->daddr, 
 				      NULL, self->maxsdusize, NULL); 
 		break;
 
@@ -383,8 +390,8 @@
 	}
 }	
 
-
-static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb){
+static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb)
+{
 
 	/*
 	 * Not implemented parameter"Reason".That is optional.
@@ -399,7 +406,8 @@
 }
 
 static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, 
-			       struct sk_buff *skb){
+			       struct sk_buff *skb)
+{
 
 /* If controlparameters don't exist, we use the servicetype"DEFAULT".*/
 /* 	if( !ircomm_parse_controlchannel( self, data)) */
@@ -412,13 +420,15 @@
     
 #if 0
 /*   it's for THREE_WIRE_RAW.*/
-static void connect_indication_three_wire_raw(void){ 
+static void connect_indication_three_wire_raw(void)
+{ 
 	DEBUG(0,"ircomm:connect_indication_threewire():not implemented!");
 }    
 #endif 
 
 
-static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb){
+static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb)
+{
 
 	/* give a connect_confirm to the client */
 	if( self->notify.connect_confirm )
@@ -427,7 +437,8 @@
 }
 
 static void issue_connect_response(struct ircomm_cb *self,
-				   struct sk_buff *skb ){
+				   struct sk_buff *skb)
+{
 
 	DEBUG(0,"ircomm:issue_connect_response:\n");
 	
@@ -441,7 +452,8 @@
 }
 
 static void issue_disconnect_request(struct ircomm_cb *self,
-				struct sk_buff *userdata ){
+				     struct sk_buff *userdata)
+{
 	if(self->servicetype == THREE_WIRE_RAW){
 		DEBUG(0,"ircomm:issue_disconnect_request():3wireraw is not implemented!");
 	}
@@ -450,7 +462,8 @@
 }
     
 static void issue_data_request(struct ircomm_cb *self,
-			       struct sk_buff *userdata ){
+			       struct sk_buff *userdata )
+{
 	int err;
 
 	if(self->servicetype == THREE_WIRE_RAW){
@@ -469,7 +482,8 @@
 }
 
 static void issue_control_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata ){
+				  struct sk_buff *userdata )
+{
 	if(self->servicetype == THREE_WIRE_RAW){
 		DEBUG(0,"THREE_WIRE_RAW is not implemented\n");
 		
@@ -478,8 +492,8 @@
 	}
 }
 
-
-static void process_data(struct ircomm_cb *self, struct sk_buff *skb ){
+static void process_data(struct ircomm_cb *self, struct sk_buff *skb )
+{
 	
 	DEBUG(4,"ircomm:process_data:skb_len is(%d),clen_is(%d)\n",
 	      (int)skb->len ,(int)skb->data[0]);
@@ -496,7 +510,8 @@
 					     skb);
 }
 
-void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb){
+void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
+{
 	/* Not implemented yet:THREE_WIRE_RAW service uses this function.  */
 	DEBUG(0,"ircomm_data_indication:not implemented yet!\n");
 }
@@ -510,14 +525,16 @@
  */
 
 static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
-			     struct sk_buff *skb) {
+			     struct sk_buff *skb) 
+{
 	
 	DEBUG( 4, "ircomm_do_event: STATE = %s, EVENT = %s\n",
 	       ircommstate[self->state], ircommevent[event]);
 	(*state[ self->state ]) ( self, event, skb);
 }
 
-void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) {
+void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) 
+{
 	self->state = state;
 	DEBUG( 0, "ircomm_next_state: NEXT STATE = %d(%s), sv(%d)\n", 
 	       (int)state, ircommstate[self->state],self->servicetype);
@@ -530,7 +547,8 @@
  */
 
 static void ircomm_state_discovery( struct ircomm_cb *self,
-				    IRCOMM_EVENT event, struct sk_buff *skb ){
+				    IRCOMM_EVENT event, struct sk_buff *skb )
+{
 	DEBUG(0,"ircomm_state_discovery: "
 	      "why call me? \n");
 	if(skb)
@@ -543,7 +561,8 @@
  */
 
 static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb ){
+			       struct sk_buff *skb )
+{
 	switch(event){
 	case IRCOMM_CONNECT_REQUEST:
 
@@ -577,7 +596,8 @@
  */
 
 static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb ){
+			  struct sk_buff *skb )
+{
 	switch(event){
 	case TTP_CONNECT_CONFIRM:
 		ircomm_next_state(self, COMM_CONN);
@@ -607,7 +627,8 @@
  * ircomm_state_waitr
  */
 static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb ) {
+			  struct sk_buff *skb ) 
+{
 	
 	switch(event){
 	case IRCOMM_CONNECT_RESPONSE:
@@ -651,7 +672,8 @@
  */
 
 static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb ){
+			      struct sk_buff *skb )
+{
 	switch(event){
 	case TTP_DATA_INDICATION:
 		process_data(self, skb);
@@ -696,7 +718,8 @@
  */
 
 
-void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize){
+void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize)
+{
 
 	/*
 	 * TODO:build a packet which contains "initial control parameters"
@@ -713,7 +736,8 @@
 }
 
 void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     int maxsdusize){
+			     int maxsdusize)
+{
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -746,7 +770,9 @@
 	ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
 }	
 
-void ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata){
+void ircomm_disconnect_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata)
+{
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -756,7 +782,8 @@
 }	
 
 
-void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata){
+void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
+{
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -780,7 +807,8 @@
  *  ----------------------------------------------------------------------
  */
 
-static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self ){
+static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self )
+{
 
 	__u8 clen;
 	struct sk_buff *skb = self->ctrl_skb;
@@ -817,7 +845,8 @@
 }
 
 
-void ircomm_control_request(struct ircomm_cb *self){
+void ircomm_control_request(struct ircomm_cb *self)
+{
 	
 	struct sk_buff *skb;
 
@@ -839,8 +868,9 @@
 }
 
 
-static void append_tuple(struct ircomm_cb *self,
-			 __u8 instruction, __u8 pl , __u8 *value){
+static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl , 
+			 __u8 *value)
+{
 
 	__u8 *frame;
 	struct sk_buff *skb;
@@ -886,7 +916,8 @@
  * to peer device
  */
 
-void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction){
+void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction)
+{
 
 	__u8  pv[70];
 	__u8  *value = &pv[0];
@@ -1028,7 +1059,8 @@
 
 static void ircomm_parse_control(struct ircomm_cb *self,
 				 struct sk_buff *skb,
-				 int type){
+				 int type)
+{
 
 	__u8 *data;
 	__u8 pi,pl,pv[64];
@@ -1210,7 +1242,8 @@
 
 #ifdef MODULE
 
-int init_module(void) {
+int init_module(void) 
+{
 	ircomm_init();
 
 	DEBUG( 4, "ircomm:init_module:done\n");
@@ -1238,7 +1271,8 @@
  *
  */
 int ircomm_proc_read(char *buf, char **start, off_t offset,
-		     int len, int unused){
+		     int len, int unused)
+{
 	int i, index;
 
 	len = 0;
@@ -1285,6 +1319,5 @@
 	return len;
 }
 
-
 #endif /* CONFIG_PROC_FS */
 
diff -urN linux-2.2.3-pre2/net/irda/irda_device.c linux-2.2.3-pre3/net/irda/irda_device.c
--- linux-2.2.3-pre2/net/irda/irda_device.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irda_device.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irda_device.c
- * Version:       0.3
+ * Version:       0.4
  * Description:   Abstract device driver layer and helper functions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Mon Jan 18 11:05:59 1999
+ * Modified at:   Tue Feb 16 17:36:04 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -30,10 +30,15 @@
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/tty.h>
 
-#include <net/pkt_sched.h>
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 
+#include <net/pkt_sched.h>
+
 #include <net/irda/irda_device.h>
 #include <net/irda/irlap_frame.h>
 #include <net/irda/timer.h>
@@ -45,11 +50,10 @@
 extern int esi_init(void);
 extern int tekram_init(void);
 extern int actisys_init(void);
+extern int girbil_init(void);
 
 hashbin_t *irda_device = NULL;
 
-void irda_device_start_todo_timer( struct irda_device *self, int timeout);
-
 /* Netdevice functions */
 static int irda_device_net_rebuild_header(struct sk_buff *skb);
 static int irda_device_net_hard_header(struct sk_buff *skb, 
@@ -67,8 +71,6 @@
 
 __initfunc(int irda_device_init( void))
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
-
 	/* Allocate master array */
 	irda_device = hashbin_new( HB_LOCAL);
 	if ( irda_device == NULL) {
@@ -98,7 +100,9 @@
 #ifdef CONFIG_ACTISYS_DONGLE
 	actisys_init();
 #endif
-
+#ifdef CONFIG_GIRBIL_DONGLE
+	girbil_init();
+#endif
 	return 0;
 }
 
@@ -178,7 +182,7 @@
 	 * a name like "irda0" and the self->descriptin will get a name
 	 * like "irda0 <-> irtty0" 
 	 */
-	strncpy( self->description, self->name, 4);
+	strncpy( self->description, self->name, 5);
 	strcat( self->description, " <-> ");
 	strncat( self->description, name, 23);
 
@@ -280,16 +284,11 @@
  */
 static void __irda_device_change_speed( struct irda_device *self, int speed)
 {
-	ASSERT( self != NULL, return;);
-
-	if ( self->magic != IRDA_DEVICE_MAGIC) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), irda device is gone! Maybe you need to update "
-		       "your irmanager and/or irattach!");
-		       
-		       return;
-	}
+	DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies);
 
+	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.
@@ -304,9 +303,9 @@
 			self->qos.baud_rate.value = speed;
 		}
 	} else {
-		DEBUG( 0, __FUNCTION__ "(), Warning, wait_until_sent() "
-		       "is not implemented by the irda_device!\n");
-     
+		DEBUG(0, __FUNCTION__ "(), Warning, wait_until_sent() "
+		      "has not implemented by the device driver!\n");
+		
 	}
 }
 
@@ -323,9 +322,8 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
 
-	irda_execute_as_process( self, 
-				 (TODO_CALLBACK) __irda_device_change_speed, 
-				 speed);
+	irda_execute_as_process(
+		self, (TODO_CALLBACK) __irda_device_change_speed, speed);
 }
 
 inline int irda_device_is_media_busy( struct irda_device *self)
@@ -368,28 +366,6 @@
 	__irda_device_change_speed( self, self->new_speed);
 }
 
-/*
- * Function irda_device_start_todo_timer (self, timeout)
- *
- *    Start todo timer. This function is used to delay execution of certain
- *    functions. Its implemented using timers since delaying a timer or a
- *    bottom halves function can be very difficult othervise.
- *
- */
-void irda_device_start_todo_timer( struct irda_device *self, int timeout)
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
-
-	del_timer( &self->todo_timer);
-	
-	self->todo_timer.data     = (unsigned long) self;
-	self->todo_timer.function = &irda_device_todo_expired;
-	self->todo_timer.expires  = jiffies + timeout;
-	
-	add_timer( &self->todo_timer);
-}
-
 static struct enet_statistics *irda_device_get_stats( struct device *dev)
 {
 	struct irda_device *priv = (struct irda_device *) dev->priv;
@@ -420,7 +396,7 @@
 	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->hard_header     = irda_device_net_hard_header; */
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
@@ -435,7 +411,7 @@
 	
 	dev_init_buffers( dev);
 
-	dev->flags = 0; /* IFF_NOARP | IFF_POINTOPOINT; */
+	dev->flags = 0;
 	
 	return 0;
 }
@@ -453,16 +429,15 @@
 	return 0;
 }
 
-static int irda_device_net_hard_header (struct sk_buff *skb, 
-					struct device *dev,
-					unsigned short type, void *daddr, 
-					void *saddr, unsigned len)
+static int irda_device_net_hard_header(struct sk_buff *skb, struct 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 PPP_HARD_HDR_LEN; */
 	
 	return 0;
 }
@@ -535,14 +510,44 @@
 }
 
 #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_DONGLE)
+		len += sprintf( buf+len, "DONGLE ");
+
+	len += sprintf( buf+len, "\n");
+
+	return len;
+}
+
 /*
- * Function irlap_proc_read (buf, start, offset, len, unused)
+ * 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)
+int irda_device_proc_read(char *buf, char **start, off_t offset, int len, 
+			  int unused)
 {
 	struct irda_device *self;
 	unsigned long flags;
@@ -552,32 +557,33 @@
 
 	len = 0;
 
-	self = (struct irda_device *) hashbin_get_first( irda_device);
+	self = (struct irda_device *) hashbin_get_first(irda_device);
 	while ( self != NULL) {
-		len += sprintf( buf+len, "device name: %s\n", self->name);
-		len += sprintf( buf+len, "description: %s\n", 
-				self->description);
-		len += sprintf( buf+len, "  tbusy=%s\n", self->netdev.tbusy ? 
-				"TRUE" : "FALSE");
-		len += sprintf( buf+len, "  bps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
+		len += sprintf(buf+len, "%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");
 		
-		len += sprintf( buf+len, "  %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);
+		self = (struct irda_device *) hashbin_get_next(irda_device);
 	}
 	restore_flags(flags);
 
diff -urN linux-2.2.3-pre2/net/irda/iriap.c linux-2.2.3-pre3/net/irda/iriap.c
--- linux-2.2.3-pre2/net/irda/iriap.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/iriap.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      iriap.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   Information Access Protocol (IAP)
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Tue Dec 15 16:00:35 1998
+ * Modified at:   Thu Feb 11 01:22:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -33,18 +33,35 @@
 
 #include <net/irda/irda.h>
 #include <net/irda/irttp.h>
+#include <net/irda/irmod.h>
 #include <net/irda/irlmp.h>
 #include <net/irda/irias_object.h>
 #include <net/irda/iriap_event.h>
 #include <net/irda/iriap.h>
 
+/* FIXME: This one should go in irlmp.c */
+static const char *ias_charset_types[] = {
+	"CS_ASCII",
+	"CS_ISO_8859_1",
+	"CS_ISO_8859_2",
+	"CS_ISO_8859_3",
+	"CS_ISO_8859_4",
+	"CS_ISO_8859_5",
+	"CS_ISO_8859_6",
+	"CS_ISO_8859_7",
+	"CS_ISO_8859_8",
+	"CS_ISO_8859_9",
+	"CS_UNICODE"
+};
+
 hashbin_t *iriap = NULL;
 
+extern char *lmp_reasons[];
+
 static struct iriap_cb *iriap_open( __u8 slsap, int mode);
 static void __iriap_close( struct iriap_cb *self);
-static void iriap_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *skb);
+static void iriap_disconnect_indication(void *instance, void *sap, 
+					LM_REASON reason, struct sk_buff *skb);
 
 /*
  * Function iriap_init (void)
@@ -56,7 +73,7 @@
 {
 	struct ias_object *obj;
 
-	DEBUG( 4, "--> iriap_init\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	/* Allocate master array */
 	iriap = hashbin_new( HB_LOCAL);
@@ -91,8 +108,6 @@
 	 */
 	iriap_open( LSAP_IAS, IAS_SERVER);
 	
-	DEBUG( 4, "iriap_init -->\n");
-	
 	return 0;
 }
 
@@ -151,14 +166,14 @@
 		DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n");
 		return NULL;
 	}
-	DEBUG( 4, "iriap_register: source LSAP sel=%02x\n", slsap_sel);
+	DEBUG( 4, __FUNCTION__ "(), source LSAP sel=%02x\n", slsap_sel);
 	
 	self->magic = IAS_MAGIC;
 	self->lsap = lsap;
 	self->slsap_sel = slsap_sel;
 	self->mode = mode;
 
-	init_timer( &self->watchdog_timer);
+	/* init_timer( &self->watchdog_timer); */
 
 	hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
 	
@@ -178,10 +193,12 @@
  */
 static void __iriap_close( struct iriap_cb *self)
 {
+	DEBUG( 4, __FUNCTION__ "()\n");
+
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
-	del_timer( &self->watchdog_timer);
+	/* del_timer( &self->watchdog_timer); */
 
 	self->magic = 0;
 
@@ -195,7 +212,9 @@
  */
 void iriap_close( struct iriap_cb *self)
 {
-	DEBUG( 4, "iriap_close()\n");
+	struct iriap_cb *entry;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -205,7 +224,9 @@
 		self->lsap = NULL;
 	}
 
-	hashbin_remove( iriap, self->slsap_sel, NULL);
+	entry = (struct iriap_cb *) hashbin_remove( iriap, self->slsap_sel, 
+						    NULL);
+	ASSERT( entry == self, return;);
 
 	__iriap_close( self);
 }
@@ -221,7 +242,7 @@
 {
 	struct iriap_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 
 	self = (struct iriap_cb *) instance;
 
@@ -230,20 +251,24 @@
 
 	ASSERT( iriap != NULL, return;);
 
-	del_timer( &self->watchdog_timer);
+	/* del_timer( &self->watchdog_timer); */
 
 	if ( self->mode == IAS_CLIENT) {
 		DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
 
-		/* Inform service user */
+		/* 
+		 * Inform service user that the request failed by sending 
+		 * it a NULL value.
+		 */
 		if ( self->confirm)
-			self->confirm( 0, NULL, self->priv);
-
+ 			self->confirm( 0, NULL, self->priv);
+		
+		
 		iriap_do_client_event( self, IAP_LM_DISCONNECT_INDICATION, 
 				       NULL);
 		/* Close instance only if client */
 		iriap_close( self);
-
+		
 	} else {
 		DEBUG( 4, __FUNCTION__ "(), disconnect as server\n");
 		iriap_do_server_event( self, IAP_LM_DISCONNECT_INDICATION, 
@@ -265,15 +290,15 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG( 4, "iriap_disconnect_request()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb( 64);
 	if (skb == NULL) {
-		DEBUG( 0,"iriap_getvaluebyclass: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+		DEBUG( 0, __FUNCTION__
+		       "(), Could not allocate an sk_buff of length %d\n", 64);
 		return;
 	}
 
@@ -316,9 +341,9 @@
  *    Retreive all values from attribute in all objects with given class
  *    name
  */
-void iriap_getvaluebyclass_request( __u32 daddr, char *name, char *attr, 
-				    CONFIRM_CALLBACK callback,
-				    void *priv)
+void iriap_getvaluebyclass_request( char *name, char *attr, 
+				    __u32 saddr, __u32 daddr,
+				    CONFIRM_CALLBACK callback, void *priv)
 {
 	struct sk_buff *skb;
 	struct iriap_cb *self;
@@ -326,16 +351,18 @@
 	int name_len, attr_len;
 	__u8 slsap = LSAP_ANY;  /* Source LSAP to use */
 
-	DEBUG( 4, "iriap_getvaluebyclass_request()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	self = iriap_open( slsap, IAS_CLIENT);
-	if ( self == NULL)
+	if (!self)
 		return;
 
 	self->mode = IAS_CLIENT;
 	self->confirm = callback;
 	self->priv = priv;
+
 	self->daddr = daddr;
+	self->saddr = saddr;
 
 	/* 
 	 *  Save operation, so we know what the later indication is about
@@ -343,14 +370,11 @@
 	self->operation = GET_VALUE_BY_CLASS; 
 
 	/* Give ourselves 7 secs to finish this operation */
-	iriap_start_watchdog_timer( self, 700);
+	/* iriap_start_watchdog_timer( self, 700); */
 	
 	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"iriap_getvaluebyclass: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	if (!skb)
 		return;
-	}
 
 	name_len = strlen( name);
 	attr_len = strlen( attr);
@@ -377,8 +401,7 @@
  *    to service user.
  *
  */
-void iriap_getvaluebyclass_confirm( struct iriap_cb *self, 
-				    struct sk_buff *skb) 
+void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb) 
 {
 	struct ias_value *value;
 	__u16 obj_id;
@@ -387,6 +410,7 @@
 	int   value_len;
 	__u8 *fp;
 	int n;
+	int charset;
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -399,7 +423,7 @@
 	/* Get length, MSB first */
 	len = ntohs( *(__u16 *)( fp+n)); n += 2;
 
-	DEBUG( 4, "iriap_getvaluebyclass_confirm: len=%d\n", len);
+	DEBUG( 4, __FUNCTION__ "(), len=%d\n", len);
 
 	/* Get object ID, MSB first */
 	obj_id = ntohs( *(__u16 *)( fp+n)); n += 2;
@@ -407,39 +431,54 @@
 	type = fp[n++];
 	DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type);
 
-
 	switch( type) {
 	case IAS_INTEGER:
 		value = irias_new_integer_value( ntohl(*(__u32 *)(fp+n)));
 		/* 
 		 *  Legal values restricted to 0x01-0x6f, page 15 irttp 
 		 */
-		DEBUG( 4, "iriap_getvaluebyclass_confirm: lsap=%d\n", 
-		       value->t.integer); 
+		DEBUG( 4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
 		break;
 	case IAS_STRING:
-		/* FIXME: check len of string, and if string is/should be
-		 *  null terminated? */
-		ASSERT( fp[n++] == 0, return;); /* ASCII only! */
+		charset = fp[n++];
+
+		switch(charset) {
+		case CS_ASCII:
+			break;
+/* 		case CS_ISO_8859_1: */
+/* 		case CS_ISO_8859_2: */
+/* 		case CS_ISO_8859_3: */
+/* 		case CS_ISO_8859_4: */
+/* 		case CS_ISO_8859_5: */
+/* 		case CS_ISO_8859_6: */
+/* 		case CS_ISO_8859_7: */
+/* 		case CS_ISO_8859_8: */
+/* 		case CS_ISO_8859_9: */
+/* 		case CS_UNICODE: */
+		default:
+			DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
+			      ias_charset_types[charset]);
+			return;
+			/* break; */
+		}
 		value_len = fp[n++];
-		DEBUG( 0, __FUNCTION__ "(), strlen=%d\n", value_len);
+		DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
 		ASSERT( value_len < 64, return;);
 		
-		DEBUG( 0, "Got string %s\n", fp+n);
-
+		/* Make sure the string is null-terminated */
+		fp[n+value_len] = 0x00;
+		
+		DEBUG(4, "Got string %s\n", fp+n);
 		value = irias_new_string_value( fp+n);
-
 		break;
 	case IAS_OCT_SEQ:
 		value_len = ntohs( *(__u16 *)( fp+n)); n += 2;
 		
 		/* FIXME:should be 1024, but.... */
-		DEBUG( 0, __FUNCTION__ "():octet sequence:len=%d\n",
-		       value_len);
+		DEBUG(0, __FUNCTION__ "():octet sequence:len=%d\n", value_len);
 		ASSERT(value_len <= 55, return;);      
 		
 		value = irias_new_octseq_value( fp+n, value_len);
-		
 		break;
 	default:
 		value = &missing;
@@ -458,39 +497,37 @@
 /*
  * Function iriap_getvaluebyclass_response ()
  *
- *    Send answer to getvaluebyclass_indication back to peer LM-IAS
+ *    Send answer back to remote LM-IAS
  * 
  */
-void iriap_getvaluebyclass_response( struct iriap_cb *self,
-				     __u16 obj_id, 
-				     __u8 ret_code,
-				     struct ias_value *value)
+void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id, 
+				    __u8 ret_code, struct ias_value *value)
 {
 	struct sk_buff *skb;
 	__u8 *fp;
 	int n;
 
-	DEBUG( 4, "iriap_getvaluebyclass_response()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT( value != NULL, return;);
+	ASSERT( value->len <= 1024, return;);
 
 	/* Initialize variables */
 	n = 0;
 
 	/* 
-	 *  FIXME: adjust the size of the response after the length of the 
-	 *  value 
+	 *  We must adjust the size of the response after the length of the 
+	 *  value. We add 9 bytes because of the 6 bytes for the frame and
+	 *  max 3 bytes for the value coding.
 	 */
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(),"
-		       "Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(value->len + LMP_HEADER + LAP_HEADER + 9);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for MUX and LAP header */
- 	skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+ 	skb_reserve( skb, LMP_HEADER+LAP_HEADER);
 	skb_put( skb, 6);
 	
 	fp = skb->data;
@@ -520,13 +557,6 @@
 		*((__u32 *)(fp+n)) = htonl(value->t.integer); n+=4;
 		break;
 	case IAS_OCT_SEQ:
-		
-		/* FIXME:
-		 * we can send only 55 octets at this time. 
-		 * we should be able to send 1024 octets.       TH
-		 */
-
-		ASSERT(value->len <= 55, return ;);
 		skb_put( skb, 3 + value->len);
 		fp[n++] = value->type;
 		*((__u16 *)(fp+n)) = htons(value->len); n+=2;
@@ -540,8 +570,7 @@
 		break;
 
 	default:
-		DEBUG( 0, "iriap_getvaluebyclass_response: "
-		       "type not implemented!\n");
+		DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
 		break;
 	}
 	iriap_do_r_connect_event( self, IAP_CALL_RESPONSE, skb);
@@ -553,8 +582,8 @@
  *    getvaluebyclass is requested from peer LM-IAS
  *
  */
-void iriap_getvaluebyclass_indication( struct iriap_cb *self,
-				       struct sk_buff *skb)
+void iriap_getvaluebyclass_indication(struct iriap_cb *self, 
+				      struct sk_buff *skb)
 {
 	__u8 *fp;
 	int n;
@@ -562,11 +591,10 @@
 	int attr_len;
 	char name[64];
 	char attr[64];
- 	char both[128];
  	struct ias_object *obj;
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, "iriap_getvaluebyclass_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -588,30 +616,26 @@
 	/* 
 	 *  Now, do some advanced parsing! :-) 
 	 */
-	DEBUG( 9, "LM-IAS: Looking up %s: %s\n", name, attr);
-
-	sprintf( both, "%s:%s", name, attr);
-	DEBUG( 0, "LM-IAS: looking for %s\n", both);
-
-	obj = irias_find_object( name);
-
+	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");
 		iriap_getvaluebyclass_response( self, 0x1235, 
 						IAS_CLASS_UNKNOWN, &missing);
 		return;
 	}
-	DEBUG( 0, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
+	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);
-		iriap_getvaluebyclass_response( self, obj->id, 
-						IAS_ATTRIB_UNKNOWN, &missing);
+		iriap_getvaluebyclass_response(self, obj->id,
+					       IAS_ATTRIB_UNKNOWN, &missing);
 		return;
 	}
 	
-	DEBUG( 0, "LM-IAS: found %s\n", attrib->name);
+	DEBUG(4, "LM-IAS: found %s\n", attrib->name);
 	
 	/*
 	 * We have a match; send the value.
@@ -633,17 +657,14 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG( 6, "iriap_send_ack()\n");
+	DEBUG( 6, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, "iriap_send_ack: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb( 64);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for MUX and LAP header */
  	skb_reserve( skb, 4);
@@ -671,9 +692,9 @@
 	ASSERT( self->magic == IAS_MAGIC, return;);
 	ASSERT( userdata != NULL, return;);
 	
-	DEBUG( 4, "iriap_connect_confirm()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
-	del_timer( &self->watchdog_timer);
+	/* del_timer( &self->watchdog_timer); */
 
 	iriap_do_client_event( self, IAP_LM_CONNECT_CONFIRM, userdata);
 }
@@ -684,13 +705,12 @@
  *    Remote LM-IAS is requesting connection
  *
  */
-void iriap_connect_indication( void *instance, void *sap, 
-			       struct qos_info *qos, int max_sdu_size,
-			       struct sk_buff *userdata)
+void iriap_connect_indication(void *instance, void *sap, struct qos_info *qos,
+			      int max_sdu_size, struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
 
-	DEBUG( 4, "iriap_connect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	self = ( struct iriap_cb *) instance;
 
@@ -713,7 +733,7 @@
 	__u8  *frame;
 	__u8  opcode;
 	
-	DEBUG( 4, "iriap_data_indication()\n"); 
+	DEBUG( 4, __FUNCTION__ "()\n"); 
 	
 	self = ( struct iriap_cb *) instance;
 
@@ -769,8 +789,7 @@
 		iriap_close( self);
 		break;
 	default:
-		DEBUG( 0, "iriap_data_indication: Unknown op-code: %02x\n", 
-		       opcode);
+		DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
 		break;
 	}
 }
@@ -786,7 +805,7 @@
 	__u8 *fp;
 	__u8  opcode;
 
-	DEBUG( 4, "iriap_call_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -816,7 +835,9 @@
 {
 	struct iriap_cb *self = ( struct iriap_cb *) data;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	return;
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
@@ -834,23 +855,7 @@
 	"IAS_STRING"
 };
 
-/* FIXME: This one should go in irlmp.c */
-static char *ias_charset_types[] = {
-	"CS_ASCII",
-	"CS_ISO_8859_1",
-	"CS_ISO_8859_2",
-	"CS_ISO_8859_3",
-	"CS_ISO_8859_4",
-	"CS_ISO_8859_5",
-	"CS_ISO_8859_6",
-	"CS_ISO_8859_7",
-	"CS_ISO_8859_8",
-	"CS_ISO_8859_9",
-	"CS_UNICODE"
-};
-
-int irias_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused)
+int irias_proc_read(char *buf, char **start, off_t offset, int len, int unused)
 {
 	struct ias_object *obj;
 	struct ias_attrib *attrib;
diff -urN linux-2.2.3-pre2/net/irda/iriap_event.c linux-2.2.3-pre3/net/irda/iriap_event.c
--- linux-2.2.3-pre2/net/irda/iriap_event.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/iriap_event.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Wed Dec  9 02:20:02 1998
+ * Modified at:   Tue Jan 26 12:29:36 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -184,6 +184,8 @@
 static void state_s_disconnect( struct iriap_cb *self, IRIAP_EVENT event, 
 				struct sk_buff *skb) 
 {
+	int ret;
+
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
@@ -191,13 +193,14 @@
 	case IAP_CALL_REQUEST_GVBC:
 		iriap_next_client_state( self, S_CONNECTING);
 		self->skb = skb;
-		irlmp_connect_request( self->lsap, LSAP_IAS, self->daddr, 
-				       NULL, NULL);
+		ret = irlmp_connect_request( self->lsap, LSAP_IAS, 
+					     self->saddr, self->daddr, 
+					     NULL, NULL);
 		break;
 	case IAP_LM_DISCONNECT_INDICATION:
 		break;
 	default:
-		DEBUG( 0, "state_s_disconnect: Unknown event %d\n", event);
+		DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
 		break;
 	}
 }
diff -urN linux-2.2.3-pre2/net/irda/irlan/Config.in linux-2.2.3-pre3/net/irda/irlan/Config.in
--- linux-2.2.3-pre2/net/irda/irlan/Config.in	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/Config.in	2003-08-15 15:05:26.000000000 -0700
@@ -1,7 +1 @@
-
 dep_tristate 'IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA
-
-if [ "$CONFIG_IRLAN" != "n" ]; then
-  dep_tristate '   IrLAN client support' CONFIG_IRLAN_CLIENT $CONFIG_IRLAN
-  dep_tristate '   IrLAN server support' CONFIG_IRLAN_SERVER $CONFIG_IRLAN
-fi
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_cli.c linux-2.2.3-pre3/net/irda/irlan/irlan_cli.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_cli.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_cli.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,676 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_cli.c
- * Version:       0.8
- * Description:   IrDA LAN Access Protocol Client
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Jan 18 13:24:26 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
- *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
- *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <net/arp.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-#include <net/irda/timer.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_event.h>
-#include <net/irda/irlan_eth.h>
-#include <net/irda/irlan_cli.h>
-
-/*
- *  Private functions
- */
-static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr);
-static void irlan_client_close( struct irlan_cb *self);
-
-
-static int irlan_client_eth_open( struct device *dev)
-{
-	/* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	MOD_INC_USE_COUNT;
-	
-	return 0;
-}
-
-/*
- * Function irlan_eth_close (dev)
- *
- *    Stop the Client ether network device, his function will be called by
- *    ifconfig down.
- */
-static int irlan_client_eth_close(struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( dev != NULL, return -1;);
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	MOD_DEC_USE_COUNT;
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_eth_init (dev)
- *
- *    
- *
- */
-int irlan_client_eth_init( struct device *dev) 
-{
-	irlan_eth_init( dev);
-
-	/* Overrride some functions */
-	dev->open  = irlan_client_eth_open;
-	dev->stop = irlan_client_eth_close;
-
-	return 0;
-}
-
-/*
- * Function irlan_client_init (dev)
- *
- *   Allocates the master array. Called by modprobe().
- */
-__initfunc(int irlan_client_init( void))
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	/* Register with IrLMP as a service user */
-	irlmp_register_layer( S_LAN, CLIENT, TRUE, 
-			      irlan_discovery_indication);
-
-	/* Do some fast discovery! */
-	irlmp_discovery_request( 8);
-
-	return 0;
-}
-
-/*
- * Function irlan_client_cleanup (void)
- *
- *    Removes all instances of the IrLAN network device driver, and the
- *    master array. Called by rmmod().
- *
- */
-void irlan_client_cleanup(void) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	irlmp_unregister_layer( S_LAN, CLIENT);
-}
-
-/*
- * Function irlan_client_open (void)
- *
- *    This function allocates and opens a new instance of the IrLAN network
- *    device driver.
- *
- */
-static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr) 
-{
-	struct irlan_cb *self;
-	int result;
-
-	DEBUG( 4, "IrLAN: irlan_client_open()\n");
-
-	ASSERT( irlan != NULL, return NULL;);
-	
-	self = irlan_open();
-	if ( self == NULL)
-		return NULL;
-
-	/* Use default name instead! */
-	/* sprintf( self->ifname, "irlan%d", ); */
- 	self->dev.name = self->ifname;
-	self->dev.priv = (void *) self;
-	self->dev.next = NULL;
-	self->dev.init = irlan_client_eth_init;
-	
-	self->saddr = saddr;
-	self->daddr = daddr;
-
-	/*
-	 *  Insert ourself into the hashbin
-	 */
-	hashbin_insert( irlan, (QUEUE *) self, saddr, NULL);
-
-	if (( result = register_netdev( &self->dev)) != 0) {
-		DEBUG( 0, "IrLAN, Register_netdev() failed!\n");
-		return NULL;
-	}
-
-	irlan_next_state( self, IRLAN_IDLE);
-
-	irlan_client_open_tsaps( self);
-	
-	return self;
-}
-
-/*
- * Function irlan_client_close (self)
- *
- *    
- *
- */
-static void irlan_client_close( struct irlan_cb *self)
-{
-	struct irlan_cb *entry;
-
-	DEBUG( 0, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	entry = hashbin_remove( irlan, self->daddr, NULL);
-
-	ASSERT( entry == self, return;);
-
-	/* __irlan_close( self); */
-}
-
-/*
- * Function irlan_discovery_indication (daddr)
- *
- *    Remote device with IrLAN server support discovered
- *
- */
-void irlan_discovery_indication( DISCOVERY *discovery) 
-{
-	struct irlan_cb *self;
-	__u32 saddr, daddr;
-	
-	ASSERT( irlan != NULL, return;);
-	ASSERT( discovery != NULL, return;);
-
-	saddr = discovery->saddr;
-	daddr = discovery->daddr;
-
-	/* 
-	 *  Check if an instance is already dealing with this device
-	 *  (saddr) 
-	 */
-	self = (struct irlan_cb *) hashbin_find( irlan, saddr, NULL);
-      	if ( self != NULL) {
-		ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-		DEBUG( 4, __FUNCTION__ "(), Found instance!\n");
-		if ( self->state == IRLAN_IDLE) {
-			/* daddr may have changed! */
-			self->daddr = daddr;
-
-			irlan_do_client_event( self, 
-					       IRLAN_DISCOVERY_INDICATION, 
-					       NULL);
-		} else {
-			DEBUG( 0, __FUNCTION__ "(), state=%s\n", 
-			       irlan_state[ self->state]);
-			/*  
-			 *  If we get here, it's obvious that the last 
-			 *  connection attempt has failed, so its best 
-			 *  to go back to idle!
-			 */
-			irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, 
-					       NULL);
-		}
-		return;
-	}
-	
-	/* 
-	 * We have no instance for daddr, so time to start a new instance.
-	 */
-	DEBUG( 0, __FUNCTION__ "(), Opening new instance for saddr=%#x\n",
-	       saddr);
-
-	if (( self = irlan_client_open( saddr, daddr)) == NULL) {
-		DEBUG( 0, "irlan_client_open failed!\n");
-		return;
-	}	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	DEBUG( 4, "Setting irlan_client state!\n");
-	if ( self->state == IRLAN_IDLE) {
-		irlan_do_client_event( self, IRLAN_DISCOVERY_INDICATION, NULL);
-	} else {
-		DEBUG( 0, __FUNCTION__ "(), Hmm, got here too!\n");
-	}
-}
-
-/*
- * Function irlan_client_disconnect_indication (handle)
- *
- *    Callback function for the IrTTP layer. Indicates a disconnection of
- *    the specified connection (handle)
- */
-void irlan_client_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *userdata) 
-{
-	struct irlan_cb *self;
-	struct tsap_cb *tsap;
-
-	self = ( struct irlan_cb *) instance;
-	tsap = ( struct tsap_cb *) sap;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);	
-	ASSERT( tsap != NULL, return;);
-	ASSERT( tsap->magic == TTP_TSAP_MAGIC, return;);
-	
-	DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
-	
-	if ( tsap == self->tsap_data) {
-		DEBUG( 4, "IrLAN, data channel disconnected by peer!\n");
-		self->connected = FALSE;
-	} else if ( tsap == self->tsap_ctrl) {
-		DEBUG( 4, "IrLAN, control channel disconnected by peer!\n");
-	} else {
-		DEBUG( 0, "Error, disconnect on unknown handle!\n");
-	}
-	
-	/* Stop IP from transmitting more packets */
-	/* irlan_client_flow_indication( handle, FLOW_STOP, priv); */
-
-	irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, NULL);
-}
-	
-/*
- * Function irlan_control_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the control channel
- *
- */
-void irlan_client_ctrl_data_indication( void *instance, void *sap, 
-					struct sk_buff *skb)
-{
-	struct irlan_cb *self;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irlan_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	
-	DEBUG( 4, "Got IRLAN_DATA_INDICATION!\n");
-	irlan_do_client_event( self, IRLAN_DATA_INDICATION, skb); 
-}
-
-/*
- * Function irlan_client_open_tsaps (self)
- *
- *    Initialize callbacks and open IrTTP TSAPs
- *
- */
-void irlan_client_open_tsaps( struct irlan_cb *self) 
-{
-	/* struct irlan_frame frame; */
-	struct notify_t notify_ctrl;
-	struct notify_t notify_data;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	irda_notify_init( &notify_ctrl);
-	irda_notify_init( &notify_data);
-
-	/* Set up callbacks */
-	notify_ctrl.data_indication       = irlan_client_ctrl_data_indication;
-	notify_ctrl.connect_confirm       = irlan_client_connect_confirm;
-	notify_ctrl.disconnect_indication = irlan_client_disconnect_indication;
-	notify_ctrl.instance              = self;
-	strncpy( notify_ctrl.name, "IrLAN ctrl", NOTIFY_MAX_NAME);
-	
-	notify_data.data_indication       = irlan_eth_rx;
-	notify_data.udata_indication      = irlan_eth_rx;
-	notify_data.connect_confirm       = irlan_client_connect_confirm;
- 	notify_data.flow_indication       = irlan_eth_flow_indication;
-	notify_data.disconnect_indication = irlan_client_disconnect_indication;
-	notify_data.instance              = self;
-	strncpy( notify_data.name, "IrLAN data", NOTIFY_MAX_NAME);
-
-	/* Create TSAP's */
-	self->tsap_ctrl = irttp_open_tsap( LSAP_ANY, 
-					   DEFAULT_INITIAL_CREDIT, 
-					   &notify_ctrl);
-	self->tsap_data = irttp_open_tsap( LSAP_ANY, 
-					   DEFAULT_INITIAL_CREDIT,
-					   &notify_data);
-}
-
-/*
- * Function irlan_client_connect_confirm (handle, skb)
- *
- *    Connection to peer IrLAN laye confirmed
- *
- */
-void irlan_client_connect_confirm( void *instance, void *sap, 
-				   struct qos_info *qos, int max_sdu_size,
-				   struct sk_buff *skb) 
-{
-	struct irlan_cb *self;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = ( struct irlan_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	/* TODO: we could set the MTU depending on the max_sdu_size */
-
-	irlan_do_client_event( self, IRLAN_CONNECT_COMPLETE, NULL);
-}
-
-/*
- * Function irlan_client_reconnect_data_channel (self)
- *
- *    Try to reconnect data channel (currently not used)
- *
- */
-void irlan_client_reconnect_data_channel( struct irlan_cb *self) 
-{
-	struct sk_buff *skb;
-	__u8 *frame;
-		
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an sk_buff of length %d\n", 64);
-		return;
-	}
-
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
-	
-	frame = skb->data;
-	
- 	frame[0] = CMD_RECONNECT_DATA_CHAN;
-	frame[1] = 0x01;
- 	insert_array_param( skb, "RECONNECT_KEY", 
-			    self->t.client.reconnect_key, 
-			    self->t.client.key_len);
-	
-	irttp_data_request( self->tsap_ctrl, skb);	
-}
-
-/*
- * Function irlan_client_extract_params (skb)
- *
- *    Extract all parameters from received buffer, then feed them to 
- *    check_params for parsing
- *
- */
-void irlan_client_extract_params( struct irlan_cb *self, 
-				  struct sk_buff *skb)
-{
-	__u8 *frame;
-	__u8 *ptr;
-	int count;
-	int ret;
-	int val_len;
-	int i;
-
-	ASSERT( skb != NULL, return;);	
-	
-	DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got NULL skb!\n");
-		return;
-	}
-	frame = skb->data;
-
-	/* 
-	 *  Check return code and print it if not success 
-	 */
-	if ( frame[0])
-		print_ret_code( frame[0]);
-	
-	/* How many parameters? */
-	count = frame[1];
-
-	DEBUG( 4, "Got %d parameters\n", count);
-	
-	ptr = frame+2;
-
-	/* For all parameters */
- 	for ( i=0; i<count;i++) {
-		ret = irlan_get_response_param( ptr, self->name, self->value, 
-						&val_len);
-		if ( ret == -1) {
-			DEBUG( 0, __FUNCTION__ "(), IrLAN, Error!\n");
-			return;
-		}
-		ptr+=ret;
-		check_response_param( self, self->name, self->value, val_len);
- 	}
-}
-
-/*
- * Function check_param (param, value)
- *
- *    Check which parameter is received and update local variables
- *
- */
-void check_response_param( struct irlan_cb *self, char *param, 
-			   char *value, int val_len) 
-{
-	int i;
-	__u8 *bytes;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	/*
-	 *  Media type
-	 */
-	if ( strcmp( param, "MEDIA") == 0) {
-		if ( strcmp( value, "802.3") == 0)
-			self->media = MEDIA_802_3;
-		else
-			self->media = MEDIA_802_5;
-		return;
-	}
-	/*
-	 *  IRLAN version
-	 */
-	if ( strcmp( param, "IRLAN_VER") == 0) {
-		DEBUG( 4, "IrLAN version %d.%d\n", 
-			(__u8) value[0], (__u8) value[1]);
-		return;
-	}
-	/*
-	 *  Which remote TSAP to use for data channel
-	 */
-	if ( strcmp( param, "DATA_CHAN") == 0) {
-		self->dtsap_sel_data = value[0];
-		DEBUG( 4, "Data TSAP = %02x\n", self->dtsap_sel_data);
-		return;
-	}
-	/*
-	 *  RECONNECT_KEY, in case the link goes down!
-	 */
-	if ( strcmp( param, "RECONNECT_KEY") == 0) {
-		DEBUG( 4, "Got reconnect key: ");
-		/* for (i = 0; i < val_len; i++) */
-/* 			printk( "%02x", value[i]); */
-		memcpy( self->t.client.reconnect_key, value, val_len);
-		self->t.client.key_len = val_len;
-		DEBUG( 4, "\n");
-	}
-	/*
-	 *  FILTER_ENTRY, have we got the ethernet address?
-	 */
-	if ( strcmp( param, "FILTER_ENTRY") == 0) {
-		bytes = value;
-		DEBUG( 4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
-		       bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 
-		       bytes[5]);
-		for (i = 0; i < 6; i++) 
-			self->dev.dev_addr[i] = bytes[i];
-#if 0
-	/*
-	 * When we get a new MAC address do a gratuitous ARP. This is useful
-	 * if we have changed access points on the same subnet.
-	 */
-		DEBUG( 4, "IrLAN: Sending gratuitous ARP\n");
-		arp_send( ARPOP_REQUEST, ETH_P_ARP, self->dev.pa_addr,
-			&self->dev, self->dev.pa_addr, NULL,
-			self->dev.dev_addr, NULL);
-#endif
-	}
-}
-
-/*
- * Function irlan_client_get_value_confirm (obj_id, value)
- *
- *    Got results from previous GetValueByClass request
- *
- */
-void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value,
-				     void *priv) 
-{
-	struct irlan_cb *self;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( priv != NULL, return;);
-
-	self = ( struct irlan_cb *) priv;
-
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	switch ( value->type) {
-	case IAS_INTEGER:
-		self->dtsap_sel_ctrl = value->t.integer;
-
-		if ( value->t.integer != -1) {
-			irlan_do_client_event( self, IRLAN_IAS_PROVIDER_AVAIL,
-					       NULL);
-			return;
-		}
-		break;
-	case IAS_STRING:
-		DEBUG( 0, __FUNCTION__ "(), got string %s\n", value->t.string);
-		break;
-	case IAS_OCT_SEQ:
-		DEBUG( 0, __FUNCTION__ "(), OCT_SEQ not implemented\n");
-		break;
-	case IAS_MISSING:
-		DEBUG( 0, __FUNCTION__ "(), MISSING not implemented\n");
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown type!\n");
-		break;
-	}
-	irlan_do_client_event( self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLAN module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-	DEBUG( 4, __FUNCTION__ "(), irlan_client.c\n");
-
-	irlan_client_init();
-
-	return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLAN module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-	DEBUG( 4, "--> irlan, cleanup_module\n");
-	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-	/* Free some memory */
- 	irlan_client_cleanup();
-
-	DEBUG( 4, "irlan, cleanup_module -->\n");
-}
-
-#endif /* MODULE */
-
-
-
-
-
-
-
-
-
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_client.c linux-2.2.3-pre3/net/irda/irlan/irlan_client.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_client.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_client.c	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,617 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client.c
+ * Version:       0.9
+ * Description:   IrDA LAN Access Protocol (IrLAN) Client
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb 17 23:29:34 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
+ *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
+ *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/iriap.h>
+#include <net/irda/timer.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_event.h>
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_client.h>
+
+#undef CONFIG_IRLAN_GRATUITOUS_ARP
+
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
+						    LM_REASON reason, 
+						    struct sk_buff *);
+
+static void irlan_client_ctrl_data_indication(void *instance, void *sap, 
+					      struct sk_buff *skb);
+
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
+					      struct qos_info *qos, 
+					      int max_sdu_size,
+					      struct sk_buff *);
+
+static void irlan_check_response_param(struct irlan_cb *self, char *param, 
+				       char *value, int val_len);
+
+static void irlan_client_kick_timer_expired(unsigned long data)
+{
+	struct irlan_cb *self = (struct irlan_cb *) data;
+	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	/*  
+	 * If we are in peer mode, the client may not have got the discovery
+	 * indication it needs to make progress. If the client is still in 
+	 * IDLE state, we must kick it to, but only if the provider is not IDLE
+ 	 */
+	if ((self->access_type == ACCESS_PEER) && 
+	    (self->client.state == IRLAN_IDLE) &&
+	    (self->provider.state != IRLAN_IDLE)) {
+		irlan_client_wakeup(self, self->saddr, self->daddr);
+	}
+}
+
+void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	irda_start_timer(&self->client.kick_timer, timeout, 
+			 (unsigned long) self, 
+			 irlan_client_kick_timer_expired);
+}
+
+void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+{
+	struct irmanager_event mgr_event;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	if (self->client.state == IRLAN_IDLE) {
+		/* saddr may have changed! */
+		self->saddr = saddr;
+		
+		/* Check if network device is up */
+		if (self->dev.start) {
+			/* Open TSAPs */
+			irlan_client_open_ctrl_tsap(self);
+			irlan_provider_open_ctrl_tsap(self);
+			irlan_open_data_tsap(self);
+			
+			irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION,
+					      NULL);
+		} else if (self->notify_irmanager) {
+			/* 
+			 * Tell irmanager that the device can now be 
+			 * configured but only if the device was not taken
+			 * down by the user
+			 */
+			mgr_event.event = EVENT_IRLAN_START;
+			sprintf(mgr_event.devname, "%s", self->ifname);
+			irmanager_notify(&mgr_event);
+
+			/* 
+			 * We set this so that we only notify once, since if 
+			 * configuration of the network device fails, the user
+			 * will have to sort it out first anyway. No need to 
+			 * try again.
+			 */
+			self->notify_irmanager = FALSE;
+		}
+		/* Restart watchdog timer */
+		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+
+		/* Start kick timer */
+		irlan_client_start_kick_timer(self, 200);
+	} else {
+		DEBUG(2, __FUNCTION__ "(), state=%s\n", 
+		      irlan_state[ self->client.state]);
+		/*  
+		 *  If we get here, it's obvious that the last 
+		 *  connection attempt has failed, so its best 
+		 *  to go back to idle!
+		 */
+		irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+	}
+}
+
+/*
+ * Function irlan_discovery_indication (daddr)
+ *
+ *    Remote device with IrLAN server support discovered
+ *
+ */
+void irlan_client_discovery_indication(DISCOVERY *discovery) 
+{
+	struct irlan_cb *self, *entry;
+	__u32 saddr, daddr;
+	
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(irlan != NULL, return;);
+	ASSERT(discovery != NULL, return;);
+
+	saddr = discovery->saddr;
+	daddr = discovery->daddr;
+
+	/* 
+	 *  Check if we already have an instance for dealing with this 
+	 *  provider.
+	 */
+	self = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL);
+      	if (self) {
+		ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+		DEBUG(2, __FUNCTION__ "(), Found instance!\n");
+		
+		irlan_client_wakeup(self, saddr, daddr);
+
+		return;
+	}
+	
+	/* 
+	 * We have no instance for daddr, so try and find an unused one
+	 */
+	self = hashbin_find(irlan, DEV_ADDR_ANY, NULL);
+	if (self) {
+		DEBUG(2, __FUNCTION__ "(), Found instance with DEV_ADDR_ANY!\n");
+		/*
+		 * Rehash instance, now we have a client (daddr) to serve.
+		 */
+		entry = hashbin_remove(irlan, self->daddr, NULL);
+		ASSERT( entry == self, return;);
+
+		self->daddr = daddr;
+		self->saddr = saddr;
+
+		DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+		
+		/* Check if network device has been registered */
+		if (!self->netdev_registered)
+			irlan_register_netdev(self);
+		
+		/* Remember that we might have to start a new provider */
+		self->client.start_new_provider = TRUE;
+	} else {
+		DEBUG(2, __FUNCTION__ "(), Found none, starting new one!\n");
+		/* No instance available, so we have to start one! */
+		self = irlan_open(saddr, daddr, TRUE);
+		if (!self) {
+			DEBUG(2, __FUNCTION__ "(), irlan_open failed!\n");
+			return;
+		}
+		ASSERT( self != NULL, return;);
+	}
+	/* Restart watchdog timer */
+	irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+}
+	
+/*
+ * Function irlan_client_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the control channel
+ *
+ */
+static void irlan_client_ctrl_data_indication(void *instance, void *sap, 
+					      struct sk_buff *skb)
+{
+	struct irlan_cb *self;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	
+	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb); 
+}
+
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
+						    LM_REASON reason, 
+						    struct sk_buff *userdata) 
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(tsap != NULL, return;);
+	ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+	
+	ASSERT(tsap == self->client.tsap_ctrl, return;);
+
+	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+/*
+ * Function irlan_client_open_tsaps (self)
+ *
+ *    Initialize callbacks and open IrTTP TSAPs
+ *
+ */
+void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
+{
+	struct notify_t notify;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if already open */
+	if (self->client.tsap_ctrl)
+		return;
+
+	irda_notify_init(&notify);
+
+	/* Set up callbacks */
+	notify.data_indication       = irlan_client_ctrl_data_indication;
+	notify.connect_confirm       = irlan_client_ctrl_connect_confirm;
+	notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrLAN ctrl (c)", NOTIFY_MAX_NAME);
+	
+	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+	if (!tsap) {
+		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		return;
+	}
+	self->client.tsap_ctrl = tsap;
+}
+
+/*
+ * Function irlan_client_connect_confirm (handle, skb)
+ *
+ *    Connection to peer IrLAN laye confirmed
+ *
+ */
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
+					      struct qos_info *qos, 
+					      int max_sdu_size,
+					      struct sk_buff *skb) 
+{
+	struct irlan_cb *self;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	self = (struct irlan_cb *) instance;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* TODO: we could set the MTU depending on the max_sdu_size */
+
+	irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
+}
+
+/*
+ * Function irlan_client_reconnect_data_channel (self)
+ *
+ *    Try to reconnect data channel (currently not used)
+ *
+ */
+void irlan_client_reconnect_data_channel(struct irlan_cb *self) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+		
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	skb = dev_alloc_skb(128);
+	if (!skb)
+		return;
+
+	/* Reserve space for TTP, LMP, and LAP header */
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
+	
+	frame = skb->data;
+	
+ 	frame[0] = CMD_RECONNECT_DATA_CHAN;
+	frame[1] = 0x01;
+ 	irlan_insert_array_param(skb, "RECONNECT_KEY", 
+				 self->client.reconnect_key,
+				 self->client.key_len);
+	
+	irttp_data_request(self->client.tsap_ctrl, skb);	
+}
+
+/*
+ * Function irlan_client_extract_params (skb)
+ *
+ *    Extract all parameters from received buffer, then feed them to 
+ *    check_params for parsing
+ *
+ */
+void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb)
+{
+	__u8 *frame;
+	__u8 *ptr;
+	int count;
+	int ret;
+	__u16 val_len;
+	int i;
+        char *name;
+        char *value;
+
+	ASSERT(skb != NULL, return;);	
+	
+	DEBUG(4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	if (!skb) {
+		DEBUG(2, __FUNCTION__ "(), Got NULL skb!\n");
+		return;
+	}
+	frame = skb->data;
+	
+	/* 
+	 *  Check return code and print it if not success 
+	 */
+	if (frame[0]) {
+		print_ret_code(frame[0]);
+		return;
+	}
+	
+	name = kmalloc(255, GFP_ATOMIC);
+	if (!name)
+		return;
+	value = kmalloc(1016, GFP_ATOMIC);
+	if (!value) {
+		kfree(name);
+		return;
+	}
+
+	/* How many parameters? */
+	count = frame[1];
+
+	DEBUG(4, __FUNCTION__ "(), got %d parameters\n", count);
+	
+	ptr = frame+2;
+
+	/* For all parameters */
+ 	for (i=0; i<count;i++) {
+		ret = irlan_get_param(ptr, name, value, &val_len);
+		if (ret == -1) {
+			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+			break;
+		}
+		ptr+=ret;
+		irlan_check_response_param(self, name, value, val_len);
+ 	}
+	/* Cleanup */
+	kfree(name);
+	kfree(value);
+}
+
+/*
+ * Function check_param (param, value)
+ *
+ *    Check which parameter is received and update local variables
+ *
+ */
+static void irlan_check_response_param(struct irlan_cb *self, char *param, 
+				       char *value, int val_len) 
+{
+	struct in_device *in_dev;
+	__u8 *bytes;
+	int i;
+
+	DEBUG(4, __FUNCTION__ "(), parm=%s\n", param);
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/*
+	 *  Media type
+	 */
+	if (strcmp(param, "MEDIA") == 0) {
+		if (strcmp(value, "802.3") == 0)
+			self->media = MEDIA_802_3;
+		else
+			self->media = MEDIA_802_5;
+		return;
+	}
+	if (strcmp(param, "FILTER_TYPE") == 0) {
+		if (strcmp(value, "DIRECTED") == 0)
+			self->client.filter_type |= IRLAN_DIRECTED;
+		else if (strcmp(value, "FUNCTIONAL") == 0)
+			self->client.filter_type |= IRLAN_FUNCTIONAL;
+		else if (strcmp(value, "GROUP") == 0)
+			self->client.filter_type |= IRLAN_GROUP;
+		else if (strcmp(value, "MAC_FRAME") == 0)
+			self->client.filter_type |= IRLAN_MAC_FRAME;
+		else if (strcmp(value, "MULTICAST") == 0)
+			self->client.filter_type |= IRLAN_MULTICAST;
+		else if (strcmp(value, "BROADCAST") == 0)
+			self->client.filter_type |= IRLAN_BROADCAST;
+		else if (strcmp(value, "IPX_SOCKET") == 0)
+			self->client.filter_type |= IRLAN_IPX_SOCKET;
+		
+	}
+	if (strcmp(param, "ACCESS_TYPE") == 0) {
+		if (strcmp(value, "DIRECT") == 0)
+			self->access_type = ACCESS_DIRECT;
+		else if (strcmp(value, "PEER") == 0)
+			self->access_type = ACCESS_PEER;
+		else if (strcmp(value, "HOSTED") == 0)
+			self->access_type = ACCESS_HOSTED;
+		else {
+			DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
+		}
+	}
+	/*
+	 *  IRLAN version
+	 */
+	if (strcmp(param, "IRLAN_VER") == 0) {
+		DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0], 
+		      (__u8) value[1]);
+
+		self->version[0] = value[0];
+		self->version[1] = value[1];
+		return;
+	}
+	/*
+	 *  Which remote TSAP to use for data channel
+	 */
+	if (strcmp(param, "DATA_CHAN") == 0) {
+		self->dtsap_sel_data = value[0];
+		DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
+		return;
+	}
+	if (strcmp(param, "CON_ARB") == 0) {
+		self->client.recv_arb_val = le16_to_cpup(value);
+		DEBUG(2, __FUNCTION__ "(), receive arb val=%d\n", 
+		      self->client.recv_arb_val);
+	}
+	if (strcmp(param, "MAX_FRAME") == 0) {
+		self->client.max_frame = le16_to_cpup(value);
+		DEBUG(4, __FUNCTION__ "(), max frame=%d\n", 
+		      self->client.max_frame);
+	}
+	 
+	/*
+	 *  RECONNECT_KEY, in case the link goes down!
+	 */
+	if (strcmp(param, "RECONNECT_KEY") == 0) {
+		DEBUG(4, "Got reconnect key: ");
+		/* for (i = 0; i < val_len; i++) */
+/* 			printk("%02x", value[i]); */
+		memcpy(self->client.reconnect_key, value, val_len);
+		self->client.key_len = val_len;
+		DEBUG(4, "\n");
+	}
+	/*
+	 *  FILTER_ENTRY, have we got an ethernet address?
+	 */
+	if (strcmp(param, "FILTER_ENTRY") == 0) {
+		bytes = value;
+		DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
+		      bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 
+		      bytes[5]);
+		for (i = 0; i < 6; i++) 
+			self->dev.dev_addr[i] = bytes[i];
+
+#ifdef CONFIG_IRLAN_GRATUITOUS_ARP
+		/* 
+		 * When we get a new MAC address do a gratuitous ARP. This
+		 * is useful if we have changed access points on the same
+		 * subnet.  
+		 */
+		DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
+		in_dev = self->dev.ip_ptr;
+		arp_send(ARPOP_REQUEST, ETH_P_ARP, 
+			  in_dev->ifa_list->ifa_address,
+			  &self->dev, 
+			  in_dev->ifa_list->ifa_address,
+			  NULL, self->dev.dev_addr, NULL);
+#endif
+	}
+}
+
+/*
+ * Function irlan_client_get_value_confirm (obj_id, value)
+ *
+ *    Got results from remote LM-IAS
+ *
+ */
+void irlan_client_get_value_confirm(__u16 obj_id, struct ias_value *value,
+				    void *priv) 
+{
+	struct irlan_cb *self;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(priv != NULL, return;);
+
+	self = (struct irlan_cb *) priv;
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if request succeeded */
+	if (!value) {
+		DEBUG(2, __FUNCTION__ "(), got NULL value!\n");
+		irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, 
+				      NULL);
+		return;
+	}
+
+	switch (value->type) {
+	case IAS_INTEGER:
+		self->dtsap_sel_ctrl = value->t.integer;
+
+		if (value->t.integer != -1) {
+			irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
+					      NULL);
+			return;
+		}
+		break;
+	case IAS_STRING:
+		DEBUG(2, __FUNCTION__ "(), got string %s\n", value->t.string);
+		break;
+	case IAS_OCT_SEQ:
+		DEBUG(2, __FUNCTION__ "(), OCT_SEQ not implemented\n");
+		break;
+	case IAS_MISSING:
+		DEBUG(2, __FUNCTION__ "(), MISSING not implemented\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), unknown type!\n");
+		break;
+	}
+	irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
+}
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_client_event.c linux-2.2.3-pre3/net/irda/irlan/irlan_client_event.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_client_event.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_client_event.c	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,532 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client_event.c
+ * Version:       0.9
+ * Description:   IrLAN client state machine
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Thu Feb  4 16:08:07 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     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.
+ *
+ ********************************************************************/
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/timer.h>
+#include <net/irda/irmod.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_client.h>
+#include <net/irda/irlan_event.h>
+
+static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_arb  (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb);
+
+static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
+{ 
+	irlan_client_state_idle,
+	irlan_client_state_query,
+	irlan_client_state_conn,
+	irlan_client_state_info,
+	irlan_client_state_media,
+	irlan_client_state_open,
+	irlan_client_state_wait,
+	irlan_client_state_arb,
+	irlan_client_state_data,
+	irlan_client_state_close,
+	irlan_client_state_sync
+};
+
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			   struct sk_buff *skb) 
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	(*state[ self->client.state]) (self, event, skb);
+}
+
+/*
+ * Function irlan_client_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+	
+	switch(event) {
+	case IRLAN_DISCOVERY_INDICATION:
+		/* Get some values from peer IAS */
+		iriap_getvaluebyclass_request(
+			"IrLAN", "IrDA:TinyTP:LsapSel",
+			self->saddr, self->daddr,
+			irlan_client_get_value_confirm, self);
+		
+		irlan_next_client_state(self, IRLAN_QUERY);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb) 
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_query (event, skb, info)
+ *
+ *    QUERY, We have queryed the remote IAS and is ready to connect
+ *    to provider, just waiting for the confirm.
+ *
+ */
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+	
+	switch(event) {
+	case IRLAN_IAS_PROVIDER_AVAIL:
+		ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
+
+		self->client.open_retries = 0;
+		
+		irttp_connect_request(self->client.tsap_ctrl, 
+				      self->dtsap_sel_ctrl, 
+				      self->saddr, self->daddr, NULL, 
+				      IRLAN_MTU, NULL);
+		irlan_next_client_state(self, IRLAN_CONN);
+		break;
+	case IRLAN_IAS_PROVIDER_NOT_AVAIL:
+		DEBUG(2, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
+		irlan_next_client_state(self, IRLAN_IDLE);
+
+		/* Give the client a kick! */
+		if ((self->access_type == ACCESS_PEER) && 
+		    (self->provider.state != IRLAN_IDLE))
+			irlan_client_wakeup(self, self->saddr, self->daddr);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__"(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_conn (event, skb, info)
+ *
+ *    CONN, We have connected to a provider but has not issued any
+ *    commands yet.
+ *
+ */
+static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_CONNECT_COMPLETE:
+		/* Send getinfo cmd */
+		irlan_get_provider_info(self);
+		irlan_next_client_state(self, IRLAN_INFO);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_info (self, event, skb, info)
+ *
+ *    INFO, We have issued a GetInfo command and is awaiting a reply.
+ */
+static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		ASSERT(skb != NULL, return -1;);
+	
+		irlan_client_extract_params(self, skb);
+		
+		irlan_next_client_state(self, IRLAN_MEDIA);
+		
+		irlan_get_media_char(self);
+		break;
+		
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_media (self, event, skb, info)
+ *
+ *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
+ *    reply.
+ *
+ */
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		irlan_client_extract_params(self, skb);
+		irlan_open_data_channel(self);
+		irlan_next_client_state(self, IRLAN_OPEN);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_open (self, event, skb, info)
+ *
+ *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
+ *    reply
+ *
+ */
+static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	struct qos_info qos;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		irlan_client_extract_params(self, skb);
+		
+		/*
+		 *  Check if we have got the remote TSAP for data 
+		 *  communications
+		 */
+	  	ASSERT(self->dtsap_sel_data != 0, return -1;);
+
+		/* Check which access type we are dealing with */
+		switch(self->access_type) {
+		case ACCESS_PEER:
+		    if (self->provider.state == IRLAN_OPEN) {
+			    
+			    irlan_next_client_state(self, IRLAN_ARB);
+			    irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, 
+						  NULL);
+		    } else {
+			
+			    irlan_next_client_state(self, IRLAN_WAIT);
+		    }
+		    break;
+		case ACCESS_DIRECT:
+		case ACCESS_HOSTED:
+			qos.link_disc_time.bits = 0x01; /* 3 secs */
+			
+			irttp_connect_request(self->tsap_data, 
+					      self->dtsap_sel_data, 
+					      self->saddr, self->daddr, &qos, 
+					      IRLAN_MTU, NULL);
+			
+			irlan_next_client_state(self, IRLAN_DATA);
+
+			if (self->client.start_new_provider) {
+				irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+				self->client.start_new_provider = FALSE;
+			}
+			break;
+		default:
+			DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
+			break;
+		}
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_wait (self, event, skb, info)
+ *
+ *    WAIT, The irlan_client is waiting for the local provider to enter the
+ *    provider OPEN state.
+ *
+ */
+static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_PROVIDER_SIGNAL:
+		irlan_next_client_state(self, IRLAN_ARB);
+		irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event, 
+				  struct sk_buff *skb) 
+{
+	struct qos_info qos;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_CHECK_CON_ARB:
+		if (self->client.recv_arb_val == self->provider.send_arb_val) {
+			irlan_next_client_state(self, IRLAN_CLOSE);
+			irlan_close_data_channel(self);
+		} else if (self->client.recv_arb_val < 
+			   self->provider.send_arb_val) 
+		{
+			qos.link_disc_time.bits = 0x01; /* 3 secs */
+
+			irlan_next_client_state(self, IRLAN_DATA);
+			irttp_connect_request(self->tsap_data, 
+					      self->dtsap_sel_data, 
+					      self->saddr, self->daddr, &qos, 
+					      IRLAN_MTU, NULL);
+		} else if (self->client.recv_arb_val >
+			   self->provider.send_arb_val) 
+		{
+			DEBUG(2, __FUNCTION__ "(), lost the battle :-(\n");
+		}
+		break;
+	case IRLAN_DATA_CONNECT_INDICATION:
+		irlan_next_client_state(self, IRLAN_DATA);
+		break;
+	case IRLAN_LMP_DISCONNECT:
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	case IRLAN_WATCHDOG_TIMEOUT:
+		DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_data (self, event, skb, info)
+ *
+ *    DATA, The data channel is connected, allowing data transfers between
+ *    the local and remote machines.
+ *
+ */
+static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+
+	switch(event) {
+	case IRLAN_DATA_INDICATION:
+		irlan_client_extract_params(self, skb);
+		break;		
+	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_client_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_close (self, event, skb, info)
+ *
+ *    
+ *
+ */
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
+				    struct sk_buff *skb) 
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_client_state_sync (self, event, skb, info)
+ *
+ *    
+ *
+ */
+static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+	
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_cli_event.c linux-2.2.3-pre3/net/irda/irlan/irlan_cli_event.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_cli_event.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_cli_event.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,494 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_cli_event.c
- * Version:       0.1
- * Description:   IrLAN Client FSM (Finite State Machine)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Wed Dec  9 02:36:49 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
- *     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.
- *
- ********************************************************************/
-
-#include <linux/skbuff.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_cli.h>
-#include <net/irda/irlan_event.h>
-
-static int irlan_client_state_idle ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_query( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_conn ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_info ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_media( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_open ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_wait ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_arb  ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_data ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_close( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-static int irlan_client_state_sync ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb);
-
-static int (*state[])( struct irlan_cb *, IRLAN_EVENT event, 
-		       struct sk_buff *) = 
-{ 
-	irlan_client_state_idle,
-	irlan_client_state_query,
-	irlan_client_state_conn,
-	irlan_client_state_info,
-	irlan_client_state_media,
-	irlan_client_state_open,
-	irlan_client_state_wait,
-	irlan_client_state_arb,
-	irlan_client_state_data,
-	irlan_client_state_close,
-	irlan_client_state_sync
-};
-
-void irlan_do_client_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb) 
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	(*state[ self->state]) ( self, event, skb);
-}
-
-/*
- * Function irlan_client_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlan_client_state_idle( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, "irlan_client_state_idle()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-	
-	switch( event) {
-	case IRLAN_DISCOVERY_INDICATION:
-		/* Get some values from peer IAS */
-#if 0
-		iriap_getvaluebyclass_request( self->daddr,
-					       /*  "PnP", "DeviceID",  */
-					       "Device", "DeviceName",
-					       irlan_client_get_value_confirm,
-					       self);
-#endif
-		iriap_getvaluebyclass_request( self->daddr,
-					       "IrLAN", "IrDA:TinyTP:LsapSel",
-					       irlan_client_get_value_confirm,
-					       self);
-
-		irlan_next_state( self, IRLAN_QUERY);
-		break;
-	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	return 0;
-}
-
-/*
- * Function irlan_client_state_query (event, skb, info)
- *
- *    QUERY, We have queryed the remote IAS and is ready to connect
- *    to provider, just waiting for the confirm.
- *
- */
-static int irlan_client_state_query( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-	
-	switch( event) {
-	case IRLAN_IAS_PROVIDER_AVAIL:
-		ASSERT( self->dtsap_sel_ctrl != 0, return -1;);
-
-		self->t.client.open_retries = 0;
-		
-		irttp_connect_request( self->tsap_ctrl, self->dtsap_sel_ctrl, 
-				       self->daddr, NULL, IRLAN_MTU, NULL);
-		irlan_next_state( self, IRLAN_CONN);
-		break;
-	case IRLAN_IAS_PROVIDER_NOT_AVAIL:
-		DEBUG( 0, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_conn (event, skb, info)
- *
- *    CONN, We have connected to a provider but has not issued any
- *    commands yet.
- *
- */
-static int irlan_client_state_conn( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_CONNECT_COMPLETE:
-		/* Send getinfo cmd */
-		irlan_get_provider_info( self);
-		irlan_next_state( self, IRLAN_INFO);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_info (self, event, skb, info)
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlan_client_state_info( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_DATA_INDICATION:
-		ASSERT( skb != NULL, return -1;);
-	
-		irlan_client_extract_params( self, skb);
-		
-		irlan_next_state( self, IRLAN_MEDIA);
-		
-		irlan_get_media_char( self);
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_media (self, event, skb, info)
- *
- *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
- *    reply.
- *
- */
-static int irlan_client_state_media( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_DATA_INDICATION:
-		irlan_client_extract_params( self, skb);
-		irlan_open_data_channel( self);
-		irlan_next_state( self, IRLAN_OPEN);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, "irlan_client_state_media, Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_open (self, event, skb, info)
- *
- *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
- *    reply
- *
- */
-static int irlan_client_state_open( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	struct qos_info qos;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_DATA_INDICATION:
-		irlan_client_extract_params( self, skb);
-		
-		/*
-		 *  Check if we have got the remote TSAP for data 
-		 *  communications
-		 */
-	  	ASSERT( self->dtsap_sel_data != 0, return -1;);
-
-		qos.link_disc_time.bits = 0x01; /* 3 secs */
-
-		irttp_connect_request( self->tsap_data, 
-				       self->dtsap_sel_data, self->daddr,
-				       NULL, IRLAN_MTU, NULL);
-		
-  		irlan_next_state( self, IRLAN_DATA);
-		break;
-
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	return 0;
-}
-
-/*
- * Function irlan_client_state_wait (self, event, skb, info)
- *
- *    WAIT, The irlan_client is waiting for the local provider to enter the
- *    provider OPEN state.
- *
- */
-static int irlan_client_state_wait( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 4, "irlan_client_state_wait()\n");
-	
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-static int irlan_client_state_arb( struct irlan_cb *self, 
-				   IRLAN_EVENT event, 
-				   struct sk_buff *skb) 
-{
-	DEBUG( 0, __FUNCTION__ "(), not implemented!\n");
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	return 0;
-}
-
-/*
- * Function irlan_client_state_data (self, event, skb, info)
- *
- *    DATA, The data channel is connected, allowing data transfers between
- *    the local and remote machines.
- *
- */
-static int irlan_client_state_data( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	struct irmanager_event mgr_event;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLAN_CONNECT_COMPLETE:
-		irlan_get_unicast_addr( self);
-		irlan_open_unicast_addr( self);
-		/* irlan_set_broadcast_filter( self, TRUE);  */
-
-		DEBUG( 4, "IrLAN, We are now connected!\n");
-
-		/* irlan_next_state( LAN_DATA); */
-		break;
-	case IRLAN_DATA_INDICATION:
-		irlan_client_extract_params( self, skb);
-
-		/* irlan_client_flow_indication( self->data_tsap, FLOW_START,  */
-/* 					self); */
-
-		/* Make sure the code below only runs once */
-		if ( !self->connected) {
-			mgr_event.event = EVENT_IRLAN_START;
-			sprintf( mgr_event.devname, "%s", self->ifname);
-			irmanager_notify( &mgr_event);
-
-			self->connected = TRUE;
-		}
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		mgr_event.event = EVENT_IRLAN_STOP;
-		sprintf( mgr_event.devname, "%s", self->ifname);
-		irmanager_notify( &mgr_event);
-
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_client_state_close (self, event, skb, info)
- *
- *    
- *
- */
-static int irlan_client_state_close( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb) 
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	return 0;
-}
-
-/*
- * Function irlan_client_state_sync (self, event, skb, info)
- *
- *    
- *
- */
-static int irlan_client_state_sync( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb) 
-{
-	DEBUG( 0, __FUNCTION__ "()\n");
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_common.c linux-2.2.3-pre3/net/irda/irlan/irlan_common.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_common.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_common.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlan_common.c
- * Version:       0.1
+ * Version:       0.9
  * Description:   IrDA LAN Access Protocol Implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Tue Jan 19 23:11:30 1999
+ * Modified at:   Wed Feb 17 23:49:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -44,17 +44,59 @@
 #include <net/irda/timer.h>
 
 #include <net/irda/irlan_common.h>
+#include <net/irda/irlan_client.h>
+#include <net/irda/irlan_provider.h> 
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_filter.h>
 
-static void __irlan_close( struct irlan_cb *self);
+/* extern char sysctl_devname[]; */
 
 /*
  *  Master structure
  */
 hashbin_t *irlan = NULL;
 
+/* Module parameters */
+static int eth = 0; /* Use "eth" or "irlan" name for devices */
+static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
+static int timeout = IRLAN_TIMEOUT;
+
+static char *irlan_state[] = {
+	"IRLAN_IDLE",
+	"IRLAN_QUERY",
+	"IRLAN_CONN", 
+	"IRLAN_INFO",
+	"IRLAN_MEDIA",
+	"IRLAN_OPEN",
+	"IRLAN_WAIT",
+	"IRLAN_ARB", 
+	"IRLAN_DATA",
+	"IRLAN_CLOSE",
+	"IRLAN_SYNC"
+};
+
+static char *irlan_access[] = {
+	"UNKNOWN",
+	"DIRECT",
+	"PEER",
+	"HOSTED"
+};
+
+static char *irlan_media[] = {
+	"UNKNOWN",
+	"802.3",
+	"802.5"
+};
+
+static void __irlan_close(struct irlan_cb *self);
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
+				__u8 value_byte, __u16 value_short, 
+				__u8 *value_array, __u16 value_len);
+static void irlan_close_tsaps(struct irlan_cb *self);
+
 #ifdef CONFIG_PROC_FS
-static int irlan_proc_read( char *buf, char **start, off_t offset, 
-			    int len, int unused);
+static int irlan_proc_read(char *buf, char **start, off_t offset, int len, 
+			   int unused);
 
 extern struct proc_dir_entry proc_irda;
 
@@ -64,7 +106,164 @@
 	0, NULL,
 	&irlan_proc_read,
 };
+#endif /* CONFIG_PROC_FS */
+
+void irlan_watchdog_timer_expired(unsigned long data)
+{
+	struct irmanager_event mgr_event;
+	struct irlan_cb *self = (struct irlan_cb *) data;
+	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if device still configured */
+	if (self->dev.start) {
+		mgr_event.event = EVENT_IRLAN_STOP;
+		sprintf(mgr_event.devname, "%s", self->ifname);
+		irmanager_notify(&mgr_event);
+
+		/*
+		 *  We set this to false, so that irlan_dev_close known that
+		 *  notify_irmanager should actually be set to TRUE again 
+		 *  instead of FALSE, since this close has not been initiated
+		 *  by the user.
+		 */
+		self->notify_irmanager = FALSE;
+	} else
+		irlan_close(self);
+}
+
+void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self,
+			 irlan_watchdog_timer_expired);
+}
+
+static int irlan_eth_open(struct device *dev)
+{
+	struct irlan_cb *self;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = (struct irlan_cb *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	/* Ready to play! */
+/* 	dev->tbusy = 0; */ /* Wait until data link is ready */
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	self->notify_irmanager = TRUE;
+
+	MOD_INC_USE_COUNT;
+	
+	return 0;
+}
+
+/*
+ * Function irlan_eth_close (dev)
+ *
+ *    Stop the ether network device, his function will usually be called by
+ *    ifconfig down. We should now disconnect the link, We start the 
+ *    close timer, so that the instance will be removed if we are unable
+ *    to discover the remote device after the disconnect.
+ */
+static int irlan_eth_close(struct device *dev)
+{
+	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	MOD_DEC_USE_COUNT;
+
+	irlan_close_data_channel(self);
+
+	irlan_close_tsaps(self);
+
+	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);	
+	
+	irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+
+	/* Device closed by user */
+	if (self->notify_irmanager)
+		self->notify_irmanager = FALSE;
+	else
+		self->notify_irmanager = TRUE;
+
+	return 0;
+}
+/*
+ * Function irlan_eth_init (dev)
+ *
+ *    The network device initialization function.
+ *
+ */
+int irlan_eth_init(struct device *dev)
+{
+	struct irmanager_event mgr_event;
+	struct irlan_cb *self;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(dev != NULL, return -1;);
+       
+	self = (struct irlan_cb *) dev->priv;
+
+	dev->open               = irlan_eth_open;
+	dev->stop               = irlan_eth_close;
+	dev->hard_start_xmit    = irlan_eth_xmit; 
+	dev->get_stats	        = irlan_eth_get_stats;
+	dev->set_multicast_list = irlan_eth_set_multicast_list;
+
+	dev->tbusy = 1;
+	
+	ether_setup(dev);
+	
+	dev->tx_queue_len = TTP_MAX_QUEUE;
+
+#ifdef 0
+	/*  
+	 *  OK, since we are emulating an IrLAN sever we will have to give
+	 *  ourself an ethernet address!
+	 *  FIXME: this must be more dynamically
+	 */
+	dev->dev_addr[0] = 0x40;
+	dev->dev_addr[1] = 0x00;
+	dev->dev_addr[2] = 0x00;
+	dev->dev_addr[3] = 0x00;
+	dev->dev_addr[4] = 0x23;
+	dev->dev_addr[5] = 0x45;
 #endif
+	/* 
+	 * Network device has now been registered, so tell irmanager about
+	 * it, so it can be configured with network parameters
+	 */
+	mgr_event.event = EVENT_IRLAN_START;
+	sprintf(mgr_event.devname, "%s", self->ifname);
+	irmanager_notify(&mgr_event);
+
+	/* 
+	 * We set this so that we only notify once, since if 
+	 * configuration of the network device fails, the user
+	 * will have to sort it out first anyway. No need to 
+	 * try again.
+	 */
+	self->notify_irmanager = FALSE;
+
+	return 0;
+}
 
 /*
  * Function irlan_init (void)
@@ -72,61 +271,147 @@
  *    Initialize IrLAN layer
  *
  */
-__initfunc(int irlan_init( void))
+__initfunc(int irlan_init(void))
 {
+	struct irlan_cb *new;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
 	/* Allocate master array */
-	irlan = hashbin_new( HB_LOCAL); 
-	if ( irlan == NULL) {
-		printk( KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
+	irlan = hashbin_new(HB_LOCAL); 
+	if (irlan == NULL) {
+		printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
 		return -ENOMEM;
 	}
 #ifdef CONFIG_PROC_FS
-	proc_register( &proc_irda, &proc_irlan);
+	proc_register(&proc_irda, &proc_irlan);
 #endif /* CONFIG_PROC_FS */
 
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	/* Register with IrLMP as a service user */
+	irlmp_register_layer(S_LAN, CLIENT, TRUE, 
+			     irlan_client_discovery_indication);
+	
+	/* Register with IrLMP as a service */
+ 	irlmp_register_layer(S_LAN, SERVER, FALSE, NULL);
+
+	/* Start the first IrLAN instance */
+ 	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+
+	/* Do some fast discovery! */
+	irlmp_discovery_request(8);
+
 	return 0;
 }
 
 void irlan_cleanup(void) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	irlmp_unregister_layer(S_LAN, SERVER);
+
+	irlmp_unregister_layer(S_LAN, CLIENT);
 
 #ifdef CONFIG_PROC_FS
-	proc_unregister( &proc_irda, proc_irlan.low_ino);
-#endif
+	proc_unregister(&proc_irda, proc_irlan.low_ino);
+#endif /* CONFIG_PROC_FS */
 	/*
 	 *  Delete hashbin and close all irlan client instances in it
 	 */
-	hashbin_delete( irlan, (FREE_FUNC) __irlan_close);
+	hashbin_delete(irlan, (FREE_FUNC) __irlan_close);
 }
 
+/*
+ * Function irlan_register_netdev (self)
+ *
+ *    Registers the network device to be used. We should don't register until
+ *    we have been binded to a particular provider or client.
+ */
+int irlan_register_netdev(struct irlan_cb *self)
+{
+	int i=0;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Check if we should call the device eth<x> or irlan<x> */
+	if (!eth) {
+		/* Get the first free irlan<x> name */
+		do {
+			sprintf(self->ifname, "%s%d", "irlan", i++);
+		} while (dev_get(self->ifname) != NULL);
+	}
+	self->dev.name = self->ifname;
+	
+	if (register_netdev(&self->dev) != 0) {
+		DEBUG(2, __FUNCTION__ 
+		      "(), register_netdev() failed!\n");
+		return -1;
+	}
+	self->netdev_registered = TRUE;
+	
+	return 0;
+}
 
 /*
  * Function irlan_open (void)
  *
- *    
- *
+ *    Open new instance of a client/provider, we should only register the 
+ *    network device if this instance is ment for a particular client/provider
  */
-struct irlan_cb *irlan_open(void)
+struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev)
 {
 	struct irlan_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
 	/* 
 	 *  Initialize the irlan structure. 
 	 */
-	self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
-	if ( self == NULL)
+	self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC);
+	if (self == NULL)
 		return NULL;
 	
-	memset( self, 0, sizeof( struct irlan_cb));
+	memset(self, 0, sizeof(struct irlan_cb));
 
 	/*
 	 *  Initialize local device structure
 	 */
 	self->magic = IRLAN_MAGIC;
 
+	ASSERT(irlan != NULL, return NULL;);
+	
+	sprintf(self->ifname, "%s", "unknown");
+
+	self->dev.priv = (void *) self;
+	self->dev.next = NULL;
+	self->dev.init = irlan_eth_init;
+	
+	self->saddr = saddr;
+	self->daddr = daddr;
+
+	/* Provider access can only be PEER, DIRECT, or HOSTED */
+	self->access_type = access;
+	self->media = MEDIA_802_3;
+
+	self->notify_irmanager = TRUE;
+
+	init_timer(&self->watchdog_timer);
+	init_timer(&self->client.kick_timer);
+
+	hashbin_insert(irlan, (QUEUE *) self, daddr, NULL);
+		
+	irlan_next_client_state(self, IRLAN_IDLE);
+	irlan_next_provider_state(self, IRLAN_IDLE);
+
+	irlan_open_data_tsap(self);
+  	irlan_provider_open_ctrl_tsap(self);
+	irlan_client_open_ctrl_tsap(self);
+
+	/* Register network device now, or wait until some later time? */
+	if (netdev)
+		irlan_register_netdev(self);
+
 	return self;
 }
 /*
@@ -137,63 +422,281 @@
  *    hashbin_remove() first!!!
  *
  */
-void __irlan_close( struct irlan_cb *self)
+static void __irlan_close(struct irlan_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	/* 
-	 *  Disconnect open TSAP connections
-	 */
-	if ( self->tsap_data) {
-		irttp_disconnect_request( self->tsap_data, NULL, P_HIGH);
-		
-		/* FIXME: this will close the tsap before the disconenct
-		 * frame has been sent 
+	del_timer(&self->watchdog_timer);
+	del_timer(&self->client.kick_timer);
+
+	/* Close all open connections and remove TSAPs */
+	irlan_close_tsaps(self);
+
+	if (self->netdev_registered)
+		unregister_netdev(&self->dev);
+	
+	self->magic = 0;
+	kfree(self);
+}
+
+/*
+ * Function irlan_close (self)
+ *
+ *    Close instance
+ *
+ */
+void irlan_close(struct irlan_cb *self)
+{
+	struct irlan_cb *entry;
+	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+        ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if device is still configured */
+	if (self->dev.start) {
+		DEBUG(2, __FUNCTION__ 
+		       "(), Device still configured, closing later!\n");
+		return;
+	}
+	DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+	entry = hashbin_remove(irlan, self->daddr, NULL);
+
+	ASSERT(entry == self, return;);
+	
+        __irlan_close(self);
+}
+
+void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
+			      int max_sdu_size, struct sk_buff *skb)
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	ASSERT(tsap == self->tsap_data,return;);
+
+	DEBUG(2, "IrLAN, We are now connected!\n");
+	del_timer(&self->watchdog_timer);
+
+	irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
+	irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
+
+	if (self->access_type == ACCESS_PEER) {
+		/* 
+		 * Data channel is open, so we are now allowed to
+		 * configure the remote filter 
 		 */
-		/* irttp_close_tsap( self->tsap_data); */
+		irlan_get_unicast_addr(self);
+		irlan_open_unicast_addr(self);
 	}
-	if ( self->tsap_ctrl) {
-		irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH);
-		
-		/* irttp_close_tsap( self->tsap_control); */
+	/* Ready to transfer Ethernet frames */
+	self->dev.tbusy = 0;
+}
+
+void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
+			   int max_sdu_size, struct sk_buff *skb) 
+{
+	struct irlan_cb *self;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	self = (struct irlan_cb *) instance;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* TODO: we could set the MTU depending on the max_sdu_size */
+
+	DEBUG(2, "IrLAN, We are now connected!\n");
+	del_timer(&self->watchdog_timer);
+
+	/* 
+	 * Data channel is open, so we are now allowed to configure the remote
+	 * filter 
+	 */
+	irlan_get_unicast_addr(self);
+	irlan_open_unicast_addr(self);
+
+	/* Ready to transfer Ethernet frames */
+	self->dev.tbusy = 0;
+}
+
+/*
+ * Function irlan_client_disconnect_indication (handle)
+ *
+ *    Callback function for the IrTTP layer. Indicates a disconnection of
+ *    the specified connection (handle)
+ */
+void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
+				 struct sk_buff *userdata) 
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason);
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(tsap != NULL, return;);
+	ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+	
+	ASSERT(tsap == self->tsap_data, return;);
+
+	DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
+
+	switch(reason) {
+	case LM_USER_REQUEST: /* User request */
+		irlan_close(self);
+		break;
+	case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
+		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+		break;
+	case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
+		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		break;
+	case LM_LAP_RESET:  /* IrLAP reset */
+		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		break;
+	case LM_INIT_DISCONNECT:
+		DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+		break;
+	default:
+		break;
 	}
 	
-	unregister_netdev( &self->dev);
+	/* Stop IP from transmitting more packets */
+	/* irlan_client_flow_indication(handle, FLOW_STOP, priv); */
 
-	/*
-	 *  Make sure that nobody uses this instance anymore!
+	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+void irlan_open_data_tsap(struct irlan_cb *self)
+{
+	struct notify_t notify;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if already open */
+	if (self->tsap_data)
+		return;
+
+	irda_notify_init(&notify);
+
+	notify.data_indication       = irlan_eth_receive;
+	notify.udata_indication      = irlan_eth_receive;
+	notify.connect_indication    = irlan_connect_indication;
+	notify.connect_confirm       = irlan_connect_confirm;
+ 	notify.flow_indication       = irlan_eth_flow_indication;
+	notify.disconnect_indication = irlan_disconnect_indication;
+	notify.instance              = self;
+	strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
+
+	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+	if (!tsap) {
+		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		return;
+	}
+	self->tsap_data = tsap;
+
+	/* 
+	 *  This is the data TSAP selector which we will pass to the client
+	 *  when the client ask for it.
 	 */
-	self->magic = 0;
-	
-	/*
-	 *  Dealloacte structure
+	self->stsap_sel_data = self->tsap_data->stsap_sel;
+}
+
+static void irlan_close_tsaps(struct irlan_cb *self)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* 
+	 *  Disconnect and close all open TSAP connections
 	 */
-	kfree( self);
+	if (self->tsap_data) {
+		irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
+		irttp_close_tsap(self->tsap_data);
+		self->tsap_data = NULL;
+		
+	}
+	if (self->client.tsap_ctrl) {
+		irttp_disconnect_request(self->client.tsap_ctrl, NULL, 
+					 P_NORMAL);
+		irttp_close_tsap(self->client.tsap_ctrl);
+		self->client.tsap_ctrl = NULL;
+	}
+	if (self->provider.tsap_ctrl) {
+		irttp_disconnect_request(self->provider.tsap_ctrl, NULL, 
+					 P_NORMAL);
+		irttp_close_tsap(self->provider.tsap_ctrl);
+		self->provider.tsap_ctrl = NULL;
+	}
 }
 
 /*
- * Function irlan_close (self)
+ * Function irlan_ias_register (self, tsap_sel)
  *
- *    
+ *    Register with LM-IAS
  *
  */
-void irlan_close( struct irlan_cb *self)
+void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
 {
-	struct irlan_cb *entry;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	struct ias_object *obj;
+	struct ias_value *new_value;
 
-        ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	entry = hashbin_remove( irlan, self->daddr, NULL);
-
-	ASSERT( entry == self, return;);
+	/* 
+	 * Check if object has already been registred by a previous provider.
+	 * If that is the case, we just change the value of the attribute
+	 */
+	if (!irias_find_object("IrLAN")) {
+		obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
+		irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel);
+		irias_insert_object(obj);
+	} else {
+		new_value = irias_new_integer_value(tsap_sel);
+		irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
+					      new_value);
+	}
 	
-        __irlan_close( self);
+        /* Register PnP object only if not registred before */
+        if (!irias_find_object("PnP")) {
+		obj = irias_new_object("PnP", IAS_PNP_ID);
+#if 0
+		irias_add_string_attrib(obj, "Name", sysctl_devname);
+#else
+		irias_add_string_attrib(obj, "Name", "Linux");
+#endif
+		irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
+		irias_add_integer_attrib(obj, "CompCnt", 2);
+		irias_add_string_attrib(obj, "Comp#01", "PNP8294");
+		irias_add_string_attrib(obj, "Comp#02", "PNP8389");
+		irias_add_string_attrib(obj, "Manufacturer", "Linux-IrDA Project");
+		irias_insert_object(obj);
+	}
 }
 
 /*
@@ -202,33 +705,30 @@
  *    Send Get Provider Information command to peer IrLAN layer
  *
  */
-void irlan_get_provider_info( struct irlan_cb *self)
+void irlan_get_provider_info(struct irlan_cb *self)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_GET_PROVIDER_INFO;
 	frame[1] = 0x00;                 /* Zero parameters */
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -237,26 +737,22 @@
  *    Send an Open Data Command to provider
  *
  */
-void irlan_open_data_channel( struct irlan_cb *self) 
+void irlan_open_data_channel(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
@@ -264,13 +760,41 @@
  	frame[0] = CMD_OPEN_DATA_CHANNEL;
 	frame[1] = 0x02; /* Two parameters */
 
-	insert_string_param( skb, "MEDIA", "802.3");
-	insert_string_param( skb, "ACCESS_TYPE", "DIRECT");
-	/* insert_string_param( skb, "MODE", "UNRELIABLE"); */
+	irlan_insert_string_param(skb, "MEDIA", "802.3");
+	irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
+	/* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
 
 /* 	self->use_udata = TRUE; */
 
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
+}
+
+void irlan_close_data_channel(struct irlan_cb *self) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	skb = dev_alloc_skb(64);
+	if (!skb)
+		return;
+
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
+	
+	frame = skb->data;
+	
+	/* Build frame */
+ 	frame[0] = CMD_CLOSE_DATA_CHAN;
+	frame[1] = 0x01; /* Two parameters */
+
+	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -280,84 +804,74 @@
  *    address.
  *
  */
-void irlan_open_unicast_addr( struct irlan_cb *self) 
+void irlan_open_unicast_addr(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
 	
-	skb = dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
+	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN" , self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
- 	insert_string_param( skb, "FILTER_MODE", "FILTER"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+ 	irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
  * Function irlan_set_broadcast_filter (self, status)
  *
  *    Make IrLAN provider accept ethernet frames addressed to the broadcast
- *    address. Be careful with the use of this one, sice there may be a lot
+ *    address. Be careful with the use of this one, since there may be a lot
  *    of broadcast traffic out there. We can still function without this
  *    one but then _we_ have to initiate all communication with other
- *    hosts, sice ARP request for this host will not be answered.
+ *    hosts, since ARP request for this host will not be answered.
  */
-void irlan_set_broadcast_filter( struct irlan_cb *self, int status) 
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	/* Should only be used by client */
-	if (!self->client)
+ 	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
 
- 	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
-		return;
-	}
-
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "BROADCAST");
-	if ( status)
-		insert_string_param( skb, "FILTER_MODE", "FILTER"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
+	if (status)
+		irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
 	else
-		insert_string_param( skb, "FILTER_MODE", "NONE"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -367,43 +881,36 @@
  *    address. 
  *
  */
-void irlan_set_multicast_filter( struct irlan_cb *self, int status) 
+void irlan_set_multicast_filter(struct irlan_cb *self, int status) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	/* Should only be used by client */
-	if (!self->client)
+ 	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
 	
- 	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), Could not allocate an skb of length %d\n", 64);
-		return;
-	}
-
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "MULTICAST");
-	if ( status)
-		insert_string_param( skb, "FILTER_MODE", "ALL"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
+	if (status)
+		irlan_insert_string_param(skb, "FILTER_MODE", "ALL"); 
 	else
-		insert_string_param( skb, "FILTER_MODE", "NONE"); 
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -414,36 +921,33 @@
  *    can construct its packets.
  *
  */
-void irlan_get_unicast_addr( struct irlan_cb *self) 
+void irlan_get_unicast_addr(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 		
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0, "irlan_client_get_unicast_addr: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(128);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
  	frame[0] = CMD_FILTER_OPERATION;
 	frame[1] = 0x03;                 /* Three parameters */
- 	insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
- 	insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
- 	insert_string_param( skb, "FILTER_OPERATION", "DYNAMIC"); 
+ 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+ 	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+ 	irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC"); 
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -452,26 +956,23 @@
  *    
  *
  */
-void irlan_get_media_char( struct irlan_cb *self) 
+void irlan_get_media_char(struct irlan_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlan_server_get_media_char: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
 	
 	frame = skb->data;
 	
@@ -479,9 +980,9 @@
  	frame[0] = CMD_GET_MEDIA_CHAR;
 	frame[1] = 0x01; /* One parameter */
 	
-	insert_string_param( skb, "MEDIA", "802.3");
+	irlan_insert_string_param(skb, "MEDIA", "802.3");
 	
-	irttp_data_request( self->tsap_ctrl, skb);
+	irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -490,47 +991,14 @@
  *    Insert byte parameter into frame
  *
  */
-int insert_byte_param( struct sk_buff *skb, char *param, __u8 value)
+int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
 {
-	__u8 *frame;
-	__u8 len_param;
-	__u16 len_value;
-	int n=0;
-	
-	if ( skb == NULL) {
-		DEBUG( 0, "insert_param: Got NULL skb\n");
-		return 0;
-	}
-	
-	len_param = strlen( param);
-	len_value = 1;
-
-	/*
-	 *  Insert at end of sk-buffer
-	 */
-	frame = skb->tail;
-
-	/* Make space for data */
-	if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-		DEBUG( 0, "insert_param: No more space at end of skb\n");
-		return 0;
-	}	
-	skb_put( skb, len_param+len_value+3);
-
-	/* Insert parameter length */
-	frame[n++] = len_param;
-	
-	/* Insert parameter */
-	memcpy( frame+n, param, len_param); 
-	n += len_param;
-	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	frame[n++] = len_value & 0xff;
-	frame[n++] = len_value >> 8;
+	return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
+}
 
-	frame[n++] = value;
-	
-	return len_param+len_value+3;
+int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
+{
+	return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
 }
 
 /*
@@ -539,96 +1007,25 @@
  *    Insert string parameter into frame
  *
  */
-int insert_string_param( struct sk_buff *skb, char *param, char *value)
+int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
 {
-	__u8 *frame;
-	__u8 len_param;
-	__u16 len_value;
-	int n=0;
-	
-	if ( skb == NULL) {
-		DEBUG( 0, "insert_param: Got NULL skb\n");
-		return 0;
-	}	
-	len_param = strlen( param);
-	len_value = strlen( value);
+	int string_len = strlen(string);
 
-	/*
-	 *  Insert at end of sk-buffer
-	 */
-	frame = skb->tail;
-
-	/* Make space for data */
-	if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-		DEBUG( 0, "insert_param: No more space at end of skb\n");
-		return 0;
-	}	
-	skb_put( skb, len_param+len_value+3);
-
-	/* Insert parameter length */
-	frame[n++] = len_param;
-	
-	/* Insert parameter */
-	memcpy( frame+n, param, len_param); 
-	n += len_param;
-	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	frame[n++] = len_value & 0xff;
-	frame[n++] = len_value >> 8;
-
-	memcpy( frame+n, value, len_value); 
-	n+=len_value;
-	
-	return len_param+len_value+3;
+	return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string, 
+				    string_len);
 }
 
 /*
- * Function insert_array_param( skb, param, value, len_value)
+ * Function insert_array_param(skb, param, value, len_value)
  *
  *    Insert array parameter into frame
  *
  */
-int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, 
-			__u16 value_len)
+int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
+			     __u16 array_len)
 {
-	__u8 *frame;
-	__u8 name_len;
-	int n=0;
-	
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got NULL skb\n");
-		return 0;
-	}	
-	name_len = strlen( name);
-
-	/*
-	 *  Insert at end of sk-buffer
-	 */
-	frame = skb->tail;
-
-	/* Make space for data */
-	if ( skb_tailroom(skb) < (name_len+value_len+3)) {
-		DEBUG( 0, __FUNCTION__ "(), No more space at end of skb\n");
-		return 0;
-	}	
-	skb_put( skb, name_len+value_len+3);
-
-	/* Insert parameter length */
-	frame[n++] = name_len;
-	
-	/* Insert parameter */
-	memcpy( frame+n, name, name_len); 
-	n += name_len;
-	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	/* FIXME: should we use htons() here? */
-	frame[n++] = value_len & 0xff;
-	frame[n++] = value_len >> 8;
-
-	memcpy( frame+n, value, value_len); 
-	n+=value_len;
-	
-	return name_len+value_len+3;
+	return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array, 
+				    array_len);
 }
 
 /*
@@ -640,130 +1037,121 @@
  *    | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
  *    -----------------------------------------------------------------------
  */
-int insert_param( struct sk_buff *skb, char *param, int type, char *value_char,
- 		  __u8 value_byte, __u16 value_short) 
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
+				__u8 value_byte, __u16 value_short, 
+				__u8 *value_array, __u16 value_len)
 {
 	__u8 *frame;
-	__u8 len_param;
-	__u16 len_value;
-	int n;
+	__u8 param_len;
+	int n=0;
 	
-	if ( skb == NULL) {
-		DEBUG( 0, "insert_param: Got NULL skb\n");
+	if (skb == NULL) {
+		DEBUG(2, __FUNCTION__ "(), Got NULL skb\n");
 		return 0;
-	}
-	
-	n = 0;
+	}	
 
-	len_param = strlen( param);
-	switch ( type) {
-	case 1:
-		ASSERT( value_char != NULL, return 0;);
-		len_value = strlen( value_char);
+	param_len = strlen(param);
+	switch (type) {
+	case IRLAN_BYTE:
+		value_len = 1;
 		break;
-	case 2:
-		len_value = 1;
+	case IRLAN_SHORT:
+		value_len = 2;
 		break;
-	case 3:
-		len_value = 2;
+	case IRLAN_ARRAY:
+		ASSERT(value_array != NULL, return 0;);
+		ASSERT(value_len > 0, return 0;);
 		break;
 	default:
-		DEBUG( 0, "Error in insert_param!\n");
+		DEBUG(2, __FUNCTION__ "(), Unknown parameter type!\n");
 		return 0;
 		break;
 	}
 	
-	/*
-	 *  Insert at end of sk-buffer
-	 */
+	/* Insert at end of sk-buffer */
 	frame = skb->tail;
 
 	/* Make space for data */
-	if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-		DEBUG( 0, "insert_param: No more space at end of skb\n");
+	if (skb_tailroom(skb) < (param_len+value_len+3)) {
+		DEBUG(2, __FUNCTION__ "(), No more space at end of skb\n");
 		return 0;
 	}	
-	skb_put( skb, len_param+len_value+3);
-
+	skb_put(skb, param_len+value_len+3);
+	
 	/* Insert parameter length */
-	frame[n++] = len_param;
+	frame[n++] = param_len;
 	
 	/* Insert parameter */
-	memcpy( frame+n, param, len_param); n += len_param;
+	memcpy(frame+n, param, param_len); n += param_len;
 	
-	/* Insert value length ( 2 byte little endian format, LSB first) */
-	frame[n++] = len_value & 0xff;
-	frame[n++] = len_value >> 8;
+	/* Insert value length (2 byte little endian format, LSB first) */
+	*((__u16 *) (frame+n)) = cpu_to_le16(value_len); n += 2;
 
 	/* Insert value */
 	switch (type) {
-	case 1:
-		memcpy( frame+n, value_char, len_value); n+=len_value;
-		break;
-	case 2:
+	case IRLAN_BYTE:
 		frame[n++] = value_byte;
 		break;
-	case 3:
-		frame[n++] = value_short & 0xff;
-		frame[n++] = (value_short >> 8) & 0xff;
+	case IRLAN_SHORT:
+		*((__u16 *) (frame+n)) = cpu_to_le16(value_short); n += 2;
+		break;
+	case IRLAN_ARRAY:
+		memcpy(frame+n, value_array, value_len); n+=value_len;
 		break;
 	default:
 		break;
 	}
-	ASSERT( n == (len_param+len_value+3), return 0;);
+	ASSERT(n == (param_len+value_len+3), return 0;);
 
-	return len_param+len_value+3;
+	return param_len+value_len+3;
 }
 
 /*
  * Function irlan_get_response_param (buf, param, value)
  *
  *    Extracts a single parameter name/value pair from buffer and updates
- *    the buffer pointer to point to the next name/value pair.
- * 
+ *    the buffer pointer to point to the next name/value pair. 
  */
-int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len)
+int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len)
 {
 	__u8 name_len;
 	__u16 val_len;
 	int n=0;
-
-	DEBUG( 4, "irlan_get_response_param()\n");
 	
-	/* get length of parameter name ( 1 byte) */
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	/* get length of parameter name (1 byte) */
 	name_len = buf[n++];
 	
 	if (name_len > 254) {
-		DEBUG( 0, __FUNCTION__ "(), name_len > 254\n");
-		return -1;
+		DEBUG(2, __FUNCTION__ "(), name_len > 254\n");
+		return -RSP_INVALID_COMMAND_FORMAT;
 	}
 	
 	/* get parameter name */
-	memcpy( name, buf+n, name_len);
+	memcpy(name, buf+n, name_len);
 	name[ name_len] = '\0';
 	n+=name_len;
 	
 	/*  
-	 *  Get length of parameter value ( 2 bytes in little endian 
+	 *  Get length of parameter value (2 bytes in little endian 
 	 *  format) 
 	 */
-	val_len = buf[n++] & 0xff;
-	val_len |= buf[n++] << 8;
+	val_len = le16_to_cpup(buf+n); n+=2;
 	
 	if (val_len > 1016) {
-		DEBUG( 0, __FUNCTION__ "(), parameter length to long\n");
-		return -1;
+		DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
+		return -RSP_INVALID_COMMAND_FORMAT;
 	}
-	
 	*len = val_len;
 
 	/* get parameter value */
-	memcpy( value, buf+n, val_len);
+	memcpy(value, buf+n, val_len);
 	value[ val_len] = '\0';
 	n+=val_len;
 	
-	DEBUG( 4, "Parameter: %s ", name); 
-	DEBUG( 4, "Value: %s\n", value); 
+	DEBUG(4, "Parameter: %s ", name); 
+	DEBUG(4, "Value: %s\n", value); 
 
 	return n;
 }
@@ -774,37 +1162,55 @@
  *
  *    Give some info to the /proc file system
  */
-static int irlan_proc_read( char *buf, char **start, off_t offset, 
-			    int len, int unused)
+static int irlan_proc_read(char *buf, char **start, off_t offset, int len, 
+			   int unused)
 {
  	struct irlan_cb *self;
-	
-	ASSERT( irlan != NULL, return 0;);
+	unsigned long flags;
+     
+	save_flags(flags);
+	cli();
+
+	ASSERT(irlan != NULL, return 0;);
 	
 	len = 0;
 	
-	len += sprintf( buf+len, "IrLAN\n");
-
-	self = ( struct irlan_cb *) hashbin_get_first( irlan);
-	while ( self != NULL) {
-		ASSERT( self->magic == IRLAN_MAGIC, return len;);
-
-		len += sprintf( buf+len, "ifname: %s, ",
-				self->ifname);
-		/* len += sprintf( buf+len, "state: %s, ", */
-/* 				irlan_client_state[ self->state]); */
-		len += sprintf( buf+len, "saddr: %#08x\n",
-				self->saddr);
-		len += sprintf( buf+len, "daddr: %#08x\n",
-				self->daddr);
-		len += sprintf( buf+len, "tbusy: %s\n", self->dev.tbusy ? 
-				"TRUE" : "FALSE");
+	len += sprintf(buf+len, "IrLAN instances:\n");
+	
+	self = (struct irlan_cb *) hashbin_get_first(irlan);
+	while (self != NULL) {
+		ASSERT(self->magic == IRLAN_MAGIC, return len;);
 		
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "ifname: %s,\n",
+			       self->ifname);
+		len += sprintf(buf+len, "client state: %s, ",
+			       irlan_state[ self->client.state]);
+		len += sprintf(buf+len, "provider state: %s,\n",
+			       irlan_state[ self->provider.state]);
+		len += sprintf(buf+len, "saddr: %#08x, ",
+			       self->saddr);
+		len += sprintf(buf+len, "daddr: %#08x\n",
+			       self->daddr);
+		len += sprintf(buf+len, "version: %d.%d,\n",
+			       self->version[1], self->version[0]);
+		len += sprintf(buf+len, "access type: %s\n", 
+			       irlan_access[ self->access_type]);
+		len += sprintf(buf+len, "media: %s\n", 
+			       irlan_media[ self->media]);
+
+		len += sprintf(buf+len, "local filter:\n");
+		len += sprintf(buf+len, "remote filter: ");
+		len += irlan_print_filter(self->client.filter_type, buf+len);
+
+		len += sprintf(buf+len, "tx busy: %s\n", self->dev.tbusy ? 
+			       "TRUE" : "FALSE");
 
-		self = ( struct irlan_cb *) hashbin_get_next( irlan);
-		DEBUG( 4, "self=%p\n", self);
+		len += sprintf(buf+len, "\n");
+
+		self = (struct irlan_cb *) hashbin_get_next(irlan);
  	} 
+	restore_flags(flags);
+
 	return len;
 }
 #endif
@@ -815,41 +1221,41 @@
  *    Print return code of request to peer IrLAN layer.
  *
  */
-void print_ret_code( __u8 code) 
+void print_ret_code(__u8 code) 
 {
-	switch( code) {
+	switch(code) {
 	case 0:
-		printk( KERN_INFO "Success\n");
+		printk(KERN_INFO "Success\n");
 		break;
 	case 1:
-		printk( KERN_WARNING "Insufficient resources\n");
+		printk(KERN_WARNING "Insufficient resources\n");
 		break;
 	case 2:
-		printk( KERN_WARNING "Invalid command format\n");
+		printk(KERN_WARNING "Invalid command format\n");
 		break;
 	case 3:
-		printk( KERN_WARNING "Command not supported\n");
+		printk(KERN_WARNING "Command not supported\n");
 		break;
 	case 4:
-		printk( KERN_WARNING "Parameter not supported\n");
+		printk(KERN_WARNING "Parameter not supported\n");
 		break;
 	case 5:
-		printk( KERN_WARNING "Value not supported\n");
+		printk(KERN_WARNING "Value not supported\n");
 		break;
 	case 6:
-		printk( KERN_WARNING "Not open\n");
+		printk(KERN_WARNING "Not open\n");
 		break;
 	case 7:
-		printk( KERN_WARNING "Authentication required\n");
+		printk(KERN_WARNING "Authentication required\n");
 		break;
 	case 8:
-		printk( KERN_WARNING "Invalid password\n");
+		printk(KERN_WARNING "Invalid password\n");
 		break;
 	case 9:
-		printk( KERN_WARNING "Protocol error\n");
+		printk(KERN_WARNING "Protocol error\n");
 		break;
 	case 255:
-		printk( KERN_WARNING "Asynchronous status\n");
+		printk(KERN_WARNING "Asynchronous status\n");
 		break;
 	}
 }
@@ -859,6 +1265,10 @@
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
 
+MODULE_PARM(eth, "i");
+MODULE_PARM(access, "i");
+MODULE_PARM(timeout, "i");
+
 /*
  * Function init_module (void)
  *
@@ -867,8 +1277,6 @@
  */
 int init_module(void) 
 {
-	DEBUG( 4, __FUNCTION__ "(), irlan.c\n");
-
 	irlan_init();
 
 	return 0;
@@ -882,15 +1290,9 @@
  */
 void cleanup_module(void) 
 {
-	DEBUG( 4, "--> irlan, cleanup_module\n");
-	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
 	/* Free some memory */
  	irlan_cleanup();
-
-	DEBUG( 4, "irlan, cleanup_module -->\n");
 }
 
 #endif /* MODULE */
 
-
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_eth.c linux-2.2.3-pre3/net/irda/irlan/irlan_eth.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_eth.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_eth.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Wed Dec  9 11:14:53 1998
+ * Modified at:   Wed Feb  3 19:58:28 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
@@ -35,158 +35,50 @@
 #include <net/irda/irlan_eth.h>
 
 /*
- * Function irlan_eth_init (dev)
- *
- *    The network device initialization function. Called only once.
- *
- */
-int irlan_eth_init( struct device *dev)
-{
-	struct irlan_cb *self;
-
-	DEBUG( 4, __FUNCTION__"()\n");
-
-	ASSERT( dev != NULL, return -1;);
-       
-	self = (struct irlan_cb *) dev->priv;
-
-/*  	dev->open               = irlan_eth_open;  */
-/* 	dev->stop	        = irlan_eth_close; */
-
-	dev->hard_start_xmit    = irlan_eth_tx; 
-	dev->get_stats	        = irlan_eth_get_stats;
-	dev->set_multicast_list = irlan_eth_set_multicast_list;
-
-	dev->tbusy = 1;
-	
-	ether_setup( dev);
-	
-	dev->tx_queue_len = TTP_MAX_QUEUE;
-
-	return 0;
-}
-
-/*
- * Function irlan_eth_open (dev)
- *
- *    Start the IrLAN ether network device, this function will be called by
- *    "ifconfig irlan0 up".
- *
- */
-int irlan_eth_open( struct device *dev)
-{
-	/* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	/* MOD_INC_USE_COUNT; */
-	
-	return 0;
-}
-
-/*
- * Function irlan_eth_close (dev)
- *
- *    Stop the Client ether network device, his function will be called by
- *    ifconfig down.
- */
-int irlan_eth_close(struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( dev != NULL, return -1;);
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	/* MOD_DEC_USE_COUNT; */
-	
-	return 0;
-}
-
-/*
  * Function irlan_eth_tx (skb)
  *
  *    Transmits ethernet frames over IrDA link.
  *
  */
-int irlan_eth_tx( struct sk_buff *skb, struct device *dev)
+int irlan_eth_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct irlan_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
 	self = (struct irlan_cb *) dev->priv;
 
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRLAN_MAGIC, return 0;);
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRLAN_MAGIC, return 0;);
 
-	if ( dev->tbusy) {
+	/* Lock transmit buffer */
+	if (irda_lock((void *) &dev->tbusy) == FALSE) {
 		/*
 		 * 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; 
-		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
 		
-		if ( tickssofar < 5) 
+		if (tickssofar < 5) 
  			return -EBUSY;
 		
  		dev->tbusy = 0;
  		dev->trans_start = jiffies;
 	}
-	/*
-	 * If some higher layer thinks we've missed an tx-done interrupt
-	 * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
-	 * itself.
-	 */
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), skb==NULL\n");
-
-		return 0;
-	}
-	/*
-	 *  Check that we are connected
-         */
-	if ( !self->connected) {
-		DEBUG( 4, __FUNCTION__ "(), Not connected, dropping frame!\n");
-
-		dev_kfree_skb( skb);
-                ++self->stats.tx_dropped;
-		
-                return 0;
-	}
 	
-	/*
-	 * Block a timer-based transmit from overlapping. This could better be
-	 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-	 */
-	if ( test_and_set_bit(0, (void*) &dev->tbusy) != 0) {
- 		printk( KERN_WARNING "%s: Transmitter access conflict.\n", 
-			dev->name);
-		return 0;
-	}	
-	DEBUG( 4, "Room left at head: %d\n", skb_headroom(skb));
-	DEBUG( 4, "Room left at tail: %d\n", skb_tailroom(skb));
-	DEBUG( 4, "Required room: %d\n", IRLAN_MAX_HEADER);
+	DEBUG(4, "Room left at head: %d\n", skb_headroom(skb));
+	DEBUG(4, "Room left at tail: %d\n", skb_tailroom(skb));
+	DEBUG(4, "Required room: %d\n", IRLAN_MAX_HEADER);
 	
-	/* Skb headroom large enough to contain IR-headers? */
-	if (( skb_headroom( skb) < IRLAN_MAX_HEADER) || ( skb_shared( skb))) {
+	/* skb headroom large enough to contain IR-headers? */
+	if ((skb_headroom(skb) < IRLAN_MAX_HEADER) || (skb_shared(skb))) {
 		struct sk_buff *new_skb = 
 			skb_realloc_headroom(skb, IRLAN_MAX_HEADER);
-		ASSERT( new_skb != NULL, return 0;);
-		ASSERT( skb_headroom( new_skb) >= IRLAN_MAX_HEADER, return 0;);
+		ASSERT(new_skb != NULL, return 0;);
+		ASSERT(skb_headroom(new_skb) >= IRLAN_MAX_HEADER, return 0;);
 
 		/*  Free original skb, and use the new one */
-		dev_kfree_skb( skb);
+		dev_kfree_skb(skb);
 		skb = new_skb;
 	} 
 
@@ -198,14 +90,14 @@
 	 *  Now queue the packet in the transport layer
 	 *  FIXME: clean up the code below! DB
 	 */
-	if ( self->use_udata) {
-		irttp_udata_request( self->tsap_data, skb);
+	if (self->use_udata) {
+		irttp_udata_request(self->tsap_data, skb);
 		dev->tbusy = 0;
 	
 		return 0;
 	}
 
-	if ( irttp_data_request( self->tsap_data, skb) == -1) {
+	if (irttp_data_request(self->tsap_data, skb) == -1) {
 		/*  
 		 *  IrTTPs tx queue is full, so we just have to drop the
 		 *  frame! You might think that we should just return -1
@@ -215,53 +107,51 @@
 		 *  really confuse do_dev_queue_xmit() in dev.c! I have
 		 *  tried :-) DB
 		 */
-		DEBUG( 4, __FUNCTION__ "(), Dropping frame\n");
-		dev_kfree_skb( skb);
+		dev_kfree_skb(skb);
 		++self->stats.tx_dropped;
 		
 		return 0;
 	}
-	dev->tbusy = 0;
+	dev->tbusy = 0; /* Finished! */
 	
 	return 0;
 }
 
 /*
- * Function irlan_eth_rx (handle, skb)
+ * Function irlan_eth_receive (handle, skb)
  *
  *    This function gets the data that is received on the data channel
  *
  */
-void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb)
+void irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
 {
 	struct irlan_cb *self;
 
-	self = ( struct irlan_cb *) instance;
+	self = (struct irlan_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	if (skb == NULL) {
 		++self->stats.rx_dropped; 
 		return;
 	}
-	IS_SKB( skb, return;);
-	ASSERT( skb->len > 1, return;);
+	ASSERT(skb->len > 1, return;);
 		
-	DEBUG( 4, "Got some ether data: length=%d\n", (int)skb->len); 
-	
 	/* 
 	 * Adopt this frame! Important to set all these fields since they 
 	 * might have been previously set by the low level IrDA network
 	 * device driver 
 	 */
 	skb->dev = &self->dev;
-	skb->protocol=eth_type_trans( skb, skb->dev); /* Remove eth header */
+	skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */
 	
-	netif_rx( skb);   /* Eat it! */
+	netif_rx(skb);   /* Eat it! */
 	
 	self->stats.rx_packets++;
 	self->stats.rx_bytes += skb->len; 
+
+/* 	net_bh(); */
 }
 
 /*
@@ -270,25 +160,25 @@
  *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by 
  *    controlling the dev->tbusy variable.
  */
-void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow)
+void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 {
 	struct irlan_cb *self;
 	struct device *dev;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct irlan_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
 	dev = &self->dev;
 
-	ASSERT( dev != NULL, return;);
+	ASSERT(dev != NULL, return;);
 	
-	switch ( flow) {
+	switch (flow) {
 	case FLOW_STOP:
-		DEBUG( 4, "IrLAN, stopping Ethernet layer\n");
+		DEBUG(4, "IrLAN, stopping Ethernet layer\n");
 
 		dev->tbusy = 1;
 		break;
@@ -296,7 +186,7 @@
 		/* 
 		 *  Tell upper layers that its time to transmit frames again
 		 */
-		DEBUG( 4, "IrLAN, starting Ethernet layer\n");
+		DEBUG(4, "IrLAN, starting Ethernet layer\n");
 
 		dev->tbusy = 0;
 
@@ -304,10 +194,10 @@
 		 *  Ready to receive more frames, so schedule the network
 		 *  layer
 		 */
-		mark_bh( NET_BH);		
+		mark_bh(NET_BH);		
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 
@@ -317,13 +207,13 @@
  *    If we don't want to use ARP. Currently not used!!
  *
  */
-void irlan_eth_rebuild_header( void *buff, struct device *dev, 
-			       unsigned long dest, struct sk_buff *skb)
+void irlan_eth_rebuild_header(void *buff, struct device *dev, 
+			      unsigned long dest, struct sk_buff *skb)
 {
-	struct ethhdr *eth = ( struct ethhdr *) buff;
+	struct ethhdr *eth = (struct ethhdr *) buff;
 
-	memcpy( eth->h_source, dev->dev_addr, dev->addr_len);
-	memcpy( eth->h_dest, dev->dev_addr, dev->addr_len);
+	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+	memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
 
 	/* return 0; */
 }
@@ -335,47 +225,47 @@
  *
  */
 #define HW_MAX_ADDRS 4 /* Must query to get it! */
-void irlan_eth_set_multicast_list( struct device *dev) 
+void irlan_eth_set_multicast_list(struct device *dev) 
 {
  	struct irlan_cb *self;
 
  	self = dev->priv; 
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
- 	ASSERT( self != NULL, return;); 
- 	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	DEBUG(0, __FUNCTION__ "()\n");
+	return;
+ 	ASSERT(self != NULL, return;); 
+ 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	if (dev->flags&IFF_PROMISC) {
 		/* Enable promiscuous mode */
-		DEBUG( 0, "Promiscous mode not implemented\n");
+		DEBUG(0, "Promiscous mode not implemented\n");
 		/* outw(MULTICAST|PROMISC, ioaddr); */
 	}
-	else if ((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
+	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
 		/* Disable promiscuous mode, use normal mode. */
-		DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n");
+		DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
 		/* hardware_set_filter(NULL); */
 
-		irlan_set_multicast_filter( self, TRUE);
+		irlan_set_multicast_filter(self, TRUE);
 	}
 	else if (dev->mc_count) {
-		DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n");
+		DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
 		/* Walk the address list, and load the filter */
 		/* hardware_set_filter(dev->mc_list); */
 
-		irlan_set_multicast_filter( self, TRUE);
+		irlan_set_multicast_filter(self, TRUE);
 	}
 	else {
-		DEBUG( 4, __FUNCTION__ "(), Clearing multicast filter\n");
-		irlan_set_multicast_filter( self, FALSE);
+		DEBUG(4, __FUNCTION__ "(), Clearing multicast filter\n");
+		irlan_set_multicast_filter(self, FALSE);
 	}
 
-	if ( dev->flags & IFF_BROADCAST) {
-		DEBUG( 4, __FUNCTION__ "(), Setting broadcast filter\n");
-		irlan_set_broadcast_filter( self, TRUE);
+	if (dev->flags & IFF_BROADCAST) {
+		DEBUG(4, __FUNCTION__ "(), Setting broadcast filter\n");
+		irlan_set_broadcast_filter(self, TRUE);
 	} else {
-		DEBUG( 4, __FUNCTION__ "(), Clearing broadcast filter\n");
-		irlan_set_broadcast_filter( self, FALSE);
+		DEBUG(4, __FUNCTION__ "(), Clearing broadcast filter\n");
+		irlan_set_broadcast_filter(self, FALSE);
 	}
 }
 
@@ -385,12 +275,12 @@
  *    Get the current statistics for this device
  *
  */
-struct enet_statistics *irlan_eth_get_stats( struct device *dev) 
+struct enet_statistics *irlan_eth_get_stats(struct device *dev) 
 {
 	struct irlan_cb *self = (struct irlan_cb *) dev->priv;
 
-	ASSERT( self != NULL, return NULL;);
-	ASSERT( self->magic == IRLAN_MAGIC, return NULL;);
+	ASSERT(self != NULL, return NULL;);
+	ASSERT(self->magic == IRLAN_MAGIC, return NULL;);
 
 	return &self->stats;
 }
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_event.c linux-2.2.3-pre3/net/irda/irlan/irlan_event.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_event.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_event.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Oct 20 09:10:16 1998
- * Modified at:   Sat Dec  5 14:52:22 1998
+ * Modified at:   Wed Feb  3 21:42:27 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -38,11 +38,23 @@
 	"IRLAN_SYNC",
 };
 
-void irlan_next_state( struct irlan_cb *self, 
-		       IRLAN_STATE state) 
+void irlan_next_client_state( struct irlan_cb *self, IRLAN_STATE state) 
 {
+	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLAN_MAGIC, return;);
 
-	self->state = state;
+	self->client.state = state;
 }
+
+void irlan_next_provider_state( struct irlan_cb *self, IRLAN_STATE state) 
+{
+	DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+	self->provider.state = state;
+}
+
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_filter.c linux-2.2.3-pre3/net/irda/irlan/irlan_filter.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_filter.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_filter.c	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,235 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_filter.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Jan 29 11:16:38 1999
+ * Modified at:   Sun Feb  7 23:48:07 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 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.
+ *     
+ ********************************************************************/
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irlan_common.h>
+
+/*
+ * Function handle_filter_request (self, skb)
+ *
+ *    Handle filter request from client peer device
+ *
+ */
+void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	    (self->provider.filter_operation == DYNAMIC))
+	{
+		DEBUG(0, "Giving peer a dynamic Ethernet address\n");
+
+		self->provider.mac_address[0] = 0x40;
+		self->provider.mac_address[1] = 0x00;
+		self->provider.mac_address[2] = 0x00;
+		self->provider.mac_address[3] = 0x00;
+		
+		/* Use arbitration value to generate MAC address */
+		if (self->access_type == ACCESS_PEER) {
+			self->provider.mac_address[4] = 
+				self->provider.send_arb_val & 0xff;
+			self->provider.mac_address[5] = 
+				(self->provider.send_arb_val >> 8) & 0xff;;
+		} else {
+			/* Just generate something for now */
+			self->provider.mac_address[4] = jiffies & 0xff;
+			self->provider.mac_address[5] = (jiffies >> 8) & 0xff;
+		}
+
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x03;
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
+		irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001);
+		irlan_insert_array_param(skb, "FILTER_ENTRY", self->provider.mac_address, 6);
+		return;
+	}
+	
+	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	    (self->provider.filter_mode == FILTER))
+	{
+		DEBUG(0, "Directed filter on\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+	    (self->provider.filter_mode == NONE))
+	{
+		DEBUG(0, "Directed filter off\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+
+	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+	    (self->provider.filter_mode == FILTER))
+	{
+		DEBUG(0, "Broadcast filter on\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+	    (self->provider.filter_mode == NONE))
+	{
+		DEBUG(0, "Broadcast filter off\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	    (self->provider.filter_mode == FILTER))
+	{
+		DEBUG(0, "Multicast filter on\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	    (self->provider.filter_mode == NONE))
+	{
+		DEBUG(0, "Multicast filter off\n");
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x00;
+		return;
+	}
+	if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+	    (self->provider.filter_operation == GET))
+	{
+		DEBUG(0, "Multicast filter get\n");
+		skb->data[0] = 0x00; /* Success? */
+		skb->data[1] = 0x02;
+		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
+		irlan_insert_short_param(skb, "MAX_ENTRY", 16);
+		return;
+	}
+	skb->data[0] = 0x00; /* Command not supported */
+	skb->data[1] = 0x00;
+
+	DEBUG(0, "Not implemented!\n");
+}
+
+/*
+ * Function check_request_param (self, param, value)
+ *
+ *    Check parameters in request from peer device
+ *
+ */
+static void irlan_check_command_param(struct irlan_cb *self, char *param, 
+				      char *value)
+{
+	__u8 *bytes;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	bytes = value;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	DEBUG(4, "%s, %s\n", param, value);
+
+	/*
+	 *  This is experimental!! DB.
+	 */
+	 if (strcmp(param, "MODE") == 0) {
+		DEBUG(0, __FUNCTION__ "()\n");
+		self->use_udata = TRUE;
+		return;
+	}
+
+	/*
+	 *  FILTER_TYPE
+	 */
+	if (strcmp(param, "FILTER_TYPE") == 0) {
+		if (strcmp(value, "DIRECTED") == 0) {
+			self->provider.filter_type = IRLAN_DIRECTED;
+			return;
+		}
+		if (strcmp(value, "MULTICAST") == 0) {
+			self->provider.filter_type = IRLAN_MULTICAST;
+			return;
+		}
+		if (strcmp(value, "BROADCAST") == 0) {
+			self->provider.filter_type = IRLAN_BROADCAST;
+			return;
+		}
+	}
+	/*
+	 *  FILTER_MODE
+	 */
+	if (strcmp(param, "FILTER_MODE") == 0) {
+		if (strcmp(value, "ALL") == 0) {
+			self->provider.filter_mode = ALL;
+			return;
+		}
+		if (strcmp(value, "FILTER") == 0) {
+			self->provider.filter_mode = FILTER;
+			return;
+		}
+		if (strcmp(value, "NONE") == 0) {
+			self->provider.filter_mode = FILTER;
+			return;
+		}
+	}
+	/*
+	 *  FILTER_OPERATION
+	 */
+	if (strcmp(param, "FILTER_OPERATION") == 0) {
+		if (strcmp(value, "DYNAMIC") == 0) {
+			self->provider.filter_operation = DYNAMIC;
+			return;
+		}
+		if (strcmp(value, "GET") == 0) {
+			self->provider.filter_operation = GET;
+			return;
+		}
+	}
+}
+
+int irlan_print_filter(int filter_type, char *buf)
+{
+	int len = 0;
+
+	if (filter_type & IRLAN_DIRECTED)
+		len += sprintf(buf+len, "%s", "DIRECTED ");
+	if (filter_type & IRLAN_FUNCTIONAL)
+		len += sprintf(buf+len, "%s", "FUNCTIONAL ");
+	if (filter_type & IRLAN_GROUP)
+		len += sprintf(buf+len, "%s", "GROUP ");
+	if (filter_type & IRLAN_MAC_FRAME)
+		len += sprintf(buf+len, "%s", "MAC_FRAME ");
+	if (filter_type & IRLAN_MULTICAST)
+		len += sprintf(buf+len, "%s", "MULTICAST ");
+	if (filter_type & IRLAN_BROADCAST)
+		len += sprintf(buf+len, "%s", "BROADCAST ");
+	if (filter_type & IRLAN_IPX_SOCKET)
+		len += sprintf(buf+len, "%s", "IPX_SOCKET");
+
+	len += sprintf(buf+len, "\n");
+
+	return len;
+}
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_provider.c linux-2.2.3-pre3/net/irda/irlan/irlan_provider.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_provider.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_provider.c	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,431 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider.c
+ * Version:       0.9
+ * Description:   IrDA LAN Access Protocol Implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Thu Feb  4 16:08:33 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
+ *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
+ *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/iriap.h>
+#include <net/irda/timer.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_event.h>
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_filter.h>
+#include <net/irda/irlan_client.h>
+
+/*
+ * Function irlan_provider_control_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the control channel
+ *
+ */
+void irlan_provider_data_indication(void *instance, void *sap, 
+				    struct sk_buff *skb) 
+{
+	struct irlan_cb *self;
+	__u8 code;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	ASSERT(skb != NULL, return;);
+
+	code = skb->data[0];
+	switch(code) {
+	case CMD_GET_PROVIDER_INFO:
+		DEBUG(4, "Got GET_PROVIDER_INFO command!\n");
+		irlan_do_provider_event(self, IRLAN_GET_INFO_CMD, skb); 
+		break;
+
+	case CMD_GET_MEDIA_CHAR:
+		DEBUG(4, "Got GET_MEDIA_CHAR command!\n");
+		irlan_do_provider_event(self, IRLAN_GET_MEDIA_CMD, skb); 
+		break;
+	case CMD_OPEN_DATA_CHANNEL:
+		DEBUG(4, "Got OPEN_DATA_CHANNEL command!\n");
+		irlan_do_provider_event(self, IRLAN_OPEN_DATA_CMD, skb); 
+		break;
+	case CMD_FILTER_OPERATION:
+		DEBUG(4, "Got FILTER_OPERATION command!\n");
+		irlan_do_provider_event(self, IRLAN_FILTER_CONFIG_CMD, skb);
+		break;
+	case CMD_RECONNECT_DATA_CHAN:
+		DEBUG(2, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n");
+		DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
+		break;
+	case CMD_CLOSE_DATA_CHAN:
+		DEBUG(2, "Got CLOSE_DATA_CHAN command!\n");
+		DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+		break;
+	}
+}
+
+/*
+ * Function irlan_provider_connect_indication (handle, skb, priv)
+ *
+ *    Got connection from peer IrLAN layer
+ *
+ */
+void irlan_provider_connect_indication(void *instance, void *sap, 
+				       struct qos_info *qos, int max_sdu_size,
+				       struct sk_buff *skb)
+{
+	struct irlan_cb *self, *entry, *new;
+	struct tsap_cb *tsap;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+	
+	ASSERT(tsap == self->provider.tsap_ctrl,return;);
+	ASSERT(self->provider.state == IRLAN_IDLE, return;);
+
+	/* Check if this provider is unused */
+	if (self->daddr == DEV_ADDR_ANY) {
+		/*
+		 * Rehash instance, now we have a client (daddr) to serve.
+		 */
+		entry = hashbin_remove(irlan, self->daddr, NULL);
+		ASSERT( entry == self, return;);
+		
+		self->daddr = irttp_get_daddr(tsap);
+		DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+	} else {
+		/*
+		 * If we already have the daddr set, this means that the
+		 * client must already have started (peer mode). We must
+		 * make sure that this connection attempt is from the same
+		 * device as the client is dealing with!  
+		 */
+		ASSERT(self->daddr == irttp_get_daddr(tsap), return;);
+	}
+	
+	/* Update saddr, since client may have moved to a new link */
+	self->saddr = irttp_get_saddr(tsap);
+	DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", self->saddr);
+	
+	/* Check if network device has been registered */
+	if (!self->netdev_registered)
+		irlan_register_netdev(self);
+	
+	irlan_do_provider_event(self, IRLAN_CONNECT_INDICATION, NULL);
+
+	/*  
+	 * If we are in peer mode, the client may not have got the discovery
+	 * indication it needs to make progress. If the client is still in 
+	 * IDLE state, we must kick it to 
+	 */
+	if ((self->access_type == ACCESS_PEER) && 
+	    (self->client.state == IRLAN_IDLE))
+		irlan_client_wakeup(self, self->saddr, self->daddr);
+
+	/* 
+	 * This provider is now in use, so start a new provider instance to
+         * serve other clients. This will also change the LM-IAS entry so that
+	 * other clients don't try to connect to us, now that we are busy.
+	 */
+	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+	self->client.start_new_provider = FALSE;
+}
+
+/*
+ * Function irlan_provider_connect_response (handle)
+ *
+ *    Accept incomming connection
+ *
+ */
+void irlan_provider_connect_response(struct irlan_cb *self,
+				     struct tsap_cb *tsap)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Just accept */
+	irttp_connect_response(tsap, IRLAN_MTU, NULL);
+
+	/* Check if network device has been registered */
+	if (!self->netdev_registered)
+		irlan_register_netdev(self);
+		
+}
+
+void irlan_provider_disconnect_indication(void *instance, void *sap, 
+					  LM_REASON reason, 
+					  struct sk_buff *userdata) 
+{
+	struct irlan_cb *self;
+	struct tsap_cb *tsap;
+
+	DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+	
+	self = (struct irlan_cb *) instance;
+	tsap = (struct tsap_cb *) sap;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);	
+	ASSERT(tsap != NULL, return;);
+	ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+	
+	ASSERT(tsap == self->provider.tsap_ctrl, return;);
+	
+	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+/*
+ * Function irlan_parse_open_data_cmd (self, skb)
+ *
+ *    
+ *
+ */
+int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb)
+{
+	int ret;
+	
+	ret = irlan_provider_extract_params(self, CMD_OPEN_DATA_CHANNEL, skb);
+
+	return ret;
+}
+
+/*
+ * Function extract_params (skb)
+ *
+ *    Extract all parameters from received buffer, then feed them to 
+ *    check_params for parsing
+ *
+ */
+int irlan_provider_extract_params(struct irlan_cb *self, int cmd,
+				  struct sk_buff *skb) 
+{
+	__u8 *frame;
+	__u8 *ptr;
+	int count;
+	__u8 name_len;
+	__u16 val_len;
+	int i;
+	char *name;
+        char *value;
+	int ret = RSP_SUCCESS;
+	
+	ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
+	
+	DEBUG(4, __FUNCTION__ "(), skb->len=%d\n", (int)skb->len);
+
+	ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
+	
+	if (!skb)
+		return -RSP_PROTOCOL_ERROR;
+
+	frame = skb->data;
+
+	name = kmalloc(255, GFP_ATOMIC);
+	if (!name)
+		return -RSP_INSUFFICIENT_RESOURCES;
+	value = kmalloc(1016, GFP_ATOMIC);
+	if (!value) {
+		kfree(name);
+		return -RSP_INSUFFICIENT_RESOURCES;
+	}
+
+	/* How many parameters? */
+	count = frame[1];
+
+	DEBUG(4, "Got %d parameters\n", count);
+	
+	ptr = frame+2;
+	
+	/* For all parameters */
+ 	for (i=0; i<count;i++) {
+		ret = irlan_get_param(ptr, name, value, &val_len);
+		if (ret < 0) {
+			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+			break;
+		}
+		ptr+=ret;
+		ret = RSP_SUCCESS;
+		irlan_check_command_param(self, name, value);
+	}
+	/* Cleanup */
+	kfree(name);
+	kfree(value);
+
+	return ret;
+}
+
+/*
+ * Function irlan_provider_send_reply (self, info)
+ *
+ *    Send reply to query to peer IrLAN layer
+ *
+ */
+void irlan_provider_send_reply(struct irlan_cb *self, int command, 
+			       int ret_code)
+{
+	struct sk_buff *skb;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	skb = dev_alloc_skb(128);
+	if (!skb)
+		return;
+
+	/* Reserve space for TTP, LMP, and LAP header */
+	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_put(skb, 2);
+       
+	switch (command) {
+	case CMD_GET_PROVIDER_INFO:
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x02; /* 2 parameters */
+		switch (self->media) {
+		case MEDIA_802_3:
+			irlan_insert_string_param(skb, "MEDIA", "802.3");
+			break;
+		case MEDIA_802_5:
+			irlan_insert_string_param(skb, "MEDIA", "802.5");
+			break;
+		default:
+			DEBUG(2, __FUNCTION__ "(), unknown media type!\n");
+			break;
+		}
+		irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
+		break;
+	case CMD_GET_MEDIA_CHAR:
+		skb->data[0] = 0x00; /* Success */
+		skb->data[1] = 0x05; /* 5 parameters */
+		irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+		irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
+		irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
+
+		switch(self->access_type) {
+		case ACCESS_DIRECT:
+			irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
+			break;
+		case ACCESS_PEER:
+			irlan_insert_string_param(skb, "ACCESS_TYPE", "PEER");
+			break;
+		case ACCESS_HOSTED:
+			irlan_insert_string_param(skb, "ACCESS_TYPE", "HOSTED");
+			break;
+		default:
+			DEBUG(2, __FUNCTION__ "(), Unknown access type\n");
+			break;
+		}
+		irlan_insert_short_param(skb, "MAX_FRAME", 0x05ee);
+		break;
+	case CMD_OPEN_DATA_CHANNEL:
+		skb->data[0] = 0x00; /* Success */
+		if (self->provider.send_arb_val) {
+			skb->data[1] = 0x03; /* 3 parameters */
+			irlan_insert_short_param(skb, "CON_ARB", 
+						 self->provider.send_arb_val);
+		} else
+			skb->data[1] = 0x02; /* 2 parameters */
+		irlan_insert_byte_param(skb, "DATA_CHAN", self->stsap_sel_data);
+		irlan_insert_array_param(skb, "RECONNECT_KEY", "LINUX RULES!",
+					 12);
+		break;
+	case CMD_FILTER_OPERATION:
+		handle_filter_request(self, skb);
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+		break;
+	}
+
+	irttp_data_request(self->provider.tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_provider_register(void)
+ *
+ *    Register provider support so we can accept incomming connections.
+ * 
+ */
+void irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
+{
+	struct notify_t notify;
+	struct tsap_cb *tsap;
+	
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+	/* Check if already open */
+	if (self->provider.tsap_ctrl)
+		return;
+	
+	/*
+	 *  First register well known control TSAP
+	 */
+	irda_notify_init(&notify);
+	notify.data_indication       = irlan_provider_data_indication;
+	notify.connect_indication    = irlan_provider_connect_indication;
+	notify.disconnect_indication = irlan_provider_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrLAN ctrl (p)", 16);
+
+	tsap = irttp_open_tsap(LSAP_ANY, 1, &notify);
+	if (!tsap) {
+		DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+		return;
+	}
+	self->provider.tsap_ctrl = tsap;
+
+	/* Register with LM-IAS */
+	irlan_ias_register(self,tsap->stsap_sel);
+}
+
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_provider_event.c linux-2.2.3-pre3/net/irda/irlan/irlan_provider_event.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_provider_event.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_provider_event.c	2003-08-15 15:05:26.000000000 -0700
@@ -0,0 +1,240 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider_event.c
+ * Version:       0.9
+ * Description:   IrLAN provider state machine)
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb  3 21:43:06 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ ********************************************************************/
+
+#include <net/irda/irda.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_event.h>
+
+static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb);
+
+static int (*state[])(struct irlan_cb *self, IRLAN_EVENT event, 
+		      struct sk_buff *skb) = 
+{ 
+	irlan_provider_state_idle,
+	NULL, /* Query */
+	NULL, /* Info */
+	irlan_provider_state_info,
+	NULL, /* Media */
+	irlan_provider_state_open,
+	NULL, /* Wait */
+	NULL, /* Arb */
+	irlan_provider_state_data,
+	NULL, /* Close */
+	NULL, /* Sync */
+};
+
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event, 
+			     struct sk_buff *skb) 
+{
+	ASSERT(*state[ self->provider.state] != NULL, return;);
+
+	(*state[self->provider.state]) (self, event, skb);
+}
+
+/*
+ * Function irlan_provider_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+				     struct sk_buff *skb)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	
+	switch(event) {
+	case IRLAN_CONNECT_INDICATION:
+	     irlan_provider_connect_response( self, self->provider.tsap_ctrl);
+	     irlan_next_provider_state( self, IRLAN_INFO);
+	     break;
+	default:
+		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_provider_state_info (self, event, skb, info)
+ *
+ *    INFO, We have issued a GetInfo command and is awaiting a reply.
+ */
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb) 
+{
+	int ret;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_GET_INFO_CMD:
+		/* Be sure to use 802.3 in case of peer mode */
+		if (self->access_type == ACCESS_PEER)
+			self->media = MEDIA_802_3;
+
+		irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO, 
+					  RSP_SUCCESS);
+		/* Keep state */
+		break;
+	case IRLAN_GET_MEDIA_CMD: 
+		irlan_provider_send_reply(self, CMD_GET_MEDIA_CHAR, 
+					  RSP_SUCCESS);
+		/* Keep state */
+		break;		
+	case IRLAN_OPEN_DATA_CMD:
+		ret = irlan_parse_open_data_cmd(self, skb);
+		if (self->access_type == ACCESS_PEER) {
+			/* FIXME: make use of random functions! */
+			self->provider.send_arb_val = (jiffies & 0xffff);
+		}
+		irlan_provider_send_reply(self, CMD_OPEN_DATA_CHANNEL, ret);
+
+		if (ret == RSP_SUCCESS) {
+			irlan_next_provider_state(self, IRLAN_OPEN);
+
+			/* Signal client that we are now open */
+			irlan_do_client_event(self, IRLAN_PROVIDER_SIGNAL, NULL);
+		}
+		break;
+	case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_provider_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+/*
+ * Function irlan_provider_state_open (self, event, skb, info)
+ *
+ *    OPEN, The client has issued a OpenData command and is awaiting a
+ *    reply
+ *
+ */
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+
+	switch(event) {
+	case IRLAN_FILTER_CONFIG_CMD:
+		irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb);
+		irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+					  RSP_SUCCESS);
+		/* Keep state */
+		break;
+	case IRLAN_DATA_CONNECT_INDICATION: 
+		irlan_next_provider_state(self, IRLAN_DATA);
+		irlan_provider_connect_response(self, self->tsap_data);
+		break;
+	case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		irlan_next_provider_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function irlan_provider_state_data (self, event, skb, info)
+ *
+ *    DATA, The data channel is connected, allowing data transfers between
+ *    the local and remote machines.
+ *
+ */
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+				     struct sk_buff *skb) 
+{
+	struct irmanager_event mgr_event;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+
+	switch(event) {
+	case IRLAN_FILTER_CONFIG_CMD:
+		irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb);
+		irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+					  RSP_SUCCESS);
+		break;
+	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
+	case IRLAN_LAP_DISCONNECT:
+		mgr_event.event = EVENT_IRLAN_STOP;
+		sprintf(mgr_event.devname, "%s", self->ifname);
+		irmanager_notify(&mgr_event);
+
+		irlan_next_provider_state(self, IRLAN_IDLE);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+	if (skb)
+		dev_kfree_skb(skb);
+	
+	return 0;
+}
+
+
+
+
+
+
+
+
+
+
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_srv.c linux-2.2.3-pre3/net/irda/irlan/irlan_srv.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_srv.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_srv.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,915 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_srv.c
- * Version:       0.1
- * Description:   IrDA LAN Access Protocol Implementation
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Dec 14 19:10:49 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
- *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
- *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- ********************************************************************/
-
-#include <linux/module.h> 
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-
-#include <net/irda/irda.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-#include <net/irda/timer.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_eth.h>
-#include <net/irda/irlan_event.h>
-#include <net/irda/irlan_srv.h>
-
-/*
- *  Private functions
- */
-static void __irlan_server_close( struct irlan_cb *self);
-static int irlan_server_dev_init( struct device *dev);
-static int irlan_server_dev_open(struct device *dev);
-static int irlan_server_dev_close(struct device *dev);
-static void irlan_check_param( struct irlan_cb *self, char *param, char *value);
-
-/*
- * Function irlan_server_init (dev)
- *
- *   Allocates the master array. Called by modprobe().
- */
-__initfunc(int irlan_server_init( void))
-{
-	DEBUG( 4, "--> irlan_server_init\n");
-
-	/* Register with IrLMP as a service */
-	irlmp_register_layer( S_LAN, SERVER, FALSE, NULL);
-	
- 	irlan_server_register();
-		
-	DEBUG( 4, "irlan_server_init -->\n");
-		
-	return 0;
-}
-
-/*
- * Function irlan_server_cleanup (void)
- *
- *    Removes all instances of the IrLAN network device driver, and the
- *    master array. Called by rmmod().
- */
-void irlan_server_cleanup(void) 
-{
-	DEBUG( 4, "--> irlan_server_cleanup\n");
-
-	irlmp_unregister_layer( S_LAN, SERVER);
-
-	/*
-	 *  Delete hashbin and close all irlan client instances in it
-	 */
-	/* hashbin_delete( irlan, (FREE_FUNC) __irlan_server_close); */
-	
-	DEBUG( 4, "irlan_server_cleanup -->\n");
-}
-
-/*
- * Function irlan_server_open (void)
- *
- *    This function allocates and opens a new instance of the IrLAN network
- *    device driver.
- */
-struct irlan_cb *irlan_server_open(void) 
-{
-	struct irlan_cb *self;
-	int result;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/* 
-	 *  Initialize the irlan_server structure. 
-	 */
-
-	self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
-	if ( self == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
-		return NULL;
-	}
-	memset( self, 0, sizeof(struct irlan_cb));
-
-	/*
-	 *  Initialize local device structure
-	 */
-	self->magic = IRLAN_MAGIC;
-
-	self->dev.name = self->ifname;
-	self->dev.init = irlan_server_dev_init;
-	self->dev.priv = (void *) self;
-	self->dev.next = NULL;
-
-	if (( result = register_netdev( &self->dev)) != 0) {
-		DEBUG( 0, __FUNCTION__ "(), register_netdev() failed!\n");
-		return NULL;
-	}
-
-	irlan_next_state( self, IRLAN_IDLE);
-
-	hashbin_insert( irlan , (QUEUE *) self, (int) self, NULL);
-	
-	return self;
-}
-
-/*
- * Function irlan_server_dev_init (dev)
- *
- *    The network device initialization function. Called only once.
- *
- */
-static int irlan_server_dev_init( struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-       
-	irlan_eth_init( dev);
-
-	/* Overrride some functions */
-	dev->open               = irlan_server_dev_open;
-	dev->stop	        = irlan_server_dev_close;
-	
-	/*  
-	 *  OK, since we are emulating an IrLAN sever we will have to give
-	 *  ourself an ethernet address!
-	 *  FIXME: this must be more dynamically
-	 */
-	dev->dev_addr[0] = 0x40;
-	dev->dev_addr[1] = 0x00;
-	dev->dev_addr[2] = 0x00;
-	dev->dev_addr[3] = 0x00;
-	dev->dev_addr[4] = 0x23;
-	dev->dev_addr[5] = 0x45;
-
-	return 0;
-}
-
-/*
- * Function irlan_server_dev_open (dev)
- *
- *    Start the Servers ether network device, this function will be called by
- *    "ifconfig server0 up".  
- */
-static int irlan_server_dev_open( struct device *dev)
-{
-	/* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-	
-	DEBUG( 4, "irlan_server_dev_open()\n");
-
-	ASSERT( dev != NULL, return -1;);
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	MOD_INC_USE_COUNT;
-	
-	return 0;
-}
-
-static void __irlan_server_close( struct irlan_cb *self)
-{
-	DEBUG( 4, "--> irlan_server_close()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	/* 
-	 *  Disconnect open TSAP connections
-	 */
-	if ( self->tsap_data) {
-		irttp_disconnect_request( self->tsap_data, NULL, P_HIGH);
-		
-		/* FIXME: this will close the tsap before the disconenct
-		 * frame has been sent 
-		 */
-		/* irttp_close_tsap( self->tsap_data); */
-	}
-	if ( self->tsap_ctrl) {
-		irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH);
-		
-		/* irttp_close_tsap( self->tsap_control); */
-	}
-
-	unregister_netdev( &self->dev);
-
-	self->magic = ~IRLAN_MAGIC;
-	
-	kfree( self);
-
-	DEBUG( 4, "irlan_server_close() -->\n");
-}
-
-/*
- * Function irlan_server_close (self)
- *
- *    This function closes and marks the IrLAN instance as not in use. 
- */
-void irlan_server_close( struct irlan_cb *self)
-{
-	struct irlan_cb *entry;
-
-	DEBUG( 4, "--> irlan_server_close()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	entry = hashbin_remove( irlan, (int) self, NULL);
-
-	ASSERT( entry == self, return;);
-	
-	__irlan_server_close( self);
-
-	DEBUG( 4, "irlan_server_close() -->\n");	
-}
-
-/*
- * Function irlan_server_dev_close (dev)
- *
- *    Stop the IrLAN ether network device, his function will be called by
- *    ifconfig down.
- */
-static int irlan_server_dev_close( struct device *dev)
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( dev != NULL, return -1;);
-	
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	MOD_DEC_USE_COUNT;
-	
-	return 0;
-}
-
-
-/*
- * Function irlan_server_disconnect_indication (handle, reason, priv)
- *
- *    Callback function for the IrTTP layer. Indicates a disconnection of
- *    the specified connection (handle)
- *
- */
-void irlan_server_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *skb) 
-{
-	struct irlan_info info;
-	struct irlan_cb *self;
-	struct tsap_cb *tsap;
-	
-	DEBUG( 4, __FUNCTION__ "(), Reason=%d\n", reason);
-	
-	self = ( struct irlan_cb *) instance;
-	tsap = ( struct tsap_cb *) sap;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);	
-
-	info.daddr = self->daddr;
-	
-	if ( tsap == self->tsap_data) {
-		DEBUG( 0, "IrLAN, data channel disconnected by peer!\n");
-		self->connected = FALSE;
-	} else if ( tsap == self->tsap_ctrl) {
-		DEBUG( 0, "IrLAN, control channel disconnected by peer!\n");
-	} else {
-		DEBUG( 0, "Error, disconnect on unknown handle!\n");
-	}
-	
-	/* Stop IP from transmitting more packets */
-	/* irlan_flow_indication( handle, FLOW_STOP, priv); */
-
-	irlan_do_server_event( self, IRLAN_LMP_DISCONNECT, NULL, NULL);
-}
-	
-/*
- * Function irlan_server_control_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the control channel
- *
- */
-void irlan_server_control_data_indication( void *instance, void *sap, 
-					   struct sk_buff *skb) 
-{
-	struct irlan_cb *self;
-	__u8 code;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irlan_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	ASSERT( skb != NULL, return;);
-
-	code = skb->data[0];
-	switch( code) {
-	case CMD_GET_PROVIDER_INFO:
-		DEBUG( 4, "Got GET_PROVIDER_INFO command!\n");
-		irlan_do_server_event( self, IRLAN_GET_INFO_CMD, skb, NULL); 
-		break;
-
-	case CMD_GET_MEDIA_CHAR:
-		DEBUG( 4, "Got GET_MEDIA_CHAR command!\n");
-		irlan_do_server_event( self, IRLAN_GET_MEDIA_CMD, skb, NULL); 
-		break;
-	case CMD_OPEN_DATA_CHANNEL:
-		DEBUG( 4, "Got OPEN_DATA_CHANNEL command!\n");
-		irlan_do_server_event( self, IRLAN_OPEN_DATA_CMD, skb, NULL); 
-		break;
-	case CMD_FILTER_OPERATION:
-		DEBUG( 4, "Got FILTER_OPERATION command!\n");
-		irlan_do_server_event( self, IRLAN_FILTER_CONFIG_CMD, skb, 
-				       NULL);
-		break;
-	case CMD_RECONNECT_DATA_CHAN:
-		DEBUG( 0, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n");
-		DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n");
-		break;
-	case CMD_CLOSE_DATA_CHAN:
-		DEBUG( 0, "Got CLOSE_DATA_CHAN command!\n");
-		DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n");
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown command!\n");
-		break;
-	}
-}
-
-/*
- * Function irlan_server_connect_indication (handle, skb, priv)
- *
- *    Got connection from peer IrLAN layer
- *
- */
-void irlan_server_connect_indication( void *instance, void *sap, 
-				      struct qos_info *qos, int max_sdu_size,
-				      struct sk_buff *skb)
-{
-	struct irlan_cb *self;
-	struct irlan_info info;
-	struct tsap_cb *tsap;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irlan_cb *) instance;
-	tsap = ( struct tsap_cb *) sap;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-	
-	info.tsap = tsap;
-	
-	if ( tsap == self->tsap_data)
-		irlan_do_server_event( self, IRLAN_DATA_CONNECT_INDICATION, 
-				       NULL, &info);
-	else
-		irlan_do_server_event( self, IRLAN_CONNECT_INDICATION, NULL, 
-				       &info);
-}
-
-/*
- * Function irlan_server_connect_response (handle)
- *
- *    Accept incomming connection
- *
- */
-void irlan_server_connect_response( struct irlan_cb *self, 
-				    struct tsap_cb *tsap)
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	/* FIXME: define this value */
-	irttp_connect_response( tsap, 1518, NULL);
-}
-
-/*
- * Function irlan_server_get_provider_info (self)
- *
- *    Send Get Provider Information command to peer IrLAN layer
- *
- */
-void irlan_server_get_provider_info( struct irlan_cb *self) 
-{
-	struct sk_buff *skb;
-	__u8 *frame;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlan_server_get_provider_info: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
-		return;
-	}
-
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
-	
-	frame = skb->data;
-	
- 	frame[0] = CMD_GET_PROVIDER_INFO;
-	frame[1] = 0x00;                 /* Zero parameters */
-	
-	irttp_data_request( self->tsap_ctrl, skb);
-}
-
-/*
- * Function irlan_parse_open_data_cmd (self, skb)
- *
- *    
- *
- */
-int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb)
-{
-	int ret = RSP_SUCCESS;
-	
-	irlan_server_extract_params( self, CMD_OPEN_DATA_CHANNEL, skb);
-
-	return ret;
-}
-
-/*
- * Function extract_params (skb)
- *
- *    Extract all parameters from received buffer, then feed them to 
- *    check_params for parsing
- *
- */
-int irlan_server_extract_params( struct irlan_cb *self, int cmd,
-				struct sk_buff *skb) 
-{
-	__u8 *frame;
-	__u8 *ptr;
-	int count;
-	__u8 name_len;
-	__u16 val_len;
-	int i;
-	
-	ASSERT( skb != NULL, return -RSP_PROTOCOL_ERROR;);
-	
-	DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int)skb->len);
-
-	ASSERT( self != NULL, return -RSP_PROTOCOL_ERROR;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
-	
-	if ( skb == NULL) {
-		DEBUG( 0, "extract_params: Got NULL skb!\n");
-		return -RSP_PROTOCOL_ERROR;
-	}
-	frame = skb->data;
-
-	/* How many parameters? */
-	count = frame[1];
-
-	DEBUG( 4, "Got %d parameters\n", count);
-	
-	ptr = frame+2;
-
-	/* For all parameters */
- 	for ( i=0; i<count;i++) {
-		/* get length of parameter name ( 1 byte) */
-		name_len = *ptr++;
-
-		if (name_len > 255) {
-			DEBUG( 0, "extract_params, name_len > 255\n");
-			return -RSP_PROTOCOL_ERROR;
-		}
-
-		/* get parameter name */
-		memcpy( self->name, ptr, name_len);
-		self->name[ name_len] = '\0';
-		ptr+=name_len;
-		
-		/*  
-		 *  Get length of parameter value ( 2 bytes in little endian 
-		 *  format) 
-		 */
-		val_len = *ptr++ & 0xff;	
-		val_len |= *ptr++ << 8;
-		
-		if (val_len > 1016) {
-			DEBUG( 0, 
-			       "extract_params, parameter length to long\n");
-			return -RSP_PROTOCOL_ERROR;
-		}
-		
-		/* get parameter value */
- 		memcpy( self->value, ptr, val_len);
- 		self->value[ val_len] = '\0';
- 		ptr+=val_len;
-		
- 		DEBUG( 4, "Parameter: %s ", self->name); 
- 		DEBUG( 4, "Value: %s\n", self->value); 
-		
-		irlan_check_param( self, self->name, self->value);
-	}
-	return RSP_SUCCESS;
-}
-
-/*
- * Function handle_filter_request (self, skb)
- *
- *    Handle filter request from client peer device
- *
- */
-void handle_filter_request( struct irlan_cb *self, struct sk_buff *skb)
-{
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	if (( self->t.server.filter_type == IR_DIRECTED) && 
-	    ( self->t.server.filter_operation == DYNAMIC))
-	{
-		DEBUG( 0, "Giving peer a dynamic Ethernet address\n");
-
-		self->t.server.mac_address[0] = 0x40;
-		self->t.server.mac_address[1] = 0x00;
-		self->t.server.mac_address[2] = 0x00;
-		self->t.server.mac_address[3] = 0x00;
-		self->t.server.mac_address[4] = 0x12;
-		self->t.server.mac_address[5] = 0x34;
-
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x03;
-		insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0);
-		insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 0x0001);
-		insert_array_param( skb, "FILTER_ENTRY", self->t.server.mac_address, 6);
-		return;
-	}
-	
-	if (( self->t.server.filter_type == IR_DIRECTED) && 
-	    ( self->t.server.filter_mode == FILTER))
-	{
-		DEBUG( 0, "Directed filter on\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_DIRECTED) && 
-	    ( self->t.server.filter_mode == NONE))
-	{
-		DEBUG( 0, "Directed filter off\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-
-	if (( self->t.server.filter_type == IR_BROADCAST) && 
-	    ( self->t.server.filter_mode == FILTER))
-	{
-		DEBUG( 0, "Broadcast filter on\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_BROADCAST) && 
-	    ( self->t.server.filter_mode == NONE))
-	{
-		DEBUG( 0, "Broadcast filter off\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_MULTICAST) && 
-	    ( self->t.server.filter_mode == FILTER))
-	{
-		DEBUG( 0, "Multicast filter on\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_MULTICAST) && 
-	    ( self->t.server.filter_mode == NONE))
-	{
-		DEBUG( 0, "Multicast filter off\n");
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x00;
-		return;
-	}
-	if (( self->t.server.filter_type == IR_MULTICAST) && 
-	    ( self->t.server.filter_operation == GET))
-	{
-		DEBUG( 0, "Multicast filter get\n");
-		skb->data[0] = 0x00; /* Success? */
-		skb->data[1] = 0x02;
-		insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0);
-		insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 16);
-		return;
-	}
-	skb->data[0] = 0x00; /* Command not supported */
-	skb->data[1] = 0x00;
-
-	DEBUG( 0, "Not implemented!\n");
-}
-
-/*
- * Function check_request_param (self, param, value)
- *
- *    Check parameters in request from peer device
- *
- */
-static void irlan_check_param( struct irlan_cb *self, char *param, char *value)
-{
-	__u8 *bytes;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	bytes = value;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	DEBUG( 4, "%s, %s\n", param, value);
-
-	/*
-	 *  This is experimental!! DB.
-	 */
-	 if ( strcmp( param, "MODE") == 0) {
-		DEBUG( 0, __FUNCTION__ "()\n");
-		self->use_udata = TRUE;
-		return;
-	}
-
-	/*
-	 *  FILTER_TYPE
-	 */
-	if ( strcmp( param, "FILTER_TYPE") == 0) {
-		if ( strcmp( value, "DIRECTED") == 0) {
-			self->t.server.filter_type = IR_DIRECTED;
-			return;
-		}
-		if ( strcmp( value, "MULTICAST") == 0) {
-			self->t.server.filter_type = IR_MULTICAST;
-			return;
-		}
-		if ( strcmp( value, "BROADCAST") == 0) {
-			self->t.server.filter_type = IR_BROADCAST;
-			return;
-		}
-	}
-	/*
-	 *  FILTER_MODE
-	 */
-	if ( strcmp( param, "FILTER_MODE") == 0) {
-		if ( strcmp( value, "ALL") == 0) {
-			self->t.server.filter_mode = ALL;
-			return;
-		}
-		if ( strcmp( value, "FILTER") == 0) {
-			self->t.server.filter_mode = FILTER;
-			return;
-		}
-		if ( strcmp( value, "NONE") == 0) {
-			self->t.server.filter_mode = FILTER;
-			return;
-		}
-	}
-	/*
-	 *  FILTER_OPERATION
-	 */
-	if ( strcmp( param, "FILTER_OPERATION") == 0) {
-		if ( strcmp( value, "DYNAMIC") == 0) {
-			self->t.server.filter_operation = DYNAMIC;
-			return;
-		}
-		if ( strcmp( value, "GET") == 0) {
-			self->t.server.filter_operation = GET;
-			return;
-		}
-	}
-}
-
-/*
- * Function irlan_server_send_reply (self, info)
- *
- *    Send reply to query to peer IrLAN layer
- *
- */
-void irlan_server_send_reply( struct irlan_cb *self, int command, int ret_code)
-{
-	struct sk_buff *skb;
-
-	DEBUG( 4, "irlan_server_send_reply()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-	skb =  dev_alloc_skb( 128);
-	if (skb == NULL) {
-		DEBUG( 0,"irlan_server_send_reply: "
-		       "Could not allocate an sk_buff of length %d\n", 128);
-		return;
-	}
-
-	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 2);
-       
-	switch ( command) {
-	case CMD_GET_PROVIDER_INFO:
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x02; /* 2 parameters */
-		insert_param( skb, "MEDIA", 1, "802.3", 0, 0);
-		insert_param( skb, "IRLAN_VER", 3, NULL, 0, 0x0101);
-		break;
-	case CMD_GET_MEDIA_CHAR:
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x05; /* 5 parameters */
-		insert_param( skb, "FILTER_TYPE", 1, "DIRECTED", 0, 0);
-		insert_param( skb, "FILTER_TYPE", 1, "BROADCAST", 0, 0);
-		insert_param( skb, "FILTER_TYPE", 1, "MULTICAST", 0, 0);
-		insert_param( skb, "ACCESS_TYPE", 1, "DIRECTED", 0, 0);
-		insert_param( skb, "MAX_FRAME", 3, NULL, 0, 0x05ee);
-		break;
-	case CMD_OPEN_DATA_CHANNEL:
-		skb->data[0] = 0x00; /* Success */
-		skb->data[1] = 0x02; /* 2 parameters */
-		insert_param( skb, "DATA_CHAN", 2, NULL, self->stsap_sel_data, 0);
-		insert_param( skb, "RECONNECT_KEY", 1, "LINUX RULES!", 0, 0);
-		break;
-	case CMD_FILTER_OPERATION:
-		handle_filter_request( self, skb);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown command!\n");
-		break;
-	}
-
-	irttp_data_request( self->tsap_ctrl, skb);
-}
-
-/*
- * Function irlan_server_register(void)
- *
- *    Register server support so we can accept incomming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-void irlan_server_register(void)
-{
-	struct notify_t notify;
-	struct irlan_cb *self;
-	struct ias_object *obj;
-	struct tsap_cb *tsap;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	/*
-	 *  Open irlan_server instance
-	 */
-	self = irlan_server_open();
-	if ( !self || self->magic != IRLAN_MAGIC) {
-		DEBUG( 0, __FUNCTION__"(), Unable to open server!\n");
-		return;
-	}
-	/*
-	 *  First register well known control TSAP
-	 */
-	irda_notify_init( &notify);
-	notify.data_indication       = irlan_server_control_data_indication;
-	notify.connect_indication    = irlan_server_connect_indication;
-	notify.disconnect_indication = irlan_server_disconnect_indication;
-	notify.instance = self;
-	strncpy( notify.name, "IrLAN srv. ctrl", 16);
-
-	/* FIXME: should not use a static value here! */
-	tsap = irttp_open_tsap( TSAP_IRLAN, 1, &notify);
-	if ( tsap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got no handle!!\n");
-		return;
-	}
-	self->tsap_ctrl = tsap;
-
-	/*
-	 *  Now register data TSAP
-	 */
-	irda_notify_init( &notify);
-	notify.data_indication       = irlan_eth_rx;
-	notify.udata_indication      = irlan_eth_rx;
-	notify.connect_indication    = irlan_server_connect_indication;
-	notify.disconnect_indication = irlan_server_disconnect_indication;
-	notify.instance = self;
-	strncpy( notify.name, "IrLAN srv. data", 16);
-
-	/*
-	 *  Register well known address with IrTTP
-	 */ 
-	tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
-	if ( tsap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Got no handle!\n");
-		return;
-	}
-	self->tsap_data = tsap;
-
-	/* 
-	 *  This is the data TSAP selector which we will pass to the client
-	 *  when the client ask for it.
-	 */
-	self->stsap_sel_data = tsap->stsap_sel;
-	ASSERT( self->stsap_sel_data > 0, return;);
-
-	DEBUG( 0, "irlan_server_register(), Using Source TSAP selector=%02x\n",
-	       self->stsap_sel_data);
-	
-	/* 
-	 *  Register with LM-IAS
-	 */
-	obj = irias_new_object( "IrLAN", IAS_IRLAN_ID);
-	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IRLAN);
-	irias_insert_object( obj);
-
-	obj = irias_new_object( "PnP", IAS_PNP_ID);
-	irias_add_string_attrib( obj, "Name", "Linux");
-	irias_add_string_attrib( obj, "DeviceID", "HWP19F0");
-	irias_add_integer_attrib( obj, "CompCnt", 2);
-	irias_add_string_attrib( obj, "Comp#01", "PNP8294");
-	irias_add_string_attrib( obj, "Comp#01", "PNP8389");
-	irias_add_string_attrib( obj, "Manufacturer", "Linux/IR Project");
-	irias_insert_object( obj);
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA LAN Server protocol"); 
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLAN module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-/* 	int result; */
-
-	DEBUG( 4, "--> IrLAN irlan_server: init_module\n");
-
-	irlan_server_init();
-
-	DEBUG( 4, "IrLAN irlan_server: init_module -->\n");	
-
-	return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLAN module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-	DEBUG( 4, "--> irlan_server, cleanup_module\n");
-	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-	/* Free some memory */
- 	irlan_server_cleanup();
-
-	DEBUG( 4, "irlan_server, cleanup_module -->\n");
-}
-
-#endif /* MODULE */
diff -urN linux-2.2.3-pre2/net/irda/irlan/irlan_srv_event.c linux-2.2.3-pre3/net/irda/irlan/irlan_srv_event.c
--- linux-2.2.3-pre2/net/irda/irlan/irlan_srv_event.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/irlan_srv_event.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,268 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_srv_event.c
- * Version:       0.1
- * Description:   IrLAN Server FSM (Finite State Machine)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Wed Dec  9 02:39:05 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- ********************************************************************/
-
-#include <net/irda/irda.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-
-#include <net/irda/irlan_srv.h>
-#include <net/irda/irlan_event.h>
-
-static int irlan_server_state_idle ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-static int irlan_server_state_info ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-static int irlan_server_state_open ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-static int irlan_server_state_data ( struct irlan_cb *self, 
-				     IRLAN_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlan_info *info);
-
-static int (*state[])( struct irlan_cb *self, IRLAN_EVENT event, 
-		       struct sk_buff *skb, struct irlan_info *info) = 
-{ 
-	irlan_server_state_idle,
-	NULL, /* Query */
-	NULL, /* Info */
-	irlan_server_state_info,
-	NULL, /* Media */
-	irlan_server_state_open,
-	NULL, /* Wait */
-	NULL, /* Arb */
-	irlan_server_state_data,
-	NULL, /* Close */
-	NULL, /* Sync */
-};
-
-void irlan_do_server_event( struct irlan_cb *self, 
-			    IRLAN_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlan_info *info) 
-{
-	(*state[ self->state]) ( self, event, skb, info);
-}
-
-/*
- * Function irlan_server_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlan_server_state_idle( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-	
-	switch( event) {
-	case IRLAN_CONNECT_INDICATION:
-	     ASSERT( info != NULL, return 0;);
-	     irlan_server_connect_response( self, info->tsap);
-	     irlan_next_state( self, IRLAN_INFO);
-	     break;
-	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	return 0;
-}
-
-/*
- * Function irlan_server_state_info (self, event, skb, info)
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlan_server_state_info( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	int ret;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_GET_INFO_CMD: 
-		irlan_server_send_reply( self, CMD_GET_PROVIDER_INFO, 
-					 RSP_SUCCESS);
-		/* Keep state */
-		break;
-
-	case IRLAN_GET_MEDIA_CMD: 
-		irlan_server_send_reply( self, CMD_GET_MEDIA_CHAR, 
-					 RSP_SUCCESS);
-		/* Keep state */
-		break;
-		
-	case IRLAN_OPEN_DATA_CMD:
-		ret = irlan_parse_open_data_cmd( self, skb);
-		irlan_server_send_reply( self, CMD_OPEN_DATA_CHANNEL, ret);
-
-		if ( ret == RSP_SUCCESS)
-			irlan_next_state( self, IRLAN_OPEN);
-		break;
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, "irlan_server_state_info, Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-/*
- * Function irlan_server_state_open (self, event, skb, info)
- *
- *    OPEN, The client has issued a OpenData command and is awaiting a
- *    reply
- *
- */
-static int irlan_server_state_open( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-
-	switch( event) {
-	case IRLAN_FILTER_CONFIG_CMD:
-		irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb);
-		irlan_server_send_reply( self, CMD_FILTER_OPERATION, 
-					 RSP_SUCCESS);
-		/* Keep state */
-		break;
-		
-	case IRLAN_DATA_CONNECT_INDICATION: 
-		DEBUG( 4, "DATA_CONNECT_INDICATION\n");
-		irlan_next_state( self, IRLAN_DATA);
-		irlan_server_connect_response( self, info->tsap);
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-		       event);
-		break;
-	}
-	
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	return 0;
-}
-
-/*
- * Function irlan_server_state_data (self, event, skb, info)
- *
- *    DATA, The data channel is connected, allowing data transfers between
- *    the local and remote machines.
- *
- */
-static int irlan_server_state_data( struct irlan_cb *self, 
-				    IRLAN_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlan_info *info) 
-{
-	struct irmanager_event mgr_event;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLAN_FILTER_CONFIG_CMD:
-		irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb);
-		irlan_server_send_reply( self, CMD_FILTER_OPERATION, 
-					 RSP_SUCCESS);
-
-		/* Make sure the code below only runs once */
-		if ( !self->connected) {
-			mgr_event.event = EVENT_IRLAN_START;
-			sprintf( mgr_event.devname, "%s", self->ifname);
-			irmanager_notify( &mgr_event);
-
-			self->connected = TRUE;
-		}
-		break;
-		
-	case IRLAN_LMP_DISCONNECT:
-	case IRLAN_LAP_DISCONNECT:
-		mgr_event.event = EVENT_IRLAN_STOP;
-		sprintf( mgr_event.devname, "%s", self->ifname);
-		irmanager_notify( &mgr_event);
-
-		irlan_next_state( self, IRLAN_IDLE);
-		break;
-	default:
-		DEBUG( 0, "irlan_server_state_data, Unknown event %d\n", 
-		       event);
-		break;
-	}
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-	
-	return 0;
-}
-
-
-
-
-
-
-
-
-
-
diff -urN linux-2.2.3-pre2/net/irda/irlan/Makefile linux-2.2.3-pre3/net/irda/irlan/Makefile
--- linux-2.2.3-pre2/net/irda/irlan/Makefile	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlan/Makefile	2003-08-15 15:05:26.000000000 -0700
@@ -9,44 +9,13 @@
 
 MOD_LIST_NAME := IRDA_MODULES
 O_TARGET := irlan.o
-O_OBJS	 := irlan_common.o irlan_eth.o irlan_event.o
+O_OBJS	 := irlan_common.o irlan_eth.o irlan_event.o irlan_client.o irlan_provider.o irlan_filter.o irlan_provider_event.o irlan_client_event.o
 M_OBJS   := $(O_TARGET)
 MI_OBJS  :=
 
 OX_OBJS  += 
 
-ifeq ($(CONFIG_IRLAN_CLIENT),y)
-O_OBJS += irlan_cli.o irlan_cli_event.o
-else
-  ifeq ($(CONFIG_IRLAN_CLIENT),m)
-#  MI_OBJS += irlan_cli.o irlan_cli_event.o
-  M_OBJS += irlan_client.o
-  endif
-endif
-
-ifeq ($(CONFIG_IRLAN_SERVER),y)
-O_OBJS += irlan_srv.o irlan_srv_event.o
-else
-  ifeq ($(CONFIG_IRLAN_SERVER),m)
-#  MI_OBJS += irlan_srv.o irlan_srv_event.o
-  M_OBJS += irlan_server.o
-  endif
-endif
-
-# Special rule to build the composite modules
-ifeq ($(CONFIG_IRLAN),m)
-irlan_client.o: irlan_cli.o irlan_cli_event.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlan_cli.o irlan_cli_event.o
-
-irlan_server.o: irlan_srv.o irlan_srv_event.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlan_srv.o irlan_srv_event.o
-endif
-
 include $(TOPDIR)/Rules.make
 
 tar:
 		tar -cvf /dev/f1 .
-
-
-
-
diff -urN linux-2.2.3-pre2/net/irda/irlap.c linux-2.2.3-pre3/net/irda/irlap.c
--- linux-2.2.3-pre2/net/irda/irlap.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlap.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap.c
- * Version:       0.8
+ * Version:       0.9
  * Description:   An IrDA LAP driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:19:27 1999
+ * Modified at:   Sat Feb 20 01:39:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -43,12 +43,23 @@
 #include <net/irda/irlap_comp.h>
 
 hashbin_t *irlap = NULL;
+int sysctl_slot_timeout = SLOT_TIMEOUT;
 
 static void __irlap_close( struct irlap_cb *self);
 
+static char *lap_reasons[] = {
+	"ERROR, NOT USED",
+	"LAP_DISC_INDICATION",
+	"LAP_NO_RESPONSE",
+	"LAP_RESET_INDICATION",
+	"LAP_FOUND_NONE",
+	"LAP_MEDIA_BUSY",
+	"LAP_PRIMARY_CONFLICT",
+	"ERROR, NOT USED",
+};
+
 #ifdef CONFIG_PROC_FS
-int irlap_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused);
+int irlap_proc_read( char *, char **, off_t, int, int);
 
 #endif /* CONFIG_PROC_FS */
 
@@ -138,8 +149,6 @@
 
 	irlmp_register_irlap( self, self->saddr, &self->notify);
 	
-	DEBUG( 4, "irlap_open -->\n");
-
 	return self;
 }
 
@@ -166,7 +175,7 @@
 	irlap_flush_all_queues( self);
        
 	self->irdev = NULL;
-	self->magic = ~LAP_MAGIC;
+	self->magic = 0;
 	
 	kfree( self);
 }
@@ -194,7 +203,7 @@
 	/* Be sure that we manage to remove ourself from the hash */
 	lap = hashbin_remove( irlap, self->saddr, NULL);
 	if ( !lap) {
-		DEBUG( 0, __FUNCTION__ "(), Didn't find myself!\n");
+		DEBUG( 1, __FUNCTION__ "(), Didn't find myself!\n");
 		return;
 	}
 	__irlap_close( lap);
@@ -206,17 +215,17 @@
  *    Another device is attempting to make a connection
  *
  */
-void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_init_qos_capabilities( self, NULL); /* No user QoS! */
+	irlap_init_qos_capabilities(self, NULL); /* No user QoS! */
 	
-	irlmp_link_connect_indication( self->notify.instance, &self->qos_tx, 
-				       skb);
+	irlmp_link_connect_indication(self->notify.instance, self->saddr, 
+				      self->daddr, &self->qos_tx, skb);
 }
 
 /*
@@ -247,21 +256,17 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 
  	self->daddr = daddr;
-
+	
 	/*
 	 *  If the service user specifies QoS values for this connection, 
 	 *  then use them
 	 */
 	irlap_init_qos_capabilities( self, qos_user);
 	
-	if ( self->state == LAP_NDM) {
+	if ( self->state == LAP_NDM)
 		irlap_do_event( self, CONNECT_REQUEST, NULL, NULL);
-	} else {
-		DEBUG( 0, __FUNCTION__ "() Wrong state!\n");
-		
-		irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
-	}
-	       
+	else
+		self->connect_pending = TRUE;
 }
 
 /*
@@ -302,12 +307,11 @@
 	if ( self->qos_tx.compression.value) {
 		skb = irlap_decompress_frame( self, skb);
 		if ( !skb) {
-			DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+			DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
 #endif
-
 	irlmp_link_data_indication( self->notify.instance, LAP_RELIABLE, skb);
 }
 
@@ -319,7 +323,7 @@
  */
 void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
 {
-	DEBUG( 0, __FUNCTION__ "()\n"); 
+	DEBUG( 1, __FUNCTION__ "()\n"); 
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -333,7 +337,7 @@
 		
 		skb = irlap_decompress_frame( self, skb);
 		if ( !skb) {
-			DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+			DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
@@ -356,14 +360,14 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 	ASSERT( skb != NULL, return;);
 
-	DEBUG( 4, "irlap_data_request: tx_list=%d\n", 
+	DEBUG( 4, __FUNCTION__ "(), tx_list=%d\n", 
 		   skb_queue_len( &self->tx_list));
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if ( self->qos_tx.compression.value) {
 		skb = irlap_compress_frame( self, skb);
 		if ( !skb) {
-			DEBUG( 0, __FUNCTION__ "(), Compress error!\n");
+			DEBUG( 1, __FUNCTION__ "(), Compress error!\n");
 			return;
 		}
 	}
@@ -401,8 +405,7 @@
 		}
 		irlap_do_event( self, SEND_I_CMD, skb, NULL);
 	} else
-		skb_queue_tail( &self->tx_list, skb);
-	
+		skb_queue_tail( &self->tx_list, skb);	
 }
 
 /*
@@ -410,14 +413,26 @@
  *
  *    Request to disconnect connection by service user
  */
-void irlap_disconnect_request( struct irlap_cb *self) 
+void irlap_disconnect_request(struct irlap_cb *self) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(3, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-
-	irlap_do_event( self, DISCONNECT_REQUEST, NULL, NULL);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	
+	switch (self->state) {
+	case LAP_XMIT_P:        /* FALLTROUGH */
+	case LAP_XMIT_S:        /* FALLTROUGH */
+ 	case LAP_CONN:          /* FALLTROUGH */
+ 	case LAP_RESET_WAIT:    /* FALLTROUGH */
+ 	case LAP_RESET_CHECK:   
+		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__ "(), disconnect pending!\n");
+		self->disconnect_pending = TRUE;
+		break;
+	}
 }
 
 /*
@@ -428,7 +443,7 @@
  */
 void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -442,18 +457,18 @@
 	
 	switch( reason) {
 	case LAP_RESET_INDICATION:
-		DEBUG( 0, "Sending reset request!\n");
+		DEBUG( 1, __FUNCTION__ "(), Sending reset request!\n");
 		irlap_do_event( self, RESET_REQUEST, NULL, NULL);
 		break;
-	case LAP_NO_RESPONSE:		
-	case LAP_DISC_INDICATION:
-	case LAP_FOUND_NONE:
+	case LAP_NO_RESPONSE:	   /* FALLTROUGH */	
+	case LAP_DISC_INDICATION:  /* FALLTROUGH */
+	case LAP_FOUND_NONE:       /* FALLTROUGH */
 	case LAP_MEDIA_BUSY:
 		irlmp_link_disconnect_indication( self->notify.instance, 
 						  self, reason, NULL);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Reason %d not implemented!\n", 
+		DEBUG( 1, __FUNCTION__ "(), Reason %d not implemented!\n", 
 		       reason);
 	}
 }
@@ -471,24 +486,48 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
 	ASSERT( discovery != NULL, return;);
+	
+	DEBUG( 4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
 
+	ASSERT(( discovery->nslots == 1) || ( discovery->nslots == 6) ||
+	       ( discovery->nslots == 8) || ( discovery->nslots == 16), 
+	       return;);
+	
   	/*
 	 *  Discovery is only possible in NDM mode
 	 */ 
 	if ( self->state == LAP_NDM) {
 		ASSERT( self->discovery_log == NULL, return;);
 		self->discovery_log= hashbin_new( HB_LOCAL);
-
-		info.S = 6; /* Number of slots */
+		
+		info.S = discovery->nslots; /* Number of slots */
 		info.s = 0; /* Current slot */
-
+		
 		self->discovery_cmd = discovery;
 		info.discovery = discovery;
 		
+		/* Check if the slot timeout is within limits */
+		if ( sysctl_slot_timeout < 2) {
+			DEBUG( 1, __FUNCTION__ 
+			       "(), to low value for slot timeout!\n");
+			sysctl_slot_timeout = 2;
+		}
+		/* 
+		 * Highest value is actually 8, but we allow higher since
+		 * some devices seems to require it.
+		 */
+		if ( sysctl_slot_timeout > 16) {
+			DEBUG( 1, __FUNCTION__ 
+			       "(), to high value for slot timeout!\n");
+			sysctl_slot_timeout = 16;
+		}
+
+		self->slot_timeout = sysctl_slot_timeout;
+		
 		irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info);
 	} else { 
  		DEBUG( 4, __FUNCTION__ 
- 			"(), discovery only possible in NDM mode\n");
+		       "(), discovery only possible in NDM mode\n");
 		irlap_discovery_confirm( self, NULL);
  	} 
 }
@@ -506,6 +545,14 @@
 	
 	ASSERT( self->notify.instance != NULL, return;);
 	
+	/* 
+	 * Check for successful discovery, since we are then allowed to clear 
+	 * 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)
+		irda_device_set_media_busy(self->irdev, FALSE);
+	
 	/* Inform IrLMP */
 	irlmp_link_discovery_confirm( self->notify.instance, discovery_log);
 	
@@ -552,7 +599,6 @@
 	default:
 		break;
 	}
-	/* TODO: layering violation! */
 	irlmp_status_indication( quality_of_link, NO_CHANGE);
 }
 
@@ -564,7 +610,7 @@
  */
 void irlap_reset_indication( struct irlap_cb *self)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 1, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -583,7 +629,7 @@
  */
 void irlap_reset_confirm(void)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 1, __FUNCTION__ "()\n");
 }
 
 /*
@@ -672,7 +718,7 @@
 
 	/*  ns as expected?  */
 	if ( ns == self->vr) {
-		DEBUG( 4, "*** irlap_validate_ns_received: expected!\n");
+		DEBUG( 4, __FUNCTION__ "(), expected!\n");
 		return NS_EXPECTED;
 	}
 	/*
@@ -696,7 +742,7 @@
 
 	/*  nr as expected?  */
 	if ( nr == self->vs) {
-		DEBUG( 4, "*** irlap_validate_nr_received: expected!\n");
+		DEBUG( 4, __FUNCTION__ "(), expected!\n");
 		return NR_EXPECTED;
 	}
 
@@ -724,7 +770,7 @@
  */
 void irlap_initiate_connection_state( struct irlap_cb *self) 
 {
-	DEBUG( 4, "irlap_initiate_connection_state()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -818,26 +864,26 @@
  *    Change the speed of the IrDA port
  *
  */
-void irlap_change_speed( struct irlap_cb *self, int speed)
+void irlap_change_speed(struct irlap_cb *self, int speed)
 {
-	DEBUG( 4, __FUNCTION__ "(), setting speed to %d\n", speed);
+	DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	if ( !self->irdev) {
-		DEBUG( 0, __FUNCTION__ "(), driver missing!\n");
+	if (!self->irdev) {
+		DEBUG( 1, __FUNCTION__ "(), driver missing!\n");
 		return;
 	}
 
-	irda_device_change_speed( self->irdev, speed);
+	irda_device_change_speed(self->irdev, speed);
 
 	self->qos_rx.baud_rate.value = speed;
 	self->qos_tx.baud_rate.value = speed;
 }
 
 #ifdef CONFIG_IRDA_COMPRESSION
-void irlap_init_comp_qos_capabilities( struct irlap_cb *self)
+void irlap_init_comp_qos_capabilities(struct irlap_cb *self)
 {
 	struct irda_compressor *comp;
 	__u8 mask; /* Current bit tested */
@@ -888,8 +934,8 @@
  *    IrLAP itself. Normally, IrLAP will not specify any values, but it can
  *    be used to restrict certain values.
  */
-void irlap_init_qos_capabilities( struct irlap_cb *self, 
-				  struct qos_info *qos_user)
+void irlap_init_qos_capabilities(struct irlap_cb *self,
+				 struct qos_info *qos_user)
 {
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -911,8 +957,8 @@
 	 *  allowed to supply these values. We check each parameter since the
 	 *  user may not have set all of them.
 	 */
-	if ( qos_user != NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Found user specified QoS!\n");
+	if (qos_user) {
+		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;
@@ -966,6 +1012,7 @@
 	self->bofs_count = 11;
 
 	/* Use these until connection has been made */
+	self->slot_timeout = sysctl_slot_timeout;
 	self->final_timeout = FINAL_TIMEOUT;
 	self->poll_timeout = POLL_TIMEOUT;
 	self->wd_timeout = WD_TIMEOUT;
@@ -974,6 +1021,8 @@
 	self->qos_tx.additional_bofs.value = 11;
 
 	irlap_flush_all_queues( self);
+
+	self->disconnect_pending = FALSE;
 }
 
 /*
@@ -982,8 +1031,8 @@
  *    Initialize IrLAP with the negotiated QoS values
  *
  */
-void irlap_apply_connection_parameters( struct irlap_cb *self, 
-					struct qos_info *qos) 
+void irlap_apply_connection_parameters(struct irlap_cb *self, 
+				       struct qos_info *qos) 
 {
 	DEBUG( 4, __FUNCTION__ "()\n");
 	
@@ -1010,15 +1059,13 @@
 	 *  TODO: these values should be calculated from the final timer
          *  as well
 	 */
-	if ( qos->link_disc_time.value == 3)
+	if (qos->link_disc_time.value == 3)
 		self->N1 = 0;
 	else
-		/* self->N1 = 6; */
 		self->N1 = 3000 / qos->max_turn_time.value;
 	
 	DEBUG( 4, "Setting N1 = %d\n", self->N1);
 	
-	/* self->N2 = qos->link_disc_time.value * 2; */
 	self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
 	DEBUG( 4, "Setting N2 = %d\n", self->N2);
 
@@ -1033,7 +1080,7 @@
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if ( qos->compression.value) {
-		DEBUG( 0, __FUNCTION__ "(), Initializing compression\n");
+		DEBUG( 1, __FUNCTION__ "(), Initializing compression\n");
 		irda_set_compression( self, qos->compression.value);
 
 		irlap_compressor_init( self, 0);
@@ -1065,7 +1112,7 @@
 		ASSERT( self != NULL, return -ENODEV;);
 		ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
 
-		len += sprintf( buf+len, "IrLAP[%d] <-> %s ",
+		len += sprintf( buf+len, "irlap%d <-> %s ",
 				i++, self->irdev->name);
 		len += sprintf( buf+len, "state: %s\n", 
 				irlap_state[ self->state]);
diff -urN linux-2.2.3-pre2/net/irda/irlap_comp.c linux-2.2.3-pre3/net/irda/irlap_comp.c
--- linux-2.2.3-pre2/net/irda/irlap_comp.c	1998-12-18 08:06:39.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlap_comp.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Oct  9 09:18:07 1998
- * Modified at:   Mon Dec 14 11:55:27 1998
+ * Modified at:   Mon Feb  8 01:23:52 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       ppp.c, isdn_ppp.c
  * 
@@ -81,8 +81,7 @@
 	if ( !node) {
 		DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
 		return;
-	}
-	
+	}	
 	kfree( node);
 }
 
@@ -99,7 +98,7 @@
 
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return -ENODEV;);
 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -180,7 +179,7 @@
 	int debug = TRUE;
 	__u8 options[CILEN_DEFLATE];
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -240,8 +239,8 @@
 	
 	ASSERT( skb != NULL, return NULL;);
 	
-	DEBUG( 0, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
-	       jiffies);
+	DEBUG(4, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
+	      jiffies);
 
 	ASSERT( self != NULL, return NULL;);
 	ASSERT( self->magic == LAP_MAGIC, return NULL;);
@@ -267,7 +266,7 @@
 						 skb->data, new_skb->data, 
 						 skb->len, new_skb->len);
 	if( count <= 0) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to compress frame!\n");
+		DEBUG(4, __FUNCTION__ "(), Unable to compress frame!\n");
 		dev_kfree_skb( new_skb);
 
 		/* Tell peer that this frame is not compressed */
@@ -284,8 +283,8 @@
 
 	dev_kfree_skb( skb);
 	
-	DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
-	       (int) new_skb->len, jiffies);
+	DEBUG(4, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
+	      (int) new_skb->len, jiffies);
 	
 	return new_skb;
 }
@@ -336,7 +335,7 @@
 	count = irda_decompress( self->decompressor.state, skb->data, 
 				 skb->len, new_skb->data, new_skb->len);
 	if ( count <= 0) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to decompress frame!\n");
+		DEBUG( 4, __FUNCTION__ "(), Unable to decompress frame!\n");
 		
 		dev_kfree_skb( new_skb);
 		return skb;
@@ -344,7 +343,7 @@
 
 	skb_trim( new_skb, count);
 	
-	DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
+	DEBUG( 4, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
 
 	return new_skb;
 }
diff -urN linux-2.2.3-pre2/net/irda/irlap_event.c linux-2.2.3-pre3/net/irda/irlap_event.c
--- linux-2.2.3-pre2/net/irda/irlap_event.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlap_event.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap_event.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   IrLAP state machine implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Tue Jan 19 22:58:45 1999
+ * Modified at:   Thu Feb 11 00:38:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>,
@@ -71,7 +71,7 @@
 static int irlap_state_reset_check( struct irlap_cb *, IRLAP_EVENT event, 
 				    struct sk_buff *, struct irlap_info *);
 
-static char *irlap_event[] = {
+static const char *irlap_event[] = {
 	"DISCOVERY_REQUEST",
 	"CONNECT_REQUEST",
 	"CONNECT_RESPONSE",
@@ -103,7 +103,7 @@
 	"BACKOFF_TIMER_EXPIRED",
 };
 
-char *irlap_state[] = {
+const char *irlap_state[] = {
 	"LAP_NDM",
 	"LAP_QUERY",
 	"LAP_REPLY",
@@ -198,53 +198,63 @@
 /*
  * Function irlap_do_event (event, skb, info)
  *
- *    Rushes through the state machine without any delay. If state = XMIT
+ *    Rushes through the state machine without any delay. If state == XMIT
  *    then send queued data frames. 
  */
 void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
 		     struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret;
-	int iter = 0;
 	
-	if ( !self || self->magic != LAP_MAGIC) {
-		DEBUG( 0, "irlap_do_event: bad pointer *self\n");
+	if ( !self || self->magic != LAP_MAGIC)
 		return;
-	}
-		
-  	DEBUG( 4, "irlap_do_event: event = %s, state = %s\n", 
+	
+  	DEBUG( 4, __FUNCTION__ "(), event = %s, state = %s\n", 
 	       irlap_event[ event], irlap_state[ self->state]); 
-
-	/* 
-	 *  Do event, this implementation does not deal with pending events. 
-	 *  This is because I don't see the need for this. DB
-	 */
+	
 	ret = (*state[ self->state]) ( self, event, skb, info);
 	
 	/* 
-	 *  Check if we have switched to XMIT state? If so, send queued data 
-	 *  frames if any, if -1 is returned it means that we are not allowed 
-	 *  to send any more frames.  
+	 *  Check if there are any pending events that needs to be executed
 	 */
-	while (( self->state == LAP_XMIT_P) || ( self->state == LAP_XMIT_S)) { 
-		if ( skb_queue_len( &self->tx_list) > 0) {
+	switch (self->state) {
+	case LAP_XMIT_P: /* FALLTHROUGH */
+	case LAP_XMIT_S:
+		/* 
+		 * Check if there are any queued data frames, and do not
+		 * try to disconnect link if we send any data frames, since
+		 * that will change the state away form XMIT
+		 */
+		if (skb_queue_len(&self->tx_list)) {
+			/* Try to send away all queued data frames */
+			while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
+				ret = (*state[ self->state])(self, SEND_I_CMD,
+							     skb, NULL);
+				if ( ret == -EPROTO)
+					break; /* Try again later! */
+			}
+		} else if (self->disconnect_pending) {
+			DEBUG(0, __FUNCTION__ "(), disconnecting!\n");
+			self->disconnect_pending = FALSE;
 			
-			struct sk_buff *skb = skb_dequeue( &self->tx_list); 
-			ASSERT( skb != NULL, return;);
+			ret = (*state[self->state])(self, DISCONNECT_REQUEST,
+						    NULL, NULL);
+		}
+		break;
+	case LAP_NDM:
+		/* Check if we should try to connect */
+		if (self->connect_pending) {
+			self->connect_pending = FALSE;
 			
-			DEBUG( 4, "** Sending queued data frames\n");
-			ret = (*state[ self->state])( self, SEND_I_CMD, skb,
-						      NULL);
-			if ( ret == -EPROTO)
-				return; /* Try again later! */
-		} else
-			return;
-
-		/* Just in case :-) */
-		if (iter++ > 100) {
-			DEBUG( 0, __FUNCTION__ "(), *** breaking!! ***\n");
-			return;
+			ret = (*state[self->state])(self, CONNECT_REQUEST, 
+						    NULL, NULL);
 		}
+		break;
+/* 	case LAP_CONN: */
+/* 	case LAP_RESET_WAIT: */
+/* 	case LAP_RESET_CHECK: */
+	default:
+		break;
 	}
 }
 
@@ -256,10 +266,8 @@
  */
 void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) 
 {	
-	if ( !self || self->magic != LAP_MAGIC) {
-		DEBUG( 4, "irlap_next_state: I have lost myself!\n");
+	if ( !self || self->magic != LAP_MAGIC)
 		return;
-	}
 	
 	DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]);
 
@@ -308,7 +316,7 @@
 			irlap_send_snrm_frame( self, &self->qos_rx);
 			
 			/* Start Final-bit timer */
-			irlap_start_final_timer( self, self->final_timeout);
+			irlap_start_final_timer(self, self->final_timeout);
 
 			self->retry_count = 0;
 			irlap_next_state( self, LAP_SETUP);
@@ -328,7 +336,7 @@
 		ASSERT( info != NULL, return -1;);
 
 	 	if ( irda_device_is_media_busy( self->irdev)) {
- 			DEBUG(0, "irlap_discovery_request: media busy!\n"); 
+ 			DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
 			/* irlap->log.condition = MEDIA_BUSY; */
 			
 			/* Always switch state before calling upper layers */
@@ -345,7 +353,7 @@
 						info->discovery);
 		self->s++;
 
-		irlap_start_slot_timer( self, SLOT_TIMEOUT);
+		irlap_start_slot_timer( self, self->slot_timeout);
 		irlap_next_state( self, LAP_QUERY);
 		break;
 
@@ -424,7 +432,7 @@
 							self->s, TRUE,
 							self->discovery_cmd);
 			self->s++;
-			irlap_start_slot_timer( self, SLOT_TIMEOUT);
+			irlap_start_slot_timer( self, self->slot_timeout);
 			
 			/* Keep state */
 			irlap_next_state( self, LAP_QUERY);
@@ -477,8 +485,8 @@
 
 	switch( event) {
 	case QUERY_TIMER_EXPIRED:
-		DEBUG( 0, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
-		       jiffies);
+		DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
+		      jiffies);
 		irlap_next_state( self, LAP_NDM);
 		break;
 	case RECV_DISCOVERY_XID_CMD:
@@ -510,12 +518,12 @@
 		dev_kfree_skb( skb);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event,
-		       irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+		      irlap_event[event]);
 
-		if ( skb != NULL)
+		if ( skb)
 			dev_kfree_skb( skb);
-
+		
 		ret = -1;
 		break;
 	}
@@ -571,20 +579,20 @@
 		irlap_next_state( self, LAP_NDM);
 #endif
 		break;
-
+		
 	case RECV_DISCOVERY_XID_CMD:
 		DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
 		irlap_next_state( self, LAP_NDM);
 		break;
-
+		
 	case DISCONNECT_REQUEST:
 		irlap_send_dm_frame( self);
 		irlap_next_state( self, LAP_CONN);
 		break;
 
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
-		       irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
+		      irlap_event[event]);
 		ret = -1;
 		break;
 	}
@@ -682,7 +690,9 @@
 
 		irlap_apply_connection_parameters( self, &self->qos_tx); 
 		self->retry_count = 0;
-		irlap_send_rr_frame( self, CMD_FRAME);
+		
+		/* This frame will just be sent at the old speed */
+		/* irlap_send_rr_frame( self, CMD_FRAME); */
 
 		irlap_start_final_timer( self, self->final_timeout/2);
 		irlap_next_state( self, LAP_NRM_P);
@@ -724,9 +734,10 @@
 /*
  * Function irlap_state_xmit_p (self, event, skb, info)
  * 
- *    XMIT, Only the primary station has right to transmit, and we therefor
- *    do not expect to receive any transmissions from other stations.  
- *
+ *    XMIT, Only the primary station has right to transmit, and we
+ *    therefore do not expect to receive any transmissions from other
+ *    stations.
+ * 
  */
 static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event, 
 			       struct sk_buff *skb, struct irlap_info *info) 
@@ -785,6 +796,12 @@
 				DEBUG( 4, __FUNCTION__ "(), window <= 1\n");
 				irlap_send_data_primary_poll( self, skb);
 				irlap_next_state( self, LAP_NRM_P);
+				
+				/* 
+				 * Make sure state machine does not try to send
+				 * any more frames 
+				 */
+				ret = -EPROTO;
 			}
 #ifdef CONFIG_IRDA_FAST_RR
 			/* Peer may want to reply immediately */
@@ -817,7 +834,8 @@
 		irlap_next_state( self, LAP_NRM_P);
 		break;
 	default:
-		/* DEBUG( 0, "irlap_state_xmit: Unknown event"); */
+		DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[event]);
 		ret = -EINVAL;
 		break;
 	}
@@ -834,7 +852,7 @@
 {
 	int ret = 0;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(1, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == LAP_MAGIC, return -1;);	
@@ -870,7 +888,7 @@
 		}
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
 		ret = -1;
 		break;	
 	}
@@ -961,8 +979,8 @@
 			/* Keep state */
 			irlap_next_state( self, LAP_NRM_P);
 		} else if ( ret == NR_INVALID) {
-			DEBUG( 0, "irlap_state_nrm_p: received RR with "
-			       "invalid nr !\n");
+			DEBUG(1, "irlap_state_nrm_p: received RR with "
+			      "invalid nr !\n");
 			del_timer( &self->final_timer);
 
 			irlap_next_state( self, LAP_RESET_WAIT);
@@ -1181,8 +1199,8 @@
 			}
 			break;
 		}
-		DEBUG( 0, "irlap_state_nrm_p: Not implemented!\n");
-		DEBUG( 0, "event=%s, ns_status=%d, nr_status=%d\n", 
+		DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
+		DEBUG(1, __FUNCTION__ "(), event=%s, ns_status=%d, nr_status=%d\n", 
 		       irlap_event[ event], ns_status, nr_status);
 		break;
 	case RECV_UI_FRAME:
@@ -1257,7 +1275,7 @@
 		}
 		break;
 	case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */
-		DEBUG( 0, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
+		DEBUG(1, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
 
 		/* Always switch state before calling upper layers */
 		irlap_next_state( self, LAP_NDM);
@@ -1277,7 +1295,8 @@
 		
 		break;
 	default:
-		/* DEBUG( 0, "irlap_state_nrm_p: Unknown event"); */
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[event]);
 		ret = -1;
 		break;
 	}
@@ -1322,8 +1341,8 @@
 		irlap_next_state( self, LAP_PCLOSE);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-		       irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[event]);
 		ret = -1;
 		break;	
 	}
@@ -1403,8 +1422,8 @@
 		break;
 
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-		       irlap_event[ event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[ event]);
 		ret = -1;
 		break;	
 	}
@@ -1468,16 +1487,22 @@
 				DEBUG( 4, "(), window <= 1\n");
 				irlap_send_data_secondary_final( self, skb);
 				irlap_next_state( self, LAP_NRM_S);
+
+				/* 
+				 * Make sure state machine does not try to send
+				 * any more frames 
+				 */
+				ret = -EPROTO;
 			}
 		} else {
-			DEBUG( 0, __FUNCTION__ "(), Unable to send!\n");
+			DEBUG(1, __FUNCTION__ "(), Unable to send!\n");
 			skb_queue_head( &self->tx_list, skb);
 			ret = -EPROTO;
 		}
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-		       irlap_event[ event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+		      irlap_event[ event]);
 		ret = -EINVAL;
 		break;
 	}
@@ -1543,8 +1568,7 @@
 			/* Keep state */
 			irlap_next_state( self, LAP_NRM_S); 
 		} else {
-			DEBUG( 0, __FUNCTION__ "(), "
-			       "invalid nr not implemented!\n");
+			DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
 		} 
 		if ( skb)
 			dev_kfree_skb( skb);
@@ -1731,7 +1755,7 @@
 		break;
 	case RECV_SNRM_CMD:
 		del_timer( &self->wd_timer);
-		DEBUG( 0, "irlap_state_nrm_s: received SNRM cmd\n");
+		DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
 		irlap_next_state( self, LAP_RESET_CHECK);
 
 		irlap_reset_indication( self);
@@ -1743,7 +1767,8 @@
 		 *  Wait until retry_count * n matches negotiated threshold/
 		 *  disconnect time (note 2 in IrLAP p. 82)
 		 */
-		DEBUG( 0, "retry_count = %d\n", self->retry_count);
+		DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
+		      self->retry_count);
 
 		if (( self->retry_count < (self->N2/2))  && 
 		    ( self->retry_count != self->N1/2)) {
@@ -1800,8 +1825,8 @@
 		break;
 
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-		       event, irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+		      event, irlap_event[event]);
 		ret = -1;
 		break;
 	}
@@ -1828,7 +1853,7 @@
 {
 	int ret = 0;
 
-	DEBUG( 0, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
 
 	ASSERT( self != NULL, return -ENODEV;);
 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -1848,8 +1873,8 @@
 		irlap_start_wd_timer( self, WD_TIMEOUT);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-		       event, irlap_event[event]);
+		DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+		      event, irlap_event[event]);
 		ret = -1;
 		break;
 	}
diff -urN linux-2.2.3-pre2/net/irda/irlap_frame.c linux-2.2.3-pre3/net/irda/irlap_frame.c
--- linux-2.2.3-pre2/net/irda/irlap_frame.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlap_frame.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap_frame.c
- * Version:       0.3
+ * Version:       0.8
  * Description:   Build and transmit IrLAP frames
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Tue Jan 19 22:58:13 1999
+ * Modified at:   Sat Feb 20 01:40:14 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 
-#include <linux/skbuff.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -49,7 +48,7 @@
  *    need to do this since it's per packet relevant information.
  *
  */
-__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
 {
 	struct irlap_skb_cb *cb;
 
@@ -76,18 +75,41 @@
 }
 
 /*
+ * Function irlap_queue_xmit (self, skb)
+ *
+ *    A little wrapper for dev_queue_xmit, so we can insert some common
+ *    code into it.
+ */
+void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
+{
+	/* Some init stuff */
+	skb->dev = self->netdev;
+	skb->h.raw = skb->nh.raw = skb->mac.raw = skb->data;
+ 	skb->protocol = htons(ETH_P_IRDA);
+
+	/* 
+	 * Insert MTT (min. turn time) into skb, so that the device driver 
+	 * knows which MTT to use 
+	 */
+	irlap_insert_mtt(self, skb);
+	
+	dev_queue_xmit(skb);
+	self->stats.tx_packets++;
+}
+
+/*
  * Function irlap_send_snrm_cmd (void)
  *
  *    Transmits a connect SNRM command frame
  */
-void irlap_send_snrm_frame( struct irlap_cb *self, struct qos_info *qos) 
+void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	int len;
 	int n;
 
-	DEBUG( 4, "irlap_send_snrm_cmd()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -95,14 +117,11 @@
 	n = 0;
 
 	/* Allocate frame */
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_snrm_cmd: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
-	skb_put( skb, 2); 
+	skb_put(skb, 2); 
 	frame = skb->data;
 
 	/* Insert address field */
@@ -116,23 +135,20 @@
 	 *  If we are establishing a connection then insert QoS paramerters 
 	 */
 	if (qos) {
-		skb_put( skb, 9); /* 21 left */
-		memcpy( frame+n, &self->saddr, 4); n += 4;
-		memcpy( frame+n, &self->daddr, 4); n += 4;
+		skb_put(skb, 9); /* 21 left */
+		*((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
+		*((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
+
+/* 		memcpy(frame+n, &self->saddr, 4); n += 4; */
+/* 		memcpy(frame+n, &self->daddr, 4); n += 4; */
 
 		frame[n++] = self->caddr;
 				
-		/* skb_put( skb, 21); */
-		len = irda_insert_qos_negotiation_params( qos, frame+n);
+		len = irda_insert_qos_negotiation_params(qos, frame+n);
 		/* Should not be dangerous to do this afterwards */
-		skb_put( skb, len);
+		skb_put(skb, len);
 	}
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -154,7 +170,8 @@
 	frame = ( struct snrm_frame *) skb->data;
 
 	/* Copy peer device address */
-	memcpy( &info->daddr, &frame->saddr, 4);
+	/* memcpy( &info->daddr, &frame->saddr, 4); */
+	info->daddr = le32_to_cpu(frame->saddr);
 
 	/* Copy connection address */
 	info->caddr = frame->ncaddr;
@@ -168,29 +185,25 @@
  *    Send UA (Unnumbered Acknowledgement) frame
  *
  */
-void irlap_send_ua_response_frame( struct irlap_cb *self, 
-				   struct qos_info *qos)
+void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	int n;
 	int len;
 	
-	DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
+	DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	skb = NULL;
 	n = 0;
 
 	/* Allocate frame */
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb =  dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 10);
 	frame = skb->data;
@@ -198,21 +211,20 @@
 	/* Build UA response */
 	frame[n++] = self->caddr;
  	frame[n++] = UA_RSP | PF_BIT;
-	memcpy( frame+n, &self->saddr, 4); n += 4;
-	memcpy( frame+n, &self->daddr, 4); n += 4;
+
+	*((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
+	*((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
+
+/* 	memcpy( frame+n, &self->saddr, 4); n += 4; */
+/* 	memcpy( frame+n, &self->daddr, 4); n += 4; */
 	
 	/* Should we send QoS negotiation parameters? */
-	if ( qos) {
-		len = irda_insert_qos_negotiation_params( qos, frame+n);
-		skb_put( skb, len);
+	if (qos) {
+		len = irda_insert_qos_negotiation_params(qos, frame+n);
+		skb_put(skb, len);
 	}
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 
@@ -230,12 +242,9 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LAP_MAGIC, return;);
 
-	skb =  dev_alloc_skb( 32);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_disc_frame: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(32);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 2);
 	frame = skb->data;
@@ -246,13 +255,8 @@
 		frame[0] = self->caddr;
 
 	frame[1] = DM_RSP | PF_BIT;
-	
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
 
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);	
 }
 
 /*
@@ -261,33 +265,27 @@
  *    Send disconnect (DISC) frame
  *
  */
-void irlap_send_disc_frame( struct irlap_cb *self) 
+void irlap_send_disc_frame(struct irlap_cb *self) 
 {
 	struct sk_buff *skb = NULL;
 	__u8 *frame;
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
+	DEBUG(3, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb =  dev_alloc_skb( 32);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_disc_frame: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(32);
+	if (!skb)
 		return;
-	}
 
-	skb_put( skb, 2);
+	skb_put(skb, 2);
 	frame = skb->data;
 	
 	frame[0] = self->caddr | CMD_FRAME;
 	frame[1] = DISC_CMD | PF_BIT;
-	
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
 
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -309,12 +307,9 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 	ASSERT( discovery != NULL, return;);
 
-	skb =  dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0,"irlap_send_discovery_xid_frame: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	skb = dev_alloc_skb(64);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 14);
 	frame = ( struct xid_frame *) skb->data;
@@ -328,12 +323,15 @@
 	}
 	frame->ident = XID_FORMAT;
 
-	memcpy( &frame->saddr, &self->saddr, 4);
+	frame->saddr = cpu_to_le32(self->saddr);
+/* 	memcpy( &frame->saddr, &self->saddr, 4); */
 
 	if ( command)
-		memcpy( &frame->daddr, &bcast, 4);
+		/* memcpy( &frame->daddr, &bcast, 4); */
+		frame->daddr = cpu_to_le32(bcast);
 	else
-		memcpy( &frame->daddr, &self->daddr, 4);	
+		/* memcpy( &frame->daddr, &self->daddr, 4); */
+		frame->daddr = cpu_to_le32(self->daddr);
 	
 	switch( S) {
 	case 1:
@@ -364,7 +362,7 @@
 	if ( !command || ( frame->slotnr == 0xff)) {
 		int i;
 
-		if( discovery->hint[0] & HINT_EXTENSION)
+		if (discovery->hint[0] & HINT_EXTENSION)
 			skb_put( skb, 3+discovery->info_len);
 		else
 			skb_put( skb, 2+discovery->info_len);
@@ -382,15 +380,9 @@
 			discovery->info_len);
 
 	} 
-
 	ASSERT( self->netdev != NULL, return;);
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -479,7 +471,8 @@
 	xid = (struct xid_frame *) skb->data;
 	
 	/* Copy peer device address */
-	memcpy( &info->daddr, &xid->saddr, 4);
+	/* memcpy( &info->daddr, &xid->saddr, 4); */
+	info->daddr = le32_to_cpu(xid->saddr);
 
 	switch ( xid->flags & 0x03) {
 	case 0x00:
@@ -567,13 +560,11 @@
 		self->recycle_rr_skb = NULL;
 	}
 #endif      
-	if ( !skb) {
+	if (!skb) {
 		skb = dev_alloc_skb( 32);
-		if (skb == NULL) {
-			printk( KERN_WARNING "irlap_send_rr_frame: "
-				"Could not allocate an skb of length %d\n", 32);
+		if (!skb)
 			return;
-		}
+   
 		skb_put( skb, 2);
 	}
 	ASSERT( skb->len == 2, return;);
@@ -585,14 +576,9 @@
 
 	frame[1] = RR | PF_BIT | (self->vr << 5);
 
-   	DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); 
-
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
+   	DEBUG(4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); 
 
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -613,7 +599,7 @@
 	frame = skb->data;
 	info->nr = frame[1] >> 5;
 
-	DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+	DEBUG(4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
 
 	/*
 	 *  Make sure the state-machine is in the right state for receiving, 
@@ -660,11 +646,8 @@
 	ASSERT( self->magic == LAP_MAGIC, return;);
 
 	skb = dev_alloc_skb( 32);
-	if (skb == NULL) {
-		printk( KERN_WARNING "irlap_send_frmr_frame: "
-			"Could not allocate an sk_buff of length %d\n", 32);
+	if (!skb)
 		return;
-	}
 
 	skb_put( skb, 2);
 	frame = skb->data;
@@ -680,12 +663,7 @@
 
    	DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -716,15 +694,15 @@
  *    Received UA (Unnumbered Acknowledgement) frame
  *
  */
-static void irlap_recv_ua_frame( struct irlap_cb *self, struct sk_buff *skb, 
-				 struct irlap_info *info) 
+static void irlap_recv_ua_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				struct irlap_info *info) 
 {
- 	DEBUG( 4, __FUNCTION__ "()\n"); 
+ 	DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies); 
 
-	ASSERT( skb != NULL, return;);
-	ASSERT( info != NULL, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(info != NULL, return;);
 
-	irlap_do_event( self, RECV_UA_RSP, skb, info);
+	irlap_do_event(self, RECV_UA_RSP, skb, info);
 }
 
 /*
@@ -756,7 +734,6 @@
 		
 		/* * Copy buffer */
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC);  */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -813,7 +790,6 @@
 		
 		/* Copy buffer */
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC);  */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -890,7 +866,6 @@
 		skb->data[1] = I_FRAME | (self->vs << 1);
 		
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC); */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -950,7 +925,6 @@
 		skb->data[1] = I_FRAME | (self->vs << 1);
 		
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC); */
 		if ( tx_skb == NULL) {
 			dev_kfree_skb( skb);
 			return;
@@ -1006,7 +980,6 @@
 		irlap_wait_min_turn_around( self, &self->qos_tx);
 
 		tx_skb = skb_clone( skb, GFP_ATOMIC);
-		/* tx_skb = skb_copy( skb, GFP_ATOMIC); */
 		if ( tx_skb == NULL) {
 			/* Unlink tx_skb from list */
 			tx_skb->next = tx_skb->prev = NULL;
@@ -1098,12 +1071,7 @@
 	frame[0] = self->caddr;
 	frame[0] |= (command) ? CMD_FRAME : 0;
 
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -1137,16 +1105,11 @@
 		vs = (frame[1] >> 1) & 0x07;
 		pf = (frame[1] >> 4) & 0x01;
 		
-		DEBUG( 0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
-		       vs, vr, pf, jiffies);
+		DEBUG(0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
+		      vs, vr, pf, jiffies);
 	}
 #endif	
-	skb->dev = self->netdev;
-	skb->h.raw = skb->data;
-	irlap_insert_mtt( self, skb);
-
-	dev_queue_xmit( skb);
-	self->stats.tx_packets++;
+	irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -1170,8 +1133,8 @@
 	info->pf = frame[1] & PF_BIT;      /* Final bit */
 	info->ns = (frame[1] >> 1) & 0x07; /* Next to send */
 
- 	DEBUG( 4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", 
-	       info->ns, info->nr, info->pf>>4, jiffies); 
+ 	DEBUG(4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", 
+	      info->ns, info->nr, info->pf>>4, jiffies); 
 
 	/*
 	 *  Make sure the state-machine is in the right state for receiving, 
@@ -1376,7 +1339,7 @@
 		irlap_next_state( self, LAP_NDM);
 		break;
 	case DISC_CMD:
-		DEBUG( 0, "DISC cmd frame received!\n");
+		DEBUG( 2, "DISC cmd frame received!\n");
 		irlap_do_event( self, RECV_DISC_FRAME, skb, &info);
 		break;
 	case TEST_CMD:
diff -urN linux-2.2.3-pre2/net/irda/irlmp.c linux-2.2.3-pre3/net/irda/irlmp.c
--- linux-2.2.3-pre2/net/irda/irlmp.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlmp.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Sat Jan 16 22:13:20 1999
+ * Modified at:   Sat Feb 20 01:28:39 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -44,9 +44,21 @@
 /* Master structure */
 struct irlmp_cb *irlmp = NULL;
 
+/* These can be altered by the sysctl interface */
 int sysctl_discovery = 0;
+int sysctl_discovery_slots = 6;
 char sysctl_devname[65];
 
+char *lmp_reasons[] = {
+	"ERROR, NOT USED",
+	"LM_USER_REQUEST",
+	"LM_LAP_DISCONNECT",
+	"LM_CONNECT_FAILURE",
+	"LM_LAP_RESET",
+	"LM_INIT_DISCONNECT",
+	"ERROR, NOT USED",
+};
+
 __u8 *irlmp_hint_to_service( __u8 *hint);
 #ifdef CONFIG_PROC_FS
 int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
@@ -61,8 +73,6 @@
  */
 __initfunc(int irlmp_init(void))
 {
-	DEBUG( 4, "--> irlmp_init\n");
-
 	/* Initialize the irlmp structure. */
 	if ( irlmp == NULL) {
 		irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
@@ -128,7 +138,7 @@
 	ASSERT( irlmp != NULL, return NULL;);
 	ASSERT( irlmp->magic == LMP_MAGIC, return NULL;);
 
-	DEBUG( 4, "irlmp_open_lsap(), slsap_sel=%02x\n", slsap_sel);
+	DEBUG( 4, __FUNCTION__ "(), slsap_sel=%02x\n", slsap_sel);
 
 	/* 
 	 *  Does the client care which Source LSAP selector it gets? 
@@ -166,6 +176,7 @@
 	self->magic = LMP_LSAP_MAGIC;
 	self->slsap_sel = slsap_sel;
 	self->dlsap_sel = LSAP_ANY;
+	self->connected = FALSE;
 
 	init_timer( &self->watchdog_timer);
 
@@ -190,7 +201,7 @@
  */
 static void __irlmp_close_lsap( struct lsap_cb *self)
 {
-	DEBUG( 4, "irlmp_close()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -205,12 +216,7 @@
 	ASSERT( irlmp != NULL, return;);
 	irlmp->cache.valid = FALSE;
 #endif
-	/*
-	 *  Deallocate structure
-	 */
 	kfree( self);
-
-	DEBUG( 4, "irlmp_close() -->\n");
 }
 
 /*
@@ -243,7 +249,7 @@
 		lsap = hashbin_remove( lap->lsaps, self->slsap_sel, NULL);
 	}
 	if ( lsap == NULL) {
-		DEBUG( 0, __FUNCTION__ 
+		DEBUG( 1, __FUNCTION__ 
 		       "(), Looks like somebody has removed me already!\n");
 		return;
 	}
@@ -285,11 +291,14 @@
 	lap->irlap = irlap;
 	lap->magic = LMP_LAP_MAGIC;
 	lap->saddr = saddr;
+	lap->daddr = DEV_ADDR_ANY;
 	lap->lsaps = hashbin_new( HB_GLOBAL);
  	lap->cachelog = hashbin_new( HB_LOCAL);
 
 	irlmp_next_lap_state( lap, LAP_STANDBY);
 	
+	init_timer(&lap->idle_timer);
+
 	/*
 	 *  Insert into queue of unconnected LSAPs
 	 */
@@ -309,20 +318,22 @@
  *    IrLAP layer has been removed!
  *
  */
-void irlmp_unregister_irlap( __u32 saddr)
+void irlmp_unregister_irlap(__u32 saddr)
 {
 	struct lap_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	self = hashbin_remove( irlmp->links, saddr, NULL);
-	if ( self != NULL) {
-		ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	self = hashbin_remove(irlmp->links, saddr, NULL);
+	if (self) {
+		ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 
-		self->magic = ~LMP_LAP_MAGIC;
-		kfree( self);
+		del_timer(&self->idle_timer);	
+
+		self->magic = 0;
+		kfree(self);
 	} else {
-		DEBUG( 0, "irlmp_unregister_irlap(), Didn't find LAP!\n");
+		DEBUG(1, __FUNCTION__ "(), Didn't find LAP layer!\n");
 	}
 }
 
@@ -334,98 +345,123 @@
 
 	d = (DISCOVERY *) hashbin_get_first( log);
 	while( d != NULL) {
-		DEBUG( 0, "Discovery:\n");
-		DEBUG( 0, "  daddr=%08x\n", d->daddr);
-		DEBUG( 0, "  name=%s\n", d->info);
+		DEBUG( 1, "Discovery:\n");
+		DEBUG( 1, "  daddr=%08x\n", d->daddr);
+		DEBUG( 1, "  name=%s\n", d->info);
 
 		d = (DISCOVERY *) hashbin_get_next( log);
 	}
 }
 
+static struct lap_cb *irlmp_find_link( __u32 daddr)
+{
+	struct lap_cb *lap;
+	unsigned long flags;
+
+	DEBUG( 1, __FUNCTION__ 
+	       "(), client didn't supply saddr, so try to look it up!\n");
+
+	/* 
+	 *  Find out which link to connect on, and make sure nothing strange
+	 *  happens while we traverse the list
+	 */
+	save_flags( flags);
+	cli();
+
+	lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
+	while ( lap != NULL) {
+		ASSERT( lap->magic == LMP_LAP_MAGIC, return NULL;);
+		/* dump_discoveries( lap->cachelog); */
+
+		if ( hashbin_find( lap->cachelog, daddr, NULL)) {
+			DEBUG( 4, __FUNCTION__
+			       "() found link to connect on!\n");
+			return lap;
+		}
+		lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
+	}
+	restore_flags(flags);
+
+	return NULL;
+}
+
 /*
  * Function irlmp_connect_request (handle, dlsap, userdata)
  *
  *    Connect with a peer LSAP  
  *
  */
-void irlmp_connect_request( struct lsap_cb *self, __u8 dlsap_sel, __u32 daddr, 
-			    struct qos_info *qos, struct sk_buff *userdata) 
+int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, 
+			  __u32 saddr, __u32 daddr, 
+			  struct qos_info *qos, struct sk_buff *userdata) 
 {
 	struct sk_buff *skb = NULL;
 	struct lap_cb *lap;
 	struct lsap_cb *lsap;
-	unsigned long flags;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return -1;);
+	
+	DEBUG( 4, __FUNCTION__ 
+	       "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n", 
+	       self->slsap_sel, dlsap_sel, saddr, daddr);
 	
-	DEBUG( 4, "irlmp_connect_request(), "
-	       "slsap_sel=%02x, dlsap_sel=%02x, daddr=%08x\n", 
-	       self->slsap_sel, dlsap_sel, daddr);
-
 	if ( self->connected) {
-		DEBUG( 0, __FUNCTION__ "(), Error: already connected!!\n");
+		DEBUG( 1, __FUNCTION__ "(), Error: already connected!!\n");
 		
-		return;
+		return -EISCONN;
 	}
 
 	/* Any userdata? */
 	if ( userdata == NULL) {
 		skb = dev_alloc_skb( 64);
 		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ 
+			DEBUG( 1, __FUNCTION__ 
 			       "(), Could not allocate sk_buff of length %d\n",
 			       64);
-			return;
+			return -1;
 		}
 		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
 	} else
 		skb = userdata;
 	
 	/* Make room for MUX control header ( 3 bytes) */
-	ASSERT( skb_headroom( skb) >= LMP_CONTROL_HEADER, return;);
+	ASSERT( skb_headroom( skb) >= LMP_CONTROL_HEADER, return -1;);
 	skb_push( skb, LMP_CONTROL_HEADER);
 
 	self->dlsap_sel = dlsap_sel;
 	self->tmp_skb = skb;
 	
-	/* 
-	 *  Find out which link to connect on, and make sure nothing strange
-	 *  happens while we traverse the list
-	 */
-	save_flags( flags);
-	cli();
-
-	lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
-	while ( lap != NULL) {
-		ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
-		/* dump_discoveries( lap->cachelog); */
-
-		if ( hashbin_find( lap->cachelog, daddr, NULL)) {
-			DEBUG( 4, "irlmp_connect_request() found link to connect on!\n");
-			self->lap = lap;
-			break;
-		}
-		lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
-	}
-	restore_flags(flags);
+	/*  
+	 * Find the link to where we should try to connect since there may
+	 * be more than one IrDA port on this machine. If the client has
+	 * passed us the saddr (and already knows which link to use), then
+	 * we use that to find the link, if not then we have to look in the
+	 * discovery log and check if any of the links has discovered a
+	 * device with the given daddr 
+	 */
+	if ( saddr)
+		lap = hashbin_find( irlmp->links, saddr, NULL);
+	else
+		lap = irlmp_find_link( daddr);
 	
+	if ( lap == NULL) {
+		DEBUG( 1, __FUNCTION__ "(), Unable to find a usable link!\n");
+		
+		return -EHOSTUNREACH;
+	}
+	self->lap = lap;
+
 	/* 
 	 *  Remove LSAP from list of unconnected LSAPs and insert it into the 
 	 *  list of connected LSAPs for the particular link */
 	lsap = hashbin_remove( irlmp->unconnected_lsaps, self->slsap_sel, 
 			       NULL);
 
-	/* Check if we found a link to connect on */
-	if ( self->lap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to find a usable link!\n");
-		return;
-	}
-
-	ASSERT( lsap != NULL, return;);
-	ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( lsap->lap != NULL, return;);
-	ASSERT( lsap->lap->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( lsap != NULL, return -1;);
+	ASSERT( lsap->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT( lsap->lap != NULL, return -1;);
+	ASSERT( lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
 
 	hashbin_insert( self->lap->lsaps, (QUEUE *) self, self->slsap_sel, 
 			NULL);
@@ -435,13 +471,15 @@
 	/*
 	 *  User supplied qos specifications?
 	 */
-	if ( qos)
+	if (qos)
 		self->qos = *qos;
 	
 	DEBUG( 4, "*** Connecting SLSAP=%02x, DLSAP= %02x\n",
 	       self->slsap_sel, self->dlsap_sel);
 	
 	irlmp_do_lsap_event( self, LM_CONNECT_REQUEST, skb);
+
+	return 0;
 }
 
 /*
@@ -454,7 +492,7 @@
 {
 	int max_seg_size;
 
-	DEBUG( 4, "irlmp_connect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -470,9 +508,8 @@
 	skb_pull( skb, LMP_CONTROL_HEADER);
 
 	if ( self->notify.connect_indication)
-		self->notify.connect_indication( self->notify.instance, self, 
-						 &self->qos, max_seg_size, 
-						 skb);
+		self->notify.connect_indication(self->notify.instance, self, 
+						&self->qos, max_seg_size, skb);
 }
 
 /*
@@ -483,7 +520,7 @@
  */
 void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) 
 {
-	DEBUG( 4, "irlmp_connect_response()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -541,14 +578,14 @@
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 4, "irlmp_disconnect_request()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 
 	/* Already disconnected? */
 	if ( !self->connected) {
-		DEBUG( 0, __FUNCTION__ "(), already disconnected!\n");
+		DEBUG( 1, __FUNCTION__ "(), already disconnected!\n");
 		return;
 	}
 
@@ -596,20 +633,20 @@
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");	
+	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( 4, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	DEBUG( 3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
 	       self->slsap_sel, self->dlsap_sel);
 
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
 
 	/* 
-	 *  Remove assosiation betwen this LSAP and the kink it used 
+	 *  Remove association between this LSAP and the link it used 
 	 */
 	ASSERT( self->lap != NULL, return;);
 	ASSERT( self->lap->lsaps != NULL, return;);
@@ -622,11 +659,6 @@
 			lsap->slsap_sel, NULL);
 
 	self->lap = NULL;
-
-	/* FIXME: the reasons should be extracted somewhere else? */
-	if ( userdata) {
-		DEBUG( 4, __FUNCTION__ "(), reason=%02x\n", userdata->data[3]);
-	}
 	
 	/*
 	 *  Inform service user
@@ -647,13 +679,18 @@
 {
 	struct lap_cb *lap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "(), nslots=%d\n", nslots);
 
 	ASSERT( irlmp != NULL, return;);
 
 	if ( !sysctl_discovery)
 		return;
 
+	if ((nslots != 1)&&(nslots != 6)&&(nslots != 8)&&(nslots != 16)) {
+		DEBUG( 1, __FUNCTION__ "(), invalid number of slots value!\n");
+		nslots = sysctl_discovery_slots = 8;
+	}
+
 	/*
 	 *  Construct new discovery info to be used by IrLAP,
 	 *  TODO: no need to do this every time!
@@ -670,6 +707,7 @@
 	
 	strncpy( irlmp->discovery_cmd.info, sysctl_devname, 31);
 	irlmp->discovery_cmd.info_len = strlen( irlmp->discovery_cmd.info);
+	irlmp->discovery_cmd.nslots = nslots;
 	
 	/*
 	 * Try to send discovery packets on all links
@@ -678,7 +716,7 @@
 	while ( lap != NULL) {
 		ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
 
-		DEBUG( 4, "irlmp_discovery_request() sending request!\n");
+		DEBUG( 4, __FUNCTION__ "() sending request!\n");
 		irlmp_do_lap_event( lap, LM_LAP_DISCOVERY_REQUEST, NULL);
 		
 		lap = ( struct lap_cb *) hashbin_get_next( irlmp->links);
@@ -698,8 +736,8 @@
 	__u8 *service;
 	int i = 0;
 
-	printk( KERN_INFO "IrDA Discovered: %s\n", discovery->info);
-	printk( KERN_INFO "    Services: ");
+	DEBUG(1, "IrDA Discovered: %s\n", discovery->info);
+	DEBUG(1, "    Services: ");
 
 	service = irlmp_hint_to_service( discovery->hint);
 	if (service != NULL) {
@@ -712,7 +750,7 @@
 					      service[i], NULL);
 			if ( entry && entry->discovery_callback) {
 				DEBUG( 4, "discovery_callback!\n");
-					entry->discovery_callback( discovery);
+				entry->discovery_callback( discovery);
 			} else {
 				/* 
 				 * Found no clients for dealing with this
@@ -783,11 +821,6 @@
 	DEBUG( 4, "discovery->daddr = 0x%08x\n", discovery->daddr); 
 	self->daddr = discovery->daddr;
 
-	/*
-	 *  Create a new discovery log if neccessary
-	 */
-	/* if ( self->cachelog == NULL) */
-/* 		self->cachelog = hashbin_new( HB_LOCAL); */
 	ASSERT( self->cachelog != NULL, return;);
 
 	/*
@@ -858,7 +891,7 @@
  */
 void irlmp_data_indication( struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG( 4, "irlmp_data_indication()\n"); 
+ 	DEBUG( 4, __FUNCTION__ "()\n"); 
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -877,13 +910,11 @@
  *    
  *
  */
-void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
+inline void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
 {
  	DEBUG( 4, __FUNCTION__ "()\n"); 
 
 	ASSERT( skb != NULL, return;);
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 	
 	/* Make room for MUX header */
 	ASSERT( skb_headroom( skb) >= LMP_HEADER, return;);
@@ -922,7 +953,7 @@
  */
 void irlmp_connectionless_data_request( struct sk_buff *skb)
 {
-	DEBUG( 0, __FUNCTION__ "(), Sorry not implemented\n"); 
+	DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n"); 
 }
 
 /*
@@ -933,12 +964,12 @@
  */
 void irlmp_connectionless_data_indication( struct sk_buff *skb)
 {
-	DEBUG( 0, __FUNCTION__ "()\n"); 
+	DEBUG( 1, __FUNCTION__ "()\n"); 
 }
 
 void irlmp_status_request(void) 
 {
-	DEBUG( 0, "irlmp_status_request(), Not implemented\n");
+	DEBUG( 1, "irlmp_status_request(), Not implemented\n");
 }
 
 void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) 
@@ -952,38 +983,41 @@
  *    Returns a list of all servics contained in the given hint bits. This
  *    funtion assumes that the hint bits have the size of two bytes only
  */
-__u8 *irlmp_hint_to_service( __u8 *hint)
+__u8 *irlmp_hint_to_service(__u8 *hint)
 {
 	__u8 *service;
 	int i = 0;
 
-	/* Allocate array to store services in */
+	/* 
+	 * Allocate array to store services in. 16 entries should be safe 
+	 * since we currently only support 2 hint bytes
+	 */
 	service = kmalloc( 16, GFP_ATOMIC);
 	if ( !service) {
-		DEBUG( 0, "irlmp_hint_to_service: Unable to kmalloc!\n");
+		DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
 	if ( !hint[0]) {
-		printk( "<None>\n");
+		DEBUG(1, "<None>\n");
 		return NULL;
 	}
 	if ( hint[0] & HINT_PNP)
-		printk( "PnP Compatible ");
+		DEBUG(1, "PnP Compatible ");
 	if ( hint[0] & HINT_PDA)
-		printk( "PDA/Palmtop ");
+		DEBUG(1, "PDA/Palmtop ");
 	if ( hint[0] & HINT_COMPUTER)
-		printk( "Computer ");
+		DEBUG(1, "Computer ");
 	if ( hint[0] & HINT_PRINTER) {
-		printk( "Printer\n");
+		DEBUG(1, "Printer ");
 		service[i++] = S_PRINTER;
 	}
 	if ( hint[0] & HINT_MODEM)
-		printk( "Modem ");
+		DEBUG(1, "Modem ");
 	if ( hint[0] & HINT_FAX)
-		printk( "Fax ");
+		DEBUG(1, "Fax ");
 	if ( hint[0] & HINT_LAN) {
-		printk( "LAN Access\n");			
+		DEBUG(1, "LAN Access ");		
 		service[i++] = S_LAN;
 	}
 	/* 
@@ -992,22 +1026,22 @@
 	 *  (IrLMP p. 29)
 	 */
 	if ( hint[0] & HINT_EXTENSION) {
-		if ( hint[1] & HINT_TELEPHONY)
-			printk( "Telephony ");
-		
-		if ( hint[1] & HINT_FILE_SERVER)
-			printk( "File Server ");
+		if ( hint[1] & HINT_TELEPHONY) {
+			DEBUG(1, "Telephony ");
+			service[i++] = S_TELEPHONY;
+		} if ( hint[1] & HINT_FILE_SERVER)
+			DEBUG(1, "File Server ");
 		
 		if ( hint[1] & HINT_COMM) {
-			printk( "IrCOMM ");
+			DEBUG(1, "IrCOMM ");
 			service[i++] = S_COMM;
 		}
 		if ( hint[1] & HINT_OBEX) {
-			printk( "IrOBEX ");
+			DEBUG(1, "IrOBEX ");
 			service[i++] = S_OBEX;
 		}
 	}
-	printk( "\n");
+	DEBUG(1, "\n");
 
 	service[i] = S_END;
 	
@@ -1050,7 +1084,7 @@
 		hint[1] |= HINT_OBEX;
 		break;
 	default:
-		DEBUG( 0, "irlmp_service_to_hint(), Unknown service!\n");
+		DEBUG( 1, __FUNCTION__ "(), Unknown service!\n");
 		break;
 	}
 }
@@ -1089,7 +1123,7 @@
 	/* Make a new registration */
  	entry = kmalloc( sizeof( struct irlmp_registration), GFP_ATOMIC);
 	if ( !entry) {
-		DEBUG( 0, "irlmp_register(), Unable to kmalloc!\n");
+		DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return;
 	}
 
@@ -1120,7 +1154,7 @@
 	}
 
 	if ( !entry) {
-		DEBUG( 0, "Unable to find entry to unregister!\n");
+		DEBUG( 1, __FUNCTION__ "Unable to find entry to unregister!\n");
 		return;
 	}
 
@@ -1164,7 +1198,7 @@
 	ASSERT( irlmp->magic == LMP_MAGIC, return TRUE;);
 	ASSERT( slsap_sel != LSAP_ANY, return TRUE;);
 
-	DEBUG( 4, "irlmp_slsap_inuse()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 *  Check if slsap is already in use. To do this we have to loop over
@@ -1208,8 +1242,7 @@
       
 	lsap_sel = irlmp->free_lsap_sel++;
 
-	DEBUG( 4, "irlmp_find_free_slsap(), picked next free lsap_sel=%02x\n",
-	       lsap_sel);
+	DEBUG( 4, __FUNCTION__ "(), next free lsap_sel=%02x\n", lsap_sel);
 
 	return lsap_sel;
 }
@@ -1227,21 +1260,25 @@
 
 	switch (lap_reason) {		
 	case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
+		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");
 		reason = LM_LAP_DISCONNECT;
 		break;
 	case LAP_RESET_INDICATION:
+		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");
 		reason = LM_CONNECT_FAILURE;
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ 
+		DEBUG( 1, __FUNCTION__ 
 		       "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
 		reason = LM_LAP_DISCONNECT;
 		break;
@@ -1250,6 +1287,26 @@
 	return reason;
 }	
 
+__u32 irlmp_get_saddr(struct lsap_cb *self)
+{
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->lap != NULL, return 0;);
+
+	return self->lap->saddr;
+}
+
+__u32 irlmp_get_daddr(struct lsap_cb *self)
+{
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->lap != NULL, return 0;);
+	
+	return self->lap->daddr;
+}
+
 #ifdef CONFIG_PROC_FS
 /*
  * Function irlmp_proc_read (buf, start, offset, len, unused)
@@ -1295,8 +1352,7 @@
 		len += sprintf( buf+len, "lap state: %s, ", 
 				irlmp_state[ lap->lap_state]);
 
-		len += sprintf( buf+len, 
-				"saddr: %#08x, daddr: %#08x, ",
+		len += sprintf( buf+len, "saddr: %#08x, daddr: %#08x, ",
 				lap->saddr, lap->daddr); 
 		len += sprintf( buf+len, "\n");
 
diff -urN linux-2.2.3-pre2/net/irda/irlmp_event.c linux-2.2.3-pre3/net/irda/irlmp_event.c
--- linux-2.2.3-pre2/net/irda/irlmp_event.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlmp_event.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlmp_event.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   An IrDA LMP event driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:22:29 1999
+ * Modified at:   Thu Feb 11 01:24:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -32,13 +32,13 @@
 #include <net/irda/irlmp_frame.h>
 #include <net/irda/irlmp_event.h>
 
-char *irlmp_state[] = {
+const char *irlmp_state[] = {
 	"LAP_STANDBY",
 	"LAP_U_CONNECT",
 	"LAP_ACTIVE",
 };
 
-char *irlsap_state[] = {
+const char *irlsap_state[] = {
 	"LSAP_DISCONNECTED",
 	"LSAP_CONNECT",
 	"LSAP_CONNECT_PEND",
@@ -47,7 +47,7 @@
 	"LSAP_SETUP_PEND",
 };
 
-static char *irlmp_event[] = {
+static const char *irlmp_event[] = {
 	"LM_CONNECT_REQUEST",
  	"LM_CONNECT_CONFIRM",
 	"LM_CONNECT_RESPONSE",
@@ -71,6 +71,7 @@
 	"LM_LAP_DISCONNECT_REQUEST",
 	"LM_LAP_DISCOVERY_REQUEST",
  	"LM_LAP_DISCOVERY_CONFIRM",
+	"LM_LAP_IDLE_TIMEOUT",
 };
 
 /* LAP Connection control proto declarations */
@@ -150,7 +151,7 @@
 	
 	DEBUG( 4, "IrLMP, discovery timer expired!\n");
 	
-	irlmp_discovery_request( 8);
+	irlmp_discovery_request( sysctl_discovery_slots);
 
 	/* Restart timer */
 	irlmp_start_discovery_timer( irlmp, 300);
@@ -168,6 +169,18 @@
 	irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL);
 }
 
+void irlmp_idle_timer_expired(unsigned long data)
+{
+	struct lap_cb *self = (struct lap_cb *) data;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+
+	irlmp_do_lap_event( self, LM_LAP_IDLE_TIMEOUT, NULL);
+}
+
 /*********************************************************************
  *
  *    LAP connection control states
@@ -207,10 +220,10 @@
 		irlap_connect_response( self->irlap, skb);
 		break;
 	case LM_LAP_CONNECT_REQUEST:
-		DEBUG( 4, "irlmp_state_standby() LS_CONNECT_REQUEST\n");
+		DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
 
 		/* FIXME: need to set users requested QoS */
-		irlap_connect_request( self->irlap, self->daddr, NULL, 0);
+		irlap_connect_request(self->irlap, self->daddr, NULL, 0);
 
 		irlmp_next_lap_state( self, LAP_U_CONNECT);
 		break;
@@ -221,7 +234,7 @@
 		irlmp_next_lap_state( self, LAP_STANDBY);
 		break;
 	default:
-		DEBUG( 4, "irlmp_state_standby: Unknown event\n");
+		DEBUG(4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}
 }
@@ -239,7 +252,7 @@
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
 	
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[ event]);
 
 	switch( event) {
 	case LM_LAP_CONNECT_CONFIRM:
@@ -253,7 +266,7 @@
 		}		
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG( 4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
+		DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
 	
 		irlmp_next_lap_state( self, LAP_STANDBY);
 
@@ -312,25 +325,31 @@
 		 */
 		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
 		while ( lsap != NULL) {
-			irlmp_do_lsap_event( lsap, LM_LAP_CONNECT_CONFIRM, 
-					     skb); 
-			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
+ 			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
 		}
-		
 		/* Keep state */
 		break;
 	case LM_LAP_DISCONNECT_REQUEST:
 		DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
 
 		/*
-		 *  Need to find out if we should close IrLAP or not
+		 *  Need to find out if we should close IrLAP or not. If there
+		 *  is only one LSAP connection left on this link, that LSAP 
+		 *  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) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), no more LSAPs so time to disconnect IrLAP\n");
-			irlmp_next_lap_state( self, LAP_STANDBY);
-		
-			irlap_disconnect_request( self->irlap);
+		if (hashbin_get_size(self->lsaps) == 1)
+			irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+
+		break;
+	case LM_LAP_IDLE_TIMEOUT:
+		if (hashbin_get_size(self->lsaps) == 0) {
+			DEBUG(0, __FUNCTION__ 
+			      "(), no more LSAPs so time to close IrLAP\n");
+			irlmp_next_lap_state(self, LAP_STANDBY);
+			
+			irlap_disconnect_request(self->irlap);
 		}
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
@@ -395,7 +414,6 @@
 	case LM_CONNECT_INDICATION:
 		irlmp_next_lsap_state( self, LSAP_CONNECT_PEND);
 
-
 		/* 
 		 *  Bind this LSAP to the IrLAP link where the connect was
 		 *  received 
@@ -415,8 +433,7 @@
 		irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, skb);
 		break;
 	default:
-		/* DEBUG( 4, "irlmp_state_disconnected: Unknown event %d\n",
-		   event); */
+		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
 }
@@ -448,7 +465,7 @@
 		irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY);
 		break;
 	default:
-		DEBUG( 4, "irlmp_state_connect: Unknown event\n");
+		DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}
 }
@@ -489,8 +506,7 @@
 		break;
 		
 	default:
-		DEBUG( 4, "irlmp_state_connect_pend: Unknown event %d\n", 
-		       event);
+		DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
 		break;	
 	}	
 }
@@ -571,12 +587,13 @@
 		ASSERT( self->lap != NULL, return;);
 		ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
 	
-		reason = irlmp_convert_lap_reason( self->lap->reason);
+		ASSERT(skb != NULL, return;);
+		ASSERT(skb->len > 3, return;);
+		reason = skb->data[3];
 
 		 /* Try to close the LAP connection */
 		DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n");
-		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, 
-				    NULL);
+		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
 
 		irlmp_disconnect_indication( self, reason, skb);
 
@@ -602,7 +619,7 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 
-	DEBUG( 4, "irlmp_state_setup()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	switch( event) {
 	case LM_CONNECT_CONFIRM:
@@ -622,10 +639,21 @@
 		ASSERT( self->lap != NULL, return;);
 		ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
 		
-		reason = irlmp_convert_lap_reason( self->lap->reason);
-		
+		ASSERT(skb != NULL, return;);
+		ASSERT(skb->len > 3, return;);
+		reason = skb->data[3];
+
 		irlmp_disconnect_indication( self, reason, skb);
 		break;
+	case LM_WATCHDOG_TIMEOUT:
+		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+		
+		ASSERT( self->lap != NULL, return;);
+		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		
+		irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+		break;
 	default:
 		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
@@ -643,6 +671,7 @@
 static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event, 
 				    struct sk_buff *skb) 
 {
+	LM_REASON reason;
 
 	DEBUG( 4, __FUNCTION__ "()\n"); 
 
@@ -656,18 +685,23 @@
 				    self->tmp_skb);
 		irlmp_next_lsap_state( self, LSAP_SETUP);
 		break;
-	case LM_DISCONNECT_INDICATION:
-		del_timer( &self->watchdog_timer);
-
-		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
-		break;
 	case LM_WATCHDOG_TIMEOUT:
 		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 
-		/* FIXME: should we do a disconnect_indication? */
 		ASSERT( self->lap != NULL, return;);
-		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+
+		irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+		break;
+	case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
+		del_timer( &self->watchdog_timer);
+
 		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		
+		reason = irlmp_convert_lap_reason( self->lap->reason);
+		
+		irlmp_disconnect_indication( self, reason, NULL);
 		break;
 	default:
 		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
diff -urN linux-2.2.3-pre2/net/irda/irlmp_frame.c linux-2.2.3-pre3/net/irda/irlmp_frame.c
--- linux-2.2.3-pre2/net/irda/irlmp_frame.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlmp_frame.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Sat Jan 16 22:14:04 1999
+ * Modified at:   Thu Feb 18 08:48:28 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
@@ -196,15 +196,15 @@
  *    IrLAP has disconnected 
  *
  */
-void irlmp_link_disconnect_indication( struct lap_cb *lap, 
-				       struct irlap_cb *irlap, 
-				       LAP_REASON reason, 
-				       struct sk_buff *userdata)
+void irlmp_link_disconnect_indication(struct lap_cb *lap, 
+				      struct irlap_cb *irlap, 
+				      LAP_REASON reason, 
+				      struct sk_buff *userdata)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( lap != NULL, return;);
-	ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(lap != NULL, return;);
+	ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
 
 	lap->reason = reason;
 
@@ -213,7 +213,7 @@
 	/*
 	 *  Inform station state machine
 	 */
-	irlmp_do_lap_event( lap, LM_LAP_DISCONNECT_INDICATION, NULL);
+	irlmp_do_lap_event(lap, LM_LAP_DISCONNECT_INDICATION, NULL);
 }
 
 /*
@@ -222,7 +222,8 @@
  *    Incoming LAP connection!
  *
  */
-void irlmp_link_connect_indication( struct lap_cb *self, struct qos_info *qos,
+void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, 
+				    __u32 daddr, struct qos_info *qos,
 				    struct sk_buff *skb) 
 {
 	DEBUG( 4, __FUNCTION__ "()\n");
@@ -230,6 +231,10 @@
 	/* Copy QoS settings for this session */
 	self->qos = qos;
 
+	/* Update destination device address */
+	self->daddr = daddr;
+	ASSERT(self->saddr == saddr, return;);
+
 	irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb);
 }
 
diff -urN linux-2.2.3-pre2/net/irda/irlpt/irlpt_cli.c linux-2.2.3-pre3/net/irda/irlpt/irlpt_cli.c
--- linux-2.2.3-pre2/net/irda/irlpt/irlpt_cli.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlpt/irlpt_cli.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,6 +1,6 @@
 /*********************************************************************
  *
- * Filename:      irlpt.c
+ * Filename:      irlpt_cli.c
  * Version:       
  * Description:   
  * Status:        Experimental.
@@ -49,18 +49,21 @@
 
 static void irlpt_client_discovery_indication( DISCOVERY *);
 
-static void irlpt_client_connect_confirm( void *instance, void *sap, 
+static void irlpt_client_connect_confirm( void *instance, 
+					  void *sap, 
 					  struct qos_info *qos, 
 					  int max_seg_size, 
 					  struct sk_buff *skb);
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+static void irlpt_client_disconnect_indication( void *instance, 
+						void *sap, 
 						LM_REASON reason,
 						struct sk_buff *userdata);
+static void irlpt_client_expired(unsigned long data);
 
 #if 0
 static char *rcsid = "$Id: irlpt_client.c,v 1.10 1998/11/10 22:50:57 dagb Exp $";
 #endif
-static char *version = "IrLPT, $Revision: 1.10 $/$Date: 1998/11/10 22:50:57 $ (Thomas Davis)";
+static char *version = "IrLPT client, v2 (Thomas Davis)";
 
 struct file_operations client_fops = {
 	irlpt_seek,    /* seek */
@@ -102,6 +105,9 @@
 	while( self) {
 	        ASSERT( self != NULL, return len;);
           	ASSERT( self->magic == IRLPT_MAGIC, return len;);
+		if (self->in_use == FALSE) {
+		        break;
+		}
 
 		len += sprintf(buf+len, "ifname: %s\n", self->ifname);
 		len += sprintf(buf+len, "minor: %d\n", self->ir_dev.minor);
@@ -130,19 +136,20 @@
 			break;
 		}
 		
-		len += sprintf(buf+len, "service_type: %s\n", 
-			       irlpt_service_type[index]);
-		len += sprintf(buf+len, "port_type: %s\n", 
+		len += sprintf(buf+len, "service_type: %s, port type: %s\n", 
+			       irlpt_service_type[index],
 			       irlpt_port_type[ self->porttype]);
-		len += sprintf(buf+len, "daddr: 0x%08x\n", self->daddr);
-		len += sprintf(buf+len, "fsm_state: %s\n", 
-			       irlpt_client_fsm_state[self->state]);
-		len += sprintf(buf+len, "retries: %d\n", self->open_retries);
-		len += sprintf(buf+len, "dlsap: %d\n", self->dlsap_sel);
 
-		len += sprintf(buf+len, "count: %d\n", self->count);
-		len += sprintf(buf+len, "rx_queue: %d\n", 
-			       skb_queue_len(&self->rx_queue));
+		len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
+			       self->saddr, self->daddr);
+		len += sprintf(buf+len, 
+			       "retries: %d, count: %d, queued packets: %d\n", 
+			       self->open_retries,
+			       self->count, self->pkt_count);
+		len += sprintf(buf+len, "slsap: %d, dlsap: %d\n", 
+			       self->slsap_sel, self->dlsap_sel);
+		len += sprintf(buf+len, "fsm state: %s\n", 
+			       irlpt_client_fsm_state[self->state]);
 		len += sprintf(buf+len, "\n\n");
 		
 		self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
@@ -163,7 +170,7 @@
 #endif /* CONFIG_PROC_FS */
 
 /*
- * Function irlpt_init (dev)
+ * Function irlpt_client_init (dev)
  *
  *   Initializes the irlpt control structure
  *
@@ -176,7 +183,8 @@
 
 	irlpt_clients = hashbin_new( HB_LOCAL); 
 	if ( irlpt_clients == NULL) {
-		printk( KERN_WARNING "IrLPT: Can't allocate hashbin!\n");
+		printk( KERN_WARNING 
+			"IrLPT client: Can't allocate hashbin!\n");
 		return -ENOMEM;
 	}
 
@@ -195,9 +203,7 @@
 
 #ifdef MODULE
 /*
- * Function irlpt_cleanup (void)
- *
- *
+ * Function irlpt_client_cleanup (void)
  *
  */
 static void irlpt_client_cleanup(void)
@@ -207,7 +213,7 @@
 	irlmp_unregister_layer( S_PRINTER, CLIENT);
 
 	/*
-	 *  Delete hashbin and close all irlan client instances in it
+	 *  Delete hashbin and close all irlpt client instances in it
 	 */
 	hashbin_delete( irlpt_clients, (FREE_FUNC) irlpt_client_close);
 
@@ -221,9 +227,7 @@
 
 
 /*
- * Function irlpt_open (void)
- *
- *    This is the entry-point which starts all the fun! Currently this
+ * Function irlpt_client_open (void)
  *
  */
 static struct irlpt_cb *irlpt_client_open( __u32 daddr)
@@ -232,15 +236,24 @@
 
 	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
 
-	self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
-	if (self == NULL)
-		return NULL;
+	self = (struct irlpt_cb *) hashbin_find(irlpt_clients, daddr, NULL);
+
+	if (self == NULL) {
+	        self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
+		if (self == NULL)
+		        return NULL;
+
+		memset(self, 0, sizeof(struct irlpt_cb));
 
-	memset(self, 0, sizeof(struct irlpt_cb));
+		ASSERT( self != NULL, return NULL;);
 
-	ASSERT( self != NULL, return NULL;);
+		sprintf(self->ifname, "irlpt%d", 
+			hashbin_get_size(irlpt_clients));
+
+		hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
+
+	}
 
- 	sprintf(self->ifname, "irlpt%d", hashbin_get_size(irlpt_clients));
 	self->ir_dev.minor = MISC_DYNAMIC_MINOR;
 	self->ir_dev.name = self->ifname;
 	self->ir_dev.fops = &client_fops;
@@ -251,14 +264,13 @@
 	self->in_use = TRUE;
 	self->servicetype = IRLPT_THREE_WIRE_RAW;
 	self->porttype = IRLPT_SERIAL;
+	self->do_event = irlpt_client_do_event;
 
 	skb_queue_head_init(&self->rx_queue);
 
 	irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
 
-	hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
-
-	/*	MOD_INC_USE_COUNT; */
+	MOD_INC_USE_COUNT;
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 
@@ -280,17 +292,15 @@
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
 	while (( skb = skb_dequeue(&self->rx_queue)) != NULL) {
-		DEBUG(3, "irlpt_client_close: freeing SKB\n");
+		DEBUG(irlpt_client_debug, 
+		      __FUNCTION__ ": freeing SKB\n");
                 dev_kfree_skb( skb);
 	}
 
 	misc_deregister(&self->ir_dev);
+	self->in_use = FALSE;
 
-	self->magic = ~IRLPT_MAGIC;
-
-	kfree( self);
-
-	/* MOD_DEC_USE_COUNT; */
+	MOD_DEC_USE_COUNT;
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -306,49 +316,51 @@
 {
 	struct irlpt_info info;
 	struct irlpt_cb *self;
-	__u32 daddr;
+	__u32 daddr; /* address of remote printer */
+	__u32 saddr; /* address of local link where it was discovered */
 
 	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
 
 	ASSERT( irlpt_clients != NULL, return;);
 	ASSERT( discovery != NULL, return;);
 
-	daddr = discovery->daddr;
+	daddr = info.daddr = discovery->daddr;
+	saddr = info.saddr = discovery->saddr;
 
 	/*
 	 *  Check if an instance is already dealing with this device
 	 *  (daddr)
 	 */
 	self = (struct irlpt_cb *) hashbin_find( irlpt_clients, daddr, NULL);
-      	if ( self != NULL) {
-		ASSERT( self->magic == IRLPT_MAGIC, return;);
-		if ( self->state == IRLPT_CLIENT_IDLE) {
-			irlpt_client_do_event( self, 
-					       IRLPT_DISCOVERY_INDICATION, 
-					       NULL, &info);
+      	if (self == NULL || self->in_use == FALSE) {
+	        DEBUG( irlpt_client_debug, __FUNCTION__ 
+		       ": daddr 0x%08x not found or was closed\n", daddr);
+	        /*
+		 * We have no instance for daddr, so time to start a new 
+		 * instance. First we must find a free entry in master array
+		 */
+		if (( self = irlpt_client_open( daddr)) == NULL) {
+			DEBUG(irlpt_client_debug, __FUNCTION__ 
+			      ": failed!\n");
+			return;
 		}
-		return;
-	}
-    
-
-	/*
-	 * We have no instance for daddr, so time to start a new instance.
-	 * First we must find a free entry in master array
-	 */
-	if (( self = irlpt_client_open( daddr)) == NULL) {
-		DEBUG(irlpt_client_debug, __FUNCTION__ 
-		      ":irlpt_client_open failed!\n");
 	}
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLPT_MAGIC, return;);
 
-	self->daddr = info.daddr = daddr;
+	self->daddr = daddr;
+	self->saddr = saddr;
+	self->timeout = irlpt_client_expired;
+
+	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
+			  self->timeout);
 	
-	if (self->state == IRLPT_CLIENT_IDLE) {
-		irlpt_client_do_event( self, IRLPT_DISCOVERY_INDICATION, 
-				       NULL, &info);
-	}
+#if 0
+	/* changed to wake up when we get connected; that way,
+	   if the connection drops, we can easily kill the link. */
+	wake_up_interruptible( &self->write_wait);
+#endif
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -357,7 +369,8 @@
  * Function irlpt_disconnect_indication (handle)
  *
  */
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+static void irlpt_client_disconnect_indication( void *instance,
+						void *sap, 
 						LM_REASON reason,
 						struct sk_buff *skb)
 {
@@ -373,8 +386,8 @@
 
 	info.daddr = self->daddr;
 
-        DEBUG( irlpt_client_debug, __FUNCTION__ 
-	       ": reason=%d (%s), peersap=%d\n",
+        DEBUG( irlpt_client_debug, 
+	       __FUNCTION__ ": reason=%d (%s), peersap=%d\n",
 	       reason, irlpt_reasons[reason], self->dlsap_sel);
 
 	self->connected = IRLPT_DISCONNECTED;
@@ -413,6 +426,7 @@
 
 	info.daddr = self->daddr;
 
+#if 0
 	/*
 	 *  Check if we have got some QoS parameters back! This should be the
 	 *  negotiated QoS for the link.
@@ -421,6 +435,7 @@
 		DEBUG( irlpt_client_debug, __FUNCTION__ ": Frame Size: %d\n",
 		       qos->data_size.value);
 	}
+#endif
 
 	self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER);
 	self->connected = TRUE;
@@ -489,7 +504,6 @@
  *    Fixed to match changes in iriap.h, DB.
  *
  */
-
 void irlpt_client_get_value_confirm(__u16 obj_id, struct ias_value *value, 
 				    void *priv)
 {
@@ -505,10 +519,13 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-	/* can't stop here..  if we get a bad obj, must tell the state
-	   machine that!
-	ASSERT( type == IAS_INTEGER, return;);
-	*/
+	/* Check if request succeeded */
+	if ( !value) {
+		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
+				       &info);
+		return;
+	}
 
 	if ( value->type == IAS_INTEGER && value->t.integer != -1) {
 	        info.dlsap_sel = value->t.integer;
@@ -518,11 +535,10 @@
 		       ": obj_id = %d, value = %d\n", 
 		       obj_id, value->t.integer);
 
-		irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, 
-				       NULL, &info);
+		irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, NULL, &info);
 	} else
-		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, 
-				       NULL, &info);
+		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
+				       &info);
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -536,9 +552,12 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
+	irda_notify_init( &lpt_notify);
+
 	lpt_notify.connect_confirm = irlpt_client_connect_confirm;
 	lpt_notify.disconnect_indication = irlpt_client_disconnect_indication;
 	lpt_notify.data_indication = irlpt_client_data_indication;
+	strcpy( lpt_notify.name, "IrLPT client");
 	lpt_notify.instance = self;
 
 	self->lsap = irlmp_open_lsap( LSAP_ANY, &lpt_notify);
@@ -549,17 +568,51 @@
 	        DEBUG( irlpt_client_debug, __FUNCTION__ 
 		       ": issue THREE_WIRE_RAW connect\n");
 		irlmp_connect_request( self->lsap, self->dlsap_sel, 
-				       self->daddr, NULL, NULL);
+				       self->saddr, self->daddr, NULL, NULL);
 	}
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
 
+static void irlpt_client_expired(unsigned long data)
+{
+	struct irlpt_cb *self = (struct irlpt_cb *) data;
+	struct sk_buff *skb;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+	DEBUG( irlpt_client_debug, __FUNCTION__
+	       ": removing irlpt_cb!\n");
+
+	ASSERT(self != NULL, return; );
+	ASSERT(self->magic == IRLPT_MAGIC, return;);
+
+	if (self->state == IRLPT_CLIENT_CONN) {
+		skb = dev_alloc_skb(64);
+		if (skb == NULL) {
+			DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
+			       "sk_buff of length %d\n", 64);
+			return;
+		}
+
+		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		irlmp_disconnect_request(self->lsap, skb);
+		DEBUG(irlpt_client_debug, __FUNCTION__
+		      ": irlmp_close_slap(self->lsap)\n");
+		irlmp_close_lsap(self->lsap);
+	}
+
+	irlpt_client_close(self);
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
 
 #ifdef MODULE
 
 MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT client protocol");
+MODULE_PARM(irlpt_client_debug,"1i");
+MODULE_PARM(irlpt_client_fsm_debug,"1i");
 
 /*
  * Function init_module (void)
@@ -570,11 +623,11 @@
 int init_module(void)
 {
 
-        DEBUG( irlpt_client_debug, "--> irlpt client: init_module\n");
+        DEBUG( irlpt_client_debug, "--> IrLPT client: init_module\n");
 
         irlpt_client_init();
 
-        DEBUG( irlpt_client_debug, "irlpt client: init_module -->\n");
+        DEBUG( irlpt_client_debug, "IrLPT client: init_module -->\n");
 
         return 0;
 }
@@ -587,13 +640,13 @@
  */
 void cleanup_module(void)
 {
-        DEBUG( irlpt_client_debug, "--> irlpt client: cleanup_module\n");
+        DEBUG( irlpt_client_debug, "--> IrLPT client: cleanup_module\n");
         /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 
         /* Free some memory */
         irlpt_client_cleanup();
 
-        DEBUG( irlpt_client_debug, "irlpt client: cleanup_module -->\n");
+        DEBUG( irlpt_client_debug, "IrLPT client: cleanup_module -->\n");
 }
 
 #endif /* MODULE */
diff -urN linux-2.2.3-pre2/net/irda/irlpt/irlpt_cli_fsm.c linux-2.2.3-pre3/net/irda/irlpt/irlpt_cli_fsm.c
--- linux-2.2.3-pre2/net/irda/irlpt/irlpt_cli_fsm.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlpt/irlpt_cli_fsm.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jan 12 11:06:00 1999
- * Modified at:   Tue Jan 12 11:14:22 1999
+ * Modified at:   Tue Jan 26 12:02:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
@@ -35,50 +35,53 @@
 static char *rcsid = "$Id: irlpt_client_fsm.c,v 1.3 1998/10/05 05:46:44 ratbert Exp $";
 #endif
 
-static int irlpt_client_state_idle  ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_idle  ( struct irlpt_cb *self, 
+				      IRLPT_EVENT event,
 				      struct sk_buff *skb, 
 				      struct irlpt_info *info);
-static int irlpt_client_state_query ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_query ( struct irlpt_cb *self, 
+				      IRLPT_EVENT event,
 				      struct sk_buff *skb, 
 				      struct irlpt_info *info);
 static int irlpt_client_state_ready  ( struct irlpt_cb *self, 
 				       IRLPT_EVENT event, 
 				       struct sk_buff *skb, 
 				       struct irlpt_info *info);
-static int irlpt_client_state_waiti ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_waiti ( struct irlpt_cb *self, 
+				      IRLPT_EVENT event,
 				      struct sk_buff *skb, 
 				      struct irlpt_info *info);
-static int irlpt_client_state_waitr ( struct irlpt_cb *self, IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_conn  ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_conn  ( struct irlpt_cb *self, 
+				      IRLPT_EVENT event,
 				      struct sk_buff *skb, 
 				      struct irlpt_info *info);
 
-int irlpt_client_fsm_debug = 3;
+int irlpt_client_fsm_debug = 4;
 
-int (*irlpt_client_state[])( struct irlpt_cb *self, IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) = 
+int (*irlpt_client_state[])( struct irlpt_cb *self, 
+			     IRLPT_EVENT event, 
+			     struct sk_buff *skb, 
+			     struct irlpt_info *info) = 
 { 
 	irlpt_client_state_idle,
 	irlpt_client_state_query,
 	irlpt_client_state_ready,
 	irlpt_client_state_waiti,
-	irlpt_client_state_waitr,
 	irlpt_client_state_conn,
 };
 
-void irlpt_client_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
-				   struct sk_buff *skb, 
-				   struct irlpt_info *info) 
+void irlpt_client_do_event( struct irlpt_cb *self, 
+			    IRLPT_EVENT event, 
+			    struct sk_buff *skb, 
+			    struct irlpt_info *info) 
 {
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ "\n");
+	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ "\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
+	DEBUG( irlpt_client_fsm_debug, 
+	       __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
 	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
 
 	(*irlpt_client_state[ self->state]) ( self, event, skb, info);
@@ -86,9 +89,10 @@
 	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
 }
 
-void irlpt_client_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+void irlpt_client_next_state( struct irlpt_cb *self, 
+			      IRLPT_CLIENT_STATE state) 
 {
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
@@ -102,16 +106,17 @@
 }
 
 /*
- * Function client_state_idle (event, skb, info)
+ * Function irlpt_client_state_idle (self, event, skb, info)
  *
  *    IDLE, We are waiting for an indication that there is a provider
  *    available.
  */
-static int irlpt_client_state_idle( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_idle( struct irlpt_cb *self, 
+				    IRLPT_EVENT event, 
 				    struct sk_buff *skb, 
 				    struct irlpt_info *info) 
 {
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
@@ -120,11 +125,13 @@
 	case IRLPT_DISCOVERY_INDICATION:
 		/* Get some values from peer IAS */
 		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": IRLPT_DISCOVERY_INDICATION, sending getvaluebyclass command..\n");
-		iriap_getvaluebyclass_request( info->daddr, 
-					"IrLPT", "IrDA:IrLMP:LsapSel",
-					irlpt_client_get_value_confirm,
-					(void *) self);
+		       ": IRLPT_DISCOVERY_INDICATION, "
+		       "sending getvaluebyclass command..\n");
+		iriap_getvaluebyclass_request( 
+			"IrLPT", "IrDA:IrLMP:LsapSel",
+			info->saddr, info->daddr,
+			irlpt_client_get_value_confirm,
+			(void *) self);
 		irlpt_client_next_state( self, IRLPT_CLIENT_QUERY);
 		break;
 
@@ -145,36 +152,53 @@
 }
 
 /*
- * Function client_state_query
+ * Function irlpt_client_state_query
  *
  *    QUERY, We have queryed the remote IAS and is ready to connect
  *    to provider, just waiting for the confirm.
  *
  */
-static int irlpt_client_state_query( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_query( struct irlpt_cb *self, 
+				     IRLPT_EVENT event, 
 				     struct sk_buff *skb, 
 				     struct irlpt_info *info) 
 {
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
 	switch( event) {
 	case IAS_PROVIDER_AVAIL:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": IAS_PROVIDER_AVAIL\n");
+		DEBUG( irlpt_client_fsm_debug, 
+		       __FUNCTION__ ": IAS_PROVIDER_AVAIL\n");
 		self->open_retries = 0;
 		irlpt_client_next_state( self, IRLPT_CLIENT_READY);
-		irlpt_client_do_event( self, IRLPT_CONNECT_REQUEST, NULL, NULL);
+		irlpt_client_do_event( self, IRLPT_CONNECT_REQUEST, 
+				       NULL, NULL);
 		break;
 
 	case IAS_PROVIDER_NOT_AVAIL:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": IAS_PROVIDER_NOT_AVAIL\n");
+		DEBUG( irlpt_client_fsm_debug, 
+		       __FUNCTION__ ": IAS_PROVIDER_NOT_AVAIL\n");
 		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+		      ": waking any sleepers..\n");
+		wake_up_interruptible(&self->read_wait);
 		break;
 
+	case LMP_DISCONNECT:
+	case LAP_DISCONNECT:
+	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
+		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+		      ": waking any sleepers..\n");
+		wake_up_interruptible(&self->read_wait);
+		break;
 	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": Unknown event %d (%s)\n",
+		DEBUG( irlpt_client_fsm_debug, 
+		       __FUNCTION__ ": Unknown event %d (%s)\n",
 		       event, irlpt_fsm_event[event]);
 		break;
 	}
@@ -189,11 +213,12 @@
 }
 
 /*
- * Function client_state_info 
+ * Function irlpt_client_state_info 
  *
  *    INFO, We have issued a GetInfo command and is awaiting a reply.
  */
-static int irlpt_client_state_ready( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_ready( struct irlpt_cb *self, 
+				     IRLPT_EVENT event,
 				     struct sk_buff *skb, 
 				     struct irlpt_info *info) 
 {
@@ -204,8 +229,8 @@
 
 	switch( event) {
 	case IRLPT_CONNECT_REQUEST:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": IRLPT_CONNECT_REQUEST\n");
+	        DEBUG( irlpt_client_fsm_debug, 
+		       __FUNCTION__ ": IRLPT_CONNECT_REQUEST\n");
 		irlpt_client_connect_request(self);
 		irlpt_client_next_state( self, IRLPT_CLIENT_WAITI);
 		break;
@@ -213,6 +238,9 @@
 	case LAP_DISCONNECT:
 	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
 		       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
+		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+		      ": waking any sleepers..\n");
+		wake_up_interruptible(&self->read_wait);
 		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
 		break;
 	default:
@@ -233,11 +261,12 @@
 
 
 /*
- * Function client_state_waiti 
+ * Function irlpt_client_state_waiti 
  *
  *
  */
-static int irlpt_client_state_waiti( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_waiti( struct irlpt_cb *self, 
+				     IRLPT_EVENT event, 
 				     struct sk_buff *skb, 
 				     struct irlpt_info *info) 
 {
@@ -250,10 +279,17 @@
 	case LMP_CONNECT:
 	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
 	        irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
+		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+		      ": waking any sleepers..\n");
+		wake_up_interruptible(&self->read_wait);
 	        break;
 	case LAP_DISCONNECT:
 	case LMP_DISCONNECT:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_DISCONNECT\n");
+	        DEBUG( irlpt_client_fsm_debug, 
+		       __FUNCTION__ ": LMP_DISCONNECT\n");
+		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+		      ": waking any sleepers..\n");
+		wake_up_interruptible(&self->read_wait);
 	        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
 	        break;
 
@@ -274,63 +310,18 @@
 }
 
 /*
- * Function client_state_waitr 
- *
- *
- */
-static int irlpt_client_state_waitr( struct irlpt_cb *self, IRLPT_EVENT event,
-				     struct sk_buff *skb, 
-				     struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case LMP_CONNECT:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
-		irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
-		break;
-
-	case LMP_DISCONNECT:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_DISCONNECT\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		break;
-
-	case LAP_DISCONNECT:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LAP_DISCONNECT\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		break;
-
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d, (%s)\n",
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function client_state_conn (event, skb, info)
+ * Function irlpt_client_state_conn (self, event, skb, info)
  *
  *    CONN, We have connected to a provider but has not issued any
  *    commands yet.
  *
  */
-static int irlpt_client_state_conn( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_conn( struct irlpt_cb *self, 
+				    IRLPT_EVENT event, 
 				    struct sk_buff *skb, 
 				    struct irlpt_info *info) 
 {
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+	DEBUG( irlpt_client_fsm_debug, "--> " __FUNCTION__ ":\n");
 
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
@@ -346,6 +337,10 @@
 	case LAP_DISCONNECT:
 		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
 		       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
+		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+		      ": waking any sleepers..\n");
+		wake_up_interruptible(&self->read_wait);
+	        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
 		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
 		break;
 
diff -urN linux-2.2.3-pre2/net/irda/irlpt/irlpt_common.c linux-2.2.3-pre3/net/irda/irlpt/irlpt_common.c
--- linux-2.2.3-pre2/net/irda/irlpt/irlpt_common.c	1999-01-24 21:55:05.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlpt/irlpt_common.c	2003-08-15 15:05:26.000000000 -0700
@@ -68,7 +68,7 @@
 
 char *irlpt_reasons[] = {
 	"SERVICE_CLOSE",     /* Service has closed the connection */
-	"DISC_INDICATION",   /* Received a disconnect request from peer entity*/
+	"DISC_INDICATION",   /* Received disconnect request from peer entity*/
 	"NO_RESPONSE",       /* To many retransmits without response */
 	"DEADLOCK_DETECTED", /* To many retransmits _with_ response */
 	"FOUND_NONE",        /* No devices were discovered */
@@ -81,7 +81,6 @@
 	"IRLPT_CLIENT_QUERY",
 	"IRLPT_CLIENT_READY",
 	"IRLPT_CLIENT_WAITI",
-	"IRLPT_CLIENT_WAITR",
 	"IRLPT_CLIENT_CONN"
 };
 
@@ -108,9 +107,8 @@
 hashbin_t *irlpt_clients = NULL;
 struct irlpt_cb *irlpt_server = NULL;
 int irlpt_common_debug = 4;  /* want to change this? please don't! 
-				use irlpt_common_debug=3 on the command line! */
-
-static struct wait_queue *irlpt_wait;
+				use irlpt_common_debug=3 on the 
+				command line! */
 
 #if 0
 static char *rcsid = "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
@@ -152,7 +150,6 @@
 	char *ptr = buffer;
 	struct irlpt_cb *self;
 	struct sk_buff *skb = NULL;
-	struct wait_queue wait = { current, NULL };
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -170,11 +167,12 @@
 		switch (self->eof) {
 		case LM_USER_REQUEST:
 			self->eof = FALSE;
-			DEBUG(3, "irlpt_read: returning 0\n");
+			DEBUG(irlpt_common_debug, 
+			      __FUNCTION__ ": returning 0\n");
 			return 0;
 		case LM_LAP_DISCONNECT:
 			self->eof = FALSE;
-			return -EIO;
+			return 0;
 		case LM_LAP_RESET:
 			self->eof = FALSE;
 			return -ECONNRESET;
@@ -208,11 +206,7 @@
 			       len, count, self->eof);
 
 			if (!signal_pending(current) && !self->eof) {
-			        add_wait_queue(&irlpt_wait, &wait);
-				current->state = TASK_INTERRUPTIBLE;
-				schedule();
-				current->state = TASK_RUNNING;
-				remove_wait_queue(&irlpt_wait, &wait);
+				interruptible_sleep_on(&self->read_wait);
 			} else
 				break;
 		}
@@ -228,7 +222,6 @@
 {
 	struct irlpt_cb *self;
 	struct sk_buff *skb;
-	struct wait_queue wait = { current, NULL };
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -240,26 +233,25 @@
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
 	       ": count = %d\n", count);
 
-	if (self->state != IRLPT_CLIENT_CONN) {
+	DEBUG( irlpt_common_debug, __FUNCTION__ 
+	       ": pkt_count = %d\n", self->pkt_count);
+	if (self->pkt_count > 8) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state != IRLPT_CONN (possible link problems?)\n");
-		return -ENOLINK;
+		       ": too many outstanding buffers, going to sleep\n");
+		interruptible_sleep_on(&self->write_wait);
 	}
 
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
 	       ": pkt_count = %d\n", self->pkt_count);
-	if (self->pkt_count > 8) {
+
+	if (self->state != IRLPT_CLIENT_CONN) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": too many outstanding buffers, going to sleep\n");
-		add_wait_queue(&self->write_wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&self->write_wait, &wait);
+		       ": state != IRLPT_CONN (possible link problems?)\n");
+		return -ENOLINK;
 	}
 
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ":count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
+	       ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
 		count, self->irlap_data_size, IRLPT_MAX_HEADER);
 
  	if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) {
@@ -272,7 +264,8 @@
 
 	skb = dev_alloc_skb(count + IRLPT_MAX_HEADER);
 	if ( skb == NULL) {
-		printk( KERN_INFO __FUNCTION__ ": couldn't allocate skbuff!\n");
+		printk( KERN_INFO 
+			__FUNCTION__ ": couldn't allocate skbuff!\n");
 		return 0;
 	}
 
@@ -292,6 +285,9 @@
 
 	irlmp_data_request(self->lsap, skb);
 
+	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
+			  self->timeout);
+
 	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 
 	return(count);
@@ -305,60 +301,13 @@
 	return -ESPIPE;
 }
 
-#if 0
-
-/*
- * Function irlpt_select (inode, filp, mode, table)
- *
- *    Implementation for the select() call
- *
- */
-int irlpt_select( struct inode *inode, struct file *filp, int mode, 
-			 select_table *table)
-{
-	struct irlpt_cb *self;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-	
-	self = irlpt_find_handle(MINOR( inode->i_rdev));
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch (mode) {
-	case SEL_IN:
-		if ( skb_queue_len( &self->rx_queue))
-			return 1; /* Readable */
-		select_wait( &self->read_wait, table);
-		break;
-	case SEL_OUT:
-		if ( self->connected)
-			return 1;
-		select_wait( &self->write_wait, table);
-		break;
-	case SEL_EX:
-		if ( self->connected)
-			return 1;
-		select_wait( &self->ex_wait, table);
-		break;
-	default:
-		break;
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-#else
-
 /*
- * Function irobex_poll (file, wait)
+ * Function irlpt_poll (file, wait)
  *
  *    
  *
  */
-static u_int irlpt_poll(struct file *file, poll_table *wait)
+u_int irlpt_poll(struct file *file, poll_table *wait)
 {
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -367,8 +316,6 @@
 	return 0;
 }
 
-#endif
-
 /*
  * Function open_irlpt (inode, file)
  *
@@ -378,6 +325,7 @@
 int irlpt_open(struct inode *inode, struct file *file)
 {
 	struct irlpt_cb *self;
+	struct irlpt_info info;
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -386,22 +334,6 @@
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-#if 0
-	if (self->state == IRLPT_IDLE) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state == IRLPT_IDLE! (no device found yet)\n");
-		return -ENODEV;
-	}
-
-	if (self->state == IRLPT_QUERY ||
-	    self->state == IRLPT_READY ||
-	    self->state == IRLPT_WAITI) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ ": state == IRLPT_QUERY, " 
-		       "IRLPT_READY or IRLPT_WAITI (link problems)!\n");
-		return -EBUSY;
-	}
-#endif
-
 	if (self->count++) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
 		       ": count not zero; actual = %d\n", self->count);
@@ -409,6 +341,35 @@
 		return -EBUSY;
 	}
 
+	self->eof = FALSE;
+
+	/* ok, now, if it's idle, try to get some information
+	   about the remote end, and sleep till we get totally connected.. */
+
+	if ((self->servicetype != IRLPT_SERVER_MODE) && 
+	    self->state != IRLPT_CLIENT_CONN) {
+		DEBUG(irlpt_common_debug, __FUNCTION__
+		      ": self->state != IRLPT_CLIENT_CONN\n");
+
+		info.daddr = self->daddr;
+		info.saddr = self->saddr;
+
+		if (self->do_event != NULL) {
+			DEBUG(irlpt_common_debug, __FUNCTION__ 
+			      ": doing a discovery..\n");
+			self->do_event( self, 
+					IRLPT_DISCOVERY_INDICATION, 
+					NULL, &info);
+			DEBUG(irlpt_common_debug, __FUNCTION__ 
+			      ": sleeping until connected.\n");
+			interruptible_sleep_on(&self->read_wait);
+		}
+	}
+
+	/* at this point, if it's a client, we have a connection.
+	 * if it's the server, it's waiting for a connection.
+	 */
+
 	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 
 	return 0;
@@ -420,9 +381,12 @@
  *
  *
  */
-int irlpt_close(struct inode *inode, struct file *file)
+int irlpt_close(struct inode *inode, 
+		struct file *file)
 {
 	struct irlpt_cb *self;
+	struct sk_buff *skb;
+	struct irlpt_info info;
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -433,12 +397,42 @@
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-	DEBUG(irlpt_common_debug, __FUNCTION__ ": self->count=%d\n", self->count);
+	DEBUG(irlpt_common_debug, 
+	      __FUNCTION__ ": self->count=%d\n", self->count);
+
 	if (self->count > 0)
 		self->count--;
 
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+	while (self->pkt_count > 0) {
+		interruptible_sleep_on(&self->write_wait);
+	}
 
+	/* all done, tear down the connection and wait for the next open */
+	if ((self->servicetype != IRLPT_SERVER_MODE) &&
+	    self->state == IRLPT_CLIENT_CONN) {
+		skb = dev_alloc_skb(64);
+		if (skb == NULL) {
+			DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
+			       "sk_buff of length %d\n", 64);
+			return 0;
+		}
+
+		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		irlmp_disconnect_request(self->lsap, skb);
+		DEBUG(irlpt_common_debug, __FUNCTION__
+		      ": irlmp_close_slap(self->lsap)\n");
+		irlmp_close_lsap(self->lsap);
+	}
+
+	info.daddr = self->daddr;
+
+	if (self->do_event != NULL) {
+	        DEBUG(irlpt_common_debug, __FUNCTION__ 
+		      ": closing connection..\n");
+		self->do_event( self, LMP_DISCONNECT, NULL, &info);
+	}
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 	return 0;
 }
 
@@ -486,6 +480,10 @@
 
 #ifdef MODULE
 
+MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT common");
+MODULE_PARM(irlpt_common_debug,"1i");
+
 /*
  * Function init_module (void)
  *
diff -urN linux-2.2.3-pre2/net/irda/irlpt/irlpt_srvr.c linux-2.2.3-pre3/net/irda/irlpt/irlpt_srvr.c
--- linux-2.2.3-pre2/net/irda/irlpt/irlpt_srvr.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlpt/irlpt_srvr.c	2003-08-15 15:05:26.000000000 -0700
@@ -49,31 +49,34 @@
 
 int irlpt_server_init(void);
 static void irlpt_server_cleanup(void);
-static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+static void irlpt_server_disconnect_indication( void *instance, 
+						void *sap, 
 						LM_REASON reason,
 						struct sk_buff *skb);
-static void irlpt_server_connect_confirm( void *instance, void *sap, 
+static void irlpt_server_connect_confirm( void *instance, 
+					  void *sap, 
 					  struct qos_info *qos,  
 					  int max_seg_size,
 					  struct sk_buff *skb);
-static void irlpt_server_connect_indication( void *instance, void *sap, 
+static void irlpt_server_connect_indication( void *instance, 
+					     void *sap, 
 					     struct qos_info *qos, 
 					     int max_seg_size,
 					     struct sk_buff *skb);
-static void irlpt_server_data_indication( void *instance, void *sap, 
+static void irlpt_server_data_indication( void *instance, 
+					  void *sap, 
 					  struct sk_buff *skb);
 static void register_irlpt_server(void);
 static void deregister_irlpt_server(void);
 
-static struct wait_queue *irlpt_server_wait;
-
 int irlpt_server_lsap = LSAP_IRLPT;
 int irlpt_server_debug = 4;
 
 #if 0
 static char *rcsid = "$Id: irlpt_server.c,v 1.9 1998/10/22 12:02:22 dagb Exp $";
 #endif
-static char *version = "IrLPT server, $Revision: 1.9 $/$Date: 1998/10/22 12:02:22 $ (Thomas Davis)";
+
+static char *version = "IrLPT server, v2 (Thomas Davis)";
 
 struct file_operations irlpt_fops = {
 	irlpt_seek,	/* seek */
@@ -96,7 +99,7 @@
 #ifdef CONFIG_PROC_FS
 
 /*
- * Function proc_irlpt_read (buf, start, offset, len, unused)
+ * Function irlpt_server_proc_read (buf, start, offset, len, unused)
  *
  *
  *
@@ -137,21 +140,19 @@
 			break;
 		}
 
-		len += sprintf(buf+len, "servicetype: %s\n", 
-			       irlpt_service_type[index]);
-		len += sprintf(buf+len, "porttype: %s\n", 
+		len += sprintf(buf+len, "servicetype: %s, porttype: %s\n",
+			       irlpt_service_type[index],
 			       irlpt_port_type[irlpt_server->porttype]);
-		len += sprintf(buf+len, "daddr: %d\n", 
-			       irlpt_server->daddr);
-		len += sprintf(buf+len, "state: %s\n", 
-			       irlpt_server_fsm_state[irlpt_server->state]);
-		len += sprintf(buf+len, "retries: %d\n", 
-			       irlpt_server->open_retries);
-		len += sprintf(buf+len, "peersap: %d\n", 
+		len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
+			       irlpt_server->saddr, irlpt_server->daddr);
+		len += sprintf(buf+len, "slsap: 0x%08x, dlsap: 0x%08x\n", 
+			       irlpt_server->slsap_sel, 
 			       irlpt_server->dlsap_sel);
-		len += sprintf(buf+len, "count: %d\n", 
+		len += sprintf(buf+len, "retries: %d, count: %d\n", 
+			       irlpt_server->open_retries,
 			       irlpt_server->count);
-		len += sprintf(buf+len, "rx_queue: %d\n", 
+		len += sprintf(buf+len, "fsm state: %s, rx queue depth: %d\n", 
+			       irlpt_server_fsm_state[irlpt_server->state],
 			       skb_queue_len(&irlpt_server->rx_queue));
 		len += sprintf(buf+len, "\n");
 	}
@@ -258,11 +259,14 @@
  * Function irlpt_disconnect_indication (handle)
  *
  */
-static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+static void irlpt_server_disconnect_indication( void *instance, 
+						void *sap, 
 						LM_REASON reason,
 						struct sk_buff *userdata)
 {
+#if 0
 	struct irlpt_info info;
+#endif
 	struct irlpt_cb *self;
 
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -272,17 +276,22 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
+#if 0
 	info.daddr = self->daddr;
+#endif
 
-	DEBUG( irlpt_server_debug, __FUNCTION__ ": reason=%d (%s), dlsap_sel=%d\n",
+	DEBUG( irlpt_server_debug, 
+	       __FUNCTION__ ": reason=%d (%s), dlsap_sel=%d\n",
 	       reason, irlpt_reasons[reason], self->dlsap_sel);
 
 	self->connected = IRLPT_DISCONNECTED;
 	self->eof = reason;
 
-        wake_up_interruptible(&irlpt_server_wait);
+        wake_up_interruptible(&self->read_wait);
+	wake_up_interruptible(&self->write_wait);
+	wake_up_interruptible(&self->ex_wait);
 
-	DEBUG( irlpt_server_debug, __FUNCTION__ ": skb_queue_len=%d\n",
+	DEBUG( irlpt_server_debug, __FUNCTION__ ": rx queue length: %d\n",
 	       skb_queue_len(&irlpt_server->rx_queue));
 
 	irlpt_server_do_event( self, LMP_DISCONNECT, NULL, NULL);
@@ -298,12 +307,12 @@
  *
  *    LSAP connection confirmed!
  */
-static void irlpt_server_connect_confirm( void *instance, void *sap, 
+static void irlpt_server_connect_confirm( void *instance, 
+					  void *sap, 
 					  struct qos_info *qos,
 					  int max_seg_size,
 					  struct sk_buff *skb)
 {
-	struct irlpt_info info;
 	struct irlpt_cb *self;
 
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -312,21 +321,6 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-	info.daddr = self->daddr;
-
-	/*
-	 *  Check if we have got some QoS parameters back! This should be the
-	 *  negotiated QoS for the link.
-	 */
-	if ( qos) {
-		DEBUG( irlpt_server_debug, __FUNCTION__ 
-		       ": IrLPT Negotiated BAUD_RATE: %02x\n", 
-		       qos->baud_rate.bits);			
-		DEBUG( irlpt_server_debug, __FUNCTION__ 
-		       ": IrLPT Negotiated BAUD_RATE: %d bps.\n", 
-		       qos->baud_rate.value);
-	}
-
 	self->connected = TRUE;
 
 	irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
@@ -338,19 +332,20 @@
  * Function irlpt_connect_indication (handle)
  *
  */
-static void irlpt_server_connect_indication( void *instance, void *sap, 
+static void irlpt_server_connect_indication( void *instance, 
+					     void *sap, 
 					     struct qos_info *qos, 
 					     int max_seg_size,
 					     struct sk_buff *skb)
 {
 	struct irlpt_cb *self;
 	struct irlpt_info info;
-	struct lsap_cb *lsap;
 
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
 
 	self = ( struct irlpt_cb *) instance;
-	lsap = (struct lsap_cb *) sap;
+
+	info.lsap  = (struct lsap_cb *) sap;
 	
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
@@ -358,8 +353,6 @@
 	self->connected = IRLPT_CONNECTED;
 	self->eof = FALSE;
 
-	info.lsap = lsap;
-
 	irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
 
 	if (skb) {
@@ -370,12 +363,13 @@
 }
 
 /*
- * Function irlpt_data_indication (handle, skb)
+ * Function irlpt_server_data_indication (handle, skb)
  *
  *    This function gets the data that is received on the data channel
  *
  */
-static void irlpt_server_data_indication( void *instance, void *sap, 
+static void irlpt_server_data_indication( void *instance, 
+					  void *sap, 
 					  struct sk_buff *skb) 
 {
 
@@ -397,7 +391,7 @@
 #endif
 	
 	skb_queue_tail(&self->rx_queue, skb);
-        wake_up_interruptible(&irlpt_server_wait);
+        wake_up_interruptible(&self->read_wait);
 
 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
 }
@@ -419,9 +413,8 @@
 	/*
 	 *  First register control TSAP
 	 */
-
 	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-		DEBUG( 0, "irlpt_register_server:, unable to obtain handle!\n");
+		DEBUG( 0, __FUNCTION__ ": unable to obtain handle!\n");
 		return;
 	}
 
@@ -432,12 +425,13 @@
 	notify.disconnect_indication = irlpt_server_disconnect_indication;
 	notify.data_indication = irlpt_server_data_indication;
 	notify.instance = irlpt_server;
-	strcpy(notify.name, "IrLPT");
+	strcpy(notify.name, "IrLPT server");
 
 	irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, &notify);
 
 	irlpt_server->connected = IRLPT_WAITING;
 	irlpt_server->service_LSAP = irlpt_server_lsap;
+	irlpt_server->slsap_sel = irlpt_server_lsap;
 
 	/* 
 	 *  Register with LM-IAS
@@ -461,35 +455,9 @@
  */
 static void deregister_irlpt_server(void)
 {
-#if 0
-	struct notify_t notify;
-#endif
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
 
-#if 0
-	/*
-	 *  First register control TSAP
-	 */
-
-	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-		DEBUG( 0, "irlpt_register_server:, unable to obtain handle!\n");
-		return;
-	}
-
-	irda_notify_init(&notify);
-
-	notify.connect_confirm = irlpt_server_connect_confirm;
-	notify.connect_indication = irlpt_server_connect_indication;
-	notify.disconnect_indication = irlpt_server_disconnect_indication;
-	notify.data_indication = irlpt_server_data_indication;
-	notify.instance = irlpt_server;
-	strcpy(notify.name, "IrLPT");
-
-	irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, &notify);
-
-	irlpt_server->connected = IRLPT_WAITING;
-	irlpt_server->service_LSAP = irlpt_server_lsap;
-#endif
+	irlpt_server->connected = IRLPT_DISCONNECTED;
 
 	/* 
 	 *  de-Register with LM-IAS
@@ -504,7 +472,9 @@
 #ifdef MODULE
 
 MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT server protocol");
+MODULE_PARM(irlpt_server_debug,"1i");
+MODULE_PARM(irlpt_server_fsm_debug, "1i");
 
 /*
  * Function init_module (void)
@@ -515,11 +485,11 @@
 int init_module(void)
 {
 
-        DEBUG( irlpt_server_debug, "--> irlpt server: init_module\n");
+        DEBUG( irlpt_server_debug, "--> IrLPT server: init_module\n");
 
         irlpt_server_init();
 
-        DEBUG( irlpt_server_debug, "irlpt server: init_module -->\n");
+        DEBUG( irlpt_server_debug, "IrLPT server: init_module -->\n");
 
         return 0;
 }
@@ -532,14 +502,14 @@
  */
 void cleanup_module(void)
 {
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-        DEBUG( 3, "--> irlpt server: cleanup_module\n");
+        DEBUG( irlpt_server_debug, "--> IrLPT server: cleanup_module\n");
+
         /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 
         /* Free some memory */
         irlpt_server_cleanup();
 
-        DEBUG( irlpt_server_debug, "irlpt server: cleanup_module -->\n");
+        DEBUG( irlpt_server_debug, "IrLPT server: cleanup_module -->\n");
 }
 
 #endif /* MODULE */
diff -urN linux-2.2.3-pre2/net/irda/irlpt/irlpt_srvr_fsm.c linux-2.2.3-pre3/net/irda/irlpt/irlpt_srvr_fsm.c
--- linux-2.2.3-pre2/net/irda/irlpt/irlpt_srvr_fsm.c	1999-01-24 21:55:05.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irlpt/irlpt_srvr_fsm.c	2003-08-15 15:05:26.000000000 -0700
@@ -4,8 +4,10 @@
  * Version:       0.1
  * Sources:       irlan_event.c
  * 
- *     Copyright (c) 1997, Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, All Rights Reserved.
+ *     Copyright (c) 1997, Dag Brattli <dagb@cs.uit.no>, 
+ *		All Rights Reserved.
+ *     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 
@@ -38,9 +40,10 @@
 static char *rcsid = "$Id: irlpt_server_fsm.c,v 1.4 1998/10/05 05:46:45 ratbert Exp $";
 #endif
 
-int irlpt_server_fsm_debug = 3;
+int irlpt_server_fsm_debug = 4; /* don't change this! */
 
-static int (*irlpt_server_state[])( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int (*irlpt_server_state[])( struct irlpt_cb *self, 
+				    IRLPT_EVENT event, 
 				    struct sk_buff *skb,
 				    struct irlpt_info *info) = 
 { 
@@ -48,10 +51,13 @@
 	irlpt_server_state_conn,
 };
 
-void irlpt_server_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
-			    struct sk_buff *skb, struct irlpt_info *info) 
+void irlpt_server_do_event( struct irlpt_cb *self, 
+			    IRLPT_EVENT event, 
+			    struct sk_buff *skb, 
+			    struct irlpt_info *info) 
 {
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
+	DEBUG( irlpt_server_fsm_debug, 
+	       __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
 	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
 
 	ASSERT( self != NULL, return;);
@@ -62,7 +68,8 @@
 	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
 }
 
-void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+void irlpt_server_next_state( struct irlpt_cb *self, 
+			      IRLPT_CLIENT_STATE state) 
 {
 
 	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
@@ -82,7 +89,8 @@
  *    IDLE, We are waiting for an indication that there is a provider
  *    available.
  */
-static int irlpt_server_state_idle( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_server_state_idle( struct irlpt_cb *self, 
+				    IRLPT_EVENT event, 
 				    struct sk_buff *skb, 
 				    struct irlpt_info *info) 
 {
@@ -96,10 +104,12 @@
 	switch( event) {
 	case LMP_CONNECT:
 		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": LM_CONNECT, remote lsap=%d\n", 
-		       info->dlsap_sel);
+		       ": LM_CONNECT, remote lsap: 0x%08x\n",
+		       info->lsap->dlsap_sel);
 
-		self->dlsap_sel = info->dlsap_sel;
+		self->dlsap_sel = info->lsap->dlsap_sel;
+		self->daddr = info->daddr;
+		self->saddr = info->saddr;
 
 		r_skb = dev_alloc_skb(64);
 		if (r_skb == NULL) { 
@@ -107,12 +117,9 @@
 				": can't allocate sk_buff of length 64\n");
 			return 0;
 		}
-		ALLOC_SKB_MAGIC(r_skb);
 		skb_reserve( r_skb, LMP_MAX_HEADER);
-		skb->len = 0;
 		irlmp_connect_response( self->lsap, r_skb);
 		irlpt_server_next_state( self, IRLPT_SERVER_CONN);
-
 		break;
 
 	default:
diff -urN linux-2.2.3-pre2/net/irda/irmod.c linux-2.2.3-pre3/net/irda/irmod.c
--- linux-2.2.3-pre2/net/irda/irmod.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irmod.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Tue Jan 19 23:34:18 1999
+ * Modified at:   Thu Feb 18 08:51:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -24,14 +24,28 @@
 
 #include <linux/config.h>
 #include <linux/module.h> 
+
 #include <linux/init.h>
-#include <asm/segment.h>
 #include <linux/poll.h>
+#include <asm/segment.h>
+
+#include <linux/proc_fs.h>
 
 #include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
+#ifdef CONFIG_IRDA_COMPRESSION
+#include <net/irda/irlap_comp.h>
+#endif /* CONFIG_IRDA_COMPRESSION */
 #include <net/irda/irlmp.h>
 #include <net/irda/iriap.h>
+#include <net/irda/irias_object.h>
 #include <net/irda/irttp.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/timer.h>
+
+extern struct proc_dir_entry proc_irda;
 
 struct irda_cb irda; /* One global instance */
 
@@ -57,15 +71,15 @@
 extern int irlpt_client_init(void);
 extern int irlpt_server_init(void);
 
-static int irda_open( struct inode * inode, struct file *file);
-static int irda_ioctl( struct inode *inode, struct file *filp, 
-			 unsigned int cmd, unsigned long arg);
-static int irda_close( struct inode *inode, struct file *file);
-static ssize_t irda_read( struct file *file, char *buffer, size_t count, 
-			    loff_t *noidea);
-static ssize_t irda_write( struct file *file, const char *buffer,
-			     size_t count, loff_t *noidea);
-static u_int irda_poll( struct file *file, poll_table *wait);
+static int irda_open(struct inode * inode, struct file *file);
+static int irda_ioctl(struct inode *inode, struct file *filp, 
+		      unsigned int cmd, unsigned long arg);
+static int irda_close(struct inode *inode, struct file *file);
+static ssize_t irda_read(struct file *file, char *buffer, size_t count, 
+			 loff_t *noidea);
+static ssize_t irda_write(struct file *file, const char *buffer,
+			  size_t count, loff_t *noidea);
+static u_int irda_poll(struct file *file, poll_table *wait);
 
 static struct file_operations irda_fops = {
 	NULL,	       /* seek */
@@ -82,13 +96,95 @@
 	NULL,          /* fasync */
 };
 
+/* IrTTP */
+EXPORT_SYMBOL(irttp_open_tsap);
+EXPORT_SYMBOL(irttp_close_tsap);
+EXPORT_SYMBOL(irttp_connect_response);
+EXPORT_SYMBOL(irttp_data_request);
+EXPORT_SYMBOL(irttp_disconnect_request);
+EXPORT_SYMBOL(irttp_flow_request);
+EXPORT_SYMBOL(irttp_connect_request);
+EXPORT_SYMBOL(irttp_udata_request);
+
+/* Main IrDA module */
+#ifdef CONFIG_IRDA_DEBUG
+EXPORT_SYMBOL(irda_debug);
+#endif
+EXPORT_SYMBOL(irda_notify_init);
+EXPORT_SYMBOL(irmanager_notify);
+EXPORT_SYMBOL(irda_lock);
+EXPORT_SYMBOL(proc_irda);
+
+/* IrIAP/IrIAS */
+EXPORT_SYMBOL(iriap_getvaluebyclass_request);
+EXPORT_SYMBOL(irias_object_change_attribute);
+EXPORT_SYMBOL(irias_add_integer_attrib);
+EXPORT_SYMBOL(irias_add_octseq_attrib);
+EXPORT_SYMBOL(irias_add_string_attrib);
+EXPORT_SYMBOL(irias_insert_object);
+EXPORT_SYMBOL(irias_new_object);
+EXPORT_SYMBOL(irias_delete_object);
+EXPORT_SYMBOL(irias_find_object);
+EXPORT_SYMBOL(irias_find_attrib);
+EXPORT_SYMBOL(irias_new_integer_value);
+EXPORT_SYMBOL(irias_new_string_value);
+EXPORT_SYMBOL(irias_new_octseq_value);
+
+/* IrLMP */
+EXPORT_SYMBOL(irlmp_discovery_request);
+EXPORT_SYMBOL(irlmp_register_layer);
+EXPORT_SYMBOL(irlmp_unregister_layer);
+EXPORT_SYMBOL(irlmp_data_request);
+EXPORT_SYMBOL(irlmp_open_lsap);
+EXPORT_SYMBOL(irlmp_close_lsap);
+EXPORT_SYMBOL(irlmp_connect_request);
+EXPORT_SYMBOL(irlmp_connect_response);
+EXPORT_SYMBOL(irlmp_disconnect_request);
+EXPORT_SYMBOL(irlmp_get_daddr);
+EXPORT_SYMBOL(irlmp_get_saddr);
+EXPORT_SYMBOL(lmp_reasons);
+
+/* Queue */
+EXPORT_SYMBOL(hashbin_find);
+EXPORT_SYMBOL(hashbin_new);
+EXPORT_SYMBOL(hashbin_insert);
+EXPORT_SYMBOL(hashbin_delete);
+EXPORT_SYMBOL(hashbin_remove);
+EXPORT_SYMBOL(hashbin_get_next);
+EXPORT_SYMBOL(hashbin_get_first);
+
+/* IrLAP */
+#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(async_wrap_skb);
+EXPORT_SYMBOL(async_unwrap_char);
+EXPORT_SYMBOL(irda_start_timer);
+EXPORT_SYMBOL(irda_get_mtt);
+EXPORT_SYMBOL(setup_dma);
+
+#ifdef CONFIG_IRTTY
+EXPORT_SYMBOL(irtty_set_dtr_rts);
+EXPORT_SYMBOL(irtty_register_dongle);
+EXPORT_SYMBOL(irtty_unregister_dongle);
+#endif
+
 __initfunc(int irda_init(void))
 {
-        printk( KERN_INFO "Linux Support for the IrDA (tm) protocols (Dag Brattli)\n");
+        printk(KERN_INFO "Linux-2.2 Support for the IrDA (tm) Protocols (Dag Brattli)\n");
 
-	irda_device_init();
-	irlap_init();
  	irlmp_init();
+	irlap_init();
+	irda_device_init();
+
 	iriap_init();
  	irttp_init();
 	
@@ -113,12 +209,6 @@
 #ifdef CONFIG_IRLAN
 	irlan_init();
 #endif
-#ifdef CONFIG_IRLAN_CLIENT
-	irlan_client_init();
-#endif
-#ifdef CONFIG_IRLAN_SERVER
-	irlan_server_init();
-#endif
 #ifdef CONFIG_IROBEX
 	irobex_init();
 #endif
@@ -135,9 +225,21 @@
 	irlpt_server_init();
 #endif
 
+#ifdef CONFIG_IRDA_COMPRESSION
+#ifdef CONFIG_IRDA_DEFLATE
+	irda_deflate_init();
+#endif /* CONFIG_IRDA_DEFLATE */
+#endif /* CONFIG_IRDA_COMPRESSION */
+
 	return 0;
 }
 
+/* 
+ * FIXME:
+ * This function should have been wrapped with #ifdef MODULE, but then
+ * irda_proto_cleanup() must be moved from af_irda.c to this file since
+ * that function must also be wrapped if this one is.
+ */
 void irda_cleanup(void)
 {
 	misc_deregister( &irda.dev);
@@ -168,10 +270,12 @@
  *    Lock variable. Returns false if the lock is already set.
  *    
  */
-inline int irda_lock( int *lock) {
-	if ( test_and_set_bit( 0, (void *) lock))  {
-             printk("Trying to lock, already locked variable!\n");
-	     return FALSE;
+inline int irda_lock(int *lock) 
+{
+	if (test_and_set_bit( 0, (void *) lock))  {
+		DEBUG(3, __FUNCTION__ 
+		      "(), Trying to lock, already locked variable!\n");
+		return FALSE;
         }  
 	return TRUE;
 }
@@ -182,8 +286,9 @@
  *    Unlock variable. Returns false if lock is already unlocked
  *
  */
-inline int irda_unlock( int *lock) {
-	if ( !test_and_clear_bit( 0, (void *) lock))  {
+inline int irda_unlock(int *lock) 
+{
+	if (!test_and_clear_bit(0, (void *) lock))  {
 		printk("Trying to unlock already unlocked variable!\n");
 		return FALSE;
         }
@@ -198,7 +303,6 @@
  */
 void irda_notify_init( struct notify_t *notify)
 {
-
 	notify->data_indication = NULL;
 	notify->udata_indication = NULL;
 	notify->connect_confirm = NULL;
@@ -402,9 +506,19 @@
 }
 
 #ifdef MODULE
+#ifdef CONFIG_PROC_FS
+void irda_proc_modcount(struct inode *inode, int fill)
+{
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+}
+#endif /* CONFIG_PROC_FS */
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); 
+MODULE_PARM(irda_debug, "1l");
 
 /*
  * Function init_module (void)
diff -urN linux-2.2.3-pre2/net/irda/irobex/irobex.c linux-2.2.3-pre3/net/irda/irobex/irobex.c
--- linux-2.2.3-pre2/net/irda/irobex/irobex.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irobex/irobex.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irobex.c
- * Version:       0.3
+ * Version:       0.4
  * Description:   Kernel side of the IrOBEX layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Jun 25 21:21:07 1998
- * Modified at:   Sat Jan 16 22:18:03 1999
+ * Modified at:   Mon Feb  8 09:05:01 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -46,6 +46,8 @@
  */
 struct irobex_cb *irobex;
 
+extern char *lmp_reasons[];
+
 char *irobex_state[] = {
 	"OBEX_IDLE",
 	"OBEX_DISCOVER",
@@ -54,10 +56,29 @@
 	"OBEX_DATA",
 };
 
-static int irobex_dev_open( struct inode * inode, struct file *file);
+static void   irobex_cleanup(void);
+/* static struct irobex_cb *irobex_open(void); */
+/* static void   irobex_close( struct irobex_cb *self); */
+
+static void irobex_data_indication( void *instance, void *sap, 
+				    struct sk_buff *skb);
+static void irobex_disconnect_indication( void *instance, void *sap, 
+					  LM_REASON reason, 
+					  struct sk_buff *skb);
+static void irobex_disconnect_request( struct irobex_cb *self);
+static int irobex_connect_request(struct irobex_cb *self);
+static void irobex_connect_confirm( void *instance, void *sap, 
+				    struct qos_info *qos,
+				    int max_sdu_size, struct sk_buff *skb);
+static void irobex_discovery_indication( DISCOVERY *discovery);
+static void irobex_flow_indication( void *instance, void *sap, 
+				    LOCAL_FLOW flow);
+static void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, 
+				     void *priv);
+static void irobex_register_server( struct irobex_cb *self);
 static int irobex_ioctl( struct inode *inode, struct file *filp, 
 			 unsigned int cmd, unsigned long arg);
-
+static int irobex_dev_open( struct inode * inode, struct file *file);
 static int irobex_dev_close( struct inode *inode, struct file *file);
 static ssize_t irobex_read( struct file *file, char *buffer, size_t count, 
 			    loff_t *noidea);
@@ -105,6 +126,7 @@
  */
 __initfunc(int irobex_init(void))
 {
+	struct irmanager_event mgr_event;
 	struct irobex_cb *self;
 
 	self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC);
@@ -134,6 +156,10 @@
 		
 	irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE, 
 			      irobex_discovery_indication);
+
+/* 	mgr_event.event = EVENT_IROBEX_INIT; */
+/* 	sprintf( mgr_event.devname, "%s", self->devname); */
+/* 	irmanager_notify( &mgr_event); */
 	
 	return 0;
 }
@@ -145,7 +171,7 @@
  *
  */
 #ifdef MODULE
-void irobex_cleanup(void)
+static void irobex_cleanup(void)
 {
 	struct sk_buff *skb;
 	struct irobex_cb *self;
@@ -163,6 +189,7 @@
 	irlmp_unregister_layer( S_OBEX, CLIENT | SERVER);
 
 	if ( self->tsap) {
+		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
 		irttp_close_tsap( self->tsap);
 		self->tsap = NULL;
 	}
@@ -207,8 +234,7 @@
   
 	DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, state=%s, eof=%d\n", 
 	       count, skb_queue_len( &self->rx_queue), 
-	       irobex_state[self->state], 
-	       self->eof);
+	       irobex_state[self->state], self->eof);
 
 	if ( self->state != OBEX_DATA) {
 		DEBUG( 0, __FUNCTION__ "(), link not connected yet!\n");
@@ -446,8 +472,8 @@
 
 	self = irobex;
 	
-	ASSERT( self != NULL, return -ENOTTY;);
-	ASSERT( self->magic = IROBEX_MAGIC, return -ENOTTY;);
+	ASSERT(self != NULL, return -ENOTTY;);
+	ASSERT(self->magic == IROBEX_MAGIC, return -ENOTTY;);
 	
 	if ( _IOC_TYPE(cmd) != IROBEX_IOC_MAGIC) 
 		return -EINVAL;
@@ -464,107 +490,11 @@
 	switch ( cmd) {
 	case IROBEX_IOCSCONNECT:
 		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
-		
-		/* Already connected? */
-		if ( self->state == OBEX_DATA) {
-			DEBUG( 0, __FUNCTION__ "(), already connected!\n");
-			return 0;
-		}
-		
-		/* Timeout after 15 secs. */
-		irobex_start_watchdog_timer( self, 1000);
-
-		/*
-		 * If we have discovered a remote device we
-		 * check if the discovery is still fresh. If not, we don't
-		 * trust the address.
-		 */
-		if ( self->daddr && ((jiffies - self->time_discovered) > 500))
-			self->daddr = 0;
-
-		/* 
-		 * Try to discover remote remote device if it has not been 
-		 * discovered yet. 
-		 */
-		if ( !self->daddr) {
-			self->state = OBEX_DISCOVER;
-			
-			irlmp_discovery_request( 8);
-			
-			/* Wait for discovery to complete */
-			interruptible_sleep_on( &self->write_wait);
-			del_timer( &self->watchdog_timer);
-		}
-		
-		/* Give up if we are unable to discover any remote devices */
-		if ( !self->daddr) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unable to discover any devices!\n");
-			return -ENOTTY;
-		}
-		
-		/* Need to find remote destination TSAP selector? */
-		if ( !self->dtsap_sel) {
-			DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
-			
-			self->state = OBEX_QUERY;
-			
-			/* Timeout after 5 secs. */
-			irobex_start_watchdog_timer( self, 500);
-			iriap_getvaluebyclass_request( 
-				self->daddr,
-				"OBEX", 
-				"IrDA:TinyTP:LsapSel",
-				irobex_get_value_confirm,
-				self);
-			
-			interruptible_sleep_on( &self->write_wait);
-			del_timer( &self->watchdog_timer);
-		}	
-		
-		if ( !self->dtsap_sel) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unable to query remote LM-IAS!\n");
-			return -ENOTTY;
-		}
-
-		self->state = OBEX_CONN;
-		
-		/* Timeout after 5 secs. */
-		irobex_start_watchdog_timer( self, 500);
-
-		irttp_connect_request( self->tsap, self->dtsap_sel, 
-				       self->daddr, NULL, SAR_DISABLE, 
-				       NULL);
-		
-		/* Go to sleep and wait for connection!  */
-		interruptible_sleep_on( &self->write_wait);
-		del_timer( &self->watchdog_timer);
-		
-		if ( self->state != OBEX_DATA) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unable to connect to remote device!\n");
-			return -ENOTTY;
-		}
-		
+		return irobex_connect_request( self);		
 		break;
 	case IROBEX_IOCSDISCONNECT:
 		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
-
-		if ( self->state != OBEX_DATA)
-			return 0;
-
-		irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
-
-		/* Reset values for this instance */
-		self->state = OBEX_IDLE;
-		self->eof = LM_USER_REQUEST;
-		self->daddr = 0;
-		self->dtsap_sel = 0;
-		self->rx_flow = FLOW_START;
-		self->tx_flow = FLOW_START;
-		
-		wake_up_interruptible( &self->read_wait);
+		irobex_disconnect_request( self);
 		break;
 	default:
 		return -EINVAL;
@@ -631,6 +561,7 @@
 
 	/* Close TSAP is its still there */
 	if ( self->tsap) {
+		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
 		irttp_close_tsap( self->tsap);
 		self->tsap = NULL;
 	}
@@ -658,11 +589,11 @@
  *    device it is, and which services it has.
  *
  */
-void irobex_discovery_indication( DISCOVERY *discovery) 
+static void irobex_discovery_indication( DISCOVERY *discovery)
 {
  	struct irobex_cb *self;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG( 0, __FUNCTION__ "()\n");
 	
 	self = irobex;
 
@@ -671,6 +602,7 @@
 
 	/* Remember address and time if was discovered */
 	self->daddr = discovery->daddr;
+	self->saddr = discovery->saddr;
 	self->time_discovered = jiffies;
 	
 	/* Wake up process if its waiting for device to be discovered */
@@ -678,18 +610,37 @@
 		wake_up_interruptible( &self->write_wait);
 }
 
+static void irobex_disconnect_request( struct irobex_cb *self)
+{
+	if ( self->state != OBEX_DATA)
+		return;
+	
+	irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
+	
+	/* Reset values for this instance */
+	self->state = OBEX_IDLE;
+	self->eof = LM_USER_REQUEST;
+	self->daddr = 0;
+	self->dtsap_sel = 0;
+	self->rx_flow = FLOW_START;
+	self->tx_flow = FLOW_START;
+		
+	wake_up_interruptible( &self->read_wait);
+}
+
 /*
  * Function irobex_disconnect_indication (handle, reason, priv)
  *
  *    Link has been disconnected
  *
  */
-void irobex_disconnect_indication( void *instance, void *sap, 
-				   LM_REASON reason, struct sk_buff *userdata)
+static void irobex_disconnect_indication( void *instance, void *sap, 
+					  LM_REASON reason, 
+					  struct sk_buff *userdata)
 {
 	struct irobex_cb *self;
 	
-	DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
+	DEBUG( 0, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 	
 	self = ( struct irobex_cb *) instance;
 	
@@ -712,14 +663,105 @@
 	        dev_kfree_skb( userdata);
 }
 
+int irobex_connect_request(struct irobex_cb *self)
+{
+	int count = 0;
+
+	/* Already connected? */
+	if ( self->state == OBEX_DATA) {
+		DEBUG( 0, __FUNCTION__ "(), already connected!\n");
+		return 0;
+	}
+	
+	/* Timeout after 15 secs. */
+	irobex_start_watchdog_timer( self, 1000);
+	
+	/*
+	 * If we have discovered a remote device we
+	 * check if the discovery is still fresh. If not, we don't
+	 * trust the address.
+	 */
+	if ( self->daddr && ((jiffies - self->time_discovered) > 1000)) {
+		DEBUG( 0, __FUNCTION__ "(), daddr is old <%d>!\n",
+		       jiffies - self->time_discovered);
+		self->daddr = 0;
+	}
+	
+	/* 
+	 * Try to discover remote remote device if it has not been 
+	 * discovered yet. 
+	 */
+	if ( !self->daddr) {
+		self->state = OBEX_DISCOVER;
+		
+		irlmp_discovery_request( 8);
+		
+		/* Wait for discovery to complete */
+		interruptible_sleep_on( &self->write_wait);
+		del_timer( &self->watchdog_timer);
+	}
+	
+	/* Give up if we are unable to discover any remote devices */
+	if ( !self->daddr) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to discover any devices!\n");
+		return -EHOSTUNREACH;
+	}
+	
+	/* Need to find remote destination TSAP selector? */
+	while ( !self->dtsap_sel) {
+		DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
+		
+		self->state = OBEX_QUERY;
+		
+		/* Timeout after 5 secs. */
+		irobex_start_watchdog_timer( self, 500);
+		iriap_getvaluebyclass_request( 
+			"OBEX", "IrDA:TinyTP:LsapSel",
+			self->saddr, self->daddr,
+			irobex_get_value_confirm,
+			self);
+		
+		interruptible_sleep_on( &self->write_wait);
+		del_timer( &self->watchdog_timer);
+		
+		/* Give up after a few tries */
+		if (( count++ > 2) && !self->dtsap_sel) {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Unable to query remote LM-IAS!\n");
+			return -ETIMEDOUT;
+		}
+	}
+	self->state = OBEX_CONN;
+	
+	/* Timeout after 5 secs. */
+	irobex_start_watchdog_timer( self, 500);
+	
+	irttp_connect_request( self->tsap, self->dtsap_sel, 
+			       self->saddr, self->daddr, NULL, SAR_DISABLE, 
+			       NULL);
+	
+	/* Go to sleep and wait for connection!  */
+	interruptible_sleep_on( &self->write_wait);
+	del_timer( &self->watchdog_timer);
+	
+	if ( self->state != OBEX_DATA) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to connect to remote device!\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
 /*
  * Function irobex_connect_confirm (instance, sap, qos, userdata)
  *
  *    Connection to peer IrOBEX layer established
  *
  */
-void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-			     int max_sdu_size, struct sk_buff *userdata)
+static void irobex_connect_confirm( void *instance, void *sap, 
+				    struct qos_info *qos,
+				    int max_sdu_size, struct sk_buff *userdata)
 {
 	struct irobex_cb *self;
 	
@@ -834,7 +876,8 @@
  *    This function gets the data that is received on the data channel
  *
  */
-void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb) 
+static void irobex_data_indication( void *instance, void *sap, 
+				    struct sk_buff *skb) 
 {
 
 	struct irobex_cb *self;
@@ -876,7 +919,8 @@
  *    
  *
  */
-void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow) 
+static void irobex_flow_indication( void *instance, void *sap, 
+				    LOCAL_FLOW flow) 
 {
 	struct irobex_cb *self;
 
@@ -908,8 +952,8 @@
  *    Got results from previous GetValueByClass request
  *
  */
-void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
-			       void *priv)
+static void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
+				      void *priv)
 {
 	struct irobex_cb *self;
 	
@@ -919,7 +963,14 @@
 	self = ( struct irobex_cb *) priv;
 	
 	if ( !self || self->magic != IROBEX_MAGIC) {
-		DEBUG( 0, "irobex_get_value_confirm: bad magic!\n");
+		DEBUG( 0, __FUNCTION__ "(), bad magic!\n");
+		return;
+	}
+
+	/* Check if request succeeded */
+	if ( !value) {
+		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+
 		return;
 	}
 
@@ -996,7 +1047,7 @@
  *    must register both a TSAP for control and data
  * 
  */
-void irobex_register_server( struct irobex_cb *self)
+static void irobex_register_server( struct irobex_cb *self)
 {
 	struct notify_t notify;
 	struct ias_object *obj;
diff -urN linux-2.2.3-pre2/net/irda/irproc.c linux-2.2.3-pre3/net/irda/irproc.c
--- linux-2.2.3-pre2/net/irda/irproc.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irproc.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Tue Dec 15 09:21:50 1998
+ * Modified at:   Thu Feb 11 15:23:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
@@ -31,27 +31,24 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp.h>
 
-static int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry);
+static int proc_irda_lookup(struct inode * dir, struct dentry *dentry);
 
 static int proc_irda_readdir(struct file *filp, void *dirent, 
  			     filldir_t filldir);
 
-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, 
-			    int unused);
-extern int irttp_proc_read( char *buf, char **start, off_t offset, int len, 
-			    int unused);
-extern int irias_proc_read( char *buf, char **start, off_t offset, int len,
- 			    int unused);
+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, 
+			   int unused);
+extern int irttp_proc_read(char *buf, char **start, off_t offset, int len, 
+			   int unused);
+extern int irias_proc_read(char *buf, char **start, off_t offset, int len,
+			   int unused);
 
-static int proc_discovery_read( char *buf, char **start, off_t offset, int len,
-				int unused);
-
-/* int proc_irda_readdir(struct inode *inode, struct file *filp, void *dirent,  */
-/* 		      filldir_t filldir); */
+static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
+			       int unused);
 
 enum irda_directory_inos {
 	PROC_IRDA_LAP = 1,
@@ -82,7 +79,7 @@
 struct inode_operations proc_irda_dir_inode_operations = {
         &proc_irda_dir_operations,   /* default net directory file-ops */
         NULL,                   /* create */
-	proc_irda_21x_lookup, 
+	proc_irda_lookup, 
         NULL,                   /* link */
         NULL,                   /* unlink */
         NULL,                   /* symlink */
@@ -186,13 +183,14 @@
  *
  */
 void irda_proc_register(void) {
-	proc_net_register( &proc_irda);
-	proc_register( &proc_irda, &proc_lap);
-	proc_register( &proc_irda, &proc_lmp);
-	proc_register( &proc_irda, &proc_ttp);
-	proc_register( &proc_irda, &proc_ias);
- 	proc_register( &proc_irda, &proc_irda_device); 
-	proc_register( &proc_irda, &proc_discovery);
+	proc_net_register(&proc_irda);
+	proc_irda.fill_inode = &irda_proc_modcount;
+	proc_register(&proc_irda, &proc_lap);
+	proc_register(&proc_irda, &proc_lmp);
+	proc_register(&proc_irda, &proc_ttp);
+	proc_register(&proc_irda, &proc_ias);
+ 	proc_register(&proc_irda, &proc_irda_device); 
+	proc_register(&proc_irda, &proc_discovery);
 }
 
 /*
@@ -202,22 +200,22 @@
  *
  */
 void irda_proc_unregister(void) {
-	proc_unregister( &proc_irda, proc_discovery.low_ino);
+	proc_unregister(&proc_irda, proc_discovery.low_ino);
  	proc_unregister(&proc_irda, proc_irda_device.low_ino);
-	proc_unregister( &proc_irda, proc_ias.low_ino);
-	proc_unregister( &proc_irda, proc_ttp.low_ino);
-	proc_unregister( &proc_irda, proc_lmp.low_ino);
-	proc_unregister( &proc_irda, proc_lap.low_ino);
-	proc_unregister( proc_net, proc_irda.low_ino);
+	proc_unregister(&proc_irda, proc_ias.low_ino);
+	proc_unregister(&proc_irda, proc_ttp.low_ino);
+	proc_unregister(&proc_irda, proc_lmp.low_ino);
+	proc_unregister(&proc_irda, proc_lap.low_ino);
+	proc_unregister(proc_net, proc_irda.low_ino);
 }
 
 /*
- * Function proc_irda_21x_lookup (dir, dentry)
+ * Function proc_irda_lookup (dir, dentry)
  *
- *    This is a copy of proc_lookup from the linux-2.1.x 
+ *    This is a copy of proc_lookup from the linux-2.2.x kernel
  *
  */
-int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry)
+int proc_irda_lookup(struct inode * dir, struct dentry *dentry)
 {
 	struct inode *inode;
 	struct proc_dir_entry * de;
@@ -261,8 +259,8 @@
  *    to the irda module
  * 
  */
-static int proc_irda_readdir( struct file *filp, void *dirent, 
-			      filldir_t filldir)
+static int proc_irda_readdir(struct file *filp, void *dirent, 
+			     filldir_t filldir)
 {
 	struct proc_dir_entry * de;
 	unsigned int ino;
@@ -319,8 +317,8 @@
  *    Print discovery information in /proc file system
  *
  */
-int proc_discovery_read( char *buf, char **start, off_t offset, int len, 
-			 int unused)
+int proc_discovery_read(char *buf, char **start, off_t offset, int len, 
+			int unused)
 {
 	DISCOVERY *discovery;
 	struct lap_cb *lap;
diff -urN linux-2.2.3-pre2/net/irda/irqueue.c linux-2.2.3-pre3/net/irda/irqueue.c
--- linux-2.2.3-pre2/net/irda/irqueue.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irqueue.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Wed Jan 13 21:21:22 1999
+ * Modified at:   Mon Feb  8 09:05:51 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
@@ -55,6 +55,8 @@
 	 * Allocate new hashbin
 	 */
 	hashbin = kmalloc( sizeof(hashbin_t), GFP_ATOMIC);
+	if (!hashbin)
+		return NULL;
 
 	/*
 	 * Initialize structure
@@ -205,13 +207,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* entry, __u32 hashv, char* name)
 {
 	unsigned long flags = 0;
 	int bin;
 
-	DEBUG( 4, "hashbin_insert()\n");
+	DEBUG( 4, __FUNCTION__"()\n");
 
 	ASSERT( hashbin != NULL, return;);
 	ASSERT( hashbin->magic == HB_MAGIC, return;);
@@ -583,7 +584,7 @@
 void enqueue_first(QUEUE **queue, QUEUE* element)
 {
 	
-	DEBUG( 4, "enqueue_first()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
 
 	/*
 	 * Check if queue is empty.
diff -urN linux-2.2.3-pre2/net/irda/irsysctl.c linux-2.2.3-pre3/net/irda/irsysctl.c
--- linux-2.2.3-pre2/net/irda/irsysctl.c	1999-01-24 21:55:05.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irsysctl.c	2003-08-15 15:05:26.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 24 22:12:06 1998
- * Modified at:   Thu Jan  7 10:35:02 1999
+ * Modified at:   Mon Jan 25 13:55:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -31,9 +31,11 @@
 #include <net/irda/irda.h>
 
 #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG };
+enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG, SLOTS, SLOT_TIMEOUT };
 
 extern int sysctl_discovery;
+extern int sysctl_discovery_slots;
+extern int sysctl_slot_timeout;
 int sysctl_compression = 0;
 extern char sysctl_devname[];
 
@@ -53,6 +55,10 @@
 	{ DEBUG, "debug", &irda_debug,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
 #endif
+	{ SLOTS, "discovery_slots", &sysctl_discovery_slots,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
+	{ SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
 	{ 0 }
 };
 
diff -urN linux-2.2.3-pre2/net/irda/irttp.c linux-2.2.3-pre3/net/irda/irttp.c
--- linux-2.2.3-pre2/net/irda/irttp.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/irttp.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irttp.c
- * Version:       0.4
+ * Version:       1.0
  * Description:   Tiny Transport Protocol (TTP) implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Tue Jan 19 23:56:58 1999
+ * Modified at:   Sat Feb 20 01:30:39 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -35,26 +35,26 @@
 
 struct irttp_cb *irttp = NULL;
 
-static void __irttp_close_tsap( struct tsap_cb *self);
+static void __irttp_close_tsap(struct tsap_cb *self);
 
-static void irttp_data_indication( void *instance, void *sap, 
+static void irttp_data_indication(void *instance, void *sap, 
+				  struct sk_buff *skb);
+static void irttp_udata_indication(void *instance, void *sap, 
 				   struct sk_buff *skb);
-static void irttp_udata_indication( void *instance, void *sap, 
-				    struct sk_buff *skb);
-static void irttp_disconnect_indication( void *instance, void *sap,  
-					 LM_REASON reason,
-					 struct sk_buff *);
-static void irttp_connect_indication( void *instance, void *sap, 
-				      struct qos_info *qos, int max_sdu_size,
-				      struct sk_buff *skb);
-
-static void irttp_run_tx_queue( struct tsap_cb *self);
-static void irttp_run_rx_queue( struct tsap_cb *self);
-
-static void irttp_flush_queues( struct tsap_cb *self);
-static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb);
-static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self);
-static void irttp_start_todo_timer( struct tsap_cb *self, int timeout);
+static void irttp_disconnect_indication(void *instance, void *sap,  
+					LM_REASON reason,
+					struct sk_buff *);
+static void irttp_connect_indication(void *instance, void *sap, 
+				     struct qos_info *qos, int max_sdu_size,
+				     struct sk_buff *skb);
+
+static void irttp_run_tx_queue(struct tsap_cb *self);
+static void irttp_run_rx_queue(struct tsap_cb *self);
+
+static void irttp_flush_queues(struct tsap_cb *self);
+static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
+static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
 
 /*
  * Function irttp_init (void)
@@ -64,21 +64,19 @@
  */
 __initfunc(int irttp_init(void))
 {
-	DEBUG( 4, "--> irttp_init\n");
-
 	/* Initialize the irttp structure. */
-	if ( irttp == NULL) {
-		irttp = kmalloc( sizeof(struct irttp_cb), GFP_KERNEL);
-		if ( irttp == NULL)
+	if (irttp == NULL) {
+		irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
+		if (irttp == NULL)
 			return -ENOMEM;
 	}
-	memset( irttp, 0, sizeof(struct irttp_cb));
-
+	memset(irttp, 0, sizeof(struct irttp_cb));
+	
 	irttp->magic = TTP_MAGIC;
 
-	irttp->tsaps = hashbin_new( HB_LOCAL);
-	if ( !irttp->tsaps) {
-		printk( KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
+	irttp->tsaps = hashbin_new(HB_LOCAL);
+	if (!irttp->tsaps) {
+		printk(KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
 		return -ENOMEM;
 	}
 	
@@ -91,69 +89,69 @@
  *    Called by module destruction/cleanup code
  *
  */
+#ifdef MODULE
 void irttp_cleanup(void) 
 {
-	DEBUG( 4, "irttp_cleanup\n");
-	
 	/* Check for main structure */
-	ASSERT( irttp != NULL, return;);
-	ASSERT( irttp->magic == TTP_MAGIC, return;);
+	ASSERT(irttp != NULL, return;);
+	ASSERT(irttp->magic == TTP_MAGIC, return;);
 	
 	/*
 	 *  Delete hashbin and close all TSAP instances in it
 	 */
-	hashbin_delete( irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
+	hashbin_delete(irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
 
-	irttp->magic = ~TTP_MAGIC;
+	irttp->magic = 0;
 	
 	/* De-allocate main structure */
-	kfree( irttp);
+	kfree(irttp);
 
 	irttp = NULL;
 }
+#endif
 
 /*
  * Function irttp_open_tsap (stsap, notify)
  *
  *    Create TSAP connection endpoint,
  */
-struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit, 
-				 struct notify_t *notify) 
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
+				struct notify_t *notify) 
 {
 	struct notify_t ttp_notify;
 	struct tsap_cb *self;
 	struct lsap_cb *lsap;
 
-	ASSERT( irttp != NULL, return NULL;);
-	ASSERT( irttp->magic == TTP_MAGIC, return NULL;);
+	ASSERT(irttp != NULL, return NULL;);
+	ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
 
-	self = kmalloc( sizeof(struct tsap_cb), GFP_ATOMIC);
-	if ( self == NULL) {
-		printk( KERN_ERR "IrTTP: Can't allocate memory for "
+	self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+	if (self == NULL) {
+		printk(KERN_ERR "IrTTP: Can't allocate memory for "
 			"TSAP control block!\n");
 		return NULL;
 	}
-	memset( self, 0, sizeof(struct tsap_cb));
+	memset(self, 0, sizeof(struct tsap_cb));
 
-	init_timer( &self->todo_timer);
+	init_timer(&self->todo_timer);
 
 	/* Initialize callbacks for IrLMP to use */
 
-	irda_notify_init( &ttp_notify);
+	irda_notify_init(&ttp_notify);
 	ttp_notify.connect_confirm = irttp_connect_confirm;
 	ttp_notify.connect_indication = irttp_connect_indication;
 	ttp_notify.disconnect_indication = irttp_disconnect_indication;
 	ttp_notify.data_indication = irttp_data_indication;
 	ttp_notify.udata_indication = irttp_udata_indication;
 	ttp_notify.instance = self;
-	strncpy( ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
+	strncpy(ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
 
 	/*
 	 *  Create LSAP at IrLMP layer
 	 */
-	lsap = irlmp_open_lsap( stsap_sel, &ttp_notify);
-	if ( lsap == NULL) {
-		printk( KERN_ERR "IrTTP, Unable to get LSAP!!\n");
+	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
+	if (lsap == NULL) {
+		printk(KERN_ERR "IrTTP, Unable to get LSAP!!\n");
 		return NULL;
 	}
 	
@@ -163,22 +161,23 @@
 	 *  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);
+	DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
 
 	self->notify = *notify;
 	self->lsap = lsap;
 	self->magic = TTP_TSAP_MAGIC;
+	self->connected = FALSE;
 
-	skb_queue_head_init( &self->rx_queue);
-	skb_queue_head_init( &self->tx_queue);
-	skb_queue_head_init( &self->rx_fragments);
+	skb_queue_head_init(&self->rx_queue);
+	skb_queue_head_init(&self->tx_queue);
+	skb_queue_head_init(&self->rx_fragments);
 
 	/*
 	 *  Insert ourself into the hashbin
 	 */
-	hashbin_insert( irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
+	hashbin_insert(irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
 
-	if ( credit > TTP_MAX_QUEUE)
+	if (credit > TTP_MAX_QUEUE)
 		self->initial_credit = TTP_MAX_QUEUE;
 	else
 		self->initial_credit = credit;
@@ -193,27 +192,22 @@
  *    deallocation of the TSAP, and resetting of the TSAPs values;
  *
  */
-static void __irttp_close_tsap( struct tsap_cb *self)
+static void __irttp_close_tsap(struct tsap_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	/* First make sure we're connected. */
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	irttp_flush_queues( self);
+	irttp_flush_queues(self);
 
-	del_timer( &self->todo_timer);
+	del_timer(&self->todo_timer);
 
 	self->connected = FALSE;
 	self->magic = ~TTP_TSAP_MAGIC;
 
-	/*
-	 *  Deallocate structure
-	 */
-	kfree( self);
-
-	DEBUG( 4, "irttp_close_tsap() -->\n");
+	kfree(self);
 }
 
 /*
@@ -223,24 +217,41 @@
  *    associated with this TSAP
  *
  */
-void irttp_close_tsap( struct tsap_cb *self)
+int irttp_close_tsap(struct tsap_cb *self)
 {
 	struct tsap_cb *tsap;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	tsap = hashbin_remove( irttp->tsaps, self->stsap_sel, NULL);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
-	ASSERT( tsap == self, return;);
+	/* Make sure tsap has been disconnected */
+	if (self->connected) {
+		/* Check if disconnect is not pending */
+		if (!self->disconnect_pend) {
+			DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+			irttp_disconnect_request(self, NULL, P_NORMAL);
+		}
+		self->close_pend = TRUE;
+		irttp_start_todo_timer(self, 100);
+
+		return 0; /* Will be back! */
+	}
+	
+	tsap = hashbin_remove(irttp->tsaps, self->stsap_sel, NULL);
+
+	ASSERT(tsap == self, return -1;);
 
 	/* Close corresponding LSAP */
-	if ( self->lsap) {
-		irlmp_close_lsap( self->lsap);
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
 		self->lsap = NULL;
 	}
 
-	__irttp_close_tsap( self);
+	__irttp_close_tsap(self);
+
+	return 0;
 }
 
 /*
@@ -249,26 +260,26 @@
  *    Send unreliable data on this TSAP
  *
  */
-int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb) 
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb) 
 {
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
-	ASSERT( skb != NULL, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Check that nothing bad happens */
-	if (( skb->len == 0) || ( !self->connected)) {
-		DEBUG( 0, __FUNCTION__ "(), No data, or not connected\n");
+	if ((skb->len == 0) || (!self->connected)) {
+		DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
 		return -1;
 	}
 	
-	if ( skb->len > self->max_seg_size) {
-		DEBUG( 0, __FUNCTION__ "(), UData is to large for IrLAP!\n");
+	if (skb->len > self->max_seg_size) {
+		DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
 		return -1;
 	}
 		    
-	irlmp_udata_request( self->lsap, skb);
+	irlmp_udata_request(self->lsap, skb);
 	self->stats.tx_packets++;
 
 	return 0;
@@ -280,19 +291,19 @@
  *    Queue frame for transmission. If SAR is enabled, fragement the frame 
  *    and queue the fragments for transmission
  */
-int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb) 
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb) 
 {
 	__u8 *frame;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
-	ASSERT( skb != NULL, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
 
 	/* Check that nothing bad happens */
-	if (( skb->len == 0) || ( !self->connected)) {
-		DEBUG( 4, __FUNCTION__ "(), No data, or not connected\n");
+	if ((skb->len == 0) || (!self->connected)) {
+		DEBUG(4, __FUNCTION__ "(), No data, or not connected\n");
 		return -1;
 	}
 
@@ -300,10 +311,8 @@
 	 *  Check if SAR is disabled, and the frame is larger than what fits
 	 *  inside an IrLAP frame
 	 */
-	if (( self->tx_max_sdu_size == 0) && 
-	    ( skb->len > self->max_seg_size)) 
-	{
-		DEBUG( 0, __FUNCTION__ 
+	if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
+		DEBUG(1, __FUNCTION__ 
 		       "(), SAR disabled, and data is to large for IrLAP!\n");
 		return -1;
 	}
@@ -312,34 +321,33 @@
 	 *  Check if SAR is enabled, and the frame is larger than the 
 	 *  TxMaxSduSize 
 	 */
-	if (( self->tx_max_sdu_size != 0) && 
+	if ((self->tx_max_sdu_size != 0) && 
 	    (skb->len > self->tx_max_sdu_size))
 	{
-		DEBUG( 0, __FUNCTION__ "(), SAR enabled, "
+		DEBUG(1, __FUNCTION__ "(), SAR enabled, "
 		       "but data is larger than TxMaxSduSize!\n");
 		return -1;
 	}
 	/* 
 	 *  Check if transmit queue is full
 	 */
-	if ( skb_queue_len( &self->tx_queue) >= TTP_MAX_QUEUE) {
+	if (skb_queue_len(&self->tx_queue) >= TTP_MAX_QUEUE) {
 		/*
 		 *  Give it a chance to empty itself
 		 */
-		irttp_run_tx_queue( self);
+		irttp_run_tx_queue(self);
 		
 		return -1;
 	}
        
 	/* Queue frame, or queue frame segments */
-	if (( self->tx_max_sdu_size == 0) || 
-	    ( skb->len < self->max_seg_size)) {
+	if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
 		/* Queue frame */
-		frame = skb_push( skb, TTP_HEADER);
+		frame = skb_push(skb, TTP_HEADER);
 		frame[0] = 0x00; /* Clear more bit */
 		
-		DEBUG( 4, __FUNCTION__ "(), queueing original skb\n");
-		skb_queue_tail( &self->tx_queue, skb);
+		DEBUG(4, __FUNCTION__ "(), queueing original skb\n");
+		skb_queue_tail(&self->tx_queue, skb);
 	} else {
 		/*
 		 *  Fragment the frame, this function will also queue the
@@ -347,25 +355,24 @@
 		 *  queue may be overfilled by all the segments for a little
 		 *  while
 		 */
-		irttp_fragment_skb( self, skb);
+		irttp_fragment_skb(self, skb);
 	}
 
 	/* Check if we can accept more data from client */
-	if (( !self->tx_sdu_busy) && 
-	    ( skb_queue_len( &self->tx_queue) > HIGH_THRESHOLD)) {
+	if ((!self->tx_sdu_busy) && 
+	    (skb_queue_len(&self->tx_queue) > HIGH_THRESHOLD)) {
 		
 		/* Tx queue filling up, so stop client */
 		self->tx_sdu_busy = TRUE;
 		
-	 	if ( self->notify.flow_indication) {
- 			self->notify.flow_indication( self->notify.instance, 
-						      self, 
-						      FLOW_STOP);
+	 	if (self->notify.flow_indication) {
+ 			self->notify.flow_indication(
+				self->notify.instance, self, FLOW_STOP);
 		}
  	}
 	
 	/* Try to make some progress */
-	irttp_run_tx_queue( self);
+	irttp_run_tx_queue(self);
 	
 	return 0;
 }
@@ -376,40 +383,40 @@
  *    If possible, transmit a frame queued for transmission.
  *
  */
-static void irttp_run_tx_queue( struct tsap_cb *self) 
+static void irttp_run_tx_queue(struct tsap_cb *self) 
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
 	__u8 *frame;
 	int n;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-
-	if ( irda_lock( &self->tx_queue_lock) == FALSE)
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	
+	if (irda_lock(&self->tx_queue_lock) == FALSE)
 		return;
 
-	while (( self->send_credit > 0) && !skb_queue_empty( &self->tx_queue)){
+	while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)){
 
-		skb = skb_dequeue( &self->tx_queue);
-		ASSERT( skb != NULL, return;);
+		skb = skb_dequeue(&self->tx_queue);
+		ASSERT(skb != NULL, return;);
 		
 		/* Make room for TTP header */
-		ASSERT( skb_headroom( skb) >= TTP_HEADER, return;);
+		ASSERT(skb_headroom(skb) >= TTP_HEADER, return;);
 				
 		/*
 		 *  Since we can transmit and receive frames concurrently, 
 		 *  the code below is a critical region and we must assure that
 		 *  nobody messes with the credits while we update them.
 		 */
-		save_flags( flags); 
+		save_flags(flags); 
 		cli();
 
 		n = self->avail_credit;
 		self->avail_credit = 0;
 		
 		/* Only space for 127 credits in frame */
-		if ( n > 127) {
+		if (n > 127) {
 			self->avail_credit = n-127;
 			n = 127;
 		}
@@ -418,7 +425,7 @@
 
 		restore_flags(flags);
 
-		DEBUG( 4, "irttp_xmit: Giving away %d credits\n", n);
+		DEBUG(4, "irttp_xmit: Giving away %d credits\n", n);
 		
 		/* 
 		 *  More bit must be set by the data_request() or fragment() 
@@ -426,38 +433,27 @@
 		 */
 		frame = skb->data;
 
-		DEBUG( 4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
+		DEBUG(4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
 		       "TRUE" : "FALSE" );
 
 		frame[0] |= (__u8) (n & 0x7f);
 		
-		irlmp_data_request( self->lsap, skb);
+		irlmp_data_request(self->lsap, skb);
 		self->stats.tx_packets++;
 
 		/* Check if we can accept more frames from client */
-		if (( self->tx_sdu_busy) && 
-		    ( skb_queue_len( &self->tx_queue) < LOW_THRESHOLD)) { 
+		if ((self->tx_sdu_busy) && 
+		    (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD)) { 
 			self->tx_sdu_busy = FALSE;
 			
-			if ( self->notify.flow_indication)
-				self->notify.flow_indication( self->notify.instance, 
-							      self, 
-							      FLOW_START);
+			if (self->notify.flow_indication)
+				self->notify.flow_indication(
+				      self->notify.instance, self, FLOW_START);
 		}
 	}
 	
 	/* Reset lock */
 	self->tx_queue_lock = 0;
-
-	/* Check if there is any disconnect request pending */
-	if ( self->disconnect_pend) {
-		if ( self->disconnect_skb) {
-			irttp_disconnect_request( self, self->disconnect_skb,
-						  P_NORMAL);
-			self->disconnect_skb = NULL;
-		} else
-			irttp_disconnect_request( self, NULL, P_NORMAL);
-	}
 }
 
 /*
@@ -466,42 +462,39 @@
  *    Send a dataless flowdata TTP-PDU and give available credit to peer
  *    TSAP
  */
-void irttp_give_credit( struct tsap_cb *self) 
+void irttp_give_credit(struct tsap_cb *self) 
 {
 	struct sk_buff *tx_skb = NULL;
 	unsigned long flags;
 	int n;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	
 
-	DEBUG( 4, "irttp_give_credit() send=%d,avail=%d,remote=%d\n", 
+	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
 	       self->send_credit, self->avail_credit, self->remote_credit);
 	
 	/* Give credit to peer */
-	tx_skb = dev_alloc_skb( 64);
-	if ( tx_skb == NULL) {
-		DEBUG( 0, "irttp_give_credit: "
-		       "Could not allocate an sk_buff of length %d\n", 64);
+	tx_skb = dev_alloc_skb(64);
+	if (!tx_skb)
 		return;
-	}
 
 	/* Reserve space for LMP, and LAP header */
-	skb_reserve( tx_skb, LMP_HEADER+LAP_HEADER);
+	skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER);
 
 	/*
 	 *  Since we can transmit and receive frames concurrently, 
 	 *  the code below is a critical region and we must assure that
 	 *  nobody messes with the credits while we update them.
 	 */
-	save_flags( flags);
+	save_flags(flags);
 	cli();
 
 	n = self->avail_credit;
 	self->avail_credit = 0;
 	
 	/* Only space for 127 credits in frame */
-	if ( n > 127) {
+	if (n > 127) {
 		self->avail_credit = n - 127;
 		n = 127;
 	}
@@ -509,10 +502,10 @@
 
 	restore_flags(flags);
 
-	skb_put( tx_skb, 1);
-	tx_skb->data[0] = (__u8) ( n & 0x7f);
+	skb_put(tx_skb, 1);
+	tx_skb->data[0] = (__u8) (n & 0x7f);
 	
-	irlmp_data_request( self->lsap, tx_skb);
+	irlmp_data_request(self->lsap, tx_skb);
 	self->stats.tx_packets++;
 }
 
@@ -522,22 +515,21 @@
  *    
  *
  */
-void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb) 
+void irttp_udata_indication(void *instance, void *sap, struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	/* Just pass data to layer above */
-	if ( self->notify.udata_indication) {
-		self->notify.udata_indication( self->notify.instance, self, 
-					       skb);
+	if (self->notify.udata_indication) {
+		self->notify.udata_indication(self->notify.instance, self, skb);
 	}
 	self->stats.rx_packets++;
 }
@@ -548,7 +540,7 @@
  *    Receive segment from IrLMP. 
  *
  */
-void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
+void irttp_data_indication(void *instance, void *sap, struct sk_buff *skb)
 {
 	struct tsap_cb *self;
 	int more;
@@ -557,16 +549,16 @@
 	
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	frame = skb->data;
 	
 	n = frame[0] & 0x7f;     /* Extract the credits */
 	more = frame[0] & 0x80;
 
- 	DEBUG( 4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", 
+ 	DEBUG(4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", 
 	       n, self->stsap_sel);
 
 	self->stats.rx_packets++;
@@ -575,7 +567,7 @@
 	 *  Data or dataless frame? Dataless frames only contain the 
 	 *  TTP_HEADER
 	 */
-	if ( skb->len == 1) {
+	if (skb->len == 1) {
 		/* Dataless flowdata TTP-PDU */
 		self->send_credit += n;
 	} else {
@@ -587,27 +579,27 @@
 		 *  We don't remove the TTP header, since we must preserve the
 		 *  more bit, so the defragment routing knows what to do
 		 */
-		skb_queue_tail( &self->rx_queue, skb);
+		skb_queue_tail(&self->rx_queue, skb);
 	} 
 
-	irttp_run_rx_queue( self);
+	irttp_run_rx_queue(self);
 
 	/* 
 	 *  Give avay some credits to peer? 
 	 */
-	if (( skb_queue_empty( &self->tx_queue)) && 
-	    ( self->remote_credit < LOW_THRESHOLD) && 
-	    ( self->avail_credit > 0)) 
+	if ((skb_queue_empty(&self->tx_queue)) && 
+	    (self->remote_credit < LOW_THRESHOLD) && 
+	    (self->avail_credit > 0)) 
 	{
 		/* Schedule to start immediately after this thread */
-		irttp_start_todo_timer( self, 0);
+		irttp_start_todo_timer(self, 0);
 	}
 
 	/* If peer has given us some credites and we didn't have anyone
          * from before, the we need to shedule the tx queue? 
 	 */
-	if ( self->send_credit == n)
-		irttp_start_todo_timer( self, 0);
+	if (self->send_credit == n)
+		irttp_start_todo_timer(self, 0);
 }
 
 /*
@@ -617,26 +609,26 @@
  *    delivering frames if the receive queues are starting to get full, or 
  *    to tell IrTTP to start delivering frames again.
  */
-void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow)
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
 {
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(1, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	switch ( flow) {
+	switch (flow) {
 	case FLOW_STOP:
-		DEBUG( 0, __FUNCTION__ "(), flow stop\n");
+		DEBUG(1, __FUNCTION__ "(), flow stop\n");
 		self->rx_sdu_busy = TRUE;
 		break;
 	case FLOW_START:
-		DEBUG( 0, __FUNCTION__ "(), flow start\n");
+		DEBUG(1, __FUNCTION__ "(), flow start\n");
 		self->rx_sdu_busy = FALSE;
 		
-		irttp_run_rx_queue( self);
+		irttp_run_rx_queue(self);
 		break;
 	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 	
@@ -646,37 +638,35 @@
  *    Try to connect to remote destination TSAP selector
  *
  */
-void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
-			    struct qos_info *qos, int max_sdu_size, 
-			    struct sk_buff *userdata) 
+void irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, 
+			   __u32 saddr, __u32 daddr,
+			   struct qos_info *qos, int max_sdu_size, 
+			   struct sk_buff *userdata) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	__u8 n;
 	
-	DEBUG( 4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
+	DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	/* Any userdata supplied? */
-	if ( userdata == NULL) {
-		skb = dev_alloc_skb( 64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "Could not allocate an "
-			       "sk_buff of length %d\n", 64);
+	if (userdata == NULL) {
+		skb = dev_alloc_skb(64);
+		if (!skb) 
 			return;
-		}
 		
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
 	} else {
 		skb = userdata;
 		/*  
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT( skb_headroom( userdata) >= 
+		ASSERT(skb_headroom(userdata) >= 
 			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
 	}
 
@@ -696,7 +686,7 @@
 	/*
 	 *  Give away max 127 credits for now
 	 */
-	if ( n > 127) {
+	if (n > 127) {
 		self->avail_credit=n-127;
 		n = 127;
 	}
@@ -704,29 +694,29 @@
 	self->remote_credit = n;
 
 	/* SAR enabled? */
-	if ( max_sdu_size > 0) {
-		ASSERT( skb_headroom( skb) >= 
+	if (max_sdu_size > 0) {
+		ASSERT(skb_headroom(skb) >= 
 			(TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
 			return;);
 
 		/* Insert SAR parameters */
-		frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
 		
 		frame[0] = TTP_PARAMETERS | n; 
 		frame[1] = 0x04; /* Length */
 		frame[2] = 0x01; /* MaxSduSize */
 		frame[3] = 0x02; /* Value length */
-		*((__u16 *) (frame+4))= htons( max_sdu_size); /* Big endian! */
+		*((__u16 *) (frame+4))= htons(max_sdu_size); /* Big endian! */
 	} else {
 		/* Insert plain TTP header */
-		frame = skb_push( skb, TTP_HEADER);
+		frame = skb_push(skb, TTP_HEADER);
 		
 		/* Insert initial credit in frame */
 		frame[0] = n & 0x7f;
 	}
 
 	/* Connect with IrLMP. No QoS parameters for now */
-	irlmp_connect_request( self->lsap, dtsap_sel, daddr, qos, skb);
+	irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos, skb);
 }
 
 /*
@@ -735,24 +725,21 @@
  *    Sevice user confirms TSAP connection with peer. 
  *
  */
-void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-			    int max_seg_size, struct sk_buff *skb) 
+void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos,
+			   int max_seg_size, struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 	__u8 *frame;
 	__u8 n;
 	int parameters;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-
-	/* FIXME: just remove this when we know its working */
-	ASSERT( max_seg_size == qos->data_size.value, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
 
@@ -760,40 +747,40 @@
 	 *  Check if we have got some QoS parameters back! This should be the
 	 *  negotiated QoS for the link.
 	 */
-	if ( qos) {
-		DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
+	if (qos) {
+		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
 		       qos->baud_rate.bits);			
-		DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
+		DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
 		       qos->baud_rate.value);
 	}
 
 	frame = skb->data;
 	n = frame[0] & 0x7f;
 	
-	DEBUG( 4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
+	DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
 	
 	self->send_credit = n;
 	self->tx_max_sdu_size = 0;
 	self->connected = TRUE;
 
 	parameters = frame[0] & 0x80;	
-	if ( parameters) {
-		DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
+	if (parameters) {
+		DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
 		
 		self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
-		DEBUG( 4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
+		DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
 		       self->tx_max_sdu_size);
 	}
 	
-	DEBUG( 4, "irttp_connect_confirm() send=%d,avail=%d,remote=%d\n", 
-	       self->send_credit, self->avail_credit, self->remote_credit);
+	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+	      self->send_credit, self->avail_credit, self->remote_credit);
 
-	skb_pull( skb, TTP_HEADER);
+	skb_pull(skb, TTP_HEADER);
 
-	if ( self->notify.connect_confirm) {
-		self->notify.connect_confirm( self->notify.instance, self, 
-					      qos, self->tx_max_sdu_size, 
-					      skb);
+	if (self->notify.connect_confirm) {
+		self->notify.connect_confirm(self->notify.instance, self, 
+					     qos, self->tx_max_sdu_size, 
+					     skb);
 	}
 }
 
@@ -803,32 +790,33 @@
  *    Some other device is connecting to this TSAP
  *
  */
-void irttp_connect_indication( void *instance, void *sap, 
-			       struct qos_info *qos, int max_seg_size, 
-			       struct sk_buff *skb) 
+void irttp_connect_indication(void *instance, void *sap, 
+			      struct qos_info *qos, int max_seg_size, 
+			      struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
+	struct lsap_cb *lsap;
 	__u8 *frame;
 	int parameters;
 	int n;
 
 	self = (struct tsap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
- 	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ 	ASSERT(skb != NULL, return;);
+
+	lsap = (struct lsap_cb *) sap;
 
 	/* FIXME: just remove this when we know its working */
-	ASSERT( max_seg_size == qos->data_size.value, return;);
+	ASSERT(max_seg_size == qos->data_size.value, return;);
 
 	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
 
-	DEBUG( 4, "irttp_connect_indication(), TSAP sel=%02x\n", 
-	       self->stsap_sel);
+	DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
 
-	/* FIXME: Need to update dtsap_sel if its equal to LSAP_ANY */
-/* 	if ( self->dtsap_sel == LSAP_ANY) */
-/* 		self->dtsap_sel = lsap->dlsap_sel; */
+	/* Need to update dtsap_sel if its equal to LSAP_ANY */
+	self->dtsap_sel = lsap->dlsap_sel;
 
 	frame = skb->data;
 	n = frame[0] & 0x7f;
@@ -837,22 +825,22 @@
 	self->tx_max_sdu_size = 0;
 	
 	parameters = frame[0] & 0x80;	
-	if ( parameters) {
-		DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
+	if (parameters) {
+		DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
 		
 		self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
-		DEBUG( 4, __FUNCTION__ "(), MaxSduSize=%d\n", 
-		       self->tx_max_sdu_size);
+		DEBUG(4, __FUNCTION__ "(), MaxSduSize=%d\n", 
+		      self->tx_max_sdu_size);
 	}
 
-	DEBUG( 4, "irttp_connect_indication: initial send_credit=%d\n", n);
+	DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
 
-	skb_pull( skb, 1);
+	skb_pull(skb, 1);
 
-	if ( self->notify.connect_indication) {
-		self->notify.connect_indication( self->notify.instance, self, 
-						 qos, self->rx_max_sdu_size, 
-						 skb);
+	if (self->notify.connect_indication) {
+		self->notify.connect_indication(self->notify.instance, self, 
+						qos, self->rx_max_sdu_size, 
+						skb);
 	}
 }
 
@@ -863,37 +851,34 @@
  *    IrLMP!
  * 
  */
-void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, 
-			     struct sk_buff *userdata)
+void irttp_connect_response(struct tsap_cb *self, int max_sdu_size, 
+			    struct sk_buff *userdata)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	__u8 n;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	DEBUG( 4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
-	       self->stsap_sel);
+	DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
+	      self->stsap_sel);
 	
 	/* Any userdata supplied? */
-	if ( userdata == NULL) {
-		skb = dev_alloc_skb( 64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "Could not allocate an "
-			       "sk_buff of length %d\n", 64);
+	if (userdata == NULL) {
+		skb = dev_alloc_skb(64);
+		if (!skb)
 			return;
-		}
 
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
 	} else {
 		skb = userdata;
 		/*  
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT( skb_headroom( skb) >= 
+		ASSERT(skb_headroom(skb) >= 
 			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
 	}
 	
@@ -906,7 +891,7 @@
 	n = self->initial_credit;
 
 	/* Frame has only space for max 127 credits (7 bits) */
-	if ( n > 127) {
+	if (n > 127) {
 		self->avail_credit = n - 127;
 		n = 127;
 	}
@@ -915,117 +900,112 @@
 	self->connected = TRUE;
 
 	/* SAR enabled? */
-	if ( max_sdu_size > 0) {
-		ASSERT( skb_headroom( skb) >= 
-			(TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
-			return;);
+	if (max_sdu_size > 0) {
+		ASSERT(skb_headroom(skb) >= 
+		       (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
+		       return;);
 		
 		/* Insert TTP header with SAR parameters */
-		frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
 		
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
 		frame[2] = 0x01; /* MaxSduSize */
 		frame[3] = 0x02; /* Value length */
-		*((__u16 *) (frame+4))= htons( max_sdu_size);
+		*((__u16 *) (frame+4))= htons(max_sdu_size);
 	} else {
 		/* Insert TTP header */
-		frame = skb_push( skb, TTP_HEADER);
+		frame = skb_push(skb, TTP_HEADER);
 		
 		frame[0] = n & 0x7f;
 	}
 	 
-	irlmp_connect_response( self->lsap, skb);
+	irlmp_connect_response(self->lsap, skb);
 }
 
 /*
- * Function irttp_disconnect_request ( self)
+ * Function irttp_disconnect_request (self)
  *
  *    Close this connection please! If priority is high, the queued data 
  *    segments, if any, will be deallocated first
  *
  */
-void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *userdata, 
-			       int priority)
+void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, 
+			      int priority)
 {
 	struct sk_buff *skb;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	/* Already disconnected? */
-	if ( !self->connected) {
-		DEBUG( 4, __FUNCTION__ "(), already disconnected!\n");
+	if (!self->connected) {
+		DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
 		return;
 	}
 
 	/* Disconnect already pending? */
-	if ( self->disconnect_pend) {
-		DEBUG( 0, __FUNCTION__ "(), disconnect already pending\n");
-		if ( userdata) {
-			dev_kfree_skb( userdata);
+	if (self->disconnect_pend) {
+		DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
+		if (userdata) {
+			dev_kfree_skb(userdata);
 		}
 
 		/* Try to make some progress */
-		irttp_run_rx_queue( self);
+		irttp_run_rx_queue(self);
 		return;
 	}
 
 	/*
 	 *  Check if there is still data segments in the transmit queue
 	 */
-	if ( skb_queue_len( &self->tx_queue) > 0) {
-		if ( priority == P_HIGH) {
-			DEBUG( 0, __FUNCTION__  "High priority!!()\n" );
+	if (skb_queue_len(&self->tx_queue) > 0) {
+		if (priority == P_HIGH) {
+			DEBUG(1, __FUNCTION__  "High priority!!()\n" );
 			
 			/* 
 			 *  No need to send the queued data, if we are 
 			 *  disconnecting right now since the data will
 			 *  not have any usable connection to be sent on
 			 */
-			irttp_flush_queues( self);
-		} else if ( priority == P_NORMAL) {
+			irttp_flush_queues(self);
+		} else if (priority == P_NORMAL) {
 			/* 
 			 *  Must delay disconnect til after all data segments
 			 *  have been sent an the tx_queue is empty
 			 */
-			if ( userdata)
+			if (userdata)
 				self->disconnect_skb = userdata;
 			else
 				self->disconnect_skb = NULL;
 
 			self->disconnect_pend = TRUE;
 
-			irttp_run_tx_queue( self);
-			/*  
-			 *  irttp_xmit will call us again when the tx_queue
-			 *  is empty
-			 */
+			irttp_run_tx_queue(self);
+
+			irttp_start_todo_timer(self, 100);
 			return;
 		}
 	}
-	DEBUG( 0, __FUNCTION__ "(), Disconnecting ...\n");
+	DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
 
 	self->connected = FALSE;
 	
-	if ( !userdata) {
-		skb = dev_alloc_skb( 64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "(), Could not allocate an "
-			       "sk_buff of length %d\n", 64);
+	if (!userdata) {
+		skb = dev_alloc_skb(64);
+		if (!skb)
 			return;
-		}
-
+		
 		/* 
 		 *  Reserve space for MUX and LAP header 
 		 */
-		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
-
+		skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		
 		userdata = skb;
 	}
-	irlmp_disconnect_request( self->lsap, userdata);
+	irlmp_disconnect_request(self->lsap, userdata);
 }
 
 /*
@@ -1034,26 +1014,26 @@
  *    Disconnect indication, TSAP disconnected by peer?
  *
  */
-void irttp_disconnect_indication( void *instance, void *sap, LM_REASON reason, 
-				  struct sk_buff *userdata) 
+void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
+				 struct sk_buff *userdata) 
 {
 	struct tsap_cb *self;
 
-	DEBUG( 4, "irttp_disconnect_indication()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	self = ( struct tsap_cb *) instance;
+	self = (struct tsap_cb *) instance;
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 	
 	self->connected = FALSE;
 	
 	/* 
 	 *  Use callback to notify layer above 
 	 */
-	if ( self->notify.disconnect_indication)
-		self->notify.disconnect_indication( self->notify.instance, 
-						    self, reason, userdata);
+	if (self->notify.disconnect_indication)
+		self->notify.disconnect_indication(self->notify.instance, 
+						   self, reason, userdata);
 }
 
 /*
@@ -1062,43 +1042,43 @@
  *     Check if we have any frames to be transmitted, or if we have any
  *     available credit to give away.
  */
-void irttp_run_rx_queue( struct tsap_cb *self) 
+void irttp_run_rx_queue(struct tsap_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 	int more = 0;
 	void *instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
 	instance = self->notify.instance;
-	ASSERT( instance != NULL, return;);
+	ASSERT(instance != NULL, return;);
 
-	DEBUG( 4, "irttp_do_events() send=%d,avail=%d,remote=%d\n", 
+	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)
+	if (irda_lock(&self->rx_queue_lock) == FALSE)
 		return;
 	
 	/*
 	 *  Process receive queue
 	 */
-	while (( !skb_queue_empty( &self->rx_queue)) &&  !self->rx_sdu_busy) {
+	while ((!skb_queue_empty(&self->rx_queue)) &&  !self->rx_sdu_busy) {
 
-		skb = skb_dequeue( &self->rx_queue);
-		if ( !skb)
+		skb = skb_dequeue(&self->rx_queue);
+		if (!skb)
 			break; /* Should not happend, but ...  */
 		
 		self->avail_credit++;
 
 		frame = skb->data;
 		more = frame[0] & 0x80;
-		DEBUG( 4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" : 
+		DEBUG(4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" : 
 		       "FALSE");
 
 		/* Remove TTP header */
-		skb_pull( skb, TTP_HEADER);
+		skb_pull(skb, TTP_HEADER);
 
 		/* Add the length of the remaining data */
 		self->rx_sdu_size += skb->len;
@@ -1110,52 +1090,52 @@
 		 * implements byte streams without any message boundaries
 		 */
 		if ((self->no_defrag) || (self->rx_max_sdu_size == 0)) {
-			self->notify.data_indication( instance, self, skb);
+			self->notify.data_indication(instance, self, skb);
 			self->rx_sdu_size = 0;
-
+			
 			continue;
 		}
 
 		/* Check if this is a fragment, and not the last fragment */
-		if ( more) {
+		if (more) {
 			/*  
 			 *  Queue the fragment if we still are within the 
 			 *  limits of the maximum size of the rx_sdu
 			 */
-			if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
-				DEBUG( 4, __FUNCTION__ 
+			if (self->rx_sdu_size <= self->rx_max_sdu_size) {
+				DEBUG(4, __FUNCTION__ 
 				       "(), queueing fragment\n");
 
-				skb_queue_tail( &self->rx_fragments, skb);
+				skb_queue_tail(&self->rx_fragments, skb);
 			} else {
-				DEBUG( 0, __FUNCTION__ "(), Error!\n");
+				DEBUG(1, __FUNCTION__ "(), Error!\n");
 			}
 		} else {
 			/*
 			 *  This is the last fragment, so time to reassemble!
 			 */
-			if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
+			if (self->rx_sdu_size <= self->rx_max_sdu_size) {
 
 				/* A little optimizing. Only queue the 
 				 * fragment if there is other fragments. Since
 				 * if this is the last and only fragment, 
 				 * there is no need to reassemble 
 				 */
-				if ( !skb_queue_empty( &self->rx_fragments)) {
+				if (!skb_queue_empty(&self->rx_fragments)) {
 
-					DEBUG( 4, __FUNCTION__ 
+					DEBUG(4, __FUNCTION__ 
 					       "(), queueing fragment\n");
-					skb_queue_tail( &self->rx_fragments, 
+					skb_queue_tail(&self->rx_fragments, 
 							skb);
 
-					skb = irttp_reassemble_skb( self);
+					skb = irttp_reassemble_skb(self);
 				}
-				self->notify.data_indication( instance, self, 
-							      skb);
+				self->notify.data_indication(instance, self, 
+							     skb);
 			} else {
-				DEBUG( 0, __FUNCTION__ 
+				DEBUG(1, __FUNCTION__ 
 				       "(), Truncated frame\n");
-				self->notify.data_indication( 
+				self->notify.data_indication(
 					self->notify.instance, self, skb);
 			}
 			self->rx_sdu_size = 0;
@@ -1170,28 +1150,26 @@
  *
  *     Flushes (removes all frames) in transitt-buffer (tx_list)
  */
-void irttp_flush_queues( struct tsap_cb *self)
+void irttp_flush_queues(struct tsap_cb *self)
 {
 	struct sk_buff* skb;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 	
 	/* Deallocate frames waiting to be sent */
-	while (( skb = skb_dequeue( &self->tx_queue)) != NULL) {
-		dev_kfree_skb( skb);
-	}
+	while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
+		dev_kfree_skb(skb);
+	
 	/* Deallocate received frames */
-	while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
-		dev_kfree_skb( skb);
-	}
-	/* Deallocate received fragments */
-	while (( skb = skb_dequeue( &self->rx_fragments)) != NULL) {
-		dev_kfree_skb( skb);
-	}
+	while ((skb = skb_dequeue(&self->rx_queue)) != NULL)
+		dev_kfree_skb(skb);
 	
+	/* Deallocate received fragments */
+	while ((skb = skb_dequeue(&self->rx_fragments)) != NULL)
+		dev_kfree_skb(skb);
 }
 
 /*
@@ -1201,40 +1179,38 @@
  *    queue
  *
  */
-static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self)
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
 {
 	struct sk_buff *skb, *frag;
 	int n = 0;  /* Fragment index */
+	
+      	ASSERT(self != NULL, return NULL;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
 
-      	ASSERT( self != NULL, return NULL;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return NULL;);
-
-	DEBUG( 4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
-	       self->rx_sdu_size);
+	DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
+	      self->rx_sdu_size);
 
-	skb = dev_alloc_skb( self->rx_sdu_size);
-	if ( !skb) {
-		DEBUG( 0, __FUNCTION__ "(), unable to allocate skb\n");
+	skb = dev_alloc_skb(self->rx_sdu_size);
+	if (!skb)
 		return NULL;
-	}
 
-	skb_put( skb, self->rx_sdu_size);
+	skb_put(skb, self->rx_sdu_size);
 
 	/*
 	 *  Copy all fragments to a new buffer
 	 */
-	while (( frag = skb_dequeue( &self->rx_fragments)) != NULL) {
-		memcpy( skb->data+n, frag->data, frag->len);
+	while ((frag = skb_dequeue(&self->rx_fragments)) != NULL) {
+		memcpy(skb->data+n, frag->data, frag->len);
 		n += frag->len;
 		
-		dev_kfree_skb( frag);
+		dev_kfree_skb(frag);
 	}
-	DEBUG( 4, __FUNCTION__ "(), frame len=%d\n", n);
+	DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
 	/* Set the new length */
 
-	DEBUG( 4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
-	ASSERT( n <= self->rx_sdu_size, return NULL;);
-	skb_trim( skb, n);
+	DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+	ASSERT(n <= self->rx_sdu_size, return NULL;);
+	skb_trim(skb, n);
 
 	self->rx_sdu_size = 0;
 
@@ -1247,60 +1223,57 @@
  *    Fragments a frame and queues all the fragments for transmission
  *
  */
-static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb)
+static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb)
 {
 	struct sk_buff *frag;
 	__u8 *frame;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	/*
 	 *  Split frame into a number of segments
 	 */
-	while ( skb->len > 0) {
+	while (skb->len > 0) {
 		/*
 		 *  Instead of making the last segment, we just
 		 *  queue what is left of the original skb
 		 */
-		if ( skb->len < self->max_seg_size) {
-			DEBUG( 4, __FUNCTION__ 
+		if (skb->len < self->max_seg_size) {
+			DEBUG(4, __FUNCTION__ 
 			       "(), queuing last segment\n");
 
-			frame = skb_push( skb, TTP_HEADER);
+			frame = skb_push(skb, TTP_HEADER);
 			frame[0] = 0x00; /* Clear more bit */
-			skb_queue_tail( &self->tx_queue, skb);
+			skb_queue_tail(&self->tx_queue, skb);
 			
 			return;
 		}
 		
 		/* Make new segment */
-		frag = dev_alloc_skb( self->max_seg_size+
-					 TTP_HEADER+LMP_HEADER+
-					 LAP_HEADER);
-		if ( frag == NULL) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Couldn't allocate skbuff!\n");
+		frag = dev_alloc_skb(self->max_seg_size+
+				      TTP_HEADER+LMP_HEADER+
+				      LAP_HEADER);
+		if (!frag)
 			return;
-		}
 
-		skb_reserve( frag, LMP_HEADER+LAP_HEADER);
+		skb_reserve(frag, LMP_HEADER+LAP_HEADER);
 
 		/*
 		 *  Copy data from the original skb into this fragment. We
 		 *  first insert the TTP header with the more bit set
 		 */
-		frame = skb_put( frag, self->max_seg_size+TTP_HEADER);
+		frame = skb_put(frag, self->max_seg_size+TTP_HEADER);
 		frame[0] = TTP_MORE;
-		memcpy( frag->data+1, skb->data, self->max_seg_size);
+		memcpy(frag->data+1, skb->data, self->max_seg_size);
 		
 		/* Hide the copied data from the original skb */
-		skb_pull( skb, self->max_seg_size);
+		skb_pull(skb, self->max_seg_size);
 		
-		skb_queue_tail( &self->tx_queue, frag);
+		skb_queue_tail(&self->tx_queue, frag);
 	}
 }
 
@@ -1310,31 +1283,51 @@
  *    Todo timer has expired!
  *
  */
-static void irttp_todo_expired( unsigned long data)
+static void irttp_todo_expired(unsigned long data)
 {
-	struct tsap_cb *self = ( struct tsap_cb *) data;
+	struct tsap_cb *self = (struct tsap_cb *) data;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
 	/* Check that we still exist */
-	if ( !self || self->magic != TTP_TSAP_MAGIC) {
+	if (!self || self->magic != TTP_TSAP_MAGIC) {
 		return;
 	}
 
-	irttp_run_rx_queue( self);
-	irttp_run_tx_queue( self);
+	irttp_run_rx_queue(self);
+	irttp_run_tx_queue(self);
 
 	/*  Give avay some credits to peer?  */
-	if (( skb_queue_empty( &self->tx_queue)) && 
-	    ( self->remote_credit < LOW_THRESHOLD) && 
-	    ( self->avail_credit > 0)) 
+	if ((skb_queue_empty(&self->tx_queue)) && 
+	    (self->remote_credit < LOW_THRESHOLD) && 
+	    (self->avail_credit > 0)) 
 	{
-		DEBUG( 4, "irttp_do_events: sending credit!\n");
-		irttp_give_credit( self);
+		DEBUG(4, __FUNCTION__ "(), sending credit!\n");
+		irttp_give_credit(self);
 	}
-	
-	/* Rearm! */
-	/* irttp_start_todo_timer( self, 50); */
+
+	/* Check if time for disconnect */
+	if (self->disconnect_pend) {
+		/* Check if it's possible to disconnect yet */
+		if (skb_queue_empty(&self->tx_queue)) {
+			if (self->disconnect_skb) {
+				irttp_disconnect_request(
+					self, self->disconnect_skb, P_NORMAL);
+				self->disconnect_skb = NULL;
+			} else
+				irttp_disconnect_request(self, NULL, P_NORMAL);
+		} else {
+			/* Try again later */
+			irttp_start_todo_timer(self, 100);
+			
+			/* No reason to try and close now */
+			return;
+		}
+	}
+
+	/* Check if it's closing time */
+	if (self->close_pend)
+		irttp_close_tsap(self);
 }
 
 /*
@@ -1343,18 +1336,18 @@
  *    Start todo timer. 
  *
  */
-static void irttp_start_todo_timer( struct tsap_cb *self, int timeout)
+static void irttp_start_todo_timer(struct tsap_cb *self, int timeout)
 {
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-	del_timer( &self->todo_timer);
+	del_timer(&self->todo_timer);
 	
 	self->todo_timer.data     = (unsigned long) self;
 	self->todo_timer.function = &irttp_todo_expired;
 	self->todo_timer.expires  = jiffies + timeout;
 	
-	add_timer( &self->todo_timer);
+	add_timer(&self->todo_timer);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -1363,65 +1356,64 @@
  *
  *    Give some info to the /proc file system
  */
-int irttp_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused)
+int irttp_proc_read(char *buf, char **start, off_t offset, int len, int unused)
 {
 	struct tsap_cb *self;
 	unsigned long flags;
 	int i = 0;
 	
-	ASSERT( irttp != NULL, return 0;);
+	ASSERT(irttp != NULL, return 0;);
 	
 	len = 0;
 	
 	save_flags(flags);
 	cli();
 
-	self = ( struct tsap_cb *) hashbin_get_first( irttp->tsaps);
-	while ( self != NULL) {
-		if ( !self || self->magic != TTP_TSAP_MAGIC) {
-			DEBUG( 0, "irttp_proc_read: bad ptr self\n");
+	self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
+	while (self != NULL) {
+		if (!self || self->magic != TTP_TSAP_MAGIC) {
+			DEBUG(1, "irttp_proc_read: bad ptr self\n");
 			return len;
 		}
 
-		len += sprintf( buf+len, "TSAP %d, ", i++);
-		len += sprintf( buf+len, "stsap_sel: %02x, ", 
+		len += sprintf(buf+len, "TSAP %d, ", i++);
+		len += sprintf(buf+len, "stsap_sel: %02x, ", 
 				self->stsap_sel);
-		len += sprintf( buf+len, "dtsap_sel: %02x\n", 
+		len += sprintf(buf+len, "dtsap_sel: %02x\n", 
 				self->dtsap_sel);
-		len += sprintf( buf+len, "  connected: %s, ",
+		len += sprintf(buf+len, "  connected: %s, ",
 				self->connected? "TRUE":"FALSE");
-		len += sprintf( buf+len, "avail credit: %d, ",
+		len += sprintf(buf+len, "avail credit: %d, ",
 				self->avail_credit);
-		len += sprintf( buf+len, "remote credit: %d, ",
+		len += sprintf(buf+len, "remote credit: %d, ",
 				self->remote_credit);
-		len += sprintf( buf+len, "send credit: %d\n",
+		len += sprintf(buf+len, "send credit: %d\n",
 				self->send_credit);
-		len += sprintf( buf+len, "  tx packets: %d, ",
+		len += sprintf(buf+len, "  tx packets: %d, ",
 				self->stats.tx_packets);
-		len += sprintf( buf+len, "rx packets: %d, ",
+		len += sprintf(buf+len, "rx packets: %d, ",
 				self->stats.rx_packets);
-		len += sprintf( buf+len, "tx_queue len: %d ", 
-				skb_queue_len( &self->tx_queue));
-		len += sprintf( buf+len, "rx_queue len: %d\n", 
-				skb_queue_len( &self->rx_queue));
-		len += sprintf( buf+len, "  tx_sdu_busy: %s, ",
+		len += sprintf(buf+len, "tx_queue len: %d ", 
+				skb_queue_len(&self->tx_queue));
+		len += sprintf(buf+len, "rx_queue len: %d\n", 
+				skb_queue_len(&self->rx_queue));
+		len += sprintf(buf+len, "  tx_sdu_busy: %s, ",
 				self->tx_sdu_busy? "TRUE":"FALSE");
-		len += sprintf( buf+len, "rx_sdu_busy: %s\n",
+		len += sprintf(buf+len, "rx_sdu_busy: %s\n",
 				self->rx_sdu_busy? "TRUE":"FALSE");
-		len += sprintf( buf+len, "  max_seg_size: %d, ",
+		len += sprintf(buf+len, "  max_seg_size: %d, ",
 				self->max_seg_size);
-		len += sprintf( buf+len, "tx_max_sdu_size: %d, ",
+		len += sprintf(buf+len, "tx_max_sdu_size: %d, ",
 				self->tx_max_sdu_size);
-		len += sprintf( buf+len, "rx_max_sdu_size: %d\n",
+		len += sprintf(buf+len, "rx_max_sdu_size: %d\n",
 				self->rx_max_sdu_size);
 
-		len += sprintf( buf+len, "  Used by (%s)\n", 
+		len += sprintf(buf+len, "  Used by (%s)\n", 
 				self->notify.name);
 
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "\n");
 		
-		self = ( struct tsap_cb *) hashbin_get_next( irttp->tsaps);
+		self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps);
 	}
 	restore_flags(flags);
 
diff -urN linux-2.2.3-pre2/net/irda/Makefile linux-2.2.3-pre3/net/irda/Makefile
--- linux-2.2.3-pre2/net/irda/Makefile	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/Makefile	2003-08-15 15:05:26.000000000 -0700
@@ -10,13 +10,19 @@
 ALL_SUB_DIRS := irlan ircomm irlpt compressors
 SUB_DIRS :=
 MOD_SUB_DIRS :=
+OX_OBJS :=
 
 O_TARGET := irda.o
-O_OBJS	 := irmod.o iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
+O_OBJS	 := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
             irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
             irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o
+OX_OBJS := irmod.o
+
 MOD_LIST_NAME := IRDA_MODULES
+
+ifeq ($(CONFIG_IRDA),m)
 M_OBJS   := $(O_TARGET)
+endif
 
 ifeq ($(CONFIG_IRDA_COMPRESSION),y)
 O_OBJS += irlap_comp.o
diff -urN linux-2.2.3-pre2/net/irda/qos.c linux-2.2.3-pre3/net/irda/qos.c
--- linux-2.2.3-pre2/net/irda/qos.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/qos.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      qos.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   IrLAP QoS negotiation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Sat Dec 12 12:21:42 1998
+ * Modified at:   Mon Feb  1 09:56:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -109,8 +109,8 @@
  *    We just set the QoS capabilities for the peer station
  *
  */
-void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx, 
-			 struct sk_buff *skb) 
+void irda_qos_negotiate(struct qos_info *qos_rx, struct qos_info *qos_tx, 
+			struct sk_buff *skb) 
 {
 	int n=0;
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -162,7 +162,7 @@
 			break;
 		}
 
-		switch( code) {
+		switch(code) {
 		case PI_BAUD_RATE:
 			/* 
 			 *  Stations must agree on baud rate, so calculate
@@ -178,7 +178,8 @@
 			/*
 			 *  Negotiated independently for each station
 			 */
-			DEBUG( 4, "MAX_TURN_TIME: %02x\n", byte);
+			DEBUG(4, __FUNCTION__ "(), MAX_TURN_TIME: %02x\n", 
+			      byte);
 			qos_tx->max_turn_time.bits = byte;
 			break;
 		case PI_DATA_SIZE:
@@ -268,7 +269,7 @@
  *    Insert QoS negotiaion pararameters into frame
  *
  */
-int irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *frame)
+int irda_insert_qos_negotiation_params(struct qos_info *qos, __u8 *frame)
 {
 	int n;
 	__u16_host_order word;
diff -urN linux-2.2.3-pre2/net/irda/timer.c linux-2.2.3-pre3/net/irda/timer.c
--- linux-2.2.3-pre2/net/irda/timer.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/timer.c	2003-08-15 15:05:26.000000000 -0700
@@ -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 Dec  9 01:34:59 1998
+ * Modified at:   Thu Feb  4 10:49:38 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -100,11 +100,16 @@
 			  irlmp_watchdog_timer_expired);
 }
 
-inline void irlmp_start_discovery_timer( struct irlmp_cb *self, int timeout) 
+inline void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
 {
-	irda_start_timer( &self->discovery_timer, timeout, 
-			  (unsigned long) self,
-			  irlmp_discovery_timer_expired);
+	irda_start_timer(&self->discovery_timer, timeout, (unsigned long) self,
+			 irlmp_discovery_timer_expired);
+}
+
+inline void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
+{
+	irda_start_timer(&self->idle_timer, timeout, (unsigned long) self,
+			 irlmp_idle_timer_expired);
 }
 
 /*
diff -urN linux-2.2.3-pre2/net/irda/wrapper.c linux-2.2.3-pre3/net/irda/wrapper.c
--- linux-2.2.3-pre2/net/irda/wrapper.c	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.3-pre3/net/irda/wrapper.c	2003-08-15 15:05:26.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.c
- * Version:       
- * Description:   IrDA Wrapper layer
+ * Version:       1.0
+ * Description:   SIR wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:05:45 1999
+ * Modified at:   Tue Feb 16 17:27:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -36,7 +36,7 @@
 
 #define MIN_LENGTH 14
 
-__inline__ static int stuff_byte( __u8 byte, __u8 *buf);
+inline static int stuff_byte( __u8 byte, __u8 *buf);
 
 /*
  * Function async_wrap (skb, *tx_buff)
@@ -54,8 +54,6 @@
 		__u8 bytes[2];
 	} fcs;
 
-
- 	DEBUG( 6, __FUNCTION__ "()\n"); 
 	ASSERT( skb != NULL, return 0;);
 
 	/* Initialize variables */
@@ -63,7 +61,7 @@
 	n = 0;
 
 	if ( skb->len > 2048) {
-		DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n", 
+		DEBUG( 0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n", 
 		       (int) skb->len);
 
 		return 0;
@@ -119,15 +117,12 @@
  *    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)
+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 == NULL)  {
-		printk( KERN_INFO __FUNCTION__ "() memory squeeze, " 
-			"dropping frame.\n");
+	skb = dev_alloc_skb(len+1);
+	if (!skb)  {
 		idev->stats.rx_dropped++;
 		return;
 	}
@@ -141,7 +136,6 @@
 	skb_put( skb, len-2);
 	memcpy( skb->data, buf, len-2); 
 	
-	idev->rx_buff.len = 0;
 	/* 
 	 *  Feed it to IrLAP layer 
 	 */
@@ -150,11 +144,11 @@
 	skb->mac.raw  = skb->data;
 	skb->protocol = htons(ETH_P_IRDA);
 
-	netif_rx( skb);
+	netif_rx(skb);
 	idev->stats.rx_packets++;
 	idev->stats.rx_bytes += skb->len;	
 }
- 
+
 /*
  * Function async_unwrap (skb)
  *
@@ -166,16 +160,25 @@
 	/* State machine for receiving frames */	   
 	switch( idev->rx_buff.state) {
 	case OUTSIDE_FRAME:
-		if ( byte == BOF) {
+		switch( byte) {
+		case BOF:
 			idev->rx_buff.state = BEGIN_FRAME;
 			idev->rx_buff.in_frame = TRUE;
-		} else if ( byte == EOF) {
+			break;
+		case XBOF:
+			idev->xbofs++;
+			break;
+		case EOF:
 			irda_device_set_media_busy( idev, TRUE);
+			break;
+		default:
+			break;
 		}
 		break;
 	case BEGIN_FRAME:
 		switch ( byte) {
 		case BOF:
+			
 			/* Continue */
 			break;
 		case CE:
@@ -191,13 +194,10 @@
 			break;
 		default:
 			/* Got first byte of frame */
-			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
-				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
+			idev->rx_buff.data[ idev->rx_buff.len++] = byte;
 			
-				idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte);
-				idev->rx_buff.state = INSIDE_FRAME;
-			} else 
-				printk( "Rx buffer overflow\n");
+			idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte);
+			idev->rx_buff.state = INSIDE_FRAME;
 			break;
 		}
 		break;
@@ -205,7 +205,6 @@
 		switch ( byte) {
 		case BOF:
 			/* New frame? */
-			DEBUG( 4, "New frame?\n");
 			idev->rx_buff.state = BEGIN_FRAME;
 			idev->rx_buff.len = 0;
 			irda_device_set_media_busy( idev, TRUE);
@@ -215,7 +214,6 @@
 			break;
 		case EOF:
 			/* Abort frame */
-			DEBUG( 0, "Abort frame (2)\n");
 			idev->rx_buff.state = OUTSIDE_FRAME;
 			idev->rx_buff.len = 0;
 			break;
@@ -228,10 +226,15 @@
 			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
 				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
 			
-				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
+				idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs,
+							   byte);
 				idev->rx_buff.state = INSIDE_FRAME;
-			} else 
-				printk( "Rx buffer overflow\n");
+			} else {
+				DEBUG( 1, __FUNCTION__ 
+				       "(), Rx buffer overflow, aborting\n");
+				idev->rx_buff.state = OUTSIDE_FRAME;
+				idev->rx_buff.len = 0;
+			}
 			break;
 		}
 		break;
@@ -258,6 +261,7 @@
 			if ( idev->rx_buff.fcs == GOOD_FCS) {
 				async_bump( idev, idev->rx_buff.data, 
 					    idev->rx_buff.len);
+				idev->rx_buff.len = 0;
 			} else {
 				/* Wrong CRC, discard frame!  */
 				irda_device_set_media_busy( idev, TRUE); 
@@ -272,9 +276,14 @@
 			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
 				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
 				
-				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
-			} else 
-				printk( "Rx buffer overflow\n");
+				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs,
+							    byte);
+			} else {
+				DEBUG( 1, __FUNCTION__ 
+				       "(), Rx buffer overflow, aborting\n");
+				idev->rx_buff.state = OUTSIDE_FRAME;
+				idev->rx_buff.len = 0;
+			}
 			break;
 		}
 		break;
@@ -288,11 +297,11 @@
  *    buf. The buffer must at all times be able to have two bytes inserted.
  * 
  */
-__inline__ static int stuff_byte( __u8 byte, __u8 *buf) 
+inline static int stuff_byte( __u8 byte, __u8 *buf) 
 {
 	switch ( byte) {
-	case BOF:
-	case EOF:
+	case BOF: /* FALLTHROUGH */
+	case EOF: /* FALLTHROUGH */
 	case CE:
 		/* Insert transparently coded */
 		buf[0] = CE;               /* Send link escape */
@@ -308,3 +317,5 @@
 }
 	 
 
+
+
diff -urN linux-2.2.3-pre2/net/Makefile linux-2.2.3-pre3/net/Makefile
--- linux-2.2.3-pre2/net/Makefile	1999-02-06 12:46:21.000000000 -0800
+++ linux-2.2.3-pre3/net/Makefile	2003-08-15 15:05:26.000000000 -0700
@@ -128,7 +128,7 @@
 ifeq ($(CONFIG_IRDA),y)
 SUB_DIRS += irda
 # There might be some irda features that are compiled as modules
-MOD_SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
 else
   ifeq ($(CONFIG_IRDA),m)
   MOD_SUB_DIRS += irda
