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

diff -urN linux-2.2.10-pre1/arch/i386/lib/checksum.S linux-2.2.10-pre2/arch/i386/lib/checksum.S
--- linux-2.2.10-pre1/arch/i386/lib/checksum.S	1999-01-15 14:36:20.000000000 -0800
+++ linux-2.2.10-pre2/arch/i386/lib/checksum.S	2003-08-15 15:06:23.000000000 -0700
@@ -369,7 +369,7 @@
 
 #define ROUND1(x) \
 	SRC(movl x(%esi), %ebx	)	;	\
-	addl %ebx, %eax\n		;	\
+	addl %ebx, %eax			;	\
 	DST(movl %ebx, x(%edi)	)	; 
 
 #define ROUND(x) \
diff -urN linux-2.2.10-pre1/arch/sparc64/kernel/setup.c linux-2.2.10-pre2/arch/sparc64/kernel/setup.c
--- linux-2.2.10-pre1/arch/sparc64/kernel/setup.c	1999-04-22 19:24:51.000000000 -0700
+++ linux-2.2.10-pre2/arch/sparc64/kernel/setup.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.43 1999/04/12 08:08:24 davem Exp $
+/*  $Id: setup.c,v 1.43.2.1 1999/05/28 02:18:13 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -550,7 +550,9 @@
 			ic_servaddr = sv;
 			if (gw)
 				ic_gateway = gw;
+#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP)
 			ic_proto_enabled = 0;
+#endif
 		}
 	}
 #endif
diff -urN linux-2.2.10-pre1/drivers/block/loop.c linux-2.2.10-pre2/drivers/block/loop.c
--- linux-2.2.10-pre1/drivers/block/loop.c	1999-01-14 10:33:36.000000000 -0800
+++ linux-2.2.10-pre2/drivers/block/loop.c	2003-08-15 15:06:23.000000000 -0700
@@ -504,6 +504,8 @@
 	if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE)
 		return -EINVAL;
 	type = info.lo_encrypt_type; 
+	if (info.lo_encrypt_key_size == 0 && type == LO_CRYPT_XOR)
+		return -EINVAL;
 	if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL)
 		return -EINVAL;
 	err = loop_release_xfer(lo);
diff -urN linux-2.2.10-pre1/drivers/block/ns87415.c linux-2.2.10-pre2/drivers/block/ns87415.c
--- linux-2.2.10-pre1/drivers/block/ns87415.c	1999-03-15 16:11:29.000000000 -0800
+++ linux-2.2.10-pre2/drivers/block/ns87415.c	2003-08-15 15:06:23.000000000 -0700
@@ -49,8 +49,25 @@
 	new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
 
 	if (new != *old) {
+		unsigned char stat;
+
+		/*
+		 * Don't change DMA engine settings while Write Buffers
+		 * are busy.
+		 */
+		(void) pci_read_config_byte(dev, 0x43, &stat);
+		while (stat & 0x03) {
+			udelay(1);
+			(void) pci_read_config_byte(dev, 0x43, &stat);
+		}
+
 		*old = new;
 		(void) pci_write_config_dword(dev, 0x40, new);
+
+		/*
+		 * And let things settle...
+		 */
+		udelay(10);
 	}
 
 	__restore_flags(flags);	/* local CPU only */
diff -urN linux-2.2.10-pre1/drivers/char/bttv.c linux-2.2.10-pre2/drivers/char/bttv.c
--- linux-2.2.10-pre1/drivers/char/bttv.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/char/bttv.c	2003-08-15 15:06:23.000000000 -0700
@@ -543,6 +543,8 @@
         { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
         /* Pixelview PlayTV (bt878) */
         { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }},
+        /* "Leadtek WinView 601", */
+        { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}},
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
 
@@ -2036,6 +2038,41 @@
 				I2CWrite(&(btv->i2c), I2C_TDA9850,
 					TDA9850_CON3, con3, 1);
 			}
+		   
+		       /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
+		        if (btv->type == BTTV_WINVIEW_601) { 
+			   int bits_out, loops, vol, data;
+
+			   /* 32 levels logarithmic */
+			   vol = 32 - ((v.volume>>11));
+			   /* units */
+                           bits_out = (PT2254_DBS_IN_2>>(vol%5));
+			   /* tens */
+                           bits_out |= (PT2254_DBS_IN_10>>(vol/5));
+			   bits_out |= PT2254_L_CHANEL | PT2254_R_CHANEL;
+			   data = btread(BT848_GPIO_DATA);
+			   data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
+				      WINVIEW_PT2254_STROBE);
+			   for (loops = 17; loops >= 0 ; loops--) {
+				if (bits_out & (1<<loops))
+				   data |=  WINVIEW_PT2254_DATA;
+				else
+				   data &= ~WINVIEW_PT2254_DATA;
+			       btwrite(data, BT848_GPIO_DATA);
+			       udelay(5);
+			       data |= WINVIEW_PT2254_CLK;
+			       btwrite(data, BT848_GPIO_DATA);
+			       udelay(5);
+			       data &= ~WINVIEW_PT2254_CLK;
+			       btwrite(data, BT848_GPIO_DATA);
+			   }
+			   data |=  WINVIEW_PT2254_STROBE;
+			   data &= ~WINVIEW_PT2254_DATA;
+			   btwrite(data, BT848_GPIO_DATA);
+			   udelay(10);			   
+			   data &= ~WINVIEW_PT2254_STROBE;
+			   btwrite(data, BT848_GPIO_DATA);
+			}
 			if (btv->have_msp3400) 
 			{
                                 i2c_control_device(&(btv->i2c),
@@ -3033,6 +3070,9 @@
 		case BTTV_VHX:
 			strcpy(btv->video_dev.name,"BT848(Aimslab-VHX)");
  			break;
+	        case BTTV_WINVIEW_601:
+			strcpy(btv->video_dev.name,"BT848(Leadtek WinView 601)");
+ 			break;	   
 	}
 	printk("%s\n",btv->video_dev.name);
 	audio(btv, AUDIO_MUTE);
diff -urN linux-2.2.10-pre1/drivers/char/bttv.h linux-2.2.10-pre2/drivers/char/bttv.h
--- linux-2.2.10-pre1/drivers/char/bttv.h	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/char/bttv.h	2003-08-15 15:06:23.000000000 -0700
@@ -210,6 +210,7 @@
 #define BTTV_VHX           0x0e
 #define BTTV_ZOLTRIX       0x0f
 #define BTTV_PIXVIEWPLAYTV 0x10
+#define BTTV_WINVIEW_601   0x11
 
 #define AUDIO_TUNER        0x00
 #define AUDIO_RADIO        0x01
@@ -260,4 +261,12 @@
 #define TEA6300_FA         0x04		/* fader control */
 #define TEA6300_SW         0x05		/* mute and source switch */
 
+#define PT2254_L_CHANEL 0x10
+#define PT2254_R_CHANEL 0x08
+#define PT2254_DBS_IN_2 0x400
+#define PT2254_DBS_IN_10 0x20000
+#define WINVIEW_PT2254_CLK  0x40
+#define WINVIEW_PT2254_DATA 0x20
+#define WINVIEW_PT2254_STROBE 0x80
+
 #endif
diff -urN linux-2.2.10-pre1/drivers/misc/parport_pc.c linux-2.2.10-pre2/drivers/misc/parport_pc.c
--- linux-2.2.10-pre1/drivers/misc/parport_pc.c	2003-08-15 15:06:23.000000000 -0700
+++ linux-2.2.10-pre2/drivers/misc/parport_pc.c	2003-08-15 15:06:23.000000000 -0700
@@ -371,12 +371,12 @@
 	 * copy. Some ports _do_ allow reads, so bypass the software
 	 * copy here.  In addition, some bits aren't writable. */
 	r = inb (pb->base+CONTROL);
-	if ((r & 0x3f) == w) {
+	if ((r & 0xf) == w) {
 		w = 0xe;
 		parport_pc_write_control (pb, w);
 		r = inb (pb->base+CONTROL);
 		parport_pc_write_control (pb, 0xc);
-		if ((r & 0x3f) == w)
+		if ((r & 0xf) == w)
 			return PARPORT_MODE_PCSPP;
 	}
 
diff -urN linux-2.2.10-pre1/drivers/net/cosa.c linux-2.2.10-pre2/drivers/net/cosa.c
--- linux-2.2.10-pre1/drivers/net/cosa.c	1999-03-07 15:47:46.000000000 -0800
+++ linux-2.2.10-pre2/drivers/net/cosa.c	2003-08-15 15:06:23.000000000 -0700
@@ -2,6 +2,9 @@
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
+ * 
+ * 	5/25/1999 : Marcelo Tosatti <marcelo@conectiva.com.br>
+ * 		fixed a deadlock in cosa_sppp_open 
  *
  *  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
@@ -598,6 +601,7 @@
 	if (chan->usage != 0) {
 		printk(KERN_WARNING "%s: sppp_open called with usage count %d\n",
 			chan->name, chan->usage);
+		spin_unlock_irqrestore(&chan->cosa->lock, flags);
 		return -EBUSY;
 	}
 	chan->setup_rx = sppp_setup_rx;
diff -urN linux-2.2.10-pre1/drivers/net/eexpress.c linux-2.2.10-pre2/drivers/net/eexpress.c
--- linux-2.2.10-pre1/drivers/net/eexpress.c	1999-05-06 23:14:36.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/eexpress.c	2003-08-15 15:06:23.000000000 -0700
@@ -81,7 +81,20 @@
  * ftp's, which is significantly better than I get in DOS, so the overhead of
  * stopping and restarting the CU with each transmit is not prohibitive in
  * practice.
+ *
+ * Update by David Woodhouse 11/5/99:
+ *
+ * I've seen "CU wedged" messages in 16-bit mode, on the Alpha architecture.
+ * I assume that this is because 16-bit accesses are actually handled as two
+ * 8-bit accesses.
  */
+
+#ifdef __alpha__
+#define LOCKUP16 1
+#endif
+#ifndef LOCKUP16
+#define LOCKUP16 0
+#endif
   
 #include <linux/config.h>
 #include <linux/module.h>
@@ -297,7 +310,7 @@
 	outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config);
 }
 
-static inline short int SHADOW(short int addr)
+static inline unsigned short int SHADOW(short int addr)
 {
 	addr &= 0x1f;
 	if (addr > 0xf) addr += 0x3ff0;
@@ -400,7 +413,10 @@
 	outb(0,ioaddr+SIGNAL_CA);
 	free_irq(irq,dev);
 	outb(i586_RST,ioaddr+EEPROM_Ctrl);
-	release_region(ioaddr,16);
+	release_region(ioaddr, EEXP_IO_EXTENT);
+	release_region(ioaddr+0x4000, 16);
+	release_region(ioaddr+0x8000, 16);
+	release_region(ioaddr+0xc000, 16);
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -887,7 +903,7 @@
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short ioaddr = dev->base_addr;
 
-	if (lp->width) {
+	if (LOCKUP16 || lp->width) {
 		/* Stop the CU so that there is no chance that it
 		   jumps off to a bogus address while we are writing the
 		   pointer to the next transmit packet in 8-bit mode -- 
@@ -927,7 +943,7 @@
 	if (lp->tx_head != lp->tx_reap)
 		dev->tbusy = 0;
 
-	if (lp->width) {
+	if (LOCKUP16 || lp->width) {
 		/* Restart the CU so that the packet can actually
 		   be transmitted. (Zoltan Szilagyi 10-12-96) */
 		scb_command(dev, SCB_CUresume);
diff -urN linux-2.2.10-pre1/drivers/net/irda/actisys.c linux-2.2.10-pre2/drivers/net/irda/actisys.c
--- linux-2.2.10-pre1/drivers/net/irda/actisys.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/actisys.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,16 +1,16 @@
 /*********************************************************************
  *                
  * Filename:      actisys.c
- * Version:       0.5
+ * Version:       0.8
  * 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 Apr 12 11:56:35 1999
+ * Modified at:   Mon May 10 15:12:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -36,15 +36,14 @@
 #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 actisys_reset( struct irda_device *dev, int unused);
-static void actisys_open( struct irda_device *idev, int type);
-static void actisys_close( struct irda_device *dev);
+static void actisys_reset(struct irda_device *dev, int unused);
+static void actisys_open(struct irda_device *idev, int type);
+static void actisys_close(struct irda_device *dev);
 static void actisys_change_speed( struct irda_device *dev, int baudrate);
-static void actisys_reset( struct irda_device *dev, int unused);
-static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos);
+static void actisys_reset(struct irda_device *dev, int unused);
+static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos);
 
 /* These are the baudrates supported */
 static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
@@ -58,17 +57,37 @@
 	actisys_init_qos,
 };
 
-__initfunc(void actisys_init(void))
+static struct dongle dongle_plus = {
+	ACTISYS_PLUS_DONGLE,
+	actisys_open,
+	actisys_close,
+	actisys_reset,
+	actisys_change_speed,
+	actisys_init_qos,
+};
+
+__initfunc(int actisys_init(void))
 {
-	irtty_register_dongle(&dongle);
+	int ret;
+
+	ret = irda_device_register_dongle(&dongle);
+	if (ret < 0)
+		return ret;
+	ret = irda_device_register_dongle(&dongle_plus);
+	if (ret < 0) {
+		irda_device_unregister_dongle(&dongle);
+		return ret;
+	}	
+	return 0;
 }
 
 void actisys_cleanup(void)
 {
-	irtty_unregister_dongle(&dongle);
+	irda_device_unregister_dongle(&dongle);
+	irda_device_unregister_dongle(&dongle_plus);
 }
 
-static void actisys_open( struct irda_device *idev, int type)
+static void actisys_open(struct irda_device *idev, int type)
 {
 	strcat(idev->description, " <-> actisys");
 
@@ -78,8 +97,11 @@
 	MOD_INC_USE_COUNT;
 }
 
-static void actisys_close( struct irda_device *dev)
+static void actisys_close(struct irda_device *idev)
 {
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
 	MOD_DEC_USE_COUNT;
 }
 
@@ -90,25 +112,16 @@
  *    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)
+static void actisys_change_speed(struct irda_device *idev, int baudrate)
 {
-        struct irtty_cb *self;
-        struct tty_struct *tty;
-        struct termios old_termios;
-	int cflag;
         int current_baudrate;
         int index = 0;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) idev->priv;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRTTY_MAGIC, return;);
-
 	current_baudrate = idev->qos.baud_rate.value;
 
 	/* Find the correct baudrate index for the currently used baudrate */
@@ -117,69 +130,34 @@
 
         DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
 
-	if ( !self->tty)
-		return;
-
-	tty = self->tty;
-
 	/* Cycle through avaiable baudrates until we reach the correct one */
-        while ( current_baudrate != baudrate) {	
-                DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n",
-                       baud_rates[index]);
+        while (current_baudrate != baudrate) {	
+                DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
+		      baud_rates[index]);
 		
 		/* Set DTR, clear RTS */
-		irtty_set_dtr_rts(tty, TRUE, FALSE);
+		irda_device_set_dtr_rts(idev, TRUE, FALSE);
 		
 		/* Wait at a few ms */
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(2);
 
 		/* Set DTR, Set RTS */
-		irtty_set_dtr_rts(tty, TRUE, TRUE);
+		irda_device_set_dtr_rts(idev, TRUE, TRUE);
 		
 		/* Wait at a few ms again */
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout( 2);
+		schedule_timeout(2);
 
                 /* Go to next baudrate */
-		if ( idev->io.dongle_id == ACTISYS_DONGLE)
+		if (idev->io.dongle_id == ACTISYS_DONGLE)
                         index = (index+1) % 4; /* IR-220L */
 		else
                         index = (index+1) % 5; /* IR-220L+ */
 
                 current_baudrate = 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);
-	cflag = tty->termios->c_cflag;
-
-	cflag &= ~CBAUD;
-
-        switch ( baudrate) {
-        case 9600:
-        default:
-		cflag |= B9600;
-		break;
-	case 19200:
-		cflag |= B19200;
-		break;
-	case 38400:
-		cflag |= B38400;
-		break;
-	case 57600:
-		cflag |= B57600;
-		break;
-	case 115200:
-		cflag |= B115200;
-		break;
-	}
-
-	/* Change speed of serial port */
-	tty->termios->c_cflag = cflag;
-	tty->driver.set_termios( tty, &old_termios);
+	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",baud_rates[index]);
 }
 
 /*
@@ -191,32 +169,20 @@
  *    	1. Clear DTR for a few ms.
  *
  */
-static void actisys_reset( struct irda_device *idev, int unused)
+static void actisys_reset(struct irda_device *idev, int unused)
 {
-	struct irtty_cb *self;
-        struct tty_struct *tty;
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) idev->priv;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRTTY_MAGIC, return;);
-
-	tty = self->tty;
-	if ( !tty)
-		return;
-
 	/* Clear DTR */
-	irtty_set_dtr_rts(tty, FALSE, TRUE);
+	irda_device_set_dtr_rts(idev, FALSE, TRUE);
 
 	/* Sleep 10-20 ms*/
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(2);
 	
 	/* Go back to normal mode */
-	irtty_set_dtr_rts(tty, TRUE, TRUE);
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
 	
 	idev->qos.baud_rate.value = 9600;
 }
@@ -227,12 +193,12 @@
  *    Initialize QoS capabilities
  *
  */
-static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos)
+static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos)
 {
 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 
 	/* Remove support for 38400 if this is not a 220L+ dongle */
-	if ( idev->io.dongle_id == ACTISYS_DONGLE)
+	if (idev->io.dongle_id == ACTISYS_DONGLE)
 		qos->baud_rate.bits &= ~IR_38400;
 	
 	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
@@ -251,8 +217,7 @@
  */
 int init_module(void)
 {
-	actisys_init();
-	return(0);
+	return actisys_init();
 }
 
 /*
diff -urN linux-2.2.10-pre1/drivers/net/irda/Config.in linux-2.2.10-pre2/drivers/net/irda/Config.in
--- linux-2.2.10-pre1/drivers/net/irda/Config.in	1999-03-07 15:26:43.000000000 -0800
+++ linux-2.2.10-pre2/drivers/net/irda/Config.in	2003-08-15 15:06:23.000000000 -0700
@@ -1,18 +1,24 @@
 mainmenu_option next_comment
 comment 'Infrared-port device drivers'
 
-dep_tristate 'IrTTY (uses serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
-if [ "$CONFIG_IRTTY_SIR" != "n" ]; then
-  comment '   Dongle support' 
-  bool '   Serial dongle support' CONFIG_DONGLE
-  if [ "$CONFIG_DONGLE" != "n" ]; then
-    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
+comment 'SIR device drivers'
+dep_tristate 'IrTTY (uses Linux serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
+dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
+
+comment 'FIR device drivers'
+dep_tristate 'NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
+dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
+dep_tristate 'Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA
+dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
+
+comment 'Dongle support' 
+bool 'Serial dongle support' CONFIG_DONGLE
+if [ "$CONFIG_DONGLE" != "n" ]; then
+  dep_tristate '   ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA
+  dep_tristate '   ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA
+  dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
+  dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
+  dep_tristate '   Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
 fi
-dep_tristate '  NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
-dep_tristate '  Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
-dep_tristate '  Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA
+
 endmenu
diff -urN linux-2.2.10-pre1/drivers/net/irda/esi.c linux-2.2.10-pre2/drivers/net/irda/esi.c
--- linux-2.2.10-pre1/drivers/net/irda/esi.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/esi.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,17 +1,17 @@
 /*********************************************************************
  *                
  * Filename:      esi.c
- * Version:       1.2
+ * Version:       1.4
  * 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 Apr 12 11:55:30 1999
+ * Modified at:   Mon May 10 15:13:12 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  esi.c
  *
+ *     Copyright (c) 1998-1999, Dag Brattli, <dagb@cs.uit.no>
  *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *     Copyright (c) 1998, Dag Brattli,  <dagb@cs.uit.no>
  *     All Rights Reserved.
  *
  *     This program is free software; you can redistribute it and/or
@@ -41,11 +41,11 @@
 #include <net/irda/irtty.h>
 #include <net/irda/dongle.h>
 
-static void esi_open( struct irda_device *idev, int type);
-static void esi_close( struct irda_device *driver);
-static void esi_change_speed( struct irda_device *idev, int baud);
-static void esi_reset( struct irda_device *idev, int unused);
-static void esi_qos_init( struct irda_device *idev, struct qos_info *qos);
+static void esi_open(struct irda_device *idev, int type);
+static void esi_close(struct irda_device *driver);
+static void esi_change_speed(struct irda_device *idev, int baud);
+static void esi_reset(struct irda_device *idev, int unused);
+static void esi_qos_init(struct irda_device *idev, struct qos_info *qos);
 
 static struct dongle dongle = {
 	ESI_DONGLE,
@@ -58,17 +58,17 @@
 
 __initfunc(int esi_init(void))
 {
-	return irtty_register_dongle(&dongle);
+	return irda_device_register_dongle(&dongle);
 }
 
 void esi_cleanup(void)
 {
-	irtty_unregister_dongle( &dongle);
+	irda_device_unregister_dongle(&dongle);
 }
 
-static void esi_open( struct irda_device *idev, int type)
+static void esi_open(struct irda_device *idev, int type)
 {
-	strcat( idev->description, " <-> esi");
+	strcat(idev->description, " <-> esi");
 
 	idev->io.dongle_id = type;
 	idev->flags |= IFF_DONGLE;
@@ -76,8 +76,11 @@
 	MOD_INC_USE_COUNT;
 }
 
-static void esi_close( struct irda_device *driver)
-{
+static void esi_close(struct irda_device *idev)
+{		
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
 	MOD_DEC_USE_COUNT;
 }
 
@@ -87,54 +90,30 @@
  *    Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
  *
  */
-static void esi_change_speed( struct irda_device *idev, int baud)
+static void esi_change_speed(struct irda_device *idev, int baud)
 {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
 	int dtr, rts;
-        struct termios old_termios;
-	int cflag;
-	
-	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;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
-
-	cflag &= ~CBAUD;
-
 	switch (baud) {
 	case 19200:
-		cflag |= B19200;
 		dtr = TRUE;
 		rts = FALSE;
 		break;
 	case 115200:
-		cflag |= B115200;
 		dtr = rts = TRUE;
 		break;
 	case 9600:
 	default:
-		cflag |= B9600;
 		dtr = FALSE;
 		rts = TRUE;
 		break;
 	}
-	/* Change speed of serial driver */
-	tty->termios->c_cflag = cflag;
-	tty->driver.set_termios(tty, &old_termios);
 
-	irtty_set_dtr_rts(tty, dtr, rts);
+	/* Change speed of dongle */
+	irda_device_set_dtr_rts(idev, dtr, rts);
 }
 
 static void esi_reset( struct irda_device *idev, int unused)
@@ -148,14 +127,17 @@
  *    Init QoS capabilities for the dongle
  *
  */
-static void esi_qos_init( struct irda_device *idev, struct qos_info *qos)
+static void esi_qos_init(struct irda_device *idev, struct qos_info *qos)
 {
 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
 	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
 }
 
 #ifdef MODULE
-		
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
+
 /*
  * Function init_module (void)
  *
diff -urN linux-2.2.10-pre1/drivers/net/irda/girbil.c linux-2.2.10-pre2/drivers/net/irda/girbil.c
--- linux-2.2.10-pre1/drivers/net/irda/girbil.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/girbil.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      girbil.c
- * Version:       1.0
+ * Version:       1.1
  * 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:   Sat Apr 10 19:53:12 1999
+ * Modified at:   Mon May 10 16:01:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -80,19 +80,19 @@
 	girbil_init_qos,
 };
 
-__initfunc(void girbil_init(void))
+__initfunc(int girbil_init(void))
 {
-	irtty_register_dongle(&dongle);
+	return irda_device_register_dongle(&dongle);
 }
 
 void girbil_cleanup(void)
 {
-	irtty_unregister_dongle(&dongle);
+	irda_device_unregister_dongle(&dongle);
 }
 
 static void girbil_open(struct irda_device *idev, int type)
 {
-	strcat( idev->description, " <-> girbil");
+	strcat(idev->description, " <-> girbil");
 
 	idev->io.dongle_id = type;
 	idev->flags |= IFF_DONGLE;
@@ -100,8 +100,11 @@
 	MOD_INC_USE_COUNT;
 }
 
-static void girbil_close(struct irda_device *dev)
+static void girbil_close(struct irda_device *idev)
 {
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
 	MOD_DEC_USE_COUNT;
 }
 
@@ -114,71 +117,42 @@
  */
 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);
+	irda_device_set_dtr_rts(idev, FALSE, TRUE);
 
 	/* Write control bytes */
-	if (tty->driver.write)
-		tty->driver.write(self->tty, 0, control, 2);
+	irda_device_raw_write(idev, 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);	
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
 }
 
 /*
@@ -193,44 +167,32 @@
  */
 void girbil_reset(struct irda_device *idev, int unused)
 {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
 	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
 
 	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);
+	irda_device_set_dtr_rts(idev, 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);
+	irda_device_set_dtr_rts(idev, FALSE, TRUE);
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(2);
 
 	/* Write control byte */
-	if (tty->driver.write)
-		tty->driver.write(self->tty, 0, &control, 1);
+	irda_device_raw_write(idev, &control, 1);
 
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(2);
 
 	/* Go back to normal mode */
-	irtty_set_dtr_rts(tty, TRUE, TRUE);
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
 }
 
 /*
@@ -258,8 +220,7 @@
  */
 int init_module(void)
 {
-	girbil_init();
-	return(0);
+	return girbil_init();
 }
 
 /*
diff -urN linux-2.2.10-pre1/drivers/net/irda/irport.c linux-2.2.10-pre2/drivers/net/irda/irport.c
--- linux-2.2.10-pre1/drivers/net/irda/irport.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/irport.c	2003-08-15 15:06:23.000000000 -0700
@@ -64,58 +64,168 @@
 
 #define IO_EXTENT 8
 
-/* static unsigned int io[]  = { 0x3e8, ~0, ~0, ~0 }; */
-/* static unsigned int irq[] = { 11, 0, 0, 0 }; */
+/* 
+ * Currently you'll need to set these values using insmod like this:
+ * insmod irport io=0x3e8 irq=11
+ */
+static unsigned int io[]  = { ~0, ~0, ~0, ~0 };
+static unsigned int irq[] = { 0, 0, 0, 0 };
+
+static unsigned int qos_mtt_bits = 0x03;
+
+static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+static char *driver_name = "irport";
+
+static int irport_open(int i, unsigned int iobase, unsigned int irq);
+static int irport_close(struct irda_device *idev);
 
 static void irport_write_wakeup(struct irda_device *idev);
 static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
 static void irport_receive(struct irda_device *idev);
 
+static int  irport_net_init(struct device *dev);
+static int  irport_net_open(struct device *dev);
+static int  irport_net_close(struct device *dev);
+static void irport_wait_until_sent(struct irda_device *idev);
+static int  irport_is_receiving(struct irda_device *idev);
+static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
+static int  irport_raw_write(struct irda_device *idev, __u8 *buf, int len);
+
 __initfunc(int irport_init(void))
 {
-/* 	int i; */
+ 	int i;
 
-/* 	for ( i=0; (io[i] < 2000) && (i < 4); i++) { */
-/* 		int ioaddr = io[i]; */
-/* 		if (check_region(ioaddr, IO_EXTENT)) */
-/* 			continue; */
-/* 		if (irport_open( i, io[i], io2[i], irq[i], dma[i]) == 0) */
-/* 			return 0; */
-/* 	} */
-/* 	return -ENODEV; */
-	return 0;
+ 	for (i=0; (io[i] < 2000) && (i < 4); i++) {
+ 		int ioaddr = io[i];
+ 		if (check_region(ioaddr, IO_EXTENT))
+ 			continue;
+ 		if (irport_open(i, io[i], irq[i]) == 0)
+ 			return 0;
+ 	}
+	/* 
+	 * Maybe something failed, but we can still be usable for FIR drivers 
+	 */
+ 	return 0;
 }
 
 /*
- * Function pc87108_cleanup ()
+ * Function irport_cleanup ()
  *
- *    Close all configured chips
+ *    Close all configured ports
  *
  */
 #ifdef MODULE
 static void irport_cleanup(void)
 {
-/* 	int i; */
+ 	int i;
 
         DEBUG( 4, __FUNCTION__ "()\n");
 
-	/* for ( i=0; i < 4; i++) { */
-/* 		if ( dev_self[i]) */
-/* 			irport_close( &(dev_self[i]->idev)); */
-/* 	} */
+	for (i=0; i < 4; i++) {
+ 		if (dev_self[i])
+ 			irport_close(dev_self[i]);
+ 	}
 }
 #endif /* MODULE */
 
-/*
- * Function irport_open (void)
- *
- *    Start IO port 
- *
- */
-int irport_open(int iobase)
+static int irport_open(int i, unsigned int iobase, unsigned int irq)
 {
-	DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
+	struct irda_device *idev;
+	int ret;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+/* 	if (irport_probe(iobase, irq) == -1) */
+/* 		return -1; */
+
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL);
+	if (idev == NULL) {
+		printk( KERN_ERR "IrDA: Can't allocate memory for "
+			"IrDA control block!\n");
+		return -ENOMEM;
+	}
+	memset(idev, 0, sizeof(struct irda_device));
+   
+	/* Need to store self somewhere */
+	dev_self[i] = idev;
+
+	/* Initialize IO */
+	idev->io.iobase2   = iobase;
+        idev->io.irq2      = irq;
+        idev->io.io_ext    = IO_EXTENT;
+        idev->io.fifo_size = 16;
+
+	/* Lock the port that we need */
+	ret = check_region(idev->io.iobase2, idev->io.io_ext);
+	if (ret < 0) { 
+		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		       idev->io.iobase2);
+		/* w83977af_cleanup( self->idev);  */
+		return -ENODEV;
+	}
+	request_region(idev->io.iobase2, idev->io.io_ext, idev->name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&idev->qos);
+	
+	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200;
+
+	idev->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&idev->qos);
+	
+	idev->flags = IFF_SIR|IFF_PIO;
+
+	/* Specify which buffer allocation policy we need */
+	idev->rx_buff.flags = GFP_KERNEL;
+	idev->tx_buff.flags = GFP_KERNEL;
+
+	idev->rx_buff.truesize = 4000; 
+	idev->tx_buff.truesize = 4000;
+	
+	/* Initialize callbacks */
+	idev->change_speed    = irport_change_speed;
+	idev->wait_until_sent = irport_wait_until_sent;
+        idev->is_receiving    = irport_is_receiving;
+	idev->set_dtr_rts     = irport_set_dtr_rts;
+	idev->raw_write       = irport_raw_write;
+
+	/* Override the network functions we need to use */
+	idev->netdev.init            = irport_net_init;
+	idev->netdev.hard_start_xmit = irport_hard_xmit;
+	idev->netdev.open            = irport_net_open;
+	idev->netdev.stop            = irport_net_close;
+
+	/* Open the IrDA device */
+	irda_device_open(idev, driver_name, NULL);
+	
+	return 0;
+}
+
+static int irport_close(struct irda_device *idev)
+{
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 
+	/* Release the PORT that this driver is using */
+	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
+	      idev->io.iobase2);
+	release_region(idev->io.iobase2, idev->io.io_ext);
+
+	irda_device_close(idev);
+
+	kfree(idev);
+
+	return 0;
+}
+
+void irport_start(int iobase)
+{
 	/* Initialize UART */
 	outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
 	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
@@ -123,24 +233,29 @@
 	/* Turn on interrups */
 	outb((UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER);
 
-	return 0;
+}
+
+void irport_stop(int iobase)
+{
+	/* Reset UART */
+	outb(0, iobase+UART_MCR);
+	
+	/* Turn off interrupts */
+	outb(0, iobase+UART_IER);
 }
 
 /*
- * Function irport_cleanup ()
+ * Function irport_probe (void)
  *
- *    Stop IO port
+ *    Start IO port 
  *
  */
-void irport_close(int iobase) 
+int irport_probe(int iobase)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
 
-	/* Reset UART */
-	outb(0, iobase+UART_MCR);
 
-	/* Turn off interrupts */
-	outb(0, iobase+UART_IER);
+	return 0;
 }
 
 /*
@@ -149,14 +264,23 @@
  *    Set speed of port to specified baudrate
  *
  */
-void irport_change_speed( int iobase, int speed) 
+void irport_change_speed(struct irda_device *idev, int speed)
 {
+	int iobase; 
 	int fcr;    /* FIFO control reg */
 	int lcr;    /* Line control reg */
 	int divisor;
 
 	DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
 
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase2;
+	
+	/* Update accounting for new speed */
+	idev->io.baudrate = speed;
+
 	/* Turn off interrupts */
 	outb(0, iobase+UART_IER); 
 
@@ -373,8 +497,145 @@
 	idev->netdev.interrupt = 0;
 }
 
+static int irport_net_init(struct device *dev)
+{
+	/* Set up to be a normal IrDA network device driver */
+	irda_device_setup(dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+/*
+ * Function irport_net_open (dev)
+ *
+ *    
+ *
+ */
+static int irport_net_open(struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+
+	ASSERT(dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+
+	iobase = idev->io.iobase2;
+
+	if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name, 
+			(void *) idev)) {
+		return -EAGAIN;
+	}
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	MOD_INC_USE_COUNT;
+
+	irport_start(iobase);
+
+	return 0;
+}
+
+/*
+ * Function irport_net_close (idev)
+ *
+ *    
+ *
+ */
+static int irport_net_close(struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+
+	ASSERT(dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	iobase = idev->io.iobase2;
+
+	irport_stop(iobase);
+
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	free_irq(idev->io.irq2, idev);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static void irport_wait_until_sent(struct irda_device *idev)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(60*HZ/1000);
+}
+
+static int irport_is_receiving(struct irda_device *idev)
+{
+	return (idev->rx_buff.state != OUTSIDE_FRAME);
+}
+
+/*
+ * Function irtty_set_dtr_rts (tty, dtr, rts)
+ *
+ *    This function can be used by dongles etc. to set or reset the status
+ *    of the dtr and rts lines
+ */
+static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+{
+	int iobase;
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase2;
+
+	if (dtr)
+		dtr = UART_MCR_DTR;
+	if (rts)
+		rts = UART_MCR_RTS;
+
+	outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR);
+}
+
+static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len)
+{
+	int iobase;
+	int actual = 0;
+
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	iobase = idev->io.iobase2;
+
+	/* Tx FIFO should be empty! */
+	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
+		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		return -1;
+	}
+        
+	/* Fill FIFO with current frame */
+	while (actual < len) {
+		/* Transmit next byte */
+		outb(buf[actual], iobase+UART_TX);
+		actual++;
+	}
+
+	return actual;
+}
+
 #ifdef MODULE
 
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(irq, "1-4i");
+
 /*
  * Function cleanup_module (void)
  *
@@ -393,11 +654,7 @@
  */
 int init_module(void)
 {
-	if (irport_init() < 0) {
-		cleanup_module();
-		return 1;
-	}
-	return(0);
+	return irport_init();
 }
 
 #endif /* MODULE */
diff -urN linux-2.2.10-pre1/drivers/net/irda/irtty.c linux-2.2.10-pre2/drivers/net/irda/irtty.c
--- linux-2.2.10-pre1/drivers/net/irda/irtty.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/irtty.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,12 +6,12 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Thu Apr 22 09:20:24 1999
+ * Modified at:   Mon May 10 15:45:50 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>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -38,19 +38,21 @@
 #include <net/irda/irlap.h>
 #include <net/irda/timer.h>
 #include <net/irda/irda_device.h>
-#include <linux/kmod.h>
 
 static hashbin_t *irtty = NULL;
-static hashbin_t *dongles = NULL;
 
 static struct tty_ldisc irda_ldisc;
 
-static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int qos_mtt_bits = 0x03;      /* 5 ms or more */
+
+static int  irtty_hard_xmit(struct sk_buff *skb, struct device *dev);
 static void irtty_wait_until_sent(struct irda_device *driver);
-static int irtty_is_receiving(struct irda_device *idev);
-static int irtty_net_init(struct device *dev);
-static int irtty_net_open(struct device *dev);
-static int irtty_net_close(struct device *dev);
+static int  irtty_is_receiving(struct irda_device *idev);
+static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
+static int  irtty_raw_write(struct irda_device *idev, __u8 *buf, int len);
+static int  irtty_net_init(struct device *dev);
+static int  irtty_net_open(struct device *dev);
+static int  irtty_net_close(struct device *dev);
 
 static int  irtty_open(struct tty_struct *tty);
 static void irtty_close(struct tty_struct *tty);
@@ -73,13 +75,6 @@
 		return -ENOMEM;
 	}
 
-	dongles = hashbin_new(HB_LOCAL);
-	if (dongles == NULL) {
-		printk(KERN_WARNING 
-		       "IrDA: Can't allocate dongles hashbin!\n");
-		return -ENOMEM;
-	}
-
 	/* Fill in our line protocol discipline, and register it */
 	memset(&irda_ldisc, 0, sizeof( irda_ldisc));
 
@@ -132,7 +127,6 @@
 	 *  function to hashbin_destroy().
 	 */
 	hashbin_delete(irtty, NULL);
-	hashbin_delete(dongles, NULL);
 }
 #endif /* MODULE */
 
@@ -201,7 +195,7 @@
 	/* The only value we must override it the baudrate */
 	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200;
-	self->idev.qos.min_turn_time.bits = 0x0f;
+	self->idev.qos.min_turn_time.bits = qos_mtt_bits;
 	self->idev.flags = IFF_SIR | IFF_PIO;
 	irda_qos_bits_to_value(&self->idev.qos);
 
@@ -216,7 +210,8 @@
 	/* Initialize callbacks */
 	self->idev.change_speed    = irtty_change_speed;
  	self->idev.is_receiving    = irtty_is_receiving;
-	/* self->idev.is_tbusy        = irtty_is_tbusy; */
+	self->idev.set_dtr_rts     = irtty_set_dtr_rts;
+	self->idev.raw_write       = irtty_raw_write;
 	self->idev.wait_until_sent = irtty_wait_until_sent;
 
 	/* Override the network functions we need to use */
@@ -248,10 +243,6 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRTTY_MAGIC, return;);
 
-	/* We are not using any dongle anymore! */
-	if (self->dongle_q)
-		self->dongle_q->dongle->close(&self->idev);
-
 	/* Remove driver */
 	irda_device_close(&self->idev);
 
@@ -359,68 +350,6 @@
 }
 
 /*
- * Function irtty_init_dongle (self, type)
- *
- *    Initialize attached dongle. Warning, must be called with a process
- *    context!
- */
-static void irtty_init_dongle(struct irtty_cb *self, int type)
-{
-	struct dongle_q *node;
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-
-#ifdef CONFIG_KMOD
-	/* Try to load the module needed */
-	switch( type) {
-	case ESI_DONGLE:
-		MESSAGE("IrDA: Trying to initialize ESI dongle!\n");
-		request_module("esi");
-		break;
-	case TEKRAM_DONGLE:
-		MESSAGE("IrDA: Trying to initialize Tekram dongle!\n");
-		request_module("tekram");
-		break;
-	case ACTISYS_DONGLE:     /* FALLTHROUGH */
-	case ACTISYS_PLUS_DONGLE:
-		MESSAGE("IrDA: Trying to initialize ACTiSYS dongle!\n");
-		request_module("actisys");
-		break;
-	case GIRBIL_DONGLE:
-		MESSAGE("IrDA: Trying to initialize GIrBIL dongle!\n");
-		request_module("girbil");
-		break;
-	default:
-		ERROR("Unknown dongle type!\n");
-		return;
-	}
-#endif /* CONFIG_KMOD */
-
-	node = hashbin_find(dongles, type, NULL);
-	if ( !node) {
-		ERROR("Unable to find requested dongle\n");
-		return;
-	}
-	self->dongle_q = node;
-
-	/* Use this change speed function instead of the default */
-	self->idev.change_speed = node->dongle->change_speed;
-
-	/*
-	 * Now initialize the dongle!
-	 */
-	node->dongle->open(&self->idev, type);
-	node->dongle->qos_init(&self->idev, &self->idev.qos);
-	
-	/* Reset dongle */
-	node->dongle->reset(&self->idev, 0);
-
-	/* Set to default baudrate */
-	node->dongle->change_speed(&self->idev, 9600);
-}
-
-/*
  * Function irtty_ioctl (tty, file, cmd, arg)
  *
  *     The Swiss army knife of system calls :-)
@@ -452,7 +381,7 @@
 		break;
 	case IRTTY_IOCTDONGLE:
 		/* Initialize dongle */
-		irtty_init_dongle(self, (int) arg);
+		irda_device_init_dongle(&self->idev, (int) arg);
 		break;
 	default:
 		return -ENOIOCTLCMD;
@@ -645,54 +574,23 @@
 	tty_wait_until_sent(self->tty, 0);
 }
 
-int irtty_register_dongle(struct dongle *dongle)
-{
-	struct dongle_q *new;
-	
-	/* Check if this compressor has been registred before */
-	if ( hashbin_find ( dongles, dongle->type, NULL)) {
-		DEBUG( 0, __FUNCTION__ "(), Dongle already registered\n");
-                return 0;
-        }
-	
-	/* Make new IrDA dongle */
-        new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
-        if (new == NULL)
-                return -1;
-		
-	memset(new, 0, sizeof( struct dongle_q));
-        new->dongle = dongle;
-
-	/* Insert IrDA dongle into hashbin */
-	hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL);
-	
-        return 0;
-}
-
-void irtty_unregister_dongle(struct dongle *dongle)
-{
-	struct dongle_q *node;
-
-	node = hashbin_remove(dongles, dongle->type, NULL);
-	if (!node) {
-		ERROR(__FUNCTION__ "(), dongle not found!\n");
-		return;
-	}
-	kfree(node);
-}
-
-
 /*
  * Function irtty_set_dtr_rts (tty, dtr, rts)
  *
  *    This function can be used by dongles etc. to set or reset the status
  *    of the dtr and rts lines
  */
-void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts)
+static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
 {
+	struct tty_struct *tty;
+	struct irtty_cb *self;
 	mm_segment_t fs;
 	int arg = 0;
 
+	self = (struct irtty_cb *) idev->priv;
+
+	tty = self->tty;
+
 #ifdef TIOCM_OUT2 /* Not defined for ARM */
 	arg = TIOCM_OUT2;
 #endif
@@ -718,6 +616,25 @@
 	set_fs(fs);
 }
 
+static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len)
+{
+	struct irtty_cb *self;
+	int actual = 0;
+
+	ASSERT(idev != NULL, return 0;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	
+	self = (struct irtty_cb *) idev->priv;
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRTTY_MAGIC, return 0;);
+
+	if (self->tty->driver.write)
+		actual = self->tty->driver.write(self->tty, 0, buf, len);
+
+	return actual;
+}
+
 static int irtty_net_init(struct device *dev)
 {
 	/* Set up to be a normal IrDA network device driver */
@@ -760,6 +677,8 @@
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("IrDA TTY device driver");
 
+MODULE_PARM(qos_mtt_bits, "i");
+
 /*
  * Function init_module (void)
  *
diff -urN linux-2.2.10-pre1/drivers/net/irda/litelink.c linux-2.2.10-pre2/drivers/net/irda/litelink.c
--- linux-2.2.10-pre1/drivers/net/irda/litelink.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.10-pre2/drivers/net/irda/litelink.c	2003-08-15 15:06:23.000000000 -0700
@@ -0,0 +1,209 @@
+/*********************************************************************
+ *                
+ * Filename:      litelink.c
+ * Version:       1.0
+ * Description:   Driver for the Parallax LiteLink dongle
+ * Status:        Stable
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri May  7 12:50:33 1999
+ * Modified at:   Mon May 10 15:12:18 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.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/ioctls.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/dongle.h>
+
+static void litelink_reset(struct irda_device *dev, int unused);
+static void litelink_open(struct irda_device *idev, int type);
+static void litelink_close(struct irda_device *dev);
+static void litelink_change_speed( struct irda_device *dev, int baudrate);
+static void litelink_reset(struct irda_device *dev, int unused);
+static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos);
+
+/* These are the baudrates supported */
+static int baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
+
+static struct dongle dongle = {
+	LITELINK_DONGLE,
+	litelink_open,
+	litelink_close,
+	litelink_reset,
+	litelink_change_speed,
+	litelink_init_qos,
+};
+
+__initfunc(int litelink_init(void))
+{
+	return irda_device_register_dongle(&dongle);
+}
+
+void litelink_cleanup(void)
+{
+	irda_device_unregister_dongle(&dongle);
+}
+
+static void litelink_open(struct irda_device *idev, int type)
+{
+	strcat(idev->description, " <-> litelink");
+
+        idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void litelink_close(struct irda_device *idev)
+{
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function litelink_change_speed (tty, baud)
+ *
+ *    Change speed of the Litelink dongle. To cycle through the available 
+ *    baud rates, pulse RTS low for a few ms.  
+ */
+static void litelink_change_speed(struct irda_device *idev, int baudrate)
+{
+        int i;
+	
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	/* Clear RTS to reset dongle */
+	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+
+	/* Go back to normal mode */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+	
+	/* Cycle through avaiable baudrates until we reach the correct one */
+	for (i=0; i<5 && baud_rates[i] != baudrate; i++) {
+
+		/* Set DTR, clear RTS */
+		irda_device_set_dtr_rts(idev, FALSE, TRUE);
+		
+		/* Sleep a minimum of 15 us */
+		udelay(15);
+		
+		/* Set DTR, Set RTS */
+		irda_device_set_dtr_rts(idev, TRUE, TRUE);
+		
+		/* Sleep a minimum of 15 us */
+		udelay(15);
+        }
+}
+
+/*
+ * Function litelink_reset (dev)
+ *
+ *      Reset the Litelink type dongle. Warning, this function must only be
+ *      called with a process context!
+ *
+ */
+static void litelink_reset(struct irda_device *idev, int unused)
+{
+	struct irtty_cb *self;
+        struct tty_struct *tty;
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	/* Power on dongle */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+
+	/* Clear RTS to reset dongle */
+	irda_device_set_dtr_rts(idev, TRUE, FALSE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+
+	/* Go back to normal mode */
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+	
+	/* Sleep a minimum of 15 us */
+	udelay(15);
+
+	/* This dongles speed defaults to 115200 bps */
+	idev->qos.baud_rate.value = 115200;
+}
+
+/*
+ * Function litelink_init_qos (qos)
+ *
+ *    Initialize QoS capabilities
+ *
+ */
+static void litelink_init_qos( struct irda_device *idev, struct qos_info *qos)
+{
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Parallax Litelink dongle driver");	
+		
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Litelink module
+ *
+ */
+int init_module(void)
+{
+	return litelink_init();
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Litelink module
+ *
+ */
+void cleanup_module(void)
+{
+	litelink_cleanup();
+}
+
+#endif
diff -urN linux-2.2.10-pre1/drivers/net/irda/Makefile linux-2.2.10-pre2/drivers/net/irda/Makefile
--- linux-2.2.10-pre1/drivers/net/irda/Makefile	1999-04-15 05:42:41.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/Makefile	2003-08-15 15:06:23.000000000 -0700
@@ -20,6 +20,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_IRPORT_SIR),y)
+L_OBJS += irport.o
+else
+  ifeq ($(CONFIG_IRPORT_SIR),m)
+  M_OBJS += irport.o
+  endif
+endif
+
 ifeq ($(CONFIG_NSC_FIR),y)
 L_OBJS += pc87108.o
 else
@@ -44,6 +52,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_TOSHIBA_FIR),y)
+L_OBJS += toshoboe.o
+else
+  ifeq ($(CONFIG_TOSHIBA_FIR),m)
+  M_OBJS += toshoboe.o
+  endif
+endif
+
 ifeq ($(CONFIG_ESI_DONGLE),y)
 L_OBJS += esi.o
 else
@@ -76,6 +92,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_LITELINK_DONGLE),y)
+L_OBJS += litelink.o
+else
+  ifeq ($(CONFIG_LITELINK_DONGLE),m)
+  M_OBJS += litelink.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 clean:
diff -urN linux-2.2.10-pre1/drivers/net/irda/pc87108.c linux-2.2.10-pre2/drivers/net/irda/pc87108.c
--- linux-2.2.10-pre1/drivers/net/irda/pc87108.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/pc87108.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Tue Apr 20 11:11:39 1999
+ * Modified at:   Sun May  9 12:57:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
  *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
  *     Copyright (c) 1998 Actisys Corp., www.actisys.com
  *     All Rights Reserved
@@ -67,6 +67,7 @@
 #define BROKEN_DONGLE_ID
 
 static char *driver_name = "pc87108";
+static int qos_mtt_bits = 0x07;  /* 1 ms or more */
 
 #define CHIP_IO_EXTENT 8
 
@@ -219,7 +220,7 @@
 	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
 	
-	idev->qos.min_turn_time.bits = 0x07;
+	idev->qos.min_turn_time.bits = qos_mtt_bits;
 	irda_qos_bits_to_value( &idev->qos);
 	
 	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
@@ -259,8 +260,9 @@
  *    Close driver instance
  *
  */
-static int pc87108_close( struct irda_device *idev)
+static int pc87108_close(struct irda_device *idev)
 {
+	struct pc87108 *self;
 	int iobase;
 
 	DEBUG( 4, __FUNCTION__ "()\n");
@@ -269,13 +271,16 @@
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 
         iobase = idev->io.iobase;
+	self = (struct pc87108 *) idev->priv;
 
 	/* Release the PORT that this driver is using */
 	DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", 
 	       idev->io.iobase);
-	release_region( idev->io.iobase, idev->io.io_ext);
+	release_region(idev->io.iobase, idev->io.io_ext);
+
+	irda_device_close(idev);
 
-	irda_device_close( idev);
+	kfree(self);
 
 	return 0;
 }
@@ -805,7 +810,6 @@
 	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
 		  DMA_MODE_WRITE);
 	
-	/* idev->media_busy = TRUE; */
 	idev->io.direction = IO_XMIT;
 	
 	/* Choose transmit DMA channel  */ 
@@ -973,7 +977,7 @@
  *
  *    
  */
-static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase)
+static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
 {
 	struct sk_buff *skb;
 	struct pc87108 *self;
@@ -988,8 +992,6 @@
 	/* Save current bank */
 	bank = inb( iobase+BSR);
 	
-	iobase = idev->io.iobase;
-
 	/* Read status FIFO */
 	switch_bank(iobase, BANK5);
 	while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) {
@@ -1003,18 +1005,18 @@
 	}
 	
 	/* Try to process all entries in status FIFO */
-	switch_bank( iobase, BANK0);
-	while ( st_fifo->len) {
+	switch_bank(iobase, BANK0);
+	while (st_fifo->len) {
       
 		/* Get first entry */
-		status = st_fifo->entries[ st_fifo->head].status;
-		len    = st_fifo->entries[ st_fifo->head].len;
+		status = st_fifo->entries[st_fifo->head].status;
+		len    = st_fifo->entries[st_fifo->head].len;
 		st_fifo->head++;
 		st_fifo->len--;
 
 		/* Check for errors */
-		if ( status & FRM_ST_ERR_MSK) {
-			if ( status & FRM_ST_LOST_FR) {
+		if (status & FRM_ST_ERR_MSK) {
+			if (status & FRM_ST_LOST_FR) {
 				/* Add number of lost frames to stats */
 				idev->stats.rx_errors += len;	
 			} else {
@@ -1188,8 +1190,8 @@
 	bank = inb( iobase+BSR);
 	
 	/* Status event, or end of frame detected in FIFO */
-	if ( eir & (EIR_SFIF_EV|EIR_LS_EV)) {
-		if ( pc87108_dma_receive_complete( idev, iobase)) {
+	if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
+		if (pc87108_dma_receive_complete( idev, iobase)) {
 
 			/* Wait for next status FIFO interrupt */
 			new_ier |= IER_SFIF_IE;
@@ -1460,6 +1462,11 @@
 
 #ifdef MODULE
 
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
+
 /*
  * Function init_module (void)
  *
diff -urN linux-2.2.10-pre1/drivers/net/irda/tekram.c linux-2.2.10-pre2/drivers/net/irda/tekram.c
--- linux-2.2.10-pre1/drivers/net/irda/tekram.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/tekram.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,15 +1,15 @@
 /*********************************************************************
  *                
  * Filename:      tekram.c
- * Version:       1.0
+ * Version:       1.1
  * 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:   Tue Apr 13 16:33:54 1999
+ * Modified at:   Mon May 10 16:10:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -62,15 +62,15 @@
 
 __initfunc(int tekram_init(void))
 {
-	return irtty_register_dongle(&dongle);
+	return irda_device_register_dongle(&dongle);
 }
 
 void tekram_cleanup(void)
 {
-	irtty_unregister_dongle( &dongle);
+	irda_device_unregister_dongle(&dongle);
 }
 
-static void tekram_open( struct irda_device *idev, int type)
+static void tekram_open(struct irda_device *idev, int type)
 {
 	strcat(idev->description, " <-> tekram");
 
@@ -80,8 +80,11 @@
 	MOD_INC_USE_COUNT;
 }
 
-static void tekram_close( struct irda_device *dev)
-{
+static void tekram_close(struct irda_device *idev)
+{		
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
 	MOD_DEC_USE_COUNT;
 }
 
@@ -101,79 +104,49 @@
  *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
  *       after
  */
-static void tekram_change_speed( struct irda_device *dev, int baud)
+static void tekram_change_speed(struct irda_device *idev, int baud)
 {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
-	struct termios old_termios;
-	int cflag;
 	__u8 byte;
 	
 	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(dev != NULL, return;);
-	ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) dev->priv;
-	
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-	
-	if (!self->tty)
-		return;
-
-	tty = self->tty;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	
-	old_termios = *(tty->termios);
-	cflag = tty->termios->c_cflag;
-
-	cflag &= ~CBAUD;
-
 	switch (baud) {
 	default:
-		/* FALLTHROUGH */
 	case 9600:
-		cflag |= B9600;
 		byte = TEKRAM_PW|TEKRAM_9600;
 		break;
 	case 19200:
-		cflag |= B19200;
 		byte = TEKRAM_PW|TEKRAM_19200;
 		break;
 	case 34800:
-		cflag |= B38400;
 		byte = TEKRAM_PW|TEKRAM_38400;
 		break;
 	case 57600:
-		cflag |= B57600;
 		byte = TEKRAM_PW|TEKRAM_57600;
 		break;
 	case 115200:
-		cflag |= B115200;
 		byte = TEKRAM_PW|TEKRAM_115200;
 		break;
 	}
 
 	/* Set DTR, Clear RTS */
-	irtty_set_dtr_rts(tty, TRUE, FALSE);
+	irda_device_set_dtr_rts(idev, TRUE, FALSE);
 	
 	/* Wait at least 7us */
 	udelay(7);
 
 	/* Write control byte */
-	if (tty->driver.write)
-		tty->driver.write(self->tty, 0, &byte, 1);
+	irda_device_raw_write(idev, &byte, 1);
 	
 	/* Wait at least 100 ms */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(100));
         
 	/* Set DTR, Set RTS */
-	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);	
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
 }
 
 /*
@@ -189,41 +162,27 @@
  *        3. clear DTR to SPACE state, wait at least 50 us for further 
  *         operation
  */
-void tekram_reset(struct irda_device *dev, int unused)
+void tekram_reset(struct irda_device *idev, int unused)
 {
-	struct irtty_cb *self;
-	struct tty_struct *tty;
-
-	DEBUG(4, __FUNCTION__ "()\n");
-
-	ASSERT(dev != NULL, return;);
-	ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;);
-	
-	self = (struct irtty_cb *) dev->priv;
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-
-	tty = self->tty;
-	if (!tty)
-		return;
-
 	/* Power off dongle */
-	irtty_set_dtr_rts(tty, FALSE, FALSE);
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
 
 	/* Sleep 50 ms */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(50));
 
 	/* Clear DTR, Set RTS */
-	irtty_set_dtr_rts(tty, FALSE, TRUE); 
+	irda_device_set_dtr_rts(idev, FALSE, TRUE); 
 
 	/* Should sleep 1 ms, but 10-20 should not do any harm */
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(MSECS_TO_JIFFIES(20));
 
 	/* Set DTR, Set RTS */
-	irtty_set_dtr_rts(tty, TRUE, TRUE);
+	irda_device_set_dtr_rts(idev, TRUE, TRUE);
 	
 	udelay(50);
 
diff -urN linux-2.2.10-pre1/drivers/net/irda/toshoboe.c linux-2.2.10-pre2/drivers/net/irda/toshoboe.c
--- linux-2.2.10-pre1/drivers/net/irda/toshoboe.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.10-pre2/drivers/net/irda/toshoboe.c	2003-08-15 15:06:23.000000000 -0700
@@ -0,0 +1,901 @@
+/*********************************************************************
+ *                
+ * Filename:      toshoboe.c
+ * Version:       0.1
+ * Description:   Driver for the Toshiba OBOE (or type-O or 700 or 701)
+ *                FIR Chipset. 
+ * Status:        Experimental.
+ * Author:        James McKenzie <james@fishsoup.dhs.org>
+ * Created at:    Sat May 8  12:35:27 1999
+ * 
+ *     Copyright (c) 1999 James McKenzie, 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 James McKenzie nor Cambridge University admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Applicable Models : Libretto 100CT. and many more
+ *     Toshiba refers to this chip as the type-O IR port.
+ *
+ ********************************************************************/
+
+/* This driver is experimental, I have only three ir devices */
+/* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */
+/* an hp printer, this works fine at 4MBPS with my HP printer */
+
+static char *rcsid = "$Id: toshoboe.c,v 1.5 1999/05/12 12:24:39 root Exp root $";
+
+/* 
+ * $Log: toshoboe.c,v $
+ * Revision 1.5  1999/05/12 12:24:39  root
+ * *** empty log message ***
+ *
+ * Revision 1.4  1999/05/12 11:55:08  root
+ * *** empty log message ***
+ *
+ * Revision 1.3  1999/05/09 01:33:12  root
+ * *** empty log message ***
+ *
+ * Revision 1.2  1999/05/09 01:30:38  root
+ * *** empty log message ***
+ *
+ * Revision 1.1  1999/05/09 01:25:04  root
+ * Initial revision
+ * 
+ */
+
+/* Define this to have only one frame in the XMIT or RECV queue */
+/* Toshiba's drivers do this, but it disables back to back tansfers */
+/* I think that the chip may have some problems certainly, I have */
+/* seen it jump over tasks in the taskfile->xmit with this turned on */
+#define ONETASK
+
+/* To adjust the number of tasks in use edit toshoboe.h */
+
+/* Define this to enable FIR and MIR support */
+#define ENABLE_FAST
+
+/* Number of ports this driver can support, you also need to edit dev_self below */
+#define NSELFS 4
+
+/* Size of IO window */
+#define CHIP_IO_EXTENT	0x1f
+
+/* Transmit and receive buffer sizes, adjust at your peril */
+#define RX_BUF_SZ 	4196
+#define TX_BUF_SZ	4196
+
+/* No user servicable parts below here */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/toshoboe.h>
+
+static char *driver_name = "toshoboe";
+
+static struct toshoboe_cb *dev_self[NSELFS + 1] =
+{NULL, NULL, NULL, NULL, NULL};
+
+/* Shutdown the chip and point the taskfile reg somewhere else */
+static void 
+toshoboe_stopchip (struct toshoboe_cb *self)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  outb_p (0x0e, OBOE_REG_11);
+
+  outb_p (0x00, OBOE_RST);
+  outb_p (0x3f, OBOE_TFP2);     /*Write the taskfile address */
+  outb_p (0xff, OBOE_TFP1);
+  outb_p (0xff, OBOE_TFP0);
+  outb_p (0x0f, OBOE_REG_1B);
+  outb_p (0xff, OBOE_REG_1A);
+  outb_p (0x00, OBOE_ISR);      /*FIXME: should i do this to disbale ints */
+  outb_p (0x80, OBOE_RST);
+  outb_p (0xe, OBOE_LOCK);
+}
+
+/*Set the baud rate */
+static void 
+toshoboe_setbaud (struct toshoboe_cb *self, int baud)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
+
+  cli ();
+  switch (baud)
+    {
+    case 2400:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0xbf, OBOE_UDIV);
+      break;
+    case 4800:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x5f, OBOE_UDIV);
+      break;
+    case 9600:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x2f, OBOE_UDIV);
+      break;
+    case 19200:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x17, OBOE_UDIV);
+      break;
+    case 38400:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0xb, OBOE_UDIV);
+      break;
+    case 57600:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x7, OBOE_UDIV);
+      break;
+    case 115200:
+      outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+      outb_p (0x3, OBOE_UDIV);
+      break;
+    case 1152000:
+      outb_p (OBOE_PMDL_MIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_MIR, OBOE_SMDL);
+      outb_p (0x1, OBOE_UDIV);
+      break;
+    case 4000000:
+      outb_p (OBOE_PMDL_FIR, OBOE_PMDL);
+      outb_p (OBOE_SMDL_FIR, OBOE_SMDL);
+      outb_p (0x0, OBOE_UDIV);
+      break;
+    }
+
+  sti ();
+
+  outb_p (0x00, OBOE_RST);
+  outb_p (0x80, OBOE_RST);
+  outb_p (0x01, OBOE_REG_9);
+
+}
+
+/* Wake the chip up and get it looking at the taskfile */
+static void 
+toshoboe_startchip (struct toshoboe_cb *self)
+{
+  __u32 physaddr;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+
+  outb_p (0, OBOE_LOCK);
+  outb_p (0, OBOE_RST);
+  outb_p (OBOE_NTR_VAL, OBOE_NTR);
+  outb_p (0xf0, OBOE_REG_D);
+  outb_p (0xff, OBOE_ISR);
+  outb_p (0x0f, OBOE_REG_1A);
+  outb_p (0xff, OBOE_REG_1B);
+
+
+  physaddr = virt_to_bus (self->taskfile);
+
+  outb_p ((physaddr >> 0x0a) & 0xff, OBOE_TFP0);
+  outb_p ((physaddr >> 0x12) & 0xff, OBOE_TFP1);
+  outb_p ((physaddr >> 0x1a) & 0x3f, OBOE_TFP2);
+
+  outb_p (0x0e, OBOE_REG_11);
+  outb_p (0x80, OBOE_RST);
+
+  toshoboe_setbaud (self, 9600);
+
+}
+
+/*Let the chip look at memory */
+static void 
+toshoboe_enablebm (struct toshoboe_cb *self)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+  pci_set_master (self->pdev);
+}
+
+/*Don't let the chip look at memory */
+static void 
+toshoboe_disablebm (struct toshoboe_cb *self)
+{
+  __u8 command;
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
+  command &= ~PCI_COMMAND_MASTER;
+  pci_write_config_byte (self->pdev, PCI_COMMAND, command);
+
+}
+
+/*setup the taskfile */
+static void 
+toshoboe_initbuffs (struct toshoboe_cb *self)
+{
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  cli ();
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      self->taskfile->xmit[i].len = 0;
+      self->taskfile->xmit[i].control = 0x00;
+      self->taskfile->xmit[i].buffer = virt_to_bus (self->xmit_bufs[i]);
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      self->taskfile->recv[i].len = 0;
+      self->taskfile->recv[i].control = 0x83;
+      self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]);
+    }
+
+  sti ();
+}
+
+
+/*Transmit something */
+static int 
+toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev)
+{
+  struct irda_device *idev;
+  struct toshoboe_cb *self;
+  int mtt, len;
+
+  idev = (struct irda_device *) dev->priv;
+  ASSERT (idev != NULL, return 0;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return 0;);
+
+
+#ifdef ONETASK
+  if (self->txpending)
+    return -EBUSY;
+
+  self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
+
+  self->txs &= 0x3f;
+
+#endif
+
+  if (self->taskfile->xmit[self->txs].control)
+    return -EBUSY;
+
+
+  if (inb_p (OBOE_RST) & OBOE_RST_WRAP)
+    {
+      len = async_wrap_skb (skb, self->xmit_bufs[self->txs], TX_BUF_SZ);
+    }
+  else
+    {
+      len = skb->len;
+      memcpy (self->xmit_bufs[self->txs], skb->data, len);
+    }
+  self->taskfile->xmit[self->txs].len = len & 0x0fff;
+
+
+
+  outb_p (0, OBOE_RST);
+  outb_p (0x1e, OBOE_REG_11);
+
+  self->taskfile->xmit[self->txs].control = 0x84;
+
+  mtt = irda_get_mtt (skb);
+  if (mtt)
+    udelay (mtt);
+
+  self->txpending++;
+
+  /*FIXME: ask about tbusy,media_busy stuff, for the moment */
+  /*tbusy means can't queue any more */
+#ifndef ONETASK
+  if (self->txpending == TX_SLOTS)
+    {
+#else
+  {
+#endif
+    if (irda_lock ((void *) &dev->tbusy) == FALSE)
+      return -EBUSY;
+  }
+
+  outb_p (0x80, OBOE_RST);
+  outb_p (1, OBOE_REG_9);
+
+  self->txs++;
+  self->txs %= TX_SLOTS;
+
+  dev_kfree_skb (skb);
+
+  return 0;
+}
+
+/*interrupt handler */
+static void 
+toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+  struct irda_device *idev = (struct irda_device *) dev_id;
+  struct toshoboe_cb *self;
+  __u8 irqstat;
+  struct sk_buff *skb;
+
+  if (idev == NULL)
+    {
+      printk (KERN_WARNING "%s: irq %d for unknown device.\n",
+              driver_name, irq);
+      return;
+    }
+
+  self = idev->priv;
+
+  if (!self)
+    return;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  irqstat = inb_p (OBOE_ISR);
+
+/* woz it us */
+  if (!(irqstat & 0xf8))
+    return;
+
+  outb_p (irqstat, OBOE_ISR);   /*Acknologede it */
+
+
+/* Txdone */
+  if (irqstat & OBOE_ISR_TXDONE)
+    {
+      self->txpending--;
+
+      idev->stats.tx_packets++;
+
+      idev->media_busy = FALSE;
+      idev->netdev.tbusy = 0;
+
+      mark_bh (NET_BH);
+    }
+
+  if (irqstat & OBOE_ISR_RXDONE)
+    {
+
+#ifdef ONETASK
+      self->rxs = inb_p (OBOE_RCVT);
+      self->rxs += (RX_SLOTS - 1);
+      self->rxs %= RX_SLOTS;
+#else
+      while (self->taskfile->recv[self->rxs].control == 0)
+#endif
+        {
+          int len = self->taskfile->recv[self->rxs].len;
+	
+	  if (len>2) len-=2;
+
+          skb = dev_alloc_skb (len + 1);
+          if (skb)
+            {
+              skb_reserve (skb, 1);
+
+              skb_put (skb, len);
+              memcpy (skb->data, self->recv_bufs[self->rxs], len);
+
+              idev->stats.rx_packets++;
+              skb->dev = &idev->netdev;
+              skb->mac.raw = skb->data;
+              skb->protocol = htons (ETH_P_IRDA);
+            }
+          else
+            {
+              printk (KERN_INFO __FUNCTION__
+                      "(), memory squeeze, dropping frame.\n");
+            }
+
+
+
+          self->taskfile->recv[self->rxs].control = 0x83;
+          self->taskfile->recv[self->rxs].len = 0x0;
+
+          self->rxs++;
+          self->rxs %= RX_SLOTS;
+
+          if (skb)
+            netif_rx (skb);
+
+        }
+
+    }
+
+  if (irqstat & OBOE_ISR_20)
+    {
+      printk (KERN_WARNING "Oboe_irq: 20\n");
+    }
+  if (irqstat & OBOE_ISR_10)
+    {
+      printk (KERN_WARNING "Oboe_irq: 10\n");
+    }
+  if (irqstat & 0x8)
+    {
+      /*FIXME: I think this is a TX or RX error of some sort */
+
+      idev->stats.tx_errors++;
+      idev->stats.rx_errors++;
+
+    }
+
+
+}
+
+
+
+/* Change the baud rate */
+static void 
+toshoboe_change_speed (struct irda_device *idev, int speed)
+{
+  struct toshoboe_cb *self;
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (idev != NULL, return;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return;);
+
+  idev->io.baudrate = speed;
+
+  toshoboe_setbaud (self, speed);
+
+}
+
+
+/* Check all xmit_tasks finished */
+static void 
+toshoboe_wait_until_sent (struct irda_device *idev)
+{
+  struct toshoboe_cb *self;
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (idev != NULL, return;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return;);
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      while (self->taskfile->xmit[i].control)
+        {
+          current->state = TASK_INTERRUPTIBLE;
+          schedule_timeout (6);
+        }
+    }
+
+}
+
+static int 
+toshoboe_is_receiving (struct irda_device *idev)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+/*FIXME Can't tell! */
+  return (FALSE);
+}
+
+
+static int 
+toshoboe_net_init (struct device *dev)
+{
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  /* Setup to be a normal IrDA network device driver */
+  irda_device_setup (dev);
+
+  /* Insert overrides below this line! */
+  return 0;
+}
+
+
+
+
+static int 
+toshoboe_net_open (struct device *dev)
+{
+  struct irda_device *idev;
+  struct toshoboe_cb *self;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (dev != NULL, return -1;);
+  idev = (struct irda_device *) dev->priv;
+
+  ASSERT (idev != NULL, return 0;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+  self = idev->priv;
+  ASSERT (self != NULL, return 0;);
+
+  if (request_irq (idev->io.irq, toshoboe_interrupt,
+                   SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev))
+    {
+
+      return -EAGAIN;
+    }
+
+  toshoboe_initbuffs (self);
+  toshoboe_enablebm (self);
+  toshoboe_startchip (self);
+
+
+  cli ();
+
+  /*FIXME: need to test this carefully to check which one */
+  /*of the two possible startup logics the chip uses */
+  /*although it won't make any difference if no-one xmits durining init */
+  /*and none what soever if using ONETASK */
+
+  self->rxs = inb_p (OBOE_RCVT);
+  self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
+
+#ifdef 0
+  self->rxs = 0;
+  self->txs = 0;
+#endif
+#ifdef 0
+  self->rxs = RX_SLOTS - 1;
+  self->txs = 0;
+#endif
+
+
+  self->txpending = 0;
+
+  sti ();
+
+
+  dev->tbusy = 0;
+  dev->interrupt = 0;
+  dev->start = 1;
+
+  MOD_INC_USE_COUNT;
+
+  return 0;
+
+}
+
+static int 
+toshoboe_net_close (struct device *dev)
+{
+  struct irda_device *idev;
+  struct toshoboe_cb *self;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (dev != NULL, return -1;);
+  idev = (struct irda_device *) dev->priv;
+
+  ASSERT (idev != NULL, return 0;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+  dev->tbusy = 1;
+  dev->start = 0;
+
+
+  self = idev->priv;
+
+  ASSERT (self != NULL, return 0;);
+
+  free_irq (idev->io.irq, (void *) idev);
+
+  toshoboe_stopchip (self);
+  toshoboe_disablebm (self);
+
+  MOD_DEC_USE_COUNT;
+
+  return 0;
+
+}
+
+
+
+#ifdef MODULE
+
+static int 
+toshoboe_close (struct irda_device *idev)
+{
+  struct toshoboe_cb *self;
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  ASSERT (idev != NULL, return -1;);
+  ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+  self = idev->priv;
+
+  ASSERT (self != NULL, return -1;);
+
+  toshoboe_stopchip (self);
+
+  release_region (idev->io.iobase, idev->io.io_ext);
+
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      kfree (self->xmit_bufs[i]);
+      self->xmit_bufs[i] = NULL;
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      kfree (self->recv_bufs[i]);
+      self->recv_bufs[i] = NULL;
+    }
+
+
+  kfree (self->taskfilebuf);
+  self->taskfilebuf = NULL;
+  self->taskfile = NULL;
+
+
+  irda_device_close (idev);
+
+  return (0);
+
+}
+
+#endif
+
+
+
+static int 
+toshoboe_open (struct pci_dev *pci_dev)
+{
+  struct toshoboe_cb *self;
+  struct irda_device *idev;
+  int i = 0;
+  int ok=0;
+
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  while (dev_self[i])
+    i++;
+
+  if (i == NSELFS)
+    {
+      printk (KERN_ERR "Oboe: No more instances available");
+      return -ENOMEM;
+    }
+
+  self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL);
+
+  if (self == NULL)
+    {
+      printk (KERN_ERR "IrDA: Can't allocate memory for "
+              "IrDA control block!\n");
+      return -ENOMEM;
+    }
+
+  memset (self, 0, sizeof (struct toshoboe_cb));
+
+
+  dev_self[i] = self;
+
+  self->pdev = pci_dev;
+  self->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+
+  idev = &self->idev;
+
+  /*Setup idev */
+
+  idev->io.iobase = self->base;
+  idev->io.irq = pci_dev->irq;
+  idev->io.io_ext = CHIP_IO_EXTENT;
+
+  /* Lock the port that we need */
+  i = check_region (idev->io.iobase, idev->io.io_ext);
+  if (i < 0)
+    {
+      DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+             idev->io.iobase);
+
+      dev_self[i] = NULL;
+      kfree (self);
+
+      return -ENODEV;
+    }
+
+  request_region (idev->io.iobase, idev->io.io_ext, driver_name);
+
+  irda_init_max_qos_capabilies (&idev->qos);
+
+  idev->qos.baud_rate.bits = IR_2400 | /*IR_4800 | */ IR_9600 | IR_19200 |
+    IR_115200;
+#ifdef ENABLE_FAST
+ idev->qos.baud_rate.bits|= IR_576000 | IR_1152000 | (IR_4000000 << 8);
+#endif
+
+  idev->qos.min_turn_time.bits = 0xff;  /*FIXME: what does this do? */
+
+  irda_qos_bits_to_value (&idev->qos);
+
+  idev->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+
+#ifdef ENABLE_FAST
+  idev->flags |= IFF_FIR;
+#endif
+
+  /* These aren't much use as we need to have a whole panoply of
+   * buffers running */
+
+  idev->rx_buff.flags = 0;
+  idev->tx_buff.flags = 0;
+  idev->rx_buff.truesize = 0;
+  idev->rx_buff.truesize = 0;
+
+  idev->change_speed = toshoboe_change_speed;
+  idev->wait_until_sent = toshoboe_wait_until_sent;
+  idev->is_receiving = toshoboe_is_receiving;
+
+  idev->netdev.init = toshoboe_net_init;
+  idev->netdev.hard_start_xmit = toshoboe_hard_xmit;
+  idev->netdev.open = toshoboe_net_open;
+  idev->netdev.stop = toshoboe_net_close;
+
+
+  /* Now setup the endless buffers we need */
+
+  self->txs = 0;
+  self->rxs = 0;
+
+  self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL | GFP_DMA);
+  if (!self->taskfilebuf) {
+	printk(KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
+	kfree(self);
+	return -ENOMEM;
+  }
+
+
+  memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN);
+
+  /*We need to align the taskfile on a taskfile size boundary */
+  {
+    __u32 addr;
+
+    addr = (__u32) self->taskfilebuf;
+    addr &= ~(sizeof (struct OboeTaskFile) - 1);
+    addr += sizeof (struct OboeTaskFile);
+
+    self->taskfile = (struct OboeTaskFile *) addr;
+  }
+
+  for (i = 0; i < TX_SLOTS; ++i)
+    {
+      self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
+      if (self->xmit_bufs[i]) ok++;
+    }
+
+  for (i = 0; i < RX_SLOTS; ++i)
+    {
+      self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
+      if (self->recv_bufs[i]) ok++;
+    }
+
+  if (ok!=RX_SLOTS+TX_SLOTS) {
+	printk(KERN_ERR  "toshoboe: kmalloc for buffers failed()\n");
+
+
+  for (i = 0; i < TX_SLOTS; ++i) if (self->xmit_bufs[i]) kfree(self->xmit_bufs[i]);
+  for (i = 0; i < RX_SLOTS; ++i) if (self->recv_bufs[i]) kfree(self->recv_bufs[i]);
+
+	kfree(self);
+	return -ENOMEM;
+
+  }
+
+
+  irda_device_open (idev, driver_name, self);
+
+  printk (KERN_WARNING "ToshOboe: Using ");
+#ifdef ONETASK
+  printk ("single");
+#else
+  printk ("multiple");
+#endif
+  printk (" tasks, version %s\n", rcsid);
+
+  return (0);
+}
+
+__initfunc (int toshoboe_init (void))
+{
+  struct pci_dev *pci_dev = NULL;
+  int found = 0;
+
+  do
+    {
+      pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA,
+                                 PCI_DEVICE_ID_FIR701, pci_dev);
+      if (pci_dev)
+        {
+          printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n",
+                  pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK,
+                  pci_dev->irq);
+
+          if (!toshoboe_open (pci_dev))
+            found++;
+        }
+
+    }
+  while (pci_dev);
+
+  if (found)
+    return 0;
+
+  return -ENODEV;
+}
+
+#ifdef MODULE
+
+static void 
+toshoboe_cleanup (void)
+{
+  int i;
+
+  DEBUG (4, __FUNCTION__ "()\n");
+
+  for (i = 0; i < 4; i++)
+    {
+      if (dev_self[i])
+        toshoboe_close (&(dev_self[i]->idev));
+    }
+}
+
+
+
+int 
+init_module (void)
+{
+  return toshoboe_init ();
+}
+
+
+void 
+cleanup_module (void)
+{
+  toshoboe_cleanup ();
+}
+
+
+#endif
diff -urN linux-2.2.10-pre1/drivers/net/irda/uircc.c linux-2.2.10-pre2/drivers/net/irda/uircc.c
--- linux-2.2.10-pre1/drivers/net/irda/uircc.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/uircc.c	2003-08-15 15:06:23.000000000 -0700
@@ -7,10 +7,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Dec 26 10:59:03 1998
- * Modified at:   Tue Apr 20 11:15:52 1999
+ * Modified at:   Mon May 10 22:11:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -216,7 +216,7 @@
 	idev->netdev.open            = uircc_net_open;
 	idev->netdev.stop            = uircc_net_close;
 
-	irport_open(iobase2);
+	irport_start(iobase2);
 
 	/* Open the IrDA device */
 	irda_device_open(idev, driver_name, self);
@@ -233,6 +233,7 @@
 #ifdef MODULE
 static int uircc_close(struct irda_device *idev)
 {
+	struct uircc_cb *self;
 	int iobase;
 	int status;
 
@@ -242,6 +243,7 @@
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 
         iobase = idev->io.iobase;
+	self = (struct uircc_cb *) idev->priv;
 
 	/* Some magic to disable FIR and enable SIR */
 	uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000);
@@ -249,7 +251,7 @@
 	/* Disable modem */
 	outb(0x00, iobase+UIRCC_CR10);
 
-	irport_close(idev->io.iobase2);
+	irport_stop(idev->io.iobase2);
 
 	/* Release the PORT that this driver is using */
 	DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
@@ -262,6 +264,8 @@
 	}
 	irda_device_close(idev);
 
+	kfree(self);
+
 	return 0;
 }
 #endif /* MODULE */
@@ -346,8 +350,8 @@
 	case 37600:
 	case 57600:
 	case 115200:
- 		irport_open(idev->io.iobase2);
-		irport_change_speed( idev->io.iobase2, speed);
+ 		irport_start(idev->io.iobase2);
+		irport_change_speed(idev, speed);
 
 		/* Some magic to disable FIR and enable SIR */
 		uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000);
@@ -363,7 +367,7 @@
 		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
-		irport_close(idev->io.iobase2);
+		irport_stop(idev->io.iobase2);
 
 		/* Some magic to disable SIR and enable FIR */
 		uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001);
diff -urN linux-2.2.10-pre1/drivers/net/irda/w83977af_ir.c linux-2.2.10-pre2/drivers/net/irda/w83977af_ir.c
--- linux-2.2.10-pre1/drivers/net/irda/w83977af_ir.c	1999-04-24 17:49:37.000000000 -0700
+++ linux-2.2.10-pre2/drivers/net/irda/w83977af_ir.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,16 +1,16 @@
 /*********************************************************************
  *                
  * Filename:      w83977af_ir.c
- * Version:       0.8
- * Description:   FIR/MIR driver for the Winbond W83977AF Super I/O chip
+ * Version:       1.0
+ * Description:   FIR driver for the Winbond W83977AF Super I/O chip
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Tue Apr 20 11:15:00 1999
+ * Modified at:   Thu May 13 08:03:27 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
  *     Copyright (c) 1998 Corel Computer Corp.
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -40,7 +40,7 @@
  ********************************************************************/
 
 #include <linux/module.h>
-
+ 
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
@@ -61,44 +61,45 @@
 #include <net/irda/w83977af.h>
 #include <net/irda/w83977af_ir.h>
 
-#define NETWINDER
+#define CONFIG_NETWINDER                 /* Adjust to NetWinder differences */
+#undef  CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */
+#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */
+#undef  CONFIG_USE_INTERNAL_TIMER        /* Just cannot make that timer work */
+#define CONFIG_USE_W977_PNP              /* Currently needed */
+#define PIO_MAX_SPEED       115200 
 
 static char *driver_name = "w83977af_ir";
+static int  qos_mtt_bits = 0x07;           /* 1 ms or more */
 
 #define CHIP_IO_EXTENT 8
 
 static unsigned int io[] = { 0x180, ~0, ~0, ~0 };
 static unsigned int irq[] = { 6, 0, 0, 0 };
-static unsigned int dma[] = { 0, 0, 0, 0 };
-
-static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+static unsigned int dma[] = 
+{ 1, 0, 0, 0 };
 
-/* For storing entries in the status FIFO */
-struct st_fifo_entry {
-	int status;
-	int len;
-};
+static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL};
 
 static struct st_fifo_entry prev;
 
 /* Some prototypes */
-static int  w83977af_open( int i, unsigned int iobase, unsigned int irq, 
-			   unsigned int dma);
-static int  w83977af_close( struct irda_device *idev);
-static int  w83977af_probe( int iobase, int irq, int dma);
+static int  w83977af_open(int i, unsigned int iobase, unsigned int irq, 
+                          unsigned int dma);
+static int  w83977af_close(struct irda_device *idev);
+static int  w83977af_probe(int iobase, int irq, int dma);
 static int  w83977af_dma_receive(struct irda_device *idev); 
 static int  w83977af_dma_receive_complete(struct irda_device *idev);
-static int  w83977af_hard_xmit( struct sk_buff *skb, struct device *dev);
-static int  w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
-static void w83977af_dma_write( struct irda_device *idev, int iobase);
-static void w83977af_change_speed( struct irda_device *idev, int baud);
+static int  w83977af_hard_xmit(struct sk_buff *skb, struct device *dev);
+static int  w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void w83977af_dma_write(struct irda_device *idev, int iobase);
+static void w83977af_change_speed(struct irda_device *idev, int baud);
 static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void w83977af_wait_until_sent( struct irda_device *idev);
-static int w83977af_is_receiving( struct irda_device *idev);
+static void w83977af_wait_until_sent(struct irda_device *idev);
+static int  w83977af_is_receiving(struct irda_device *idev);
 
-static int w83977af_net_init( struct device *dev);
-static int w83977af_net_open( struct device *dev);
-static int w83977af_net_close( struct device *dev);
+static int  w83977af_net_init(struct device *dev);
+static int  w83977af_net_open(struct device *dev);
+static int  w83977af_net_close(struct device *dev);
 
 /*
  * Function w83977af_init ()
@@ -108,13 +109,13 @@
  */
 __initfunc(int w83977af_init(void))
 {
-	int i;
+        int i;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
 
 	prev.status = 0;
 
-	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+	for (i=0; (io[i] < 2000) && (i < 4); i++) { 
 		int ioaddr = io[i];
 		if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
 			continue;
@@ -135,11 +136,11 @@
 {
 	int i;
 
-        DEBUG( 4, __FUNCTION__ "()\n");
+        DEBUG(4, __FUNCTION__ "()\n");
 
-	for ( i=0; i < 4; i++) {
-		if ( dev_self[i])
-			w83977af_close( dev_self[i]);
+	for (i=0; i < 4; i++) {
+		if (dev_self[i])
+			w83977af_close(&(dev_self[i]->idev));
 	}
 }
 #endif /* MODULE */
@@ -154,26 +155,29 @@
 		   unsigned int dma)
 {
 	struct irda_device *idev;
+        struct w83977af_ir *self;
 	int ret;
 
 	DEBUG( 0, __FUNCTION__ "()\n");
 
-	if ( w83977af_probe( iobase, irq, dma) == -1)
+	if (w83977af_probe(iobase, irq, dma) == -1)
 		return -1;
 
 	/*
 	 *  Allocate new instance of the driver
 	 */
-	idev = kmalloc( sizeof(struct irda_device), GFP_KERNEL);
-	if ( idev == NULL) {
+	self = kmalloc(sizeof(struct w83977af_ir), GFP_KERNEL);
+	if (self == NULL) {
 		printk( KERN_ERR "IrDA: Can't allocate memory for "
 			"IrDA control block!\n");
 		return -ENOMEM;
 	}
-	memset( idev, 0, sizeof(struct irda_device));
+	memset(self, 0, sizeof(struct w83977af_ir));
    
 	/* Need to store self somewhere */
-	dev_self[i] = idev;
+	dev_self[i] = self;
+
+	idev = &self->idev;
 
 	/* Initialize IO */
 	idev->io.iobase    = iobase;
@@ -183,17 +187,17 @@
         idev->io.fifo_size = 32;
 
 	/* Lock the port that we need */
-	ret = check_region( idev->io.iobase, idev->io.io_ext);
-	if ( ret < 0) { 
+	ret = check_region(idev->io.iobase, idev->io.io_ext);
+	if (ret < 0) { 
 		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
 		       idev->io.iobase);
 		/* w83977af_cleanup( self->idev);  */
 		return -ENODEV;
 	}
-	request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+	request_region(idev->io.iobase, idev->io.io_ext, idev->name);
 
 	/* Initialize QoS for this device */
-	irda_init_max_qos_capabilies( &idev->qos);
+	irda_init_max_qos_capabilies(&idev->qos);
 	
 	/* The only value we must override it the baudrate */
 
@@ -202,8 +206,8 @@
 		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
 
 	/* The HP HDLS-1100 needs 1 ms according to the specs */
-	idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
-	irda_qos_bits_to_value( &idev->qos);
+	idev->qos.min_turn_time.bits = qos_mtt_bits;
+	irda_qos_bits_to_value(&idev->qos);
 	
 	idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 
@@ -221,13 +225,13 @@
         idev->is_receiving    = w83977af_is_receiving;
 
 	/* Override the network functions we need to use */
-	idev->netdev.init = w83977af_net_init;
+	idev->netdev.init            = w83977af_net_init;
 	idev->netdev.hard_start_xmit = w83977af_hard_xmit;
-	idev->netdev.open = w83977af_net_open;
-	idev->netdev.stop = w83977af_net_close;
+	idev->netdev.open            = w83977af_net_open;
+	idev->netdev.stop            = w83977af_net_close;
 
 	/* Open the IrDA device */
-	irda_device_open( idev, driver_name, NULL);
+	irda_device_open(idev, driver_name, self);
 	
 	return 0;
 }
@@ -240,15 +244,18 @@
  */
 static int w83977af_close( struct irda_device *idev)
 {
+	struct w83977af_ir *self;
 	int iobase;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
 
-	ASSERT( idev != NULL, return -1;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 
         iobase = idev->io.iobase;
+	self = (struct w83977af_ir *) idev->priv;
 
+#ifdef CONFIG_USE_W977_PNP
 	/* enter PnP configuration mode */
 	w977_efm_enter();
 
@@ -258,13 +265,15 @@
 	w977_write_reg(0x30, 0x00);
 
 	w977_efm_exit();
-
+#endif /* CONFIG_USE_W977_PNP */
 	/* Release the PORT that this driver is using */
 	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
 	      idev->io.iobase);
-	release_region( idev->io.iobase, idev->io.io_ext);
+	release_region(idev->io.iobase, idev->io.io_ext);
+
+	irda_device_close(idev);
 
-	irda_device_close( idev);
+	kfree(self);
 
 	return 0;
 }
@@ -280,7 +289,7 @@
 	int version;
 	
 	DEBUG( 0, __FUNCTION__ "()\n");
-
+#ifdef CONFIG_USE_W977_PNP
 	/* Enter PnP configuration mode */
 	w977_efm_enter();
 
@@ -289,14 +298,14 @@
 	/* Configure PnP port, IRQ, and DMA channel */
 	w977_write_reg(0x60, (iobase >> 8) & 0xff);
 	w977_write_reg(0x61, (iobase) & 0xff);
-	/* w977_write_reg(0x70, 0x06); */
+
 	w977_write_reg(0x70, irq);
-#ifdef NETWINDER
-	w977_write_reg(0x74, dma+1); /* Netwinder uses one higher than Linux */
+#ifdef CONFIG_NETWINDER
+	w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */
 #else
 	w977_write_reg(0x74, dma);   
 #endif
-	w977_write_reg(0x75, dma);   /* Disable Tx DMA */
+	w977_write_reg(0x75, 0x04);  /* Disable Tx DMA */
 	
 	/* Set append hardware CRC, enable IR bank selection */	
 	w977_write_reg(0xf0, APEDCRC|ENBNKSEL);
@@ -305,26 +314,26 @@
 	w977_write_reg(0x30, 0x01);
 
 	w977_efm_exit();
-
+#endif
  	/* Disable Advanced mode */
- 	switch_bank( iobase, SET2);
+ 	switch_bank(iobase, SET2);
  	outb(iobase+2, 0x00);  
 
 	/* Turn on UART (global) interrupts */
-	switch_bank( iobase, SET0);
-	outb( HCR_EN_IRQ, iobase+HCR);
+	switch_bank(iobase, SET0);
+	outb(HCR_EN_IRQ, iobase+HCR);
 	
 	/* Switch to advanced mode */
-	switch_bank( iobase, SET2);
-	outb( inb( iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
+	switch_bank(iobase, SET2);
+	outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
 
 	/* Set default IR-mode */
-	switch_bank( iobase, SET0);
-	outb( HCR_SIR, iobase+HCR);
+	switch_bank(iobase, SET0);
+	outb(HCR_SIR, iobase+HCR);
 
 	/* Read the Advanced IR ID */
 	switch_bank(iobase, SET3);
-	version =  inb( iobase+AUID);
+	version = inb(iobase+AUID);
 	
 	/* Should be 0x1? */
 	if (0x10 != (version & 0xf0)) {
@@ -333,18 +342,17 @@
 	}
 	
 	/* Set FIFO size to 32 */
-	switch_bank( iobase, SET2);
-	outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+	switch_bank(iobase, SET2);
+	outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
 	
 	/* Set FIFO threshold to TX17, RX16 */
 	switch_bank(iobase, SET0);	
 	outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR);
-/* 	outb( 0xa7, iobase+UFR); */
 
 	/* Receiver frame length */
-	switch_bank( iobase, SET4);
-	outb( 2048 & 0xff, iobase+6);
-	outb(( 2048 >> 8) & 0x1f, iobase+7);
+	switch_bank(iobase, SET4);
+	outb(2048 & 0xff, iobase+6);
+	outb((2048 >> 8) & 0x1f, iobase+7);
 
 	/* 
 	 * Init HP HSDL-1100 transceiver. 
@@ -358,8 +366,8 @@
 	 *   FIRRX pin 39 connected to receiver      (IRSL0) 
 	 *   CIRRX pin 40 connected to pin 37
 	 */
-	switch_bank( iobase, SET7);
-	outb( 0x40, iobase+7);
+	switch_bank(iobase, SET7);
+	outb(0x40, iobase+7);
 		
 	DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
 	
@@ -372,16 +380,14 @@
  *    Change the speed of the device
  *
  */
-void w83977af_change_speed( struct irda_device *idev, int speed)
+void w83977af_change_speed(struct irda_device *idev, int speed)
 {
 	int ir_mode = HCR_SIR;
 	int iobase; 
 	__u8 set;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	ASSERT( idev != NULL, return;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 
 	iobase = idev->io.iobase;
 
@@ -389,22 +395,22 @@
 	idev->io.baudrate = speed;
 
 	/* Save current bank */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
 
 	/* Disable interrupts */
-	switch_bank( iobase, SET0);
-	outb( 0, iobase+ICR);
+	switch_bank(iobase, SET0);
+	outb(0, iobase+ICR);
 
 	/* Select Set 2 */
-	switch_bank( iobase, SET2);
+	switch_bank(iobase, SET2);
+	outb(0x00, iobase+ABHL);
 
-	outb( 0x00, iobase+ABHL);
-	switch ( speed) {
-	case 9600:   outb( 0x0c, iobase+ABLL); break;
-	case 19200:  outb( 0x06, iobase+ABLL); break;
-	case 37600:  outb( 0x03, iobase+ABLL); break;
-	case 57600:  outb( 0x02, iobase+ABLL); break;
-	case 115200: outb( 0x01, iobase+ABLL); break;
+	switch (speed) {
+	case 9600:   outb(0x0c, iobase+ABLL); break;
+	case 19200:  outb(0x06, iobase+ABLL); break;
+	case 37600:  outb(0x03, iobase+ABLL); break;
+	case 57600:  outb(0x02, iobase+ABLL); break;
+	case 115200: outb(0x01, iobase+ABLL); break;
 	case 576000:
 		ir_mode = HCR_MIR_576;
 		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
@@ -419,34 +425,37 @@
 		break;
 	default:
 		ir_mode = HCR_FIR;
-		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
 		break;
 	}
 
 	/* Set speed mode */
 	switch_bank(iobase, SET0);
-	outb( ir_mode, iobase+HCR);
+	outb(ir_mode, iobase+HCR);
 
 	/* set FIFO size to 32 */
-	switch_bank( iobase, SET2);
-	outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+	switch_bank(iobase, SET2);
+	outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
 	
 	/* set FIFO threshold to TX17, RX16 */
 	switch_bank(iobase, SET0);
-	outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
-	
+
+	outb(0x00, iobase+UFR);        /* Reset */
+	outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
+	outb(0xa7, iobase+UFR);
+
 	idev->netdev.tbusy = 0;
 	
 	/* Enable some interrupts so we can receive frames */
 	switch_bank(iobase, SET0);
-	if ( speed > 115200) {
-		outb( ICR_EFSFI, iobase+ICR);
-		w83977af_dma_receive( idev);
+	if (speed > PIO_MAX_SPEED) {
+		outb(ICR_EFSFI, iobase+ICR);
+		w83977af_dma_receive(idev);
 	} else
-		outb( ICR_ERBRI, iobase+ICR);
+		outb(ICR_ERBRI, iobase+ICR);
     	
 	/* Restore SSR */
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
 }
 
 /*
@@ -455,7 +464,7 @@
  *    Sets up a DMA transfer to send the current frame.
  *
  */
-int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev)
+int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -474,20 +483,21 @@
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
-	
+
 	/* Save current set */
 	set = inb(iobase+SSR);
 	
 	/* Decide if we should use PIO or DMA transfer */
-	if (idev->io.baudrate > 115200) {
+	if (idev->io.baudrate > PIO_MAX_SPEED) {
+		idev->tx_buff.data = idev->tx_buff.head;
 		memcpy(idev->tx_buff.data, skb->data, skb->len);
 		idev->tx_buff.len = skb->len;
-		idev->tx_buff.data = idev->tx_buff.head;
 		
 		mtt = irda_get_mtt(skb);
+#ifdef CONFIG_USE_INTERNAL_TIMER
 	        if (mtt > 50) {
 			/* Adjust for timer resolution */
-			mtt = mtt / 1000 + 1;
+			mtt /= 1000+1;
 
 			/* Setup timer */
 			switch_bank(iobase, SET4);
@@ -502,6 +512,8 @@
 			switch_bank(iobase, SET0);
 			outb(ICR_ETMRI, iobase+ICR);
 		} else {
+#endif
+			DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
 			if (mtt)
 				udelay(mtt);
 
@@ -509,7 +521,9 @@
 			switch_bank(iobase, SET0);
 	 		outb(ICR_EDMAI, iobase+ICR);
 	     		w83977af_dma_write(idev, iobase);
+#ifdef CONFIG_USE_INTERNAL_TIMER
 		}
+#endif
 	} else {
 		idev->tx_buff.data = idev->tx_buff.head;
 		idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
@@ -527,41 +541,57 @@
 	return 0;
 }
 
-
 /*
  * Function w83977af_dma_write (idev, iobase)
  *
- *    
+ *    Send frame using DMA
  *
  */
-static void w83977af_dma_write( struct irda_device *idev, int iobase)
+static void w83977af_dma_write(struct irda_device *idev, int iobase)
 {
 	__u8 set;
-
-        DEBUG( 4, __FUNCTION__ "()\n");
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+	unsigned long flags;
+	__u8 hcr;
+#endif
+        DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len);
 
 	/* Save current set */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
 
 	/* Disable DMA */
 	switch_bank(iobase, SET0);
-	outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
-	
-	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
-		  DMA_MODE_WRITE);
-	
-	/* idev->media_busy = TRUE; */
-	idev->io.direction = IO_XMIT;
-	
+	outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+
 	/* Choose transmit DMA channel  */ 
 	switch_bank(iobase, SET2);
-	outb(inb(iobase+ADCR1) | ADCR1_D_CHSW|ADCR1_DMA_F|ADCR1_ADV_SL, 
-	     iobase+ADCR1);
+	outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+	save_flags(flags);
+	cli();
+
+	disable_dma(idev->io.dma);
+	clear_dma_ff(idev->io.dma);
+	set_dma_mode(idev->io.dma, DMA_MODE_READ);
+	set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data));
+	set_dma_count(idev->io.dma, idev->tx_buff.len);
+#else
+	setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+		  DMA_MODE_WRITE);	
+#endif
+	idev->io.direction = IO_XMIT;
 	
 	/* Enable DMA */
  	switch_bank(iobase, SET0);
-	outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
-	
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+	hcr = inb(iobase+HCR);
+	outb(hcr | HCR_EN_DMA, iobase+HCR);
+	enable_dma(idev->io.dma);
+	restore_flags(flags);
+#else	
+	outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
+#endif
+
 	/* Restore set register */
 	outb(set, iobase+SSR);
 }
@@ -577,17 +607,17 @@
 	int actual = 0;
 	__u8 set;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Save current bank */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
 
-	switch_bank( iobase, SET0);
+	switch_bank(iobase, SET0);
 	if (!(inb_p(iobase+USR) & USR_TSRE)) {
-		DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+		DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
 
 		fifo_size -= 17;
-		DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+		DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
 	}
 
 	/* Fill FIFO with current frame */
@@ -597,7 +627,7 @@
 	}
         
 	DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	      fifo_size, actual, len);
+	       fifo_size, actual, len);
 
 	/* Restore bank */
 	outb(set, iobase+SSR);
@@ -617,7 +647,7 @@
 	int iobase;
 	__u8 set;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
 
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -663,9 +693,10 @@
  */
 int w83977af_dma_receive(struct irda_device *idev) 
 {
+	struct w83977af_ir *self;
 	int iobase;
 	__u8 set;
-#ifdef NETWINDER
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
@@ -673,62 +704,60 @@
 	ASSERT(idev != NULL, return -1;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 
-	DEBUG(0, __FUNCTION__ "\n");
+	DEBUG(4, __FUNCTION__ "\n");
 
+	self = idev->priv;
 	iobase= idev->io.iobase;
 
 	/* Save current set */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
 
 	/* Disable DMA */
-	switch_bank( iobase, SET0);
-	outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+	switch_bank(iobase, SET0);
+	outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
 
-#ifdef NETWINDER
+	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
+	switch_bank(iobase, SET2);
+	outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL,
+	     iobase+ADCR1);
+
+	idev->io.direction = IO_RECV;
+	idev->rx_buff.data = idev->rx_buff.head;
+
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
-	disable_dma( idev->io.dma);
-	clear_dma_ff( idev->io.dma);
-	set_dma_mode( idev->io.dma, DMA_MODE_READ);
-	set_dma_addr( idev->io.dma, virt_to_bus(idev->rx_buff.data));
-	set_dma_count( idev->io.dma, idev->rx_buff.truesize);
+	disable_dma(idev->io.dma);
+	clear_dma_ff(idev->io.dma);
+	set_dma_mode(idev->io.dma, DMA_MODE_READ);
+	set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data));
+	set_dma_count(idev->io.dma, idev->rx_buff.truesize);
 #else
-	setup_dma(idev->io.dma, idev->rx_buff.data, 
-		  idev->rx_buff.truesize, DMA_MODE_READ);
+	setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
+		  DMA_MODE_READ);
 #endif
-	/* driver->media_busy = FALSE; */
-	idev->io.direction = IO_RECV;
-	idev->rx_buff.data = idev->rx_buff.head;
-
 	/* 
 	 * Reset Rx FIFO. This will also flush the ST_FIFO, it's very 
 	 * important that we don't reset the Tx FIFO since it might not
 	 * be finished transmitting yet
 	 */
-	outb( UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
-	prev.status = 0;
-
-	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
-	switch_bank(iobase, SET2);
-	outb(( inb( iobase+ADCR1) & ~ADCR1_D_CHSW)|ADCR1_DMA_F|ADCR1_ADV_SL,
-	     iobase+ADCR1);
+	switch_bank(iobase, SET0);
+	outb(UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
+	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
 	
 	/* Enable DMA */
 	switch_bank(iobase, SET0);
-#ifdef NETWINDER
-	hcr = inb( iobase+HCR);
-	enable_dma( idev->io.dma);
-	outb( hcr | HCR_EN_DMA, iobase+HCR);
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+	hcr = inb(iobase+HCR);
+	outb(hcr | HCR_EN_DMA, iobase+HCR);
+	enable_dma(idev->io.dma);
 	restore_flags(flags);
 #else	
-	outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR);
+	outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
 #endif
-	
 	/* Restore set */
-	outb( set, iobase+SSR);
-
-	DEBUG( 4, __FUNCTION__ "(), done!\n");	
+	outb(set, iobase+SSR);
 
 	return 0;
 }
@@ -742,12 +771,17 @@
 int w83977af_dma_receive_complete(struct irda_device *idev)
 {
 	struct sk_buff *skb;
+	struct w83977af_ir *self;
+	struct st_fifo *st_fifo;
 	int len;
 	int iobase;
 	__u8 set;
 	__u8 status;
 
-	DEBUG(0, __FUNCTION__ "\n");
+	DEBUG(4, __FUNCTION__ "\n");
+
+	self = idev->priv;
+	st_fifo = &self->st_fifo;
 
 	iobase = idev->io.iobase;
 
@@ -756,22 +790,28 @@
 	
 	iobase = idev->io.iobase;
 
+	/* Read status FIFO */
 	switch_bank(iobase, SET5);
-	if (prev.status & FS_FO_FSFDR) {
-		status = prev.status;
-		len = prev.len;
+	while ((status = inb(iobase+FS_FO)) & FS_FO_FSFDR) {
+		st_fifo->entries[st_fifo->tail].status = status;
 		
-		prev.status = 0;
-	} else {
-		status = inb(iobase+FS_FO);
-		len = inb(iobase+RFLFL);
-		len |= inb(iobase+RFLFH) << 8;
+		st_fifo->entries[st_fifo->tail].len  = inb(iobase+RFLFL);
+		st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+		
+		st_fifo->tail++;
+		st_fifo->len++;
 	}
+	
+	while (st_fifo->len) {
+		/* Get first entry */
+		status = st_fifo->entries[st_fifo->head].status;
+		len    = st_fifo->entries[st_fifo->head].len;
+		st_fifo->head++;
+		st_fifo->len--;
 
-	while (status & FS_FO_FSFDR) {
 		/* Check for errors */
 		if (status & FS_FO_ERR_MSK) {
-			if ( status & FS_FO_LST_FR) {
+			if (status & FS_FO_LST_FR) {
 				/* Add number of lost frames to stats */
 				idev->stats.rx_errors += len;	
 			} else {
@@ -800,14 +840,20 @@
 			/* Check if we have transfered all data to memory */
 			switch_bank(iobase, SET0);
 			if (inb(iobase+USR) & USR_RDR) {
+#ifdef CONFIG_USE_INTERNAL_TIMER
 				/* Put this entry back in fifo */
-				prev.status = status;
-				prev.len = len;
-
+				st_fifo->head--;
+				st_fifo->len++;
+				st_fifo->entries[st_fifo->head].status = status;
+				st_fifo->entries[st_fifo->head].len = len;
+				
 				/* Restore set register */
-				outb( set, iobase+SSR);
+				outb(set, iobase+SSR);
 			
 				return FALSE; 	/* I'll be back! */
+#else
+				udelay(80); /* Should be enough!? */
+#endif
 			}
 						
 			skb = dev_alloc_skb(len+1);
@@ -824,28 +870,23 @@
 			skb_reserve(skb, 1); 
 			
 			/* Copy frame without CRC */
-			if ( idev->io.baudrate < 4000000) {
-				skb_put( skb, len-2);
-				memcpy( skb->data, idev->rx_buff.data, len-2);
+			if (idev->io.baudrate < 4000000) {
+				skb_put(skb, len-2);
+				memcpy(skb->data, idev->rx_buff.data, len-2);
 			} else {
-				skb_put( skb, len-4);
-				memcpy( skb->data, idev->rx_buff.data, len-4);
+				skb_put(skb, len-4);
+				memcpy(skb->data, idev->rx_buff.data, len-4);
 			}
 
 			/* Move to next frame */
 			idev->rx_buff.data += len;
+			idev->stats.rx_packets++;
 			
 			skb->dev = &idev->netdev;
 			skb->mac.raw  = skb->data;
 			skb->protocol = htons(ETH_P_IRDA);
-			netif_rx( skb);
-			idev->stats.rx_packets++;
+			netif_rx(skb);
 		}
-		/* Read next entry in ST_FIFO */
-		switch_bank(iobase, SET5);
-		status = inb( iobase+FS_FO);
-		len = inb( iobase+RFLFL);
-		len |= inb( iobase+RFLFH) << 8;
 	}
 	/* Restore set register */
 	outb(set, iobase+SSR);
@@ -875,7 +916,6 @@
 	do {
 		byte = inb(iobase+RBR);
 		async_unwrap_char(idev, byte);
-
 	} while (inb(iobase+USR) & USR_RDR); /* Data available */	
 }
 
@@ -889,9 +929,12 @@
 {
 	int actual;
 	__u8 new_icr = 0;
+	__u8 set;
+	int iobase;
 
 	DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
 	
+	iobase = idev->io.iobase;
 	/* Transmit FIFO low on data */
 	if (isr & ISR_TXTH_I) {
 		/* Write data left in transmit buffer */
@@ -899,16 +942,21 @@
 					    idev->tx_buff.data, 
 					    idev->tx_buff.len, 
 					    idev->io.fifo_size);
+
 		idev->tx_buff.data += actual;
 		idev->tx_buff.len  -= actual;
 		
 		idev->io.direction = IO_XMIT;
 
 		/* Check if finished */
-		if (idev->tx_buff.len > 0)
+		if (idev->tx_buff.len > 0) {
 			new_icr |= ICR_ETXTHI;
-		else { 
-			DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+		} else {
+			set = inb(iobase+SSR);
+			switch_bank(iobase, SET0);
+			outb(AUDR_SFEND, iobase+AUDR);
+			outb(set, iobase+SSR); 
+
 			idev->netdev.tbusy = 0; /* Unlock */
 			idev->stats.tx_packets++;
 
@@ -917,7 +965,6 @@
 
 			new_icr |= ICR_ETBREI;
 		}
-		
 	}
 	/* Check if transmission has completed */
 	if (isr & ISR_TXEMP_I) {
@@ -943,22 +990,20 @@
  *    Handle MIR/FIR interrupt
  *
  */
-static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr)
+static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr)
 {
 	__u8 new_icr = 0;
 	__u8 set;
 	int iobase;
 
-	DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr);
-
 	iobase = idev->io.iobase;
-
 	set = inb(iobase+SSR);
 	
 	/* End of frame detected in FIFO */
 	if (isr & (ISR_FEND_I|ISR_FSF_I)) {
 		if (w83977af_dma_receive_complete(idev)) {
 			
+			/* Wait for next status FIFO interrupt */
 			new_icr |= ICR_EFSFI;
 		} else {
 			/* DMA not finished yet */
@@ -982,7 +1027,7 @@
 
 		/* Clear timer event */
 		/* switch_bank(iobase, SET0); */
-/* 		outb( ASCR_CTE, iobase+ASCR); */
+/* 		outb(ASCR_CTE, iobase+ASCR); */
 
 		/* Check if this is a TX timer interrupt */
 		if (idev->io.direction == IO_XMIT) {
@@ -998,15 +1043,18 @@
 	}	
 	/* Finished with DMA */
 	if (isr & ISR_DMA_I) {
-		w83977af_dma_xmit_complete( idev);
-		
+		w83977af_dma_xmit_complete(idev);
+
 		/* Check if there are more frames to be transmitted */
-		if (irda_device_txqueue_empty( idev)) {
+		/* if (irda_device_txqueue_empty(idev)) { */
 		
-			/* Prepare for receive */
-			w83977af_dma_receive(idev);
-			new_icr = ICR_EFSFI;
-		}
+		/* Prepare for receive 
+		 * 
+		 * ** Netwinder Tx DMA likes that we do this anyway **
+		 */
+		w83977af_dma_receive(idev);
+		new_icr = ICR_EFSFI;
+	       /* } */
 	}
 	
 	/* Restore set */
@@ -1030,7 +1078,7 @@
 
 	if (idev == NULL) {
 		printk(KERN_WARNING "%s: irq %d for unknown device.\n", 
-		       driver_name, irq);
+			driver_name, irq);
 		return;
 	}
 
@@ -1049,7 +1097,7 @@
 	
 	if (isr) {
 		/* Dispatch interrupt handler for the current speed */
-		if ( idev->io.baudrate > 115200)
+		if (idev->io.baudrate > PIO_MAX_SPEED )
 			icr = w83977af_fir_interrupt(idev, isr);
 		else
 			icr = w83977af_sir_interrupt(idev, isr);
@@ -1070,7 +1118,7 @@
 static void w83977af_wait_until_sent(struct irda_device *idev)
 {
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(6);
+	schedule_timeout(60*HZ/1000);
 }
 
 /*
@@ -1085,16 +1133,16 @@
 	int iobase;
 	__u8 set;
 
-	ASSERT( idev != NULL, return FALSE;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	ASSERT(idev != NULL, return FALSE;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
 
-	if ( idev->io.baudrate > 115200) {
+	if (idev->io.baudrate > 115200) {
 		iobase = idev->io.iobase;
 
 		/* Check if rx FIFO is not empty */
 		set = inb(iobase+SSR);
-		switch_bank( iobase, SET2);
-		if (( inb( iobase+RXFDTH) & 0x3f) != 0) {
+		switch_bank(iobase, SET2);
+		if ((inb(iobase+RXFDTH) & 0x3f) != 0) {
 			/* We are receiving something */
 			status =  TRUE;
 		}
@@ -1111,12 +1159,12 @@
  *    
  *
  */
-static int w83977af_net_init( struct device *dev)
+static int w83977af_net_init(struct device *dev)
 {
 	DEBUG(0, __FUNCTION__ "()\n");
 
 	/* Set up to be a normal IrDA network device driver */
-	irda_device_setup( dev);
+	irda_device_setup(dev);
 
 	/* Insert overrides below this line! */
 
@@ -1130,7 +1178,7 @@
  *    Start the device
  *
  */
-static int w83977af_net_open( struct device *dev)
+static int w83977af_net_open(struct device *dev)
 {
 	struct irda_device *idev;
 	int iobase;
@@ -1147,7 +1195,7 @@
 	iobase = idev->io.iobase;
 
 	if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name, 
-			(void *) idev)) {
+			 (void *) idev)) {
 		return -EAGAIN;
 	}
 	/*
@@ -1170,13 +1218,13 @@
  	/* Enable some interrupts so we can receive frames again */
  	switch_bank(iobase, SET0);
  	if (idev->io.baudrate > 115200) {
- 		outb( ICR_EFSFI, iobase+ICR);
- 		w83977af_dma_receive( idev);
+ 		outb(ICR_EFSFI, iobase+ICR);
+ 		w83977af_dma_receive(idev);
  	} else
- 		outb( ICR_ERBRI, iobase+ICR);
+ 		outb(ICR_ERBRI, iobase+ICR);
 
 	/* Restore bank register */
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
 
 	MOD_INC_USE_COUNT;
 
@@ -1195,34 +1243,34 @@
 	int iobase;
 	__u8 set;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
 	
 	/* Stop device */
 	dev->tbusy = 1;
 	dev->start = 0;
 
-	ASSERT( dev != NULL, return -1;);
+	ASSERT(dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
 	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(idev != NULL, return 0;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
 	
 	iobase = idev->io.iobase;
 
-	disable_dma( idev->io.dma);
+	disable_dma(idev->io.dma);
 
 	/* Save current set */
-	set = inb( iobase+SSR);
+	set = inb(iobase+SSR);
 	
 	/* Disable interrupts */
-	switch_bank( iobase, SET0);
-	outb( 0, iobase+ICR); 
+	switch_bank(iobase, SET0);
+	outb(0, iobase+ICR); 
 
-	free_irq( idev->io.irq, idev);
-	free_dma( idev->io.dma);
+	free_irq(idev->io.irq, idev);
+	free_dma(idev->io.dma);
 
 	/* Restore bank register */
-	outb( set, iobase+SSR);
+	outb(set, iobase+SSR);
 
 	MOD_DEC_USE_COUNT;
 
@@ -1231,6 +1279,11 @@
 
 #ifdef MODULE
 
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
+
 /*
  * Function init_module (void)
  *
diff -urN linux-2.2.10-pre1/drivers/net/sunhme.c linux-2.2.10-pre2/drivers/net/sunhme.c
--- linux-2.2.10-pre1/drivers/net/sunhme.c	1999-03-15 16:11:30.000000000 -0800
+++ linux-2.2.10-pre2/drivers/net/sunhme.c	2003-08-15 15:06:23.000000000 -0700
@@ -1834,7 +1834,7 @@
 #define RXD(x)
 #endif
 
-/* Originally I use to handle the allocation failure by just giving back just
+/* Originally I used to handle the allocation failure by just giving back just
  * that one ring buffer to the happy meal.  Problem is that usually when that
  * condition is triggered, the happy meal expects you to do something reasonable
  * with all of the packets it has DMA'd in.  So now I just drop the entire
diff -urN linux-2.2.10-pre1/drivers/video/cgsixfb.c linux-2.2.10-pre2/drivers/video/cgsixfb.c
--- linux-2.2.10-pre1/drivers/video/cgsixfb.c	1999-03-15 16:11:31.000000000 -0800
+++ linux-2.2.10-pre2/drivers/video/cgsixfb.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.16 1999/03/09 14:01:49 davem Exp $
+/* $Id: cgsixfb.c,v 1.16.2.1 1999/05/25 00:59:35 davem Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -588,7 +588,7 @@
 	p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);
 }
 
-static char idstring[60] __initdata = { 0 };
+static char idstring[70] __initdata = { 0 };
 
 __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
 {
@@ -599,6 +599,7 @@
 	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
 	u32 conf;
 	char *p;
+	char *cardtype;
 	struct bt_regs *bt;
 
 	strcpy(fb->info.modename, "CGsix");
@@ -656,15 +657,29 @@
 	case CG6_FHC_CPU_68020: p = "68020"; break;
 	default: p = "i386"; break;
 	}
+
+	if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
+		if (fix->smem_len <= 0x100000) {
+			cardtype = "TurboGX";
+		} else {
+			cardtype = "TurboGX+";
+		}
+	} else {
+		if (fix->smem_len <= 0x100000) {
+			cardtype = "GX";
+		} else {
+			cardtype = "GX+";
+		}
+	}
 	                                                                        
 	sprintf(idstring, 
 #ifdef __sparc_v9__
-		    "cgsix at %016lx TEC Rev %x CPU %s Rev %x", phys, 
+		    "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, 
 #else	
-		    "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys, 
+		    "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, 
 #endif
 		    (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK,
-		    p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK);
+		    p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype);
 		    
 	cg6_reset(fb);
 		    
diff -urN linux-2.2.10-pre1/fs/ext2/file.c linux-2.2.10-pre2/fs/ext2/file.c
--- linux-2.2.10-pre1/fs/ext2/file.c	1998-12-21 15:22:54.000000000 -0800
+++ linux-2.2.10-pre2/fs/ext2/file.c	2003-08-15 15:06:23.000000000 -0700
@@ -162,7 +162,7 @@
 	struct buffer_head * bh, *bufferlist[NBUF];
 	struct super_block * sb;
 	int err;
-	int i,buffercount,write_error;
+	int i,buffercount,write_error, new_buffer;
 
 	/* POSIX: mtime/ctime may not change for 0 count */
 	if (!count)
@@ -247,30 +247,59 @@
 		}
 		if (c > count)
 			c = count;
-		if (c != sb->s_blocksize && !buffer_uptodate(bh)) {
-			ll_rw_block (READ, 1, &bh);
-			wait_on_buffer (bh);
-			if (!buffer_uptodate(bh)) {
-				brelse (bh);
+
+		/* Tricky: what happens if we are writing the complete
+		 * contents of a block which is not currently
+		 * initialised?  We have to obey the same
+		 * synchronisation rules as the IO code, to prevent some
+		 * other process from stomping on the buffer contents by
+		 * refreshing them from disk while we are setting up the
+		 * buffer.  The copy_from_user() can page fault, after
+		 * all.  We also have to throw away partially successful
+		 * copy_from_users to such buffers, since we can't trust
+		 * the rest of the buffer_head in that case.  --sct */
+
+		new_buffer = (!buffer_uptodate(bh) && !buffer_locked(bh) &&
+			      c == sb->s_blocksize);
+
+		if (new_buffer) {
+			set_bit(BH_Lock, &bh->b_state);
+			c -= copy_from_user (bh->b_data + offset, buf, c);
+			if (c != sb->s_blocksize) {
+				c = 0;
+				unlock_buffer(bh);
+				brelse(bh);
 				if (!written)
-					written = -EIO;
+					written = -EFAULT;
 				break;
 			}
+			mark_buffer_uptodate(bh, 1);
+			unlock_buffer(bh);
+		} else {
+			if (!buffer_uptodate(bh)) {
+				ll_rw_block (READ, 1, &bh);
+				wait_on_buffer (bh);
+				if (!buffer_uptodate(bh)) {
+					brelse (bh);
+					if (!written)
+						written = -EIO;
+					break;
+				}
+			}
+			c -= copy_from_user (bh->b_data + offset, buf, c);
 		}
-		c -= copy_from_user (bh->b_data + offset, buf, c);
 		if (!c) {
 			brelse(bh);
 			if (!written)
 				written = -EFAULT;
 			break;
 		}
+		mark_buffer_dirty(bh, 0);
 		update_vm_cache(inode, pos, bh->b_data + offset, c);
 		pos += c;
 		written += c;
 		buf += c;
 		count -= c;
-		mark_buffer_uptodate(bh, 1);
-		mark_buffer_dirty(bh, 0);
 
 		if (filp->f_flags & O_SYNC)
 			bufferlist[buffercount++] = bh;
diff -urN linux-2.2.10-pre1/fs/smbfs/inode.c linux-2.2.10-pre2/fs/smbfs/inode.c
--- linux-2.2.10-pre1/fs/smbfs/inode.c	2003-08-15 15:06:23.000000000 -0700
+++ linux-2.2.10-pre2/fs/smbfs/inode.c	2003-08-15 15:06:23.000000000 -0700
@@ -601,8 +601,6 @@
 	smb_current_vmalloced = 0;
 #endif
 
-	read_semaphore = MUTEX;
-
 	return init_smb_fs();
 }
 
diff -urN linux-2.2.10-pre1/include/net/irda/crc.h linux-2.2.10-pre2/include/net/irda/crc.h
--- linux-2.2.10-pre1/include/net/irda/crc.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/crc.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,25 +6,28 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Tue Dec 15 22:18:53 1998
+ * Modified at:   Sun May  2 20:25:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  ********************************************************************/
 
-#ifndef IR_CRC_H
-#define IR_CRC_H
+#ifndef IRDA_CRC_H
+#define IRDA_CRC_H
 
 #include <linux/types.h>
 
 #define INIT_FCS  0xffff   /* Initial FCS value */
 #define GOOD_FCS  0xf0b8   /* Good final FCS value */
 
+extern __u16 const irda_crc16_table[];
+
 /* Recompute the FCS with one more character appended. */
-#define IR_FCS(fcs, c) (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff])
+static inline __u16 irda_fcs(__u16 fcs, __u8 c)
+{
+	return (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff]);
+}
 
 /* Recompute the FCS with len bytes appended. */
 unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len);
 
-extern __u16 const irda_crc16_table[];
-
 #endif
diff -urN linux-2.2.10-pre1/include/net/irda/dongle.h linux-2.2.10-pre2/include/net/irda/dongle.h
--- linux-2.2.10-pre1/include/net/irda/dongle.h	1999-03-07 15:26:43.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/dongle.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Sat Feb  6 07:37:49 1999
+ * Modified at:   Mon May 10 14:51:06 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -26,7 +26,6 @@
 #define DONGLE_H
 
 #include <net/irda/qos.h>
-#include <net/irda/irda_device.h>
 
 /* These are the currently known dongles */
 typedef enum {
@@ -35,8 +34,11 @@
 	ACTISYS_DONGLE,
 	ACTISYS_PLUS_DONGLE,
 	GIRBIL_DONGLE,
+	LITELINK_DONGLE,
 } DONGLE_T;
 
+struct irda_device;
+
 struct dongle {
 	DONGLE_T type;
 	void (*open)(struct irda_device *, int type);
diff -urN linux-2.2.10-pre1/include/net/irda/ircomm_common.h linux-2.2.10-pre2/include/net/irda/ircomm_common.h
--- linux-2.2.10-pre1/include/net/irda/ircomm_common.h	1999-04-24 17:50:05.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/ircomm_common.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
  *
- *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
  *     All Rights Reserved.
  *
  *     This program is free software; you can redistribute it and/or
@@ -78,7 +78,7 @@
 #define IRCOMM_MAGIC            0x434f4d4d
 #define COMM_INIT_CTRL_PARAM    3          /* length of initial control parameters */
 #define COMM_HEADER             1          /* length of clen field */
-#define COMM_HEADER_SIZE        (LAP_HEADER+LMP_HEADER+TTP_HEADER+COMM_HEADER)
+#define COMM_HEADER_SIZE        (TTP_MAX_HEADER+COMM_HEADER)
 #define COMM_DEFAULT_DATA_SIZE  64
 #define IRCOMM_MAX_CONNECTION   1          /* Don't change for now */
 
@@ -167,7 +167,7 @@
 #define LSR_BI     0x01    /* Break interrupt indicator */
 
 
-struct ircomm_cb{
+struct ircomm_cb {
 	int magic;
 	int state;          /* Current state of IrCOMM layer: 
 			     *  DISCOVERY,COMM_IDLE, COMM_WAITR,
@@ -178,7 +178,8 @@
 	int ttp_stop;
 
 	int max_txbuff_size;          
-	__u32 maxsdusize;
+	__u32 max_sdu_size;
+	__u8 max_header_size;
 
  	__u32 daddr;        /* Device address of the peer device */ 
 	__u32 saddr;
@@ -211,8 +212,6 @@
 	int                 pending_control_tuples;
 	int                 ignored_control_tuples;
 
-
-
 	__u8 pi ;            /* instruction of control channel*/ 
 
 	__u8 port_type;
@@ -253,8 +252,6 @@
 	int port_name_critical;
 };
 
-
-
 void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype);
 void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
 			     __u32 maxsdusize);
diff -urN linux-2.2.10-pre1/include/net/irda/irda_device.h linux-2.2.10-pre2/include/net/irda/irda_device.h
--- linux-2.2.10-pre1/include/net/irda/irda_device.h	1999-04-24 17:50:05.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/irda_device.h	2003-08-15 15:06:23.000000000 -0700
@@ -4,24 +4,29 @@
  * Version:       
  * Description:   
  * Status:        Experimental.
- * Author:        Haris Zukanovic <haris@stud.cs.uit.no>
+ * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Tue Apr 20 11:06:28 1999
+ * Modified at:   Mon May 10 15:46:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
- *     Copyright (c) 1998 Dag Brattli, <dagb@cs.uit.no>
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
- *     All Rights Reserved.
- *      
+ *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
+ *
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     Neither Haris Zukanovic nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
  *     
  ********************************************************************/
 
@@ -35,6 +40,7 @@
 
 #include <net/irda/irda.h>
 #include <net/irda/qos.h>
+#include <net/irda/dongle.h>
 #include <net/irda/irqueue.h>
 #include <net/irda/irlap_frame.h>
 
@@ -52,6 +58,11 @@
 #define IO_XMIT 0x01
 #define IO_RECV 0x02
 
+struct dongle_q {
+	QUEUE q;
+	struct dongle *dongle;
+};
+
 /* Chip specific info */
 struct chipio_t {
         int iobase, iobase2;  /* IO base */
@@ -111,6 +122,8 @@
 	struct iobuff_t tx_buff;
 	struct iobuff_t rx_buff;
 
+	struct dongle *dongle; /* Dongle driver */
+
 	/* spinlock_t lock; */ /* For serializing operations */
 	
 	/* Media busy stuff */
@@ -120,7 +133,8 @@
 	/* Callbacks for driver specific implementation */
         void (*change_speed)(struct irda_device *driver, int baud);
  	int  (*is_receiving)(struct irda_device *);    /* receiving? */
-	/* int (*is_tbusy)(struct irda_device *); */   /* transmitting? */
+	void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts);
+	int  (*raw_write)(struct irda_device *idev, __u8 *buf, int len);
 	void (*wait_until_sent)(struct irda_device *);
 	void (*set_caddr)(struct irda_device *);      /* Set connection addr */
 };
@@ -142,6 +156,9 @@
 
 inline struct qos_info *irda_device_get_qos(struct irda_device *self);
 int irda_device_txqueue_empty(struct irda_device *self);
+void irda_device_init_dongle(struct irda_device *self, int type);
+void irda_device_unregister_dongle(struct dongle *dongle);
+int irda_device_register_dongle(struct dongle *dongle);
 
 int irda_device_setup(struct device *dev);
 
@@ -153,7 +170,7 @@
  *    Utility function for getting the minimum turnaround time out of 
  *    the skb, where it has been hidden in the cb field.
  */
-inline static __u16 irda_get_mtt(struct sk_buff *skb)
+extern inline __u16 irda_get_mtt(struct sk_buff *skb)
 {
 	__u16 mtt;
 
@@ -167,6 +184,23 @@
 	return mtt;
 }
 
+extern inline void irda_device_set_dtr_rts(struct irda_device *self, int dtr,
+					   int rts)
+{
+	if (self->set_dtr_rts)
+		self->set_dtr_rts(self, dtr, rts);
+}
+
+extern inline int irda_device_raw_write(struct irda_device *self, __u8 *buf,
+					int len)
+{
+	int ret = -1;
+
+	if (self->raw_write)
+		ret = self->raw_write(self, buf, len);
+	return ret;
+}
+
 #endif
 
 
diff -urN linux-2.2.10-pre1/include/net/irda/irda.h linux-2.2.10-pre2/include/net/irda/irda.h
--- linux-2.2.10-pre1/include/net/irda/irda.h	1999-05-11 10:36:42.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/irda.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Wed Apr 21 17:49:00 1999
+ * Modified at:   Mon May 10 09:51:13 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -109,6 +109,8 @@
 	
 	__u32 max_sdu_size_rx;
 	__u32 max_sdu_size_tx;
+	__u32 max_data_size;
+	__u8  max_header_size;
 	struct qos_info qos_tx;
 
 	__u16 mask;           /* Hint bits mask */
@@ -225,10 +227,10 @@
 	int (*udata_indication)(void *priv, void *sap, struct sk_buff *skb);
 	void (*connect_confirm)(void *instance, void *sap, 
 				struct qos_info *qos, __u32 max_sdu_size,
-				struct sk_buff *skb);
+				__u8 max_header_size, struct sk_buff *skb);
 	void (*connect_indication)(void *instance, void *sap, 
 				   struct qos_info *qos, __u32 max_sdu_size,
-				   struct sk_buff *skb);
+				   __u8 max_header_size, struct sk_buff *skb);
 	void (*disconnect_indication)(void *instance, void *sap, 
 				      LM_REASON reason, struct sk_buff *);
 	void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow);
diff -urN linux-2.2.10-pre1/include/net/irda/iriap.h linux-2.2.10-pre2/include/net/irda/iriap.h
--- linux-2.2.10-pre1/include/net/irda/iriap.h	1999-04-24 17:50:05.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/iriap.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Wed Apr 21 16:37:21 1999
+ * Modified at:   Sun May  9 10:56:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 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 
@@ -81,6 +81,8 @@
 	CONFIRM_CALLBACK confirm;
 	void *priv;
 
+	__u8 max_header_size;
+	
 	struct timer_list watchdog_timer;
 };
 
@@ -92,8 +94,6 @@
 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
 
 void iriap_send_ack( struct iriap_cb *self);
-void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
-			   __u32 max_sdu_size, struct sk_buff *skb);
 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb);
 
 void iriap_register_server(void);
diff -urN linux-2.2.10-pre1/include/net/irda/irlan_common.h linux-2.2.10-pre2/include/net/irda/irlan_common.h
--- linux-2.2.10-pre1/include/net/irda/irlan_common.h	1999-04-24 17:50:05.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/irlan_common.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 14:30:37 1999
+ * Modified at:   Sun May  9 11:45:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -98,7 +99,7 @@
 #define IRLAN_SHORT  1
 #define IRLAN_ARRAY  2
 
-#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
+#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_MAX_HEADER)
 
 /*
  *  IrLAN client
@@ -109,7 +110,10 @@
 	int open_retries;
 
 	struct tsap_cb *tsap_ctrl;
+	__u32 max_sdu_size;
+	__u8  max_header_size;
 	
+	int access_type;         /* Access type of provider */
 	__u8 reconnect_key[255];
 	__u8 key_len;
 	
@@ -130,6 +134,8 @@
 	int state;
 	
 	struct tsap_cb *tsap_ctrl;
+	__u32 max_sdu_size;
+	__u8  max_header_size;
 
 	/*
 	 *  Store some values here which are used by the provider to parse
@@ -140,42 +146,45 @@
 	int filter_mode;
 	int filter_operation;
 	int filter_entry;
-
+	int access_type;     /* Access type */
 	__u16 send_arb_val;
 
 	__u8 mac_address[6]; /* Generated MAC address for peer device */
 };
 
 /*
- *  IrLAN
+ *  IrLAN control block
  */
 struct irlan_cb {
 	QUEUE queue; /* Must be first */
 
 	int    magic;
 	char   ifname[9];
-	struct device dev;  /* Ethernet device structure*/
+	struct device dev;        /* Ethernet device structure*/
 	struct enet_statistics stats;
 
-	__u32 saddr;        /* Source devcie address */
-	__u32 daddr;        /* Destination device address */
+	__u32 saddr;              /* Source devcie address */
+	__u32 daddr;              /* Destination device address */
 	int   netdev_registered;
 	int   notify_irmanager;
 	
-	int media;          /* Media type */
-	int access_type;    /* Currently used access type */
-	__u8 version[2];    /* IrLAN version */
+	int media;                /* Media type */
+	__u8 version[2];          /* IrLAN version */
 	
 	struct tsap_cb *tsap_data;
 
-	int  use_udata;  /* Use Unit Data transfers */
+	int  master;              /* Master instance? */
+	int  use_udata;           /* Use Unit Data transfers */
 
-	__u8 stsap_sel_data; /* Source data TSAP selector */
-	__u8 dtsap_sel_data; /* Destination data TSAP selector */
-	__u8 dtsap_sel_ctrl; /* Destination ctrl 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 */
 
-	struct irlan_client_cb client;     /* Client specific fields */
+	struct irlan_client_cb   client;   /* Client specific fields */
 	struct irlan_provider_cb provider; /* Provider specific fields */
+
+	__u32 max_sdu_size;
+	__u8  max_header_size;
 	
 	struct timer_list watchdog_timer;
 };
diff -urN linux-2.2.10-pre1/include/net/irda/irlan_provider.h linux-2.2.10-pre2/include/net/irda/irlan_provider.h
--- linux-2.2.10-pre1/include/net/irda/irlan_provider.h	1999-04-24 17:50:05.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/irlan_provider.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 14:29:16 1999
+ * Modified at:   Sun May  9 12:26:11 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -36,13 +36,7 @@
 					       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, 
-				       __u32 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);
diff -urN linux-2.2.10-pre1/include/net/irda/irlap.h linux-2.2.10-pre2/include/net/irda/irlap.h
--- linux-2.2.10-pre1/include/net/irda/irlap.h	1999-04-24 17:50:05.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/irlap.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri Apr 23 09:51:15 1999
+ * Modified at:   Sun May  9 11:38:18 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -42,11 +42,11 @@
 #define LAP_COMP_HEADER 1  /* IrLAP Compression Header */
 
 #ifdef CONFIG_IRDA_COMPRESSION
-#  define LAP_HEADER  (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER)
+#  define LAP_MAX_HEADER  (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER)
 #  define IRDA_COMPRESSED 1
 #  define IRDA_NORMAL     0
 #else
-#define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)
+#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)
 #endif
 
 #define BROADCAST  0xffffffff /* Broadcast device address */
@@ -138,7 +138,7 @@
 
 	__u8    vs;           /* Next frame to be sent */
 	__u8    vr;           /* Next frame to be received */
-	int     tmp;
+/* 	int     tmp; */
 	__u8    va;           /* Last frame acked */
  	int     window;       /* Nr of I-frames allowed to send */
 	int     window_size;  /* Current negotiated window size */
@@ -155,8 +155,7 @@
  	__u8    s;           /* Current slot */
 	int     frame_sent;  /* Have we sent reply? */
 
-	int discovery_count;
-	hashbin_t *discovery_log;
+	hashbin_t   *discovery_log;
  	discovery_t *discovery_cmd;
 
 	struct qos_info qos_tx;    /* QoS requested by peer */
@@ -227,4 +226,9 @@
 void irlap_apply_default_connection_parameters(struct irlap_cb *self);
 void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *);
 
+extern inline __u8 irlap_get_header_size(struct irlap_cb *self)
+{
+	return 2;
+}
+
 #endif
diff -urN linux-2.2.10-pre1/include/net/irda/irlmp.h linux-2.2.10-pre2/include/net/irda/irlmp.h
--- linux-2.2.10-pre1/include/net/irda/irlmp.h	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/irlmp.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Fri Apr 23 09:15:07 1999
+ * Modified at:   Sun May  9 11:01:34 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -52,7 +52,7 @@
 
 #define LMP_HEADER          2    /* Dest LSAP + Source LSAP */
 #define LMP_CONTROL_HEADER  4
-#define LMP_MAX_HEADER      (LAP_HEADER+LMP_HEADER)
+#define LMP_MAX_HEADER      (LMP_CONTROL_HEADER+LAP_MAX_HEADER)
 
 #define LM_MAX_CONNECTIONS  10
 
diff -urN linux-2.2.10-pre1/include/net/irda/irlpt_common.h linux-2.2.10-pre2/include/net/irda/irlpt_common.h
--- linux-2.2.10-pre1/include/net/irda/irlpt_common.h	1999-03-07 15:26:43.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/irlpt_common.h	2003-08-15 15:06:23.000000000 -0700
@@ -158,7 +158,8 @@
 	struct miscdevice ir_dev; /* used to register the misc device. */
 
 	int count;                /* open count */
-	int irlap_data_size;	/* max frame size we can send */
+	int max_data_size;	/* max frame size we can send */
+	int max_header_size;    /* how much header space is needed */
 	int pkt_count;		/* how many packets are queued up */
 
 	struct wait_queue *read_wait;	/* wait queues */
diff -urN linux-2.2.10-pre1/include/net/irda/irport.h linux-2.2.10-pre2/include/net/irda/irport.h
--- linux-2.2.10-pre1/include/net/irda/irport.h	1999-01-20 11:05:33.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/irport.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug  3 13:49:59 1997
- * Modified at:   Thu Jan  7 14:17:31 1999
+ * Modified at:   Mon May 10 22:12:56 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1998 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -49,13 +49,13 @@
 
 #define FRAME_MAX_SIZE 2048
 
-void irport_close( int iobase);
-int  irport_open( int iobase);
-int  irport_detect(struct irda_device *idev);
+void irport_start(int iobase);
+void irport_stop(int iobase);
+int  irport_probe(int iobase);
 
-void irport_change_speed( int iobase, int speed);
+void irport_change_speed(struct irda_device *idev, int speed);
 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
-int  irport_hard_xmit( struct sk_buff *skb, struct device *dev);
+int  irport_hard_xmit(struct sk_buff *skb, struct device *dev);
 
 #endif
diff -urN linux-2.2.10-pre1/include/net/irda/irttp.h linux-2.2.10-pre2/include/net/irda/irttp.h
--- linux-2.2.10-pre1/include/net/irda/irttp.h	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/include/net/irda/irttp.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Sat Apr 10 10:19:56 1999
+ * Modified at:   Mon May 10 19:14:51 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -36,7 +36,8 @@
 
 #define TTP_MAX_CONNECTIONS    LM_MAX_CONNECTIONS
 #define TTP_HEADER             1
-#define TTP_HEADER_WITH_SAR    6
+#define TTP_MAX_HEADER         (TTP_HEADER + LMP_MAX_HEADER)
+#define TTP_SAR_HEADER         5
 #define TTP_PARAMETERS         0x80
 #define TTP_MORE               0x80
 
@@ -61,8 +62,6 @@
 	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 */
-
 	__u8 stsap_sel;       /* Source TSAP */
 	__u8 dtsap_sel;       /* Destination TSAP */
 
@@ -88,6 +87,9 @@
 	struct irda_statistics stats;
 	struct timer_list todo_timer; 
 	
+	__u32 max_seg_size;     /* Max data that fit into an IrLAP frame */
+	__u8  max_header_size;
+
 	int   rx_sdu_busy;     /* RxSdu.busy */
 	__u32 rx_sdu_size;     /* Current size of a partially received frame */
 	__u32 rx_max_sdu_size; /* Max receive user data size */
@@ -120,8 +122,6 @@
 			  __u32 saddr, __u32 daddr,
 			  struct qos_info *qos, __u32 max_sdu_size, 
 			  struct sk_buff *userdata);
-void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
-			   __u32 max_sdu_size, struct sk_buff *skb);
 void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
 			    struct sk_buff *userdata);
 struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance);
diff -urN linux-2.2.10-pre1/include/net/irda/irtty.h linux-2.2.10-pre2/include/net/irda/irtty.h
--- linux-2.2.10-pre1/include/net/irda/irtty.h	1999-03-07 15:26:44.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/irtty.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Sun Feb  7 01:57:33 1999
+ * Modified at:   Mon May 10 13:22:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
- *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 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 
@@ -33,8 +33,6 @@
 #include <net/irda/irqueue.h>
 #include <net/irda/irda_device.h>
 
-#include <net/irda/dongle.h>
-
 #define IRTTY_IOC_MAGIC 'e'
 #define IRTTY_IOCTDONGLE  _IO(IRTTY_IOC_MAGIC, 1)
 #define IRTTY_IOC_MAXNR   1
@@ -43,28 +41,21 @@
 #define N_IRDA         11   /* This one should go in </asm/termio.h> */
 #endif
 
-struct dongle_q {
-	QUEUE q;
-
-	struct dongle *dongle;
-};
-
 struct irtty_cb {
 	QUEUE q; /* Must be first */
 
-/* 	char name[16]; */
-
 	int	magic;
 	
 	struct  tty_struct  *tty;  /* Ptr to TTY structure */
 	struct  irda_device idev;
-
-	struct dongle_q *dongle_q; /* Has this tty got a dongle attached? */
 };
  
-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);
+int irtty_register_dongle(struct dongle *dongle);
+void irtty_unregister_dongle(struct dongle *dongle);
 
 #endif
+
+
+
+
+
diff -urN linux-2.2.10-pre1/include/net/irda/toshoboe.h linux-2.2.10-pre2/include/net/irda/toshoboe.h
--- linux-2.2.10-pre1/include/net/irda/toshoboe.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/toshoboe.h	2003-08-15 15:06:23.000000000 -0700
@@ -0,0 +1,165 @@
+/*********************************************************************
+ *                
+ * Filename:      toshoboe.h
+ * Version:       0.1
+ * Description:   Driver for the Toshiba OBOE (or type-O)
+ *                FIR Chipset. 
+ * Status:        Experimental.
+ * Author:        James McKenzie <james@fishsoup.dhs.org>
+ * Created at:    Sat May 8  12:35:27 1999
+ * 
+ *     Copyright (c) 1999 James McKenzie, 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 James McKenzie nor Cambridge University admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Applicable Models : Libretto 100CT. and many more
+ *
+ ********************************************************************/
+
+/*
+ * $Log: toshoboe.h,v $
+ * Revision 1.2  1999/05/09 01:43:08  root
+ * *** empty log message ***
+ *
+ * Revision 1.1  1999/05/09 01:25:58  root
+ * Initial revision
+ *
+ */
+
+#ifndef TOSHOBOE_H
+#define TOSHOBOE_H
+
+/* Registers */
+/*Receive and transmit task registers (read only) */
+#define OBOE_RCVT	(0x00+(self->base))
+#define OBOE_XMTT	(0x01+(self->base))
+#define OBOE_XMTT_OFFSET	0x40
+
+/*Page pointers to the TaskFile structure */
+#define OBOE_TFP2	(0x02+(self->base))
+#define OBOE_TFP0	(0x04+(self->base))
+#define OBOE_TFP1	(0x05+(self->base))
+
+/*Dunno */
+#define OBOE_REG_3	(0x03+(self->base))
+
+/*Number of tasks to use in Xmit and Recv queues */
+#define OBOE_NTR	(0x07+(self->base))
+#define OBOE_NTR_XMIT4	0x00
+#define OBOE_NTR_XMIT8	0x10
+#define OBOE_NTR_XMIT16	0x30
+#define OBOE_NTR_XMIT32	0x70
+#define OBOE_NTR_XMIT64	0xf0
+#define OBOE_NTR_RECV4	0x00
+#define OBOE_NTR_RECV8	0x01
+#define OBOE_NTR_RECV6	0x03
+#define OBOE_NTR_RECV32	0x07
+#define OBOE_NTR_RECV64	0x0f
+
+/* Dunno */
+#define OBOE_REG_9	(0x09+(self->base))
+
+/* Interrupt Status Register */
+#define OBOE_ISR	(0x0c+(self->base))
+#define OBOE_ISR_TXDONE	0x80
+#define OBOE_ISR_RXDONE	0x40
+#define OBOE_ISR_20	0x20
+#define OBOE_ISR_10	0x10
+#define OBOE_ISR_8	0x08         /*This is collision or parity or something */
+#define OBOE_ISR_4	0x08
+#define OBOE_ISR_2	0x08
+#define OBOE_ISR_1	0x08
+
+/*Dunno */
+#define OBOE_REG_D	(0x0d+(self->base))
+
+/*Register Lock Register */
+#define OBOE_LOCK	((self->base)+0x0e)
+
+
+
+/*Speed control registers */
+#define OBOE_PMDL	(0x10+(self->base))
+#define OBOE_PMDL_SIR	0x18
+#define OBOE_PMDL_MIR	0xa0
+#define OBOE_PMDL_FIR	0x40
+
+#define OBOE_SMDL	(0x18+(self->base))
+#define OBOE_SMDL_SIR	0x20
+#define OBOE_SMDL_MIR	0x01
+#define OBOE_SMDL_FIR	0x0f
+
+#define OBOE_UDIV	(0x19+(self->base))
+
+/*Dunno */
+#define OBOE_REG_11	(0x11+(self->base))
+
+/*Chip Reset Register */
+#define OBOE_RST	(0x15+(self->base))
+#define OBOE_RST_WRAP	0x8
+
+/*Dunno */
+#define OBOE_REG_1A	(0x1a+(self->base))
+#define OBOE_REG_1B	(0x1b+(self->base))
+
+/* The PCI ID of the OBOE chip */
+#ifndef PCI_DEVICE_ID_FIR701
+#define PCI_DEVICE_ID_FIR701 	0x0701
+#endif
+
+typedef unsigned int dword;
+typedef unsigned short int word;
+typedef unsigned char byte;
+typedef dword Paddr;
+
+struct OboeTask
+  {
+    __u16 len;
+    __u8 unused;
+    __u8 control;
+    __u32 buffer;
+  };
+
+#define OBOE_NTASKS 64
+
+struct OboeTaskFile
+  {
+    struct OboeTask recv[OBOE_NTASKS];
+    struct OboeTask xmit[OBOE_NTASKS];
+  };
+
+#define OBOE_TASK_BUF_LEN (sizeof(struct OboeTaskFile) << 1)
+
+/*These set the number of slots in use */
+#define TX_SLOTS	4
+#define RX_SLOTS	4
+
+/* You need also to change this, toshiba uses 4,8 and 4,4 */
+/* It makes no difference if you are only going to use ONETASK mode */
+/* remember each buffer use XX_BUF_SZ more _PHYSICAL_ memory */
+#define OBOE_NTR_VAL 	(OBOE_NTR_XMIT4 | OBOE_NTR_RECV4)
+
+struct toshoboe_cb
+  {
+    struct irda_device idev;    /*IRDA device */
+    struct pci_dev *pdev;       /*PCI device */
+    int base;                   /*IO base */
+    int txpending;              /*how many tx's are pending */
+    int txs, rxs;               /*Which slots are we at  */
+    void *taskfilebuf;          /*The unaligned taskfile buffer */
+    struct OboeTaskFile *taskfile;  /*The taskfile   */
+    void *xmit_bufs[TX_SLOTS];  /*The buffers   */
+    void *recv_bufs[RX_SLOTS];
+  };
+
+
+#endif
+
+
diff -urN linux-2.2.10-pre1/include/net/irda/w83977af_ir.h linux-2.2.10-pre2/include/net/irda/w83977af_ir.h
--- linux-2.2.10-pre1/include/net/irda/w83977af_ir.h	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/w83977af_ir.h	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Thu Nov 19 13:55:34 1998
- * Modified at:   Thu Dec 10 14:06:18 1998
+ * Modified at:   Mon May  3 12:07:25 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -150,6 +150,29 @@
 #define IRM_CR_IRX_MSL	0x40
 #define IRM_CR_AF_MNT   0x80 /* Automatic format */
 
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+struct st_fifo {
+	struct st_fifo_entry entries[10];
+	int head;
+	int tail;
+	int len;
+};
+
+/* Private data for each instance */
+struct w83977af_ir {
+	struct st_fifo st_fifo;
+
+	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
+	int tx_len;          /* Number of frames in tx_buff */
+
+	struct irda_device idev;
+};
+
 static inline void switch_bank( int iobase, int set)
 {
 	outb( set, iobase+SSR);
diff -urN linux-2.2.10-pre1/include/net/irda/wrapper.h linux-2.2.10-pre2/include/net/irda/wrapper.h
--- linux-2.2.10-pre1/include/net/irda/wrapper.h	1999-03-07 15:26:44.000000000 -0800
+++ linux-2.2.10-pre2/include/net/irda/wrapper.h	2003-08-15 15:06:23.000000000 -0700
@@ -1,15 +1,16 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.h
- * Version:       1.0
- * Description:   IrDA Wrapper layer
+ * Version:       1.2
+ * Description:   IrDA SIR async wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri Jan 29 10:15:46 1999
+ * Modified at:   Mon May  3 09:02:36 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -38,17 +39,18 @@
 #define STA BOF  /* Start flag */
 #define STO EOF  /* End flag */
 
-#define IR_TRANS 0x20    /* Asynchronous transparency modifier */       
+#define IRDA_TRANS 0x20    /* Asynchronous transparency modifier */       
 
+/* States for receving a frame in async mode */
 enum {
-	OUTSIDE_FRAME = 1, 
+	OUTSIDE_FRAME, 
 	BEGIN_FRAME, 
 	LINK_ESCAPE, 
 	INSIDE_FRAME
 };
 
 /* Proto definitions */
-int  async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize);
-void async_unwrap_char( struct irda_device *, __u8 byte);
+int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize);
+inline void async_unwrap_char(struct irda_device *idev, __u8 byte);
 
 #endif
diff -urN linux-2.2.10-pre1/net/ipv4/ip_options.c linux-2.2.10-pre2/net/ipv4/ip_options.c
--- linux-2.2.10-pre1/net/ipv4/ip_options.c	1999-03-21 07:22:00.000000000 -0800
+++ linux-2.2.10-pre2/net/ipv4/ip_options.c	2003-08-15 15:06:23.000000000 -0700
@@ -452,7 +452,6 @@
 error:
 	if (skb) {
 		icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
-		kfree_skb(skb);
 	}
 	return -EINVAL;
 }
diff -urN linux-2.2.10-pre1/net/ipv6/icmp.c linux-2.2.10-pre2/net/ipv6/icmp.c
--- linux-2.2.10-pre1/net/ipv6/icmp.c	1999-03-21 07:22:00.000000000 -0800
+++ linux-2.2.10-pre2/net/ipv6/icmp.c	2003-08-15 15:06:23.000000000 -0700
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *
- *	$Id: icmp.c,v 1.21 1999/03/21 05:22:51 davem Exp $
+ *	$Id: icmp.c,v 1.21.2.1 1999/05/19 22:07:36 davem Exp $
  *
  *	Based on net/ipv4/icmp.c
  *
@@ -315,6 +315,7 @@
 	fl.nl_u.ip6_u.daddr = &hdr->saddr;
 	fl.nl_u.ip6_u.saddr = saddr;
 	fl.oif = iif;
+	fl.fl6_flowlabel = 0;
 	fl.uli_u.icmpt.type = type;
 	fl.uli_u.icmpt.code = code;
 
@@ -388,6 +389,7 @@
 	fl.nl_u.ip6_u.daddr = &hdr->saddr;
 	fl.nl_u.ip6_u.saddr = saddr;
 	fl.oif = skb->dev->ifindex;
+	fl.fl6_flowlabel = 0;
 	fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;
 	fl.uli_u.icmpt.code = 0;
 
diff -urN linux-2.2.10-pre1/net/irda/af_irda.c linux-2.2.10-pre2/net/irda/af_irda.c
--- linux-2.2.10-pre1/net/irda/af_irda.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/af_irda.c	2003-08-15 15:06:23.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 Apr 22 12:08:04 1999
+ * Modified at:   Tue May 11 12:42:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
  * 
@@ -30,6 +30,7 @@
 #include <linux/if_arp.h>
 #include <linux/net.h>
 #include <linux/irda.h>
+#include <linux/poll.h>
 
 #include <asm/uaccess.h>
 
@@ -46,11 +47,12 @@
 extern int  irlap_driver_rcv(struct sk_buff *, struct device *, 
 			     struct packet_type *);
 
-static struct proto_ops irda_proto_ops;
+static struct proto_ops irda_stream_ops;
+static struct proto_ops irda_dgram_ops;
 static hashbin_t *cachelog = NULL;
 static struct wait_queue *discovery_wait; /* Wait for discovery */
 
-#define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
+#define IRDA_MAX_HEADER (TTP_MAX_HEADER)
 
 /*
  * Function irda_data_indication (instance, sap, skb)
@@ -121,7 +123,8 @@
  */
 static void irda_connect_confirm(void *instance, void *sap, 
 				 struct qos_info *qos,
-				 __u32 max_sdu_size, struct sk_buff *skb)
+				 __u32 max_sdu_size, __u8 max_header_size, 
+				 struct sk_buff *skb)
 {
 	struct irda_sock *self;
 	struct sock *sk;
@@ -130,13 +133,28 @@
 
 	self = (struct irda_sock *) instance;
 
+	/* How much header space do we need to reserve */
+	self->max_header_size = max_header_size;
+
+	/* IrTTP max SDU size in transmit direction */
 	self->max_sdu_size_tx = max_sdu_size;
+
+	/* Find out what the largest chunk of data that we can transmit is */
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_data_size = qos->data_size.value - max_header_size;
+	else
+		self->max_data_size = max_sdu_size;
+
+	DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
 
 	sk = self->sk;
 	if (sk == NULL)
 		return;
 
+	skb_queue_tail(&sk->receive_queue, skb);
+
 	/* We are now connected! */
 	sk->state = TCP_ESTABLISHED;
 	sk->state_change(sk);
@@ -150,7 +168,7 @@
  */
 static void irda_connect_indication(void *instance, void *sap, 
 				    struct qos_info *qos, __u32 max_sdu_size,
-				    struct sk_buff *skb)
+				    __u8 max_header_size, struct sk_buff *skb)
 {
 	struct irda_sock *self;
 	struct sock *sk;
@@ -158,8 +176,21 @@
 	DEBUG(1, __FUNCTION__ "()\n");
 
 	self = (struct irda_sock *) instance;
-	
-	self->max_sdu_size_tx = max_sdu_size;
+
+	/* How much header space do we need to reserve */
+	self->max_header_size = max_header_size;
+
+	/* IrTTP max SDU size in transmit direction */
+	self->max_sdu_size_tx = max_sdu_size;	
+
+	/* Find out what the largest chunk of data that we can transmit is */
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_data_size = qos->data_size.value - max_header_size;
+	else
+		self->max_data_size = max_sdu_size;
+
+	DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
 
 	sk = self->sk;
@@ -187,12 +218,12 @@
 
 	skb = dev_alloc_skb(64);
 	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n");
+		DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n");
 		return;
 	}
 
 	/* Reserve space for MUX_CONTROL and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER);
+	skb_reserve(skb, IRDA_MAX_HEADER);
 
 	irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb);
 }
@@ -514,10 +545,13 @@
 	new->stsap_sel = new->tsap->stsap_sel;
 	new->dtsap_sel = new->tsap->dtsap_sel;
 	new->saddr = irttp_get_saddr(new->tsap);
-	new->saddr = irttp_get_saddr(new->tsap);
+	new->daddr = irttp_get_daddr(new->tsap);
 
 	new->max_sdu_size_tx = self->max_sdu_size_tx;
 	new->max_sdu_size_rx = self->max_sdu_size_rx;
+	new->max_data_size   = self->max_data_size;
+	new->max_header_size = self->max_header_size;
+
 	memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info));
 
 	/* Clean up the original one to keep it in listen state */
@@ -669,7 +703,7 @@
 
 	sock_init_data(sock, sk);
 
-	sock->ops    = &irda_proto_ops;
+	sock->ops    = &irda_stream_ops;
 	sk->protocol = protocol;
 
 	/* Register as a client with IrLMP */
@@ -786,12 +820,20 @@
 			return -ENOTCONN;
 	}
 
-	skb = sock_alloc_send_skb(sk, len + IRDA_MAX_HEADER, 0, 
+	/* Check that we don't send out to big frames */
+	if (len > self->max_data_size) {
+		DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+		      "Chopping frame from %d to %d bytes!\n", len, 
+		      self->max_data_size);
+		len = self->max_data_size;
+	}
+
+	skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, 
 				  msg->msg_flags & MSG_DONTWAIT, &err);
 	if (!skb)
 		return -ENOBUFS;
 
-	skb_reserve(skb, IRDA_MAX_HEADER);
+	skb_reserve(skb, self->max_header_size);
 	
 	DEBUG(4, __FUNCTION__ "(), appending user data\n");
 	asmptr = skb->h.raw = skb_put(skb, len);
@@ -815,8 +857,8 @@
  *    Try to receive message and copy it to user
  *
  */
-static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size,
-			int flags, struct scm_cookie *scm)
+static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg, 
+			      int size, int flags, struct scm_cookie *scm)
 {
 	struct irda_sock *self;
 	struct sock *sk = sock->sk;
@@ -862,6 +904,161 @@
 }
 
 /*
+ * Function irda_data_wait (sk)
+ *
+ *    Sleep until data has arrive. But check for races..
+ *
+ */
+static void irda_data_wait(struct sock *sk)
+{
+	if (!skb_peek(&sk->receive_queue)) {
+		sk->socket->flags |= SO_WAITDATA;
+		interruptible_sleep_on(sk->sleep);
+		sk->socket->flags &= ~SO_WAITDATA;
+	}
+}
+
+/*
+ * Function irda_recvmsg_stream (sock, msg, size, flags, scm)
+ *
+ *    
+ *
+ */
+static int irda_recvmsg_stream(struct socket *sock, struct msghdr *msg, 
+			       int size, int flags, struct scm_cookie *scm)
+{
+	struct irda_sock *self;
+	struct sock *sk = sock->sk;
+	int noblock = flags & MSG_DONTWAIT;
+	int copied = 0;
+	int target = 1;
+
+	DEBUG(3, __FUNCTION__ "()\n");
+
+	self = sk->protinfo.irda;
+	ASSERT(self != NULL, return -1;);
+
+	if (sock->flags & SO_ACCEPTCON) 
+		return(-EINVAL);
+
+	if (flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	if (flags & MSG_WAITALL)
+		target = size;
+		
+		
+	msg->msg_namelen = 0;
+
+	/* Lock the socket to prevent queue disordering
+	 * while sleeps in memcpy_tomsg
+	 */
+/* 	down(&self->readsem); */
+
+	do {
+		int chunk;
+		struct sk_buff *skb;
+
+		skb=skb_dequeue(&sk->receive_queue);
+		if (skb==NULL) {
+			if (copied >= target)
+				break;
+			
+			/*
+			 *	POSIX 1003.1g mandates this order.
+			 */
+			
+			if (sk->err) {
+				/* up(&self->readsem); */
+				return sock_error(sk);
+			}
+
+			if (sk->shutdown & RCV_SHUTDOWN)
+				break;
+
+		/* 	up(&self->readsem); */
+
+			if (noblock)
+				return -EAGAIN;
+			irda_data_wait(sk);
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+		/* 	down(&self->readsem); */
+			continue;
+		}
+
+		/* Never glue messages from different writers */
+/* 		if (check_creds && */
+/* 		    memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) */
+/* 		{ */
+/* 			skb_queue_head(&sk->receive_queue, skb); */
+/* 			break; */
+/* 		} */
+
+		chunk = min(skb->len, size);
+		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
+			skb_queue_head(&sk->receive_queue, skb);
+			if (copied == 0)
+				copied = -EFAULT;
+			break;
+		}
+		copied += chunk;
+		size -= chunk;
+
+ 		/* Copy credentials */
+/* 		scm->creds = *UNIXCREDS(skb); */
+/* 		check_creds = 1; */
+
+		/* Mark read part of skb as used */
+		if (!(flags & MSG_PEEK)) {
+			skb_pull(skb, chunk);
+
+/* 			if (UNIXCB(skb).fp) */
+/* 				unix_detach_fds(scm, skb); */
+
+			/* put the skb back if we didn't use it up.. */
+			if (skb->len) {
+				DEBUG(1, __FUNCTION__ "(), back on q!\n");
+				skb_queue_head(&sk->receive_queue, skb);
+				break;
+			}
+
+			kfree_skb(skb);
+			
+/* 			if (scm->fp) */
+/* 				break; */
+		} else {
+			DEBUG(0, __FUNCTION__ "() questionable!?\n");
+			/* It is questionable, see note in unix_dgram_recvmsg. */
+/* 			if (UNIXCB(skb).fp) */
+/* 				scm->fp = scm_fp_dup(UNIXCB(skb).fp); */
+
+			/* put message back and return */
+			skb_queue_head(&sk->receive_queue, skb);
+			break;
+		}
+	} while (size);
+
+	/*
+	 *  Check if we have previously stopped IrTTP and we know
+	 *  have more free space in our rx_queue. If so tell IrTTP
+	 *  to start delivering frames again before our rx_queue gets
+	 *  empty
+	 */
+	if (self->rx_flow == FLOW_STOP) {
+		if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) {
+			DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n");
+			self->rx_flow = FLOW_START;
+			irttp_flow_request(self->tsap, FLOW_START);
+		}
+	}
+
+	/* up(&self->readsem); */
+
+	return copied;
+}
+
+/*
  * Function irda_shutdown (sk, how)
  *
  *    
@@ -875,19 +1072,45 @@
         return -EOPNOTSUPP;
 }
 
-
 /*
  * Function irda_poll (file, sock, wait)
  *
  *    
  *
  */
-unsigned int irda_poll(struct file *file, struct socket *sock, 
-		       struct poll_table_struct *wait)
+static unsigned int irda_poll(struct file * file, struct socket *sock, 
+			      poll_table *wait)
 {
-	DEBUG(0, __FUNCTION__ "()\n");
+	struct sock *sk = sock->sk;
+	unsigned int mask;
 
-	return 0;
+	DEBUG(1, __FUNCTION__ "()\n");
+
+	poll_wait(file, sk->sleep, wait);
+	mask = 0;
+
+	/* exceptional events? */
+	if (sk->err)
+		mask |= POLLERR;
+	if (sk->shutdown & RCV_SHUTDOWN)
+		mask |= POLLHUP;
+
+	/* readable? */
+	if (!skb_queue_empty(&sk->receive_queue))
+		mask |= POLLIN | POLLRDNORM;
+
+	/* Connection-based need to check for termination and startup */
+	if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE)
+		mask |= POLLHUP;
+
+	/*
+	 * we set writable also when the other side has shut down the
+	 * connection. This prevents stuck sockets.
+	 */
+	if (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= MIN_WRITE_SPACE)
+			mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+
+	return mask;
 }
 
 /*
@@ -947,6 +1170,7 @@
 		return -EINVAL;
 		
 	default:
+		DEBUG(0, __FUNCTION__ "(), doing device ioctl!\n");
 		return dev_ioctl(cmd, (void *) arg);
 	}
 
@@ -1082,13 +1306,7 @@
 			return -EFAULT;
 		break;
 	case IRTTP_MAX_SDU_SIZE:
-		if (self->max_sdu_size_tx != SAR_DISABLE)
-			val = self->max_sdu_size_tx;
-		else
-			/* SAR is disabled, so use the IrLAP data size
-			 * instead */
-			val = self->qos_tx.data_size.value - IRDA_MAX_HEADER;
-
+		val = self->max_data_size;
 		DEBUG(0, __FUNCTION__ "(), getting max_sdu_size = %d\n", val);
 		len = sizeof(int);
 		if (put_user(len, optlen))
@@ -1110,7 +1328,7 @@
 	irda_create
 };
 
-static struct proto_ops irda_proto_ops = {
+static struct proto_ops irda_stream_ops = {
 	PF_IRDA,
 	
 	sock_no_dup,
@@ -1128,7 +1346,28 @@
 	irda_getsockopt,
 	sock_no_fcntl,
 	irda_sendmsg,
-	irda_recvmsg
+	irda_recvmsg_stream
+};
+
+static struct proto_ops irda_dgram_ops = {
+	PF_IRDA,
+	
+	sock_no_dup,
+	irda_release,
+	irda_bind,
+	irda_connect,
+	sock_no_socketpair,
+	irda_accept,
+	irda_getname,
+	datagram_poll,
+	irda_ioctl,
+	irda_listen,
+	irda_shutdown,
+	irda_setsockopt,
+	irda_getsockopt,
+	sock_no_fcntl,
+	irda_sendmsg,
+	irda_recvmsg_dgram
 };
 
 /*
@@ -1215,7 +1454,7 @@
 	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);
 	
 	sock_unregister(PF_IRDA);
 	irda_cleanup();
diff -urN linux-2.2.10-pre1/net/irda/crc.c linux-2.2.10-pre2/net/irda/crc.c
--- linux-2.2.10-pre1/net/irda/crc.c	1998-12-17 09:01:03.000000000 -0800
+++ linux-2.2.10-pre2/net/irda/crc.c	2003-08-15 15:06:23.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:   Sat Dec 12 09:56:35 1998
+ * Modified at:   Sun May  2 20:28:08 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       ppp.c by Michael Callahan <callahan@maths.ox.ac.uk>
  *                Al Longyear <longyear@netcom.com>
@@ -59,7 +59,7 @@
 
 unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len) 
 {
-    while ( len--)
-		fcs = IR_FCS(fcs, *buf++);
-    return fcs;
+	while (len--)
+                fcs = irda_fcs(fcs, *buf++);
+	return fcs;
 }
diff -urN linux-2.2.10-pre1/net/irda/discovery.c linux-2.2.10-pre2/net/irda/discovery.c
--- linux-2.2.10-pre1/net/irda/discovery.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/discovery.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr  6 15:33:50 1999
- * Modified at:   Sun Apr 11 00:41:58 1999
+ * Modified at:   Sun May  9 22:40:43 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -39,28 +39,51 @@
 /*
  * Function irlmp_add_discovery (cachelog, discovery)
  *
- *    
- *
+ *    Add a new discovery to the cachelog, and remove any old discoveries
+ *    from the same device
  */
-void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery)
+void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
 {
-	discovery_t *old;
+	discovery_t *discovery, *node;
+	unsigned long flags;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	spin_lock_irqsave(&irlmp->lock, flags);
+
+	/* 
+	 * Remove all discoveries of devices that has previously been 
+	 * discovered on the same link with the same name (info), or the 
+	 * same daddr. We do this since some devices (mostly PDAs) change
+	 * their device address between every discovery.
+	 */
+	discovery = (discovery_t *) hashbin_get_first(cachelog);
+	while (discovery != NULL ) {
+			node = discovery;
+
+			/* Be sure to stay one item ahead */
+			discovery = (discovery_t *) hashbin_get_next(cachelog);
+			
+			if ((node->daddr == new->daddr) || 
+			    (strcmp(node->info, new->info) == 0))
+			{
+				/* This discovery is a previous discovery 
+				 * from the same device, so just remove it
+				 */
+				hashbin_remove(cachelog, node->daddr, NULL);
+				kfree(node);
+			}
+		}
 
-	/* Check if we have discovered this device before */
-	old = hashbin_remove(cachelog, discovery->daddr, NULL);
-	if (old)
-		kfree(old);
 
 	/* Insert the new and updated version */
-	hashbin_insert(cachelog, (QUEUE *) discovery, discovery->daddr, NULL);
+	hashbin_insert(cachelog, (QUEUE *) new, new->daddr, NULL);
+
+	spin_unlock_irqrestore(&irlmp->lock, flags);
 }
 
 /*
  * Function irlmp_add_discovery_log (cachelog, log)
  *
- *    
+ *    Merge a disovery log into the cachlog.
  *
  */
 void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
diff -urN linux-2.2.10-pre1/net/irda/ircomm/ircomm_common.c linux-2.2.10-pre2/net/irda/ircomm/ircomm_common.c
--- linux-2.2.10-pre1/net/irda/ircomm/ircomm_common.c	1999-05-06 16:40:53.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/ircomm/ircomm_common.c	2003-08-15 15:06:23.000000000 -0700
@@ -8,7 +8,7 @@
  * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
  * Source:        irlpt_event.c
  *
- *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
  *     All Rights Reserved.
  *
  *     This program is free software; you can redistribute it and/or
@@ -44,18 +44,17 @@
 static char *revision_date = "Sun Apr 18 00:40:19 1999";
 
 
-static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb );
-
-static void ircomm_state_discoverywait( struct ircomm_cb *self, IRCOMM_EVENT event, 
+static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb );
+static void ircomm_state_discoverywait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
+				       struct sk_buff *skb );
+static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
+					IRCOMM_EVENT event, 
 					struct sk_buff *skb );
-
-static void ircomm_state_queryparamwait( struct ircomm_cb *self, IRCOMM_EVENT event, 
-					 struct sk_buff *skb );
-
-static void ircomm_state_querylsapwait( struct ircomm_cb *self, IRCOMM_EVENT event, 
-					struct sk_buff *skb );
-
+static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
+				       struct sk_buff *skb );
 static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, 
 				struct sk_buff *skb );
 static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, 
@@ -207,7 +206,7 @@
 		ircomm[i]->ack_char = 0x06;  
 
 		ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE;   /* 64 */
-		ircomm[i]->maxsdusize = SAR_DISABLE;  
+		ircomm[i]->max_sdu_size = SAR_DISABLE;  
 		ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
 		if (ircomm[i]->ctrl_skb == NULL){
 			DEBUG(0,"ircomm:init_module:alloc_skb failed!\n");
@@ -226,7 +225,6 @@
 	create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
 #endif /* CONFIG_PROC_FS */
 
-
 	discovering_instance = NULL;
 	return 0;
 }
@@ -275,51 +273,53 @@
 static int ircomm_accept_data_indication(void *instance, void *sap, 
 					 struct sk_buff *skb)
 {
-	
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return -1;);
-	ASSERT( skb != NULL, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
        
 	DEBUG(4,__FUNCTION__"():\n");
-	ircomm_do_event( self, TTP_DATA_INDICATION, skb);
+	ircomm_do_event(self, TTP_DATA_INDICATION, skb);
 	self->rx_packets++;
 	
 	return 0;
 }
 
 static void ircomm_accept_connect_confirm(void *instance, void *sap,
-				   struct qos_info *qos, 
-				   __u32 maxsdusize, struct sk_buff *skb)
+					  struct qos_info *qos, 
+					  __u32 max_sdu_size, 
+					  __u8 max_header_size,
+					  struct sk_buff *skb)
 {
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
 
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	ASSERT( qos != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
 
 	DEBUG(0,__FUNCTION__"(): got connected!\n");
 
-	if(maxsdusize == SAR_DISABLE)
-		self->max_txbuff_size = qos->data_size.value; 
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_txbuff_size = qos->data_size.value - max_header_size;
 	else {
-		ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;);
-		self->max_txbuff_size = maxsdusize; /* use fragmentation */
+		ASSERT(max_sdu_size >= COMM_DEFAULT_DATA_SIZE, return;);
+		self->max_txbuff_size = max_sdu_size; /* use fragmentation */
 	}
 
 	self->qos = qos;
-	self->null_modem_mode = 0;            	/* disable null modem emulation */
+	self->max_header_size = max_header_size;
+	self->null_modem_mode = 0;         /* disable null modem emulation */
 
-	ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb);
+	ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb);
 }
 
 static void ircomm_accept_connect_indication(void *instance, void *sap,
-				      struct qos_info *qos,
-				      __u32 maxsdusize,
-				      struct sk_buff *skb )
+					     struct qos_info *qos,
+					     __u32 max_sdu_size,
+					     __u8 max_header_size,
+					     struct sk_buff *skb)
 {
 	struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -330,12 +330,14 @@
 
 	DEBUG(0,__FUNCTION__"()\n");
 
-	if(maxsdusize == SAR_DISABLE)
-		self->max_txbuff_size = qos->data_size.value;
+	if (max_sdu_size == SAR_DISABLE)
+		self->max_txbuff_size = qos->data_size.value - max_header_size;
 	else
-		self->max_txbuff_size = maxsdusize;
+		self->max_txbuff_size = max_sdu_size;
 
 	self->qos = qos;
+	self->max_header_size = max_header_size;
+
 	ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
 
 	/* stop connecting */
@@ -556,7 +558,7 @@
 
 		irttp_connect_request(self->tsap, self->dlsap, 
 				      self->saddr, self->daddr, 
-				      NULL, self->maxsdusize, userdata); 
+				      NULL, self->max_sdu_size, userdata); 
 		break;
 
 	default:
@@ -588,9 +590,9 @@
 /* 	if( !ircomm_parse_controlchannel( self, data)) */
 /* 		self->servicetype = DEFAULT;     TODOD:fix this! TH */
 
-	if(self->notify.connect_indication)
+	if (self->notify.connect_indication)
 		self->notify.connect_indication(self->notify.instance, self, 
-						qos, 0, skb);
+						qos, 0, 0, skb);
 }
     
 #if 0
@@ -602,28 +604,26 @@
 #endif 
 
 
-static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb)
+static void connect_confirm(struct ircomm_cb *self, struct sk_buff *skb)
 {
 	DEBUG(4 ,__FUNCTION__"()\n");
 
 	/* give a connect_confirm to the client */
 	if( self->notify.connect_confirm )
 		self->notify.connect_confirm(self->notify.instance,
-					     self, NULL, SAR_DISABLE, skb);
+					     self, NULL, SAR_DISABLE, 0, skb);
 }
 
 static void issue_connect_response(struct ircomm_cb *self,
 				   struct sk_buff *skb)
 {
-
 	DEBUG(0,__FUNCTION__"()\n");
 	
 	if( self->servicetype == THREE_WIRE_RAW){
 		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n");
 		/* irlmp_connect_rsp(); */
-	} else {
-		irttp_connect_response(self->tsap, self->maxsdusize, skb);
-	}
+	} else
+		irttp_connect_response(self->tsap, self->max_sdu_size, skb);
 }
 
 static void issue_disconnect_request(struct ircomm_cb *self,
@@ -642,30 +642,29 @@
 {
 	int err;
 
-	if(self->servicetype == THREE_WIRE_RAW){
+	if (self->servicetype == THREE_WIRE_RAW){
 		/* irlmp_data_request(self->lmhandle,userdata); */
 		DEBUG(0,__FUNCTION__"():not implemented!");
 		return;
 	}
 
 	DEBUG(4,__FUNCTION__"():sending frame\n");
-	err = irttp_data_request(self->tsap , userdata  );
-	if(err){
+	err = irttp_data_request(self->tsap, userdata);
+	if (err){
 		printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n");
-		if(userdata)
+		if (userdata)
 			dev_kfree_skb( userdata);
 	}
 	self->tx_packets++;
 }
 
 static void issue_control_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata )
+				  struct sk_buff *userdata)
 {
 	int err;
 
 	DEBUG(4,__FUNCTION__"()\n"); 
-	if(self->servicetype == THREE_WIRE_RAW)
-	{
+	if (self->servicetype == THREE_WIRE_RAW) {
 		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
 		
 	}
@@ -676,7 +675,7 @@
 		{
 			printk( __FUNCTION__"():ttp_data_request failed\n");
 			if(userdata)
-				dev_kfree_skb( userdata);
+				dev_kfree_skb(userdata);
 		}
 		else
 			self->tx_controls++;
@@ -701,7 +700,7 @@
 
  	/* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */
 
-	if(self->notify.data_indication && skb->len)
+	if (self->notify.data_indication && skb->len)
 		self->notify.data_indication(self->notify.instance, self,
 					     skb);
 }
@@ -728,7 +727,7 @@
 	
 	DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n",
 	       ircommstate[self->state], ircommevent[event]);
-	(*state[ self->state ]) ( self, event, skb);
+	(*state[self->state])(self, event, skb);
 }
 
 static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) 
@@ -747,7 +746,7 @@
 static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
 			       struct sk_buff *skb )
 {
-	switch(event){
+	switch (event){
 	case IRCOMM_CONNECT_REQUEST:
 
 		/* ircomm_next_state(self, COMM_WAITI); */
@@ -779,7 +778,8 @@
 /*
  * ircomm_state_discoverywait
  */
-static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static void ircomm_state_discoverywait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
 				       struct sk_buff *skb )
 {
 	switch(event){
@@ -817,11 +817,11 @@
  * ircomm_state_queryparamwait
  */
 
-static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT event, 
-					struct sk_buff *skb )
+static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
+					IRCOMM_EVENT event, 
+					struct sk_buff *skb)
 {
-	switch(event){
-
+	switch (event) {
 	case TTP_CONNECT_INDICATION:
 
 		ircomm_next_state(self, COMM_WAITR);
@@ -855,10 +855,11 @@
  * ircomm_state_querylsapwait
  */
 
-static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT event, 
+static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
+				       IRCOMM_EVENT event, 
 				       struct sk_buff *skb )
 {
-	switch(event){
+	switch (event) {
 
 	case TTP_CONNECT_INDICATION:
 
@@ -898,10 +899,10 @@
 static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
 			  struct sk_buff *skb )
 {
-	switch(event){
+	switch (event) {
 	case TTP_CONNECT_CONFIRM:
 		ircomm_next_state(self, COMM_CONN);
-		connect_confirmation( self, skb );
+		connect_confirm(self, skb );
 		break;
 	case TTP_DISCONNECT_INDICATION:
 		ircomm_next_state(self, COMM_IDLE);
@@ -921,21 +922,18 @@
 	}
 }
 
-
-
 /*
  * 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){
+	switch (event) {
 	case IRCOMM_CONNECT_RESPONSE:
 
 	        /* issue_connect_response */
 		
-		if(self->servicetype==THREE_WIRE_RAW){
+		if (self->servicetype==THREE_WIRE_RAW) {
 			DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n");
 			/* irlmp_connect_response(Vpeersap,
 			 *                         ACCEPT,null);
@@ -987,7 +985,7 @@
 static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
 			      struct sk_buff *skb )
 {
-	switch(event){
+	switch (event) {
 	case TTP_DATA_INDICATION:
 		process_data(self, skb);
 		break;
@@ -1033,8 +1031,6 @@
 	}
 }
 
-
-
 /*
  *  ----------------------------------------------------------------------
  *  IrCOMM service interfaces and supporting functions
@@ -1042,12 +1038,12 @@
  *  ----------------------------------------------------------------------
  */
 
-/* 
- * start_discovering()
+/*
+ * Function start_discovering (self)
+ *
+ *    Start discovering and enter DISCOVERY_WAIT state
  *
- * start discovering and enter DISCOVERY_WAIT state
  */
-
 static void start_discovering(struct ircomm_cb *self)
 {
 	__u16  hints; 
@@ -1092,19 +1088,26 @@
 /*
  * queryias_done(self)
  *
- * called when discovery process got wrong results, completed, or terminated.
+ * 
  */
 
+/*
+ * Function queryias_done (self)
+ *
+ *    Called when discovery process got wrong results, completed, or
+ *    terminated.
+ * 
+ */
 static void queryias_done(struct ircomm_cb *self)
 {
 	DEBUG(0, __FUNCTION__"():\n");
-	if(self->queryias_lock){
+	if (self->queryias_lock){
 		self->queryias_lock = 0;
 		discovering_instance = NULL;
 		MOD_DEC_USE_COUNT;
 		irlmp_unregister_client(self->ckey);
 	}
-	if(ircomm_cs != 1)
+	if (ircomm_cs != 1)
 		irlmp_unregister_service(self->skey);
 	return;
 }
@@ -1120,7 +1123,6 @@
 				       ircomm_getvalue_confirm, self );
 }
 
-
 static void query_lsapsel(struct ircomm_cb * self)
 {
 	DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n");
@@ -1135,13 +1137,13 @@
 	}
 }
 
-/* 
- * ircomm_connect_request()
- * Impl. of this function is differ from one of the reference.
- * This functin does discovery as well as sending connect request
+/*
+ * Function ircomm_connect_request (self, servicetype)
+ *
+ *    Impl. of this function is differ from one of the reference. This
+ *    function does discovery as well as sending connect request
+ * 
  */
-
-
 void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype)
 {
 	/*
@@ -1158,12 +1160,12 @@
 	self->servicetype= servicetype;
 	/* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/
 
-	self->maxsdusize = SAR_DISABLE;
-	ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL);
+	self->max_sdu_size = SAR_DISABLE;
+	ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL);
 }
 
 void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     __u32 maxsdusize)
+			     __u32 max_sdu_size)
 {
 
 	ASSERT( self != NULL, return;);
@@ -1177,10 +1179,11 @@
 	 * and send it with connect_response
 	 */
 
-	if(!userdata){
+	if (!userdata){
 		/* FIXME: check for errors and initialize? DB */
 		userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
-		ASSERT(userdata != NULL, return;);
+		if (userdata == NULL)
+			return;
 
 		skb_reserve(userdata,COMM_HEADER_SIZE);
 	}
@@ -1188,9 +1191,10 @@
 	/* enable null-modem emulation (i.e. server mode )*/
 	self->null_modem_mode = 1;
 
-	self->maxsdusize = maxsdusize;
-	if(maxsdusize != SAR_DISABLE)
-		self->max_txbuff_size = maxsdusize;
+	self->max_sdu_size = max_sdu_size;
+	if (max_sdu_size != SAR_DISABLE)
+		self->max_txbuff_size = max_sdu_size;
+
 	ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
 }	
 
@@ -1341,14 +1345,13 @@
 	self->control_ch_pending = 1;
 }
 
-
-
 /*
- * ircomm_control_request();
- * this function is exported as a request to send some control-channel tuples
- * to peer device
+ * Function ircomm_control_request (self, instruction)
+ *
+ *    This function is exported as a request to send some control-channel
+ *    tuples * to peer device
+ * 
  */
-
 void ircomm_control_request(struct ircomm_cb *self,  __u8 instruction)
 {
 
diff -urN linux-2.2.10-pre1/net/irda/ircomm/irvtd_driver.c linux-2.2.10-pre2/net/irda/ircomm/irvtd_driver.c
--- linux-2.2.10-pre1/net/irda/ircomm/irvtd_driver.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/ircomm/irvtd_driver.c	2003-08-15 15:06:23.000000000 -0700
@@ -8,7 +8,7 @@
  * Source:        serial.c by Linus Torvalds
  *                isdn_tty.c by Fritz Elfert
  *
- *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
  *     All Rights Reserved.
  *
  *     This program is free software; you can redistribute it and/or
@@ -341,15 +341,15 @@
  ***********************************************************************
  */
 
-
 /*
  * Function irvtd_connect_confirm (instance, sap, qos, max_sdu_size, skb)
  *
- *    ircomm_connect_request which we have send have succeed!
+ *    ircomm_connect_request which we have send, has succeeded!
  *
  */
 void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos,
-			   __u32 max_sdu_size, struct sk_buff *skb)
+			   __u32 max_sdu_size, __u8 max_header_size, 
+			   struct sk_buff *skb)
 {
 	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
 	ASSERT(driver != NULL, return;);
@@ -364,7 +364,7 @@
 	/*
 	 * sending initial control parameters here
 	 */
-	if(driver->comm->servicetype ==	THREE_WIRE_RAW)
+	if (driver->comm->servicetype ==	THREE_WIRE_RAW)
 		return;                /* do nothing */
 
 	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
@@ -376,7 +376,7 @@
 	ircomm_control_request(driver->comm, XON_XOFF_CHAR);
 	/* ircomm_control_request(driver->comm, ENQ_ACK_CHAR); */
 
-	switch(driver->comm->servicetype){
+	switch (driver->comm->servicetype) {
 	case CENTRONICS:
 		break;
 
@@ -397,17 +397,18 @@
  *
  */
 void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos,
-			      __u32 max_sdu_size, struct sk_buff *skb)
+			      __u32 max_sdu_size, __u8 max_header_size, 
+			      struct sk_buff *skb)
 {
-
 	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
 	struct ircomm_cb *comm = (struct ircomm_cb *)sap;
+
 	ASSERT(driver != NULL, return;);
 	ASSERT(driver->magic == IRVTD_MAGIC, return;);
 	ASSERT(comm != NULL, return;);
 	ASSERT(comm->magic == IRCOMM_MAGIC, return;);
 
-	DEBUG(4,"irvtd_connect_indication:sending connect_response...\n");
+	DEBUG(4, __FUNCTION__ "():sending connect_response...\n");
 
 	ircomm_connect_response(comm, NULL, SAR_DISABLE );
 
@@ -416,7 +417,7 @@
 	/*
 	 * send initial control parameters
 	 */
-	if(driver->comm->servicetype ==	THREE_WIRE_RAW)
+	if (driver->comm->servicetype == THREE_WIRE_RAW)
 		return;                /* do nothing */
 
 	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
@@ -426,6 +427,7 @@
 		ircomm_control_request(driver->comm, DTELINE_STATE);
 		break;
 	default:
+		DEBUG(0, __FUNCTION__ "(), not implemented!\n");
 	}
 
 
@@ -576,6 +578,7 @@
 	case DATA_RATE:
 	case XON_XOFF_CHAR:
 	case DTELINE_STATE:
+	case ENQ_ACK_CHAR:	/* got this from win95 */
 		/* (maybe) nothing to do  */
 		break;
 	default:
@@ -778,7 +781,7 @@
 	skb_queue_head_init(&driver->rxbuff);
 	driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); 
 	if (!driver->txbuff){
-		DEBUG(0,__FUNCTION__"():alloc_skb failed!\n");
+		DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n");
 		return -ENOMEM;
 	}
 	skb_reserve(driver->txbuff, COMM_HEADER_SIZE);
@@ -793,9 +796,8 @@
 	irvtd_notify.instance = driver;
 
 	driver->comm = ircomm_open_instance(irvtd_notify);
-	if(!driver->comm){
+	if (!driver->comm)
 		return -ENODEV;
-	}
 
 
 	/* 
diff -urN linux-2.2.10-pre1/net/irda/irda_device.c linux-2.2.10-pre2/net/irda/irda_device.c
--- linux-2.2.10-pre1/net/irda/irda_device.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irda_device.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Wed Apr 21 09:48:19 1999
+ * Modified at:   Mon May 10 23:02:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -31,6 +31,8 @@
 #include <linux/netdevice.h>
 #include <linux/init.h>
 #include <linux/tty.h>
+#include <linux/kmod.h>
+#include <linux/wireless.h>
 
 #include <asm/ioctls.h>
 #include <asm/segment.h>
@@ -53,7 +55,8 @@
 extern int actisys_init(void);
 extern int girbil_init(void);
 
-hashbin_t *irda_device = NULL;
+static hashbin_t *irda_device = NULL;
+static hashbin_t *dongles = NULL;
 
 /* Netdevice functions */
 static int irda_device_net_rebuild_header(struct sk_buff *skb);
@@ -61,9 +64,9 @@
 				       struct device *dev,
 				       unsigned short type, void *daddr, 
 				       void *saddr, unsigned len);
-static int irda_device_net_set_config( struct device *dev, struct ifmap *map);
-static int irda_device_net_change_mtu( struct device *dev, int new_mtu);
-
+static int irda_device_net_set_config(struct device *dev, struct ifmap *map);
+static int irda_device_net_change_mtu(struct device *dev, int new_mtu);
+static int irda_device_net_ioctl(struct device *dev, struct ifreq *rq,int cmd);
 #ifdef CONFIG_PROC_FS
 int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
 			   int unused);
@@ -74,8 +77,15 @@
 {
 	/* Allocate master array */
 	irda_device = hashbin_new( HB_LOCAL);
-	if ( irda_device == NULL) {
-		printk( KERN_WARNING "IrDA: Can't allocate irda_device hashbin!\n");
+	if (irda_device == NULL) {
+		WARNING("IrDA: Can't allocate irda_device hashbin!\n");
+		return -ENOMEM;
+	}
+
+	dongles = hashbin_new(HB_LOCAL);
+	if (dongles == NULL) {
+		printk(KERN_WARNING 
+		       "IrDA: Can't allocate dongles hashbin!\n");
 		return -ENOMEM;
 	}
 
@@ -113,6 +123,7 @@
 
 	ASSERT(irda_device != NULL, return;);
 
+	hashbin_delete(dongles, NULL);
 	hashbin_delete(irda_device, (FREE_FUNC) irda_device_close);
 }
 
@@ -238,7 +249,7 @@
 /*
  * Function irda_device_close (self)
  *
- *    
+ *    Close the device
  *
  */
 void irda_device_close(struct irda_device *self)
@@ -248,6 +259,10 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
 
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		self->dongle->close(self);
+
 	/* Stop and remove instance of IrLAP */
 	if (self->irlap)
 		irlap_close(self->irlap);
@@ -298,15 +313,19 @@
 	 */
 	if (self->wait_until_sent) {
 		self->wait_until_sent(self);
+		
+		if (self->dongle)
+			self->dongle->change_speed(self, speed);
+		
 		if (self->change_speed) {
 			self->change_speed(self, speed);
-
+			
 			/* Update the QoS value only */
 			self->qos.baud_rate.value = speed;
 		}
 	} else {
-		printk(KERN_WARNING "wait_until_sent() "
-		       "has not implemented by the IrDA device driver!\n");
+		WARNING("IrDA: wait_until_sent() "
+			"has not implemented by the IrDA device driver!\n");
 	}
 }
 
@@ -386,6 +405,7 @@
 	dev->set_config      = irda_device_net_set_config;
 	dev->change_mtu      = irda_device_net_change_mtu;
 /*  	dev->hard_header     = irda_device_net_hard_header; */
+	dev->do_ioctl        = irda_device_net_ioctl;
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
@@ -444,6 +464,125 @@
      return 0;  
 }
 
+static int irda_device_net_ioctl(struct device *dev, /* ioctl device */
+				 struct ifreq *rq,   /* Data passed */
+				 int	cmd)	     /* Ioctl number */
+{
+	unsigned long flags;
+	int			ret = 0;
+#ifdef WIRELESS_EXT
+	struct iwreq *wrq = (struct iwreq *) rq;
+#endif
+	struct irda_device *self;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = (struct irda_device *) dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	DEBUG(0, "%s: ->irda_device_net_ioctl(cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	/* Look what is the request */
+	switch (cmd) {
+#ifdef WIRELESS_EXT
+	case SIOCGIWNAME:
+		/* Get name */
+		strcpy(wrq->u.name, self->name);
+		break;
+	case SIOCSIWNWID:
+		/* Set domain */
+		if (wrq->u.nwid.on) {
+			
+		} break;
+	case SIOCGIWNWID:
+		/* Read domain*/
+/* 		wrq->u.nwid.nwid = domain; */
+/* 		wrq->u.nwid.on = 1; */
+		break;
+	case SIOCGIWENCODE:
+		/* Get scramble key */
+		/* 	wrq->u.encoding.code = scramble_key; */
+/* 		wrq->u.encoding.method = 1; */
+		break;
+	case SIOCSIWENCODE:
+		/* Set  scramble key */
+		/* scramble_key = wrq->u.encoding.code; */
+		break;
+	case SIOCGIWRANGE:
+		/* Basic checking... */
+		if(wrq->u.data.pointer != (caddr_t) 0) {
+			struct iw_range	range;
+			
+			/* Verify the user buffer */
+			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
+					  sizeof(struct iw_range));
+			if(ret)
+				break;
+			
+			/* Set the length (useless : its constant...) */
+			wrq->u.data.length = sizeof(struct iw_range);
+			
+			/* Set information in the range struct */
+			range.throughput = 1.6 * 1024 * 1024;	/* don't argue on this ! */
+			range.min_nwid = 0x0000;
+			range.max_nwid = 0x01FF;
+			
+			range.num_channels = range.num_frequency = 0;
+			
+			range.sensitivity = 0x3F;
+			range.max_qual.qual = 255;
+			range.max_qual.level = 255;
+			range.max_qual.noise = 0;
+			
+			/* Copy structure to the user buffer */
+			copy_to_user(wrq->u.data.pointer, &range,
+				     sizeof(struct iw_range));
+		}
+		break;
+	case SIOCGIWPRIV:
+		/* Basic checking... */
+#if 0
+		if (wrq->u.data.pointer != (caddr_t) 0) {
+			struct iw_priv_args	priv[] =
+			{	/* cmd,		set_args,	get_args,	name */
+				{ SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0, 
+				  sizeof(struct site_survey), 
+				  "getsitesurvey" },
+			};
+			
+			/* Verify the user buffer */
+			ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
+					  sizeof(priv));
+			if (ret)
+				break;
+			
+			/* Set the number of ioctl available */
+			wrq->u.data.length = 1;
+			
+			/* Copy structure to the user buffer */
+			copy_to_user(wrq->u.data.pointer, (u_char *) priv,
+				     sizeof(priv));
+		}
+#endif 
+		break;
+#endif
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
+
 /*
  * Function irda_device_transmit_finished (void)
  *
@@ -451,7 +590,7 @@
  *    device. Maybe we should use: q->q.qlen == 0.
  *
  */
-int irda_device_txqueue_empty( struct irda_device *self)
+int irda_device_txqueue_empty(struct irda_device *self)
 {
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);	
@@ -463,6 +602,117 @@
 }
 
 /*
+ * Function irda_device_init_dongle (self, type)
+ *
+ *    Initialize attached dongle. Warning, must be called with a process
+ *    context!
+ */
+void irda_device_init_dongle(struct irda_device *self, int type)
+{
+	struct dongle_q *node;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
+
+#ifdef CONFIG_KMOD
+	/* Try to load the module needed */
+	switch (type) {
+	case ESI_DONGLE:
+		MESSAGE("IrDA: Initializing ESI dongle!\n");
+		request_module("esi");
+		break;
+	case TEKRAM_DONGLE:
+		MESSAGE("IrDA: Initializing Tekram dongle!\n");
+		request_module("tekram");
+		break;
+	case ACTISYS_DONGLE:     /* FALLTHROUGH */
+	case ACTISYS_PLUS_DONGLE:
+		MESSAGE("IrDA: Initializing ACTiSYS dongle!\n");
+		request_module("actisys");
+		break;
+	case GIRBIL_DONGLE:
+		MESSAGE("IrDA: Initializing GIrBIL dongle!\n");
+		request_module("girbil");
+		break;
+	case LITELINK_DONGLE:
+		MESSAGE("IrDA: Initializing Litelink dongle!\n");
+		request_module("litelink");
+		break;
+	default:
+		ERROR("Unknown dongle type!\n");
+		return;
+	}
+#endif /* CONFIG_KMOD */
+
+	node = hashbin_find(dongles, type, NULL);
+	if (!node) {
+		ERROR("IrDA: Unable to find requested dongle\n");
+		return;
+	}
+
+	/* Set the dongle to be used by this driver */
+	self->dongle = node->dongle;
+
+	/* Now initialize the dongle!  */
+	node->dongle->open(self, type);
+	node->dongle->qos_init(self, &self->qos);
+	
+	/* Reset dongle */
+	node->dongle->reset(self, 0);
+
+	/* Set to default baudrate */
+	irda_device_change_speed(self, 9600);
+}
+
+/*
+ * Function irda_device_register_dongle (dongle)
+ *
+ *    
+ *
+ */
+int irda_device_register_dongle(struct dongle *dongle)
+{
+	struct dongle_q *new;
+	
+	/* Check if this dongle has been registred before */
+	if (hashbin_find(dongles, dongle->type, NULL)) {
+		MESSAGE(__FUNCTION__ "(), Dongle already registered\n");
+                return 0;
+        }
+	
+	/* Make new IrDA dongle */
+        new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
+        if (new == NULL)
+                return -1;
+		
+	memset(new, 0, sizeof( struct dongle_q));
+        new->dongle = dongle;
+
+	/* Insert IrDA dongle into hashbin */
+	hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL);
+	
+        return 0;
+}
+
+/*
+ * Function irda_device_unregister_dongle (dongle)
+ *
+ *    
+ *
+ */
+void irda_device_unregister_dongle(struct dongle *dongle)
+{
+	struct dongle_q *node;
+
+	node = hashbin_remove(dongles, dongle->type, NULL);
+	if (!node) {
+		ERROR(__FUNCTION__ "(), dongle not found!\n");
+		return;
+	}
+	kfree(node);
+}
+
+/*
  * Function setup_dma (idev, buffer, count, mode)
  *
  *    Setup the DMA channel
@@ -536,7 +786,7 @@
 
 	self = (struct irda_device *) hashbin_get_first(irda_device);
 	while ( self != NULL) {
-		len += sprintf(buf+len, "%s,", self->name);
+		len += sprintf(buf+len, "\n%s,", self->name);
 		len += sprintf(buf+len, "\tbinding: %s\n", 
 			       self->description);
 		
diff -urN linux-2.2.10-pre1/net/irda/iriap.c linux-2.2.10-pre2/net/irda/iriap.c
--- linux-2.2.10-pre1/net/irda/iriap.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/iriap.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Fri Apr 23 09:57:12 1999
+ * Modified at:   Sun May  9 15:59:05 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -62,12 +62,17 @@
 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_close(struct iriap_cb *self);
 static void iriap_disconnect_indication(void *instance, void *sap, 
 					LM_REASON reason, struct sk_buff *skb);
 static void iriap_connect_indication(void *instance, void *sap, 
 				     struct qos_info *qos, __u32 max_sdu_size,
+				     __u8 max_header_size, 
 				     struct sk_buff *skb);
+static void iriap_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos, 
+				  __u32 max_sdu_size, __u8 max_header_size,
+				  struct sk_buff *skb);
 static int iriap_data_indication(void *instance, void *sap, 
 				 struct sk_buff *skb);
 
@@ -181,7 +186,7 @@
 	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);
 	
@@ -206,7 +211,7 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
-	del_timer( &self->watchdog_timer);
+	del_timer(&self->watchdog_timer);
 
 	self->magic = 0;
 
@@ -260,7 +265,7 @@
 
 	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");
@@ -284,9 +289,8 @@
 				       NULL);
 	}
 
-	if ( userdata) {
+	if (userdata)
 		dev_kfree_skb( userdata);
-	}
 }
 
 /*
@@ -295,28 +299,28 @@
  *    
  *
  */
-void iriap_disconnect_request( struct iriap_cb *self)
+void iriap_disconnect_request(struct iriap_cb *self)
 {
 	struct sk_buff *skb;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	skb = dev_alloc_skb( 64);
+	skb = dev_alloc_skb(64);
 	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__
-		       "(), 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;
 	}
 
 	/* 
-	 *  Reserve space for MUX and LAP header 
+	 *  Reserve space for MUX control and LAP header 
 	 */
- 	skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+ 	skb_reserve(skb, LMP_MAX_HEADER);
 
-	irlmp_disconnect_request( self->lsap, skb);
+	irlmp_disconnect_request(self->lsap, skb);
 }
 
 void iriap_getinfobasedetails_request(void) 
@@ -381,7 +385,7 @@
 	/* Give ourselves 10 secs to finish this operation */
 	iriap_start_watchdog_timer(self, 10*HZ);
 	
-	skb = dev_alloc_skb( 64);
+	skb = dev_alloc_skb(64);
 	if (!skb)
 		return;
 
@@ -389,7 +393,7 @@
 	attr_len = strlen(attr);
 
 	/* Reserve space for MUX and LAP header */
- 	skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+ 	skb_reserve(skb, self->max_header_size);
 	skb_put(skb, 3+name_len+attr_len);
 	frame = skb->data;
 
@@ -535,13 +539,13 @@
 	 *  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(value->len + LMP_HEADER + LAP_HEADER + 9);
+	skb = dev_alloc_skb(value->len + self->max_header_size + 9);
 	if (!skb)
 		return;
 
 	/* Reserve space for MUX and LAP header */
- 	skb_reserve( skb, LMP_HEADER+LAP_HEADER);
-	skb_put( skb, 6);
+ 	skb_reserve(skb, self->max_header_size);
+	skb_put(skb, 6);
 	
 	fp = skb->data;
 
@@ -666,7 +670,7 @@
 /*
  * Function iriap_send_ack (void)
  *
- *    
+ *    Currently not used
  *
  */
 void iriap_send_ack( struct iriap_cb *self) 
@@ -679,13 +683,13 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IAS_MAGIC, return;);
 
-	skb = dev_alloc_skb( 64);
+	skb = dev_alloc_skb(64);
 	if (!skb)
 		return;
 
 	/* Reserve space for MUX and LAP header */
- 	skb_reserve( skb, 4);
-	skb_put( skb, 3);
+ 	skb_reserve(skb, self->max_header_size);
+	skb_put(skb, 1);
 	frame = skb->data;
 
 	/* Build frame */
@@ -698,8 +702,10 @@
  *    LSAP connection confirmed!
  *
  */
-void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
-			   __u32 max_sdu_size, struct sk_buff *userdata)
+static void iriap_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos, 
+				  __u32 max_sdu_size, __u8 header_size, 
+				  struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
 	
@@ -711,7 +717,7 @@
 	
 	DEBUG(4, __FUNCTION__ "()\n");
 	
-	/* del_timer( &self->watchdog_timer); */
+	del_timer(&self->watchdog_timer);
 
 	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
 }
@@ -724,19 +730,17 @@
  */
 static void iriap_connect_indication(void *instance, void *sap, 
 				     struct qos_info *qos, __u32 max_sdu_size,
+				     __u8 header_size, 
 				     struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = ( struct iriap_cb *) instance;
+	self = (struct iriap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( self->mode == IAS_SERVER, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	iriap_do_server_event( self, IAP_LM_CONNECT_INDICATION, userdata);
+	iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata);
 }
  
 /*
@@ -856,7 +860,7 @@
 	}
 	opcode &= 0x7f; /* Mask away LST bit */
 	
-	switch( opcode) {
+	switch (opcode) {
 	case GET_INFO_BASE:
 		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
 		break;
diff -urN linux-2.2.10-pre1/net/irda/iriap_event.c linux-2.2.10-pre2/net/irda/iriap_event.c
--- linux-2.2.10-pre1/net/irda/iriap_event.c	1999-03-07 15:26:44.000000000 -0800
+++ linux-2.2.10-pre2/net/irda/iriap_event.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Tue Jan 26 12:29:36 1999
+ * Modified at:   Sun May  9 11:01:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 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 
@@ -387,9 +387,9 @@
 		}
 
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve( tx_skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(tx_skb, LMP_MAX_HEADER);
 		
-		irlmp_connect_response( self->lsap, tx_skb);
+		irlmp_connect_response(self->lsap, tx_skb);
 		/*LM_Idle_request(idle); */
 		
 		iriap_next_server_state( self, R_CALL);
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_client.c linux-2.2.10-pre2/net/irda/irlan/irlan_client.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_client.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_client.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,13 +6,14 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 23:03:55 1999
+ * Modified at:   Tue May 11 00:22:39 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.
+ *     Copyright (c) 1998-1999 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 
@@ -61,6 +62,7 @@
 static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
 					      struct qos_info *qos, 
 					      __u32 max_sdu_size,
+					      __u8 max_header_size,
 					      struct sk_buff *);
 static void irlan_check_response_param(struct irlan_cb *self, char *param, 
 				       char *value, int val_len);
@@ -79,7 +81,7 @@
 	 * 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) && 
+	if ((self->provider.access_type == ACCESS_PEER) && 
 	    (self->client.state == IRLAN_IDLE) &&
 	    (self->provider.state != IRLAN_IDLE)) {
 		irlan_client_wakeup(self, self->saddr, self->daddr);
@@ -105,23 +107,29 @@
 {
 	struct irmanager_event mgr_event;
 
-	DEBUG(0, __FUNCTION__ "()\n");
+	DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-	/* Check if we are already awake */
-	if (self->client.state != IRLAN_IDLE)
+	/* 
+	 * Check if we are already awake, or if we are a provider in direct
+	 * mode (in that case we must leave the client idle
+	 */
+	if ((self->client.state != IRLAN_IDLE) || 
+	    (self->provider.access_type == ACCESS_DIRECT))
 		return;
 
 	/* saddr may have changed! */
 	self->saddr = saddr;
 	
-	/* Check if network device is up */
+	/* Before we try to connect, we check if network device is up. If it
+	 * is up, that means that the "user" really wants to connect. If not
+	 * we notify the user about the possibility of an IrLAN connection
+	 */
 	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);
@@ -161,7 +169,7 @@
 	struct irlan_cb *self, *entry;
 	__u32 saddr, daddr;
 	
-	DEBUG(0, __FUNCTION__"()\n");
+	DEBUG(1, __FUNCTION__"()\n");
 
 	ASSERT(irlan != NULL, return;);
 	ASSERT(discovery != NULL, return;);
@@ -176,7 +184,8 @@
       	if (self) {
 		ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-		DEBUG(2, __FUNCTION__ "(), Found instance!\n");
+		DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n",
+		      daddr);
 		
 		irlan_client_wakeup(self, saddr, daddr);
 
@@ -184,30 +193,13 @@
 	}
 	
 	/* 
-	 * We have no instance for daddr, so try and find an unused one
+	 * We have no instance for daddr, so start a new one
 	 */
-	self = hashbin_find(irlan, DEV_ADDR_ANY, NULL);
-	if (self) {
-		DEBUG(0, __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(1, __FUNCTION__ "(), starting new instance!\n");
+	self = irlan_open(saddr, daddr, TRUE);
 
-		DEBUG(0, __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);
-		
-		/* Restart watchdog timer */
-		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
-	}
+	/* Restart watchdog timer */
+	irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
 }
 	
 /*
@@ -302,6 +294,7 @@
 static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
 					      struct qos_info *qos, 
 					      __u32 max_sdu_size,
+					      __u8 max_header_size,
 					      struct sk_buff *skb) 
 {
 	struct irlan_cb *self;
@@ -313,6 +306,9 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
+	self->client.max_sdu_size = max_sdu_size;
+	self->client.max_header_size = max_header_size;
+
 	/* TODO: we could set the MTU depending on the max_sdu_size */
 
 	irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
@@ -339,7 +335,7 @@
 		return;
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -410,11 +406,11 @@
 	/* For all parameters */
  	for (i=0; i<count;i++) {
 		ret = irlan_extract_param(ptr, name, value, &val_len);
-		if (ret == -1) {
+		if (ret < 0) {
 			DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
 			break;
 		}
-		ptr+=ret;
+		ptr += ret;
 		irlan_check_response_param(self, name, value, val_len);
  	}
 	/* Cleanup */
@@ -423,9 +419,9 @@
 }
 
 /*
- * Function check_param (param, value)
+ * Function irlan_check_response_param (self, param, value, val_len)
  *
- *    Check which parameter is received and update local variables
+ *     Check which parameter is received and update local variables
  *
  */
 static void irlan_check_response_param(struct irlan_cb *self, char *param, 
@@ -469,11 +465,11 @@
 	}
 	if (strcmp(param, "ACCESS_TYPE") == 0) {
 		if (strcmp(value, "DIRECT") == 0)
-			self->access_type = ACCESS_DIRECT;
+			self->client.access_type = ACCESS_DIRECT;
 		else if (strcmp(value, "PEER") == 0)
-			self->access_type = ACCESS_PEER;
+			self->client.access_type = ACCESS_PEER;
 		else if (strcmp(value, "HOSTED") == 0)
-			self->access_type = ACCESS_HOSTED;
+			self->client.access_type = ACCESS_HOSTED;
 		else {
 			DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
 		}
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_client_event.c linux-2.2.10-pre2/net/irda/irlan/irlan_client_event.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_client_event.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_client_event.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 12:23:22 1999
+ * Modified at:   Thu May  6 13:42:38 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -97,7 +97,7 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 	
-	switch(event) {
+	switch (event) {
 	case IRLAN_DISCOVERY_INDICATION:
 		/* Get some values from peer IAS */
 		iriap_getvaluebyclass_request(
@@ -152,7 +152,7 @@
 		irlan_next_client_state(self, IRLAN_IDLE);
 
 		/* Give the client a kick! */
-		if ((self->access_type == ACCESS_PEER) && 
+		if ((self->provider.access_type == ACCESS_PEER) && 
 		    (self->provider.state != IRLAN_IDLE))
 			irlan_client_wakeup(self, self->saddr, self->daddr);
 		break;
@@ -222,7 +222,7 @@
 
 	ASSERT(self != NULL, return -1;);
 	
-	switch(event) {
+	switch (event) {
 	case IRLAN_DATA_INDICATION:
 		ASSERT(skb != NULL, return -1;);
 	
@@ -314,7 +314,7 @@
 	  	ASSERT(self->dtsap_sel_data != 0, return -1;);
 
 		/* Check which access type we are dealing with */
-		switch(self->access_type) {
+		switch (self->client.access_type) {
 		case ACCESS_PEER:
 		    if (self->provider.state == IRLAN_OPEN) {
 			    
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_common.c linux-2.2.10-pre2/net/irda/irlan/irlan_common.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_common.c	1999-05-06 16:40:53.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_common.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 23:13:47 1999
+ * Modified at:   Sun May  9 11:48:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 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 
@@ -93,19 +94,25 @@
 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);
+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);
 
 extern struct proc_dir_entry *proc_irda;
-#endif
+#endif /* CONFIG_PROC_FS */
 
+/*
+ * Function irlan_watchdog_timer_expired (data)
+ *
+ *    
+ *
+ */
 void irlan_watchdog_timer_expired(unsigned long data)
 {
 	struct irmanager_event mgr_event;
-	struct irlan_cb *self, *entry;
+	struct irlan_cb *self;
 	
 	DEBUG(0, __FUNCTION__ "()\n");
 
@@ -116,6 +123,7 @@
 
 	/* Check if device still configured */
 	if (self->dev.start) {
+		DEBUG(0, __FUNCTION__ "(), notifying irmanager to stop irlan!\n");
 		mgr_event.event = EVENT_IRLAN_STOP;
 		sprintf(mgr_event.devname, "%s", self->ifname);
 		irmanager_notify(&mgr_event);
@@ -128,22 +136,13 @@
 		 */
 		self->notify_irmanager = FALSE;
 	} else {
-		DEBUG(0, __FUNCTION__ "(), recycling instance!\n");
+		DEBUG(0, __FUNCTION__ "(), closing instance!\n");
 		if (self->netdev_registered) {
 			DEBUG(0, __FUNCTION__ "(), removing netdev!\n");
 			unregister_netdev(&self->dev);
 			self->netdev_registered = FALSE;
 		}
-
-		/* Unbind from daddr */
-		entry = hashbin_remove(irlan, self->daddr, NULL);
-		ASSERT(entry == self, return;);
-
-		self->daddr = DEV_ADDR_ANY;
-		self->saddr = DEV_ADDR_ANY;
-
-		DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
-		hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+		irlan_close(self);
 	}
 }
 
@@ -195,12 +194,12 @@
 	/* Register with IrLMP as a service */
  	skey = irlmp_register_service(hints);
 
-	/* Start the first IrLAN instance */
+	/* Start the master IrLAN instance */
  	new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
 
-	irlan_open_data_tsap(new);
- 	irlan_client_open_ctrl_tsap(new);
+	/* The master will only open its (listen) control TSAP */
 	irlan_provider_open_ctrl_tsap(new);
+	new->master = TRUE;
 
 	/* Do some fast discovery! */
 	irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
@@ -293,7 +292,7 @@
 	self->daddr = daddr;
 
 	/* Provider access can only be PEER, DIRECT, or HOSTED */
-	self->access_type = access;
+	self->provider.access_type = access;
 	self->media = MEDIA_802_3;
 
 	self->notify_irmanager = TRUE;
@@ -359,8 +358,11 @@
 
 	/* Check if device is still configured */
 	if (self->dev.start) {
-		DEBUG(2, __FUNCTION__ 
+		DEBUG(0, __FUNCTION__ 
 		       "(), Device still configured, closing later!\n");
+
+		/* Give it a chance to reconnect */
+		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
 		return;
 	}
 	DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
@@ -371,8 +373,15 @@
         __irlan_close(self);
 }
 
+/*
+ * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb)
+ *
+ *    Here we receive the connect indication for the data channel
+ *
+ */
 void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
-			      __u32 max_sdu_size, struct sk_buff *skb)
+			      __u32 max_sdu_size, __u8 max_header_size, 
+			      struct sk_buff *skb)
 {
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
@@ -386,13 +395,17 @@
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	ASSERT(tsap == self->tsap_data,return;);
 
-	DEBUG(2, "IrLAN, We are now connected!\n");
+	self->max_sdu_size = max_sdu_size;
+	self->max_header_size = max_header_size;
+
+	DEBUG(0, "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) {
+	if (self->provider.access_type == ACCESS_PEER) {
 		/* 
 		 * Data channel is open, so we are now allowed to
 		 * configure the remote filter 
@@ -400,12 +413,13 @@
 		irlan_get_unicast_addr(self);
 		irlan_open_unicast_addr(self);
 	}
-	/* Ready to transfer Ethernet frames */
+	/* Ready to transfer Ethernet frames (at last) */
 	self->dev.tbusy = 0;
 }
 
 void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
-			   __u32 max_sdu_size, struct sk_buff *skb) 
+			   __u32 max_sdu_size, __u8 max_header_size, 
+			   struct sk_buff *skb) 
 {
 	struct irlan_cb *self;
 
@@ -416,6 +430,9 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
+	self->max_sdu_size = max_sdu_size;
+	self->max_header_size = max_header_size;
+
 	/* TODO: we could set the MTU depending on the max_sdu_size */
 
 	DEBUG(2, "IrLAN, We are now connected!\n");
@@ -444,7 +461,7 @@
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
 
-	DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason);
+	DEBUG(0, __FUNCTION__ "(), reason=%d\n", reason);
 	
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
@@ -460,7 +477,7 @@
 
 	switch(reason) {
 	case LM_USER_REQUEST: /* User request */
-		//irlan_close(self);
+		irlan_close(self);
 		break;
 	case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
 		irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
@@ -490,7 +507,7 @@
 	struct notify_t notify;
 	struct tsap_cb *tsap;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
@@ -500,7 +517,7 @@
 		return;
 
 	irda_notify_init(&notify);
-
+	
 	notify.data_indication       = irlan_eth_receive;
 	notify.udata_indication      = irlan_eth_receive;
 	notify.connect_indication    = irlan_connect_indication;
@@ -620,7 +637,7 @@
 		return;
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -651,7 +668,7 @@
 	if (!skb)
 		return;
 
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -683,7 +700,7 @@
 	if (!skb)
 		return;
 
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -719,7 +736,7 @@
 		return;
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -757,7 +774,7 @@
 		return;
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -796,7 +813,7 @@
 		return;
 	
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -836,7 +853,7 @@
 		return;
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -871,7 +888,7 @@
 		return;
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->client.max_header_size);
 	skb_put(skb, 2);
 	
 	frame = skb->data;
@@ -1033,7 +1050,7 @@
 	
 	/* get parameter name */
 	memcpy(name, buf+n, name_len);
-	name[ name_len] = '\0';
+	name[name_len] = '\0';
 	n+=name_len;
 	
 	/*  
@@ -1051,7 +1068,7 @@
 
 	/* get parameter value */
 	memcpy(value, buf+n, val_len);
-	value[ val_len] = '\0';
+	value[val_len] = '\0';
 	n+=val_len;
 	
 	DEBUG(4, "Parameter: %s ", name); 
@@ -1085,31 +1102,35 @@
 	while (self != NULL) {
 		ASSERT(self->magic == IRLAN_MAGIC, return len;);
 		
-		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");
-
-		len += sprintf(buf+len, "\n");
+		/* Don't display the master server */
+		if (self->master == 0) {
+			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->client.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");
+			
+			len += sprintf(buf+len, "\n");
+		}
 
 		self = (struct irlan_cb *) hashbin_get_next(irlan);
  	} 
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_eth.c linux-2.2.10-pre2/net/irda/irlan/irlan_eth.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_eth.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_eth.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,13 +6,13 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Thu Apr 22 14:26:39 1999
+ * Modified at:   Mon May 10 20:23:49 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, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -29,6 +29,7 @@
 #include <linux/etherdevice.h>
 #include <linux/inetdevice.h>
 #include <linux/if_arp.h>
+#include <linux/random.h>
 #include <net/arp.h>
 
 #include <net/irda/irda.h>
@@ -67,19 +68,19 @@
 	
 	dev->tx_queue_len = TTP_MAX_QUEUE;
 
-#if 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
+	if (self->provider.access_type == ACCESS_DIRECT) {
+		/*  
+		 * Since we are emulating an IrLAN sever we will have to
+		 * give ourself an ethernet address!  
+		 */
+		dev->dev_addr[0] = 0x40;
+		dev->dev_addr[1] = 0x00;
+		dev->dev_addr[2] = 0x00;
+		dev->dev_addr[3] = 0x00;
+		get_random_bytes(dev->dev_addr+4, 1);
+		get_random_bytes(dev->dev_addr+5, 1);
+	}
+
 	/* 
 	 * Network device has now been registered, so tell irmanager about
 	 * it, so it can be configured with network parameters
@@ -180,8 +181,6 @@
 {
 	struct irlan_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
-	
 	self = (struct irlan_cb *) dev->priv;
 
 	ASSERT(self != NULL, return 0;);
@@ -202,19 +201,19 @@
  		dev->trans_start = jiffies;
 	}
 	
-	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 all IrDA-headers? */
+	if ((skb_headroom(skb) < self->max_header_size) || (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;);
+			skb_realloc_headroom(skb, self->max_header_size);
 
-		/*  Free original skb, and use the new one */
+		/*  We have to free the original skb anyway */
 		dev_kfree_skb(skb);
+
+		/* Did the realloc succeed? */
+		if (new_skb == NULL)
+			return 0;
+
+		/* Use the new skb instead */
 		skb = new_skb;
 	} 
 
@@ -222,31 +221,26 @@
 	self->stats.tx_packets++;
 	self->stats.tx_bytes += skb->len; 
 
-	/*
-	 *  Now queue the packet in the transport layer
-	 *  FIXME: clean up the code below! DB
-	 */
-	if (self->use_udata) {
+	/* Now queue the packet in the transport layer */
+	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) {
-		/*  
-		 *  IrTTPs tx queue is full, so we just have to drop the
-		 *  frame! You might think that we should just return -1
-		 *  and don't deallocate the frame, but that is dangerous
-		 *  since it's possible that we have replaced the original
-		 *  skb with a new one with larger headroom, and that would
-		 *  really confuse do_dev_queue_xmit() in dev.c! I have
-		 *  tried :-) DB
-		 */
-		dev_kfree_skb(skb);
-		++self->stats.tx_dropped;
+	else {
+		if (irttp_data_request(self->tsap_data, skb) < 0) {
+			/*   
+			 * IrTTPs tx queue is full, so we just have to
+			 * drop the frame! You might think that we should
+			 * just return -1 and don't deallocate the frame,
+			 * but that is dangerous since it's possible that
+			 * we have replaced the original skb with a new
+			 * one with larger headroom, and that would really
+			 * confuse do_dev_queue_xmit() in dev.c! I have
+			 * tried :-) DB 
+			 */
+			dev_kfree_skb(skb);
+			++self->stats.tx_dropped;
 		
-		return 0;
+			return 0;
+		}
 	}
 	dev->tbusy = 0; /* Finished! */
 	
@@ -314,26 +308,16 @@
 	
 	switch (flow) {
 	case FLOW_STOP:
-		DEBUG(4, "IrLAN, stopping Ethernet layer\n");
-
 		dev->tbusy = 1;
 		break;
 	case FLOW_START:
-		/* 
-		 *  Tell upper layers that its time to transmit frames again
-		 */
-		DEBUG(4, "IrLAN, starting Ethernet layer\n");
-
+	default:
+		/* Tell upper layers that its time to transmit frames again */
 		dev->tbusy = 0;
 
-		/* 
-		 *  Ready to receive more frames, so schedule the network
-		 *  layer
-		 */
+		/* Schedule network layer */
 		mark_bh(NET_BH);		
 		break;
-	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n");
 	}
 }
 
@@ -373,7 +357,7 @@
 	in_dev = dev->ip_ptr;
 	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
 		 in_dev->ifa_list->ifa_address,
-		 &dev, 
+		 dev, 
 		 in_dev->ifa_list->ifa_address,
 		 NULL, dev->dev_addr, NULL);
 }
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_event.c linux-2.2.10-pre2/net/irda/irlan/irlan_event.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_event.c	1999-03-07 15:26:44.000000000 -0800
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_event.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Oct 20 09:10:16 1998
- * Modified at:   Wed Feb  3 21:42:27 1999
+ * Modified at:   Sun May  9 21:17:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -38,22 +38,22 @@
 	"IRLAN_SYNC",
 };
 
-void irlan_next_client_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;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	self->client.state = state;
 }
 
-void irlan_next_provider_state( struct irlan_cb *self, IRLAN_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;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLAN_MAGIC, return;);
 
 	self->provider.state = state;
 }
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_filter.c linux-2.2.10-pre2/net/irda/irlan/irlan_filter.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_filter.c	1999-04-15 05:42:42.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_filter.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Jan 29 11:16:38 1999
- * Modified at:   Thu Feb 25 15:10:54 1999
+ * Modified at:   Sat May  8 15:25:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -41,29 +41,29 @@
 	    (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) {
+		if (self->provider.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;
+			get_random_bytes(self->provider.mac_address+4, 1);
+			get_random_bytes(self->provider.mac_address+5, 1);
 		}
 
 		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);
+		irlan_insert_array_param(skb, "FILTER_ENTRY", 
+					 self->provider.mac_address, 6);
 		return;
 	}
 	
@@ -138,8 +138,7 @@
  *    Check parameters in request from peer device
  *
  */
-void irlan_check_command_param(struct irlan_cb *self, char *param, 
-			       char *value)
+void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
 {
 	__u8 *bytes;
 
@@ -210,6 +209,12 @@
 	}
 }
 
+/*
+ * Function irlan_print_filter (filter_type, buf)
+ *
+ *    Print status of filter. Used by /proc file system
+ *
+ */
 int irlan_print_filter(int filter_type, char *buf)
 {
 	int len = 0;
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_provider.c linux-2.2.10-pre2/net/irda/irlan/irlan_provider.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_provider.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_provider.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,13 +6,14 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 14:28:52 1999
+ * Modified at:   Sun May  9 12:22:56 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.
+ *     Copyright (c) 1998-1999 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 
@@ -31,6 +32,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
+#include <linux/random.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -50,14 +52,20 @@
 #include <net/irda/irlan_filter.h>
 #include <net/irda/irlan_client.h>
 
+static void irlan_provider_connect_indication(void *instance, void *sap, 
+					      struct qos_info *qos, 
+					      __u32 max_sdu_size,
+					      __u8 max_header_size,
+					      struct sk_buff *skb);
+
 /*
  * Function irlan_provider_control_data_indication (handle, skb)
  *
  *    This function gets the data that is received on the control channel
  *
  */
-int irlan_provider_data_indication(void *instance, void *sap, 
-				   struct sk_buff *skb) 
+static int irlan_provider_data_indication(void *instance, void *sap, 
+					  struct sk_buff *skb) 
 {
 	struct irlan_cb *self;
 	__u8 code;
@@ -111,14 +119,17 @@
  *    Got connection from peer IrLAN layer
  *
  */
-void irlan_provider_connect_indication(void *instance, void *sap, 
-				       struct qos_info *qos,
-				       __u32 max_sdu_size, struct sk_buff *skb)
+static void irlan_provider_connect_indication(void *instance, void *sap, 
+					      struct qos_info *qos,
+					      __u32 max_sdu_size, 
+					      __u8 max_header_size,
+					       struct sk_buff *skb)
 {
-	struct irlan_cb *self, *entry, *new;
+	struct irlan_cb *self, *new;
 	struct tsap_cb *tsap;
+	__u32 saddr, daddr;
 
-	DEBUG(2, __FUNCTION__ "()\n");
+	DEBUG(0, __FUNCTION__ "()\n");
 	
 	self = (struct irlan_cb *) instance;
 	tsap = (struct tsap_cb *) sap;
@@ -126,34 +137,69 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRLAN_MAGIC, return;);
 	
+	self->provider.max_sdu_size = max_sdu_size;
+	self->provider.max_header_size = max_header_size;
+
 	ASSERT(tsap == self->provider.tsap_ctrl,return;);
 	ASSERT(self->provider.state == IRLAN_IDLE, return;);
 
-	/* Check if this provider is currently 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);
+	daddr = irttp_get_daddr(tsap);
+	saddr = irttp_get_saddr(tsap);
+
+	/* Check if we already dealing with this client or peer */
+	new = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL);
+      	if (new) {
+		ASSERT(new->magic == IRLAN_MAGIC, return;);
+		DEBUG(0, __FUNCTION__ "(), found instance!\n");
+
+		/* Update saddr, since client may have moved to a new link */
+		new->saddr = saddr;
+		DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", new->saddr);
+
+		/* Make sure that any old provider control TSAP is removed */
+		if ((new != self) && new->provider.tsap_ctrl) {
+			irttp_disconnect_request(new->provider.tsap_ctrl, 
+						 NULL, P_NORMAL);
+			irttp_close_tsap(new->provider.tsap_ctrl);
+			new->provider.tsap_ctrl = 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!  
+		/* This must be the master instance, so start a new instance */
+		DEBUG(0, __FUNCTION__ "(), starting new provider!\n");
+
+		new = irlan_open(saddr, daddr, TRUE); 
+	}
+
+	/*  
+	 * Check if the connection came in on the master server, or the
+	 * slave server. If it came on the slave, then everything is
+	 * really, OK (reconnect), if not we need to dup the connection and
+	 * hand it over to the slave.  
+	 */
+	if (new != self) {
+				
+		/* Now attach up the new "socket" */
+		new->provider.tsap_ctrl = irttp_dup(self->provider.tsap_ctrl, 
+						    new);
+		if (!new->provider.tsap_ctrl) {
+			DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+			return;
+		}
+		
+		/* new->stsap_sel = new->tsap->stsap_sel; */
+		new->dtsap_sel_ctrl = new->provider.tsap_ctrl->dtsap_sel;
+
+		/* Clean up the original one to keep it in listen state */
+		self->provider.tsap_ctrl->dtsap_sel = LSAP_ANY;
+		self->provider.tsap_ctrl->lsap->dlsap_sel = LSAP_ANY;
+		self->provider.tsap_ctrl->lsap->lsap_state = LSAP_DISCONNECTED;
+		
+		/* 
+		 * Use the new instance from here instead of the master
+		 * struct! 
 		 */
-		ASSERT(self->daddr == irttp_get_daddr(tsap), return;);
+		self = new;
 	}
-	
-	/* 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);
@@ -165,9 +211,10 @@
 	 * 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))
+	if ((self->provider.access_type == ACCESS_PEER) && 
+	    (self->client.state == IRLAN_IDLE)) {
 		irlan_client_wakeup(self, self->saddr, self->daddr);
+	}
 }
 
 /*
@@ -225,6 +272,9 @@
 	
 	ret = irlan_provider_parse_command(self, CMD_OPEN_DATA_CHANNEL, skb);
 
+	/* Open data channel */
+	irlan_open_data_tsap(self);
+
 	return ret;
 }
 
@@ -314,7 +364,7 @@
 		return;
 
 	/* Reserve space for TTP, LMP, and LAP header */
-	skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+	skb_reserve(skb, self->provider.max_header_size);
 	skb_put(skb, 2);
        
 	switch (command) {
@@ -334,6 +384,7 @@
 		}
 		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 */
@@ -341,7 +392,7 @@
 		irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
 		irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
 
-		switch(self->access_type) {
+		switch (self->provider.access_type) {
 		case ACCESS_DIRECT:
 			irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
 			break;
diff -urN linux-2.2.10-pre1/net/irda/irlan/irlan_provider_event.c linux-2.2.10-pre2/net/irda/irlan/irlan_provider_event.c
--- linux-2.2.10-pre1/net/irda/irlan/irlan_provider_event.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlan/irlan_provider_event.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Apr 22 10:46:28 1999
+ * Modified at:   Fri May  7 10:53:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -108,7 +108,7 @@
 	switch(event) {
 	case IRLAN_GET_INFO_CMD:
 		/* Be sure to use 802.3 in case of peer mode */
-		if (self->access_type == ACCESS_PEER) {
+		if (self->provider.access_type == ACCESS_PEER) {
 			self->media = MEDIA_802_3;
 			
 			/* Check if client has started yet */
@@ -129,7 +129,7 @@
 		break;		
 	case IRLAN_OPEN_DATA_CMD:
 		ret = irlan_parse_open_data_cmd(self, skb);
-		if (self->access_type == ACCESS_PEER) {
+		if (self->provider.access_type == ACCESS_PEER) {
 			/* FIXME: make use of random functions! */
 			self->provider.send_arb_val = (jiffies & 0xffff);
 		}
@@ -205,8 +205,6 @@
 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;);
@@ -220,10 +218,6 @@
 		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:
diff -urN linux-2.2.10-pre1/net/irda/irlap_comp.c linux-2.2.10-pre2/net/irda/irlap_comp.c
--- linux-2.2.10-pre1/net/irda/irlap_comp.c	1999-03-07 15:26:44.000000000 -0800
+++ linux-2.2.10-pre2/net/irda/irlap_comp.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,11 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Oct  9 09:18:07 1998
- * Modified at:   Mon Feb  8 01:23:52 1999
+ * Modified at:   Sun May  9 11:37:06 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       ppp.c, isdn_ppp.c
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -255,11 +255,11 @@
 	}
 
 	/* FIXME: Find out what is the max overhead (not 10) */
-	new_skb = dev_alloc_skb( skb->len+LAP_HEADER+10);
+	new_skb = dev_alloc_skb( skb->len+LAP_MAX_HEADER+10);
 	if(!new_skb)
 		return skb;
 
-	skb_reserve( new_skb, LAP_HEADER);
+	skb_reserve( new_skb, LAP_MAX_HEADER);
 	skb_put( new_skb, skb->len+10);
 	
 	count = (self->compressor.cp->compress)( self->compressor.state, 
diff -urN linux-2.2.10-pre1/net/irda/irlap_event.c linux-2.2.10-pre2/net/irda/irlap_event.c
--- linux-2.2.10-pre1/net/irda/irlap_event.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlap_event.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Fri Apr 23 11:55:12 1999
+ * Modified at:   Sun May  9 22:44:32 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>,
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  *                        Thomas Davis <ratbert@radiks.net>
  *     All Rights Reserved.
  *     
@@ -274,22 +274,22 @@
  *    Switches state and provides debug information
  *
  */
-void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) 
+void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) 
 {	
-	if ( !self || self->magic != LAP_MAGIC)
+	if (!self || self->magic != LAP_MAGIC)
 		return;
 	
-	DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]);
+	DEBUG(4, "next LAP state = %s\n", irlap_state[ state]);
 
 	self->state = state;
 
 	/*
 	 *  If we are swithing away from a XMIT state then we are allowed to 
 	 *  transmit a maximum number of bytes again when we enter the XMIT 
-	 *  state again. Since its possible to "switch" from XMIT to XMIT and
+	 *  state again. Since its possible to "switch" from XMIT to XMIT,
 	 *  we cannot do this when swithing into the XMIT state :-)
 	 */
-	if (( state != LAP_XMIT_P) && ( state != LAP_XMIT_S))
+	if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S))
 		self->bytes_left = self->window_bytes;
 }
 
@@ -310,7 +310,7 @@
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == LAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch(event) {
 	case CONNECT_REQUEST:
 		ASSERT( self->irdev != NULL, return -1;);
 
@@ -393,7 +393,6 @@
 			irlap_start_query_timer( self, QUERY_TIMEOUT);
 			irlap_next_state( self, LAP_REPLY);
 		}
-
 		dev_kfree_skb(skb);
 		break;
 
@@ -530,7 +529,7 @@
 			irlap_send_discovery_xid_frame(self, info->S,
 						       self->slot, FALSE,
 						       discovery_rsp);
-
+			
 			self->frame_sent = TRUE;
 			irlap_next_state(self, LAP_REPLY);
 		}
@@ -568,27 +567,28 @@
 
 	switch (event) {
 	case CONNECT_RESPONSE:
-		skb_pull( skb, 11);
+		/* skb_pull(skb, 11); */
+		skb_pull(skb, sizeof(struct snrm_frame));
 
-		ASSERT( self->irdev != NULL, return -1;);
-		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+		ASSERT(self->irdev != NULL, return -1;);
+		irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
 
 		irlap_initiate_connection_state( self);
 
 		/*
 		 * We are allowed to send two frames!
 		 */
-		irlap_send_ua_response_frame( self, &self->qos_rx);
-		irlap_send_ua_response_frame( self, &self->qos_rx);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
 		
-		irlap_apply_connection_parameters( self, &self->qos_tx);
+		irlap_apply_connection_parameters(self, &self->qos_tx);
 
 		/*
 		 *  The WD-timer could be set to the duration of the P-timer 
-		 *  for this case, but it is recommomended to use twice the 
+		 *  for this case, but it is recommended to use twice the 
 		 *  value (note 3 IrLAP p. 60). 
 		 */
-		irlap_start_wd_timer( self, self->wd_timeout);
+		irlap_start_wd_timer(self, self->wd_timeout);
 		irlap_next_state( self, LAP_NRM_S);
 		break;
 
@@ -669,28 +669,30 @@
 		 *  The device with the largest device address wins the battle
 		 *  (both have sent a SNRM command!)
 		 */
-		if ( info->daddr > self->saddr) {
-			del_timer( &self->final_timer);
-			irlap_initiate_connection_state( self);
+		if (info->daddr > self->saddr) {
+			del_timer(&self->final_timer);
+			irlap_initiate_connection_state(self);
 
-			ASSERT( self->irdev != NULL, return -1;);
-			irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+			ASSERT(self->irdev != NULL, return -1;);
+			/* skb_pull(skb, 11); */
+			skb_pull(skb, sizeof(struct snrm_frame));
+			irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
 			
 			irlap_send_ua_response_frame(self, &self->qos_rx);
-			irlap_apply_connection_parameters( self, &self->qos_tx);
-			irlap_connect_confirm( self, skb);
+			irlap_apply_connection_parameters(self, &self->qos_tx);
+			irlap_connect_confirm(self, skb);
 			
 			/* 
 			 *  The WD-timer could be set to the duration of the
-			 *  P-timer for this case, but it is recommomended
+			 *  P-timer for this case, but it is recommended
 			 *  to use twice the value (note 3 IrLAP p. 60).  
 			 */
-			irlap_start_wd_timer( self, self->wd_timeout);
+			irlap_start_wd_timer(self, self->wd_timeout);
 			
-			irlap_next_state( self, LAP_NRM_S);
+			irlap_next_state(self, LAP_NRM_S);
 		} else {
 			/* We just ignore the other device! */
-			irlap_next_state( self, LAP_SETUP);
+			irlap_next_state(self, LAP_SETUP);
 		}
 		break;
 	case RECV_UA_RSP:
@@ -702,9 +704,10 @@
 
 		/* Negotiate connection parameters */
 		ASSERT( skb->len > 10, return -1;);
-		skb_pull( skb, 10);
+		/* skb_pull(skb, 10); */
+		skb_pull(skb, sizeof(struct ua_frame));
 
-		ASSERT( self->irdev != NULL, return -1;);
+		ASSERT(self->irdev != NULL, return -1;);
 		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
 
 		irlap_apply_connection_parameters( self, &self->qos_tx); 
@@ -1570,7 +1573,7 @@
 			/* 
 			 *  poll bit cleared?
 			 */
-			if ( !info->pf) {
+			if (!info->pf) {
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
@@ -1600,27 +1603,32 @@
 				 *  also before changing to XMIT_S
 				 *  state. (note 1, IrLAP p. 82) 
 				 */
-				irlap_wait_min_turn_around( self, &self->qos_tx);
-				/*
-				 *  Any pending data requests?
+				irlap_wait_min_turn_around(self, &self->qos_tx);
+
+				/*  
+				 * Give higher layers a chance to
+				 * immediately reply with some data before
+				 * we decide if we should send a RR frame
+				 * or not
 				 */
-				if (( skb_queue_len( &self->tx_list) > 0) && 
-				    ( self->window > 0)) 
+				irlap_data_indication(self, skb);
+
+				/* Any pending data requests?  */
+				if ((skb_queue_len(&self->tx_list) > 0) && 
+				    (self->window > 0)) 
 				{
 					self->ack_required = TRUE;
 					
-					del_timer( &self->wd_timer);
+					del_timer(&self->wd_timer);
 					
-					irlap_next_state( self, LAP_XMIT_S);
+					irlap_next_state(self, LAP_XMIT_S);
 				} else {
-					irlap_send_rr_frame( self, RSP_FRAME);
-					irlap_start_wd_timer( self, self->wd_timeout);
+					irlap_send_rr_frame(self, RSP_FRAME);
+					irlap_start_wd_timer(self, self->wd_timeout);
 
 					/* Keep the state */
-					irlap_next_state( self, LAP_NRM_S);
+					irlap_next_state(self, LAP_NRM_S);
 				}
-				irlap_data_indication( self, skb);
-
 				break;
 			}
 		}
diff -urN linux-2.2.10-pre1/net/irda/irlap_frame.c linux-2.2.10-pre2/net/irda/irlap_frame.c
--- linux-2.2.10-pre1/net/irda/irlap_frame.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlap_frame.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Fri Apr 23 09:30:42 1999
+ * Modified at:   Sun May  9 22:55:11 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -1056,8 +1056,8 @@
  *    Receive and parse an Unnumbered Information (UI) frame
  *
  */
-static void irlap_recv_ui_frame( struct irlap_cb *self, struct sk_buff *skb, 
-				 struct irlap_info *info)
+static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				struct irlap_info *info)
 {
 	__u8 *frame;
 
@@ -1254,7 +1254,7 @@
 		 *  Received S(upervisory) frame, check which frame type it is
 		 *  only the first nibble is of interest
 		 */
-		switch(control & 0x0f) {
+		switch (control & 0x0f) {
 		case RR:
 			irlap_recv_rr_frame( self, skb, &info, command);
 			self->stats.rx_packets++;
@@ -1279,7 +1279,7 @@
 	/* 
 	 *  This must be a C(ontrol) frame 
 	 */
-	switch(control) {
+	switch (control) {
 	case XID_RSP:
 		irlap_recv_discovery_xid_rsp(self, skb, &info);
 		break;
diff -urN linux-2.2.10-pre1/net/irda/irlmp.c linux-2.2.10-pre2/net/irda/irlmp.c
--- linux-2.2.10-pre1/net/irda/irlmp.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlmp.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Fri Apr 23 09:13:24 1999
+ * Modified at:   Sun May  9 22:45:06 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -197,7 +197,7 @@
 }
 
 /*
- * Function irlmp_close_lsap (self)
+ * Function __irlmp_close_lsap (self)
  *
  *    Remove an instance of LSAP
  */
@@ -369,11 +369,11 @@
 		if (!skb)
 			return -ENOMEM;
 
-		skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(skb, LMP_MAX_HEADER);
 	} else
 		skb = userdata;
 	
-	/* Make room for MUX control header ( 3 bytes) */
+	/* Make room for MUX control header (3 bytes) */
 	ASSERT(skb_headroom(skb) >= LMP_CONTROL_HEADER, return -1;);
 	skb_push(skb, LMP_CONTROL_HEADER);
 
@@ -443,25 +443,36 @@
 void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
 	int max_seg_size;
-
-	DEBUG(3, __FUNCTION__ "()\n");
+	int lap_header_size;
+	int max_header_size;
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
 	ASSERT(self->lap != NULL, return;);
 
+	DEBUG(0, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	      self->slsap_sel, self->dlsap_sel);
+
 	self->qos = *self->lap->qos;
 
-	max_seg_size = self->lap->qos->data_size.value;
-	DEBUG(4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	lap_header_size = irlap_get_header_size(self->lap->irlap);
+
+	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER-
+		lap_header_size;
+	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
 	
+	max_header_size = LMP_HEADER + lap_header_size;
+
+	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
 
 	if (self->notify.connect_indication)
 		self->notify.connect_indication(self->notify.instance, self, 
-						&self->qos, max_seg_size, skb);
+						&self->qos, max_seg_size, 
+						max_header_size, skb);
 }
 
 /*
@@ -470,24 +481,22 @@
  *    Service user is accepting connection
  *
  */
-void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) 
+void irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) 
 {
-	DEBUG(3, __FUNCTION__ "()\n");
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( userdata != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(userdata != NULL, return;);
 
 	self->connected = TRUE;
 
-	DEBUG( 4, "irlmp_connect_response: slsap_sel=%02x, dlsap_sel=%02x\n", 
-	       self->slsap_sel, self->dlsap_sel);
+	DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	      self->slsap_sel, self->dlsap_sel);
 
 	/* Make room for MUX control header ( 3 bytes) */
-	ASSERT( skb_headroom( userdata) >= LMP_CONTROL_HEADER, return;);
-	skb_push( userdata, LMP_CONTROL_HEADER);
+	ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return;);
+	skb_push(userdata, LMP_CONTROL_HEADER);
 	
-	irlmp_do_lsap_event( self, LM_CONNECT_RESPONSE, userdata);
+	irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata);
 }
 
 /*
@@ -498,25 +507,35 @@
 void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) 
 {
 	int max_seg_size;
+	int max_header_size;
+	int lap_header_size;
 
 	DEBUG(3, __FUNCTION__ "()\n");
 	
-	ASSERT( skb != NULL, return;);
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
 	
-	ASSERT( self->lap != NULL, return;);
+	ASSERT(self->lap != NULL, return;);
 	self->qos = *self->lap->qos;
 
-	max_seg_size = self->qos.data_size.value;
-	DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	lap_header_size = irlap_get_header_size(self->lap->irlap);
+
+	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER-
+		lap_header_size;
+	DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
 	
+	max_header_size = LMP_HEADER + lap_header_size;
+
+	DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+
 	/* Hide LMP_CONTROL_HEADER header from layer above */
-	skb_pull( skb, LMP_CONTROL_HEADER);
+	skb_pull(skb, LMP_CONTROL_HEADER);
 
-	if ( self->notify.connect_confirm) {
-		self->notify.connect_confirm( self->notify.instance, self,
-					      &self->qos, max_seg_size, skb);
+	if (self->notify.connect_confirm) {
+		self->notify.connect_confirm(self->notify.instance, self,
+					     &self->qos, max_seg_size, 
+					     max_header_size, skb);
 	}
 }
 
@@ -620,8 +639,8 @@
  *
  *    LSAP is being closed!
  */
-void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, 
-				  struct sk_buff *userdata) 
+void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, 
+				 struct sk_buff *userdata) 
 {
 	struct lsap_cb *lsap;
 
@@ -637,6 +656,10 @@
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
 
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+	irlmp->cache.valid = FALSE;
+#endif
+
 	/* 
 	 *  Remove association between this LSAP and the link it used 
 	 */
@@ -975,7 +998,7 @@
 	DEBUG( 1, "irlmp_status_request(), Not implemented\n");
 }
 
-void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) 
+void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock) 
 {
 	DEBUG( 4, "irlmp_status_indication(), Not implemented\n");
 }
@@ -1418,14 +1441,14 @@
  *    Give some info to the /proc file system
  *
  */
-int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
-		     int unused)
+int irlmp_proc_read(char *buf, char **start, off_t offset, int len, 
+		    int unused)
 {
 	struct lsap_cb *self;
 	struct lap_cb *lap;
 	unsigned long flags;
 
-	ASSERT( irlmp != NULL, return 0;);
+	ASSERT(irlmp != NULL, return 0;);
 	
 	save_flags( flags);
 	cli();
@@ -1449,35 +1472,34 @@
  	} 
 
 	len += sprintf( buf+len, "\nRegistred Link Layers:\n");
-	lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
-	while ( lap != NULL) {
-		ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;);
 
-		len += sprintf( buf+len, "lap state: %s, ", 
-				irlmp_state[ lap->lap_state]);
+	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
+	while (lap != NULL) {
+		len += sprintf(buf+len, "lap state: %s, ", 
+			       irlmp_state[lap->lap_state]);
 
-		len += sprintf( buf+len, "saddr: %#08x, daddr: %#08x, ",
-				lap->saddr, lap->daddr); 
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
+			       lap->saddr, lap->daddr); 
+		len += sprintf(buf+len, "\n");
 
 		len += sprintf( buf+len, "\nConnected LSAPs:\n");
 		self = (struct lsap_cb *) hashbin_get_first( lap->lsaps);
-		while ( self != NULL) {
-			ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;);
-			len += sprintf( buf+len, "lsap state: %s, ", 
-					irlsap_state[ self->lsap_state]);
-			len += sprintf( buf+len, 
-					"slsap_sel: %#02x, dlsap_sel: %#02x, ",
-					self->slsap_sel, self->dlsap_sel);
-			len += sprintf( buf+len, "(%s)", self->notify.name);
-			len += sprintf( buf+len, "\n");
+		while (self != NULL) {
+			ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
+			len += sprintf(buf+len, "lsap state: %s, ", 
+				       irlsap_state[ self->lsap_state]);
+			len += sprintf(buf+len, 
+				       "slsap_sel: %#02x, dlsap_sel: %#02x, ",
+				       self->slsap_sel, self->dlsap_sel);
+			len += sprintf(buf+len, "(%s)", self->notify.name);
+			len += sprintf(buf+len, "\n");
 			
-			self = ( struct lsap_cb *) hashbin_get_next( 
+			self = (struct lsap_cb *) hashbin_get_next( 
 				lap->lsaps);
 		} 
+		len += sprintf(buf+len, "\n");
 
-		lap = ( struct lap_cb *) hashbin_get_next( 
-			irlmp->links);
+		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
  	} 
 
 	restore_flags( flags);
diff -urN linux-2.2.10-pre1/net/irda/irlmp_frame.c linux-2.2.10-pre2/net/irda/irlmp_frame.c
--- linux-2.2.10-pre1/net/irda/irlmp_frame.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlmp_frame.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,15 +1,15 @@
 /*********************************************************************
  *                
  * Filename:      irlmp_frame.c
- * Version:       0.8
+ * Version:       0.9
  * Description:   IrLMP frame implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Fri Apr 23 09:12:23 1999
+ * Modified at:   Sun May  9 21:00:05 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -59,16 +59,16 @@
  *
  *    Send Link Control Frame to IrLAP
  */
-void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap,
-			 __u8 opcode, struct sk_buff *skb) 
+void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
+			__u8 opcode, struct sk_buff *skb) 
 {
 	__u8 *frame;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 	
 	frame = skb->data;
 	
@@ -82,8 +82,8 @@
 	else
 		frame[3] = 0x00; /* rsvd */
 
-	ASSERT( self->irlap != NULL, return;);
-	irlap_data_request( self->irlap, skb, TRUE);
+	ASSERT(self->irlap != NULL, return;);
+	irlap_data_request(self->irlap, skb, TRUE);
 }
 
 /*
@@ -112,7 +112,7 @@
 	 */
 	slsap_sel = fp[0] & LSAP_MASK; 
 	dlsap_sel = fp[1];
-	
+
 	/*
 	 *  Check if this is an incoming connection, since we must deal with
 	 *  it in a different way than other established connections.
@@ -224,11 +224,11 @@
  *    Incoming LAP connection!
  *
  */
-void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, 
-				    __u32 daddr, struct qos_info *qos,
-				    struct sk_buff *skb) 
+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");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Copy QoS settings for this session */
 	self->qos = qos;
@@ -237,7 +237,7 @@
 	self->daddr = daddr;
 	ASSERT(self->saddr == saddr, return;);
 
-	irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb);
+	irlmp_do_lap_event(self, LM_LAP_CONNECT_INDICATION, skb);
 }
 
 /*
@@ -246,19 +246,19 @@
  *    LAP connection confirmed!
  *
  */
-void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, 
-				 struct sk_buff *userdata)
+void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, 
+				struct sk_buff *userdata)
 {
-	DEBUG( 4, "irlmp_link_connect_confirm()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
-	ASSERT( qos != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(qos != NULL, return;);
 
 	/* Copy QoS settings for this session */
 	self->qos = qos;
 
-	irlmp_do_lap_event( self, LM_LAP_CONNECT_CONFIRM, NULL);
+	irlmp_do_lap_event(self, LM_LAP_CONNECT_CONFIRM, NULL);
 }
 
 /*
@@ -276,7 +276,9 @@
 	irlmp_add_discovery(irlmp->cachelog, discovery);
 
 	/* Just handle it the same way as a discovery confirm */
+#if 0
 	irlmp_do_lap_event(self, LM_LAP_DISCOVERY_CONFIRM, NULL);
+#endif
 }
 
 /*
@@ -365,7 +367,7 @@
 #endif
 			return lsap;
 		}
-		lsap = ( struct lsap_cb *) hashbin_get_next(queue);
+		lsap = (struct lsap_cb *) hashbin_get_next(queue);
 	}
 
 	/* Sorry not found! */
diff -urN linux-2.2.10-pre1/net/irda/irlpt/irlpt_cli.c linux-2.2.10-pre2/net/irda/irlpt/irlpt_cli.c
--- linux-2.2.10-pre1/net/irda/irlpt/irlpt_cli.c	1999-05-06 16:40:53.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlpt/irlpt_cli.c	2003-08-15 15:06:23.000000000 -0700
@@ -51,10 +51,11 @@
 static void irlpt_client_connect_confirm(void *instance, void *sap, 
 					 struct qos_info *qos, 
 					 __u32 max_seg_size, 
+					 __u8 max_header_size,
 					 struct sk_buff *skb);
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
-						LM_REASON reason,
-						struct sk_buff *userdata);
+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
@@ -187,7 +188,7 @@
 
 #ifdef CONFIG_PROC_FS
 	create_proc_entry("irlpt_client", 0, proc_irda)->get_info
-			= irlpt_client_proc_read;
+		= irlpt_client_proc_read;
 #endif /* CONFIG_PROC_FS */
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
@@ -215,7 +216,6 @@
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry("irlpt_client", proc_irda);
 #endif
-
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
 #endif /* MODULE */
@@ -403,9 +403,8 @@
 
 	irlpt_client_do_event( self, LMP_DISCONNECT, NULL, NULL);
 
-	if (skb) {
+	if (skb)
 		dev_kfree_skb( skb);
-	}
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -417,7 +416,8 @@
  */
 static void irlpt_client_connect_confirm(void *instance, void *sap, 
 					 struct qos_info *qos, 
-					 __u32 max_sdu_size,
+					 __u32 max_seg_size,
+					 __u8 max_header_size,
 					 struct sk_buff *skb)
 {
 	struct irlpt_info info;
@@ -443,14 +443,14 @@
 	}
 #endif
 
-	self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER);
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
 	self->connected = TRUE;
 	
 	irlpt_client_do_event( self, LMP_CONNECT, NULL, NULL);
 
-	if (skb) {
+	if (skb)
 		dev_kfree_skb( skb);
-	}
 
 	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -603,7 +603,7 @@
 			return;
 		}
 
-		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(skb, LMP_MAX_HEADER);
 		irlmp_disconnect_request(self->lsap, skb);
 		DEBUG(irlpt_client_debug, __FUNCTION__
 		      ": irlmp_close_slap(self->lsap)\n");
diff -urN linux-2.2.10-pre1/net/irda/irlpt/irlpt_cli_fsm.c linux-2.2.10-pre2/net/irda/irlpt/irlpt_cli_fsm.c
--- linux-2.2.10-pre1/net/irda/irlpt/irlpt_cli_fsm.c	1999-03-07 15:26:44.000000000 -0800
+++ linux-2.2.10-pre2/net/irda/irlpt/irlpt_cli_fsm.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jan 12 11:06:00 1999
- * Modified at:   Tue Jan 26 12:02:31 1999
+ * Modified at:   Sun May  9 13:36:13 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
+ *     Copyright (c) 1998-1999, Thomas Davis, <ratbert@radiks.net>
  *     Copyright (c) 1998, Dag Brattli, <dagb@cs.uit.no>
  *     All Rights Reserved.
  *      
@@ -43,10 +43,10 @@
 				      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_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,
 				      struct sk_buff *skb, 
diff -urN linux-2.2.10-pre1/net/irda/irlpt/irlpt_common.c linux-2.2.10-pre2/net/irda/irlpt/irlpt_common.c
--- linux-2.2.10-pre1/net/irda/irlpt/irlpt_common.c	1999-03-07 15:26:44.000000000 -0800
+++ linux-2.2.10-pre2/net/irda/irlpt/irlpt_common.c	2003-08-15 15:06:23.000000000 -0700
@@ -251,18 +251,18 @@
 	}
 
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
-		count, self->irlap_data_size, IRLPT_MAX_HEADER);
+	       ": count = %d, max_data_size = %d, IRLPT_MAX_HEADER = %d\n",
+		count, self->max_data_size, IRLPT_MAX_HEADER);
 
- 	if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) {
- 		count = (self->irlap_data_size - IRLPT_MAX_HEADER);
+ 	if (count > self->max_data_size) {
+ 		count = self->max_data_size;
  		DEBUG(irlpt_common_debug, __FUNCTION__ 
 		      ": setting count to %d\n", count);
  	}
 
 	DEBUG( irlpt_common_debug, __FUNCTION__ ": count = %d\n", count);
 
-	skb = dev_alloc_skb(count + IRLPT_MAX_HEADER);
+	skb = dev_alloc_skb(count + self->max_header_size);
 	if ( skb == NULL) {
 		printk( KERN_INFO 
 			__FUNCTION__ ": couldn't allocate skbuff!\n");
@@ -417,7 +417,7 @@
 			return 0;
 		}
 
-		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve( skb, LMP_MAX_HEADER);
 		irlmp_disconnect_request(self->lsap, skb);
 		DEBUG(irlpt_common_debug, __FUNCTION__
 		      ": irlmp_close_slap(self->lsap)\n");
diff -urN linux-2.2.10-pre1/net/irda/irlpt/irlpt_srvr.c linux-2.2.10-pre2/net/irda/irlpt/irlpt_srvr.c
--- linux-2.2.10-pre1/net/irda/irlpt/irlpt_srvr.c	1999-05-06 16:40:53.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irlpt/irlpt_srvr.c	2003-08-15 15:06:23.000000000 -0700
@@ -51,15 +51,21 @@
 static void irlpt_server_disconnect_indication(void *instance, void *sap, 
 						LM_REASON reason,
 						struct sk_buff *skb);
+
+#if 0
 static void irlpt_server_connect_confirm(void *instance, void *sap, 
 					 struct qos_info *qos,  
 					 __u32 max_seg_size,
+					 __u8 max_header_size,
 					 struct sk_buff *skb);
 static void irlpt_server_connect_indication(void *instance, 
 					    void *sap, 
 					    struct qos_info *qos, 
 					    __u32 max_seg_size,
+					    __u8 max_header_size,
 					    struct sk_buff *skb);
+#endif
+
 static int irlpt_server_data_indication(void *instance, void *sap, 
 					struct sk_buff *skb);
 static void register_irlpt_server(void);
@@ -161,7 +167,6 @@
 }
 
 extern struct proc_dir_entry *proc_irda;
-
 #endif /* CONFIG_PROC_FS */
 
 /*
@@ -171,9 +176,9 @@
  *
  */
 
-/*int irlpt_init( struct device *dev) {*/
 __initfunc(int irlpt_server_init(void))
 {
+	struct irmanager_event mgr_event;
 	__u16 hints;
 
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -212,6 +217,10 @@
 		= irlpt_server_proc_read;
 #endif /* CONFIG_PROC_FS */
 
+	mgr_event.event = EVENT_IRLPT_START;
+        sprintf(mgr_event.devname, "%s", irlpt_server->ifname);
+        irmanager_notify(&mgr_event);
+
 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
 
 	return 0;
@@ -225,6 +234,7 @@
  */
 static void irlpt_server_cleanup(void)
 {
+	struct irmanager_event mgr_event;
 	struct sk_buff *skb;
 
 	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -245,6 +255,10 @@
 	remove_proc_entry("irlpt_server", proc_irda);
 #endif
 
+        mgr_event.event = EVENT_IRLPT_STOP;
+        sprintf( mgr_event.devname, "%s", irlpt_server->ifname);
+        irmanager_notify( &mgr_event);
+ 
 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
 }
 
@@ -304,6 +318,7 @@
 					 void *sap, 
 					 struct qos_info *qos,
 					 __u32 max_seg_size,
+					 __u8 max_header_size,
 					 struct sk_buff *skb)
 {
 	struct irlpt_cb *self;
@@ -314,6 +329,9 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
+
 	self->connected = TRUE;
 
 	irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
@@ -329,6 +347,7 @@
 					    void *sap, 
 					    struct qos_info *qos, 
 					    __u32 max_seg_size,
+					    __u8 max_header_size,
 					    struct sk_buff *skb)
 {
 	struct irlpt_cb *self;
@@ -343,14 +362,16 @@
 	ASSERT( self != NULL, return;);
 	ASSERT( self->magic == IRLPT_MAGIC, return;);
 
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
+
 	self->connected = IRLPT_CONNECTED;
 	self->eof = FALSE;
 
 	irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
 
-	if (skb) {
+	if (skb)
 		dev_kfree_skb( skb);
-	}
 
 	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
 }
diff -urN linux-2.2.10-pre1/net/irda/irmod.c linux-2.2.10-pre2/net/irda/irmod.c
--- linux-2.2.10-pre1/net/irda/irmod.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irmod.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Mon Apr 12 11:31:01 1999
+ * Modified at:   Mon May 10 15:28:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 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 
@@ -110,6 +110,7 @@
 EXPORT_SYMBOL(irttp_flow_request);
 EXPORT_SYMBOL(irttp_connect_request);
 EXPORT_SYMBOL(irttp_udata_request);
+EXPORT_SYMBOL(irttp_dup);
 
 /* Main IrDA module */
 #ifdef CONFIG_IRDA_DEBUG
@@ -151,6 +152,7 @@
 EXPORT_SYMBOL(irlmp_disconnect_request);
 EXPORT_SYMBOL(irlmp_get_daddr);
 EXPORT_SYMBOL(irlmp_get_saddr);
+EXPORT_SYMBOL(irlmp_dup);
 EXPORT_SYMBOL(lmp_reasons);
 
 /* Queue */
@@ -174,10 +176,15 @@
 EXPORT_SYMBOL(irda_device_setup);
 EXPORT_SYMBOL(irda_device_set_media_busy);
 EXPORT_SYMBOL(irda_device_txqueue_empty);
+
+EXPORT_SYMBOL(irda_device_init_dongle);
+EXPORT_SYMBOL(irda_device_register_dongle);
+EXPORT_SYMBOL(irda_device_unregister_dongle);
+
 EXPORT_SYMBOL(async_wrap_skb);
 EXPORT_SYMBOL(async_unwrap_char);
 EXPORT_SYMBOL(irda_start_timer);
-EXPORT_SYMBOL(irda_get_mtt);
+/* EXPORT_SYMBOL(irda_get_mtt); */
 EXPORT_SYMBOL(setup_dma);
 
 #ifdef CONFIG_IRTTY
@@ -505,19 +512,28 @@
 #endif
 }
 
-#ifdef MODULE
-#ifdef CONFIG_PROC_FS
+/*
+ * Function irda_proc_modcount (inode, fill)
+ *
+ *    Use by the proc file system functions to prevent the irda module
+ *    being removed while the use is standing in the net/irda directory
+ */
 void irda_proc_modcount(struct inode *inode, int fill)
 {
+#ifdef MODULE
+#ifdef CONFIG_PROC_FS
 	if (fill)
 		MOD_INC_USE_COUNT;
 	else
 		MOD_DEC_USE_COUNT;
-}
 #endif /* CONFIG_PROC_FS */
+#endif /* MODULE */
+}
+
+#ifdef MODULE
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); 
+MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); 
 MODULE_PARM(irda_debug, "1l");
 
 /*
diff -urN linux-2.2.10-pre1/net/irda/irproc.c linux-2.2.10-pre2/net/irda/irproc.c
--- linux-2.2.10-pre1/net/irda/irproc.c	1999-05-10 13:01:21.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irproc.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Tue Apr  6 19:07:06 1999
+ * Modified at:   Fri May  7 08:06:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
+ *     Copyright (c) 1998-1999, Thomas Davis, <ratbert@radiks.net>, 
  *     All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
@@ -20,8 +20,6 @@
  *     I, Thomas Davis, provide no warranty for any of this software. 
  *     This material is provided "AS-IS" and at no charge. 
  *     
- *     Portions lifted from the linux/fs/procfs/ files.
- *
  ********************************************************************/
 
 #include <linux/miscdevice.h>
@@ -44,28 +42,27 @@
 			   int unused);
 extern int discovery_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);
 
-enum irda_directory_inos {
-	PROC_IRDA_LAP = 1,
-	PROC_IRDA_LMP,
-	PROC_IRDA_TTP,
-	PROC_IRDA_LPT,
-	PROC_IRDA_COMM,
- 	PROC_IRDA_IRDA_DEVICE,
-	PROC_IRDA_IRIAS
-};
+/* enum irda_directory_inos { */
+/* 	PROC_IRDA_LAP = 1, */
+/* 	PROC_IRDA_LMP, */
+/* 	PROC_IRDA_TTP, */
+/* 	PROC_IRDA_LPT, */
+/* 	PROC_IRDA_COMM, */
+/*  	PROC_IRDA_IRDA_DEVICE, */
+/* 	PROC_IRDA_IRIAS */
+/* }; */
 
 struct irda_entry {
 	char *name;
-	int (*fn)(char*,char**,off_t,int,int);
+	int (*fn)(char*, char**, off_t, int, int);
 };
 
 struct proc_dir_entry *proc_irda;
-
+ 
 static struct irda_entry dir[] = {
-#if 0 
-	{"lpt", irlpt_proc_read},
-#endif
 	{"discovery",	discovery_proc_read},
 	{"irda_device",	irda_device_proc_read},
 	{"irttp",	irttp_proc_read},
@@ -75,19 +72,22 @@
 };
 
 #define IRDA_ENTRIES_NUM (sizeof(dir)/sizeof(dir[0]))
-
+ 
 /*
  * Function irda_proc_register (void)
  *
  *    Register irda entry in /proc file system
  *
  */
-void irda_proc_register(void) {
+void irda_proc_register(void) 
+{
 	int i;
+
 	proc_irda = create_proc_entry("net/irda", S_IFDIR, NULL);
 #ifdef MODULE
 	proc_irda->fill_inode = &irda_proc_modcount;
 #endif /* MODULE */
+
 	for (i=0;i<IRDA_ENTRIES_NUM;i++)
 		create_proc_entry(dir[i].name,0,proc_irda)->get_info=dir[i].fn;
 }
@@ -98,9 +98,14 @@
  *    Unregister irda entry in /proc file system
  *
  */
-void irda_proc_unregister(void) {
+void irda_proc_unregister(void) 
+{
 	int i;
+
 	for (i=0;i<IRDA_ENTRIES_NUM;i++)
 		remove_proc_entry(dir[i].name, proc_irda);
+
 	remove_proc_entry("net/irda", NULL);
 }
+
+
diff -urN linux-2.2.10-pre1/net/irda/irsysctl.c linux-2.2.10-pre2/net/irda/irsysctl.c
--- linux-2.2.10-pre1/net/irda/irsysctl.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irsysctl.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,15 +1,15 @@
 /*********************************************************************
  *                
  * Filename:      irsysctl.c
- * Version:       
- * Description:   
+ * Version:       1.0
+ * Description:   Sysctl interface for IrDA
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 24 22:12:06 1998
- * Modified at:   Fri Apr 23 09:46:38 1999
+ * Modified at:   Thu May  6 21:32:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1997, 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 
diff -urN linux-2.2.10-pre1/net/irda/irttp.c linux-2.2.10-pre2/net/irda/irttp.c
--- linux-2.2.10-pre1/net/irda/irttp.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/irttp.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Sat Apr 10 10:32:21 1999
+ * Modified at:   Mon May 10 17:12:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -48,8 +48,10 @@
 					struct sk_buff *);
 static void irttp_connect_indication(void *instance, void *sap, 
 				     struct qos_info *qos, __u32 max_sdu_size,
-				     struct sk_buff *skb);
-
+				     __u8 header_size, struct sk_buff *skb);
+static void irttp_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos, __u32 max_sdu_size, 
+				  __u8 header_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);
 
@@ -337,6 +339,7 @@
 	/* Queue frame, or queue frame segments */
 	if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
 		/* Queue frame */
+		ASSERT(skb_headroom(skb) >= TTP_HEADER, return -1;);
 		frame = skb_push(skb, TTP_HEADER);
 		frame[0] = 0x00; /* Clear more bit */
 		
@@ -360,8 +363,8 @@
 		self->tx_sdu_busy = TRUE;
 		
 	 	if (self->notify.flow_indication) {
- 			self->notify.flow_indication(
-				self->notify.instance, self, FLOW_STOP);
+ 			self->notify.flow_indication(self->notify.instance, 
+						     self, FLOW_STOP);
 		}
  	}
 	
@@ -472,7 +475,7 @@
 		return;
 
 	/* Reserve space for LMP, and LAP header */
-	skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER);
+	skb_reserve(tx_skb, self->max_header_size);
 
 	/*
 	 *  Since we can transmit and receive frames concurrently, 
@@ -655,15 +658,14 @@
 			return -ENOMEM;
 		
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, TTP_MAX_HEADER);
 	} else {
 		skb = userdata;
 		/*  
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT(skb_headroom(userdata) >= 
-		       (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return -1;);
+		ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER, return -1;);
 	}
 
 	/* Initialize connection parameters */
@@ -691,12 +693,11 @@
 
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
-		ASSERT(skb_headroom(skb) >= 
-			(TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
-			return -1;);
+		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER), 
+		       return -1;);
 
 		/* Insert SAR parameters */
-		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
 		
 		frame[0] = TTP_PARAMETERS | n; 
 		frame[1] = 0x04; /* Length */
@@ -724,8 +725,10 @@
  *    Sevice user confirms TSAP connection with peer. 
  *
  */
-void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos,
-			   __u32 max_seg_size, struct sk_buff *skb) 
+static void irttp_connect_confirm(void *instance, void *sap, 
+				  struct qos_info *qos,
+				  __u32 max_seg_size, __u8 max_header_size,
+				  struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 	int parameters;
@@ -741,7 +744,8 @@
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
 
-	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
+	self->max_seg_size = max_seg_size;
+	self->max_header_size = max_header_size + TTP_HEADER;
 
 	/*
 	 *  Check if we have got some QoS parameters back! This should be the
@@ -797,9 +801,9 @@
 	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);
+		self->notify.connect_confirm(self->notify.instance, self, qos,
+					     self->tx_max_sdu_size, 
+					     self->max_header_size, skb);
 	}
 }
 
@@ -809,8 +813,8 @@
  *    Some other device is connecting to this TSAP
  *
  */
-void irttp_connect_indication(void *instance, void *sap, 
-			      struct qos_info *qos, __u32 max_seg_size, 
+void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
+			      __u32 max_seg_size,  __u8 max_header_size, 
 			      struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
@@ -828,7 +832,9 @@
 
 	lsap = (struct lsap_cb *) sap;
 
-	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
+	self->max_seg_size = max_seg_size;
+
+	self->max_header_size = max_header_size+TTP_HEADER;
 
 	DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
 
@@ -850,7 +856,7 @@
 
 		switch (pl) {
 		case 1:
-			self->tx_max_sdu_size = *(frame+4);
+			self->tx_max_sdu_size = frame[4];
 			break;
 		case 2:
 			self->tx_max_sdu_size = 
@@ -878,7 +884,7 @@
 	if (self->notify.connect_indication) {
 		self->notify.connect_indication(self->notify.instance, self, 
 						qos, self->rx_max_sdu_size, 
-						skb);
+						self->max_header_size, skb);
 	}
 }
 
@@ -909,15 +915,14 @@
 			return;
 
 		/* Reserve space for MUX_CONTROL and LAP header */
-		skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+		skb_reserve(skb, TTP_MAX_HEADER);
 	} else {
 		skb = userdata;
 		/*  
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT(skb_headroom(skb) >= 
-			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
+		ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return;);
 	}
 	
 	self->avail_credit = 0;
@@ -939,12 +944,11 @@
 
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
-		ASSERT(skb_headroom(skb) >= 
-		       (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
+		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER), 
 		       return;);
 		
 		/* Insert TTP header with SAR parameters */
-		frame = skb_push(skb, TTP_HEADER_WITH_SAR);
+		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
 		
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
@@ -1079,7 +1083,7 @@
 		/* 
 		 *  Reserve space for MUX and LAP header 
 		 */
-		skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		skb_reserve(skb, TTP_MAX_HEADER);
 		
 		userdata = skb;
 	}
@@ -1357,13 +1361,11 @@
 		}
 		
 		/* Make new segment */
-		frag = dev_alloc_skb(self->max_seg_size+
-				      TTP_HEADER+LMP_HEADER+
-				      LAP_HEADER);
+		frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
 		if (!frag)
 			return;
 
-		skb_reserve(frag, LMP_HEADER+LAP_HEADER);
+		skb_reserve(frag, self->max_header_size);
 
 		/*
 		 *  Copy data from the original skb into this fragment. We
diff -urN linux-2.2.10-pre1/net/irda/qos.c linux-2.2.10-pre2/net/irda/qos.c
--- linux-2.2.10-pre1/net/irda/qos.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/qos.c	2003-08-15 15:06:23.000000000 -0700
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Mon Apr 12 11:49:24 1999
+ * Modified at:   Mon May  3 21:15:08 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 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 
@@ -52,10 +53,10 @@
  *    Compute the intersection of the old QoS capabilites with new ones
  *
  */
-void irda_qos_compute_intersection( struct qos_info *qos, struct qos_info *new)
+void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new)
 {
-	ASSERT( qos != NULL, return;);
-	ASSERT( new != NULL, return;);
+	ASSERT(qos != NULL, return;);
+	ASSERT(new != NULL, return;);
 
 	/* Apply */
 	qos->baud_rate.bits       &= new->baud_rate.bits;
diff -urN linux-2.2.10-pre1/net/irda/wrapper.c linux-2.2.10-pre2/net/irda/wrapper.c
--- linux-2.2.10-pre1/net/irda/wrapper.c	1999-04-24 17:50:06.000000000 -0700
+++ linux-2.2.10-pre2/net/irda/wrapper.c	2003-08-15 15:06:23.000000000 -0700
@@ -1,15 +1,15 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.c
- * Version:       1.1
- * Description:   SIR wrapper layer
+ * Version:       1.2
+ * Description:   IrDA SIR async wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Wed Apr 21 12:45:55 1999
+ * Modified at:   Sun May  2 21:58:00 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -34,7 +34,20 @@
 #include <net/irda/irlap_frame.h>
 #include <net/irda/irda_device.h>
 
-inline static int stuff_byte(__u8 byte, __u8 *buf);
+static inline int stuff_byte(__u8 byte, __u8 *buf);
+
+static void state_outside_frame(struct irda_device *idev, __u8 byte);
+static void state_begin_frame(struct irda_device *idev, __u8 byte);
+static void state_link_escape(struct irda_device *idev, __u8 byte);
+static void state_inside_frame(struct irda_device *idev, __u8 byte);
+
+static void (*state[])(struct irda_device *idev, __u8 byte) = 
+{ 
+	state_outside_frame,
+	state_begin_frame,
+	state_link_escape,
+	state_inside_frame,
+};
 
 /*
  * Function async_wrap (skb, *tx_buff)
@@ -52,8 +65,6 @@
 		__u8 bytes[2];
 	} fcs;
 
-	ASSERT(skb != NULL, return 0;);
-
 	/* Initialize variables */
 	fcs.value = INIT_FCS;
 	n = 0;
@@ -74,13 +85,9 @@
 	} else
 		xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
 
-#if 0
- 	for (i=0; i<xbofs; i++)
-  		tx_buff[n++] = XBOF;
-#else
 	memset(tx_buff+n, XBOF, xbofs);
 	n += xbofs;
-#endif
+
 	/* Start of packet character BOF */
 	tx_buff[n++] = BOF;
 
@@ -94,7 +101,7 @@
 		ASSERT(n < (buffsize-5), return n;);
 
 		n += stuff_byte(skb->data[i], tx_buff+n);
-		fcs.value = IR_FCS(fcs.value, skb->data[i]);
+		fcs.value = irda_fcs(fcs.value, skb->data[i]);
 	}
 	
 	/* Insert CRC in little endian format (LSB first) */
@@ -108,15 +115,6 @@
 #endif
 	tx_buff[n++] = EOF;
 
-#if 0
-	{
-		int i;
-		
-		for (i=0;i<n;i++)
-			printk("%02x", tx_buff[i]);
-		printk("\n");
-	}
-#endif
 	return n;
 }
 
@@ -155,147 +153,13 @@
 }
 
 /*
- * Function async_unwrap (skb)
- *
- *    Parse and de-stuff frame received from the IR-port
- *
- */
-void async_unwrap_char(struct irda_device *idev, __u8 byte) 
-{
-	/* State machine for receiving frames */	   
-	switch (idev->rx_buff.state) {
-	case OUTSIDE_FRAME:
-		switch(byte) {
-		case BOF:
-			idev->rx_buff.state = BEGIN_FRAME;
-			idev->rx_buff.in_frame = TRUE;
-			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:
-			/* Stuffed byte */
-			idev->rx_buff.state = LINK_ESCAPE;
-			break;
-		case EOF:
-			/* Abort frame */
-			idev->rx_buff.state = OUTSIDE_FRAME;
-
-			idev->stats.rx_errors++;
-			idev->stats.rx_frame_errors++;
-			break;
-		default:
-			/* Got first byte of frame */
-			idev->rx_buff.data = idev->rx_buff.head;
-			idev->rx_buff.len = 0;
-
-			idev->rx_buff.data[idev->rx_buff.len++] = byte;
-			
-			idev->rx_buff.fcs = IR_FCS(INIT_FCS, byte);
-			idev->rx_buff.state = INSIDE_FRAME;
-			break;
-		}
-		break;
-	case LINK_ESCAPE:
-		switch (byte) {
-		case BOF:
-			/* New frame? */
-			idev->rx_buff.state = BEGIN_FRAME;
-			irda_device_set_media_busy(idev, TRUE);
-			break;
-		case CE:
-			DEBUG(4, "WARNING: State not defined\n");
-			break;
-		case EOF:
-			/* Abort frame */
-			idev->rx_buff.state = OUTSIDE_FRAME;
-			break;
-		default:
-			/* 
-			 *  Stuffed char, complement bit 5 of byte 
-			 *  following CE, IrLAP p.114 
-			 */
-			byte ^= IR_TRANS;
-			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.state = INSIDE_FRAME;
-			} else {
-				DEBUG(1, __FUNCTION__ 
-				       "(), Rx buffer overflow, aborting\n");
-				idev->rx_buff.state = OUTSIDE_FRAME;
-			}
-			break;
-		}
-		break;
-	case INSIDE_FRAME:
-		switch (byte) {
-		case BOF:
-			/* New frame? */
-			idev->rx_buff.state = BEGIN_FRAME;
-			irda_device_set_media_busy(idev, TRUE);
-			break;
-		case CE:
-			/* Stuffed char */
-			idev->rx_buff.state = LINK_ESCAPE;
-			break;
-		case EOF:
-			/* End of frame */
-			idev->rx_buff.state = OUTSIDE_FRAME;
-			idev->rx_buff.in_frame = FALSE;
-			
-			/* 
-			 *  Test FCS and deliver frame if it's good
-			 */			
-			if (idev->rx_buff.fcs == GOOD_FCS) {
-				async_bump(idev, idev->rx_buff.data, 
-					   idev->rx_buff.len);
-			} else {
-				/* Wrong CRC, discard frame!  */
-				irda_device_set_media_busy(idev, TRUE); 
-
-				idev->stats.rx_errors++;
-				idev->stats.rx_crc_errors++;
-			}			
-			break;
-		default:
-			/* Next byte of frame */
-			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 {
-				DEBUG(1, __FUNCTION__ 
-				      "(), Rx buffer overflow, aborting\n");
-				idev->rx_buff.state = OUTSIDE_FRAME;
-			}
-			break;
-		}
-		break;
-	}
-}
- 
-/*
  * Function stuff_byte (byte, buf)
  *
  *    Byte stuff one single byte and put the result in buffer pointed to by
  *    buf. The buffer must at all times be able to have two bytes inserted.
  * 
  */
-inline static int stuff_byte(__u8 byte, __u8 *buf) 
+static inline int stuff_byte(__u8 byte, __u8 *buf) 
 {
 	switch (byte) {
 	case BOF: /* FALLTHROUGH */
@@ -303,7 +167,7 @@
 	case CE:
 		/* Insert transparently coded */
 		buf[0] = CE;               /* Send link escape */
-		buf[1] = byte^IR_TRANS;    /* Complement bit 5 */
+		buf[1] = byte^IRDA_TRANS;    /* Complement bit 5 */
 		return 2;
 		/* break; */
 	default:
@@ -313,7 +177,159 @@
 		/* break; */
 	}
 }
+
+/*
+ * Function async_unwrap (skb)
+ *
+ *    Parse and de-stuff frame received from the IrDA-port
+ *
+ */
+inline void async_unwrap_char(struct irda_device *idev, __u8 byte)
+{
+	(*state[idev->rx_buff.state]) (idev, byte);
+}
 	 
+/*
+ * Function state_outside_frame (idev, byte)
+ *
+ *    
+ *
+ */
+static void state_outside_frame(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF:
+		idev->rx_buff.state = BEGIN_FRAME;
+		idev->rx_buff.in_frame = TRUE;
+		break;
+	case XBOF:
+		/* idev->xbofs++; */
+		break;
+	case EOF:
+		irda_device_set_media_busy( idev, TRUE);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * Function state_begin_frame (idev, byte)
+ *
+ *    
+ *
+ */
+static void state_begin_frame(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF:
+		/* Continue */
+		break;
+	case CE:
+		/* Stuffed byte */
+		idev->rx_buff.state = LINK_ESCAPE;
+		break;
+	case EOF:
+		/* Abort frame */
+		idev->rx_buff.state = OUTSIDE_FRAME;
+		
+		idev->stats.rx_errors++;
+		idev->stats.rx_frame_errors++;
+		break;
+	default:
+		/* Got first byte of frame */
+		idev->rx_buff.data = idev->rx_buff.head;
+		idev->rx_buff.len = 0;
+		
+		idev->rx_buff.data[idev->rx_buff.len++] = byte;
+		
+		idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte);
+		idev->rx_buff.state = INSIDE_FRAME;
+		break;
+	}
+}
 
+/*
+ * Function state_link_escape (idev, byte)
+ *
+ *    
+ *
+ */
+static void state_link_escape(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF: /* New frame? */
+		idev->rx_buff.state = BEGIN_FRAME;
+		irda_device_set_media_busy(idev, TRUE);
+		break;
+	case CE:
+		DEBUG(4, "WARNING: State not defined\n");
+		break;
+	case EOF: /* Abort frame */
+		idev->rx_buff.state = OUTSIDE_FRAME;
+		break;
+	default:
+		/* 
+		 *  Stuffed char, complement bit 5 of byte 
+		 *  following CE, IrLAP p.114 
+		 */
+		byte ^= IRDA_TRANS;
+		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
+			idev->rx_buff.data[idev->rx_buff.len++] = byte;
+			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
+			idev->rx_buff.state = INSIDE_FRAME;
+		} else {
+			DEBUG(1, __FUNCTION__ 
+			      "(), Rx buffer overflow, aborting\n");
+			idev->rx_buff.state = OUTSIDE_FRAME;
+		}
+		break;
+	}
+}
+
+/*
+ * Function state_inside_frame (idev, byte)
+ *
+ *    
+ *
+ */
+static void state_inside_frame(struct irda_device *idev, __u8 byte)
+{
+	switch (byte) {
+	case BOF: /* New frame? */
+		idev->rx_buff.state = BEGIN_FRAME;
+		irda_device_set_media_busy(idev, TRUE);
+		break;
+	case CE: /* Stuffed char */
+		idev->rx_buff.state = LINK_ESCAPE;
+		break;
+	case EOF: /* End of frame */
+		idev->rx_buff.state = OUTSIDE_FRAME;
+		idev->rx_buff.in_frame = FALSE;
+		
+		/* Test FCS and deliver frame if it's good */
+		if (idev->rx_buff.fcs == GOOD_FCS) {
+			async_bump(idev, idev->rx_buff.data, 
+				   idev->rx_buff.len);
+		} else {
+			/* Wrong CRC, discard frame!  */
+			irda_device_set_media_busy(idev, TRUE); 
+			
+			idev->stats.rx_errors++;
+			idev->stats.rx_crc_errors++;
+		}			
+		break;
+	default: /* Must be the next byte of the frame */
+		if (idev->rx_buff.len < idev->rx_buff.truesize)  {
+			idev->rx_buff.data[idev->rx_buff.len++] = byte;
+			idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
+		} else {
+			DEBUG(1, __FUNCTION__ 
+			      "(), Rx buffer overflow, aborting\n");
+			idev->rx_buff.state = OUTSIDE_FRAME;
+		}
+		break;
+	}
+}
 
 
diff -urN linux-2.2.10-pre1/README linux-2.2.10-pre2/README
--- linux-2.2.10-pre1/README	1999-01-07 08:41:55.000000000 -0800
+++ linux-2.2.10-pre2/README	2003-08-15 15:06:23.000000000 -0700
@@ -32,11 +32,11 @@
  - There is a lot of documentation available both in electronic form on
    the Internet and in books, both Linux-specific and pertaining to
    general UNIX questions.  I'd recommend looking into the documentation
-   subdirectories on any Linux ftp site for the LDP (Linux Documentation
+   subdirectories on any Linux FTP site for the LDP (Linux Documentation
    Project) books.  This README is not meant to be documentation on the
    system: there are much better sources available.
 
- - There are various readme's in the kernel Documentation/ subdirectory:
+ - There are various README files in the Documentation/ subdirectory:
    these typically contain kernel-specific installation notes for some 
    drivers for example. See ./Documentation/00-INDEX for a list of what
    is contained in each file.  Please read the Changes file, as it
@@ -219,7 +219,7 @@
    isn't anyone listed there, then the second best thing is to mail
    them to me (torvalds@transmeta.com), and possibly to any other
    relevant mailing-list or to the newsgroup.  The mailing-lists are
-   useful especially for SCSI and NETworking problems, as I can't test
+   useful especially for SCSI and networking problems, as I can't test
    either of those personally anyway. 
 
  - In all bug-reports, *please* tell what kernel you are talking about,
